const Ci = Components.interfaces; function getWindowId(window) { return window.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils) .outerWindowID; } function getParentWindowId(window) { return getWindowId(window.parent); } function loadListener(event) { let document = event.target; let window = document.defaultView; let url = document.documentURI; let windowId = getWindowId(window); let parentWindowId = getParentWindowId(window); sendAsyncMessage("Extension:DOMContentLoaded", {windowId, parentWindowId, url}); } addEventListener("DOMContentLoaded", loadListener); addMessageListener("Extension:DisableWebNavigation", () => { removeEventListener("DOMContentLoaded", loadListener); }); var WebProgressListener = { init: function() { let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebProgress); webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW | Ci.nsIWebProgress.NOTIFY_LOCATION); }, uninit() { if (!docShell) { return; } let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebProgress); webProgress.removeProgressListener(this); }, onStateChange: function onStateChange(webProgress, request, stateFlags, status) { let data = { requestURL: request.QueryInterface(Ci.nsIChannel).URI.spec, windowId: webProgress.DOMWindowID, parentWindowId: getParentWindowId(webProgress.DOMWindow), status, stateFlags, }; sendAsyncMessage("Extension:StateChange", data); if (webProgress.DOMWindow.top != webProgress.DOMWindow) { let webNav = webProgress.QueryInterface(Ci.nsIWebNavigation); if (!webNav.canGoBack) { // For some reason we don't fire onLocationChange for the // initial navigation of a sub-frame. So we need to simulate // it here. let data = { location: request.QueryInterface(Ci.nsIChannel).URI.spec, windowId: webProgress.DOMWindowID, parentWindowId: getParentWindowId(webProgress.DOMWindow), flags: 0, }; sendAsyncMessage("Extension:LocationChange", data); } } }, onLocationChange: function onLocationChange(webProgress, request, locationURI, flags) { let data = { location: locationURI ? locationURI.spec : "", windowId: webProgress.DOMWindowID, parentWindowId: getParentWindowId(webProgress.DOMWindow), flags, }; sendAsyncMessage("Extension:LocationChange", data); }, QueryInterface: function QueryInterface(aIID) { if (aIID.equals(Ci.nsIWebProgressListener) || aIID.equals(Ci.nsISupportsWeakReference) || aIID.equals(Ci.nsISupports)) { return this; } throw Components.results.NS_ERROR_NO_INTERFACE; } }; var disabled = false; WebProgressListener.init(); addEventListener("unload", () => { if (!disabled) { WebProgressListener.uninit(); } }); addMessageListener("Extension:DisableWebNavigation", () => { disabled = true; WebProgressListener.uninit(); });