Bug 1321303 - Part 4: Implement browsingData.removeDownloads, r=aswan
authorBob Silverberg <bsilverberg@mozilla.com>
Tue, 13 Dec 2016 12:41:11 -0500
changeset 377743 d8db138a2d4e1de01d9c5ea434e5b4e67650279f
parent 377742 bcc9cdc7579c29e2ff6f5d938885d2a6a94f7f5e
child 377744 4b819370879335a9dddac438e6ad692b6ed7ceca
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1321303
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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 downloadExists(list, path) {
+  let listArray = await list.getAll();
+  return listArray.some(i => i.target.path == path);
+}
+
+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();
+}
+
+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
@@ -1,13 +1,14 @@
 [DEFAULT]
 head = head.js
 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_settings.js]
 [test_ext_history.js]
 [test_ext_manifest_commands.js]
 [test_ext_manifest_omnibox.js]
 [test_ext_manifest_permissions.js]