Bug 1260548: Part 5 - Factor out <browser> data logic into shared modules. r?aswan
MozReview-Commit-ID: GHPympWA7U
--- a/browser/components/extensions/.eslintrc.js
+++ b/browser/components/extensions/.eslintrc.js
@@ -6,16 +6,15 @@ module.exports = { // eslint-disable-li
"globals": {
"EventEmitter": true,
"IconDetails": true,
"Tab": true,
"TabContext": true,
"Window": true,
"WindowEventManager": true,
"browserActionFor": true,
- "getBrowserInfo": true,
"getCookieStoreIdForTab": true,
"makeWidgetId": true,
"pageActionFor": true,
"tabTracker": true,
"windowTracker": true,
},
};
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -28,32 +28,31 @@ function getSender(extension, target, se
let tabId;
if ("tabId" in sender) {
// The message came from a privileged extension page running in a tab. In
// that case, it should include a tabId property (which is filled in by the
// page-open listener below).
tabId = sender.tabId;
delete sender.tabId;
} else if (target instanceof Ci.nsIDOMXULElement) {
- tabId = getBrowserInfo(target).tabId;
+ tabId = tabTracker.getBrowserData(target).tabId;
}
if (tabId) {
let tab = extension.tabManager.get(tabId, null);
if (tab) {
sender.tab = tab.convert();
}
}
}
// Used by Extension.jsm
global.tabGetSender = getSender;
/* eslint-disable mozilla/balanced-listeners */
-
extensions.on("page-shutdown", (type, context) => {
if (context.viewType == "tab") {
if (context.extension.id !== context.xulBrowser.contentPrincipal.addonId) {
// Only close extension tabs.
// This check prevents about:addons from closing when it contains a
// WebExtension as an embedded inline options page.
return;
}
@@ -61,26 +60,16 @@ extensions.on("page-shutdown", (type, co
if (gBrowser) {
let tab = gBrowser.getTabForBrowser(context.xulBrowser);
if (tab) {
gBrowser.removeTab(tab);
}
}
}
});
-
-extensions.on("fill-browser-data", (type, browser, data) => {
- let tabId, windowId;
- if (browser) {
- ({tabId, windowId} = getBrowserInfo(browser));
- }
-
- data.tabId = tabId || -1;
- data.windowId = windowId || -1;
-});
/* eslint-enable mozilla/balanced-listeners */
let tabListener = {
tabReadyInitialized: false,
tabReadyPromises: new WeakMap(),
initializingTabs: new WeakSet(),
initTabReady() {
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -90,63 +90,16 @@ TabContext.prototype = {
},
shutdown() {
windowTracker.removeListener("progress", this);
windowTracker.removeListener("TabSelect", this);
},
};
-function getBrowserInfo(browser) {
- if (!browser.ownerGlobal.gBrowser) {
- // When we're loaded into a <browser> inside about:addons, we need to go up
- // one more level.
- browser = browser.ownerGlobal.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShell)
- .chromeEventHandler;
-
- if (!browser) {
- return {};
- }
- }
-
- let result = {};
-
- let window = browser.ownerGlobal;
- if (window.gBrowser) {
- let tab = window.gBrowser.getTabForBrowser(browser);
- if (tab) {
- result.tabId = tabTracker.getId(tab);
- }
-
- result.windowId = windowTracker.getId(window);
- }
-
- return result;
-}
-global.getBrowserInfo = getBrowserInfo;
-
-// Sends the tab and windowId upon request. This is primarily used to support
-// the synchronous `browser.extension.getViews` API.
-let onGetTabAndWindowId = {
- receiveMessage({name, target, sync}) {
- let result = getBrowserInfo(target);
-
- if (result.tabId) {
- if (sync) {
- return result;
- }
- target.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", result);
- }
- },
-};
-/* eslint-disable mozilla/balanced-listeners */
-Services.mm.addMessageListener("Extension:GetTabAndWindowId", onGetTabAndWindowId);
-/* eslint-enable mozilla/balanced-listeners */
-
class WindowTracker extends WindowTrackerBase {
addProgressListener(window, listener) {
window.gBrowser.addTabsProgressListener(listener);
}
removeProgressListener(window, listener) {
window.gBrowser.removeTabsProgressListener(listener);
@@ -373,27 +326,43 @@ class TabTracker extends TabTrackerBase
// `tabs.onRemoved.addListener`, then the tab would be closed before the
// event listener is registered. To make sure that the event listener is
// notified, we dispatch `tabs.onRemoved` asynchronously.
Services.tm.mainThread.dispatch(() => {
this.emit("tab-removed", {tab, tabId, windowId, isWindowClosing});
}, Ci.nsIThread.DISPATCH_NORMAL);
}
- getBrowserId(browser) {
+ getBrowserData(browser) {
+ if (!browser.ownerGlobal.location.href === "about:addons") {
+ // When we're loaded into a <browser> inside about:addons, we need to go up
+ // one more level.
+ browser = browser.ownerGlobal.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell)
+ .chromeEventHandler;
+ }
+
+ let result = {
+ tabId: -1,
+ windowId: -1,
+ };
+
let {gBrowser} = browser.ownerGlobal;
// Some non-browser windows have gBrowser but not
// getTabForBrowser!
if (gBrowser && gBrowser.getTabForBrowser) {
+ result.windowId = windowTracker.getId(browser.ownerGlobal);
+
let tab = gBrowser.getTabForBrowser(browser);
if (tab) {
- return this.getId(tab);
+ result.tabId = this.getId(tab);
}
}
- return -1;
+
+ return result;
}
get activeTab() {
let window = windowTracker.topWindow;
if (window && window.gBrowser) {
return window.gBrowser.selectedTab;
}
return null;
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -97,20 +97,37 @@ let apiManager = new class extends Schem
}
return Promise.all(promises);
});
for (let [/* name */, value] of XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_SCRIPTS)) {
this.loadScript(value);
}
+ /* eslint-disable mozilla/balanced-listeners */
+ Services.mm.addMessageListener("Extension:GetTabAndWindowId", this);
+ /* eslint-enable mozilla/balanced-listeners */
+
this.initialized = promise;
return this.initialized;
}
+ receiveMessage({name, target, sync}) {
+ if (name === "Extension:GetTabAndWindowId") {
+ let result = this.global.tabTracker.getBrowserData(target);
+
+ if (result.tabId) {
+ if (sync) {
+ return result;
+ }
+ target.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", result);
+ }
+ }
+ }
+
registerSchemaAPI(namespace, envType, getAPI) {
if (envType == "addon_parent" || envType == "content_parent" ||
envType == "devtools_parent") {
super.registerSchemaAPI(namespace, envType, getAPI);
}
}
}();
@@ -365,23 +382,21 @@ class ExtensionPageContextParent extends
let {windowTracker} = apiManager.global;
if (currentWindow && windowTracker) {
return windowTracker.getId(currentWindow);
}
}
get tabId() {
- let {getBrowserInfo} = apiManager.global;
-
- if (getBrowserInfo) {
- // This is currently only available on desktop Firefox.
- return getBrowserInfo(this.xulBrowser).tabId;
+ let {tabTracker} = apiManager.global;
+ let data = tabTracker.getBrowserData(this.xulBrowser);
+ if (data.tabId >= 0) {
+ return data.tabId;
}
- return undefined;
}
onBrowserChange(browser) {
super.onBrowserChange(browser);
this.xulBrowser = browser;
}
shutdown() {
--- a/toolkit/components/extensions/ext-webNavigation.js
+++ b/toolkit/components/extensions/ext-webNavigation.js
@@ -115,17 +115,17 @@ function WebNavigationEventManager(conte
parentFrameId: ExtensionManagement.getParentFrameId(data.parentWindowId, data.windowId),
};
if (eventName == "onErrorOccurred") {
data2.error = data.error;
}
// Fills in tabId typically.
- extensions.emit("fill-browser-data", data.browser, data2);
+ Object.assign(data2, tabTracker.getBrowserData(data.browser));
if (data2.tabId < 0) {
return;
}
fillTransitionProperties(eventName, data, data2);
context.runSafe(callback, data2);
};
--- a/toolkit/components/extensions/ext-webRequest.js
+++ b/toolkit/components/extensions/ext-webRequest.js
@@ -22,18 +22,21 @@ function WebRequestEventManager(context,
let name = `webRequest.${eventName}`;
let register = (callback, filter, info) => {
let listener = data => {
// Prevent listening in on requests originating from system principal to
// prevent tinkering with OCSP, app and addon updates, etc.
if (data.isSystemPrincipal) {
return;
}
- let browserData = {};
- extensions.emit("fill-browser-data", data.browser, browserData);
+
+ let browserData = {tabId: -1, windowId: -1};
+ if (data.browser) {
+ browserData = tabTracker.getBrowserData(data.browser);
+ }
if (filter.tabId != null && browserData.tabId != filter.tabId) {
return;
}
if (filter.windowId != null && browserData.windowId != filter.windowId) {
return;
}
let data2 = {