Bug 1263307 P3 Move ServiceWorker update logic into central place in ServiceWorkerRegistrationInfo methods. r=jdm

This commit is contained in:
Ben Kelly 2016-04-17 04:29:53 -07:00
Родитель a9a4f7363c
Коммит b3e4dd4541
4 изменённых файлов: 124 добавлений и 95 удалений

Просмотреть файл

@ -6,6 +6,8 @@
#include "ServiceWorkerInfo.h" #include "ServiceWorkerInfo.h"
#include "ServiceWorkerScriptCache.h"
BEGIN_WORKERS_NAMESPACE BEGIN_WORKERS_NAMESPACE
NS_IMPL_ISUPPORTS(ServiceWorkerInfo, nsIServiceWorkerInfo) NS_IMPL_ISUPPORTS(ServiceWorkerInfo, nsIServiceWorkerInfo)
@ -139,6 +141,9 @@ ServiceWorkerInfo::UpdateState(ServiceWorkerState aState)
mState = aState; mState = aState;
nsCOMPtr<nsIRunnable> r = new ChangeStateUpdater(mInstances, mState); nsCOMPtr<nsIRunnable> r = new ChangeStateUpdater(mInstances, mState);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r.forget())); MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r.forget()));
if (mState == ServiceWorkerState::Redundant) {
serviceWorkerScriptCache::PurgeCache(mPrincipal, mCacheName);
}
} }
ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal, ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,

Просмотреть файл

