uBlock Origin 再び @Firefox
Add StarAPM774

uBlock Origin(以降 uBO)を入れてから一年ちょい
快適に使っているけれど、副作用というか誤爆も まあまあ ある。
気が付いたら その都度、Myフィルターにルールを追加して対応するのだけれど、たまにしかいじらないから文法とかぜんぜん頭に入ってないし、参考URL とかリンクを置いとくだけじゃダメだ。

というわけで、きちんと公式のページとか読んだ。
以下、未来の自分に向けてのメモ書き。

TL;DR

まずは、ブロックの種類から

https://github.com/gorhill/uBlock/wiki/Overview-of-uBlock's-network-filtering-engine
https://github.com/gorhill/uBlock/wiki/Overview-of-uBlock's-network-filtering-engine:-details

(1) whitelist ポップアップの青い電源ボタンで OFF にすると追加される
(2) url filtering rule ログの 4列目をつついて表示されるところで指定するやつ
(3) local dynamic filtering rule ポップアップの advanced user で表示される 2列目で指定するやつ(My ルールの一時的なルール)
(4) global dynamic filtering rule My ルールで、一時的なルールをコミットして、恒久的なルールにしたやつ
(5) static filtering rule 外部フィルター、My フィルター

ざくっとした指定しかできないけど、その分 軽いから、先に判定されるようになってるのがホワイトリストとかダイナミックルールで、このサイトは一括で OK とか NG みたいなのは、こちらが推奨。
コードをいじるような使い方だったら、Static Filter だけ覚えておけば良い、という感じか。

Static Filter の文法

https://github.com/gorhill/uBlock/wiki/Static-filter-syntax

Network Filter と Cosmetic Filter の二種類。
Adblock Plus(以降 ABP)では、Filter と Element hiding と呼んでいたやつ。

基本は ABP の文法。
https://adblockplus.org/en/filter-cheatsheet
https://adblockplus.org/en/filters

Network Filter

  • ブロック
    対象のURL + $ + オプション
  • 例外(ブロックの指定を打ち消す)
    @@ + 対象のURL + $ + オプション

#灰色は省略可

対象のURL

ワイルドキャラクタなんかが使える URL のパターン、もしくは、正規表現

special character
* wildcard character
| start or end anchor
|| domain name anchor
^ separator

セパレータは、正規表現の単語境界だと思ってると はまる。
_ - . %は、境界として扱われない。
ドメインに含まれるピリオドが、実際に踏んだ地雷だったり。

start anchor や domain name anchor は、検索パラメータ中にドメインっぽい表現がある場合なんかを除外できる。

オプション

ブロックの適用を種類やドメインで限定したり、動作を決めたりできる。
ABP のチートシートに書いてないオプションもあるし、uBO で拡張されたやつもある。
覚えておけば良いのは、このくらいか。

script, image, object, xmlhttprequest, popup リクエストの種類で限定
domain=, third-party ページのドメインで限定
important 例外指定に勝つブロック
redirect= リクエストを置き換える
inline-script inline script を消しちゃうのかな

domain= に指定するドメインは、

  • | で区切って複数指定できる
  • ~ を頭につけて、「それ以外」を表現できる

Cosmetic Filter

#灰色は省略可

ドメイン

ドメインには

  • *ワイルドカードで使える
  • ,で区切って複数指定できる
  • ~を頭につけて、except を表現できる

URL ではなく、ドメイン
「このページのこの要素」って使い方もあるような気はするけれど、本来の目的が広告のブロックだから、基本は「どこにあっても」なのか。
特定のページのある要素を隠すなら Stylish とかを使ってね、ということかも。

セレクタ

