在使用 Firefox 的 Add-on SDK 编写插件时,我注意到插件代码和内容脚本代码会互相阻塞执行。此外,插件代码似乎还会阻塞与其他 Firefox 窗口(而不仅仅是标签页)的交互。
Firefox 插件的并发/进程模型是什么?
是否可能在没有协作多线程(如定时器)的情况下同时运行插件代码和内容脚本代码?
插件代码被加载了几次?每个窗口一次?每个标签页一次?只有一次?
文档 中说:
“Mozilla 平台正在向一种模型过渡,其中它使用独立进程来显示 UI、处理 Web 内容和执行插件。主要插件代码将在插件进程中运行,并且不会直接访问任何 Web 内容。”
所以我希望未来它们确实是不会干扰彼此的独立进程,但现在似乎不是这样。
更新:
我尝试使用来自插件代码的页面工作者(page-worker),但不幸的是它仍会阻塞内容脚本(以及所有其他 JavaScript)。我还尝试使用页面工作者中的 Web Worker,在调用 Web Worker 的 postMessage 函数时遇到了以下错误:
“TypeError:worker.postMessage 不是一个函数”
我还尝试在页面工作者中创建一个 iframe,然后在 iframe 中创建一个 Web Worker,但不幸的是,我不能从页面工作者中使用 window.addEventListener。我得到了以下错误:
“TypeError:window.addEventMessage 不是一个函数”
最后,我尝试通过将脚本(通过脚本元素)注入到页面工作者页面中来创建一个 Web Worker,这似乎可以工作。不幸的是,我无法与此 Web Worker 通信,因为我只能通过 document.defaultView.postMessage 向其发送消息。
噢,我编织的错综复杂的网络...
内容脚本 -> 插件 -> 页面工作者 -> iframe -> Web Worker -> 我的代码
这里有一个简单的例子: package.json
“Mozilla 平台正在向一种模型过渡,其中它使用独立进程来显示 UI、处理 Web 内容和执行插件。主要插件代码将在插件进程中运行,并且不会直接访问任何 Web 内容。”
所以我希望未来它们确实是不会干扰彼此的独立进程,但现在似乎不是这样。
更新:
我尝试使用来自插件代码的页面工作者(page-worker),但不幸的是它仍会阻塞内容脚本(以及所有其他 JavaScript)。我还尝试使用页面工作者中的 Web Worker,在调用 Web Worker 的 postMessage 函数时遇到了以下错误:
“TypeError:worker.postMessage 不是一个函数”
我还尝试在页面工作者中创建一个 iframe,然后在 iframe 中创建一个 Web Worker,但不幸的是,我不能从页面工作者中使用 window.addEventListener。我得到了以下错误:
“TypeError:window.addEventMessage 不是一个函数”
最后,我尝试通过将脚本(通过脚本元素)注入到页面工作者页面中来创建一个 Web Worker,这似乎可以工作。不幸的是,我无法与此 Web Worker 通信,因为我只能通过 document.defaultView.postMessage 向其发送消息。
噢,我编织的错综复杂的网络...
内容脚本 -> 插件 -> 页面工作者 -> iframe -> Web Worker -> 我的代码
这里有一个简单的例子: 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!' });
});
}
});
data/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 });
postMessage
接受,当你试图传递一个没有JSON表示的对象时,就会出现这个消息。但是,可能存在作用域问题(你从哪个JS模块获取了Worker
,它有自己的作用域和Object
、Array
类),因此你确实需要手动使用JSON序列化。 - Wladimir Palant