与Firefox附加脚本和内容脚本的并发性

时间:2012-02-09 18:55:07

标签: firefox-addon firefox-addon-sdk

当我使用Add-on SDK编写Firefox附加组件时,我注意到附加代码和内容脚本代码阻止了彼此的执行。此外,附加代码似乎甚至阻止了与其他Firefox窗口(不仅仅是标签)的交互。

Firefox附加组件的并发/流程模型是什么?

是否可以在没有合作多线程(la-timers)的情况下同时运行附加代码和内容脚本代码?

加载了多少次加载代码?每个窗口一次?每个标签一次?一旦吗

documentation州:

  

Mozilla平台正朝着它所使用的模型发展   单独的进程以显示UI,处理Web内容和执行   加载项。主要的附加代码将在附加过程中运行并且将会   无法直接访问任何网络内容。

所以我希望将来它们确实是不会相互干扰的独立过程,但现在似乎并非如此。


更新

我尝试过使用附加代码中的页面工作程序,但不幸的是,它仍会阻止内容脚本(以及所有其他javascript)。我也尝试在页面工作者中使用Web worker,但在调用web worker的postMessage函数时出现以下错误。

  

TypeError:worker.postMessage不是函数

我还尝试在page-worker中创建iframe,然后在iframe中创建一个web worker,但遗憾的是我无法使用page-worker中的window.addEventListener。我收到以下错误:

  

TypeError:window.addEventMessage不是函数

最后,我尝试将脚本(通过脚本元素)注入页面工作者页面,以创建一个似乎有效的Web工作者。不幸的是,我无法与此Web工作者通信,因为我只能通过document.defaultView.postMessage向它发送消息。

哦,我正在编织缠结的网...

content-script - >附加组件 - > page-worker - > 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!' });
        });
    }
});

数据/ content.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 });

2 个答案:

答案 0 :(得分:6)

消息传递系统的设计考虑了多进程环境。然而,这种环境并没有出现,看起来它也不会在不久的将来发生。所以你真正拥有的是在主线程(UI线程)上的相同进程中运行的附加组件和内容脚本。这意味着它们中只有一个一次运行,因为您已经注意到没有并发性。

  

是否可以在没有合作多线程(la-timers)的情况下同时运行附加代码和内容脚本代码?

是的,您是use web workers(尽管名称相似,但与page-worker模块无关)。对于昂贵的操作,这通常是值得推荐的 - 您不希望加载项在执行某些操作时停止响应消息。不幸的是,Add-on SDK没有正确公开Web worker,所以我不得不使用解决方法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"];
  

加载了多少次加载代码?每个窗口一次?每个标签一次?一旦?

如果您询问附加代码:它只加载一次并且只要加载项处于活动状态就会保留。对于内容脚本,每个注入脚本的文档都有一个单独的实例。

答案 1 :(得分: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解决方法垃圾问题,似乎工作得很好。