console.logのことを思い出す
FirebugがunsafeWindowにconsoleを設定してるのだった。
コードは脆弱性、全てのサイトでGM_xmlhttpRequestを使う、解説と回避 - 実用でnanto_viさんが
対応策として考えられるのは、関数宣言・変数宣言を使わず、明示的に this をつけることにより、すべての値をsandbox オブジェクトのプロパティとして扱うことです。
といわれているように、全部thisがつけられている。コメントにもそのことが書かれている。
function FirebugConsole(context, win) { this.firebug = Firebug.version; // We store these functions as closures so that they can access the context privately, // because it would be insecure to store context as a property of window.console and // and therefore expose it to web pages. this.log = function() { logFormatted(arguments, "log"); };
そしてFirebugはこのwindow.consoleを設定するタイミングの実装に注意を払っている。
watchWindow: function(context, win) { // XXXjoe Move this to Firebug.Console if (!win.console) { win.console = new FirebugConsole(context, win); }
というコードで値を入れてるので(winはGMでいうunsafeWindow)、当然window.console のsetterに細工をされたら? ということになる。
watchWindowが呼ばれるタイミングは
var FrameProgressListener = extend(BaseProgressListener, { onStateChange: function(progress, request, flag, status) { // We need to get the hook in as soon as the new DOMWindow is created, but before // it starts executing any scripts in the page. After lengthy analysis, it seems // that the start of these "dummy" requests is the only state that works. if (flag & STATE_IS_REQUEST && flag & STATE_START) { if (safeGetName(request) == dummyURI) { // Another weird edge case here - when opening a new tab with about:blank, // "unload" is dispatched to the document, but onLocationChange is not called // again, so we have to call watchTopWindow here var win = progress.DOMWindow; if (win.parent == win && win.location.href == "about:blank") TabWatcher.watchTopWindow(win, null); TabWatcher.watchWindow(win); } } // Later I discovered that XHTML documents don't dispatch the dummy requests, so this // is our best shot here at hooking them. if (flag & STATE_IS_DOCUMENT && flag & STATE_TRANSFERRING) TabWatcher.watchWindow(progress.DOMWindow); } });
に書いてあるとおり、DOMWindowが生成された後でかつjavascriptの実行が行われる前というタイミング。これならwindowはあるけどconsoleに細工をされる心配がないので安心してunsafeWindow.consoleに代入できる。
ちなみにこのタイミング、自分で書くと簡単には取れないかんじでした。
でも拡張機能からならTabWatcher.watchWindow()で、じぶんの関数をFirebugからよんでもらうことができます。wiiremocomのwindow.wiiremocomはそうして設定しました。デバッグとか楽になると思います。
今気づいたけど、これ使うとほんとにextensionのコードとして書かないところだけをちょこっと書いて、後はふつうのhtmlファイルで開発していくとかできそう。便利かわかんないけど。