2013-10-21 90 views
1

我正在寫一些我想作爲Chrome擴展和Firefox附加組件發佈的內容。從Firefox附加內容腳本加載附加的JavaScript代碼

Chrome擴展是already available on github。我使用類似於requirejs使用的模塊加載格式將我的代碼分解爲幾個模塊;我這樣做是爲了將Chrome專用部分與我希望在Firefox附加組件中重複使用的部分分開。

具體來說,我分裂不僅後端的工作,同時也是內容的腳本。

在Chrome中,當我的內容腳本需要加載另一個模塊,它發送消息到後臺網頁說:「請加載此模塊」;背景網頁上的腳本,然後做:

function onLoadLibrary(request, sender, sendResponse) { 
    var allFrames = request.allFrames || false; 
    chrome.tabs.executeScript(
     sender.tab.id, {file: request.library.toLowerCase() + '.js', 
         allFrames: allFrames}, 
     function() { 
     sendResponse({}); 
     }); 
    return true; 
    } 

也就是說,我能額外的JavaScript加載到相同的沙箱是要求該代碼的內容腳本。這對於使模塊依賴性起作用是必需的。

在firefox中,我無法弄清楚如何做到這一點。我將通過pageMod和通過tabs的「就緒」事件調用tab.attach來附加我的初始內容腳本。這似乎很簡單,但如果該內容腳本需要加載更多的代碼,我不知道該怎麼做。

似乎沒有辦法從main.js文件中訪問我的內容腳本正在運行的沙箱,因此我可能會向其中注入更多代碼。即使我以某種方式保留了對相關tab實例的引用(它只允許我在任何情況下注入頂部框架),看起來每個新調用tab.attach都會將注入的代碼放入新的沙箱中。傳遞給我準備好的事件句柄的對象tab不是真正的XUL標籤,我可以傳遞給require("tabs/util").getBrowserForTab;如果是的話,那麼我認爲我可以通過足夠的sdk代碼來創建我自己的沙盒,但我擔心會留下意外的內存泄漏。

我認爲通過「eval-this-code」消息將代碼傳遞迴內容腳本,但由於安全考慮,我真的不想在我的擴展中使用eval;我也擔心使用eval會讓我的Firefox加載項難以無法通過AMO。 (另外,當我的加載項在具有內容安全策略的網站上運行時,這將如何相互作用?)

使用traits來定義附加API似乎關閉了對象的訪問權限,因此我無法達到Worker裏面去我的內容腳本執行在沙箱中的參考。在這一點上,似乎我需要在我的附加SDK的幾乎完全複製剛上WorkerSandbox暴露一個方法。

注意:我正在使用Add-On sdk(該項目以前稱爲JetPack)。我願意使用Components.utils.import,如果有人能告訴我如何使用來自Add-On SDK管理的內容腳本的內容。

回答

1

內容腳本不公開公共API,它被初始化後,多個腳本附加到內容腳本沙箱。您應該提交一份enhancement bug並說明您的使用案例,如果您沒有提交(首先搜索)和/或您自己的案例。

如果您的加載項擁有DOM(widget),那麼這只是附加另一個腳本標記的問題。

對於像page-mods這樣沒有DOM的東西,你只剩下幾個選項,其中沒有一個是真正令人滿意的。正如你已經發現你自己,特質的使用禁止你訪問「私人」屬性/方法。

  • page-mod/tab/content-worker提供您所需要的功能。這需要創建您自己的模塊副本並公開必要的API以將腳本注入現有的工作人員。

    這是一個陡峭的學習曲線(但鑑於你已經知道細節如性狀,應該可以爲你做),但更重要的是難以維持,因爲你需要確保你跟上游。 AMO編輯不會喜歡你:p

    從好的一面來看,你可以嘗試讓你的東西在上游提交,爲每個人解決這個問題,併成爲許多使用附加SDK的作者的英雄。

  • 您提出的eval方法。這不僅是這個eval是安全問題的主要來源,但它也可能是一個性能殺手,因爲現在IIRC eval ed編碼將不會使用JIT。當然,即使使用「正確」,它也會使我們AMO編輯畏縮。

  • 根本不要使用延遲加載,並從一開始就指定所有內容腳本。這是附加組件通常所做的(我幾乎傾向於說「總是」)。但是,這與您當前的設計衝突,根據您的附加組件,可能會導致嚴重的性能損失,用於加載最終並不真正需要的內容。

  • 您可以使用require機制將大多數腳本作爲SDK模塊而不是content-scripts。當然,這並不總是可行的,例如,處理通常會修改內容腳本中DOM的代碼,但可能適用於其他某些內容。

  • 用您自己的類似Greasemonkey的增強API替換page-mod等。這意味着很多工作,這是很容易出錯的,對安全敏感並且必須維護。所以,這不是一個真正的解決方案,國際海事組織...

Components.utils.import不會幫助你。無論如何,它不可用於內容腳本。

+0

https://bugzilla.mozilla.org/show_bug.cgi?id=929202 –

+0

而且我會看看我是否可以重構一些東西,這樣我就不會在FF端執行延遲加載 - 我仍然會使用我的模塊系統,但在後臺腳本中,我將在製作'page-mod'或'tab.attach'之前計算完整的依賴關係樹,這樣當我在客戶端腳本沙箱中加載模塊時,我可以指定所有東西前面的順序不需要返回錯過的依賴關係。在Chrome和ff之間會出現比我想要的更大的分歧,但它仍然應該保留將來可能會改變的內容,因爲代碼在兩者之間共享。 –

+0

在背景頁面上計算沙盒中的依賴關係樹,然後用所需的一切加載客戶端腳本確實看起來是一種可行的方法。接受答案... –