Параллельность с дополнительным скриптом Firefox и скриптом контента - PullRequest
3 голосов
/ 09 февраля 2012

Когда я писал надстройку Firefox, используя Add-on SDK , я заметил, что код надстройки и код сценария содержимого блокируют выполнение друг друга.Более того, код надстройки, кажется, даже блокирует взаимодействие с другими окнами Firefox (не только с вкладками).

Что такое модель параллелизма / процесса надстроек Firefox?

Можно ли запускать код дополнения и код сценария контента одновременно без совместной многопоточности (по таймеру)?

Сколько раз это дополнениекод загружен?Один раз за окно?Один раз за вкладку?Однажды?

Документация гласит:

Платформа Mozilla движется к модели, в которой используются отдельные процессы для отображения пользовательского интерфейса.веб-контент и выполнять дополнения.Основной код надстройки будет выполняться в процессе надстройки и не будет иметь прямого доступа к любому веб-контенту.

Поэтому я надеюсь, что в будущем это действительно отдельные процессы, которые не будутмешать друг другу, но сейчас это, похоже, не так.


Обновление:

Я пытался использовать страницу работника издополнительный код, но, к сожалению, он по-прежнему блокирует скрипт контента (как и все другие JavaScript).Я также пытался использовать веб-работника в Page-работнике, но я получаю следующую ошибку при вызове функции postMessage веб-работника.

TypeError: worker.postMessage не является функцией

Я также пытался создать iframe на странице-работнике, а затем создать веб-работника в iframe, но, к сожалению, я не могу использовать window.addEventListener из page-worker.Я получаю следующую ошибку:

TypeError: window.addEventMessage не является функцией

Наконец, я попытался внедрить скрипт (через элемент script) в рабочий листстраница для создания веб-работника, который, кажется, работает.К сожалению, я не могу общаться с этим веб-работником, потому что я могу только отправлять ему сообщения через document.defaultView.postMessage.

О переплетенных сетях, которые я ткаю ...

content-script -> дополнение -> page-worker -> 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 });

Ответы [ 2 ]

6 голосов
/ 10 февраля 2012

Система обмена сообщениями была разработана с учетом многопроцессорной среды.Тем не менее, эта среда не возникла, и похоже, что это не произойдет в ближайшем будущем.Так что у вас действительно есть и надстройка, и скрипт контента, работающие в одном и том же процессе в главном потоке (потоке пользовательского интерфейса).И это означает, что одновременно работает только один из них, как вы уже заметили, параллелизма нет.

Возможно ли одновременно запускать дополнительный код и код сценария содержимого без совместной многопоточности (а-ля таймеры)?

Да, вы используете веб-работников (которые не имеют ничего общего с модулем page-worker, несмотря на похожее имя).Это обычно рекомендуется для дорогостоящих операций - вы не хотите, чтобы ваше дополнение перестало отвечать на сообщения, пока оно что-то делает.К сожалению, SDK надстройки не предоставляет должным образом веб-работникам, поэтому мне пришлось воспользоваться предложенным обходным путем здесь :

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

Сколько раз загружается код дополнения?Один раз за окно?Один раз за вкладку?Один раз?

Если вы спрашиваете о коде надстройки: он загружается только один раз и остается в течение всего времени, пока надстройка активна.Что касается скриптов содержимого, то для каждого документа есть отдельный экземпляр, в который вводится скрипт.

0 голосов
/ 24 марта 2014

Я нашел хак для получения 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 обходные пути и, похоже, работает довольно хорошо.

...