diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index e5f66ff2fb28..77beae0f4853 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -1933,10 +1933,6 @@ void ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc) { AssertIsOnMainThread(); - if (!Preferences::GetBool("dom.serviceWorkers.enabled")) { - return; - } - nsRefPtr registration = GetServiceWorkerRegistrationInfo(aDoc); if (registration) { @@ -1948,14 +1944,35 @@ ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc) } } +class ServiceWorkerActivateAfterUnloadingJob MOZ_FINAL : public ServiceWorkerJob +{ + nsRefPtr mRegistration; +public: + ServiceWorkerActivateAfterUnloadingJob(ServiceWorkerJobQueue* aQueue, + ServiceWorkerRegistrationInfo* aReg) + : ServiceWorkerJob(aQueue) + , mRegistration(aReg) + { } + + void + Start() + { + if (mRegistration->mPendingUninstall) { + mRegistration->Clear(); + nsRefPtr swm = ServiceWorkerManager::GetInstance(); + swm->RemoveRegistration(mRegistration); + } else { + mRegistration->TryToActivate(); + } + + Done(NS_OK); + } +}; + void ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc) { MOZ_ASSERT(aDoc); - if (!Preferences::GetBool("dom.serviceWorkers.enabled")) { - return; - } - nsRefPtr registration; mControlledDocuments.Remove(aDoc, getter_AddRefs(registration)); // A document which was uncontrolled does not maintain that state itself, so @@ -1963,6 +1980,14 @@ ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc) // associated registration. So this check is required. if (registration) { registration->StopControllingADocument(); + if (!registration->IsControllingDocuments()) { + ServiceWorkerJobQueue* queue = GetOrCreateJobQueue(registration->mScope); + // The remaining tasks touch registration->mPendingUninstall, so queue + // them up in a job. + nsRefPtr job = + new ServiceWorkerActivateAfterUnloadingJob(queue, registration); + queue->Append(job); + } } } diff --git a/dom/workers/ServiceWorkerManager.h b/dom/workers/ServiceWorkerManager.h index e9c92be64792..0fc0bf6e6372 100644 --- a/dom/workers/ServiceWorkerManager.h +++ b/dom/workers/ServiceWorkerManager.h @@ -290,12 +290,13 @@ class ServiceWorkerManager MOZ_FINAL , public nsIIPCBackgroundChildCreateCallback { friend class ActivationRunnable; - friend class ServiceWorkerRegistrationInfo; - friend class ServiceWorkerRegisterJob; friend class GetReadyPromiseRunnable; friend class GetRegistrationsRunnable; friend class GetRegistrationRunnable; friend class QueueFireUpdateFoundRunnable; + friend class ServiceWorkerActivateAfterUnloadingJob; + friend class ServiceWorkerRegisterJob; + friend class ServiceWorkerRegistrationInfo; friend class ServiceWorkerUnregisterJob; public: @@ -349,6 +350,8 @@ public: void RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration) { + MOZ_ASSERT(aRegistration); + MOZ_ASSERT(!aRegistration->IsControllingDocuments()); MOZ_ASSERT(mServiceWorkerRegistrationInfos.Contains(aRegistration->mScope)); ServiceWorkerManager::RemoveScope(mOrderedScopes, aRegistration->mScope); mServiceWorkerRegistrationInfos.Remove(aRegistration->mScope); diff --git a/dom/workers/test/serviceworkers/test_installation_simple.html b/dom/workers/test/serviceworkers/test_installation_simple.html index c0fc0ef3483b..42de8b905e9e 100644 --- a/dom/workers/test/serviceworkers/test_installation_simple.html +++ b/dom/workers/test/serviceworkers/test_installation_simple.html @@ -140,8 +140,7 @@ window.onmessage = null; // We have to make frame navigate away, otherwise it will call // MaybeStopControlling() when this document is unloaded. At that point - // the pref has been disabled, and so MaybeStopControlling() will just - // return since it is currently gated. + // the pref has been disabled, so the ServiceWorkerManager is not available. frame.setAttribute("src", new URL("about:blank").href); resolve(); } else if (e.data.type == "check") {