@ -20,36 +20,19 @@ ServiceWorkerRegistrationInfo::Clear()
if (mWaitingWorker) { if (mWaitingWorker) {
mWaitingWorker->UpdateState(ServiceWorkerState::Redundant); mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
nsresult rv = serviceWorkerScriptCache::PurgeCache(mPrincipal,
mWaitingWorker->CacheName());
if (NS_FAILED(rv)) {
NS_WARNING("Failed to purge the waiting cache.");
}
mWaitingWorker->WorkerPrivate()->NoteDeadServiceWorkerInfo(); mWaitingWorker->WorkerPrivate()->NoteDeadServiceWorkerInfo();
mWaitingWorker = nullptr; mWaitingWorker = nullptr;
} }
if (mActiveWorker) { if (mActiveWorker) {
mActiveWorker->UpdateState(ServiceWorkerState::Redundant); mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
nsresult rv = serviceWorkerScriptCache::PurgeCache(mPrincipal,
mActiveWorker->CacheName());
if (NS_FAILED(rv)) {
NS_WARNING("Failed to purge the active cache.");
}
mActiveWorker->WorkerPrivate()->NoteDeadServiceWorkerInfo(); mActiveWorker->WorkerPrivate()->NoteDeadServiceWorkerInfo();
mActiveWorker = nullptr; mActiveWorker = nullptr;
} }
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER |
MOZ_ASSERT(swm); WhichServiceWorker::WAITING_WORKER |
swm->InvalidateServiceWorkerRegistrationWorker(this, WhichServiceWorker::ACTIVE_WORKER);
WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER);
} }
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(const nsACString& aScope, ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(const nsACString& aScope,
@ -204,44 +187,18 @@ ServiceWorkerRegistrationInfo::TryToActivate()
} }
} }
void
ServiceWorkerRegistrationInfo::PurgeActiveWorker()
{
RefPtr<ServiceWorkerInfo> exitingWorker = mActiveWorker.forget();
if (!exitingWorker)
return;
// FIXME(jaoo): Bug 1170543 - Wait for exitingWorker to finish and terminate it.
exitingWorker->UpdateState(ServiceWorkerState::Redundant);
nsresult rv = serviceWorkerScriptCache::PurgeCache(mPrincipal,
exitingWorker->CacheName());
if (NS_FAILED(rv)) {
NS_WARNING("Failed to purge the activating cache.");
}
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, WhichServiceWorker::ACTIVE_WORKER);
}
void void
ServiceWorkerRegistrationInfo::Activate() ServiceWorkerRegistrationInfo::Activate()
{ {
RefPtr<ServiceWorkerInfo> activatingWorker = mWaitingWorker; if (!mWaitingWorker) {
if (!activatingWorker) {
return; return;
} }
PurgeActiveWorker(); TransitionWaitingToActive();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, WhichServiceWorker::WAITING_WORKER);
mActiveWorker = activatingWorker.forget();
mWaitingWorker = nullptr;
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
NotifyListenersOnChange();
// FIXME(nsm): Unlink appcache if there is one. // FIXME(nsm): Unlink appcache if there is one.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->CheckPendingReadyPromises(); swm->CheckPendingReadyPromises();
// "Queue a task to fire a simple event named controllerchange..." // "Queue a task to fire a simple event named controllerchange..."
@ -311,8 +268,16 @@ ServiceWorkerRegistrationInfo::IsLastUpdateCheckTimeOverOneDay() const
} }
void void
ServiceWorkerRegistrationInfo::NotifyListenersOnChange() ServiceWorkerRegistrationInfo::NotifyListenersOnChange(WhichServiceWorker aChangedWorkers)
{ {
AssertIsOnMainThread();
MOZ_ASSERT(aChangedWorkers & (WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER));
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, aChangedWorkers);
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> listeners(mListeners); nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> listeners(mListeners);
for (size_t index = 0; index < listeners.Length(); ++index) { for (size_t index = 0; index < listeners.Length(); ++index) {
listeners[index]->OnChange(); listeners[index]->OnChange();
@ -389,24 +354,97 @@ ServiceWorkerRegistrationInfo::GetActive() const
} }
void void
ServiceWorkerRegistrationInfo::SetInstalling(ServiceWorkerInfo* aServiceWorker) ServiceWorkerRegistrationInfo::ClearInstalling()
{ {
AssertIsOnMainThread(); AssertIsOnMainThread();
mInstallingWorker = aServiceWorker;
if (!mInstallingWorker) {
return;
}
mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
mInstallingWorker = nullptr;
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER);
} }
void void
ServiceWorkerRegistrationInfo::SetWaiting(ServiceWorkerInfo* aServiceWorker) ServiceWorkerRegistrationInfo::SetInstalling(ServiceWorkerInfo* aServiceWorker)
{ {
AssertIsOnMainThread(); AssertIsOnMainThread();
mWaitingWorker = aServiceWorker; MOZ_ASSERT(aServiceWorker);
MOZ_ASSERT(!mInstallingWorker);
MOZ_ASSERT(mWaitingWorker != aServiceWorker);
MOZ_ASSERT(mActiveWorker != aServiceWorker);
mInstallingWorker = aServiceWorker;
mInstallingWorker->UpdateState(ServiceWorkerState::Installing);
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER);
}
void
ServiceWorkerRegistrationInfo::TransitionInstallingToWaiting()
{
AssertIsOnMainThread();
MOZ_ASSERT(mInstallingWorker);
if (mWaitingWorker) {
MOZ_ASSERT(mInstallingWorker->CacheName() != mWaitingWorker->CacheName());
mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
}
mWaitingWorker = mInstallingWorker.forget();
mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER);
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->StoreRegistration(mPrincipal, this);
} }
void void
ServiceWorkerRegistrationInfo::SetActive(ServiceWorkerInfo* aServiceWorker) ServiceWorkerRegistrationInfo::SetActive(ServiceWorkerInfo* aServiceWorker)
{ {
AssertIsOnMainThread(); AssertIsOnMainThread();
MOZ_ASSERT(aServiceWorker);
// TODO: Assert installing, waiting, and active are nullptr once the SWM
// moves to the parent process. After that happens this code will
// only run for browser initialization and not for cross-process
// overrides.
MOZ_ASSERT(mInstallingWorker != aServiceWorker);
MOZ_ASSERT(mWaitingWorker != aServiceWorker);
MOZ_ASSERT(mActiveWorker != aServiceWorker);
if (mActiveWorker) {
MOZ_ASSERT(aServiceWorker->CacheName() != mActiveWorker->CacheName());
mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
}
// The active worker is being overriden due to initial load or
// another process activating a worker. Move straight to the
// Activated state.
mActiveWorker = aServiceWorker; mActiveWorker = aServiceWorker;
mActiveWorker->SetActivateStateUncheckedWithoutEvent(ServiceWorkerState::Activated);
NotifyListenersOnChange(WhichServiceWorker::ACTIVE_WORKER);
}
void
ServiceWorkerRegistrationInfo::TransitionWaitingToActive()
{
AssertIsOnMainThread();
MOZ_ASSERT(mWaitingWorker);
if (mActiveWorker) {
MOZ_ASSERT(mWaitingWorker->CacheName() != mActiveWorker->CacheName());
mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
}
// We are transitioning from waiting to active normally, so go to
// the activating state.
mActiveWorker = mWaitingWorker.forget();
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
NotifyListenersOnChange(WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER);
} }
END_WORKERS_NAMESPACE END_WORKERS_NAMESPACE

Просмотреть файл

