Bug 1427463 - Implement tabs.captureTab(tabId). r=mixedpuppy draft
authorTim Nguyen <ntim.bugs@gmail.com>
Wed, 10 Jan 2018 14:51:43 +0000
changeset 718562 3bcadd40eb506bbaef53f0cafcbcd4347e5cf58b
parent 718409 6c6f3fd9c5e114a1cb0ebb7fb5c19933954e94dd
child 745524 0b9b6a547f09c6bb8d818b07e8e70c44cbe6aa7a
push id94969
push userbmo:ntim.bugs@gmail.com
push dateWed, 10 Jan 2018 14:52:14 +0000
reviewersmixedpuppy
bugs1427463
milestone59.0a1
Bug 1427463 - Implement tabs.captureTab(tabId). r=mixedpuppy MozReview-Commit-ID: 5sr3I1A1b8A
browser/components/extensions/ext-tabs.js
browser/components/extensions/schemas/tabs.json
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_tabs_captureTab.js
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -546,16 +546,24 @@ this.tabs = class extends ExtensionAPI {
           if (queryInfo.title !== null) {
             queryInfo.title = new MatchGlob(queryInfo.title);
           }
 
           return Array.from(tabManager.query(queryInfo, context),
                             tab => tab.convert());
         },
 
+        async captureTab(tabId, options) {
+          let nativeTab = getTabOrActive(tabId);
+          await tabListener.awaitTabReady(nativeTab);
+
+          let tab = tabManager.wrapTab(nativeTab);
+          return tab.capture(context, options);
+        },
+
         async captureVisibleTab(windowId, options) {
           let window = windowId == null ?
             windowTracker.topWindow :
             windowTracker.getWindow(windowId, context);
 
           let tab = tabManager.wrapTab(window.gBrowser.selectedTab);
           await tabListener.awaitTabReady(tab.nativeTab);
 
--- a/browser/components/extensions/schemas/tabs.json
+++ b/browser/components/extensions/schemas/tabs.json
@@ -932,16 +932,37 @@
             "name": "tabId",
             "minimum": 0,
             "optional": true,
             "description": "Defaults to the active tab of the $(topic:current-window)[current window]."
           }
         ]
       },
       {
+        "name": "captureTab",
+        "type": "function",
+        "description": "Captures the visible area of a specified tab. You must have $(topic:declare_permissions)[&lt;all_urls&gt;] permission to use this method.",
+        "permissions": ["<all_urls>"],
+        "async": true,
+        "parameters": [
+          {
+            "type": "integer",
+            "name": "tabId",
+            "minimum": 0,
+            "optional": true,
+            "description": "The tab to capture. Defaults to the active tab of the current window."
+          },
+          {
+            "$ref": "extensionTypes.ImageDetails",
+            "name": "options",
+            "optional": true
+          }
+        ]
+      },
+      {
         "name": "captureVisibleTab",
         "type": "function",
         "description": "Captures the visible area of the currently active tab in the specified window. You must have $(topic:declare_permissions)[&lt;all_urls&gt;] permission to use this method.",
         "permissions": ["<all_urls>"],
         "async": "callback",
         "parameters": [
           {
             "type": "integer",
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -130,16 +130,17 @@ skip-if = (os == 'win' && ccov) # Bug 14
 [browser_ext_sidebarAction_contextMenu.js]
 [browser_ext_sidebarAction_tabs.js]
 [browser_ext_sidebarAction_windows.js]
 [browser_ext_simple.js]
 [browser_ext_slow_script.js]
 skip-if = !e10s || debug || asan
 [browser_ext_tab_runtimeConnect.js]
 [browser_ext_tabs_audio.js]
+[browser_ext_tabs_captureTab.js]
 [browser_ext_tabs_captureVisibleTab.js]
 [browser_ext_tabs_create.js]
 skip-if = os == "linux" && debug && bits == 32 # Bug 1350189
 [browser_ext_tabs_create_invalid_url.js]
 [browser_ext_tabs_detectLanguage.js]
 [browser_ext_tabs_discard.js]
 skip-if = !e10s
 [browser_ext_tabs_discarded.js]
copy from browser/components/extensions/test/browser/browser_ext_tabs_captureVisibleTab.js
copy to browser/components/extensions/test/browser/browser_ext_tabs_captureTab.js
--- a/browser/components/extensions/test/browser/browser_ext_tabs_captureVisibleTab.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_captureTab.js
@@ -28,20 +28,20 @@ async function runTest(options) {
 
   async function background(options) {
     browser.test.log(`Test color ${options.color} at fullZoom=${options.fullZoom}`);
 
     try {
       let [tab] = await browser.tabs.query({currentWindow: true, active: true});
 
       let [jpeg, png, ...pngs] = await Promise.all([
-        browser.tabs.captureVisibleTab(tab.windowId, {format: "jpeg", quality: 95}),
-        browser.tabs.captureVisibleTab(tab.windowId, {format: "png", quality: 95}),
-        browser.tabs.captureVisibleTab(tab.windowId, {quality: 95}),
-        browser.tabs.captureVisibleTab(tab.windowId),
+        browser.tabs.captureTab(tab.id, {format: "jpeg", quality: 95}),
+        browser.tabs.captureTab(tab.id, {format: "png", quality: 95}),
+        browser.tabs.captureTab(tab.id, {quality: 95}),
+        browser.tabs.captureTab(tab.id),
       ]);
 
       browser.test.assertTrue(pngs.every(url => url == png), "All PNGs are identical");
 
       browser.test.assertTrue(jpeg.startsWith("data:image/jpeg;base64,"), "jpeg is JPEG");
       browser.test.assertTrue(png.startsWith("data:image/png;base64,"), "png is PNG");
 
       let promises = [jpeg, png].map(url => new Promise(resolve => {
@@ -95,61 +95,61 @@ async function runTest(options) {
             browser.test.assertTrue(Math.abs(color[0] - imageData[0]) <= SLOP, `${format} image color.red is correct at (${x}, ${y})`);
             browser.test.assertTrue(Math.abs(color[1] - imageData[1]) <= SLOP, `${format} image color.green is correct at (${x}, ${y})`);
             browser.test.assertTrue(Math.abs(color[2] - imageData[2]) <= SLOP, `${format} image color.blue is correct at (${x}, ${y})`);
             browser.test.assertEq(255, imageData[3], `${format} image color.alpha is correct at (${x}, ${y})`);
           }
         }
       }
 
-      browser.test.notifyPass("captureVisibleTab");
+      browser.test.notifyPass("captureTab");
     } catch (e) {
       browser.test.fail(`Error: ${e} :: ${e.stack}`);
-      browser.test.notifyFail("captureVisibleTab");
+      browser.test.notifyFail("captureTab");
     }
   }
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["<all_urls>"],
     },
 
     background: `(${background})(${JSON.stringify(options)})`,
   });
 
   await extension.startup();
 
-  await extension.awaitFinish("captureVisibleTab");
+  await extension.awaitFinish("captureTab");
 
   await extension.unload();
 
   await BrowserTestUtils.removeTab(tab);
 }
 
-add_task(async function testCaptureVisibleTab() {
+add_task(async function testCaptureTab() {
   await runTest({color: [0, 0, 0], fullZoom: 1});
 
   await runTest({color: [0, 0, 0], fullZoom: 2});
 
   await runTest({color: [0, 0, 0], fullZoom: 0.5});
 
   await runTest({color: [255, 255, 255], fullZoom: 1});
 });
 
-add_task(async function testCaptureVisibleTabPermissions() {
+add_task(async function testCaptureTabPermissions() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["tabs"],
     },
 
     background() {
-      browser.test.assertEq(undefined, browser.tabs.captureVisibleTab,
-                            'Extension without "<all_urls>" permission should not have access to captureVisibleTab');
-      browser.test.notifyPass("captureVisibleTabPermissions");
+      browser.test.assertEq(undefined, browser.tabs.captureTab,
+                            'Extension without "<all_urls>" permission should not have access to captureTab');
+      browser.test.notifyPass("captureTabPermissions");
     },
   });
 
   await extension.startup();
 
-  await extension.awaitFinish("captureVisibleTabPermissions");
+  await extension.awaitFinish("captureTabPermissions");
 
   await extension.unload();
 });