Bug 1321303 - Part 2: Implement browsingData.removeCache, r=aswan
authorBob Silverberg <bsilverberg@mozilla.com>
Thu, 01 Dec 2016 14:01:08 -0500
changeset 377741 34579b580023357b5b68ad80689278bec5150195
parent 377740 0d944258ba3ff8ecab9d0fce7b1c211d1985d52b
child 377742 bcc9cdc7579c29e2ff6f5d938885d2a6a94f7f5e
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 2: Implement browsingData.removeCache, r=aswan MozReview-Commit-ID: 3mBgpkoFaYJ
browser/components/extensions/ext-browsingData.js
browser/components/extensions/schemas/browsing_data.json
browser/components/extensions/test/xpcshell/head.js
browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies.js
browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies_cache.js
browser/components/extensions/test/xpcshell/xpcshell.ini
--- a/browser/components/extensions/ext-browsingData.js
+++ b/browser/components/extensions/ext-browsingData.js
@@ -26,16 +26,21 @@ const YIELD_PERIOD = 10;
 const PREF_DOMAIN = "privacy.cpd.";
 
 XPCOMUtils.defineLazyGetter(this, "sanitizer", () => {
   let sanitizer = new Sanitizer();
   sanitizer.prefDomain = PREF_DOMAIN;
   return sanitizer;
 });
 
+function clearCache() {
+  // Clearing the cache does not support timestamps.
+  return sanitizer.items.cache.clear();
+}
+
 let clearCookies = Task.async(function* (options) {
   // This code has been borrowed from sanitize.js.
   let yieldCounter = 0;
 
   if (options.since) {
     // Iterate through the cookies and delete any created after our cutoff.
     let cookiesEnum = cookieMgr.enumerator;
     while (cookiesEnum.hasMoreElements()) {
@@ -64,16 +69,19 @@ function doRemoval(options, dataToRemove
       {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;
         default:
           invalidDataTypes.push(dataType);
       }
     }
   }
@@ -112,14 +120,17 @@ extensions.registerSchemaAPI("browsingDa
         dataToRemove.formData = Preferences.get(`${PREF_DOMAIN}formdata`);
         dataRemovalPermitted.formData = true;
 
         return Promise.resolve({options, dataToRemove, dataRemovalPermitted});
       },
       remove(options, dataToRemove) {
         return doRemoval(options, dataToRemove, extension);
       },
+      removeCache(options) {
+        return doRemoval(options, {cache: true});
+      },
       removeCookies(options) {
         return doRemoval(options, {cookies: true});
       },
     },
   };
 });
