Bug 1363014 - Implement browsingData.remove WebExtension API method on android. r=bsilverberg,mixedpuppy,sebastian
authorTushar Saini (:shatur) <tushar.saini1285@gmail.com>
Wed, 30 Aug 2017 00:08:48 +0530
changeset 428269 213fe035b50b0754ddaa9d2c9473975ae5de5c04
parent 428268 bfb3d1d3cc8535f265dd8af74b815b770a9f430a
child 428270 6e5269790022f4dea5aa98df19f6e6344098c5cd
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsilverberg, mixedpuppy, sebastian
bugs1363014
milestone57.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 1363014 - Implement browsingData.remove WebExtension API method on android. r=bsilverberg,mixedpuppy,sebastian MozReview-Commit-ID: 2ipz1wqGpxc
mobile/android/components/extensions/ext-browsingData.js
mobile/android/components/extensions/schemas/browsing_data.json
mobile/android/components/extensions/test/mochitest/test_ext_browsingData_cookies_cache.html
mobile/android/components/extensions/test/mochitest/test_ext_browsingData_downloads.html
mobile/android/components/extensions/test/mochitest/test_ext_browsingData_formdata.html
--- a/mobile/android/components/extensions/ext-browsingData.js
+++ b/mobile/android/components/extensions/ext-browsingData.js
@@ -6,23 +6,22 @@ Cu.import("resource://gre/modules/Task.j
 
 XPCOMUtils.defineLazyModuleGetter(this, "Sanitizer",
                                   "resource://gre/modules/Sanitizer.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SharedPreferences",
                                   "resource://gre/modules/SharedPreferences.jsm");
 
-let clearCookies = async function(options) {
-  if (options.originTypes &&
-      (options.originTypes.protectedWeb || options.originTypes.extension)) {
-    return Promise.reject(
-      {message: "Firefox does not support protectedWeb or extension as originTypes."});
-  }
+const clearCache = () => {
+  // Clearing the cache does not support timestamps.
+  return Sanitizer.clearItem("cache");
+};
 
+const clearCookies = async function(options) {
   let cookieMgr = Services.cookies;
   let yieldCounter = 0;
   const YIELD_PERIOD = 10;
 
   if (options.since) {
     // Convert it to microseconds
     let since =  options.since * 1000;
     // Iterate through the cookies and delete any created after our cutoff.
@@ -41,18 +40,63 @@ let clearCookies = async function(option
       }
     }
   } else {
     // Remove everything.
     cookieMgr.removeAll();
   }
 };
 
+const clearDownloads = options => {
+  return Sanitizer.clearItem("downloadHistory", options.since);
+};
+
+const clearFormData = options => {
+  return Sanitizer.clearItem("formdata", options.since);
+};
+
+const doRemoval = (options, dataToRemove, extension) => {
+  if (options.originTypes &&
+      (options.originTypes.protectedWeb || options.originTypes.extension)) {
+    return Promise.reject(
+      {message: "Firefox does not support protectedWeb or extension as originTypes."});
+  }
+
+  let removalPromises = [];
+  let invalidDataTypes = [];
+  for (let dataType in 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 "formData":
+          removalPromises.push(clearFormData(options));
+          break;
+        default:
+          invalidDataTypes.push(dataType);
+      }
+    }
+  }
+  if (extension && invalidDataTypes.length) {
+    extension.logger.warn(
+      `Firefox does not support dataTypes: ${invalidDataTypes.toString()}.`);
+  }
+  return Promise.all(removalPromises);
+};
+
 this.browsingData = class extends ExtensionAPI {
   getAPI(context) {
+    let {extension} = context;
     return {
       browsingData: {
         settings() {
           const PREF_DOMAIN = "android.not_a_preference.privacy.clear";
           const PREF_KEY_PREFIX = "private.data.";
           // The following prefs are the only ones in Firefox that match corresponding
           // values used by Chrome when returning settings.
           const PREF_LIST = ["cache", "history", "formdata", "cookies_sessions", "downloadFiles"];
@@ -83,24 +127,27 @@ this.browsingData = class extends Extens
             // Firefox doesn't have the same concept of dataRemovalPermitted
             // as Chrome, so it will always be true.
             dataRemovalPermitted[name] = true;
           }
           // We do not provide option to delete history by time
           // so, since value is given 0, which means Everything
           return Promise.resolve({options: {since: 0}, dataToRemove, dataRemovalPermitted});
         },
-        removeCookies(options) {
-          return clearCookies(options);
+        remove(options, dataToRemove) {
+          return doRemoval(options, dataToRemove, extension);
         },
         removeCache(options) {
-          return Sanitizer.clearItem("cache");
+          return doRemoval(options, {cache: true});
+        },
+        removeCookies(options) {
+          return doRemoval(options, {cookies: true});
         },
         removeDownloads(options) {
-          return Sanitizer.clearItem("downloadHistory", options.since);
+          return doRemoval(options, {downloads: true});
         },
         removeFormData(options) {
-          return Sanitizer.clearItem("formdata", options.since);
+          return doRemoval(options, {formData: true});
         },
       },
     };
   }
 };
