Bug 1445475 - Make service worker self-update fallibly store its timer on the private and cleanup if that fails. r=catalinb
authorBen Kelly <ben@wanderview.com>
Thu, 22 Mar 2018 07:45:00 -0400
changeset 772174 8d0bff47a49993b2cf47c86bec9158bcf9bf8f90
parent 772173 64ea6814aefa9fd84d051982943709a59bb5f883
child 772175 f80a4001d266737752f381658dbeee500bf1c27a
push id103870
push userbmo:ntim.bugs@gmail.com
push dateSun, 25 Mar 2018 10:23:38 +0000
reviewerscatalinb
bugs1445475
milestone61.0a1
Bug 1445475 - Make service worker self-update fallibly store its timer on the private and cleanup if that fails. r=catalinb
dom/serviceworkers/ServiceWorkerPrivate.cpp
dom/serviceworkers/ServiceWorkerPrivate.h
dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
--- a/dom/serviceworkers/ServiceWorkerPrivate.cpp
+++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp
@@ -1949,24 +1949,29 @@ ServiceWorkerPrivate::SpawnWorkerIfNeede
 
   if (aNewWorkerCreated) {
     *aNewWorkerCreated = true;
   }
 
   return NS_OK;
 }
 
-void
-ServiceWorkerPrivate::StoreISupports(nsISupports* aSupports)
+bool
+ServiceWorkerPrivate::MaybeStoreISupports(nsISupports* aSupports)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate);
+
+  if (!mWorkerPrivate) {
+    MOZ_DIAGNOSTIC_ASSERT(mSupportsArray.IsEmpty());
+    return false;
+  }
+
   MOZ_ASSERT(!mSupportsArray.Contains(aSupports));
-
   mSupportsArray.AppendElement(aSupports);
+  return true;
 }
 
 void
 ServiceWorkerPrivate::RemoveISupports(nsISupports* aSupports)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mSupportsArray.RemoveElement(aSupports);
 }
--- a/dom/serviceworkers/ServiceWorkerPrivate.h
+++ b/dom/serviceworkers/ServiceWorkerPrivate.h
@@ -116,18 +116,18 @@ public:
                         const nsAString& aData,
                         const nsAString& aBehavior,
                         const nsAString& aScope);
 
   nsresult
   SendFetchEvent(nsIInterceptedChannel* aChannel, nsILoadGroup* aLoadGroup,
                  const nsAString& aClientId, bool aIsReload);
 
-  void
-  StoreISupports(nsISupports* aSupports);
+  bool
+  MaybeStoreISupports(nsISupports* aSupports);
 
   void
   RemoveISupports(nsISupports* aSupports);
 
   // This will terminate the current running worker thread and drop the
   // workerPrivate reference.
   // Called by ServiceWorkerInfo when [[Clear Registration]] is invoked
   // or whenever the spec mandates that we terminate the worker.
--- a/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
+++ b/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
@@ -390,20 +390,26 @@ public:
                                 SystemGroup::EventTargetFor(TaskCategory::Other));
 
       nsCOMPtr<nsITimer> timer = result.unwrapOr(nullptr);
       if (NS_WARN_IF(!timer)) {
         return NS_OK;
       }
 
       mDelayed = true;
+
       // We're storing the timer object on the calling service worker's private.
       // ServiceWorkerPrivate will drop the reference if the worker terminates,
       // which will cancel the timer.
-      worker->WorkerPrivate()->StoreISupports(timer);
+      if (!worker->WorkerPrivate()->MaybeStoreISupports(timer)) {
+        // The worker thread is already shutting down.  Just cancel the timer
+        // and let the update runnable be destroyed.
+        timer->Cancel();
+        return NS_OK;
+      }
 
       return NS_OK;
     }
 
     RefPtr<WorkerThreadUpdateCallback> cb =
       new WorkerThreadUpdateCallback(mPromiseProxy);
     UpdateInternal(principal, mDescriptor.Scope(), cb);
     return NS_OK;