安全にSelectionオブジェクトを得る(XPCNativeWrapperの使用)

window.getSelection と document.getSelection - hogehoge @teramakoの続き。

Firefox内部からブラウザの選択範囲を得る場合だが、ブラウザ内のコンテンツは本来の関数が上書きされている可能性があるためは安全でない。それを解決するためにXPCNativeWrapper - MDCがあり、window.content.document.getSelectionはデフォルトでXPCNativeWrapperにラップされている。
しかし、window.getSelection と document.getSelection - hogehoge @teramakoにあるようにwindow.content.document.getSelectionは選択範囲の文字列を返してしまう。通常であれば文字列で構わないのだが、Selectionオブジェクトでないとできない事もある。
かといって、window.content.window.getSelectionSelectionオブジェクトを返すがXPCNativeWrapperにラップされていないためコードが上書きされている可能性がある。これについてはwindow.content.document.getSelection()にアクセスした時の変なメッセージが出るを参照。

安全にSelectionオブジェクトを得るためには自らXPCNativeWrapperオブジェクトを作成する必要があり、XPCNativeWrapper - MDCでいう明示的かつ徹底的にラップする。

var windowWrapper = new XPCNativeWrapper(window.content.window);
var sel = windowWrapper.getSelection();

getSelection_test.html

<html>
<head>
<title>getSelection Test</title>
<script type="text/javascript">
window.getSelection = function(){
    return "window.getSelection だよん";
}
</script>
</head>
<body>
<h1>getSelection Test</h1>
<p>aaaaaaaaaaaa</p>
</body>
</html>

実際に上記のようなページを表示してaaaaaaaを選択してやってみると違いが出る。

JavaScript Shellの結果

window.content.window.getSelection
function () {
  return "window.getSelection \u3060\u3088\u3093";
}
window.content.window.getSelection()
window.getSelection だよん
var windowWrapper = new XPCNativeWrapper(window.content.window);
windowWrapper.getSelection
function XPCNativeWrapper function wrapper() {
  [native code]
}
windowWrapper.getSelection()
aaaaaaa
windowWrapper.getSelection() instanceof Selection
true
windowWrapper.getSelection().getRangeAt(0).cloneContents()
[object XPCNativeWrapper [object DocumentFragment]]

単純なwindow.content.window.getSelectionではページ中に上書きされたgetSelectionメソッドが返ってきてしまうのに対して、XPCNativeWrapperでラップすると本来のgetSelectionが呼ばれていることが分かる。(といってもラップされているので違ったオブジェクト名になっているが...)