Bug 1252998 - StorageActivityService - part 9 - Test for nsIStorageActivityService, r=gijs, r=asuth
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 04 Apr 2018 23:08:57 +0200
changeset 467880 38653c75863b9727c86621523d92908aefe09c11
parent 467879 428f49f692ce707cd7e492217f23cfc3a23915b2
child 467881 db8bf70e7847af6bcfe5a5829ec894f0ea61abe8
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgijs, asuth
bugs1252998
milestone61.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 1252998 - StorageActivityService - part 9 - Test for nsIStorageActivityService, r=gijs, r=asuth
browser/base/content/test/sanitize/browser.ini
browser/base/content/test/sanitize/browser_sanitize-offlineData.js
browser/base/content/test/sanitize/dummy.js
browser/base/content/test/sanitize/sanitize.html
dom/interfaces/storage/nsIStorageActivityService.idl
dom/storage/StorageActivityService.cpp
--- a/browser/base/content/test/sanitize/browser.ini
+++ b/browser/base/content/test/sanitize/browser.ini
@@ -1,11 +1,14 @@
 [DEFAULT]
 support-files=
   head.js
+  dummy.js
   dummy_page.html
+  sanitize.html
 
 [browser_purgehistory_clears_sh.js]
 [browser_sanitize-formhistory.js]
