--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -27,18 +27,18 @@ XPCOMUtils.defineLazyModuleGetter(this,
GMPInstallManager:false, LightweightThemeManager:false, Log:false,
LoginManagerParent:false, NewTabUtils:false, PageThumbs:false,
PluralForm:false, Preferences:false, PrivateBrowsingUtils:false,
ProcessHangMonitor:false, PromiseUtils:false, ReaderMode:false,
ReaderParent:false, RecentWindow:false, SessionStore:false,
ShortcutUtils:false, SimpleServiceDiscovery:false, SitePermissions:false,
Social:false, TabCrashHandler:false, Task:false, TelemetryStopwatch:false,
Translation:false, UITour:false, UpdateUtils:false, Weave:false,
- fxAccounts:false, gDevTools:false, gDevToolsBrowser:false, webrtcUI:false,
- FullZoomUI:false
+ WebNavigationFrames: false, fxAccounts:false, gDevTools:false,
+ gDevToolsBrowser:false, webrtcUI:false, FullZoomUI:false
*/
/**
* IF YOU ADD OR REMOVE FROM THIS LIST, PLEASE UPDATE THE LIST ABOVE AS WELL.
* XXX Bug 1325373 is for making eslint detect these automatically.
*/
[
["AboutHome", "resource:///modules/AboutHome.jsm"],
@@ -75,16 +75,17 @@ XPCOMUtils.defineLazyModuleGetter(this,
["Social", "resource:///modules/Social.jsm"],
["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
["Task", "resource://gre/modules/Task.jsm"],
["TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm"],
["Translation", "resource:///modules/translation/Translation.jsm"],
["UITour", "resource:///modules/UITour.jsm"],
["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"],
["Weave", "resource://services-sync/main.js"],
+ ["WebNavigationFrames", "resource://gre/modules/WebNavigationFrames.js"],
["fxAccounts", "resource://gre/modules/FxAccounts.jsm"],
["gDevTools", "resource://devtools/client/framework/gDevTools.jsm"],
["gDevToolsBrowser", "resource://devtools/client/framework/gDevTools.jsm"],
["webrtcUI", "resource:///modules/webrtcUI.jsm"],
].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource));
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
@@ -5770,19 +5771,17 @@ function handleLinkClick(event, href, li
linkNode) {
let referrerAttrValue = Services.netUtils.parseAttributePolicyString(linkNode.
getAttribute("referrerpolicy"));
if (referrerAttrValue != Ci.nsIHttpChannel.REFERRER_POLICY_UNSET) {
referrerPolicy = referrerAttrValue;
}
}
- let frameOuterWindowID = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils)
- .outerWindowID;
+ let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
urlSecurityCheck(href, doc.nodePrincipal);
let params = {
charset: doc.characterSet,
allowMixedContent: persistAllowMixedContentInChildTab,
referrerURI,
referrerPolicy,
noReferrer: BrowserUtils.linkHasNoReferrer(linkNode),
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -39,16 +39,18 @@ XPCOMUtils.defineLazyModuleGetter(this,
"resource://gre/modules/PageMetadata.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils",
"resource:///modules/PlacesUIUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "PageMenuChild", function() {
let tmp = {};
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
return new tmp.PageMenuChild();
});
+XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
+ "resource://gre/modules/WebNavigationFrames.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Feeds",
"resource:///modules/Feeds.jsm");
Cu.importGlobalProperties(["URL"]);
// TabChildGlobal
var global = this;
@@ -112,19 +114,17 @@ var handleContentContextMenu = function(
let doc = event.target.ownerDocument;
let docLocation = doc.mozDocumentURIIfNotForErrorPages;
docLocation = docLocation && docLocation.spec;
let charSet = doc.characterSet;
let baseURI = doc.baseURI;
let referrer = doc.referrer;
let referrerPolicy = doc.referrerPolicy;
- let frameOuterWindowID = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils)
- .outerWindowID;
+ let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
let loginFillInfo = LoginManagerContent.getFieldContext(event.target);
// The same-origin check will be done in nsContextMenu.openLinkInTab.
let parentAllowsMixedContent = !!docShell.mixedContentChannel;
// get referrer attribute from clicked link and parse it
// if per element referrer is enabled, the element referrer overrules
// the document wide referrer
@@ -524,19 +524,17 @@ var ClickEventHandler = {
node) {
let referrerAttrValue = Services.netUtils.parseAttributePolicyString(node.
getAttribute("referrerpolicy"));
if (referrerAttrValue !== Ci.nsIHttpChannel.REFERRER_POLICY_UNSET) {
referrerPolicy = referrerAttrValue;
}
}
- let frameOuterWindowID = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils)
- .outerWindowID;
+ let frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView);
let json = { button: event.button, shiftKey: event.shiftKey,
ctrlKey: event.ctrlKey, metaKey: event.metaKey,
altKey: event.altKey, href: null, title: null,
bookmark: false, frameOuterWindowID, referrerPolicy,
triggeringPrincipal: principal,
originAttributes: principal ? principal.originAttributes : {},
isContentWindowPrivate: PrivateBrowsingUtils.isContentWindowPrivate(ownerDoc.defaultView)};
@@ -1047,17 +1045,17 @@ var PageInfoListener = {
receiveMessage(message) {
let strings = message.data.strings;
let window;
let document;
let frameOuterWindowID = message.data.frameOuterWindowID;
// If inside frame then get the frame's window and document.
- if (frameOuterWindowID) {
+ if (frameOuterWindowID != undefined) {
window = Services.wm.getOuterWindowWithId(frameOuterWindowID);
document = window.document;
} else {
window = content.window;
document = content.document;
}
let imageElement = message.objects.imageElement;
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -10,16 +10,18 @@ Components.utils.import("resource://gre/
Components.utils.import("resource://gre/modules/LoginManagerContextMenu.jsm");
Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
"resource://gre/modules/LoginHelper.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
+ "resource://gre/modules/WebNavigationFrames.jsm");
var gContextMenuContentData = null;
function nsContextMenu(aXulMenu, aIsShift) {
this.shouldDisplay = true;
this.initMenu(aXulMenu, aIsShift);
}
@@ -664,20 +666,17 @@ nsContextMenu.prototype = {
} else {
editFlags = SpellCheckHelper.isEditable(this.target, window);
this.browser = ownerDoc.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
this.principal = ownerDoc.nodePrincipal;
- this.frameOuterWindowID = ownerDoc.defaultView
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils)
- .outerWindowID;
+ this.frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView);
}
this.onSocial = !!this.browser.getAttribute("origin");
// Check if we are in a synthetic document (stand alone image, video, etc.).
this.inSyntheticDoc = ownerDoc.mozSyntheticDocument;
this._setTargetForNodesNoChildren(editFlags, aRangeParent, aRangeOffset);
@@ -990,19 +989,17 @@ nsContextMenu.prototype = {
referrerPolicy: gContextMenuContentData.referrerPolicy,
frameOuterWindowID: gContextMenuContentData.frameOuterWindowID,
noReferrer: this.linkHasNoReferrer };
for (let p in extra) {
params[p] = extra[p];
}
if (!this.isRemote) {
- params.frameOuterWindowID = this.target.ownerGlobal
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
+ params.frameOuterWindowID = WebNavigationFrames.getFrameId(this.target.ownerGlobal);
}
// If we want to change userContextId, we must be sure that we don't
// propagate the referrer.
if ("userContextId" in params &&
params.userContextId != gContextMenuContentData.userContextId) {
params.noReferrer = true;
}
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -321,17 +321,17 @@ function openLinkIn(url, where, params)
let features = "chrome,dialog=no,all";
if (aIsPrivate) {
features += ",private";
}
const sourceWindow = (w || window);
let win;
- if (params.frameOuterWindowID && sourceWindow) {
+ if (params.frameOuterWindowID != undefined && sourceWindow) {
// Only notify it as a WebExtensions' webNavigation.onCreatedNavigationTarget
// event if it contains the expected frameOuterWindowID params.
// (e.g. we should not notify it as a onCreatedNavigationTarget if the user is
// opening a new window using the keyboard shortcut).
const sourceTabBrowser = sourceWindow.gBrowser.selectedBrowser;
let delayedStartupObserver = aSubject => {
if (aSubject == win) {
Services.obs.removeObserver(delayedStartupObserver, "browser-delayed-startup-finished");
@@ -445,17 +445,17 @@ function openLinkIn(url, where, params)
allowMixedContent: aAllowMixedContent,
noReferrer: aNoReferrer,
userContextId: aUserContextId,
originPrincipal: aPrincipal,
triggeringPrincipal: aTriggeringPrincipal,
});
targetBrowser = tabUsedForLoad.linkedBrowser;
- if (params.frameOuterWindowID && w) {
+ if (params.frameOuterWindowID != undefined && w) {
// Only notify it as a WebExtensions' webNavigation.onCreatedNavigationTarget
// event if it contains the expected frameOuterWindowID params.
// (e.g. we should not notify it as a onCreatedNavigationTarget if the user is
// opening a new tab using the keyboard shortcut).
Services.obs.notifyObservers({
wrappedJSObject: {
url,
createdTabBrowser: targetBrowser,
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -118,17 +118,16 @@ support-files =
[browser_ext_tabs_reload_bypass_cache.js]
[browser_ext_tabs_sendMessage.js]
[browser_ext_tabs_cookieStoreId.js]
[browser_ext_tabs_update.js]
[browser_ext_tabs_zoom.js]
[browser_ext_tabs_update_url.js]
[browser_ext_themes_icons.js]
[browser_ext_themes_validation.js]
-[browser_ext_topwindowid.js]
[browser_ext_url_overrides_newtab.js]
[browser_ext_url_overrides_home.js]
[browser_ext_webRequest.js]
[browser_ext_webNavigation_frameId0.js]
[browser_ext_webNavigation_getFrames.js]
[browser_ext_webNavigation_onCreatedNavigationTarget.js]
[browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js]
[browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js]
deleted file mode 100644
--- a/browser/components/extensions/test/browser/browser_ext_topwindowid.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set sts=2 sw=2 et tw=80: */
-"use strict";
-
-add_task(function* test_topwindowid_cleanup() {
- let {Frames} = Cu.import("resource://gre/modules/ExtensionManagement.jsm", {});
-
- let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
-
- let {outerWindowID, messageManager} = tab.linkedBrowser;
-
- ok(Frames.topWindowIds.has(outerWindowID), "Outer window ID is registered");
-
- let awaitDisconnect = TestUtils.topicObserved("message-manager-disconnect",
- subject => subject === messageManager);
-
- yield BrowserTestUtils.removeTab(tab);
-
- yield awaitDisconnect;
-
- ok(!Frames.topWindowIds.has(outerWindowID), "Outer window ID is no longer registered");
-});
-
--- a/toolkit/components/extensions/ExtensionManagement.jsm
+++ b/toolkit/components/extensions/ExtensionManagement.jsm
@@ -34,81 +34,16 @@ if (isParentProcess) {
var ExtensionManagement;
/*
* This file should be kept short and simple since it's loaded even
* when no extensions are running.
*/
-// Keep track of frame IDs for content windows. Mostly we can just use
-// the outer window ID as the frame ID. However, the API specifies
-// that top-level windows have a frame ID of 0. So we need to keep
-// track of which windows are top-level. This code listens to messages
-// from ExtensionContent to do that.
-var Frames = {
- // Window IDs of top-level content windows.
- topWindowIds: new Set(),
-
- init() {
- if (appinfo.processType === appinfo.PROCESS_TYPE_CONTENT) {
- return;
- }
-
- Services.mm.addMessageListener("Extension:TopWindowID", this);
- Services.mm.addMessageListener("Extension:RemoveTopWindowID", this, true);
- },
-
- isTopWindowId(windowId) {
- return this.topWindowIds.has(windowId);
- },
-
- // Convert an outer window ID to a frame ID. An outer window ID of 0
- // is invalid.
- getId(windowId) {
- if (this.isTopWindowId(windowId)) {
- return 0;
- }
- if (windowId == 0) {
- return -1;
- }
- return windowId;
- },
-
- // Convert an outer window ID for a parent window to a frame
- // ID. Outer window IDs follow the same convention that
- // |window.top.parent === window.top|. The API works differently,
- // giving a frame ID of -1 for the the parent of a top-level
- // window. This function handles the conversion.
- getParentId(parentWindowId, windowId) {
- if (parentWindowId == windowId) {
- // We have a top-level window.
- return -1;
- }
-
- // Not a top-level window. Just return the ID as normal.
- return this.getId(parentWindowId);
- },
-
- receiveMessage({name, data}) {
- switch (name) {
- case "Extension:TopWindowID":
- // FIXME: Need to handle the case where the content process
- // crashes. Right now we leak its top window IDs.
- this.topWindowIds.add(data.windowId);
- break;
-
- case "Extension:RemoveTopWindowID":
- this.topWindowIds.delete(data.windowId);
- break;
- }
- },
-};
-Frames.init();
-
var APIs = {
apis: new Map(),
register(namespace, schema, script) {
if (this.apis.has(namespace)) {
throw new Error(`API namespace already exists: ${namespace}`);
}
@@ -340,19 +275,16 @@ ExtensionManagement = {
},
startupExtension: Service.startupExtension.bind(Service),
shutdownExtension: Service.shutdownExtension.bind(Service),
registerAPI: APIs.register.bind(APIs),
unregisterAPI: APIs.unregister.bind(APIs),
- getFrameId: Frames.getId.bind(Frames),
- getParentFrameId: Frames.getParentId.bind(Frames),
-
getURLForExtension,
// exported API Level Helpers
getAddonIdForWindow,
getAPILevelForWindow,
API_LEVELS,
APIs,
--- a/toolkit/components/extensions/ext-webNavigation.js
+++ b/toolkit/components/extensions/ext-webNavigation.js
@@ -1,12 +1,10 @@
"use strict";
-XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement",
- "resource://gre/modules/ExtensionManagement.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "MatchURLFilters",
"resource://gre/modules/MatchPattern.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebNavigation",
"resource://gre/modules/WebNavigation.jsm");
const defaultTransitionTypes = {
topFrame: "link",
subFrame: "auto_subframe",
@@ -104,23 +102,23 @@ function WebNavigationEventManager(conte
url: data.url,
timeStamp: Date.now(),
};
if (eventName == "onErrorOccurred") {
data2.error = data.error;
}
- if (data.windowId) {
- data2.frameId = ExtensionManagement.getFrameId(data.windowId);
- data2.parentFrameId = ExtensionManagement.getParentFrameId(data.parentWindowId, data.windowId);
+ if (data.frameId != undefined) {
+ data2.frameId = data.frameId;
+ data2.parentFrameId = data.parentFrameId;
}
- if (data.sourceWindowId) {
- data2.sourceFrameId = ExtensionManagement.getFrameId(data.sourceWindowId);
+ if (data.sourceFrameId != undefined) {
+ data2.sourceFrameId = data.sourceFrameId;
}
// Fills in tabId typically.
Object.assign(data2, tabTracker.getBrowserData(data.browser));
if (data2.tabId < 0) {
return;
}
@@ -144,18 +142,18 @@ function WebNavigationEventManager(conte
WebNavigationEventManager.prototype = Object.create(SingletonEventManager.prototype);
function convertGetFrameResult(tabId, data) {
return {
errorOccurred: data.errorOccurred,
url: data.url,
tabId,
- frameId: ExtensionManagement.getFrameId(data.windowId),
- parentFrameId: ExtensionManagement.getParentFrameId(data.parentWindowId, data.windowId),
+ frameId: data.frameId,
+ parentFrameId: data.parentFrameId,
};
}
this.webNavigation = class extends ExtensionAPI {
getAPI(context) {
let {tabManager} = context.extension;
return {
--- a/toolkit/components/extensions/ext-webRequest.js
+++ b/toolkit/components/extensions/ext-webRequest.js
@@ -1,12 +1,10 @@
"use strict";
-XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement",
- "resource://gre/modules/ExtensionManagement.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
"resource://gre/modules/MatchPattern.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebRequest",
"resource://gre/modules/WebRequest.jsm");
// EventManager-like class specifically for WebRequest. Inherits from
// SingletonEventManager. Takes care of converting |details| parameter
// when invoking listeners.
@@ -47,18 +45,18 @@ function WebRequestEventManager(context,
requestId: data.requestId,
url: data.url,
originUrl: data.originUrl,
documentUrl: data.documentUrl,
method: data.method,
tabId: browserData.tabId,
type: data.type,
timeStamp: Date.now(),
- frameId: data.type == "main_frame" ? 0 : ExtensionManagement.getFrameId(data.windowId),
- parentFrameId: ExtensionManagement.getParentFrameId(data.parentWindowId, data.windowId),
+ frameId: data.type == "main_frame" ? 0 : data.windowId,
+ parentFrameId: data.type == "main_frame" ? -1 : data.parentWindowId,
};
const maybeCached = ["onResponseStarted", "onBeforeRedirect", "onCompleted", "onErrorOccurred"];
if (maybeCached.includes(eventName)) {
data2.fromCache = !!data.fromCache;
}
if ("ip" in data) {
--- a/toolkit/components/extensions/extension-process-script.js
+++ b/toolkit/components/extensions/extension-process-script.js
@@ -184,26 +184,19 @@ class ExtensionGlobal {
constructor(global) {
this.global = global;
MessageChannel.addListener(global, "Extension:Capture", this);
MessageChannel.addListener(global, "Extension:DetectLanguage", this);
MessageChannel.addListener(global, "Extension:Execute", this);
MessageChannel.addListener(global, "WebNavigation:GetFrame", this);
MessageChannel.addListener(global, "WebNavigation:GetAllFrames", this);
-
- this.windowId = global.content.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils)
- .outerWindowID;
-
- global.sendAsyncMessage("Extension:TopWindowID", {windowId: this.windowId});
}
uninit() {
- this.global.sendAsyncMessage("Extension:RemoveTopWindowID", {windowId: this.windowId});
}
get messageFilterStrict() {
return {
innerWindowID: getInnerWindowID(this.global.content),
};
}
--- a/toolkit/components/extensions/test/mochitest/test_ext_webnavigation.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webnavigation.html
@@ -48,25 +48,25 @@ function backgroundScript() {
expectedTabId = details.tabId;
}
browser.test.assertEq(details.tabId, expectedTabId, "correct tab");
browser.test.sendMessage("received", {url: details.url, event});
if (details.url == URL) {
- browser.test.assertEq(details.frameId, 0, "root frame ID correct");
- browser.test.assertEq(details.parentFrameId, -1, "root parent frame ID correct");
+ browser.test.assertEq(0, details.frameId, "root frame ID correct");
+ browser.test.assertEq(-1, details.parentFrameId, "root parent frame ID correct");
} else {
- browser.test.assertEq(details.parentFrameId, 0, "parent frame ID correct");
+ browser.test.assertEq(0, details.parentFrameId, "parent frame ID correct");
browser.test.assertTrue(details.frameId != 0, "frame ID probably okay");
}
- browser.test.assertTrue(details.frameId !== undefined);
- browser.test.assertTrue(details.parentFrameId !== undefined);
+ browser.test.assertTrue(details.frameId !== undefined, "frameId != undefined");
+ browser.test.assertTrue(details.parentFrameId !== undefined, "parentFrameId != undefined");
}
let listeners = {};
for (let event of EVENTS) {
listeners[event] = gotEvent.bind(null, event);
browser.webNavigation[event].addListener(listeners[event]);
}
--- a/toolkit/modules/addons/WebNavigation.jsm
+++ b/toolkit/modules/addons/WebNavigation.jsm
@@ -121,17 +121,17 @@ var Manager = {
createdTabBrowser,
url,
sourceFrameOuterWindowID,
sourceTabBrowser,
} = subject.wrappedJSObject;
this.fire("onCreatedNavigationTarget", createdTabBrowser, {}, {
sourceTabBrowser,
- sourceWindowId: sourceFrameOuterWindowID,
+ sourceFrameId: sourceFrameOuterWindowID,
url,
});
}
},
/**
* Recognize the type of urlbar user interaction (e.g. typing a new url,
* clicking on an url generated from a searchengine or a keyword, or a
@@ -301,17 +301,17 @@ var Manager = {
let where = ownerWin.whereToOpenLink(data);
if (where == "current") {
this.setRecentTabTransitionData({link: true});
}
}
},
onCreatedNavigationTarget(browser, data) {
- const {isSourceTab, createdWindowId, sourceWindowId, url} = data;
+ const {isSourceTab, createdWindowId, sourceFrameId, url} = data;
// We are going to potentially received two message manager messages for a single
// onCreatedNavigationTarget event that is happening in the child process,
// we are going to use the generate uuid to pair them together.
const pairedMessage = this.createdNavigationTargetByOuterWindowId.get(createdWindowId);
if (!pairedMessage) {
this.createdNavigationTargetByOuterWindowId.set(createdWindowId, {browser, data});
@@ -327,17 +327,17 @@ var Manager = {
sourceTabBrowser = browser;
createdTabBrowser = pairedMessage.browser;
} else {
sourceTabBrowser = pairedMessage.browser;
createdTabBrowser = browser;
}
this.fire("onCreatedNavigationTarget", createdTabBrowser, {}, {
- sourceTabBrowser, sourceWindowId, url,
+ sourceTabBrowser, sourceFrameId, url,
});
},
onStateChange(browser, data) {
let stateFlags = data.stateFlags;
if (stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
let url = data.requestURL;
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
@@ -386,21 +386,21 @@ var Manager = {
fire(type, browser, data, extra) {
let listeners = this.listeners.get(type);
if (!listeners) {
return;
}
let details = {
browser,
- windowId: data.windowId,
+ frameId: data.frameId,
};
- if (data.parentWindowId) {
- details.parentWindowId = data.parentWindowId;
+ if (data.parentFrameId !== undefined) {
+ details.parentFrameId = data.parentFrameId;
}
for (let prop in extra) {
details[prop] = extra[prop];
}
for (let [listener, filters] of listeners) {
// Call the listener if the listener has no filter or if its filter matches.
--- a/toolkit/modules/addons/WebNavigationContent.js
+++ b/toolkit/modules/addons/WebNavigationContent.js
@@ -8,19 +8,19 @@ Components.utils.import("resource://gre/
XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
"resource://gre/modules/WebNavigationFrames.jsm");
function loadListener(event) {
let document = event.target;
let window = document.defaultView;
let url = document.documentURI;
- let windowId = WebNavigationFrames.getWindowId(window);
- let parentWindowId = WebNavigationFrames.getParentWindowId(window);
- sendAsyncMessage("Extension:DOMContentLoaded", {windowId, parentWindowId, url});
+ let frameId = WebNavigationFrames.getFrameId(window);
+ let parentFrameId = WebNavigationFrames.getParentFrameId(window);
+ sendAsyncMessage("Extension:DOMContentLoaded", {frameId, parentFrameId, url});
}
addEventListener("DOMContentLoaded", loadListener);
addMessageListener("Extension:DisableWebNavigation", () => {
removeEventListener("DOMContentLoaded", loadListener);
});
var CreatedNavigationTargetListener = {
@@ -38,39 +38,39 @@ var CreatedNavigationTargetListener = {
return;
}
let props = subject.QueryInterface(Ci.nsIPropertyBag2);
const createdDocShell = props.getPropertyAsInterface("createdTabDocShell", Ci.nsIDocShell);
const sourceDocShell = props.getPropertyAsInterface("sourceTabDocShell", Ci.nsIDocShell);
- const isSourceTabDescendant = WebNavigationFrames.isDescendantDocShell(sourceDocShell, docShell);
+ const isSourceTabDescendant = sourceDocShell.sameTypeRootTreeItem === docShell;
if (docShell !== createdDocShell && docShell !== sourceDocShell &&
!isSourceTabDescendant) {
// if the createdNavigationTarget is not related to this docShell
// (this docShell is not the newly created docShell, it is not the source docShell,
// and the source docShell is not a descendant of it)
// there is nothing to do here and return early.
return;
}
const isSourceTab = docShell === sourceDocShell || isSourceTabDescendant;
- const sourceWindowId = WebNavigationFrames.getDocShellWindowId(sourceDocShell);
- const createdWindowId = WebNavigationFrames.getDocShellWindowId(createdDocShell);
+ const sourceFrameId = WebNavigationFrames.getDocShellFrameId(sourceDocShell);
+ const createdWindowId = WebNavigationFrames.getDocShellFrameId(createdDocShell);
let url;
if (props.hasKey("url")) {
url = props.getPropertyAsACString("url");
}
sendAsyncMessage("Extension:CreatedNavigationTarget", {
url,
- sourceWindowId,
+ sourceFrameId,
createdWindowId,
isSourceTab,
});
},
};
var FormSubmitListener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
@@ -199,34 +199,34 @@ var WebProgressListener = {
// (see Bug 1264936 and Bug 125662 for rationale)
this.sendDocumentChange({webProgress, locationURI, request});
}
},
sendStateChange({webProgress, locationURI, stateFlags, status}) {
let data = {
requestURL: locationURI.spec,
- windowId: webProgress.DOMWindowID,
- parentWindowId: WebNavigationFrames.getParentWindowId(webProgress.DOMWindow),
+ frameId: WebNavigationFrames.getFrameId(webProgress.DOMWindow),
+ parentFrameId: WebNavigationFrames.getParentFrameId(webProgress.DOMWindow),
status,
stateFlags,
};
sendAsyncMessage("Extension:StateChange", data);
},
sendDocumentChange({webProgress, locationURI, request}) {
let {loadType, DOMWindow} = webProgress;
let frameTransitionData = this.getFrameTransitionData({loadType, request, DOMWindow});
let data = {
frameTransitionData,
location: locationURI ? locationURI.spec : "",
- windowId: webProgress.DOMWindowID,
- parentWindowId: WebNavigationFrames.getParentWindowId(webProgress.DOMWindow),
+ frameId: WebNavigationFrames.getFrameId(webProgress.DOMWindow),
+ parentFrameId: WebNavigationFrames.getParentFrameId(webProgress.DOMWindow),
};
sendAsyncMessage("Extension:DocumentChange", data);
},
sendHistoryChange({webProgress, previousURI, locationURI, request}) {
let {loadType, DOMWindow} = webProgress;
@@ -253,18 +253,18 @@ var WebProgressListener = {
if (isHistoryStateUpdated || isReferenceFragmentUpdated) {
let frameTransitionData = this.getFrameTransitionData({loadType, request, DOMWindow});
let data = {
frameTransitionData,
isHistoryStateUpdated, isReferenceFragmentUpdated,
location: locationURI ? locationURI.spec : "",
- windowId: webProgress.DOMWindowID,
- parentWindowId: WebNavigationFrames.getParentWindowId(webProgress.DOMWindow),
+ frameId: WebNavigationFrames.getFrameId(webProgress.DOMWindow),
+ parentFrameId: WebNavigationFrames.getParentFrameId(webProgress.DOMWindow),
};
sendAsyncMessage("Extension:HistoryChange", data);
}
},
getFrameTransitionData({loadType, request, DOMWindow}) {
let frameTransitionData = {};
--- a/toolkit/modules/addons/WebNavigationFrames.jsm
+++ b/toolkit/modules/addons/WebNavigationFrames.jsm
@@ -5,77 +5,40 @@
"use strict";
const EXPORTED_SYMBOLS = ["WebNavigationFrames"];
var Ci = Components.interfaces;
/* exported WebNavigationFrames */
-function getWindowId(window) {
- return window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils)
- .outerWindowID;
-}
-
-function getParentWindowId(window) {
- return getWindowId(window.parent);
-}
-
-function getDocShellWindowId(docShell) {
- if (!docShell) {
- return undefined;
- }
-
- return docShell.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow)
- .getInterface(Ci.nsIDOMWindowUtils)
- .outerWindowID;
-}
-
/**
* Retrieve the DOMWindow associated to the docShell passed as parameter.
*
* @param {nsIDocShell} docShell - the docShell that we want to get the DOMWindow from.
* @returns {nsIDOMWindow} - the DOMWindow associated to the docShell.
*/
function docShellToWindow(docShell) {
return docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
}
/**
* The FrameDetail object which represents a frame in WebExtensions APIs.
*
* @typedef {Object} FrameDetail
* @inner
- * @property {number} windowId - Represents the numeric id which identify the frame in its tab.
- * @property {number} parentWindowId - Represents the numeric id which identify the parent frame.
+ * @property {number} frameId - Represents the numeric id which identify the frame in its tab.
+ * @property {number} parentFrameId - Represents the numeric id which identify the parent frame.
* @property {string} url - Represents the current location URL loaded in the frame.
* @property {boolean} errorOccurred - Indicates whether an error is occurred during the last load
* happened on this frame (NOT YET SUPPORTED).
*/
/**
- * Convert a docShell object into its internal FrameDetail representation.
- *
- * @param {nsIDocShell} docShell - the docShell object to be converted into a FrameDetail JSON object.
- * @returns {FrameDetail} the FrameDetail JSON object which represents the docShell.
- */
-function convertDocShellToFrameDetail(docShell) {
- let window = docShellToWindow(docShell);
-
- return {
- windowId: getWindowId(window),
- parentWindowId: getParentWindowId(window),
- url: window.location.href,
- };
-}
-
-/**
* A generator function which iterates over a docShell tree, given a root docShell.
*
* @param {nsIDocShell} docShell - the root docShell object
*/
function* iterateDocShellTree(docShell) {
let docShellsEnum = docShell.getDocShellEnumerator(
docShell.typeContent, docShell.ENUMERATE_FORWARDS);
@@ -88,28 +51,64 @@ function* iterateDocShellTree(docShell)
* Returns the frame ID of the given window. If the window is the
* top-level content window, its frame ID is 0. Otherwise, its frame ID
* is its outer window ID.
*
* @param {Window} window - The window to retrieve the frame ID for.
* @returns {number}
*/
function getFrameId(window) {
- let docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShell);
-
- if (!docShell.sameTypeParent) {
+ if (window.parent === window) {
return 0;
}
let utils = window.getInterface(Ci.nsIDOMWindowUtils);
return utils.outerWindowID;
}
/**
+ * Returns the frame ID of the given window's parent.
+ *
+ * @param {Window} window - The window to retrieve the parent frame ID for.
+ * @returns {number}
+ */
+function getParentFrameId(window) {
+ if (window.parent === window) {
+ return -1;
+ }
+
+ return getFrameId(window.parent);
+}
+
+function getDocShellFrameId(docShell) {
+ if (!docShell) {
+ return undefined;
+ }
+
+ return getFrameId(docShell.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow));
+}
+
+/**
+ * Convert a docShell object into its internal FrameDetail representation.
+ *
+ * @param {nsIDocShell} docShell - the docShell object to be converted into a FrameDetail JSON object.
+ * @returns {FrameDetail} the FrameDetail JSON object which represents the docShell.
+ */
+function convertDocShellToFrameDetail(docShell) {
+ let window = docShellToWindow(docShell);
+
+ return {
+ frameId: getFrameId(window),
+ parentFrameId: getParentFrameId(window),
+ url: window.location.href,
+ };
+}
+
+/**
* Search for a frame starting from the passed root docShell and
* convert it to its related frame detail representation.
*
* @param {number} frameId - the frame ID of the frame to retrieve, as
* described in getFrameId.
* @param {nsIDocShell} rootDocShell - the root docShell object
* @returns {nsIDocShell?} the docShell with the given frameId, or null
* if no match.
@@ -119,37 +118,30 @@ function findDocShell(frameId, rootDocSh
if (frameId == getFrameId(docShellToWindow(docShell))) {
return docShell;
}
}
return null;
}
-function isDescendantDocShell(targetDocShell, rootDocShell) {
- return (rootDocShell === targetDocShell.sameTypeRootTreeItem
- .QueryInterface(Ci.nsIDocShell));
-}
-
var WebNavigationFrames = {
iterateDocShellTree,
- isDescendantDocShell,
findDocShell,
getFrame(docShell, frameId) {
let result = findDocShell(frameId, docShell);
if (result) {
return convertDocShellToFrameDetail(result);
}
return null;
},
getFrameId,
+ getParentFrameId,
getAllFrames(docShell) {
return Array.from(iterateDocShellTree(docShell), convertDocShellToFrameDetail);
},
- getWindowId,
- getParentWindowId,
- getDocShellWindowId,
+ getDocShellFrameId,
};