Bug 1317101 - Part 4: Deduplicate the handling of context tab and window IDs, and handle <browser> nesting in tabs. r?aswan
This could still use a fair amount of additional cleanup.
MozReview-Commit-ID: BteBFMlZCsy
--- a/browser/components/extensions/.eslintrc.js
+++ b/browser/components/extensions/.eslintrc.js
@@ -3,16 +3,17 @@
module.exports = { // eslint-disable-line no-undef
"extends": "../../../toolkit/components/extensions/.eslintrc.js",
"globals": {
"AllWindowEvents": true,
"browserActionFor": true,
"currentWindow": true,
"EventEmitter": true,
+ "getBrowserInfo": true,
"getCookieStoreIdForTab": true,
"IconDetails": true,
"makeWidgetId": true,
"pageActionFor": true,
"PanelPopup": true,
"TabContext": true,
"ViewPopup": true,
"WindowEventManager": true,
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -20,39 +20,31 @@ Cu.import("resource://gre/modules/Extens
var {
EventManager,
ignoreEvent,
} = ExtensionUtils;
// This function is pretty tightly tied to Extension.jsm.
// Its job is to fill in the |tab| property of the sender.
function getSender(extension, target, sender) {
+ let tabId;
if ("tabId" in sender) {
// The message came from an ExtensionContext. In that case, it should
// include a tabId property (which is filled in by the page-open
// listener below).
- let tab = TabManager.getTab(sender.tabId, null, null);
+ tabId = sender.tabId;
delete sender.tabId;
+ } else if (target instanceof Ci.nsIDOMXULElement) {
+ tabId = getBrowserInfo(target).tabId;
+ }
+
+ if (tabId) {
+ let tab = TabManager.getTab(tabId, null, null);
if (tab) {
sender.tab = TabManager.convert(extension, tab);
- return;
- }
- }
- if (target instanceof Ci.nsIDOMXULElement) {
- // If the message was sent from a content script to a <browser> element,
- // then we can just get the `tab` from `target`.
- let tabbrowser = target.ownerGlobal.gBrowser;
- if (tabbrowser) {
- let tab = tabbrowser.getTabForBrowser(target);
-
- // `tab` can be `undefined`, e.g. for extension popups. This condition is
- // reached if `getSender` is called for a popup without a valid `tabId`.
- if (tab) {
- sender.tab = TabManager.convert(extension, tab);
- }
}
}
}
// Used by Extension.jsm
global.tabGetSender = getSender;
/* eslint-disable mozilla/balanced-listeners */
@@ -71,17 +63,22 @@ extensions.on("page-shutdown", (type, co
if (tab) {
gBrowser.removeTab(tab);
}
}
}
});
extensions.on("fill-browser-data", (type, browser, data) => {
- data.tabId = browser ? TabManager.getBrowserId(browser) : -1;
+ let tabId = null;
+ if (browser) {
+ tabId = getBrowserInfo(browser).tabId;
+ }
+
+ data.tabId = tabId || -1;
});
/* eslint-enable mozilla/balanced-listeners */
global.currentWindow = function(context) {
let {xulWindow} = context;
if (xulWindow && context.viewType != "background") {
return xulWindow;
}
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -684,31 +684,56 @@ ExtensionTabManager.prototype = {
getTabs(window) {
return Array.from(window.gBrowser.tabs)
.filter(tab => !tab.closing)
.map(tab => this.convert(tab));
},
};
+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 = TabManager.getId(tab);
+ }
+
+ result.windowId = WindowManager.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 {gBrowser} = target.ownerGlobal;
- let tab = gBrowser && gBrowser.getTabForBrowser(target);
- if (tab) {
- let reply = {
- tabId: TabManager.getId(tab),
- windowId: WindowManager.getId(tab.ownerGlobal),
- };
+ let result = getBrowserInfo(target);
+
+ if (result.tabId) {
if (sync) {
- return reply;
+ return result;
}
- target.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", reply);
+ target.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", result);
}
},
};
/* eslint-disable mozilla/balanced-listeners */
Services.mm.addMessageListener("Extension:GetTabAndWindowId", onGetTabAndWindowId);
/* eslint-enable mozilla/balanced-listeners */
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -332,22 +332,22 @@ class ExtensionPageContextParent extends
if (!apiManager.global.WindowManager || this.viewType == "background") {
return;
}
// viewType popup or tab:
return apiManager.global.WindowManager.getId(this.xulWindow);
}
get tabId() {
- if (!apiManager.global.TabManager) {
- return; // Not yet supported on Android.
+ let {getBrowserInfo} = apiManager.global;
+
+ if (getBrowserInfo) {
+ return getBrowserInfo(this.xulBrowser).tabId;
}
- let {gBrowser} = this.xulBrowser.ownerGlobal;
- let tab = gBrowser && gBrowser.getTabForBrowser(this.xulBrowser);
- return tab && apiManager.global.TabManager.getId(tab);
+ return undefined;
}
onBrowserChange(browser) {
super.onBrowserChange(browser);
this.xulBrowser = browser;
}
shutdown() {