Bug 1321303 - Part 4: Implement browsingData.removeDownloads, r?aswan draft
authorBob Silverberg <bsilverberg@mozilla.com>
Tue, 13 Dec 2016 12:41:11 -0500
changeset 455476 55c9f1b44600ca17e5ffaaba49c459fc7bf1d4d6
parent 455475 5e6a225cecf42013aee7076c8eee59910ed44b87
child 455477 076bf3deca4feee14997ab6343de50bea4762735
push id40255
push userbmo:bob.silverberg@gmail.com
push dateTue, 03 Jan 2017 22:37:43 +0000
reviewersaswan
bugs1321303
milestone53.0a1
Bug 1321303 - Part 4: Implement browsingData.removeDownloads, r?aswan MozReview-Commit-ID: 6D0bLoJBByy
browser/components/extensions/ext-browsingData.js
browser/components/extensions/schemas/browsing_data.json
browser/components/extensions/test/xpcshell/test_ext_browsingData_downloads.js
browser/components/extensions/test/xpcshell/xpcshell.ini
--- a/browser/components/extensions/ext-browsingData.js
+++ b/browser/components/extensions/ext-browsingData.js
@@ -63,16 +63,20 @@ let clearCookies = Task.async(function* 
       }
     }
   } else {
     // Remove everything.
     cookieMgr.removeAll();
   }
 });
 
+function clearDownloads(options) {
+  return sanitizer.items.downloads.clear(makeRange(options));
+}
+
 function clearHistory(options) {
   return sanitizer.items.history.clear(makeRange(options));
 }
 
 function doRemoval(options, dataToRemove, extension) {
   if (options.originTypes &&
       (options.originTypes.protectedWeb || options.originTypes.extension)) {
     return Promise.reject(
@@ -85,16 +89,19 @@ function doRemoval(options, dataToRemove
     if (dataToRemove[dataType]) {
       switch (dataType) {
         case "cache":
           removalPromises.push(clearCache());
           break;
         case "cookies":
           removalPromises.push(clearCookies(options));
           break;
+        case "downloads":
+          removalPromises.push(clearDownloads(options));
+          break;
         case "history":
           removalPromises.push(clearHistory(options));
           break;
         default:
           invalidDataTypes.push(dataType);
       }
     }
   }
@@ -139,14 +146,17 @@ extensions.registerSchemaAPI("browsingDa
         return doRemoval(options, dataToRemove, extension);
       },
       removeCache(options) {
         return doRemoval(options, {cache: true});
       },
       removeCookies(options) {
         return doRemoval(options, {cookies: true});
       },
+      removeDownloads(options) {
+        return doRemoval(options, {downloads: true});
+      },
       removeHistory(options) {
         return doRemoval(options, {history: true});
       },
     },
   };
 });