+[browser_sanitize-offlineData.js]
 [browser_sanitize-passwordDisabledHosts.js]
 [browser_sanitize-sitepermissions.js]
 [browser_sanitize-timespans.js]
 [browser_sanitizeDialog.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/sanitize/browser_sanitize-offlineData.js
@@ -0,0 +1,189 @@
+// Bug 380852 - Delete permission manager entries in Clear Recent History
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+const {Sanitizer} = ChromeUtils.import("resource:///modules/Sanitizer.jsm", {});
+
+XPCOMUtils.defineLazyServiceGetter(this, "sas",
+                                   "@mozilla.org/storage/activity-service;1",
+                                   "nsIStorageActivityService");
+XPCOMUtils.defineLazyServiceGetter(this, "swm",
+                                   "@mozilla.org/serviceworkers/manager;1",
+                                   "nsIServiceWorkerManager");
+XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
+                                   "@mozilla.org/dom/quota-manager-service;1",
+                                   "nsIQuotaManagerService");
+
+const oneHour = 3600000000;
+const fiveHours = oneHour * 5;
+
+const itemsToClear = [ "cookies", "offlineApps" ];
+
+function waitForUnregister(host) {
+  return new Promise(resolve => {
+    let listener = {
+      onUnregister: registration => {
+        if (registration.principal.URI.host != host) {
+          return;
+        }
+        let swm = Cc["@mozilla.org/serviceworkers/manager;1"]
+                    .getService(Ci.nsIServiceWorkerManager);
+        swm.removeListener(listener);
+        resolve(registration);
+      }
+    };
+    swm.addListener(listener);
+  });
+}
+
+async function createData(host) {
+  let pageURL = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://" + host) + "sanitize.html";
+
+  return BrowserTestUtils.withNewTab(pageURL, async function(browser) {
+    await ContentTask.spawn(browser, null, () => {
+      return new content.window.Promise(resolve => {
+        let id = content.window.setInterval(() => {
+          if ("foobar" in content.window.localStorage) {
+            content.window.clearInterval(id);
+            resolve(true);
+          }
+        }, 1000);
+      });
+    });
+  });
+}
+
+function moveOriginInTime(principals, endDate, host) {
+  for (let i = 0; i < principals.length; ++i) {
+    let principal = principals.queryElementAt(i, Ci.nsIPrincipal);
+    if (principal.URI.host == host) {
+      sas.moveOriginInTime(principal, endDate - fiveHours);
+      return true;
+    }
+  }
+  return false;
+}
+
+async function getData(host) {
+  let dummyURL = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://" + host) + "dummy_page.html";
+
+  // LocalStorage + IndexedDB
+  let data = await BrowserTestUtils.withNewTab(dummyURL, async function(browser) {
+    return ContentTask.spawn(browser, null, () => {
+      return new content.window.Promise(resolve => {
+        let obj = {
+          localStorage: "foobar" in content.window.localStorage,
+          indexedDB: true,
+          serviceWorker: false,
+        };
+
+        let request = content.window.indexedDB.open("sanitizer_test", 1);
+        request.onupgradeneeded = event => {
+          obj.indexedDB = false;
+        };
+        request.onsuccess = event => {
+          resolve(obj);
+        };
+      });
+    });
+  });
+
+  // ServiceWorkers
+  let serviceWorkers = swm.getAllRegistrations();
+  for (let i = 0; i < serviceWorkers.length; i++) {
+    let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
+    if (sw.principal.URI.host == host) {
+      data.serviceWorker = true;
+      break;
+    }
+  }
+
+  return data;
+}
+
+add_task(async function testWithRange() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["dom.serviceWorkers.enabled", true],
+    ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.testing.enabled", true]
+  ]});
+
+  // The service may have picked up activity from prior tests in this run.
+  // Clear it.
+  sas.testOnlyReset();
+
+  let endDate = Date.now() * 1000;
+  let principals = sas.getActiveOrigins(endDate - oneHour, endDate);
+  is(principals.length, 0, "starting from clear activity state");
+
+  info("sanitize: " + itemsToClear.join(", "));
+  await Sanitizer.sanitize(itemsToClear, {ignoreTimespan: false});
+
+  await createData("example.org");
+  await createData("example.com");
+
+  endDate = Date.now() * 1000;
+  principals = sas.getActiveOrigins(endDate - oneHour, endDate);
+  ok(!!principals, "We have an active origin.");
+  ok(principals.length >= 2, "We have an active origin.");
+
+  let found = 0;
+  for (let i = 0; i < principals.length; ++i) {
+    let principal = principals.queryElementAt(i, Ci.nsIPrincipal);
+    if (principal.URI.host == "example.org" ||
+        principal.URI.host == "example.com") {
+      found++;
+    }
+  }
+
+  is(found, 2, "Our origins are active.");
+
+  let dataPre = await getData("example.org");
+  ok(dataPre.localStorage, "We have localStorage data");
+  ok(dataPre.indexedDB, "We have indexedDB data");
+  ok(dataPre.serviceWorker, "We have serviceWorker data");
+
+  dataPre = await getData("example.com");
+  ok(dataPre.localStorage, "We have localStorage data");
+  ok(dataPre.indexedDB, "We have indexedDB data");
+  ok(dataPre.serviceWorker, "We have serviceWorker data");
+
+  // Let's move example.com in the past.
+  ok(moveOriginInTime(principals, endDate, "example.com"), "Operation completed!");
+
+  let p = waitForUnregister("example.org");
+
+  // Clear it
+  info("sanitize: " + itemsToClear.join(", "));
+  await Sanitizer.sanitize(itemsToClear, {ignoreTimespan: false});
+  await p;
+
+  let dataPost = await getData("example.org");
+  ok(!dataPost.localStorage, "We don't have localStorage data");
+  ok(!dataPost.indexedDB, "We don't have indexedDB data");
+  ok(!dataPost.serviceWorker, "We don't have serviceWorker data");
+
+  dataPost = await getData("example.com");
+  ok(dataPost.localStorage, "We still have localStorage data");
+  ok(dataPost.indexedDB, "We still have indexedDB data");
+  ok(dataPost.serviceWorker, "We still have serviceWorker data");
+
+  // We have to move example.com in the past because how we check IDB triggers
+  // a storage activity.
+  ok(moveOriginInTime(principals, endDate, "example.com"), "Operation completed!");
+
+  // Let's call the clean up again.
+  info("sanitize again to ensure clearing doesn't expand the activity scope");
+  await Sanitizer.sanitize(itemsToClear, {ignoreTimespan: false});
+
+  dataPost = await getData("example.com");
+  ok(dataPost.localStorage, "We still have localStorage data");
+  ok(dataPost.indexedDB, "We still have indexedDB data");
+  ok(dataPost.serviceWorker, "We still have serviceWorker data");
+
+  dataPost = await getData("example.org");
+  ok(!dataPost.localStorage, "We don't have localStorage data");
+  ok(!dataPost.indexedDB, "We don't have indexedDB data");
+  ok(!dataPost.serviceWorker, "We don't have serviceWorker data");
+
+  sas.testOnlyReset();
+});
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/sanitize/sanitize.html
@@ -0,0 +1,41 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
+</head>
+<body>
+  <script>
+
+// indexedDB
+let p = new Promise(resolve => {
+  let request = indexedDB.open("sanitizer_test", 1);
+  request.onupgradeneeded = event => {
+    let db = event.target.result;
+    event.target.onsuccess = resolve;
+    db.createObjectStore("foo", { autoIncrement: true });
+    db.createObjectStore("bar", { autoIncrement: true });
+  };
+});
+
+// ServiceWorker
+p.then(() => {
+  return navigator.serviceWorker.register("dummy.js")
+                .then(r => {
+    return new Promise(resolve => {
+      let worker = r.installing;
+      worker.addEventListener("statechange", () => {
+        if (worker.state === "installed") {
+          resolve(true);
+        }
+      });
+    });
+  });
+})
+
+// localStorage
+.then(() => {
+  localStorage.foobar = "hello world!";
+});
+
+  </script>
+</body>
+</html>
--- a/dom/interfaces/storage/nsIStorageActivityService.idl
+++ b/dom/interfaces/storage/nsIStorageActivityService.idl
@@ -27,13 +27,16 @@ interface nsIStorageActivityService : ns
   // Firefox was started.  All codebase principals are logged, which includes
   // non-system principals like "moz-extension://ID", "moz-safe-about:home",
   // "about:newtab", so principals may need to be filtered before being used.
   nsIArray getActiveOrigins(in PRTime from, in PRTime to);
 
   // NOTE: This method is meant to be used for testing only.
   // The activity of |origin| is moved to the specified timestamp |when|.
   void moveOriginInTime(in nsIPrincipal origin, in PRTime when);
+
+  // TEST-ONLY method to support clearing all previously known activity.
+  void testOnlyReset();
 };
 
 %{ C++
 #define STORAGE_ACTIVITY_SERVICE_CONTRACTID "@mozilla.org/storage/activity-service;1"
 %}
--- a/dom/storage/StorageActivityService.cpp
+++ b/dom/storage/StorageActivityService.cpp
@@ -291,16 +291,23 @@ StorageActivityService::MoveOriginInTime
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   mActivities.Put(origin, aWhen / PR_USEC_PER_SEC);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+StorageActivityService::TestOnlyReset()
+{
+  mActivities.Clear();
+  return NS_OK;
+}
+
 NS_INTERFACE_MAP_BEGIN(StorageActivityService)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStorageActivityService)
   NS_INTERFACE_MAP_ENTRY(nsIStorageActivityService)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END