Bug 1228277 - Part 1: Track service worker scripts during evaluation in ServiceWorkerRegistrationInfo. r=asuth, a=sledru
authorBen Kelly <ben@wanderview.com>
Wed, 27 Jul 2016 19:09:15 -0400
changeset 342152 156642ee5fb493be95338d680f5dccfb6acd26cf
parent 342151 52ed81c056013146ae61522464bca83f70d486d8
child 342153 a4aeae74f3ca866d348c057717e28304e288f115
push id1183
push userraliiev@mozilla.com
push dateMon, 05 Sep 2016 20:01:49 +0000
treeherdermozilla-release@3148731bed45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth, sledru
bugs1228277
milestone49.0a2
Bug 1228277 - Part 1: Track service worker scripts during evaluation in ServiceWorkerRegistrationInfo. r=asuth, a=sledru
dom/workers/ServiceWorkerRegistrationInfo.cpp
dom/workers/ServiceWorkerRegistrationInfo.h
dom/workers/ServiceWorkerUpdateJob.cpp
dom/workers/ServiceWorkerUpdateJob.h
--- a/dom/workers/ServiceWorkerRegistrationInfo.cpp
+++ b/dom/workers/ServiceWorkerRegistrationInfo.cpp
@@ -39,16 +39,20 @@ public:
   }
 };
 
 } // anonymous namespace
 
 void
 ServiceWorkerRegistrationInfo::Clear()
 {
+  if (mEvaluatingWorker) {
+    mEvaluatingWorker = nullptr;
+  }
+
   if (mInstallingWorker) {
     mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
     mInstallingWorker->WorkerPrivate()->NoteDeadServiceWorkerInfo();
     mInstallingWorker = nullptr;
     // FIXME(nsm): Abort any inflight requests from installing worker.
   }
 
   if (mWaitingWorker) {
@@ -181,18 +185,22 @@ ServiceWorkerRegistrationInfo::RemoveLis
   mListeners.RemoveElement(aListener);
 
   return NS_OK;
 }
 
 already_AddRefed<ServiceWorkerInfo>
 ServiceWorkerRegistrationInfo::GetServiceWorkerInfoById(uint64_t aId)
 {
+  AssertIsOnMainThread();
+
   RefPtr<ServiceWorkerInfo> serviceWorker;
-  if (mInstallingWorker && mInstallingWorker->ID() == aId) {
+  if (mEvaluatingWorker && mEvaluatingWorker->ID() == aId) {
+    serviceWorker = mEvaluatingWorker;
+  } else if (mInstallingWorker && mInstallingWorker->ID() == aId) {
     serviceWorker = mInstallingWorker;
   } else if (mWaitingWorker && mWaitingWorker->ID() == aId) {
     serviceWorker = mWaitingWorker;
   } else if (mActiveWorker && mActiveWorker->ID() == aId) {
     serviceWorker = mActiveWorker;
   }
 
   return serviceWorker.forget();
@@ -359,16 +367,23 @@ ServiceWorkerRegistrationInfo::CheckAndC
                 IsLastUpdateCheckTimeOverOneDay());
 
   mUpdateState = NoUpdate;
 
   return result;
 }
 
 ServiceWorkerInfo*
+ServiceWorkerRegistrationInfo::GetEvaluating() const
+{
+  AssertIsOnMainThread();
+  return mEvaluatingWorker;
+}
+
+ServiceWorkerInfo*
 ServiceWorkerRegistrationInfo::GetInstalling() const
 {
   AssertIsOnMainThread();
   return mInstallingWorker;
 }
 
 ServiceWorkerInfo*
 ServiceWorkerRegistrationInfo::GetWaiting() const
@@ -380,39 +395,63 @@ ServiceWorkerRegistrationInfo::GetWaitin
 ServiceWorkerInfo*
 ServiceWorkerRegistrationInfo::GetActive() const
 {
   AssertIsOnMainThread();
   return mActiveWorker;
 }
 
 void
+ServiceWorkerRegistrationInfo::SetEvaluating(ServiceWorkerInfo* aServiceWorker)
+{
+  AssertIsOnMainThread();
+  MOZ_ASSERT(aServiceWorker);
+  MOZ_ASSERT(!mEvaluatingWorker);
+  MOZ_ASSERT(!mInstallingWorker);
+  MOZ_ASSERT(mWaitingWorker != aServiceWorker);
+  MOZ_ASSERT(mActiveWorker != aServiceWorker);
+
+  mEvaluatingWorker = aServiceWorker;
+}
+
+void
+ServiceWorkerRegistrationInfo::ClearEvaluating()
+{
+  AssertIsOnMainThread();
+
+  if (!mEvaluatingWorker) {
+    return;
+  }
+
+  mEvaluatingWorker->UpdateState(ServiceWorkerState::Redundant);
+  mEvaluatingWorker = nullptr;
+}
+
+void
 ServiceWorkerRegistrationInfo::ClearInstalling()
 {
   AssertIsOnMainThread();
 
   if (!mInstallingWorker) {
     return;
   }
 
   mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
   mInstallingWorker = nullptr;
   NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER);
 }
 
 void