セレクタには、CSSセレクタと、uBO で拡張した書式が使える。
https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#procedural-cosmetic-filters
https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters

  • :has(...)
    ... な子要素を持つ親とか祖先を指定。
  • :has-text(...)
    ... なテキストを含む子要素を持つ親とか祖先を指定。 広告な要素は目印がついてない可能性は大きいので、:has() よりも強力か?
  • :if(...)
    :if-not(...)
    :has() の AND とかを表現できる(かな
  • :matches-css(...)
    :matches-css-before(...)
    :matches-css-after(...)
    style で要素を限定。
    -before と -after は、:before と :after 疑似要素に対応
  • :xpath(...)
    XPath じゃないと指定できない要素はあるかな?
  • script:contains(...)
    特定のインラインスクリプトを除外する(動作させない)ために使うはず。
  • script:inject(...)
    assets/ublock/resources.txt で定義されたスクリプトを注入するということか。
  • :style(...)
    非表示にするんじゃなくて、... なスタイルを適用する。
    Stylish なんかでできるやつ

ABP のセレクタ拡張は、uBO に対応するものがあるので、使う必要がないはず。

  • :-abp-properties():matches-css()
  • :-abp-has():has()

ABP のセレクタ拡張を使うときには、## の代わりに #?# を使うみたい(覚えなくて良い)。

script:inject() は、使いどころ悩む。
HASH が変わっちゃうから、普通の利用者は resources.txt を修正できないし、ほぼ開発者用。
extension-data/ublock0.sqlite の settings name=cache/ublock-resources が実体だからここを書き換えると追加できるかも。
いや、WebExtension に対応してから、置き場所が Indexed DB に変わってるんだ。
resources の文字が見当たらないなあ...
どこに保存されてるんだろう?

AdBlock Plus との違い

ABP にあって uBO にない

uBO では、例外ルールの document オプションが効かない。
Whitelist を使ってくれ、ということかな。

ABP にはなくて uBO にある

Cosmetic Filter には、結構 追加されている。
Network Filter の HOSTS files って何だ?
domain anchor や、wildcard を書かなくても、ホスト名っぽい表記だったら通すよ、ってことかな

ABP と決別したわけだから、ABP のページを参照しなくても済むように、GitHub の方に書いといて欲しい、という気はする。

Static Filter について整理

Network Filter は、指定されたリクエストをブロックする。
ページの URL が引っかかれば警告のページが表示されて、進むかどうかを聞いてくる。
ページ中の記述にある URL が引っかかれば、音なしで遮断。
「設定」の「ブロックされた要素の設置場所全てを非表示にする」にチェックを入れていると、大きさを持っている img や iframe なんかは display: none; が指定されて、要素が存在してないことになる。

Cosmetic Filter は、指定された要素を見えなくする。
テキスト埋め込みの広告など、リクエストを出さない広告をブロックする。

 
リクエストを出すわけでもなく、もともと見えてないインラインスクリプト関連は、ちょっと異質。

Network Filter に inline-script オプションが指定された場合は、対象の URL が「この URL のページで」という意味になって、Cosmetic Filter のドメインのような意味合いになっている。

Cosmetic Filter の ## より後は影響を及ぼす要素の指定だけど、script:inject だけは動作の指定になっている。
script:contains() の方は、「無効にする(動かない)」<script> を限定するものだから、ある意味「セレクタ」と言っても良い。
script:contains() というより、script タグに :contains() という疑似クラスと思えば、違和感はない。

My フィルタを書くにあたって

Static Filter の実例

uBlock filters から。

ドメインを指定して全てブロック
||mac-system-alert.com^
広告を見せない
youtube.com##.ad-div
外部フィルタの例外指定を打ち消す
# `important` must be used as there is one EasyList exception preventing # complete block. ||username1.link^$important
Network Filter の redirect
||adswithsalt.com/*/ad-loading.pic$image,redirect=3x2-transparent.png

画像を消しちゃうんじゃなくて、置き換える。
レイアウトを保ちたいときとかに使うのかなあ。

*/fuckadblock-$script,redirect=fuckadblock.js-3.2.0

# fuckadblock defuser
fuckadblock.js-3.2.0 application/javascript
(function() {
    var noopfn = function() {
        ;
    };
    //
    var Fab = function() {};
    Fab.prototype.check = noopfn;
    Fab.prototype.clearEvent = noopfn;
    Fab.prototype.emitEvent = noopfn;
    Fab.prototype.on = function(a, b) {
        if ( !a ) { b(); }
        return this;
    };
    Fab.prototype.onDetected = function() {
        return this;
    };
    Fab.prototype.onNotDetected = function(a) {
        a();
        return this;
    };
    Fab.prototype.setOption = noopfn;
    var fab = new Fab(),
        getSetFab = {
            get: function() { return Fab; },
            set: function() {}
        },
        getsetfab = {
            get: function() { return fab; },
            set: function() {}
        };
    if ( window.hasOwnProperty('FuckAdBlock') ) { window.FuckAdBlock = Fab; }
    else { Object.defineProperty(window, 'FuckAdBlock', getSetFab); }
    if ( window.hasOwnProperty('BlockAdBlock') ) { window.BlockAdBlock = Fab; }
    else { Object.defineProperty(window, 'BlockAdBlock', getSetFab); }
    if ( window.hasOwnProperty('SniffAdBlock') ) { window.SniffAdBlock = Fab; }
    else { Object.defineProperty(window, 'SniffAdBlock', getSetFab); }
    if ( window.hasOwnProperty('fuckAdBlock') ) { window.fuckAdBlock = fab; }
    else { Object.defineProperty(window, 'fuckAdBlock', getsetfab); }
    if ( window.hasOwnProperty('blockAdBlock') ) { window.blockAdBlock = fab; }
    else { Object.defineProperty(window, 'blockAdBlock', getsetfab); }
    if ( window.hasOwnProperty('sniffAdBlock') ) { window.sniffAdBlock = fab; }
    else { Object.defineProperty(window, 'sniffAdBlock', getsetfab); }
})();

この redirect は、処理を置き換えちゃう。
Anti AdBlocker のクラス、または window のプロパティを置き換えることで、それ以降の処理がエラーにならない。

Cosmetic Filter の script:inject

javascript を注入する。Greasemonkey とかでできるやつ。

deadline.com,tweaktown.com##script:inject(gpt-defuser.js)

# https://github.com/uBlockOrigin/uAssets/issues/58
gpt-defuser.js application/javascript
(function() {
    var noopfn = function() {
        ;
    };
    var props = '_resetGPT resetGPT resetAndLoadGPTRecovery _resetAndLoadGPTRecovery setupGPT setupGPTuo';
    props = props.split(/\s+/);
    while ( props.length ) {
        var prop = props.pop();
        if ( typeof window[prop] === 'function' ) {
            window[prop] = noopfn; 
        } else {
            Object.defineProperty(window, prop, {
                get: function() { return noopfn; },
                set: noopfn
            });
        }
    }
})();

window に定義されるメソッドやプロパティを無力化するんだ。
他にも eval を横取りしたり。

redirect や script:inject で、2次利用できそうなやつ

redirect
1x1-transparent.gif とか 透明画像に置き換える
nooptext
noopcss
noopjs
noopframe
noopmp3-0.1s
空っぽ系 : MIME タイプごとにある
noopmp3-0.1s は、無音の MP3
script:inject
antiAdBlock.js Anti AdBlock 対策
window.antiAdBlock()
lesechos.fr.js Anti AdBlock 対策
window.checkAdBlock()
ideal.es.js Anti AdBlock 対策
window.is_block_adb_enabled
window.name-defuser window.name を空にする
alert-buster.js alert を console.log に置き換える
noeval.js
silent-noeval.js
noeval-if.js
window.eval を殺す
setTimeout-logger.js
setInterval-logger.js
addEventListener-logger.js
メソッドの呼び出しをロギング
csp.js meta http-equiv="Content-Security-Policy" を書き換える or 設定する
addEventListener-defuser.js addEventListener をフィルタリングする
パラメータにマッチする Listener の登録をスキップする
{{1}} : イベント
{{2}} : コード
setTimeout-defuser.js setTimeout をフィルタリングする
パラメータにマッチする setTimeout の登録をスキップする
{{1}} : コード
{{2}} : delay
abort-current-inline-script.js 第一引数のプロパティがインラインスクリプトで使われたときにエラーにする(それ以降が処理されない)。
第二引数が指定されたときには、その表現が含まれるインラインスクリプトで使われた場合のみ有効になる。

abort-current-inline-script.js は、メソッドもガードできる(メソッドの実体を取得するために getter が使われるから)。
エラーにしたときの window.onerror も、自分の分だけ握りつぶしているという芸の細かさ :-)
##script,redirect=noopjs との違いは、普通は目印がない script タグで、特定のものだけ動かさないとか、途中まで実行させられることとか

