Sep 13, 2005
あ、やっとSplitWindowの意味が分かった
SplitWindowというのが一体どういうものなのか今の今までとんと理解できなかったんだけど、やっと分かった。ソースをタブで表示するのに引数オブジェクトを渡せない問題、これこそがSplitWindowの影響だったんだな。
つまりSplitWindowというのは、一つのページのビューが二つの名前空間を持っていて、関数の実行コンテキストによって、参照される名前空間が変わるというものなんだ。
以下、実例。
具体的にはこういう事だ。まず、以下のような内容のページをブラウザ内で読み込んだとする。
<!-- XML宣言、DOCTYPE宣言は省略 -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>test</title>
</head>
<body>
<script type="application/javascript"><![CDATA[
window.testNumber = 10;
]]></script>
<p><button onclick="alert(window.testNumber);">click</button></p>
</body>
</html>
次に、ブラウザウィンドウ(chrome://browser/content/browser.xul)のコンテキストで以下の関数を実行する。
gBrowser.contentWindow.testNumber = 50;
alert(gBrowser.contentWindow.testNumber);
今までであれば、内容ウィンドウの実行コンテキストのwindow
とブラウザウィンドウのgBrowser.contentWindow
は同じ物を指していた。つまり、この状態で、読み込んだページのclickと書かれたボタンをクリックすれば、50と表示される。
ところがSplitWindow実装後のGeckoでは、実行コンテキストによってwindow
オブジェクトの名前空間、プロパティを保持するメモリ領域が切り替わる。そのため、ブラウザウィンドウのコンテキストで実行したスクリプトではgBrowser.contentWindow.testNumber
は50と表示されるのに、ページ内のボタンをクリックすると、相変わらず10と表示される。「ブラウザウィンドウの実行コンテキストにおけるtestNumber
プロパティ」と「内容ウィンドウの実行コンテキストにおけるtestNumber
プロパティは、それぞれ全く別個のものとして扱われるんだ。
この名前空間のスイッチングは、windowオブジェクトだけでなく、それに従属している全てのオブジェクトに対して行われる。だから、ブラウザウィンドウの実行コンテキストでcreateElement()
で生成した要素ノードに新たなプロパティを付与した上で、内容ウィンドウのDOMツリーにappendChild()
等で埋め込んでも、内容ウィンドウの実行コンテキストになった瞬間に名前空間が切り替わるので、要素ノードに付与したプロパティは、内容ウィンドウの実行コンテキストからは完全に不可視になる。
ちなみに、gBrowser.contentWindow.setTimeout("expression", timeout)
といった形でタイマー処理させた場合は、文字列として渡したexpression
部分は内容ウィンドウの実行コンテキストで実行されることになる。また、ドキュメントのDOMツリーの変更(要素の属性のセットや内容の追加・削除など)は実行コンテキストに関係なく反映されるようだ。そのため、単純な文字列や数値などであれば、ブラウザウィンドウから内容ウィンドウへと受け渡しできる。
……ということで、分かってみれば「なーんだそういうことか」という話だった。こりゃあ確かに強力だ。これによって、「ブラウザウィンドウの実行コンテキストで内容ウィンドウの中にChromeウィンドウ内の関数や変数への参照を作っていたら、内容ウィンドウの実行コンテキストでそれらにアクセスされ、情報漏洩や攻撃の糸口に利用されてしまう」という危険はなくなったと考えていい。
セキュリティ的には非常に嬉しい進歩なんだけど、それが今回の問題では仇になってしまってるんだな。名前空間が異なってしまっているために、選択範囲オブジェクトや元ウィンドウのwindow
オブジェクトなんかの、JavaScriptオブジェクトそのものは、どう頑張っても渡すことができない。いやーもう完全にお手上げですわ。
wikieditish message: Ready to edit this entry.