3

我正在尝试增强现有的 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(),然后addMessageListener()我的框架/子脚本中的处理程序接收它,并执行它需要做的事情。


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

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

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


上下文:https ://github.com/greasemonkey/greasemonkey/issues/2280

4

2 回答 2

2

这原则上应该有效,尽管 docshell 树遍历在 e10 和非 e10 中可能会做不同的事情,所以你必须小心。在 e10s rootTreeItem->nsIContentFrameMessageManager中应该给你相当于框架脚本的 MM,并且topFrameElement.frameLoader.messageManager应该给你<browser>的 MM,这几乎是它的父方对应物。

潜在的混淆来源:

  • e10s 开启与关闭
  • 进程 MM 与框架 MM 层次结构
  • 在错误的帧中侦听消息(在所有帧中注册可能有助于调试目的)
于 2016-02-11T21:11:59.197 回答
-1

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

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

}

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

于 2016-02-12T04:16:58.923 回答