redirect=noopjs の意味

foo.bar$script foo.bar$script,redirect=noopjs

どちらも外部スクリプトのリクエストはブロックされるわけだし、中身を何もしない関数に置き換えている意味が分からなかった。

大きな違いは、onload のイベントが発火されるかどうか。

Anti AdBlock 系の処理では、script の onload をチェックしている奴がいるらしくて、そういうタイプを無効化するために利用されているみたいだ。

Cosmetic Filter の例外指定で

郵便局の郵便番号検索の結果ページがこんな感じになっている(deteil は、ぼくの typo ではない)。

<div class="adArea deteil">
    ...
</div>

こいつが、EasyList の以下の定義に引っかかる。

##.adArea

郵便局だから広告エリアはないだろうけれど、例外の指定は範囲を狭めておきたい。
というわけで、こういうふうにした。

www.post.japanpost.jp#@#div.adArea.deteil

これが、例外の指定が効いてない。

セレクタにクラスを複数指定するのがダメなのかと思ったけれど、そうではなく、例外の指定は、対象のブロックをする定義と同じになっていないと打ち消さない、ということみたい。

www.post.japanpost.jp#@#div.adArea

ちなみに、これを追記している途中(2017-11-16)に、.adArea が .bnrArea に変更された。
まさか、AdBlock を考慮したわけでもないだろうけれど。

