それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Chrome Extension のcontent scriptでの変数隔離に対応する。

chrome extension の content script は変数が隔離されている

chrome extension を作ってて、ページ内の変数やイベントハンドラを上書きしたいよね?

頻繁にイラッとして私は上書きしたいと思っています。しかし、ContentScript のJSは isolated dom world なので、おなじDOMがレイヤー化され何枚も載っています。(CSSのようにレイヤー化して、DOM空間を隔離している)

手が出せない。。。DOM

ページ側

document.oncontextmenu = some_function

content script 側

document.oncontextmenu = null; //上書きできない

実行タイミングを制御してもダメ。

content scripts には run_at があるので、実行タイミングを色々変えることをやりたくなりますが、コレは徒労に終わる。

documentに記述されたScriptタグ内で設定されたdocument.onload などのプロパティ値にもアクセス出来ない

ページ側のDOMや変数にアクセスする手段。

  • script タグを createElementして appendChild
  • location.href に javacript:: を書いて強制実行

他にも、aを追加してクリックして実行するとか、まぁHTMLのbody 以下にScriptのコードを書き足して実行するという手段しかない。

例えば、こんな感じ

manifest.json

{
  "manifest_version": 2,
  "name": "check_extension_injection",
  "version" : "1",
  "content_scripts":[
    {
      "matches" : [ "http://*/*"],
      "js": ["test.js"],
      "run_at" : "document_end"
    }
  ]
}

test.js (コンテンツに差し込むjs)

document.body.appendChild(function(){
  sc = document.createElement("script");
  var code = function(){
    console.log("aaaaaaaaaaaaaaaa")
  }
  src = "("+code.toString()+")()"
  sc.type="text/javascript";
  sc.text=src
  return sc;
}()
);

script.text = "実行したいコード"を書くことで、変数をいじることが出来て幸せになる。

ただ、実行したいコードをStringで書くと面倒なので、Function書いてからToString()のが味噌

実行時タイミング run_at について

run_at で、拡張機能content_scripts の実行タイミングを指定することができる

  • document_start
  • document_end
  • document_idle (省略時デフォルト)

になるのですが。

それぞれ、よくわからないので、DOMContentLoadedイベントを差し込んで実験してみた

content_script で埋め込んだコード

document.addEventListener("DOMContentLoaded",function(){
    console.log("from content_script");
})

このコードとページ内のJavaScriptと競争する。

ページ内DOMContentLoadedとinjection の DOMContentLoaded の競争

run_at ページ内DOMContentLoaded content_script
document_start 後から 先から
document_end 先に実行 実行されない
docunent_idle 先に実行 実行されない

意外と、シンプルですね。 document_end で書いた DOMContentLoadedは実行されない。

ページ内の、$(document).ready() より先に実行しようとしたらDOMContentLoadedに放り込むのも確実っぽい。

拡張機能のcontent_script は並列実行が良く分からない?

タイムラインを見ましょう

timeline

今回は同期的に動いてるけど、書き方に依っては非同期的にScriptが一斉にGoしたりする。