--- a/browser/components/extensions/schemas/browsing_data.json
+++ b/browser/components/extensions/schemas/browsing_data.json
@@ -233,17 +233,16 @@
           }
         ]
       },
       {
         "name": "removeDownloads",
         "description": "Clears the browser's list of downloaded files (<em>not</em> the downloaded files themselves).",
         "type": "function",
         "async": "callback",
-        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/xpcshell/test_ext_browsingData_downloads.js
@@ -0,0 +1,110 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
+                                  "resource://gre/modules/Downloads.jsm");
+
+const OLD_NAMES = {[Downloads.PUBLIC]: "old-public", [Downloads.PRIVATE]: "old-private"};
+const RECENT_NAMES = {[Downloads.PUBLIC]: "recent-public", [Downloads.PRIVATE]: "recent-private"};
+const REFERENCE_DATE = new Date();
+const OLD_DATE = new Date(Number(REFERENCE_DATE) - 10000);
+
+async function checkDownloads(expectOldExists = true, expectRecentExists = true) {
+  for (let listType of [Downloads.PUBLIC, Downloads.PRIVATE]) {
+    let downloadsList = await Downloads.getList(listType);
+    equal(
+      (await downloadExists(downloadsList, OLD_NAMES[listType])),
+      expectOldExists,
+      `Fake old download ${(expectOldExists) ? "was found" : "was removed"}.`);
+    equal(
+      (await downloadExists(downloadsList, RECENT_NAMES[listType])),
+      expectRecentExists,
+      `Fake recent download ${(expectRecentExists) ? "was found" : "was removed"}.`);
+  }
+}
+
+async function setupDownloads() {
+  let downloadsList = await Downloads.getList(Downloads.ALL);
+  await downloadsList.removeFinished();
+
+  for (let listType of [Downloads.PUBLIC, Downloads.PRIVATE]) {
+    downloadsList = await Downloads.getList(listType);
+    let download = await Downloads.createDownload({
+      source: {
+        url: "https://bugzilla.mozilla.org/show_bug.cgi?id=1321303",
+        isPrivate: listType == Downloads.PRIVATE},
+      target: OLD_NAMES[listType]
+    });
+    download.startTime = OLD_DATE,
+    download.canceled = true;
+    await downloadsList.add(download);
+
+    download = await Downloads.createDownload({
+      source: {
+        url: "https://bugzilla.mozilla.org/show_bug.cgi?id=1321303",
+        isPrivate: listType == Downloads.PRIVATE},
+      target: RECENT_NAMES[listType]
+    });
+    download.startTime = REFERENCE_DATE,
+    download.canceled = true;
+    await downloadsList.add(download);
+  }
+
+  // Confirm everything worked.
+  downloadsList = await Downloads.getList(Downloads.ALL);
+  equal((await downloadsList.getAll()).length, 4, "4 fake downloads added.");
+  checkDownloads();
+}
+
+async function downloadExists(list, path) {
+  let listArray = await list.getAll();
+  return listArray.some(i => i.target.path == path);
+}
+
+add_task(async function testDownloads() {
+  function background() {
+    browser.test.onMessage.addListener(async (msg, options) => {
+      if (msg == "removeDownloads") {
+        await browser.browsingData.removeDownloads(options);
+      } else {
+        await browser.browsingData.remove(options, {downloads: true});
+      }
+      browser.test.sendMessage("downloadsRemoved");
+    });
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background,
+    manifest: {
+      permissions: ["browsingData"],
+    },
+  });
+
+  async function testRemovalMethod(method) {
+    // Clear downloads with no since value.
+    await setupDownloads();
+    extension.sendMessage(method, {});
+    await extension.awaitMessage("downloadsRemoved");
+    await checkDownloads(false, false);
+
+    // Clear downloads with recent since value.
+    await setupDownloads();
+    extension.sendMessage(method, {since: REFERENCE_DATE});
+    await extension.awaitMessage("downloadsRemoved");
+    await checkDownloads(true, false);
+
+    // Clear downloads with old since value.
+    await setupDownloads();
+    extension.sendMessage(method, {since: REFERENCE_DATE - 100000});
+    await extension.awaitMessage("downloadsRemoved");
+    await checkDownloads(false, false);
+  }
+
+  await extension.startup();
+
+  await testRemovalMethod("removeDownloads");
+  await testRemovalMethod("remove");
+
+  await extension.unload();
+});
--- a/browser/components/extensions/test/xpcshell/xpcshell.ini
+++ b/browser/components/extensions/test/xpcshell/xpcshell.ini
@@ -2,14 +2,15 @@
 head = head.js
 tail =
 firefox-appdir = browser
 tags = webextensions
 
 [test_ext_bookmarks.js]
 [test_ext_browsingData.js]
 [test_ext_browsingData_cookies_cache.js]
+[test_ext_browsingData_downloads.js]
 [test_ext_browsingData_history.js]
 [test_ext_browsingData_settings.js]
 [test_ext_history.js]
 [test_ext_manifest_commands.js]
 [test_ext_manifest_omnibox.js]
 [test_ext_manifest_permissions.js]