インラインスクリプト系の制限?

分かっていないだけだろうけど、うまく制御できないケースがいくつか。

  • Network Filter
    • inline-script が効かない
  • Cosmetic Filter
    • script:inject が localhost に効かない
    • script:contains が効かない

script の beforescriptexecute イベントを使ってるから、Firefox でしか動かないよ的な情報はちらほらあるんだけど、こちらは Firefox
でも、inline-scrpt の指定が、Static Filter でも Dynamic Filter でも効かない。

script:contains が動かないって書いてる人、見つけた。

Other things worth noting are:

  • The new version is a hybrid extension right now. It will show up as legacy in about:addons
  • script:contains filter do not work
  • cosmetic filters are limited as the browser's user styles cannot be used for that anymore
  • Users who are on the "legacy" dev channel will notice that the "dev channel will cease to work". These users need to install the new version manually
uBlock Origin for Firefox

WebExtension になったのと、なんか関係あるんだろうか。
とりあえず、script の beforescriptexecute イベントは発火されるようだけれども。

My フィルタの実際

自分で追加するときには、フィルタの誤爆対処が一番多くって、次に広告じゃないけど見たくないやつ、そしてちょこざいなガード外し、という感じの頻度かな。

追加でブロック

あまり追加してないけど、こんな感じ。

! Internet Archive の寄付を募るやつ
web.archive.org###donate-banner

! 「Google をホームページに」のポップアップ
www.google.com,www.google.co.jp##div[role="dialog"]:has(a[title="No thanks"])

誤爆の対処

  1. 動的に作ってるようなページできちんと動いてない、もしくは、見えてるはずのものが見えてないことに気が付く
  2. UBO のリクエストログから、
    • 動いてない → ピンクになってる行で、5列目が script か xhr を探す
    • 見えない → 黄色になっている行で 5列目が dom か image を探す
  3. 3列目をクリックして、ブロックしているフィルタとルールを確認
  4. それを打ち消すルールを My フィルタに書く

ってな感じ。

これを書いている時点では、大体こんな感じになってる(そのまんまじゃない)。

! adlib さんのアイコン   http://q.hatena.ne.jp/1468372807#a1257828
@@||www.*hatena.*^*^adlib^

! http://candycrush.wikia.com の画像が見えなくなっちゃう
@@||slot1.images.wikia.nocookie.net^*_ads_*$script
! こっちは必要なかった(というか、入れるとビデオ広告がうるさい)
!@@||slot1.images.wikia.nocookie.net^*_analytics_*$script

! localhost のコンテンツは、ブロックする必要ない
@@*$domain=localhost

