dataスキームの画像をブロックしてみる2012年03月22日 03時06分18秒

面白いネタ、いただきました。

にーまるどっとこむ(旧「突然消失するかもしれないブログ」)のなかのきえたさんから、こんなメンションが飛んできた。

Adbloc PlusではData URIはフィルター対象に指定出来ないのですが、何か技術的に難しい理由があるのでしょうか?

Adblock Plusはこれまで使ったことなかったんだけど、なんだかえらく興味をひかれたので調べてみることに。

よくわからんが使ってしてみると

ちょっと調べたところ、Firefox用とChrome用があるみたいなんだけど、とりあえずFirefoxのほうを試してみる。

まずはAdblock Plusをインストールし、適当にググってみたページなんかを参考にして見よう見まねで

data:image/*
みたいな感じで登録、手持ちであったdataスキームで画像やらスクリプトを食わせているページを開いてみたが、なんの変化も見られない。ふむ。

ドキュメント類もろくすっぽ読まずに機能拡張のソースコードを追っていき、nsIContentPolicyというインターフェイスの実装を提供しているということがわかったので、ContentPolicy.jsmというモジュールのあちこちにデバッグコードをひっかけて調べたところ、内部で持っているスキームのホワイトリストにマッチするので、URLの突き合わせが行われる前にブロックされないことが確定していると判明。さて、ホワイトリストはどこに持ってるんだ?

ググってみると、あるもんだ。

キーワードは失念したがググってみたところ、adblockplus.orgのドキュメントが見つかった。

これ見ると、どうやら「extensions.adblockplus.whitelistschemes」で値を持ってるみたい。

さっそくabout:config開いて「adblockplus.whitelist」くらいでフィルタかけてみたらこんな感じで設定項目が見つかった。

なるほど、先のドキュメント通りに許可スキームをスペース区切りで持ってるので、"data"を取り除いてみることに。

一旦ブラウザを再起動して再度dataスキームを使ったページにアクセスしてみたら、こんどはちゃんと画像もスクリプトもロードされない!おお、やった。

実はもっと簡単な方法があったのねん…

なんてとこまで調べたあたりで、なかのきえたさんからこんなツイートが。

これで消せたみたいですけど、これであってます?→「##img[src*="data:image"]」
よくよく(よくよく、じゃなくても)調べてみたら、ブロックリストの書き方を解説してるページで詳しく解説されてるじゃない!

これはURLフィルタではなく、「非表示要素フィルタ」というものらしく、要素の属性に対してのマッチングパターンを記述できると。なんだ、こっちのほうが圧倒的に簡単じゃん… orz

ただ、負け惜しみじゃないんだけど、この書き方だと

  • 画像の場合はimg要素で読み込んでいるものだけが対象、cssでbackground-imageなんかに指定してる場合はブロックできない
  • script要素には(表示もクソもないので)効果がない
という違いはありますが。えぇ、負け惜しみじゃないですよ?

ということで、サンプルページをば

作ってみました。

dataスキーム使ったサンプルページ

img要素で画像表示してるところと、cssでbackground-imageにdataスキーム指定してるところと両方あるので、「data:image/*」と「img[src*="data:image"]」のフィルタの違いをご堪能あれ。

オマケ情報

URLフィルタ使う場合は、「data:*」みたいな乱暴な指定もできます。これだとcssだろうがscriptだろうがなんでもブロックできるっぽいです。

次はChorme版だ。

と思ったけど、ちょっと記事が長くなったので別エントリを起こす予定です。

追記

Chrome編、簡単に書きました。

dataスキームの画像をブロックしてみる - Chrome編2012年03月22日 03時52分25秒

前のエントリの続きで、今度はGoogle Chrome行ってみよう。といっても、それほど書くことあるわけじゃないので比較的アッサリ気味の内容で。

他にもいろいろあるんだけど、Firefoxでソースをざっくり眺めて馴染みがでたので、ターゲットはAdblock Plus。現在タイトルに「(Beta)」がついてる1.2版です。

こちらもFirefox版と同じく、単純に「data:image/*」みたいな登録をしてもフィルタリングされないので、またまたデバッグコードを仕掛けて調べてみることに。

extensionのインストールされたディレクトリをざっと眺めてみたらmanifest.jsonてのがあったのでそちらを見てみる。

manifest.jsonの内容から推測するに、メインで使用されるのはどうやら「contentScript2.js」らしいのでそちらを見てみたところ、beforeloadHandlerという関数からshouldBlock()にURLを渡して判断してるっぽいのでその辺りにデバッグコードを仕掛けて調べたら、dataスキームURIを相対URLとみなして、現在のドキュメントURLからの絶対URLに変換してた。こりゃ引っかからんわ。

コードにパッチ当てちゃってもいいんだけど、モノは試しで「http://*/*data:image/*」なんてフィルタ登録してみたらあっさりうまくいっちゃった。まぁURLの途中に「:」を挟んだパターンがあったら誤爆する可能性もあるんだけど、とりあえずこれでいいか。

ただ、URLフィルタにマッチした場合でもHTTPでの通信そのものは発生しちゃうみたいで、それだったら「##img[src*="data:image"]」のほうが誤爆の恐れもないし安全かも。

あ、あとcssでbackground-imageに指定してる場合なんかはブロックされないっぽいです。