@ -91,9 +91,6 @@ public:
void void
Clear(); Clear();
void
PurgeActiveWorker();
void void
TryToActivateAsync(); TryToActivateAsync();
@ -113,7 +110,7 @@ public:
IsLastUpdateCheckTimeOverOneDay() const; IsLastUpdateCheckTimeOverOneDay() const;
void void
NotifyListenersOnChange(); NotifyListenersOnChange(WhichServiceWorker aChangedWorkers);
void void
MaybeScheduleTimeCheckAndUpdate(); MaybeScheduleTimeCheckAndUpdate();
@ -133,14 +130,34 @@ public:
ServiceWorkerInfo* ServiceWorkerInfo*
GetActive() const; GetActive() const;
// 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.
void void
SetInstalling(ServiceWorkerInfo* aServiceWorker); SetInstalling(ServiceWorkerInfo* aServiceWorker);
// Transition the current installing worker to be the waiting worker. The
// workers state is updated to Installed.
void void
SetWaiting(ServiceWorkerInfo* aServiceWorker); 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.
void void
SetActive(ServiceWorkerInfo* aServiceWorker); SetActive(ServiceWorkerInfo* aServiceWorker);
// Transition the current waiting worker to be the new active worker. The
// worker is updated to the Activating state.
void
TransitionWaitingToActive();
}; };
} // namespace workers } // namespace workers

Просмотреть файл

@ -150,19 +150,9 @@ ServiceWorkerUpdateJob::FailUpdateJob(ErrorResult& aRv)
mServiceWorker->CacheName()); mServiceWorker->CacheName());
} }
mRegistration->ClearInstalling();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (mRegistration->GetInstalling()) {
mRegistration->GetInstalling()->UpdateState(ServiceWorkerState::Redundant);
serviceWorkerScriptCache::PurgeCache(mRegistration->mPrincipal,
mRegistration->GetInstalling()->CacheName());
mRegistration->SetInstalling(nullptr);
if (swm) {
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER);
}
}
if (swm) { if (swm) {
swm->MaybeRemoveRegistration(mRegistration); swm->MaybeRemoveRegistration(mRegistration);
} }
@ -422,12 +412,6 @@ ServiceWorkerUpdateJob::Install()
MOZ_ASSERT(mServiceWorker); MOZ_ASSERT(mServiceWorker);
mRegistration->SetInstalling(mServiceWorker); mRegistration->SetInstalling(mServiceWorker);
mServiceWorker = nullptr; mServiceWorker = nullptr;
mRegistration->GetInstalling()->UpdateState(ServiceWorkerState::Installing);
mRegistration->NotifyListenersOnChange();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER);
// Step 6 of the Install algorithm resolving the job promise. // Step 6 of the Install algorithm resolving the job promise.
InvokeResultCallbacks(NS_OK); InvokeResultCallbacks(NS_OK);
@ -435,6 +419,8 @@ ServiceWorkerUpdateJob::Install()
// The job promise cannot be rejected after this point, but the job can // The job promise cannot be rejected after this point, but the job can
// still fail; e.g. if the install event handler throws, etc. // still fail; e.g. if the install event handler throws, etc.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
// fire the updatefound event // fire the updatefound event
nsCOMPtr<nsIRunnable> upr = nsCOMPtr<nsIRunnable> upr =
NS_NewRunnableMethodWithArg<RefPtr<ServiceWorkerRegistrationInfo>>( NS_NewRunnableMethodWithArg<RefPtr<ServiceWorkerRegistrationInfo>>(
@ -471,8 +457,6 @@ ServiceWorkerUpdateJob::ContinueAfterInstallEvent(bool aInstallEventSuccess)
MOZ_ASSERT(mRegistration->GetInstalling()); MOZ_ASSERT(mRegistration->GetInstalling());
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
// Continue executing the Install algorithm at step 12. // Continue executing the Install algorithm at step 12.
// "If installFailed is true" // "If installFailed is true"
@ -482,22 +466,7 @@ ServiceWorkerUpdateJob::ContinueAfterInstallEvent(bool aInstallEventSuccess)
return; return;
} }
// "If registration's waiting worker is not null" mRegistration->TransitionInstallingToWaiting();
if (mRegistration->GetWaiting()) {
mRegistration->GetWaiting()->WorkerPrivate()->TerminateWorker();
mRegistration->GetWaiting()->UpdateState(ServiceWorkerState::Redundant);
serviceWorkerScriptCache::PurgeCache(mRegistration->mPrincipal,
mRegistration->GetWaiting()->CacheName());
}
mRegistration->SetWaiting(mRegistration->GetInstalling());
mRegistration->SetInstalling(nullptr);
mRegistration->GetWaiting()->UpdateState(ServiceWorkerState::Installed);
mRegistration->NotifyListenersOnChange();
swm->StoreRegistration(mPrincipal, mRegistration);
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER);
Finish(NS_OK); Finish(NS_OK);