首先,您需要从nsIChannel 中获取DOMWindow:
function getDOMWindowFromChannel(ch) {
var wp;
try {
if (ch.loadGroup && ch.loadGroup.groupObserver) {
wp = ch.loadGroup.groupObserver.
QueryInterface(Ci.nsIWebProgress);
}
} catch (ex) {}
try {
if (!wp) {
wp = ch.notificationCallbacks.
getInterface(Ci.nsIWebProgress);
}
}
catch (ex) {}
try {
if (wp) {
return wp.DOMWindow || null;
}
}
catch (ex) {}
return null;
}
现在你有了DOMWindow,你需要找到那个DOMWindow的顶层窗口,这不是很直观:
function getToplevelWindow(win) {
try {
return win.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShell).
treeOwner.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIXULWindow).
docShell.
contentViewer.DOMDocument.defaultView;
}
catch (ex) {
// Likely already a top-level window.
return win;
}
}
现在,让我们制作和安装观察者,把所有东西放在一起:
function observe(channel, topic, data) {
if (!(channel instanceof Ci.nsIChannel)) {
return;
}
var win = getDOMWindowFromChannel(channel);
if (!win) {
return;
}
var topWin = getToplevelWindow(win);
if (topWin.location.href.indexOf("chrome://browser/content/hiddenWindow") != 0) {
return;
}
// do stuff, e.g.
console.log(topWin.location.href);
}
Services.obs.addObserver(observe, "http-on-modify-request", false);
需要注意的是,并不是所有的请求都是nsIChannel,也不是所有的nsIChannel实际上都有一个DOMWindow或真正的loadGroup相关联(例如后台请求),因此所有这些try catch块。
另外,不要忘记在某个时候再次删除观察者,我跳过了。 ;)
最后,这里是一些实际测试的代码(我在 about:newtab 选项卡上将整个事情作为 Scratchpad 运行,它恰好具有 chrome 权限,就像附加组件一样):
var hw = Services.appShell.hiddenDOMWindow;
var iframe = hw.document.createElement("iframe");
hw.document.documentElement.appendChild(iframe);
var r = iframe.contentWindow.XMLHttpRequest();
r.open("GET", "http://example.org/");
r.send();