Greasemonkey extension のコードから実行時のスコープを調べる
Greasemonkey script execution environment – Chagama Lab でGreasemonkeyのスクリプト実行時のスコープがどうなっているかの話が書かれていました。自分もAutoPagerizeのコードを読んだときに、コードがfunctionで囲まれているのを見てブックマークレット同様そう書かないとだめなものなんだなー(ほかのスクリプトand/orウインドウとスコープが共有されている)、と思ってたので、そんなことないよ、と書かれているのは新鮮でした。
いい機会なのでどうなっているのかはっきりさせておくべくGreasemonekyのextensionのコードをのぞいてみたらシンプルなつくりになっていてすぐ分かりました。
Greasemonkeyのバージョンは0.7.20070607です。
はじめに chrome/chromeFiles/content/browser.js の GM_BrowserUI.chromeLoad でGreasemonkeyの実行時に必要なイベントをフックしています。
this.appContent = document.getElementById("appcontent");
.... snip ....
// hook various events
GM_listen(this.appContent, "DOMContentLoaded", GM_hitch(this, "contentLoad"));
GM_listen(this.contextMenu, "popupshowing", GM_hitch(this, "contextMenuShowing"));
GM_listen(this.toolsMenu, "popupshowing", GM_hitch(this, "toolsMenuShowing"));
AutoPagerizeは、ベージのロードが終わったあとで有効になるんだなー、と思ってたのですが Greasemonkeyが実行されるタイミングが DOMContentLoaded だからと分かったのは思わぬ収穫。
このイベントから2段階くらい関数が呼ばれて、最終的にuser.jsを呼び出しているのは components/greasemonkey.js の injectScripts でした。
sandbox = new Components.utils.Sandbox(safeWin);
logger = new GM_ScriptLogger(script);
console = firebugConsole ? firebugConsole : new GM_console(script);
storage = new GM_ScriptStorage(script);
xmlhttpRequester = new GM_xmlhttpRequester(unsafeContentWin,
appSvc.hiddenDOMWindow);
sandbox.window = safeWin;
sandbox.document = sandbox.window.document;
sandbox.unsafeWindow = unsafeContentWin;
// hack XPathResult since that is so commonly used
sandbox.XPathResult = Ci.nsIDOMXPathResult;
// add our own APIs
sandbox.GM_addStyle = function(css) { GM_addStyle(safeDoc, css) };
sandbox.GM_log = GM_hitch(logger, "log");
sandbox.console = console;
sandbox.GM_setValue = GM_hitch(storage, "setValue");
sandbox.GM_getValue = GM_hitch(storage, "getValue");
sandbox.GM_openInTab = GM_hitch(this, "openInTab", unsafeContentWin);
sandbox.GM_xmlhttpRequest = GM_hitch(xmlhttpRequester,
"contentStartRequest");
sandbox.GM_registerMenuCommand = GM_hitch(this,
"registerMenuCommand",
unsafeContentWin);
sandbox.__proto__ = safeWin;
this.evalInSandbox("(function(){\n" +
getContents(getScriptFileURI(script.filename)) +
"\n})()",
url,
sandbox,
script);
最後のevalInSandboxでコードをfunctionで囲んでくれているので確かにuser./js側でfunctionで書くのは意味がないと言えます。このComponents.utils.SandboxはComponents.utils.evalInSandbox – MDCによるとFirefox1.5から導入されたそうで
その名の通りjsの実行時にsandboxを作って実行してくれるもの。コードを見るとsandbox.windowにブラウザのウインドウのwindowを代入しているけれど Greasemonkey script execution environment 2 – Chagama Labに書かれている
Global オブジェクト != window オブジェクトであることも分かる
という結果になっているということは、sandboxが勝手にwindowというプロパティをグローバルスコープにしたりはしないということみたいですね。
Greasemonkeyのコードはextensionシロウトでも読めるようなつくりだったので疑問があったらのぞいてみればわかりそうです。
About this entry
You’re currently reading “Greasemonkey extension のコードから実行時のスコープを調べる,” an entry on ku
- Published:
- 2007.07.22 / 10pm
- Category:
- Firefox, greasemonkey

No comments
Jump to comment form | comments rss [?] | trackback uri [?]