--- a/browser/components/extensions/schemas/browsing_data.json
+++ b/browser/components/extensions/schemas/browsing_data.json
@@ -195,17 +195,16 @@
           }
         ]
       },
       {
         "name": "removeCache",
         "description": "Clears the browser's cache.",
         "type": "function",
         "async": "callback",
-        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
--- a/browser/components/extensions/test/xpcshell/head.js
+++ b/browser/components/extensions/test/xpcshell/head.js
@@ -22,16 +22,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
                                   "resource://testing-common/httpd.js");
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TestUtils",
+                                  "resource://testing-common/TestUtils.jsm");
 
 ExtensionTestUtils.init(this);
 
 
 /**
  * Creates a new HttpServer for testing, and begins listening on the
  * specified port. Automatically shuts down the server when the test
  * unit ends.
rename from browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies.js
rename to browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies_cache.js
--- a/browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies_cache.js
@@ -5,22 +5,71 @@
 XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
                                   "resource://gre/modules/Timer.jsm");
 
 const COOKIE = {
   host: "example.com",
   name: "test_cookie",
   path: "/",
 };
+let since, oldCookie;
 
 function addCookie(cookie) {
   Services.cookies.add(cookie.host, cookie.path, cookie.name, "test", false, false, false, Date.now() / 1000 + 10000);
   ok(Services.cookies.cookieExists(cookie), `Cookie ${cookie.name} was created.`);
 }
 
+async function setUpCookies() {
+  // Add a cookie which will end up with an older creationTime.
+  oldCookie = Object.assign({}, COOKIE, {name: Date.now()});
+  addCookie(oldCookie);
+  await new Promise(resolve => setTimeout(resolve, 10));
+  since = Date.now();
+  await new Promise(resolve => setTimeout(resolve, 10));
+
+  // Add a cookie which will end up with a more recent creationTime.
+  addCookie(COOKIE);
+}
+
+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: {
+      permissions: ["browsingData"],
+    },
+  });
+
+  async function testRemovalMethod(method) {
+    // We can assume the notification works properly, so we only need to observe
+    // the notification to know the cache was cleared.
+    let awaitNotification = TestUtils.topicObserved("cacheservice:empty-cache");
+    extension.sendMessage(method);
+    await awaitNotification;
+    await extension.awaitMessage("cacheRemoved");
+  }
+
+  await extension.startup();
+
+  await testRemovalMethod("removeCache");
+  await testRemovalMethod("remove");
+
+  await extension.unload();
+});
+
 add_task(async function testCookies() {
   function background() {
     browser.test.onMessage.addListener(async (msg, options) => {
       if (msg == "removeCookies") {
         await browser.browsingData.removeCookies(options);
       } else {
         await browser.browsingData.remove(options, {cookies: true});
       }
@@ -31,42 +80,93 @@ add_task(async function testCookies() {
   let extension = ExtensionTestUtils.loadExtension({
     background,
     manifest: {
       permissions: ["browsingData"],
     },
   });
 
   async function testRemovalMethod(method) {
-    // Add a cookie which will end up with an older creationTime.
-    let oldCookie = Object.assign({}, COOKIE, {name: Date.now()});
-    addCookie(oldCookie);
-    await new Promise(resolve => setTimeout(resolve, 10));
-    let since = Date.now();
-
-    // Add a cookie which will end up with a more recent creationTime.
-    addCookie(COOKIE);
-
-    // Clear cookies with a since value.
+    // Clear cookies with a recent since value.
+    await setUpCookies();
     extension.sendMessage(method, {since});
     await extension.awaitMessage("cookiesRemoved");
 
     ok(Services.cookies.cookieExists(oldCookie), "Old cookie was not removed.");
     ok(!Services.cookies.cookieExists(COOKIE), "Recent cookie was removed.");
 
+    // Clear cookies with an old since value.
+    await setUpCookies();
+    addCookie(COOKIE);
+    extension.sendMessage(method, {since: since - 100000});
+    await extension.awaitMessage("cookiesRemoved");
+
+    ok(!Services.cookies.cookieExists(oldCookie), "Old cookie was removed.");
+    ok(!Services.cookies.cookieExists(COOKIE), "Recent cookie was removed.");
+
     // Clear cookies with no since value and valid originTypes.
-    addCookie(COOKIE);
+    await setUpCookies();
     extension.sendMessage(
       method,
       {originTypes: {unprotectedWeb: true, protectedWeb: false}});
     await extension.awaitMessage("cookiesRemoved");
 
     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 testCacheAndCookies() {
+  function background() {
+    browser.test.onMessage.addListener(async options => {
+      await browser.browsingData.remove(options, {cache: true, cookies: true});
+      browser.test.sendMessage("cacheAndCookiesRemoved");
+    });
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background,
+    manifest: {
+      permissions: ["browsingData"],
+    },
+  });
+
+  await extension.startup();
+
+  // Clear cache and cookies with a recent since value.
+  await setUpCookies();
+  let awaitNotification = TestUtils.topicObserved("cacheservice:empty-cache");
+  extension.sendMessage({since});
+  await awaitNotification;
+  await extension.awaitMessage("cacheAndCookiesRemoved");
+
+  ok(Services.cookies.cookieExists(oldCookie), "Old cookie was not removed.");
+  ok(!Services.cookies.cookieExists(COOKIE), "Recent cookie was removed.");
+
+  // Clear cache and cookies with an old since value.
+  await setUpCookies();
+  awaitNotification = TestUtils.topicObserved("cacheservice:empty-cache");
+  extension.sendMessage({since: since - 100000});
+  await awaitNotification;
+  await extension.awaitMessage("cacheAndCookiesRemoved");
+
+  ok(!Services.cookies.cookieExists(oldCookie), "Old cookie was removed.");
+  ok(!Services.cookies.cookieExists(COOKIE), "Recent cookie was removed.");
+
+  // Clear cache and cookies with no since value.
+  await setUpCookies();
+  awaitNotification = TestUtils.topicObserved("cacheservice:empty-cache");
+  extension.sendMessage({});
+  await awaitNotification;
+  await extension.awaitMessage("cacheAndCookiesRemoved");
+
+  ok(!Services.cookies.cookieExists(COOKIE), `Cookie ${COOKIE.name}  was removed.`);
+  ok(!Services.cookies.cookieExists(oldCookie), `Cookie ${oldCookie.name}  was removed.`);
+
+  await extension.unload();
+});
--- a/browser/components/extensions/test/xpcshell/xpcshell.ini
+++ b/browser/components/extensions/test/xpcshell/xpcshell.ini
@@ -1,13 +1,13 @@
 [DEFAULT]
 head = head.js
 firefox-appdir = browser
 tags = webextensions
 
 [test_ext_bookmarks.js]
 [test_ext_browsingData.js]
-[test_ext_browsingData_cookies.js]
+[test_ext_browsingData_cookies_cache.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]