Определить запросы, возникающие в скрытом окне 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();