-ServiceWorkerRegistrationInfo::SetInstalling(ServiceWorkerInfo* aServiceWorker)
+ServiceWorkerRegistrationInfo::TransitionEvaluatingToInstalling()
 {
   AssertIsOnMainThread();
-  MOZ_ASSERT(aServiceWorker);
+  MOZ_ASSERT(mEvaluatingWorker);
   MOZ_ASSERT(!mInstallingWorker);
-  MOZ_ASSERT(mWaitingWorker != aServiceWorker);
-  MOZ_ASSERT(mActiveWorker != aServiceWorker);
 
-  mInstallingWorker = aServiceWorker;
+  mInstallingWorker = mEvaluatingWorker.forget();
   mInstallingWorker->UpdateState(ServiceWorkerState::Installing);
   NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER);
 }
 
 void
 ServiceWorkerRegistrationInfo::TransitionInstallingToWaiting()
 {
   AssertIsOnMainThread();
--- a/dom/workers/ServiceWorkerRegistrationInfo.h
+++ b/dom/workers/ServiceWorkerRegistrationInfo.h
@@ -22,16 +22,17 @@ class ServiceWorkerRegistrationInfo fina
   {
     NoUpdate,
     NeedTimeCheckAndUpdate,
     NeedUpdate
   } mUpdateState;
 
   uint64_t mLastUpdateCheckTime;
 
+  RefPtr<ServiceWorkerInfo> mEvaluatingWorker;
   RefPtr<ServiceWorkerInfo> mActiveWorker;
   RefPtr<ServiceWorkerInfo> mWaitingWorker;
   RefPtr<ServiceWorkerInfo> mInstallingWorker;
 
   virtual ~ServiceWorkerRegistrationInfo();
 
 public:
   NS_DECL_ISUPPORTS
@@ -117,37 +118,49 @@ public:
 
   void
   MaybeScheduleUpdate();
 
   bool
   CheckAndClearIfUpdateNeeded();
 
   ServiceWorkerInfo*
+  GetEvaluating() const;
+
+  ServiceWorkerInfo*
   GetInstalling() const;
 
   ServiceWorkerInfo*
   GetWaiting() const;
 
   ServiceWorkerInfo*
   GetActive() const;
 
+  // Set the given worker as the evaluating service worker.  The worker
+  // state is not changed.
+  void
+  SetEvaluating(ServiceWorkerInfo* aServiceWorker);
+
+  // Remove an existing evaluating worker, if present.  The worker will
+  // be transitioned to the Redundant state.
+  void
+  ClearEvaluating();
+
   // Remove an existing installing worker, if present.  The worker will
   // be transitioned to the Redundant state.
   void
   ClearInstalling();
 
-  // Set a new installing worker.  This may only be called if there is no
-  // existing installing worker.  The worker is transitioned to the Installing
-  // state.
+  // Transition the current evaluating worker to be the installing worker.  The
+  // worker's state is update to Installing.
   void
-  SetInstalling(ServiceWorkerInfo* aServiceWorker);
+  TransitionEvaluatingToInstalling();
 
   // Transition the current installing worker to be the waiting worker.  The
-  // workers state is updated to Installed.
+  // worker's state is updated to Installed.
   void
   TransitionInstallingToWaiting();
 
   // Override the current active worker.  This is used during browser
   // initialization to load persisted workers.  Its also used to propagate
   // active workers across child processes in e10s.  This second use will
   // go away once the ServiceWorkerManager moves to the parent process.
   // The worker is transitioned to the Activated state.
--- a/dom/workers/ServiceWorkerUpdateJob.cpp
+++ b/dom/workers/ServiceWorkerUpdateJob.cpp
@@ -205,31 +205,25 @@ ServiceWorkerUpdateJob::FailUpdateJob(Er
   // step 12 of the Install algorithm.
   //
   //  https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#installation-algorithm
   //
   // The spec currently only runs this after an install event fails,
   // but we must handle many more internal errors.  So we check for
   // cleanup on every non-successful exit.
   if (mRegistration) {
-    if (mServiceWorker) {
-      mServiceWorker->UpdateState(ServiceWorkerState::Redundant);
-      serviceWorkerScriptCache::PurgeCache(mRegistration->mPrincipal,
-                                           mServiceWorker->CacheName());
-    }
-
+    mRegistration->ClearEvaluating();
     mRegistration->ClearInstalling();
 
     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     if (swm) {
       swm->MaybeRemoveRegistration(mRegistration);
     }
   }
 
-  mServiceWorker = nullptr;
   mRegistration = nullptr;
 
   Finish(aRv);
 }
 
 void
 ServiceWorkerUpdateJob::FailUpdateJob(nsresult aRv)
 {
@@ -413,26 +407,28 @@ ServiceWorkerUpdateJob::ComparisonResult
     Finish(NS_OK);
     return;
   }
 
   Telemetry::Accumulate(Telemetry::SERVICE_WORKER_UPDATED, 1);
 
   // Begin step 7 of the Update algorithm to evaluate the new script.
 
-  MOZ_ASSERT(!mServiceWorker);
-  mServiceWorker = new ServiceWorkerInfo(mRegistration->mPrincipal,
-                                         mRegistration->mScope,
-                                         mScriptSpec, aNewCacheName);
+  RefPtr<ServiceWorkerInfo> sw =
+    new ServiceWorkerInfo(mRegistration->mPrincipal,
+                          mRegistration->mScope,
+                          mScriptSpec, aNewCacheName);
+
+  mRegistration->SetEvaluating(sw);
 
   nsMainThreadPtrHandle<ServiceWorkerUpdateJob> handle(
       new nsMainThreadPtrHolder<ServiceWorkerUpdateJob>(this));
   RefPtr<LifeCycleEventCallback> callback = new ContinueUpdateRunnable(handle);
 
-  ServiceWorkerPrivate* workerPrivate = mServiceWorker->WorkerPrivate();
+  ServiceWorkerPrivate* workerPrivate = sw->WorkerPrivate();
   MOZ_ASSERT(workerPrivate);
   rv = workerPrivate->CheckScriptEvaluation(callback);
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     FailUpdateJob(NS_ERROR_DOM_ABORT_ERR);
     return;
   }
 }
