2012-02-09 79 views
3

當我使用Add-on SDK編寫Firefox附加組件時,我注意到附加代碼和內容腳本代碼會阻止彼此的執行。此外,附加代碼似乎甚至阻止與其他Firefox窗口(不僅僅是選項卡)的交互。與Firefox附加腳本和內容腳本併發

什麼是Firefox附加組件的併發/過程模型?

是否可以同時運行附加代碼和內容腳本代碼而沒有合作多線程(la定時器)?

加載代碼加載了多少次?每個窗口一次?每個標籤一次?一旦?

documentation狀態:

The Mozilla platform is moving towards a model in which it uses separate processes to display the UI, handle web content, and execute add-ons. The main add-on code will run in the add-on process and will not have direct access to any web content.

所以我希望在未來,他們確實不會互相干擾獨立的過程,但是這似乎並沒有被現在的情況。


更新:

我一直在使用一個頁面工人從附加代碼試過,但不幸的是仍然塊內容腳本(以及其他所有的JavaScript)。我也嘗試在頁面工作者中使用web worker,但在調用web worker的postMessage函數時出現以下錯誤。

TypeError: worker.postMessage is not a function

我也嘗試創建頁面工人的iframe,然後創建在iframe一個網絡工作者,但不幸的是我無法從網頁工人使用window.addEventListener。我得到以下錯誤:

TypeError: window.addEventMessage is not a function

最後,我試着將腳本(通過腳本元素)到頁面工人頁面創建一個網絡工作者這似乎工作。不幸的是,我無法與這位網絡工作者溝通,因爲我只能通過document.defaultView.postMessage發送消息給它。

哦糾結的網,我織......

內容的腳本 - >插件 - >頁面工人 - > IFRAME - >網絡工作者 - >我的代碼


我已經包括一個簡單的例子:

的package.json

{ 
    "name": "test", 
    "author": "me", 
    "version": "0.1", 
    "fullName": "My Test Extension", 
    "homepage": "http://example.com", 
    "id": "jid1-FmgBxScAABzB2g", 
    "description": "My test extension" 
} 

LIB/main.js

var data = require("self").data; 
var pageMod = require("page-mod"); 

pageMod.PageMod({ 
    include: ["http://*", "https://*"], 
    contentScriptWhen: "start", 
    contentScriptFile: [data.url("content.js")], 
    onAttach: function (worker) { 
     worker.port.on("message", function (data) { 
      // simulate an expensive operation with a busy loop 
      var start = new Date(); 
      while (new Date() - start < data.time); 
      worker.port.emit("message", { text: 'done!' }); 
     }); 
    } 
}); 

數據/內容。JS

self.port.on("message", function (response) { 
    alert(response.text); 
}); 

// call a very expensive operation in the add-on code 
self.port.emit("message", { time: 10000 }); 

回答

6

的信息傳送系統的設計充分考慮了多進程環境。然而,這種環境並沒有出現,看起來也不會在不久的將來發生。因此,您真正擁有的是在主線程(UI線程)上的同一進程中運行的附加組件和內容腳本。這意味着其中只有一個正在運行,因爲您已經注意到沒有併發性。

Is it possible to run add-on code and content script code concurrently without cooperative multithreading (a la timers)?

是的,你use web workers(什麼都沒有做的page-worker模塊,儘管類似的名稱)。對於昂貴的操作,這通常是值得推薦的 - 你不希望你的插件在做某事時停止對消息做出響應。不幸的是,附加SDK不公開網絡工作者正確,所以我只好用變通建議here

worker.port.on("message", function (message) { 
    // Get the worker class from a JavaScript module and unload it immediately 
    var {Cu} = require("chrome"); 
    var {Worker} = Cu.import(data.url("dummy.jsm")); 
    Cu.unload(data.url("dummy.jsm")); 

    var webWorker = new Worker(data.url("expensiveOperation.js")); 
    webWorker.addEventListener("message", function(event) 
    { 
     if (event.data == "done") 
     worker.port.emit("message", { text: 'done!' }); 
    }, false); 
}); 

JavaScript的模塊data/dummy.jsm只包含一行:

var EXPORTED_SYMBOLS=["Worker"]; 

How many times is the add-on code loaded? Once per window? Once per tab? Once?

如果您詢問附加代碼:只要加載項處於活動狀態,它將只加載一次並保持在附近。至於內容腳本,腳本注入的每個文檔都有一個單獨的實例。

+0

這似乎並不奏效。如果我嘗試在附加代碼中創建一個web worker,那麼它會顯示_ReferenceError:Worker不是defined_。如果我嘗試在內容腳本中創建web worker,那麼它會顯示_ReferenceError:webWorker.addEventListener不是函數_。 – fixedpoint 2012-02-10 08:08:46

+0

@ user967974:是的,在查看一些附加SDK的討論之後,看起來網絡工作者還沒有真正受到支持。我用黑客更新了我的答案,但仍然可以使用它們。 – 2012-02-10 09:14:57

+0

這似乎工作,但有一個奇怪的警告。我無法將postMessage中的對象傳遞給worker。它引發異常_該對象無法克隆_。當然,我可以使用JSON序列化對象,然後將字符串傳輸給工作人員。謝謝。 – fixedpoint 2012-02-10 10:28:32

0

我發現一個黑客獲得WebWorkers在擴展的背景頁:

if(typeof(Worker) == 'undefined') 
{ 
    var chromewin = win_util.getMostRecentBrowserWindow(); 
    var Worker  = chromewin.Worker; 
} 
var worker  = new Worker(data.url('path/to/script.js')); 

通過訪問主窗口的window對象,你可以拉Worker類到當前範圍。這解決了所有令人討厭的Page.Worker變通辦法垃圾,似乎工作得很好。

相關問題