Firefox 扩展:响应 parent 中观察到的 http-on-modify-request,并向负责加载的 child 框架发送消息
Firefox Extension: responding to an http-on-modify-request observed in the parent with a message to the child frame responsible for the load
我正在尝试增强现有的 Firefox 扩展,它依赖于 nsIContentPolicy
来检测和中止某些网络负载(以阻止由此产生的 UI 操作,即标签导航)。然后在内部处理加载该资源。在极少数情况下,只有在处理完负载后,才发现我们根本不应该中断负载,因此我们将其标记为忽略并 re-start 它。
在 e10s/multi-process 下,这意味着 parent(内容策略为 运行)必须向 child(处理 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 太复杂了。但它有效;它在 parent 中生成一些 object,我可以调用 .sendAsyncMessage()
,然后我的 frame/child 脚本中的 addMessageListener()
处理程序接收它,并执行什么它需要做。
我想从 nsIContentPolicy
切换到 http-on-modify-request
,因为它提供了更多信息以便更早地做出更好的决定(阻止并处理此负载?)。在那个观察者里面我可以做:
var browser = httpChannel
.notificationCallbacks.getInterface(Ci.nsILoadContext)
.topFrameElement;
它给了我一个 object,它有一个 .messageManager
,它是 某种 的消息管理器,它有一个 .sendAsyncMessage()
方法.但是当我使用 .sendAsyncMessage()
时,消息消失了,child.
永远不会观察到
上下文:https://github.com/greasemonkey/greasemonkey/issues/2280
这在原则上应该可行,尽管 docshell 树遍历在 e10s 和非 e10s 中可能做不同的事情,所以你必须小心。在 e10s rootTreeItem
-> nsIContentFrameMessageManager
应该给你相当于一个框架脚本的 MM 而 topFrameElement.frameLoader.messageManager
应该给你 <browser>
的 MM,这几乎是父端与之对应。
潜在的混淆来源:
- e10s 开启与关闭
- 进程 MM 与框架 MM 层次结构
- 在错误的帧中收听消息(在所有帧中注册可能有助于调试)
这是我用来查找内容消息管理器的功能:
function contentMMFromContentWindow_Method2(aContentWindow) {
if (!gCFMM) {
gCFMM = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
}
return gCFMM;
}
所以也许获取触发该请求的内容window,然后使用此功能。
我正在尝试增强现有的 Firefox 扩展,它依赖于 nsIContentPolicy
来检测和中止某些网络负载(以阻止由此产生的 UI 操作,即标签导航)。然后在内部处理加载该资源。在极少数情况下,只有在处理完负载后,才发现我们根本不应该中断负载,因此我们将其标记为忽略并 re-start 它。
在 e10s/multi-process 下,这意味着 parent(内容策略为 运行)必须向 child(处理 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 太复杂了。但它有效;它在 parent 中生成一些 object,我可以调用 .sendAsyncMessage()
,然后我的 frame/child 脚本中的 addMessageListener()
处理程序接收它,并执行什么它需要做。
我想从 nsIContentPolicy
切换到 http-on-modify-request
,因为它提供了更多信息以便更早地做出更好的决定(阻止并处理此负载?)。在那个观察者里面我可以做:
var browser = httpChannel
.notificationCallbacks.getInterface(Ci.nsILoadContext)
.topFrameElement;
它给了我一个 object,它有一个 .messageManager
,它是 某种 的消息管理器,它有一个 .sendAsyncMessage()
方法.但是当我使用 .sendAsyncMessage()
时,消息消失了,child.
上下文:https://github.com/greasemonkey/greasemonkey/issues/2280
这在原则上应该可行,尽管 docshell 树遍历在 e10s 和非 e10s 中可能做不同的事情,所以你必须小心。在 e10s rootTreeItem
-> nsIContentFrameMessageManager
应该给你相当于一个框架脚本的 MM 而 topFrameElement.frameLoader.messageManager
应该给你 <browser>
的 MM,这几乎是父端与之对应。
潜在的混淆来源:
- e10s 开启与关闭
- 进程 MM 与框架 MM 层次结构
- 在错误的帧中收听消息(在所有帧中注册可能有助于调试)
这是我用来查找内容消息管理器的功能:
function contentMMFromContentWindow_Method2(aContentWindow) {
if (!gCFMM) {
gCFMM = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
}
return gCFMM;
}
所以也许获取触发该请求的内容window,然后使用此功能。