@@ -470,19 +466,17 @@ ServiceWorkerUpdateJob::Install()
   MOZ_ASSERT(!Canceled());
 
   MOZ_ASSERT(!mRegistration->GetInstalling());
 
   // Begin step 2 of the Install algorithm.
   //
   //  https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#installation-algorithm
 
-  MOZ_ASSERT(mServiceWorker);
-  mRegistration->SetInstalling(mServiceWorker);
-  mServiceWorker = nullptr;
+  mRegistration->TransitionEvaluatingToInstalling();
 
   // Step 6 of the Install algorithm resolving the job promise.
   InvokeResultCallbacks(NS_OK);
 
   // The job promise cannot be rejected after this point, but the job can
   // still fail; e.g. if the install event handler throws, etc.
 
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
--- a/dom/workers/ServiceWorkerUpdateJob.h
+++ b/dom/workers/ServiceWorkerUpdateJob.h
@@ -88,16 +88,15 @@ private:
   Install();
 
   // Utility method called after the install event is handled.
   void
   ContinueAfterInstallEvent(bool aInstallEventSuccess);
 
   nsCOMPtr<nsILoadGroup> mLoadGroup;
   RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
-  RefPtr<ServiceWorkerInfo> mServiceWorker;
 };
 
 } // namespace workers
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_workers_serviceworkerupdatejob_h