Bug 1321303 - Part 3: Implement browsingData.removeHistory, r=aswan
authorBob Silverberg <bsilverberg@mozilla.com>
Mon, 12 Dec 2016 16:44:59 -0500
changeset 375458 bcc9cdc7579c29e2ff6f5d938885d2a6a94f7f5e
parent 375457 34579b580023357b5b68ad80689278bec5150195
child 375459 d8db138a2d4e1de01d9c5ea434e5b4e67650279f
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [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 3: Implement browsingData.removeHistory, r=aswan MozReview-Commit-ID: 5BkLOGUSqfZ
browser/components/extensions/ext-browsingData.js
browser/components/extensions/schemas/browsing_data.json
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_browsingData_history.js
--- a/browser/components/extensions/ext-browsingData.js
+++ b/browser/components/extensions/ext-browsingData.js
@@ -26,16 +26,22 @@ const YIELD_PERIOD = 10;
 const PREF_DOMAIN = "privacy.cpd.";
 
 XPCOMUtils.defineLazyGetter(this, "sanitizer", () => {
   let sanitizer = new Sanitizer();
   sanitizer.prefDomain = PREF_DOMAIN;
   return sanitizer;
 });
 
+function makeRange(options) {
+  return (options.since == null) ?
+    null :
+    [PlacesUtils.toPRTime(options.since), PlacesUtils.toPRTime(Date.now())];
+}
+
 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;
@@ -57,16 +63,20 @@ let clearCookies = Task.async(function* 
       }
     }
   } else {
     // Remove everything.
     cookieMgr.removeAll();
   }
 });
 
+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(
       {message: "Firefox does not support protectedWeb or extension as originTypes."});
   }
 
   let removalPromises = [];
@@ -75,16 +85,19 @@ function doRemoval(options, dataToRemove
     if (dataToRemove[dataType]) {
       switch (dataType) {
         case "cache":
           removalPromises.push(clearCache());
           break;
         case "cookies":
           removalPromises.push(clearCookies(options));
           break;
+        case "history":
+          removalPromises.push(clearHistory(options));
+          break;
         default:
           invalidDataTypes.push(dataType);
       }
     }
   }
   if (extension && invalidDataTypes.length) {
     extension.logger.warn(
       `Firefox does not support dataTypes: ${invalidDataTypes.toString()}.`);
@@ -126,11 +139,14 @@ extensions.registerSchemaAPI("browsingDa
         return doRemoval(options, dataToRemove, extension);
       },
       removeCache(options) {
         return doRemoval(options, {cache: true});
       },
       removeCookies(options) {
         return doRemoval(options, {cookies: true});
       },
+      removeHistory(options) {
+        return doRemoval(options, {history: true});
+      },
     },
   };
 });
--- a/browser/components/extensions/schemas/browsing_data.json
+++ b/browser/components/extensions/schemas/browsing_data.json
@@ -293,17 +293,16 @@
           }
         ]
       },
       {
         "name": "removeHistory",
         "description": "Clears the browser's history.",
         "type": "function",
         "async": "callback",
-        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -23,16 +23,17 @@ support-files =
 [browser_ext_browserAction_context.js]
 [browser_ext_browserAction_disabled.js]
 [browser_ext_browserAction_pageAction_icon.js]
 [browser_ext_browserAction_pageAction_icon_permissions.js]
 [browser_ext_browserAction_popup.js]
 [browser_ext_browserAction_popup_preload.js]
 [browser_ext_browserAction_popup_resize.js]
 [browser_ext_browserAction_simple.js]
+[browser_ext_browsingData_history.js]
 [browser_ext_commands_execute_browser_action.js]
 [browser_ext_commands_execute_page_action.js]
 [browser_ext_commands_getAll.js]
 [browser_ext_commands_onCommand.js]
 [browser_ext_contentscript_connect.js]
 [browser_ext_contextMenus.js]
 [browser_ext_contextMenus_checkboxes.js]
 [browser_ext_contextMenus_chrome.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_browsingData_history.js
@@ -0,0 +1,91 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
+                                  "resource://testing-common/PlacesTestUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+                                  "resource://gre/modules/PlacesUtils.jsm");
+
+const OLD_URL = "http://example.com/";
+const RECENT_URL = "http://example.com/2/";
+const REFERENCE_DATE = new Date();
+
+// pages/visits to add via History.insert
+const PAGE_INFOS = [
+  {
+    url: RECENT_URL,
+    title: `test visit for ${RECENT_URL}`,
+    visits: [
+      {date: REFERENCE_DATE},
+    ],
+  },
+  {
+    url: OLD_URL,
+    title: `test visit for ${OLD_URL}`,
+    visits: [
+      {date: new Date(Number(REFERENCE_DATE) - 1000)},
+      {date: new Date(Number(REFERENCE_DATE) - 2000)},
+    ],
+  },
+];
+
+async function setupHistory() {
+  await PlacesTestUtils.clearHistory();
+  await PlacesUtils.history.insertMany(PAGE_INFOS);
+  is((await PlacesTestUtils.visitsInDB(RECENT_URL)), 1, "Expected number of visits found in history database.");
+  is((await PlacesTestUtils.visitsInDB(OLD_URL)), 2, "Expected number of visits found in history database.");
+}
+
+add_task(async function testHistory() {
+  function background() {
+    browser.test.onMessage.addListener(async (msg, options) => {
+      if (msg == "removeHistory") {
+        await browser.browsingData.removeHistory(options);
+      } else {
+        await browser.browsingData.remove(options, {history: true});
+      }
+      browser.test.sendMessage("historyRemoved");
+    });
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background,
+    manifest: {
+      permissions: ["browsingData"],
+    },
+  });
+
+  async function testRemovalMethod(method) {
+    // Clear history with no since value.
+    await setupHistory();
+    extension.sendMessage(method, {});
+    await extension.awaitMessage("historyRemoved");
+
+    is((await PlacesTestUtils.visitsInDB(RECENT_URL)), 0, "Expected number of visits removed from history database.");
+    is((await PlacesTestUtils.visitsInDB(OLD_URL)), 0, "Expected number of visits removed from history database.");
+
+    // Clear history with recent since value.
+    await setupHistory();
+    extension.sendMessage(method, {since: REFERENCE_DATE - 1000});
+    await extension.awaitMessage("historyRemoved");
+
+    is((await PlacesTestUtils.visitsInDB(RECENT_URL)), 0, "Expected number of visits removed from history database.");
+    is((await PlacesTestUtils.visitsInDB(OLD_URL)), 1, "Expected number of visits removed from history database.");
+
+    // Clear history with old since value.
+    await setupHistory();
+    extension.sendMessage(method, {since: REFERENCE_DATE - 100000});
+    await extension.awaitMessage("historyRemoved");
+
+    is((await PlacesTestUtils.visitsInDB(RECENT_URL)), 0, "Expected number of visits removed from history database.");
+    is((await PlacesTestUtils.visitsInDB(OLD_URL)), 0, "Expected number of visits removed from history database.");
+  }
+
+  await extension.startup();
+
+  await testRemovalMethod("removeHistory");
+  await testRemovalMethod("remove");
+
+  await extension.unload();
+});