Bug 1047098 - "Clear Recent History" must clean up all the ServiceWorkers, r=bkelly
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 21 Sep 2017 21:32:00 +0200
changeset 382383 14cf84cd05639c0bd7db54118102b1742e90cadf
parent 382382 9f05ef54c84d9b63fb3ad2dd2916df34cb35df8d
child 382384 40023b79401d49e45e1eb53acb2b96976f24a939
push id32555
push userarchaeopteryx@coole-files.de
push dateFri, 22 Sep 2017 09:43:20 +0000
treeherdermozilla-central@82b2ae0b03ca [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1047098
milestone58.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 1047098 - "Clear Recent History" must clean up all the ServiceWorkers, r=bkelly This includes minor shutdown fixes by :asuth as discussed on https://bugzilla.mozilla.org/show_bug.cgi?id=1047098#c56 and c57.
browser/base/content/sanitize.js
dom/workers/ServiceWorkerRegistrar.cpp
toolkit/components/places/tests/head_common.js
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -15,16 +15,19 @@ XPCOMUtils.defineLazyModuleGetters(this,
   Downloads: "resource://gre/modules/Downloads.jsm",
   DownloadsCommon: "resource:///modules/DownloadsCommon.jsm",
   TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
   console: "resource://gre/modules/Console.jsm",
   setTimeout: "resource://gre/modules/Timer.jsm",
 });
 
 
+XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
+                                   "@mozilla.org/serviceworkers/manager;1",
+                                   "nsIServiceWorkerManager");
 XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
                                    "@mozilla.org/dom/quota-manager-service;1",
                                    "nsIQuotaManagerService");
 
 var {classes: Cc, interfaces: Ci} = Components;
 
 /**
  * A number of iterations after which to yield time back
@@ -288,16 +291,24 @@ Sanitizer.prototype = {
         // AppCache
         Components.utils.import("resource:///modules/offlineAppCache.jsm");
         // This doesn't wait for the cleanup to be complete.
         OfflineAppCacheHelper.clear();
 
         // LocalStorage
         Services.obs.notifyObservers(null, "extension:purge-localStorage");
 
+        // ServiceWorkers
+        let serviceWorkers = serviceWorkerManager.getAllRegistrations();
+        for (let i = 0; i < serviceWorkers.length; i++) {
+          let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
+          let host = sw.principal.URI.host;
+          serviceWorkerManager.removeAndPropagate(host);
+        }
+
         // QuotaManager
         let promises = [];
         await new Promise(resolve => {
           quotaManagerService.getUsage(request => {
             for (let item of request.result) {
               let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
               let uri = principal.URI;
               if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") {
--- a/dom/workers/ServiceWorkerRegistrar.cpp
+++ b/dom/workers/ServiceWorkerRegistrar.cpp
@@ -1056,16 +1056,44 @@ ServiceWorkerRegistrar::ProfileStopped()
                                          getter_AddRefs(mProfileDir));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
   }
 
   PBackgroundChild* child = BackgroundChild::GetForCurrentThread();
   if (!child) {
+    // Mutations to the ServiceWorkerRegistrar happen on the PBackground thread,
+    // issued by the ServiceWorkerManagerService, so the appropriate place to
+    // trigger shutdown is on that thread.
+    //
+    // However, it's quite possible that the PBackground thread was not brought
+    // into existence for xpcshell tests.  We don't cause it to be created
+    // ourselves for any reason, for example.
+    //
+    // In this scenario, we know that:
+    // - We will receive exactly one call to ourself from BlockShutdown() and
+    //   BlockShutdown() will be called (at most) once.
+    // - The only way our Shutdown() method gets called is via
+    //   BackgroundParentImpl::RecvShutdownServiceWorkerRegistrar() being
+    //   invoked, which only happens if we get to that send below here that we
+    //   can't get to.
+    // - All Shutdown() does is set mShuttingDown=true (essential for
+    //   invariants) and invoke MaybeScheduleShutdownCompleted().
+    // - Since there is no PBackground thread, mRunnableCounter must be 0
+    //   because only ScheduleSaveData() increments it and it only runs on the
+    //   background thread, so it cannot have run.  And so we would expect
+    //   MaybeScheduleShutdownCompleted() to schedule an invocation of
+    //   ShutdownCompleted on the main thread.
+    //
+    // So it's appropriate for us to set mShuttingDown=true (as Shutdown would
+    // do) and directly invoke ShutdownCompleted() (as Shutdown would indirectly
+    // do via MaybeScheduleShutdownCompleted).
+    mShuttingDown = true;
+    ShutdownCompleted();
     return;
   }
 
   child->SendShutdownServiceWorkerRegistrar();
 }
 
 // Async shutdown blocker methods
 
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -70,17 +70,17 @@ XPCOMUtils.defineLazyGetter(this, "SMALL
          "0ibm9uZSIvPg0KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjI0LjYiIHI9IjY" +
          "uNCIvPg0KICA8cmVjdCB4PSI0NSIgeT0iMzkuOSIgd2lkdGg9IjEwLjEi" +
          "IGhlaWdodD0iNDEuOCIvPg0KPC9zdmc%2BDQo%3D");
 });
 
 var gTestDir = do_get_cwd();
 
 // Initialize profile.
-var gProfD = do_get_profile();
+var gProfD = do_get_profile(true);
 
 Services.prefs.setBoolPref("browser.urlbar.usepreloadedtopurls.enabled", false);
 do_register_cleanup(() =>
   Services.prefs.clearUserPref("browser.urlbar.usepreloadedtopurls.enabled"));
 
 // Remove any old database.
 clearDB();