Scripting #5

特に Chrome に対して重要な変更を施した。

wasavi が属する文書とスクリプトフレームが属する文書は、同一のオリジンである必要がある。これは、wasavi 側から scriptframe.contentWindow.dispatchEvent(ev) としたり、あるいは逆にスクリプトフレーム側から window.parent.dispatchEvent(ev); とするためだ。同一オリジンじゃないと dispatchEvent() は拒否される。dispatchEvent() を用いるのは、それが同期的に実行されるからで、postMessage() を使うといろいろと話がややこしくなる。

ところで Chrome では、wasavi が属する文書はエクステンション内のものにしていた。つまり chrome-extension://なんちゃら、という URL の文書。ところが、この URL に属する文書に付随するスクリプトは content script と同じ扱いになるのだった。この環境でスクリプトを動かすには、権限が高すぎる。

Opera や Firefox(Add-on SDK) では、エクステンション内の文書を通常のページの iframe の内容として表示することはできない(Firefox ではなにか方法はあると思うが調べてない)ので、appsweets.net 上の文書を参照している。これなら、スクリプトを動かす際に一般の web ページの権限が適用される。

ということで、Chrome でもその流儀に従うようにした。これは manifest の変更を意味する。ただしより強い権限を要求するのではなくその逆で、web_accessible_resources が不要になる。しかし一方でコンテキストメニューのために permissions に contextMenus を追加したので、次のリリースをインストールする際にはなにがしかのダイアログは出るはず。

ちなみに Chrome の不思議な特性として、コンテントスクリプトから、コンテントスクリプトの影響下にない素の Window オブジェクトにアクセスすることができない。つまり scriptframe.contentWindow を触れない。そういうわけなので、wasavi 側の文書で script 要素を生成し、以下のコードを text 属性に突っ込む:


document.addEventListener('WasaviScriptRequest', function (e) {
var ev = document.createEvent('CustomEvent');
ev.initCustomEvent('WasaviScriptRequest', false, false, e.detail);
document.getElementById('wasavi_script').contentWindow.dispatchEvent(ev);
}, false);

で、wasavi 側からスクリプトを呼び出す際は自らの文書に対してイベント起こす:


var ev = document.createEvent('CustomEvent');
ev.initCustomEvent('WasaviScriptRequest', false, false, {code:"console.log('hello, world')"});
document.dispatchEvent(ev);

Leave a Reply

Your email address will not be published. Required fields are marked *