--- a/mobile/android/components/extensions/schemas/browsing_data.json
+++ b/mobile/android/components/extensions/schemas/browsing_data.json
@@ -157,17 +157,16 @@
           }
         ]
       },
       {
         "name": "remove",
         "description": "Clears various types of browsing data stored in a user's profile.",
         "type": "function",
         "async": "callback",
-        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "dataToRemove",
             "$ref": "DataTypeSet",
--- a/mobile/android/components/extensions/test/mochitest/test_ext_browsingData_cookies_cache.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_browsingData_cookies_cache.html
@@ -40,17 +40,21 @@ async function setUpCookies() {
 
   // Add a cookie which will end up with a more recent creationTime.
   addCookie(COOKIE);
 }
 
 add_task(async function testCookies() {
   function background() {
     browser.test.onMessage.addListener(async (msg, options) => {
-      await browser.browsingData.removeCookies(options);
+      if (msg == "removeCookies") {
+        await browser.browsingData.removeCookies(options);
+      } else {
+        await browser.browsingData.remove(options, {cookies: true});
+      }
       browser.test.sendMessage("cookiesRemoved");
     });
   }
 
   let extension = ExtensionTestUtils.loadExtension({
     background,
     manifest: {
       permissions: ["browsingData"],
@@ -84,25 +88,28 @@ add_task(async function testCookies() {
 
     ok(!Services.cookies.cookieExists(COOKIE), `Cookie ${COOKIE.name}  was removed.`);
     ok(!Services.cookies.cookieExists(oldCookie), `Cookie ${oldCookie.name}  was removed.`);
   }
 
   await extension.startup();
 
   await testRemovalMethod("removeCookies");
+  await testRemovalMethod("remove");
 
   await extension.unload();
 });
 
 add_task(async function testCache() {
   function background() {
     browser.test.onMessage.addListener(async msg => {
       if (msg == "removeCache") {
         await browser.browsingData.removeCache({});
+      } else {
+        await browser.browsingData.remove({}, {cache: true});
       }
       browser.test.sendMessage("cacheRemoved");
     });
   }
 
   let extension = ExtensionTestUtils.loadExtension({
     background,
     manifest: {
@@ -128,15 +135,16 @@ add_task(async function testCache() {
     extension.sendMessage(method);
     await awaitNotification;
     await extension.awaitMessage("cacheRemoved");
   }
 
   await extension.startup();
 
   await testRemovalMethod("removeCache");
+  await testRemovalMethod("remove");
 
   await extension.unload();
 });
 </script>
 
 </body>
 </html>
--- a/mobile/android/components/extensions/test/mochitest/test_ext_browsingData_downloads.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_browsingData_downloads.html
@@ -72,17 +72,21 @@ async function setupDownloads() {
   downloadsList = await Downloads.getList(Downloads.ALL);
   is((await downloadsList.getAll()).length, 4, "4 fake downloads added.");
   checkDownloads();
 }
 
 add_task(async function testDownloads() {
   function background() {
     browser.test.onMessage.addListener(async (msg, options) => {
-      await browser.browsingData.removeDownloads(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"],
@@ -107,15 +111,16 @@ add_task(async function testDownloads() 
     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();
 });
 
 </script>
 </body>
 </html>
--- a/mobile/android/components/extensions/test/mochitest/test_ext_browsingData_formdata.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_browsingData_formdata.html
@@ -89,17 +89,21 @@ async function setupFormHistory() {
   await countEntries("reference", "Checking for 10minutes form history entry creation", 1);
   await countEntries("10secondsAgo", "Checking for 1hour form history entry creation", 1);
   await countEntries("10minutesAgo", "Checking for 1hour10minutes form history entry creation", 1);
 }
 
 add_task(async function testFormData() {
   function background() {
     browser.test.onMessage.addListener(async (msg, options) => {
-      await browser.browsingData.removeFormData(options);
+      if (msg == "removeFormData") {
+        await browser.browsingData.removeFormData(options);
+      } else {
+        await browser.browsingData.remove(options, {formData: true});
+      }
       browser.test.sendMessage("formDataRemoved");
     });
   }
 
   let extension = ExtensionTestUtils.loadExtension({
     background,
     manifest: {
       permissions: ["browsingData"],
@@ -133,15 +137,16 @@ add_task(async function testFormData() {
     await countEntries("reference", "reference form entry should be deleted.", 0);
     await countEntries("10secondsAgo", "10secondsAgo form entry should be deleted.", 0);
     await countEntries("10minutesAgo", "10minutesAgo form entry should be deleted.", 0);
   }
 
   await extension.startup();
 
   await testRemovalMethod("removeFormData");
+  await testRemovalMethod("remove");
 
   await extension.unload();
 });
 
 </script>
 </body>
 </html>