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
parent a9a4f7363c
commit b3e4dd4541
4 changed files with 124 additions and 95 deletions

View File

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

View File

@ -20,36 +20,19 @@ ServiceWorkerRegistrationInfo::Clear()
if (mWaitingWorker) {
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 = nullptr;
}
if (mActiveWorker) {
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 = nullptr;
}
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
swm->InvalidateServiceWorkerRegistrationWorker(this,
WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER);
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER);
}
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
ServiceWorkerRegistrationInfo::Activate()
{
RefPtr<ServiceWorkerInfo> activatingWorker = mWaitingWorker;
if (!activatingWorker) {
if (!mWaitingWorker) {
return;
}
PurgeActiveWorker();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, WhichServiceWorker::WAITING_WORKER);
mActiveWorker = activatingWorker.forget();
mWaitingWorker = nullptr;
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
NotifyListenersOnChange();
TransitionWaitingToActive();
// FIXME(nsm): Unlink appcache if there is one.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->CheckPendingReadyPromises();
// "Queue a task to fire a simple event named controllerchange..."
@ -311,8 +268,16 @@ ServiceWorkerRegistrationInfo::IsLastUpdateCheckTimeOverOneDay() const
}
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);
for (size_t index = 0; index < listeners.Length(); ++index) {
listeners[index]->OnChange();
@ -389,24 +354,97 @@ ServiceWorkerRegistrationInfo::GetActive() const
}
void
ServiceWorkerRegistrationInfo::SetInstalling(ServiceWorkerInfo* aServiceWorker)
ServiceWorkerRegistrationInfo::ClearInstalling()
{
AssertIsOnMainThread();
mInstallingWorker = aServiceWorker;
if (!mInstallingWorker) {
return;
}
mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
mInstallingWorker = nullptr;
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER);
}
void
ServiceWorkerRegistrationInfo::SetWaiting(ServiceWorkerInfo* aServiceWorker)
ServiceWorkerRegistrationInfo::SetInstalling(ServiceWorkerInfo* aServiceWorker)
{
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
ServiceWorkerRegistrationInfo::SetActive(ServiceWorkerInfo* aServiceWorker)
{
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->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

View File

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

View File

@ -150,19 +150,9 @@ ServiceWorkerUpdateJob::FailUpdateJob(ErrorResult& aRv)
mServiceWorker->CacheName());
}
mRegistration->ClearInstalling();
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) {
swm->MaybeRemoveRegistration(mRegistration);
}
@ -422,12 +412,6 @@ ServiceWorkerUpdateJob::Install()
MOZ_ASSERT(mServiceWorker);
mRegistration->SetInstalling(mServiceWorker);
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.
InvokeResultCallbacks(NS_OK);
@ -435,6 +419,8 @@ ServiceWorkerUpdateJob::Install()
// 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();
// fire the updatefound event
nsCOMPtr<nsIRunnable> upr =
NS_NewRunnableMethodWithArg<RefPtr<ServiceWorkerRegistrationInfo>>(
@ -471,8 +457,6 @@ ServiceWorkerUpdateJob::ContinueAfterInstallEvent(bool aInstallEventSuccess)
MOZ_ASSERT(mRegistration->GetInstalling());
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
// Continue executing the Install algorithm at step 12.
// "If installFailed is true"
@ -482,22 +466,7 @@ ServiceWorkerUpdateJob::ContinueAfterInstallEvent(bool aInstallEventSuccess)
return;
}
// "If registration's waiting worker is not null"
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);
mRegistration->TransitionInstallingToWaiting();
Finish(NS_OK);