Bug 1299053 - support tabId in browser.extension.getViews
MozReview-Commit-ID: Ep6pdUdbhmc
--- a/browser/components/extensions/test/browser/browser_ext_getViews.js
+++ b/browser/components/extensions/test/browser/browser_ext_getViews.js
@@ -43,17 +43,18 @@ function genericChecker() {
} else {
browser.test.sendMessage("counts", counts);
}
} else if (msg == kind + "-getViews-with-filter") {
let filter = args[0];
let count = browser.extension.getViews(filter).length;
browser.test.sendMessage("getViews-count", count);
} else if (msg == kind + "-open-tab") {
- browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("tab.html")});
+ browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("tab.html")})
+ .then((tab) => browser.test.sendMessage("opened-tab", tab.id));
} else if (msg == kind + "-close-tab") {
browser.tabs.query({
windowId: args[0],
}, tabs => {
let tab = tabs.find(tab => tab.url.indexOf("tab.html") != -1);
browser.tabs.remove(tab.id, () => {
browser.test.sendMessage("closed");
});
@@ -106,16 +107,17 @@ add_task(async function() {
let {Management: {global: {windowTracker}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
let winId1 = windowTracker.getId(win1);
let winId2 = windowTracker.getId(win2);
async function openTab(winId) {
extension.sendMessage("background-open-tab", winId);
await extension.awaitMessage("tab-ready");
+ return extension.awaitMessage("opened-tab");
}
async function checkViews(kind, tabCount, popupCount, kindCount) {
extension.sendMessage(kind + "-check-views");
let counts = await extension.awaitMessage("counts");
is(counts.background, 1, "background count correct");
is(counts.tab, tabCount, "tab count correct");
is(counts.popup, popupCount, "popup count correct");
@@ -124,27 +126,30 @@ add_task(async function() {
async function checkViewsWithFilter(filter, expectedCount) {
extension.sendMessage("background-getViews-with-filter", filter);
let count = await extension.awaitMessage("getViews-count");
is(count, expectedCount, `count for ${JSON.stringify(filter)} correct`);
}
await checkViews("background", 0, 0, 0);
+ await checkViewsWithFilter({tabId: -1}, 1);
- await openTab(winId1);
+ let tabId1 = await openTab(winId1);
await checkViews("background", 1, 0, 0);
await checkViews("tab", 1, 0, 1);
await checkViewsWithFilter({windowId: winId1}, 1);
+ await checkViewsWithFilter({tabId: tabId1}, 1);
- await openTab(winId2);
+ let tabId2 = await openTab(winId2);
await checkViews("background", 2, 0, 0);
await checkViewsWithFilter({windowId: winId2}, 1);
+ await checkViewsWithFilter({tabId: tabId2}, 1);
async function triggerPopup(win, callback) {
await clickBrowserAction(extension, win);
await awaitExtensionPanel(extension, win);
await extension.awaitMessage("popup-ready");
await callback();
@@ -157,28 +162,31 @@ add_task(async function() {
// be focus-related, but it's not caused by JS calling hidePopup), but even a
// short timeout seems to consistently fix it.
await new Promise(resolve => win1.setTimeout(resolve, 10));
await triggerPopup(win1, async function() {
await checkViews("background", 2, 1, 0);
await checkViews("popup", 2, 1, 1);
await checkViewsWithFilter({windowId: winId1}, 2);
+ await checkViewsWithFilter({type: "popup", tabId: -1}, 1);
});
await triggerPopup(win2, async function() {
await checkViews("background", 2, 1, 0);
await checkViews("popup", 2, 1, 1);
await checkViewsWithFilter({windowId: winId2}, 2);
+ await checkViewsWithFilter({type: "popup", tabId: -1}, 1);
});
info("checking counts after popups");
await checkViews("background", 2, 0, 0);
await checkViewsWithFilter({windowId: winId1}, 1);
+ await checkViewsWithFilter({tabId: -1}, 1);
info("closing one tab");
extension.sendMessage("background-close-tab", winId1);
await extension.awaitMessage("closed");
info("one tab closed, one remains");
--- a/toolkit/components/extensions/ExtensionPageChild.jsm
+++ b/toolkit/components/extensions/ExtensionPageChild.jsm
@@ -111,17 +111,18 @@ class ExtensionBaseContextChild extends
this.setContentWindow(contentWindow);
// This is the MessageSender property passed to extension.
let sender = {id: extension.id};
if (viewType == "tab") {
sender.frameId = WebNavigationFrames.getFrameId(contentWindow);
sender.tabId = tabId;
- this.tabId = tabId;
+ Object.defineProperty(this, "tabId",
+ {value: tabId, enumerable: true, configurable: true});
}
if (uri) {
sender.url = uri.spec;
}
this.sender = sender;
Schemas.exportLazyGetter(contentWindow, "browser", () => {
let browserObj = Cu.createObjectIn(contentWindow);
@@ -149,16 +150,21 @@ class ExtensionBaseContextChild extends
get windowId() {
if (["tab", "popup", "sidebar"].includes(this.viewType)) {
let globalView = ExtensionPageChild.contentGlobals.get(this.messageManager);
return globalView ? globalView.windowId : -1;
}
}
+ get tabId() {
+ // Will be overwritten in the constructor if necessary.
+ return -1;
+ }
+
// Called when the extension shuts down.
shutdown() {
this.unload();
}
// This method is called when an extension page navigates away or
// its tab is closed.
unload() {
--- a/toolkit/components/extensions/ext-c-extension.js
+++ b/toolkit/components/extensions/ext-c-extension.js
@@ -34,16 +34,20 @@ this.extension = class extends Extension
if (fetchProperties !== null) {
if (fetchProperties.type !== null && view.viewType != fetchProperties.type) {
continue;
}
if (fetchProperties.windowId !== null && view.windowId != fetchProperties.windowId) {
continue;
}
+
+ if (fetchProperties.tabId !== null && view.tabId != fetchProperties.tabId) {
+ continue;
+ }
}
result.push(view.contentWindow);
}
return result;
};
}
--- a/toolkit/components/extensions/schemas/extension.json
+++ b/toolkit/components/extensions/schemas/extension.json
@@ -67,16 +67,21 @@
"$ref": "ViewType",
"optional": true,
"description": "The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'popup', 'sidebar'."
},
"windowId": {
"type": "integer",
"optional": true,
"description": "The window to restrict the search to. If omitted, returns all views."
+ },
+ "tabId": {
+ "type": "integer",
+ "optional":true,
+ "description": "Find a view according to a tab id. If this field is omitted, returns all views."
}
}
}
],
"returns": {
"type": "array",
"description": "Array of global objects",
"items": {