2013-03-02 19 views
1

從閱讀例子來看,這看起來應該很容易。這裏是我的代碼:如何在firefox擴展中使用「targetObj」參數來loadSubScript()?

rhkTest = { 
    onPageLoad: function(event) { 
    var doc = event.originalTarget; 
    var wnd = doc.defaultView; 
    var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] 
     .getService(Components.interfaces.mozIJSSubScriptLoader); 
    loader.loadSubScript("chrome://rhkoshi-extension/content/testfoo.js", wnd); 
    alert('typeof(wnd) = ' + typeof(wnd)); 
    alert('typeof(wnd.window.rhk_test1) = ' + typeof(wnd.window.rhk_test1)); 
    alert('typeof(wnd.window.rhk_test2) = ' + typeof(wnd.window.rhk_test2)); 
    alert('typeof(wnd.window.rhk_test3) = ' + typeof(wnd.window.rhk_test3)); 
    alert('typeof(wnd.rhk_test1) = ' + typeof(wnd.rhk_test1)); 
    alert('typeof(wnd.rhk_test2) = ' + typeof(wnd.rhk_test2)); 
    alert('typeof(wnd.rhk_test3) = ' + typeof(wnd.rhk_test3)); 
    alert('typeof(rhk_test1) = ' + typeof(rhk_test1)); 
    alert('typeof(rhk_test2) = ' + typeof(rhk_test2)); 
    alert('typeof(rhk_test3) = ' + typeof(rhk_test3)); 
    alert('typeof(this.rhk_test1) = ' + typeof(this.rhk_test1)); 
    alert('typeof(this.rhk_test2) = ' + typeof(this.rhk_test2)); 
    alert('typeof(this.rhk_test3) = ' + typeof(this.rhk_test3)); 
    alert('typeof(window.rhk_test1) = ' + typeof(window.rhk_test1)); 
    alert('typeof(window.rhk_test2) = ' + typeof(window.rhk_test2)); 
    alert('typeof(window.rhk_test3) = ' + typeof(window.rhk_test3)); 
    }, 
    onLoad: function(event) { 
    var appcontent = document.getElementById("appcontent"); 
    if (appcontent) { 
     appcontent.addEventListener("DOMContentLoaded", rhkTest.onPageLoad, true); 
    } 
    }, 
}; 

window.addEventListener("load", function(e) { rhkTest.onLoad(e); }, false); 

其中testfoo.js包含:

window.rhk_test1 = 'testval1'; 
rhk_test2 = 'testval2'; 
var rhk_test3 = 'testval3'; 

window.alert('Running testfoo.js'); 

我得到警報 「運行testfoo.js」,所以找到該文件並執行。我還得到一個警告,指出wnd是一個「對象」(如預期的那樣 - 它在別處被初始化)。但是,其他所有警報都會針對各種typeof()調用顯示「未定義」。當然,我不期望所有這些有價值,但我希望至少其中一個可能會顯示的東西。

我的價值觀發生了什麼變化?他們不應該在wnd的屬性嗎?

我在Windows 7上運行Firefox 19.0(如果有的話)。

回答

1

注意:請參閱Wladimir Palant的答案以獲得更全面的概述。

就我的例子而言,我實際上正確地使用了這個函數,這或多或少都是合理的期望值。這個問題是由Firefox的XPCNativeWrapper功能引起的。

我仍然在努力瞭解細節,但簡而言之,我的wnd對象被封裝在XPCNativeWrapper中,testfoo.js被認爲是「受保護的」腳本,這意味着我看不到任何更改一旦控制對象從testfoo.js傳回。

的解決方案是前解開所述對象(或之後 - 即工程太)將它傳遞給下標,如下所示:當我這樣做,變量/屬性由改性

var wnd = XPCNativeWrapper.unwrap(doc.defaultView); 

testfoo.js對父腳本可見。

我還不完全瞭解完整的基礎設施,足以知道這是否「安全」。畢竟,這是一種安全機制,旨在保護我的擴展程序免受瀏覽器頁面上的惡意代碼的侵害。

我也看到傳遞對象到下標定義的方法中的一些問題(在我的例子中沒有顯示)。爲此,我會另外提出一個問題。長篇小說:解謎是針對我的問題提出的即時問題(可能是「解決方案」)的解決方案,但似乎並不完全解決我在第一個問題中產生的困難地點。

3

這實際上有點複雜,取決於wnd是什麼。您可以使用常規對象作爲下標的範圍:

var myScope = this; 
var subscriptScope = {}; 
loader.loadSubScript("testfoo.js", subscriptScope); 

但是,範圍並不完全是孤立的。在testfoo.js這裏是一些示例,代碼:

var foo = "bar;  // Creates subscriptScope.foo 
xyz = 1;    // Creates myScope.xyz 
function dummy() {} // Creates subscriptScope.dummy 
var outer = myScope; // Assigns a value from outer scope 

所以當標的變量和函數在其範圍內定義,它仍然可以訪問加載它的腳本的範圍 - 未聲明的變量將仍可以創建在外部範圍內,外部範圍將搜索無法在下標範圍內解析的變量。

如果你真的想下標隔離,那麼你應該使用這樣一個窗口對象或沙箱中的「正確」的全局對象:

var myScope = this; 
var subscriptScope = new Components.utils.Sandbox("about:blank"); 
loader.loadSubScript("testfoo.js", subscriptScope); 

現在testfoo.js將不能訪問外部範圍的任何更多:

var foo = "bar;  // Creates subscriptScope.foo 
xyz = 1;    // Creates subscriptScope.xyz 
function dummy() {} // Creates subscriptScope.dummy 
var outer = myScope; // Exception: myScope is not defined 

注意,並沒有什麼特別之處window變量 - 如果你想下標有該變量,你必須在範圍對象來定義它,如:

subscriptScope.window = subscriptScope; 

作用域對象本身可以作爲下標頂級的this訪問。

+0

謝謝您的詳細解答。不幸的是,鑑於你所說的話,我的結果似乎不符合我的預期。我已更新我的問題以反映更完整的示例。正如你所看到的,wnd是一個窗口對象,希望你的意思「適當」。我已經添加了更多的測試數據可能已經走了,但我仍然空着。 – 2013-03-04 13:36:38