Определить запросы, возникающие в скрытом окне Windows (или в одном из его фреймов)

Какие прослушиватели событий я могу использовать для идентификации запросов, происходящих из hiddenDOMWindow (или встроенного в него iframe) в аддоне Firefox? Мне нужно сделать это ДО того, как запрос будет отправлен, например, в событии "http-on-modify-request".

Что я пробовал:

  • зарегистрироваться для глобального "http-on-modify-request"; но я не могу отличить исходное окно
  • добавить слушателя в скрытое окно самого окна; но я не могу найти ни одного события до загрузки
  • добавить слушателя к hiddenDOMWindow.document; нет события перед загрузкой
  • добавить слушателя в созданный hiddenDOMWindow.document.iframe; нет события перед загрузкой

1 ответ

Решение

Во-первых, вам нужно получить DOMWindow из nsIChannel:

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 блоки.

Кроме того, не забудьте удалить наблюдателя снова в какой-то момент, который я пропустил.;)

И, наконец, вот некоторый код, который на самом деле проверяет это (я запустил все это как Scratchpad на вкладке about:newtab, у которой, как и надстройки, есть привилегии 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();
Другие вопросы по тегам