「読み取った URL のタイトルを自動取得」機能を実装し、Revert した話

| 開発記録 | QRリーダー

タグ: #プライバシー #iOS #意思決定

QR で読み取った URL のページタイトルを自動取得して履歴に表示する機能を実装しました。便利そうに見えたのですが、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 行に収まります(その後 Revert)。

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 コミットだけ残す

コミット履歴を辿ると、`abe1461 URLスキャン時にページタイトルを自動取得する機能を追加` と、その直後に `6f4d4f4 Revert "URLスキャン時にページタイトルを自動取得する機能を追加"` が並んでいます。

Revert したものを履歴に残しておくのは大事で、後から「なぜこれをやらなかったのか」を辿れるようにしておきます。

## 教訓

- 「便利そう」と「ユーザーが期待する範囲」は別物
- ネットワーク通信を増やすときは、必ずプライバシー観点を通す
- Revert はネガティブではない、設計判断の記録

アプリの責務範囲を超える機能は、便利でも入れない方がよいことがあります。シンプルさを守ることは、機能を増やすより難しい仕事です。