Bug 1523272 - Add unit tests for the SiteDataManager. r=baku
☠☠ backed out by 8d5ede86ee6e ☠ ☠
authorJohann Hofmann <jhofmann@mozilla.com>
Thu, 14 Feb 2019 15:22:37 +0000
changeset 459148 bbd8f0b2e3b2b3f9a58e88215dd0cdb96110884e
parent 459147 bf2ec5cdc33be29622d03a6caddc500476604bbe
child 459149 80d103201d1da15230b393da7c7a35735336c0dc
push id35556
push userdvarga@mozilla.com
push dateFri, 15 Feb 2019 01:38:24 +0000
treeherdermozilla-central@b29c87add05f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1523272
milestone67.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 1523272 - Add unit tests for the SiteDataManager. r=baku Differential Revision: https://phabricator.services.mozilla.com/D17871
browser/base/content/test/sanitize/SiteDataTestUtils.jsm
browser/base/content/test/sanitize/browser_cookiePermission.js
browser/modules/test/unit/test_SiteDataManager.js
browser/modules/test/unit/xpcshell.ini
--- a/browser/base/content/test/sanitize/SiteDataTestUtils.jsm
+++ b/browser/base/content/test/sanitize/SiteDataTestUtils.jsm
@@ -10,66 +10,81 @@ const {ContentTask} = ChromeUtils.import
 const {BrowserTestUtils} = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
 
 const {Sanitizer} = ChromeUtils.import("resource:///modules/Sanitizer.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "swm",
                                    "@mozilla.org/serviceworkers/manager;1",
                                    "nsIServiceWorkerManager");
 
