2018年2月15日木曜日

強力なポップアップブロックをChrome拡張で作ってみた (1)

Chrome 64からポップアップブロックが強化されたとの事で、さっそく入れてみました。 怪しげなサイトをいくつか開いて見ましたが、全然ブロックしてくれませんね…。少し残念。 これでは当分ポップアップとの戦いは終わらなそうです。

鬱陶しいポップアップやリダイレクトは、昔ならクリックジャッキングで実装している事が多かったと思うのですが、 最近はクリックイベントにスクリプトを仕込んでいる事が多いと思います。 そのためイベントが実行された後にブロックするのはスクリプトのスコープを覗けない以上、削除するのは割と難しいんですよね。 下手にイベントを削除するとサイトがまともに動かなくなる可能性もありますから。

しかし、ふと思いました。 そもそもJavaScriptでURLを開くイベントだけを削除してしまえば良いじゃないかと。 それなら悪影響もほとんどなくポップアップと確実にオサラバできるのではないかと。 そんな訳でChrome拡張を作ってみました。


まず以下のファイル構成を作ります。 以前の Minimal User CSS & JavaScript なChrome拡張を作った を拡張していく形で話を進めるので、合わせて参考にしてみてください。
usercssjs/
  manifest.json
  user.css
  user.js
  popup_blocker.js

manifest.jsonを以下のように編集します。 web_accessible_resourcesを指定してuser.jsからpopup_blocker.jsを呼び出せるようにするのがポイントです。
{
  "name": "Minimal User CSS & JavaScript",
  "version": "0.0.1",
  "manifest_version": 2,
  "description": "Minimal User CSS & JavaScript",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "css": ["user.css"],
      "js": ["user.js"],
    }
  ],
  "web_accessible_resources": ["popup_blocker.js"]
}

user.jsにpopup_blocker.jsを呼び出すための具体的なコードを加えます。適当な場所でOK。
function loadScript(file, tag) {
  var node = document.getElementsByTagName(tag)[0];
  var s = document.createElement('script');
  s.setAttribute('type', 'text/javascript');
  s.setAttribute('src', file);
  return node.appendChild(s);
};
loadScript(chrome.runtime.getURL('popup_blocker.js'), 'body');

popup_blocker.jsではJavaScriptでURLを開くイベントを削除します。 document.locationを凍結してページ移動を禁止し、window.openを削除する事で新規タブやポップアップを禁止します。 実はこれたったの2行で済みます。
Object.freeze(document.location);
delete window.open;

あとはこの拡張を読み込むだけです。chrome://extensions にアクセスし、上部に表示されている「デベロッパーモード」をONにします。 そして「パッケージ化されていない拡張機能を読み込む...」を押して、usercssjsディレクトリを選択すれば完了です。 普通の拡張のようにパッケージ化していないので、Chrome拡張のファイルを編集後に設定をリロードする事ができます。結構便利。



このスクリプトを使うとポップアップの鬱陶しいサイトの動きを完全に止める事ができます。 リダイレクトは気持ち程度。 …ただ、身近なサイトでもwindow.openは結構使ってるので弊害があります。 例えばBloggerの編集画面は動かない場所が出てきました。

そんな訳で実利用に用いるにはもう少し改良を加えたほうが良いです。 (1) manifest.jsonで適用サイトを限定する、 (2) popup_blocker.jsで適用URLを限定する、 (3) URLを判定してポップアップを停止する、といった対処をしていく必要がありそうです。


1に関しては、manifest.jsonの "matches": ["<all_urls>"] を編集すれば良い(参考)ですが、拡張全体に影響が出てしまうので別の拡張に分離したほうが良いでしょう。 2に関しては、popup_blocker.jsを以下のようにホストで判定して適用すると良いでしょう。
if (location.host == "www.google.co.jp") {
  Object.freeze(document.location);
  delete window.open;
}

3に関しては、ここまでの記述にも修正が加わり、長くなりそうなので次回に続きます。

0 件のコメント: