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 668885 14cf84cd05639c0bd7db54118102b1742e90cadf
parent 668884 9f05ef54c84d9b63fb3ad2dd2916df34cb35df8d
child 668888 40023b79401d49e45e1eb53acb2b96976f24a939
push id81146
push userbmo:topwu.tw@gmail.com
push dateFri, 22 Sep 2017 05:24:51 +0000
reviewersbkelly
bugs1047098
milestone58.0a1
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();