2016-07-25 48 views
1

我正在研究瀏覽器擴展/附加組件。我們在Chrome中工作,所以我試圖讓它在Firefox中工作。我怎樣才能讓Firefox附加內容注入並在其他頁面腳本之前運行腳本?

我已將我的附加組件加載到Firefox Developer Edition 49.0a2(2016-07-25)。

我的擴展涉及content_script設置爲run_at: document_start,所以它可以在其他頁面腳本運行之前注入腳本標記,因此它可以使對象全局可用於網站。

這似乎在Chrome中工作正常,但在Firefox中,它已被證明是一種競爭條件,其他頁面資源大多數時間加載。

是否有策略以可注入的方式加載內容腳本&在任何其他頁面腳本運行之前加載腳本?

當我添加日誌時,我可以很好地隔離發生的事情。在這個例子中的內容腳本:

// inject in-page script 
console.log('STEP 1, this always happens first') 
var scriptTag = document.createElement('script') 
scriptTag.src = chrome.extension.getURL('scripts/inpage.js') 
scriptTag.onload = function() { this.parentNode.removeChild(this) } 
var container = document.head || document.documentElement 
// append as first child 
container.insertBefore(scriptTag, container.children[0]) 

現在,如果文件scripts/inpage.js只是運行日誌,像

console.log('STEP 2, this should always run second') 

我訪問的網頁上的腳本是這樣的:

console.log('Step 3, the page itself, should run last') 

在實踐中,步驟2和步驟3以非確定性順序運行。

非常感謝!

我有一個特殊的分支公共倉庫的腳本的Firefox兼容的版本,如果你敢嘗試一下自己:https://github.com/MetaMask/metamask-plugin/tree/FirefoxCompatibility

+0

這是我預先在當前頁面上添加腳本標記的行。當我使用日誌執行此操作時,我確實看到此代碼在頁面腳本之前運行,但注入的腳本本身並不總是在頁面腳本之前運行。 https://github.com/MetaMask/metamask-plugin/blob/FirefoxCompatibility/app/scripts/contentscript.js#L20 – DanF

回答

3

的與外部源(<script src>)動態插入腳本不會塊腳本的執行,所以不能保證你的腳本會加載。如果您的擴展程序在Chrome中運行,那純粹是幸運的。

如果你真的想休息之前運行的腳本,你必須在線運行:

var actualCode = ` 
// Content of scripts/inpage.js here 
`; 

var s = document.createElement('script'); 
s.textContent = actualCode; 
(document.head || document.documentElement).appendChild(s); 
s.remove(); 

理想情況下,你的構建腳本會讀scripts/inpage.js,它序列化到一個字符串,並把它放在actualCode變量。但如果inpage.js只是幾行代碼,那麼可以使用上面的代碼。

請注意,您不應該在網頁中注入代碼,除非它是絕對必要的。原因是頁面的執行環境不可信。如果你注入document_start,那麼你可以保存稍後使用的函數和(原型)方法(在閉包中),但是需要非常小心的編碼。

如果您的內容腳本不是由構建腳本生成的,而您仍然希望將腳本分開,那麼您還可以使用同步XMLHttpRequest來獲取腳本。由於性能原因,不建議使用同步XHR,因此使用它需要您自擔風險。擴展代碼通常捆綁了您的擴展,所以使用同步XHR的應該是低風險:

// Note: do not use synchronous XHR in production! 
var x = new XMLHttpRequest(); 
x.open('GET', chrome.runtime.getURL('scripts/inpage.js'), false); 
x.send(); 
var actualCode = x.responseText; 

var s = document.createElement('script'); 
s.textContent = actualCode; 
(document.head || document.documentElement).appendChild(s); 
s.remove(); 
+0

我只是添加一個註釋,在IRC中,您還指出FireFox提供了額外的方法來乾淨地完成我的目標是通過導出助手將內容暴露給主頁的頁面:https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction – DanF

+1

@ DanF'Component.utils.exportFunction'等尚不可用(並且它們將不會**在「Components」命名空間中可用; WebExtensions **不能**使用'Components')。當https://bugzil.la/1280482上的補丁出現時,您可以使用全局'exportFunction'方法獲得相同的功能。 –

0

如果您使用的是基於bootstrap.js附加組件,您可以使用framescript和DOMWindowCreated與文檔工作甚至在HTML DOM(過去document.body等基礎知識)呈現--之前 - innerHTML將可用,但不會執行任何腳本。你可以把你的內聯腳本作爲@Rob提到的頂部。

相關問題