Bug 1546296 - Correctly clear Service Workers by hostname. r=baku
☠☠ backed out by f06c7f8ed1f1 ☠ ☠
authorJohann Hofmann <jhofmann@mozilla.com>
Thu, 09 May 2019 20:09:04 +0000
changeset 532115 dd551956b3329ccf67cd8d6f279b93f04f79eeab
parent 532114 ff8ab3c73de5155f8ed095acffc3ab62f66fdc02
child 532116 374e8e43a94edb8c8ca4f067084048f372edf561
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1546296
milestone68.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 1546296 - Correctly clear Service Workers by hostname. r=baku Differential Revision: https://phabricator.services.mozilla.com/D30455
toolkit/components/cleardata/ClearDataService.jsm
toolkit/components/cleardata/SiteDataTestUtils.jsm
toolkit/components/cleardata/moz.build
toolkit/components/cleardata/tests/browser/browser.ini
toolkit/components/cleardata/tests/browser/browser_serviceworkers.js
toolkit/components/cleardata/tests/browser/worker.js
--- a/toolkit/components/cleardata/ClearDataService.jsm
+++ b/toolkit/components/cleardata/ClearDataService.jsm
@@ -357,23 +357,20 @@ const QuotaCleaner = {
     // localStorage: The legacy LocalStorage implementation that will
     // eventually be removed depends on this observer notification to clear by
     // host.  Some other subsystems like Reporting headers depend on this too.
     Services.obs.notifyObservers(null, "extension:purge-localStorage", aHost);
 
     // Clear sessionStorage
     Services.obs.notifyObservers(null, "browser:purge-sessionStorage", aHost);
 
-    let exceptionThrown = false;
-
     // ServiceWorkers: they must be removed before cleaning QuotaManager.
-    return Promise.all([
-      ServiceWorkerCleanUp.removeFromHost("http://" + aHost).catch(_ => { exceptionThrown = true; }),
-      ServiceWorkerCleanUp.removeFromHost("https://" + aHost).catch(_ => { exceptionThrown = true; }),
-    ]).then(() => {
+    return ServiceWorkerCleanUp.removeFromHost(aHost)
+      .then(_ => /* exceptionThrown = */ false, _ => /* exceptionThrown = */ true)
+      .then(exceptionThrown => {
         // QuotaManager: In the event of a failure, we call reject to propagate
         // the error upwards.
 
         // delete data from both HTTP and HTTPS sites
         let httpURI = Services.io.newURI("http://" + aHost);
         let httpsURI = Services.io.newURI("https://" + aHost);
         let httpPrincipal = Services.scriptSecurityManager
                                      .createCodebasePrincipal(httpURI, aOriginAttributes);
--- a/toolkit/components/cleardata/SiteDataTestUtils.jsm
+++ b/toolkit/components/cleardata/SiteDataTestUtils.jsm
@@ -97,17 +97,17 @@ var SiteDataTestUtils = {
   addServiceWorker(path) {
     let uri = Services.io.newURI(path);
     // Register a dummy ServiceWorker.
     return BrowserTestUtils.withNewTab(uri.prePath, async function(browser) {
       return ContentTask.spawn(browser, {path}, async ({path: p}) => {
         // eslint-disable-next-line no-undef
         let r = await content.navigator.serviceWorker.register(p);
         return new Promise(resolve => {
-          let worker = r.installing;
+          let worker = r.installing || r.waiting || r.active;
           worker.addEventListener("statechange", () => {
             if (worker.state === "installed") {
               resolve();
             }
           });
         });
       });
     });
--- a/toolkit/components/cleardata/moz.build
+++ b/toolkit/components/cleardata/moz.build
@@ -20,14 +20,16 @@ EXTRA_JS_MODULES += [
 ]
 
 XPCOM_MANIFESTS += [
     'components.conf',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
+BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
+
 include('/ipc/chromium/chromium-config.mozbuild')
 
 with Files('**'):
     BUG_COMPONENT = ('Toolkit', 'Data Sanitization')
 
 FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/toolkit/components/cleardata/tests/browser/browser.ini
@@ -0,0 +1,2 @@
+[browser_serviceworkers.js]
+support-files = worker.js
new file mode 100644
--- /dev/null
+++ b/toolkit/components/cleardata/tests/browser/browser_serviceworkers.js
@@ -0,0 +1,96 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const {SiteDataTestUtils} = ChromeUtils.import("resource://testing-common/SiteDataTestUtils.jsm");
+
+function addServiceWorker(origin) {
+  let swURL = getRootDirectory(gTestPath).replace("chrome://mochitests/content", origin) + "worker.js";
+  return SiteDataTestUtils.addServiceWorker(swURL);
+}
+
+add_task(async function test_deleteFromHost() {
+  await addServiceWorker("https://example.com");
+  await addServiceWorker("https://example.org");
+
+  await TestUtils.waitForCondition(() => SiteDataTestUtils.hasServiceWorkers("https://example.com"), "example.com has a service worker");
+  ok(true, "example.com has a service worker");
+
+  await TestUtils.waitForCondition(() => SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has a service worker");
+  ok(true, "example.org has a service worker");
+
+  await new Promise(aResolve => {
+    Services.clearData.deleteDataFromHost("example.com", true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA, value => {
+      Assert.equal(value, 0);
+      aResolve();
+    });
+  });
+
+  ok(!SiteDataTestUtils.hasServiceWorkers("https://example.com"), "example.com has no service worker");
+  ok(SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has a service worker");
+
+  await new Promise(aResolve => {
+    Services.clearData.deleteDataFromHost("example.org", true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA, value => {
+      Assert.equal(value, 0);
+      aResolve();
+    });
+  });
+
+  ok(!SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has no service worker");
+});
+
+add_task(async function test_deleteFromPrincipal() {
+  await addServiceWorker("https://example.com");
+  await addServiceWorker("https://example.org");
+
+  await TestUtils.waitForCondition(() => SiteDataTestUtils.hasServiceWorkers("https://example.com"), "example.com has a service worker");
+  ok(true, "example.com has a service worker");
+
+  await TestUtils.waitForCondition(() => SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has a service worker");
+  ok(true, "example.org has a service worker");
+
+  let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://example.com/");
+  await new Promise(aResolve => {
+    Services.clearData.deleteDataFromPrincipal(principal, true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA, value => {
+      Assert.equal(value, 0);
+      aResolve();
+    });
+  });
+
+  ok(!SiteDataTestUtils.hasServiceWorkers("https://example.com"), "example.com has no service worker");
+  ok(SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has a service worker");
+
+  principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://example.org/");
+  await new Promise(aResolve => {
+    Services.clearData.deleteDataFromPrincipal(principal, true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA, value => {
+      Assert.equal(value, 0);
+      aResolve();
+    });
+  });
+
+  ok(!SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has no service worker");
+});
+
+add_task(async function test_deleteAll() {
+  await addServiceWorker("https://example.com");
+  await addServiceWorker("https://example.org");
+
+  await TestUtils.waitForCondition(() => SiteDataTestUtils.hasServiceWorkers("https://example.com"), "example.com has a service worker");
+  ok(true, "example.com has a service worker");
+
+  await TestUtils.waitForCondition(() => SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has a service worker");
+  ok(true, "example.org has a service worker");
+
+  await new Promise(aResolve => {
+    Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_DOM_QUOTA, value => {
+      Assert.equal(value, 0);
+      aResolve();
+    });
+  });
+
+  ok(!SiteDataTestUtils.hasServiceWorkers("https://example.com"), "example.com has no service worker");
+  ok(!SiteDataTestUtils.hasServiceWorkers("https://example.org"), "example.org has no service worker");
+
+  await SiteDataTestUtils.clear();
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/cleardata/tests/browser/worker.js
@@ -0,0 +1,1 @@
+console.log("hello");