关于 javascript:如何识别来自`hiddenDOMWindow` 的请求?

How to identify requests originating from the `hiddenDOMWindow`?

我可以使用哪些事件侦听器来识别来自 firefox 插件中 hiddenDOMWindow(或其中的 iframe)的请求?例如,我需要在发送请求之前执行此操作,例如在"http-on-modify-request"事件中。

我尝试过的:

  • 注册全局"http-on-modify-request";但我无法区分源窗口
  • 向 hiddenDOMWindow 本身添加侦听器;但我找不到任何加载前事件
  • 给 hiddenDOMWindow.document 添加监听器;没有加载前事件
  • 为创建的 hiddenDOMWindow.document.iframe 添加监听器;没有加载前事件

首先,你需要从 nsIChannel:

得到一个 DOMWindow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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的顶级窗口,这不是很直观:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
    }
}

现在,让我们制作并安装观察者,把所有的东西放在一起:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 权限,就像附加组件一样):

1
2
3
4
5
6
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();