「読み取った URL のタイトルを自動取得」機能を実装し、Revert した話
| 開発記録 | QRリーダー
タグ: #プライバシー #iOS #意思決定
QR で読み取った URL のページタイトルを自動で取ってきて、履歴に表示する機能を作りました。約 30 行で動きました。それでも ATT とプライバシーの観点で考え直して、Revert しました。便利さより責務の範囲を選んだ話です。
「URL だけだと味気ない」という気持ち
読み取り履歴に URL だけが並んでいると、「これ何のページだっけ?」となります。Twitter(X)の URL と Amazon の URL を見分けるのも難しい。自分の履歴なのに、です。
そこで機能を作ってみました。URL を読み取ったタイミングで、その URL の HTML を自動で取得する。タイトルタグを抜き出して、履歴に保存する。それだけです。
実装は意外と簡単
final response = await http.get(Uri.parse(url));
final document = html_parser.parse(response.body);
final title = document.head?.querySelector('title')?.text;
わずか数行です。タイムアウトとエラーハンドリングを足しても、約 30 行で動きました。
実際にリリースした関数は、おおよそ次のような実装です。タイムアウトと文字コード対応、SSL エラーのフォールバックまで入れても 30 行に収まります(このあと消すことになります)。
Future<String?> fetchPageTitle(String rawUrl) async {
final uri = Uri.tryParse(rawUrl);
if (uri == null || !(uri.isScheme('http') || uri.isScheme('https'))) {
return null;
}
try {
final response = await http
.get(uri, headers: {'User-Agent': 'qr-reader/1.0'})
.timeout(const Duration(seconds: 5));
if (response.statusCode != 200) return null;
final body = _decodeWithCharset(response);
final doc = html_parser.parse(body);
final title = doc.head?.querySelector('title')?.text.trim();
return (title == null || title.isEmpty) ? null : title;
} on TimeoutException {
return null;
} catch (_) {
return null;
}
}
リリースして数日で「履歴が見やすくなった」というコメントもいただきました。うれしかったです。
ATT とプライバシーの観点で再考
ところが、しばらくして引っかかりを感じました。ユーザーが読み取った URL に、アプリが勝手にアクセスして HTML を取得している。これは QR リーダーというアプリのプライバシー期待値を超えていないか。
ユーザーは「QR コードをスキャンする」ためにアプリを使っています。「読み取った URL にアプリがネットアクセスする」ことまで同意した覚えはないはずです。
App Store の審査と ATT
仮にこの機能を続けるなら、考えることが増えます。ATT(App Tracking Transparency)的にどう説明するか。プライバシーラベルにどう載せるか。「ネットワーク接続」「ユーザー行動の収集」と取られかねません。
社内(一人ですが)で検討しました。実装としては動く。でも QR リーダー本来のスコープを超えている。そう判断して、Revert しました。
Revert コミットだけ残す
コミット履歴を辿ると、2 つのコミットが並んでいます。abe1461 URLスキャン時にページタイトルを自動取得する機能を追加 と、その直後の 6f4d4f4 Revert "URLスキャン時にページタイトルを自動取得する機能を追加" です。
Revert したものを履歴に残しておくのは大事です。後から「なぜこれをやらなかったのか」を自分で辿れます。
教訓
- 「便利そう」と「ユーザーが期待する範囲」は別物
- ネットワーク通信を増やすときは、必ずプライバシー観点を通す
- Revert はネガティブではない。設計判断の記録
アプリの責務を超える機能は、便利でも入れない。動いたコードを消すのはちょっと惜しかったです。それでも消すほうが正しいことがあります。シンプルさを守るのは、機能を足すより難しい仕事です。