Bug 1336308: Part 2 - Add a TabBase.sendMessage and TabBase.capture helper methods. r?aswan
MozReview-Commit-ID: EP8uxCkztvi
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -517,63 +517,31 @@ extensions.registerSchemaAPI("tabs", "ad
queryInfo = Object.assign({}, queryInfo);
queryInfo.url = new MatchPattern(queryInfo.url);
}
return Array.from(tabManager.query(queryInfo, context),
tab => tab.convert());
},
- captureVisibleTab(windowId, options) {
- if (!extension.hasPermission("<all_urls>")) {
- return Promise.reject({message: "The <all_urls> permission is required to use the captureVisibleTab API"});
- }
-
+ async captureVisibleTab(windowId, options) {
let window = windowId == null ?
windowTracker.topWindow :
windowTracker.getWindow(windowId, context);
- let tab = window.gBrowser.selectedTab;
- return tabListener.awaitTabReady(tab).then(() => {
- let browser = tab.linkedBrowser;
- let recipient = {
- innerWindowID: browser.innerWindowID,
- };
+ let tab = tabManager.wrapTab(window.gBrowser.selectedTab);
+ await tabListener.awaitTabReady(tab.tab);
- if (!options) {
- options = {};
- }
- if (options.format == null) {
- options.format = "png";
- }
- if (options.quality == null) {
- options.quality = 92;
- }
-
- let message = {
- options,
- width: browser.clientWidth,
- height: browser.clientHeight,
- };
-
- return context.sendMessage(browser.messageManager, "Extension:Capture",
- message, {recipient});
- });
+ return tab.capture(context, options);
},
async detectLanguage(tabId) {
- let tab = getTabOrActive(tabId);
+ let tab = await promiseTabWhenReady(tabId);
- return tabListener.awaitTabReady(tab).then(() => {
- let browser = tab.linkedBrowser;
- let recipient = {innerWindowID: browser.innerWindowID};
-
- return context.sendMessage(browser.messageManager, "Extension:DetectLanguage",
- {}, {recipient});
- });
+ return tab.sendMessage(context, "Extension:DetectLanguage");
},
async executeScript(tabId, details) {
let tab = await promiseTabWhenReady(tabId);
return tab.executeScript(context, details);
},
--- a/mobile/android/components/extensions/ext-tabs.js
+++ b/mobile/android/components/extensions/ext-tabs.js
@@ -395,51 +395,25 @@ extensions.registerSchemaAPI("tabs", "ad
queryInfo = Object.assign({}, queryInfo);
queryInfo.url = new MatchPattern(queryInfo.url);
}
return Array.from(tabManager.query(queryInfo, context),
tab => tab.convert());
},
- captureVisibleTab(windowId, options) {
- if (!extension.hasPermission("<all_urls>")) {
- return Promise.reject({message: "The <all_urls> permission is required to use the captureVisibleTab API"});
- }
-
+ async captureVisibleTab(windowId, options) {
let window = windowId == null ?
windowTracker.topWindow :
windowTracker.getWindow(windowId, context);
- let tab = window.BrowserApp.selectedTab;
- return tabListener.awaitTabReady(tab).then(() => {
- let {browser} = tab;
- let recipient = {
- innerWindowID: browser.innerWindowID,
- };
+ let tab = tabManager.wrapTab(window.BrowserApp.selectedTab);
+ await tabListener.awaitTabReady(tab.tab);
- if (!options) {
- options = {};
- }
- if (options.format == null) {
- options.format = "png";
- }
- if (options.quality == null) {
- options.quality = 92;
- }
-
- let message = {
- options,
- width: browser.clientWidth,
- height: browser.clientHeight,
- };
-
- return context.sendMessage(browser.messageManager, "Extension:Capture",
- message, {recipient});
- });
+ return tab.capture(context, options);
},
async executeScript(tabId, details) {
let tab = await promiseTabWhenReady(tabId);
return tab.executeScript(context, details);
},
--- a/toolkit/components/extensions/ExtensionTabs.jsm
+++ b/toolkit/components/extensions/ExtensionTabs.jsm
@@ -31,16 +31,80 @@ class TabBase {
constructor(extension, tab, id) {
this.extension = extension;
this.tabManager = extension.tabManager;
this.id = id;
this.tab = tab;
this.activeTabWindowID = null;
}
+ /**
+ * Sends a message, via the given context, to the ExtensionContent running in
+ * this tab. The tab's current innerWindowID is automatically added to the
+ * recipient filter for the message, and is used to ensure that the message is
+ * not processed if the content process navigates to a different content page
+ * before the message is received.
+ *
+ * @param {BaseContext} context
+ * The context through which to send the message.
+ * @param {string} messageName
+ * The name of the messge to send.
+ * @param {object} [data = {}]
+ * Arbitrary, structured-clonable message data to send.
+ * @param {object} [options]
+ * An options object, as accepted by BaseContext.sendMessage.
+ *
+ * @returns {Promise}
+ */
+ sendMessage(context, messageName, data = {}, options = null) {
+ let {browser, innerWindowID} = this;
+
+ options = Object.assign({}, options);
+ options.recipient = Object.assign({innerWindowID}, options.recipient);
+
+ return context.sendMessage(browser.messageManager, messageName,
+ data, options);
+ }
+
+ /**
+ * Capture the visible area of this tab, and return the result as a data: URL.
+ *
+ * @param {BaseContext} context
+ * The extension context for which to perform the capture.
+ * @param {Object} [options]
+ * The options with which to perform the capture.
+ * @param {string} [options.format = "png"]
+ * The image format in which to encode the captured data. May be one of
+ * "png" or "jpeg".
+ * @param {integer} [options.quality = 92]
+ * The quality at which to encode the captured image data, ranging from
+ * 0 to 100. Has no effect for the "png" format.
+ *
+ * @returns {Promise<string>}
+ */
+ capture(context, options = null) {
+ if (!options) {
+ options = {};
+ }
+ if (options.format == null) {
+ options.format = "png";
+ }
+ if (options.quality == null) {
+ options.quality = 92;
+ }
+
+ let message = {
+ options,
+ width: this.width,
+ height: this.height,
+ };
+
+ return this.sendMessage(context, "Extension:Capture", message);
+ }
+
get innerWindowID() {
return this.browser.innerWindowID;
}
get hasTabPermission() {
return this.extension.hasPermission("tabs") || this.hasActiveTabPermission;
}
@@ -191,22 +255,17 @@ class TabBase {
options.run_at = "document_idle";
}
if (details.cssOrigin !== null) {
options.css_origin = details.cssOrigin;
} else {
options.css_origin = "author";
}
- let {browser} = this;
- let recipient = {
- innerWindowID: browser.innerWindowID,
- };
-
- return context.sendMessage(browser.messageManager, "Extension:Execute", {options}, {recipient});
+ return this.sendMessage(context, "Extension:Execute", {options});
}
executeScript(context, details) {
return this._execute(context, details, "js", "executeScript");
}
insertCSS(context, details) {
return this._execute(context, details, "css", "insertCSS").then(() => {});