! "amazon lambda" で検索すると、「ツール」が効かなくなってる (´・ω・`)
! ABP Japanese Filter
! amazon が地雷を踏む
! @@*$domain=www.google.com
@@www.google.com/*^adinfo^$script,first-party

! 2ch で Bookmarklet が動かない(豆腐フィルタ)
! |http://$third-party,script,domain=2ch.net
@@http://localhost$script,domain=2ch.net

! National Geographic for Web の動画
@@||uliza.jp^$domain=natgeo.nikkeibp.co.jp

! 人力検索の ASIN 記法の画像が無いと、やっぱり寂しい
@@amazon.com/images$domain=q.hatena.ne.jp

! 人力検索の「関連する商品」
! JPN: ABP Japanese filters (日本用フィルタ) の &affid= に引っかかる
! パラメータは、空なのに :-/
@@||q.hatena.ne.jp/api/products?keyword=$domain=q.hatena.ne.jp

! Google Search Console が動かない
@@||www.google.com/webmasters/tools^*-analytics-

! Mozilla WebExtension Example には /popup/ に配置されたソースが結構ある
@@||github.com/*^popup^$popup,first-party

コピペガード外し

某質問で、検索して見つけたこのページ
内容はきちんとしているっぽいのだけれど、右クリックメニューに始まり、範囲選択の禁止などのコピーガードが癪に障る。果ては、ソース表示やインスペクタのキーボードショートカットまで殺してある。

まずは、イベントハンドラの確認。
ctrl + shift + i や、ALT でメニューバーを出す操作も殺されてる。
でも、アドレスバーにフォーカスが当たっている状態であれば、コンテンツのイベントハンドラは無効化できる。

インスペクタで、html のイベントを確認。
keydowncontextmenudragstart が無効化されるイベントハンドラが登録されている。
document.bodyselectstart も無効化されている。

My フィルタに以下の設定を追加して、再表示する。

www.kosodatedou.com##script:inject(addEventListener-defuser.js, /^(keydown|contextmenu|dragstart|selectstart)/)

addEventListener-defuser.js は、addEventListener を Hook して、イベントハンドラの登録を阻止する。
キーは効くようになったけど、右クリックメニューや範囲選択ができない。

ctrl + u で、ソースを確認。

<script type="text/javascript">
  document.oncontextmenu = function(e) {
    var t = e || window.event;
    var n = t.target || t.srcElement;
    if (n.nodeName != "A")
      return false
  };
  document.ondragstart = function() {
    return false
  };
</script>

こんな感じで、addEventListener メソッドを使わずに oncontextmenu プロパティに、直接 ハンドラを代入しているので、addEventListener の Hook が効かない。

My フィルタに以下の設定を追加して、再表示する。

www.kosodatedou.com##script:inject(abort-current-inline-script.js, document.oncontextmenu)
www.kosodatedou.com##script:inject(abort-current-inline-script.js, document.ondragstart)
www.kosodatedou.com##script:inject(abort-current-inline-script.js, document.body.onselectstart)

abort-current-inline-script.js は、特定のプロパティの setter、getter を Hook して、その設定や参照を阻止する。
右クリックメニューは出るようになったけど、ドラッグや ctrl-a での範囲選択ができない。
document.body.onselectstart のイベントハンドラを無効化できていない様子。

onselectstart を阻害しているコードは、こんなの。

function disableSelection(e) {
  if (typeof e.onselectstart != "undefined")
    e.onselectstart = function() {
      return false
    };
  else if (typeof e.style.MozUserSelect != "undefined")
    e.style.MozUserSelect = "none";
  else
    e.onmousedown = function() {
      return false
    };
  e.style.cursor = "default"
}
window.onload = function() {
  disableSelection(document.body)
}

document.body.onselectstart を置き換えるコードが onload で走っているので、Cosmetic Filter の script:inject が動くときには、未だ document.body.onselectstart は null のままなんだ。
script:inject は、レンダリング時に実行されて、実行された後には消される
abort-current-inline-script.js は、実行されたときに存在しているプロパティの getter / setter を書き換えているから、素直に使うと空振りしちゃう。

ちょっと悩んで、追加したのは この My フィルタ。

www.kosodatedou.com##script:inject(abort-current-inline-script.js, disableSelection)

global なスコープの関数は window のプロパティで、呼び出すときには、その getter が呼ばれている様子。
関数の getter を無効にすることで、その呼び出しを無効化できる。

最終的に追加した My フィルタは、こんな感じに。

www.kosodatedou.com##script:inject(addEventListener-defuser.js, /^keydown/)
www.kosodatedou.com##script:inject(abort-current-inline-script.js, document.oncontextmenu)
www.kosodatedou.com##script:inject(abort-current-inline-script.js, document.ondragstart)
www.kosodatedou.com##script:inject(abort-current-inline-script.js, disableSelection)

アンチ AdBlocker 対策

Image Raiderという画像検索サイト。マッシュアップ(他人の褌)のくせに AdBlocker 検出をして「AD-BLOCKER 外してね」メッセージとともに YouTube の動画を流す。

うざったいのは、こんなコード。

jQuery(document).ready(function(){
    if (jQuery('#myGContainer').height() == 0) {
        document.getElementById('myGContainer').innerHTML="<h1><strong>Ad-blocker Detected!</strong> ...";
        usingAdBlock = true;
        ga('send', 'event', 'Adblock', 'Active');
    }
});

こいつも onload 的なタイミングで処理を仕込んでくるし、長めのインラインスクリプトの一部なので、微妙に手強い。

検索してみたら、こんなページがありました。

imageraider.com ・ Issue #2819 ・ AdguardTeam/AdguardFilters
Added to English filter

imageraider.com#@#.adsbygoogle

なるほど。敢えて、Cosmetic Filter の例外を追加する、と。
広告を表示するためのスクリプトはブロックされているので、真っ白なスペースとして表示される。
あとは邪魔なスペースを小さくするだけ。

imageraider.com###myGContainer:style(height: 1px !important; overflow: hidden;)

Google の検索結果から排除

よく「ノイズレスサーチ」と言われるアレ。
例えば、クックパッドを検索結果から消しちゃうには、こんな感じ。

www.google.com,www.google.co.jp##div.g:has(h3.r > a[href*="cookpad.com"])

こんなこともできちゃう :-)

リクエストログの画面の見方

https://github.com/gorhill/uBlock/wiki/The-logger

無色 通ったリクエス
ルールによってブロックされたリクエス
ルールによってブロックの例外で通されたリクエス
黄色 Cosmetic Filter で非表示にされたか、redirect= で置き換えられたイメージとか

script:inject() は、ログに残らないのかな。

2列目
クリックすると、そのページの uBlock ポップアップを表示する。

閉じられたウィンドウやタブのログ。ツールバーの×をクリックすると消える
バックグラウンド通信(behind-the-schene)

Note in the figure above the entry named "Behind the scene": selecting this entry allows to show only behind-the-scene network requests. Behind-the-scene network requests are requests which do not originate from any specific tab, and are denoted by the eye-slash icon in the second column. More about behind-the-scene network requests here.

https://github.com/gorhill/uBlock/wiki/The-logger#page-selector

3列目
適用されたルール。
クリックすると、どのフィルターに含まれているかが分かる。

4列目
処理結果。
クリックすると、そのリクエストをルールに追加する画面になる

ーー ブロック or 非表示
++ 許可(ブロックに対する例外設定がある)
<< リダイレクト

5列目
リクエストのタイプ。doc, inline-script, script, css, image, xhr, dom 。
fetch も xhr で記録される。

6列目
基本的に、

  • Network Filter では、ブロックされた URL
  • Cosmetic Filter の場合には、そのページの URL

その他

多分、忘れても良いことだけど、一応 残しておく。

Dynamic Filter

https://github.com/gorhill/uBlock/wiki/Dynamic-filtering:-quick-guide
https://github.com/gorhill/uBlock/wiki/Dynamic-filtering:-rule-syntax
https://github.com/gorhill/uBlock/wiki/Dynamic-URL-filtering

Dynamic の命名は、ルールをテキストで書くんじゃなくて、画面からポチポチやって設定するのを「動的(dynamic)」と言っているような気がする。

Dynamic Filter も、Dynamic URL Filter も定義は同じところに書かれる。
source のサイトを表示したときに、destination へのリクエストを、block / allow / noop するだけじゃないかな。
画面からの入力に制約があるので、そのうちのいくつかのパターンに名前を付けているという。

アイコンをクリックして出てくるポップアップで、上に寄せられているホスト名じゃない部分で、緑 / 灰 / 赤 が "Type based rule" 。
下のホスト名のところが、"Hostname based rule" 。

リクエストログの 4列目をクリックして出てくるポップアップで、ダイナミック... のタブの方で指定するのが Dynamic URL Filter 。

デフォルトの Whitelist

about-scheme
behind-the-scene
chrome-extension-scheme
chrome-scheme
moz-extension-scheme
opera-scheme
vivaldi-scheme

デフォルトの、この七つ。
多分、消しちゃいけないやつ。
Firefox の WebExtension だと、about-scheme とか関係ないような気がしなくもないけれど。

外部フィルタ

デフォルトでチェックが入ってるものに加えて、豆腐フィルタを使ってる。
http://tofukko.r.ribbon.to/abp.html
http://tofukko.r.ribbon.to/Adblock_Plus_list.txt

"EasyList" と "JPN: ABP Japanese filters (日本用フィルタ)" の誤爆がときどき気になるけど、現時点では外すほどではないかな。

script:inject は、どこに注入されるのか

DOM Inspector では、どこに注入されているか分からない。
js/contentscript.js を見ると、head の末尾に追加されるようだけれども。

            if ( cfeDetails.scripts ) {
                // Have the injected script tag remove itself when execution completes:
                // to keep DOM as clean as possible.
                text = cfeDetails.scripts +
                    "\n" +
                    "(function() {\n" +
                    "    var c = document.currentScript,\n" +
                    "        p = c && c.parentNode;\n" +
                    "    if ( p ) {\n" +
                    "        p.removeChild(c);\n" +
                    "    }\n" +
                    "})();";

ああ、消されるのか。
実行中の inline script が、どの script タグだ、って欲しくなるときがたまにあるけど、currentScript なんてプロパティがあるんだ。

フィルタに 8文字以上

http://cojocco.blog113.fc2.com/blog-entry-26.html
ここに書いてある「フィルタに8文字以上」は、どこソースだろう...
まあ、ABP の話だし、

  • すべてのフィルタは、内部で正規表現に変換されます。
  • 正規表現のフィルタはできるだけ少なくする。

は、矛盾した内容だから、話半分以下かな。
2010年4月の記載だし、気にしなくて良いかな。

https://adblockplus.org/forum/viewtopic.php?t=17056
2013年8月のやりとり

https://github.com/chrisaljoudi/uBlock/issues/161#issuecomment-58547364
2014年10月
これかな。

デフォルトで取り込む対象の外部フィルタとかもそのままでも、uBO の導入前に比べて確実に速くなってるんだから、ルールの記載とかは それほど気にしなくても良いような気がする(それほど広告の展開が遅い)。
遅いなあと感じたら、誤爆の多そうな外部フィルタを外していけば良いという感じかな。

script:inject には、パラメータを渡すことができる

resources.txt 中の、{{1}}{{2}} というようなのがパラメータの指定。

setTimeout-defuser.js

mio.to##script:inject(setTimeout-defuser.js, e=d(), 1000) geektime.co.il##script:inject(setTimeout-defuser.js, adObjects)
setTimeout-defuser.js application/javascript
(function() {
    var z = window.setTimeout,
        needle = '{{1}}',
        delay = parseInt('{{2}}', 10);
    if ( needle === '' || needle === '{{1}}' ) {
        needle = '.?';
    } else if ( needle.slice(0,1) === '/' && needle.slice(-1) === '/' ) {
        needle = needle.slice(1,-1);
    ...

最初の {{1}} しか置き換えないのかなあ。
じゃなければ、最初の if が不思議すぎる。

js/cosmetic-filtering.js

FilterContainer.prototype._fillupUserScript = function(content, args) {
    var i = 1,
        pos, arg;
    while ( args !== '' ) {
        pos = args.indexOf(',');
        if ( pos === -1 ) { pos = args.length; }
        arg = args.slice(0, pos).trim().replace(this._reEscapeScriptArg, '\\$&');
        content = content.replace('{{' + i + '}}', arg);
        args = args.slice(pos + 1).trim();
        i++;
    }
    return content;
};

置き換えが一回だけなのは、そういう風に作ってるから良いとして、needle === '{{1}}' という判定を入れなければならない理由が謎。
不思議な if は、こんなのを想定しているんだ。

foo.bar##script:inject(setTimeout-defuser.js) foo.bar##script:inject(setTimeout-defuser.js, , 1000)

パラメータの置き換えは、フィルターに指定された引数のループ。
引数自体を省略すると、'{{1}}' は、置換されずに そのまま残る。
カンマを続けて書いて、空の引数にすると、'{{1}}' が空文字列で置換される。




# ここまで