Я пытаюсь написать перезапускаемое дополнение для Firefox Mobile, которое будет вставлять контент на определенные веб-страницы.Кажется, все работает нормально, пока я не попытаюсь отключить, а затем снова включить надстройку, после чего я получаю несколько ответов на событие загрузки страницы, и я не могу найти способ разобраться в них.
Поскольку Fennec использует многопроцессорную платформу Electrolysis, я знаю, что мне нужно разделить мой код на скрипты chrome и content.Мой bootstrap.js выглядит примерно так (обрезано для ясности):
function startup(data, reason) {
mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIChromeFrameMessageManager);
mm.loadFrameScript(getResourceURISpec('content.js'), true);
}
function shutdown(data, reason) {
let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIChromeFrameMessageManager);
mm.sendAsyncMessage("GeoMapEnh:Disable", {reason: reason});
}
function install(data, reason) {}
function uninstall(data, reason) {}
По сути, bootstrap.js просто запускает скрипт содержимого и отправляет сообщение, чтобы он очистился при завершении работы.Content.js устанавливает eventListener для отслеживания загрузки страниц, который выглядит примерно так:
addMessageListener("GeoMapEnh:Disable", disableScript);
addEventListener("DOMContentLoaded", loadHandler, false );
function loadHandler(e) {
LOG("Page loaded");
// Do something cool with the web page.
}
function disableScript(aMessage) {
if (aMessage.name != "GeoMapEnh:Disable") {
return;
}
LOG("Disabling content script: " + aMessage.json.reason);
try {
removeEventListener("DOMContentLoaded", loadHandler, false );
removeMessageListener("GeoMapEnh:Disable", disableScript);
} catch(e) {
LOG("Remove failed: " + e);
}
}
function LOG(msg) {
dump(msg + "\n");
var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
consoleService.logStringMessage(msg);
}
Когда я впервые запускаю расширение, все работает нормально.Экземпляр content.js выполняется для каждой вкладки браузера (и любых новых вкладок, которые я открываю), и мой eventListener обнаруживает загрузки страницы, которые он должен, через событие DOMContentLoaded.Когда я отключаю расширение, все кажется, что все в порядке: загрузка страницы перестает быть обнаруженной.
Когда я повторно включаю расширение, все идет не так.Я все еще получаю экземпляр content.js, выполняемый для каждой открытой вкладки, но теперь, если я открываю новые вкладки, DOMContentLoaded запускает несколько событий EventListeners, и я не могу отличить, какая из них должна обрабатывать событие.Хуже того, некоторые из EventListener активны, но не предоставляют отладочную информацию через мою функцию LOG, и не все они удаляются, если я отключаю расширение во второй раз.
Я хочу посмотреть всевкладки браузера, включая любые новые, но я хочу, чтобы мое расширение только вставляло контент на страницу, которая его вызывает, и только один раз на загрузку страницы.Я безуспешно пробовал следующее:
- Вызов e.stopPropagation (), чтобы остановить передачу события другим слушателям.Без эффекта.
- Вызов e.preventDefault () и тестирование e.defaultPrevented, чтобы увидеть, было ли событие уже обработано.У него никогда не было.
- Проверка, если (this === content.document), чтобы увидеть, был ли EventListener запущен собственным содержимым страницы.Не работает, так как я получаю несколько «истинных» ответов.
- Создание захвата события EventListener.Без эффекта.
- Использование события загрузки вместо DOMContentLoaded.
Я не могу установить общую переменную, чтобы сказать, что событие было обработано, как в Electrolysis, различные EventListeners будутвыполнение в разных контекстах.Кроме того, я не смогу различить несколько вкладок, загружающих одну и ту же страницу, и одна загрузка страницы, обнаруженная несколько раз.Я мог бы сделать это с помощью сообщения IPC, возвращающегося обратно в скрипт начальной загрузки Chrome, но я тогда не знал бы, как вернуть ответ на нужную вкладку браузера.
Есть идеи?Это ошибка Firefox, или я делаю что-то глупое в своем коде?Я использую Fennec Desktop v4 для разработки и буду ориентироваться на Fennec Android v6 для разработки.