Firefox扩展:响应在父级中观察到的http-on-modify-request,并向负责加载的子框架发送消息

时间:2016-02-11 16:19:18

标签: firefox firefox-addon e10s

我正在尝试增强现有的Firefox扩展,该扩展依赖于nsIContentPolicy来检测并中止某些网络加载(为了阻止生成的UI操作,即标签导航)。然后处理内部加载该资源。在极少数情况下,只有在处理完负载之后,我们才能完全中断负载,因此我们将其标记为忽略并重新启动它。

在e10s / multi-process下,这意味着父级(内容策略正在运行的位置)必须向子级发送消息(处理内容的UI)以重新启动加载。今天,这完成了:

function findMessageManager(aContext) {
  // With e10s off, context is a <browser> with a direct reference to
  // the docshell loaded therein.
  var docShell = aContext && aContext.docShell;

  if (!docShell) {
    // But with e10s on, context is a content window and we have to work hard
    // to find the docshell, from which we can find the message manager.
    docShell = aContext
        .QueryInterface(Ci.nsIInterfaceRequestor)
        .getInterface(Ci.nsIWebNavigation)
        .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem;
  }

  try {
    return docShell
        .QueryInterface(Ci.nsIInterfaceRequestor)
        .getInterface(Ci.nsIContentFrameMessageManager);
  } catch (e) {
    return null;
  }
};

哪个是疯狂的复杂,​​因为e10s是疯狂的复杂。但它有效;它在父级中生成一些对象,我可以在其上调用.sendAsyncMessage(),然后我的frame / child脚本中的addMessageListener()处理程序接收它,并完成它需要做的事情。

我希望从nsIContentPolicy切换到http-on-modify-request,因为它提供了更多信息,可以更早地做出更好的决定(阻止和处理此负载?)。在那个观察者里面我能做到:

var browser = httpChannel
    .notificationCallbacks.getInterface(Ci.nsILoadContext)
    .topFrameElement;

这给了我一个对象,其中.messageManager某种的消息管理器,并且有一个.sendAsyncMessage()方法。但是,当我使用.sendAsyncMessage()时,消息消失,孩子永远不会被观察到。

背景:https://github.com/greasemonkey/greasemonkey/issues/2280

2 个答案:

答案 0 :(得分:2)

这应该原则上有效,尽管docshell树遍历可能在e10s和非e10s中做不同的事情,所以你必须要小心。在e10s rootTreeItem - &gt; nsIContentFrameMessageManager应该为您提供相当于框架脚本的MM,而topFrameElement.frameLoader.messageManager应该为您提供<browser>的MM,这几乎是与其对应的父级对象。

潜在的混淆来源:

  • e10s on vs. off
  • 处理MM与帧MM层次结构
  • 在错误的帧中侦听消息(在所有帧中注册可能有助于调试)

答案 1 :(得分:-1)

这是我用来查找内容消息管理器的功能:

function contentMMFromContentWindow_Method2(aContentWindow) {
    if (!gCFMM) {
        gCFMM = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIDocShell)
                              .QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIContentFrameMessageManager);
    }
    return gCFMM;

}

因此,可能会获取触发该请求的内容窗口,然后使用此功能。