与Firefox附加脚本和内容脚本并发 [英] Concurrency with Firefox add-on script and content script

查看:124
本文介绍了与Firefox附加脚本和内容脚本并发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用附加SDK ,我注意到附加代码和内容脚本代码阻止了彼此的执行。此外,附加代码似乎甚至阻止与其他Firefox窗口(不只是选项卡)的交互。



什么是Firefox的并发/进程模型add-ons?

是否可以同时运行附加代码和内容脚本代码,而不需要合作多线程(la timers)?

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



documentation 指出:


Mozilla平台正在朝着一种模式,在这种模式下,它使用
单独的进程来显示UI,处理web内容,并执行
附加组件。主要的附加代码将在附加过程中运行,
不能直接访问任何web内容。



<所以我希望将来他们确实是一个独立的进程,不会互相干扰,但现在看来并不是这样。






更新:

我已经尝试使用附加代码中的页面工作者,但不幸的是,仍然阻止内容脚本(以及所有其他的JavaScript)。我也试着在页面工作者中使用一个web worker,但是当调用web worker的postMessage函数的时候,我得到了下面的错误。


$ b


TypeError :worker.postMessage不是一个函数

我也尝试在page-worker中创建一个iframe,然后在iframe,但不幸的是,我不能使用page-worker的window.addEventListener。我得到以下错误:
$ b


TypeError:window.addEventMessage不是函数

最后,我尝试将脚本(通过脚本元素)注入到页面工作器页面中,以创建似乎工作的web工作器。不幸的是,我不能与这个网络工作者沟通,因为我只能通过document.defaultView.postMessage发送消息给它。



哦,我正在编织纠结的网络...



content-script - > add-on - > page-worker - > iframe - > web worker - >我的代码



我已经包含一个简单的例子:

package.json


$ b $ $ name

$ b $ ,
version:0.1,
fullName:My Test Extension,
homepage:http://example.com,
id:jid1-FmgBxScAABzB2g,
description:我的测试扩展
}



lib / main.js


$ b

  var data = require(self)。data; 
var pageMod = require(page-mod);
$ b $ pageMod.PageMod({
include:[http:// *,https:// *],
contentScriptWhen:start,
contentScriptFile:[data.url(content.js)],
onAttach:function(worker){
worker.port.on(message,function(data){
//以繁忙循环模拟一个昂贵的操作
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);
});

//在附加代码中调用非常昂贵的操作
self.port.emit(message,{time:10000});


解决方案

考虑到环境。但是,这种环境并没有出现,看起来也不会在不久的将来发生。所以你真正拥有的是在主线程(UI线程)上的同一进程中运行的加载项和内容脚本。这就意味着一次只能运行其中的一个,因为你已经注意到没有并发。


是否可以运行附加代码和内容脚本代码并发,没有合作多线程(定时器)?

是的,你使用网络工作者(与 page-worker 模块,尽管类似的名字)。对于昂贵的操作,这通常是值得推荐的 - 你不希望你的插件在做某事的时候停止对消息的响应。不幸的是,附加SDK没有正确公开Web工作,所以我不得不使用建议的 here $ b

  worker.port.on(message,function(message){
//从JavaScript模块获取工作类并立即卸载它
var {Cu} = require(chrome);
var {Worker} = Cu.import(data.url(dummy.jsm));
Cu.unload(data.url(dummy.jsm));

$ 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];




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


如果您询问附加代码,只需加载一次,只要加载项活跃。至于内容脚本,注入脚本的每个文档都有一个单独的实例。


As I was writing a Firefox add-on using the Add-on SDK, I noticed that the add-on code and the content script code block the execution of each other. Furthermore, the add-on code seems even to block the interaction with other Firefox windows (not just tabs).

What is the concurrency/process model of Firefox add-ons?

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

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

The documentation states:

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.

So I hope that in the future that they are indeed separate processes that will not interfere with each other, but that doesn't seem to be the case now.


Update:

I have tried using a page-worker from the add-on code, but unfortunately that still blocks the content script (as well as all other javascript). I also tried using a web worker in the page-worker, but I get the following error when calling the web worker's postMessage function.

TypeError: worker.postMessage is not a function

I also tried creating an iframe in the page-worker and then creating a web worker in the iframe, but unfortunately I cannot use window.addEventListener from the page-worker. I get the following error:

TypeError: window.addEventMessage is not a function

Finally, I tried to inject script (via script element) into the page-worker page to create a web worker which does seem to work. Unfortunately, I cannot communicate with this web worker because I can only send messages to it via document.defaultView.postMessage.

Oh the tangled webs I am weaving...

content-script -> add-on -> page-worker -> iframe -> web worker -> my code


I have included a simple example:

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 });

解决方案

The messaging system has been designed with a multi-process environment in mind. However, this environment didn't emerge and it looks like it won't happen in near future either. So what you really have is both the add-on and the content script running in the same process on the main thread (UI thread). And that means that only one of them is running at a time, as you already noticed there is no concurrency.

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

Yes, you use web workers (that have nothing to do with the page-worker module despite a similar name). This would be generally recommendable for expensive operations - you don't want your add-on to stop responding to messages while it is doing something. Unfortunately, the Add-on SDK doesn't expose web workers properly so I had to use the work-around suggested 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);
});

The JavaScript module data/dummy.jsm only contains a single line:

var EXPORTED_SYMBOLS=["Worker"];

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

If you are asking about add-on code: it is loaded only once and stays around as long as the add-on is active. As to content scripts, there is a separate instance for each document where the script is injected.

这篇关于与Firefox附加脚本和内容脚本并发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