宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
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オブジェクトそのものは、どう頑張っても渡すことができない。いやーもう完全にお手上げですわ。
イマイチ理解しきれていないので外してたらごめんなさい。
いかにコンテンツ部分と、chrome部分とでメモリ空間が違おうとも、chrome部分からコンテンツ部分のオブジェクトを取得できれば問題無いんじゃないかという話に落ち着くと思います。
現在、Firefox(Trunk/1.8branch)のFAYTはXPCOMを通して発見したリンクの要素を取得して、これに疑似フォーカスを与えるために見た目を操作したり、イベントの発行を行ったりしています。(ちゃんと動いてます)
つまり、別の手段でコンテンツのwindowオブジェクト等を取得する方法が何かあるんじゃないんでしょうか?
とりあえずFAYTのソースはこちらを。
http://lxr.mozilla.org/mozilla/source/toolkit/components/typeaheadfind/content/findBar.js
とりあえず、viewSource.xulやviewPartialSource.xulの初期化処理の一部を自力で行うことで解決を図ることにしました。
ああめんどくさ……
自分もよくわかっていませんが、
xpcnativewrappers=no で、
gBrowser.contentWindow.testNumber にアクセスできました。
https://bugzilla.mozilla.org/show_bug.cgi?id=302276
http://developer.mozilla.org/en/docs/Safely_accessing_content_DOM_from_chrome
の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2005-09-13_splitwindow.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。
writeback message: Ready to post a comment.