+XPCOMUtils.defineLazyGlobalGetters(this, ["indexedDB", "Blob"]);
+
 /**
  * This module assists with tasks around testing functionality that shows
  * or clears site data.
  *
  * Please note that you will have to clean up changes made manually, for
  * example using SiteDataTestUtils.clear().
  */
 var SiteDataTestUtils = {
 
   /**
-   * Adds a new entry to a dummy indexedDB database for the specified origin.
+   * Makes an origin have persistent data storage.
+   *
+   * @param {String} origin - the origin of the site to give persistent storage
+   *
+   * @returns a Promise that resolves when storage was persisted
+   */
+  persist(origin, value = Services.perms.ALLOW_ACTION) {
+    return new Promise(resolve => {
+      let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
+      Services.perms.addFromPrincipal(principal, "persistent-storage", value);
+      Services.qms.persist(principal).callback = () => resolve();
+    });
+  },
+
+  /**
+   * Adds a new blob entry to a dummy indexedDB database for the specified origin.
    *
    * @param {String} origin - the origin of the site to add test data for
-   * @param {String} name [optional] - the entry key
-   * @param {String} value [optional] - the entry value
-   * @param {Object} originAttributes [optional] - the originAttributes
+   * @param {Number} size [optional] - the size of the entry in bytes
    *
    * @returns a Promise that resolves when the data was added successfully.
    */
-  addToIndexedDB(origin, key = "foo", value = "bar", originAttributes = {}) {
+  addToIndexedDB(origin, size = 1024) {
     return new Promise(resolve => {
-      let uri = Services.io.newURI(origin);
-      let principal =
-        Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes);
+      let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
       let request = indexedDB.openForPrincipal(principal, "TestDatabase", 1);
       request.onupgradeneeded = function(e) {
         let db = e.target.result;
-        db.createObjectStore("TestStore", { keyPath: "id" });
+        db.createObjectStore("TestStore");
       };
       request.onsuccess = function(e) {
         let db = e.target.result;
         let tx = db.transaction("TestStore", "readwrite");
         let store = tx.objectStore("TestStore");
         tx.oncomplete = resolve;
-        store.put({ id: key, description: value});
+        let buffer = new ArrayBuffer(size);
+        let blob = new Blob([buffer]);
+        store.add(blob, Cu.now());
       };
     });
   },
 
   /**
    * Adds a new cookie for the specified origin, with the specified contents.
    * The cookie will be valid for one day.
    *
    * @param {String} origin - the origin of the site to add test data for
    * @param {String} name [optional] - the cookie name
    * @param {String} value [optional] - the cookie value
    */
   addToCookies(origin, name = "foo", value = "bar") {
-    let uri = Services.io.newURI(origin);
-    Services.cookies.add(uri.host, uri.pathQueryRef, name, value,
+    let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
+    Services.cookies.add(principal.URI.host, principal.URI.pathQueryRef, name, value,
       false, false, false, Date.now() + 24000 * 60 * 60, {},
       Ci.nsICookie2.SAMESITE_UNSET);
   },
 
   /**
    * Adds a new serviceworker with the specified path. Note that this
    * method will open a new tab at the domain of the SW path to that effect.
    *
@@ -116,18 +131,17 @@ var SiteDataTestUtils = {
   /**
    * Gets the current quota usage for the specified origin.
    *
    * @returns a Promise that resolves to an integer with the total
    *          amount of disk usage by a given origin.
    */
   getQuotaUsage(origin) {
     return new Promise(resolve => {
-      let uri = Services.io.newURI(origin);
-      let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
+      let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
       Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage));
     });
   },
 
   /**
    * Cleans up all site data.
    */
   clear() {
--- a/browser/base/content/test/sanitize/browser_cookiePermission.js
+++ b/browser/base/content/test/sanitize/browser_cookiePermission.js
@@ -13,18 +13,19 @@ function checkDataForAboutURL() {
     };
     request.onsuccess = function(e) {
       resolve(data);
     };
   });
 }
 
 function createIndexedDB(host, originAttributes) {
-  return SiteDataTestUtils.addToIndexedDB("https://" + host, "foo", "bar",
-                                          originAttributes);
+  let uri = Services.io.newURI("https://" + host);
+  let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes);
+  return SiteDataTestUtils.addToIndexedDB(principal.origin);
 }
 
 function checkIndexedDB(host, originAttributes) {
   return new Promise(resolve => {
     let data = true;
     let uri = Services.io.newURI("https://" + host);
     let principal =
       Services.scriptSecurityManager.createCodebasePrincipal(uri,
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/test_SiteDataManager.js
@@ -0,0 +1,148 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+"use strict";
+
+const EXAMPLE_ORIGIN = "https://www.example.com";
+const EXAMPLE_ORIGIN_2 = "https://example.org";
+
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const {SiteDataManager} = ChromeUtils.import("resource:///modules/SiteDataManager.jsm");
+const {SiteDataTestUtils} = ChromeUtils.import("resource://testing-common/SiteDataTestUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "setTimeout", "resource://gre/modules/Timer.jsm");
+ChromeUtils.defineModuleGetter(this, "TestUtils", "resource://testing-common/TestUtils.jsm");
+
+add_task(function setup() {
+  do_get_profile();
+});
+
+add_task(async function testGetSites() {
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
+  await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
+
+  await SiteDataManager.updateSites();
+
+  let sites = await SiteDataManager.getSites();
+
+  let site1 = sites.find((site) => site.baseDomain == "example.com");
+  let site2 = sites.find((site) => site.baseDomain == "example.org");
+
+  Assert.equal(site1.baseDomain, "example.com", "Has the correct base domain for example.com");
+  Assert.equal(site1.host, "www.example.com", "Has the correct host for example.com");
+  Assert.greater(site1.usage, 4096, "Has correct usage for example.com");
+  Assert.equal(site1.persisted, false, "example.com is not persisted");
+  Assert.equal(site1.cookies.length, 2, "Has correct number of cookies for example.com");
+  Assert.ok(typeof site1.lastAccessed.getDate == "function", "lastAccessed for example.com is a Date");
+  Assert.ok(site1.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.com happened recently");
+
+  Assert.equal(site2.baseDomain, "example.org", "Has the correct base domain for example.org");
+  Assert.equal(site2.host, "example.org", "Has the correct host for example.org");
+  Assert.greater(site2.usage, 2048, "Has correct usage for example.org");
+  Assert.equal(site2.persisted, true, "example.org is persisted");
+  Assert.equal(site2.cookies.length, 1, "Has correct number of cookies for example.org");
+  Assert.ok(typeof site2.lastAccessed.getDate == "function", "lastAccessed for example.org is a Date");
+  Assert.ok(site2.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.org happened recently");
+
+  await SiteDataTestUtils.clear();
+});
+
+add_task(async function testGetTotalUsage() {
+  await SiteDataManager.updateSites();
+  let sites = await SiteDataManager.getSites();
+  Assert.equal(sites.length, 0, "SiteDataManager is empty");
+
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
+
+  await SiteDataManager.updateSites();
+
+  let usage = await SiteDataManager.getTotalUsage();
+
+  Assert.greater(usage, 4096 + 2048, "Has the correct total usage.");
+
+  await SiteDataTestUtils.clear();
+});
+
+add_task(async function testRemove() {
+  await SiteDataManager.updateSites();
+
+  let uri = Services.io.newURI(EXAMPLE_ORIGIN);
+  Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION);
+
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
+  await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
+
+  await SiteDataManager.updateSites();
+
+  let sites = await SiteDataManager.getSites();
+
+  Assert.equal(sites.length, 2, "Has two sites.");
+
+  await SiteDataManager.remove(["www.example.com"]);
+
+  sites = await SiteDataManager.getSites();
+
+  Assert.equal(sites.length, 1, "Has one site.");
+  Assert.equal(sites[0].host, "example.org", "Has not cleared data for example.org");
+
+  let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN);
+  Assert.equal(usage, 0, "Has cleared quota usage for example.com");
+
+  let cookies = Services.cookies.countCookiesFromHost("example.com");
+  Assert.equal(cookies, 0, "Has cleared cookies for example.com");
+
+  let perm = Services.perms.testPermission(uri, "persistent-storage");
+  Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission.");
+  perm = Services.perms.testPermission(uri, "camera");
+  Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions.");
+
+  Services.perms.remove(uri, "camera");
+});
+
+add_task(async function testRemoveSiteData() {
+  let uri = Services.io.newURI(EXAMPLE_ORIGIN);
+  Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION);
+
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
+  SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
+  await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
+  await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
+
+  await SiteDataManager.updateSites();
+
+  let sites = await SiteDataManager.getSites();
+
+  Assert.equal(sites.length, 2, "Has two sites.");
+
+  await SiteDataManager.removeSiteData();
+
+  sites = await SiteDataManager.getSites();
+
+  Assert.equal(sites.length, 0, "Has no sites.");
+
+  let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN);
+  Assert.equal(usage, 0, "Has cleared quota usage for example.com");
+
+  usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN_2);
+  Assert.equal(usage, 0, "Has cleared quota usage for example.org");
+
+  let cookies = Services.cookies.countCookiesFromHost("example.org");
+  Assert.equal(cookies, 0, "Has cleared cookies for example.org");
+
+  let perm = Services.perms.testPermission(uri, "persistent-storage");
+  Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission.");
+  perm = Services.perms.testPermission(uri, "camera");
+  Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions.");
+
+  Services.perms.remove(uri, "camera");
+});
--- a/browser/modules/test/unit/xpcshell.ini
+++ b/browser/modules/test/unit/xpcshell.ini
@@ -3,10 +3,11 @@ head =
 firefox-appdir = browser
 skip-if = toolkit == 'android'
 
 [test_E10SUtils_nested_URIs.js]
 [test_HomePage.js]
 [test_LiveBookmarkMigrator.js]
 [test_Sanitizer_interrupted.js]
 [test_SitePermissions.js]
+[test_SiteDataManager.js]
 [test_LaterRun.js]
 [test_discovery.js]