如何在Fennec扩展中驯服多个事件侦听器?

时间:2011-09-10 17:13:43

标签: mobile firefox-addon fennec

我正在尝试为Firefox Mobile编写一个无重启的插件,用于将内容插入特定的网页。这一切似乎都工作正常,直到我尝试禁用然后重新启用加载项,此时我得到多个页面加载事件的响应,我无法想出一种方法来解决它们。

由于Fennec使用Electrolysis多进程平台,我知道我需要将代码拆分为chrome和内容脚本。我的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,我无法区分哪个应该处理该事件。更糟糕的是,一些eventListeners是活动的,但是不通过我的LOG函数提供调试信息,如果我第二次禁用扩展,则不会删除所有这些信息。

我确实想要观看所有浏览器标签,包括任何新标签,但我只希望我的扩展程序在触发它的页面上插入内容,每页加载一次。我尝试了以下但没有成功:

  • 调用e.stopPropagation()以停止将事件传递给其他侦听器。没效果。
  • 调用e.preventDefault()并测试e.defaultPrevented以查看是否已处理该事件。它永远不会。
  • 测试if(this === content.document)以查看eventListener是否已由其自己的页面内容触发。不起作用,因为我得到了多个“真实”的回复。
  • 使eventListener捕获。没效果。
  • 使用load事件而不是DOMContentLoaded。

我无法设置共享变量来表示事件已经在电解过程中处理,不同的eventListeners将在不同的上下文中执行。此外,我无法区分加载同一页面的多个选项卡和多次检测到一个页面加载。我可以通过IPC消息传递回chrome bootstrap脚本来做到这一点,但我不知道如何将响应发送回正确的浏览器选项卡。

有什么想法吗?这是Firefox的错误,还是我在代码中做了些蠢事?我正在使用Fennec Desktop v4进行开发,并将Fennec Android v6用于生产。

0 个答案:

没有答案
相关问题