bug 1245636 - Implement chrome.downloads.open r?kmag draft
authorMark Striemer <mstriemer@mozilla.com>
Mon, 14 Mar 2016 11:46:43 +0100
changeset 342390 a2b9a0f3c6caeeb0d695596c97e54c06dfea65ee
parent 342389 ad73190dcc495cfd527d0733df5bbc88fc90cd16
child 516581 15e13f8da8b910fd5799d0655f29c9551c20ac8a
push id13416
push userbmo:mstriemer@mozilla.com
push dateSat, 19 Mar 2016 02:24:51 +0000
reviewerskmag
bugs1245636
milestone48.0a1
bug 1245636 - Implement chrome.downloads.open r?kmag MozReview-Commit-ID: KYBgXTaUSkc
toolkit/components/extensions/ext-downloads.js
toolkit/components/extensions/schemas/downloads.json
toolkit/components/extensions/test/mochitest/test_ext_downloads.html
--- a/toolkit/components/extensions/ext-downloads.js
+++ b/toolkit/components/extensions/ext-downloads.js
@@ -549,25 +549,41 @@ extensions.registerSchemaAPI("downloads"
           return download.download.showContainingDirectory();
         }).then(() => {
           return true;
         }).catch(error => {
           return Promise.reject({message: error.message});
         });
       },
 
-      // When we do open(), check for additional downloads.open permission.
+      open(downloadId) {
+        if (!extension.hasPermission("downloads.open")) {
+          throw new context.cloneScope.Error(
+            "Permission denied because 'downloads.open' permission is missing.");
+        }
+        return DownloadMap.lazyInit().then(() => {
+          let download = DownloadMap.fromId(downloadId).download;
+          if (download.succeeded) {
+            return download.launch();
+          } else {
+            return Promise.reject({message: "Download has not completed."});
+          }
+        }).catch((error) => {
+          return Promise.reject({message: error.message});
+        });
+      },
+
+      // When we do setShelfEnabled(), check for additional "downloads.shelf" permission.
       // i.e.:
-      // open(downloadId) {
-      //   if (!extension.hasPermission("downloads.open")) {
-      //     throw new context.cloneScope.Error("Permission denied because 'downloads.open' permission is missing.");
+      // setShelfEnabled(enabled) {
+      //   if (!extension.hasPermission("downloads.shelf")) {
+      //     throw new context.cloneScope.Error("Permission denied because 'downloads.shelf' permission is missing.");
       //   }
       //   ...
       // }
-      // likewise for setShelfEnabled() and the "download.shelf" permission
 
       onChanged: new SingletonEventManager(context, "downloads.onChanged", fire => {
         const handler = (what, item) => {
           let changes = {};
           const noundef = val => (val === undefined) ? null : val;
           DOWNLOAD_ITEM_CHANGE_FIELDS.forEach(fld => {
             if (item[fld] != item.prechange[fld]) {
               changes[fld] = {
--- a/toolkit/components/extensions/schemas/downloads.json
+++ b/toolkit/components/extensions/schemas/downloads.json
@@ -551,22 +551,28 @@
             ],
             "type": "function"
           }
         ]
       },
       {
         "name": "open",
         "type": "function",
-        "unsupported": true,
+        "async": "callback",
         "description": "Open the downloaded file.",
         "parameters": [
           {
             "name": "downloadId",
             "type": "integer"
+          },
+          {
+            "name": "callback",
+            "type": "function",
+            "optional": true,
+            "parameters": []
           }
         ]
       },
       {
         "name": "show",
         "type": "function",
         "description": "Show the downloaded file in its folder in a file manager.",
         "async": "callback",
--- a/toolkit/components/extensions/test/mochitest/test_ext_downloads.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_downloads.html
@@ -37,12 +37,68 @@ add_task(function* test_downloads_api_na
   let extension = ExtensionTestUtils.loadExtension(extensionData);
   yield extension.startup();
   info("extension loaded");
   yield extension.awaitFinish("downloads tests");
   yield extension.unload();
   info("extension unloaded");
 });
 
+add_task(function* test_downloads_open_permission() {
+  function backgroundScript() {
+    browser.downloads.open(10, () => {
+      let error = chrome.runtime.lastError;
+      browser.test.assertTrue(!!error, "`downloads.open` raises an error.");
+      browser.test.assertTrue(error.message.indexOf("Permission denied") > -1,
+                              "`downloads.open` permission is required.");
+      browser.test.notifyPass("downloads tests");
+    });
+  }
+
+  let extensionData = {
+    background: "(" + backgroundScript.toString() + ")()",
+    manifest: {
+      permissions: ["downloads"],
+    },
+  };
+
+  let extension = ExtensionTestUtils.loadExtension(extensionData);
+  yield extension.startup();
+  info("extension loaded");
+  yield extension.awaitFinish("downloads tests");
+  yield extension.unload();
+  info("extension unloaded");
+});
+
+add_task(function* test_downloads_open() {
+  function backgroundScript() {
+    browser.downloads.open(10, () => {
+      let error = chrome.runtime.lastError;
+      browser.test.assertTrue(error, "An error exists.");
+      browser.test.assertTrue(
+        error.message === "Invalid download id 10",
+        `The error is informative. (${error.message})`);
+      browser.test.notifyPass("downloads tests");
+    });
+
+    // TODO: Once downloads.{pause,cancel,resume} lands (bug 1245602) test that this gives a good
+    // error when called with an incompleted download.
+  }
+
+  let extensionData = {
+    background: "(" + backgroundScript.toString() + ")()",
+    manifest: {
+      permissions: ["downloads", "downloads.open"],
+    },
+  };
+
+  let extension = ExtensionTestUtils.loadExtension(extensionData);
+  yield extension.startup();
+  info("extension loaded");
+  yield extension.awaitFinish("downloads tests");
+  yield extension.unload();
+  info("extension unloaded");
+});
+
 </script>
 
 </body>
 </html>