世界初の「Manifest V3」対応広告ブロッカーを公開しました。
Chromeの新しい拡張機能APIであるManifest V3は、もはや幻想的な脅威ではありません。
AdGuardブラウザ拡張機能を含む数十の広告ブロック拡張機能が動作する(またはしない)新しい現実となったのです。
Manifest V3の波は、徐々に、しかし確実に押し寄せてきています。2018年、Googleが初めて新しいAPIを説明する文書を公開したとき、開発者コミュニティは批判で沸き返った。私たちも脇目も振らず、Manifest V3実装で起こりうる悪影響を説明する記事をいくつか公開し、「そんなに悪い結果にはならない」という希望さえ表明しました。
世論の反発にもかかわらず、Manifest V3は2020年末にChrome 88 Betaとともに利用可能となった。
2022年1月からは、Manifest V2に基づく新しい拡張機能をChromeウェブストアに追加することが不可能になった。
最終段階はもうすぐです:2023年1月から、Manifest V2上のすべての拡張機能が、それ以前にChrome Web Storeに追加されたものでさえも、機能しなくなります。
AdGuard for Windows, Mac, Android をお使いの方は、MV3について全く心配する必要はございません。これらの製品は、どのブラウザでも制限を受けません。
幸いにも、準備は整っています。
Experimental AdGuard MV3 ブラウザ拡張機能
2021年半ば、私たちはManifest V3の厳しい制限内でも広告をブロックできる新しいエクステンションのプロトタイプに取り組みはじめました。この作業は簡単なものではありませんでした。新しいAPIはまだ未完成で、いくつかの側面は最終調整中で、意図したように動作しませんでした。しかし、もちろん私たちはそれに対処し、Manifest V3という黙示録の後でも広告ブロッカーが生き残ることを証明しました。
プロトタイプの開発中、新しい API の機能によって引き起こされた多くの深刻な問題に直面しました。その一つひとつについて、これから詳しく説明します。
一方、試してみたい方は、Chrome WebStoreからインストールすることができます。
その仕組みに関する短いビデオです
ルール制限
フィルタリング・ルールとは何か、広告ブロックが一般的にどのように機能するのかをご存じない方、または知識を新たにしたい方は、ナレッジベースで簡単に説明されています。
拡張機能フィルタに含まれるすべてのルールは、Manifest V3 によって静的(組み込み)ルールと動的ルールに分けられ、その数は大幅に制限されました。
静的ルールについては、Chromeは1つの拡張機能につき3万ルールという最低保証上限を設定し、1人のユーザーがインストールするすべての拡張機能の合計上限を33万ルールとしました(これは拡張機能につき1,000正規表現ルールという制限も考慮したものです)。1つの拡張機能が許容量のルールをすべて取得することもあれば、複数ある場合もあり、そうなるとおそらく一部の拡張機能が制限に足りなくなる、というカラクリです。
この現象が弊社の拡張機能で発生した場合 (これは、更新、サービスワーカーの再起動、弊社またはサードパーティのブロッカーで設定されたフィルタの変更後など、いつでも発生します)、ブラウザがアクティブなフィルタのリストを変更し、AdGuard の基本広告フィルタのみを有効にしたままにしたという内容のメッセージが表示されます。最悪の場合、30,000以上のルールが含まれているため、基本フィルターさえ有効にならない可能性があります。その場合、ユーザーはAdGuardによる保護が受けられないままになってしまいます。
このようなケースはすべて弊社が想定しており、ブラウザが無効にしたものと有効にしたものについての説明とともに、別の画面に表示されます。
ユーザーが独自のルールやフィルタを追加できる動的ルールについては、1,000の正規表現ルールの制限を含め、5,000という小さな制限があります。この制限を超えた場合、AdGuard MV3は最初の5,000ルールのみを適用することができ、残りは無効のままとなります。
制限を超えた場合の通知は、このように表示されます。
Manifest V3 の制限は、フィルタリングの品質やユーザーエクスペリエンスだけでなく、フィルタリング開発コミュニティにも害を及ぼします。以前は、誰でも自分用のフィルタを作ることができ、そのようなフィルタは時間とともに人気が出て、推奨ブロッカーリストに載ることができました。しかし現在では、これを実現するのはかなり難しくなっています。結局のところ、ブロッカーはあらかじめ設定されたフィルタ(50個以下)を使用しなければならず、どのフィルタがユーザーに利用されるかを厳選しなければならないのです。もちろん、手動で独自のフィルターを設定することは可能です。しかし、すべての**カスタムフィルターとユーザールールに5000ルールの制限があることを忘れないでください。
問題の詳細な説明には、多くの詳細が含まれていますが、ほとんどは開発者に理解しやすいものです。もしあなたが技術者でないなら、この部分は自由に読み飛ばしてください。
宣言型ルール
Manifest V3が導入される前は、フィルタリングエンジンは、拡張機能によってサーバーからダウンロードされたフィルタから動的に構築されていました。さらに、フィルターを構成するルールは、ページローディングの異なる段階で適用されていました。
たとえば、ブラウザがリクエストを送信する前にルールをトリガーすることができました。onBeforeRequest
イベント内で、ブラウザは特定のリクエストをどうするか拡張機能に尋ね、拡張機能はブロックするかリダイレクトすることで動的に反応しました。化粧品のルールは、ページがすでに読み込まれ、DOM が表示されたときに、少し遅れて適用されました。
Manifest V3 が施行された今、onBeforeRequest
メソッドはもはや適用できません。代わりに、Chrome は declarativeNetRequest API
の使用を提案しています。この API では、リクエストを修正する権利がブラウザに与えられます。この拡張機能では、ブラウザがネットワークリクエストを変更またはブロックするための宣言的なルールのセットのみを発表しています。
宣言的ルールの構文
宣言的ルールの構文は、最新の広告ブロッカーで一般的に使用されている構文とはかなり異なります。コミュニティの多くのメンバーは、Chrome専用のルールを作成する時間を避けるために、Manifest V3内で作業することをあきらめるかもしれません。
各ルールは、フィールドで構成される必要があります。
id
– the identifier of the rule. It can be used to associate a declarative rule with a text rule.priority
– the priority of the rule. It determines how the rule will be applied to the query.action
– the action of a rule.
are of three kinds:block
– actions that block requests.redirect
orupgradeScheme
– actions that redirect requests.allow
orallowAllRequests
– actions that allow requests.
condition
– condition under which the rule is applied
ルールの例:
{
"id": 1,
"priority": 1,
"action": { "type" : "block" },
"condition": {
"urlFilter": "abc",
"domains": ["example.org"],
"resourceTypes": ["script"]
}
}
*このルールは、アドレスに abc
という部分文字列を持ち、ドメイン example.org
のサイトから発信されたスクリプトへのすべてのリクエストをブロックします *。
Safari用の広告ブロック拡張機能を開発したとき、ブラウザの開発者によって課された構文にルールの構文を変換する方法を見つけなければならなかったのです。今回も同様の方法で、私たちの構文を宣言的なChromeのルールに変換しています。
静的ルールと動的ルールを変換するために、私たちは@adguard/tsurlfilterライブラリにモジュールを追加しました。このライブラリは、フィルタールールを実行して宣言型のルールに変換し、ルールセットに結合して .json
ファイルに保存します。このライブラリは、テキストルールとJSONルールの間のマッピングテーブルを構築し、それらの間の接続が失われないようにします。
コンバータがどのように動作するかのいくつかの例:
||example.com^$script
というルールは以下に変換されます:
{
"id": 1,
"action": {
"type": "block"
},
"condition": {
"urlFilter": "||example.com^",
"resourceTypes": [
"script"
],
"isUrlFilterCaseSensitive": false
}
}
@@||example.com^$script$domain=example.org
というルールは以下に変換されます:
{
"priority": 1,
"id": 23,
"action": {
"type": "allow"
},
"condition": {
"urlFilter": "||example.com^$script",
"initiatorDomains": [
"example.org"
],
"isUrlFilterCaseSensitive": false
}
}
ほとんどのルールは正しく変換されますが、様々な制限のためにいくつかの機能が失われています。
$removeparam
は、除外文字列 (~) と正規表現 (regexp) をサポートしていません。- 正規表現については、Chromeは独自の実装を使用しているため、標準機能の一部がサポートされていません。例えば、後方参照、負のルックヘッド、所有量詞を含む正規表現がこれにあたります。
- 負のルックヘッド`はフィルタによく使われます。ざっと検索したところ、AdGuard のフィルターでこの表現を使ったルールが現在 43 個あることがわかりました。一見すると、これは多くないのですが、これらのルールのほとんどは、多くの異なるドメインで動作することになっていることを念頭に置いてください。
- 正規表現は、消費されるメモリ量のために、Chrome 内で追加的に検証されます。この場合、どのような実装になっているのかがよくわからないので、一部の正規表現で問題が発生する可能性があります。
- Cookieのルールには対応していません。
- 他にも多くの問題がありますが、記事を汚さないためにここでは触れませんでした。
宣言型ルールの問題は明白です。その構文は、この拡張モジュールができることを大きく制限しています。そして、残念なことに、Chromeの開発者が時間をかけて改善してくれることを期待する以外、私たちにはどうすることもできません。
ルールセット
新しいAPIによると、宣言的なルールはルールセットに統合されなければなりません。
マニフェストV3でルールセットを統合する例:
{
"name": "AdGuard AdBlocker MV3",
"version": "1",
"declarative_net_request": {
"rule_resources": [{
"id": "ruleset_1",
"enabled": true,
"path": "rules.json"
}]
},
…
}
ルールセットは manifest.json
ファイルで指定され、拡張機能がインストールまたは更新されたときにのみ読み込まれます。そして、これがまた大きな問題なのです。フィルタリングルールが、1つまたは複数のウェブサイトのレイアウトやパフォーマンスを壊してしまうことがあるのです。このように非常に多くのルールがあるため、このような事故を完全に回避することは統計的にほぼ不可能です。さらに、ウェブサイトは常に変化しているので、以前は問題なかったルールが今は問題を起こしているかもしれません。でも大丈夫。この問題を解決するシンプルな方法があったのです。
そのようなルールがフィルタにあり、すぐにそれを無効にする必要があると想像してください。Manifest V2拡張機能では、この目的のために $badfilter
という修飾子が使用されていました。フィルタの開発者は、指定された修飾子を持つルールを追加し、拡張機能は動的に更新され、新しいルールは参照されるルールを無効にし、物事がうまくいくようになります。お分かりのように、この「トリック」はManifest V3では機能しません。
新しいバージョンをChromeストアに追加した後、審査が通過するのを待つ必要があります。悲しいことに、更新されたフィルタをユーザーに提供する他の方法はありません。個別のルールの有効化・無効化の機能についての議論は、いくつかの希望を与えてくれます。結局のところ、エクステンションにフィルタを素早く更新する機能が与えられる可能性が少しあります。
統計とフィルタリングログ
Manifest V2 に基づく AdGuard Browser 拡張機能には、ブラウザから送信されたすべてのリクエストとそれに関する詳細情報を表示するフィルタリングログがあります。特に、どのフィルタリングルールを使って、このルールがブロックされたのかがわかります。
Chrome自体が、Developer Modeで解凍・インストールした拡張機能に対してのみリクエストをブロックし、統計情報を共有するようになったため、以前のようにフィルタリングログを実装することができません。しかし、特異な代替手段を思いつくことができ、それは拡張機能の最終バージョンで行う予定です。
つまり、フィルタリングログを開くと、Manifest V2のルールで動作するエンジンが起動するのです。これはリクエストに対して何もしませんが、どのルールが適用された可能性があるかを表示するだけです。Chromeの統計情報を旧エンジンの結果と比較することで、リクエストがどのように処理されているのか、おおまかに把握することができます。
現在のプロトタイプのバージョンでは、フィルタリングログは実装されていません。その代わり、フィルタ開発者はChromeの開発者が推奨する仕組みを利用する必要があります。ポイントは、どのルールがトリガーされたかという情報を得ることはできる、ということです。しかし、注意点があります。それは、拡張機能を「解凍」した状態でインストールする必要があることです。つまり、私たちのリポジトリをクローンし、拡張機能を「ビルド」し、ブラウザを開発者モードに切り替える必要があります。この場合にのみ、フィルタをデバッグするためのツールを使用することができるようになります。
サービスワーカー
Manifest V3では、バックグラウンド ページはなくなりました。バックグラウンドページは、拡張機能が状態を維持し、ブラウザAPI(前述の onBeforeRequest
など)で動作するための独立したバックグラウンドプロセスでした。Manifest V3では、このページがサービスワーカーに置き換えられ、ブラウザによってしばしば中断されます。
ブラウザがサービスワーカーを停止すると、拡張機能は一種のスリープモードになります。宣言的なルールは動作しますが、動的に読み込まれる外観上のルールは動作しません。拡張機能が機能するためには、何かがサービスワーカーを起動させなければなりません。
サービスワーカーが目を覚ますと、エクステンションはリポジトリからフィルタリングルールを読み込んで、すばやく見つけられるように処理し始めます。この間、1.5~2秒間は、エクステンションはコスメフィルタリングを適用しませんが、ブラウザ自体によって広告要求がブロックされます。その後、エンジンが起動し、広告が消えます。サービスワーカーの起動時間を短縮し、化粧品ルールの大部分をコンテンツスクリプト(ウェブページのコンテキストで動作し、毎分殺害されない)に移行するよう努める予定ですが、一部のケースではサービスワーカーがまだ必要です。
結論
Manifest V3の制限にもかかわらず、AdGuard MV3は広告とトラッキングから非常によく保護されています。
- トラッカーへのリクエストをプロアクティブにブロック
- バナー、ソーシャルウィジェット、その他の迷惑な要素を非表示にします。
- YouTubeを含む動画共有プラットフォーム上の広告をブロック
この実験的な拡張機能は、その前任者ほど効果的ではありませんが、ほとんどのユーザーはその違いを感じることはないでしょう。唯一、化粧品ルールの適用にタイムラグがあるため、広告のちらつきが気になるかもしれません。
このプロトタイプの目的は、新しいアプローチをテストし、あなたのフィードバックを得ることです。ですから、ぜひ試して、改善すべき点をお知らせください。いつものように、このプロトタイプはオープンソースでGithubに公開されています。もし、何か問題があったり、提案があれば、Githubに投稿していただければ、私たちは耳を傾けます。
今日、広告ブロックの開発者の中で初めてManifest V3で構築された拡張機能をリリースすることで、Googleが私たちに課した課題をクリアしたと言えるのではないでしょうか。まだやるべきことはたくさんありますが、Manifest V2が廃止された後でも、Google ChromeユーザーはAdGuard Browser Extensionで広告やトラッカーから身を守ることができると、すでに主張することができるのです。