mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 12:20:56 +00:00
Bug 1462772 P4 Route ServiceWorker state changes through the ServiceWorkerRegistration. r=mrbkap
This commit is contained in:
parent
f3b6e1d527
commit
aa573bca77
@ -12,6 +12,7 @@
|
||||
#include "ServiceWorkerImpl.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "ServiceWorkerPrivate.h"
|
||||
#include "ServiceWorkerRegistration.h"
|
||||
|
||||
#include "mozilla/dom/DOMPrefs.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
@ -74,6 +75,7 @@ ServiceWorker::ServiceWorker(nsIGlobalObject* aGlobal,
|
||||
: DOMEventTargetHelper(aGlobal)
|
||||
, mDescriptor(aDescriptor)
|
||||
, mInner(aInner)
|
||||
, mLastNotifiedState(ServiceWorkerState::Installing)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(aGlobal);
|
||||
@ -147,18 +149,24 @@ ServiceWorker::State() const
|
||||
void
|
||||
ServiceWorker::SetState(ServiceWorkerState aState)
|
||||
{
|
||||
ServiceWorkerState oldState = mDescriptor.State();
|
||||
NS_ENSURE_TRUE_VOID(aState >= mDescriptor.State());
|
||||
mDescriptor.SetState(aState);
|
||||
if (oldState == aState) {
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorker::MaybeDispatchStateChangeEvent()
|
||||
{
|
||||
if (mDescriptor.State() <= mLastNotifiedState || !GetParentObject()) {
|
||||
return;
|
||||
}
|
||||
mLastNotifiedState = mDescriptor.State();
|
||||
|
||||
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("statechange"));
|
||||
|
||||
// Once we have transitioned to the redundant state then no
|
||||
// more statechange events will occur. We can allow the DOM
|
||||
// object to GC if script is not holding it alive.
|
||||
if (mDescriptor.State() == ServiceWorkerState::Redundant) {
|
||||
if (mLastNotifiedState == ServiceWorkerState::Redundant) {
|
||||
IgnoreKeepAliveIfHasListenersFor(NS_LITERAL_STRING("statechange"));
|
||||
}
|
||||
}
|
||||
@ -236,6 +244,14 @@ ServiceWorker::MaybeAttachToRegistration(ServiceWorkerRegistration* aRegistratio
|
||||
MOZ_DIAGNOSTIC_ASSERT(aRegistration);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mRegistration);
|
||||
|
||||
// If the registration no longer actually references this ServiceWorker
|
||||
// then we must be in the redundant state.
|
||||
if (!aRegistration->Descriptor().HasWorker(mDescriptor)) {
|
||||
SetState(ServiceWorkerState::Redundant);
|
||||
MaybeDispatchStateChangeEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
mRegistration = aRegistration;
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,9 @@ public:
|
||||
void
|
||||
SetState(ServiceWorkerState aState);
|
||||
|
||||
void
|
||||
MaybeDispatchStateChangeEvent();
|
||||
|
||||
void
|
||||
GetScriptURL(nsString& aURL) const;
|
||||
|
||||
@ -117,6 +120,7 @@ private:
|
||||
|
||||
RefPtr<Inner> mInner;
|
||||
RefPtr<ServiceWorkerRegistration> mRegistration;
|
||||
ServiceWorkerState mLastNotifiedState;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(ServiceWorker, NS_DOM_SERVICEWORKER_IID)
|
||||
|
@ -12,7 +12,6 @@ namespace dom {
|
||||
ServiceWorkerImpl::~ServiceWorkerImpl()
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mOuter);
|
||||
mInfo->RemoveListener(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -21,11 +20,6 @@ ServiceWorkerImpl::AddServiceWorker(ServiceWorker* aWorker)
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mOuter);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorker);
|
||||
mOuter = aWorker;
|
||||
|
||||
// Wait to attach to the info as a listener until we have the outer
|
||||
// set. This is important because the info will try to set the
|
||||
// state immediately.
|
||||
mInfo->AddListener(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -140,20 +140,71 @@ ServiceWorkerRegistration::UpdateState(const ServiceWorkerRegistrationDescriptor
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = GetParentObject();
|
||||
|
||||
// Move the currently exposed workers into a separate list
|
||||
// of "old" workers. We will then potentially add them
|
||||
// back to the registration properties below based on the
|
||||
// given descriptor. Any that are not restored will need
|
||||
// to be moved to the redundant state.
|
||||
AutoTArray<RefPtr<ServiceWorker>, 3> oldWorkerList({
|
||||
mInstallingWorker.forget(),
|
||||
mWaitingWorker.forget(),
|
||||
mActiveWorker.forget(),
|
||||
});
|
||||
|
||||
// Its important that all state changes are actually applied before
|
||||
// dispatching any statechange events. Each ServiceWorker object
|
||||
// should be in the correct state and the ServiceWorkerRegistration
|
||||
// properties need to be set correctly as well. To accomplish this
|
||||
// we use a ScopeExit to dispatch any statechange events.
|
||||
auto scopeExit = MakeScopeExit([&] {
|
||||
// Check to see if any of the "old" workers was completely discarded.
|
||||
// Set these workers to the redundant state.
|
||||
for (auto& oldWorker : oldWorkerList) {
|
||||
if (!oldWorker ||
|
||||
oldWorker == mInstallingWorker ||
|
||||
oldWorker == mWaitingWorker ||
|
||||
oldWorker == mActiveWorker) {
|
||||
continue;
|
||||
}
|
||||
|
||||
oldWorker->SetState(ServiceWorkerState::Redundant);
|
||||
}
|
||||
|
||||
// Check each worker to see if it needs a statechange event dispatched.
|
||||
if (mInstallingWorker) {
|
||||
mInstallingWorker->MaybeDispatchStateChangeEvent();
|
||||
}
|
||||
if (mWaitingWorker) {
|
||||
mWaitingWorker->MaybeDispatchStateChangeEvent();
|
||||
}
|
||||
if (mActiveWorker) {
|
||||
mActiveWorker->MaybeDispatchStateChangeEvent();
|
||||
}
|
||||
|
||||
// We also check the "old" workers to see if they need a statechange
|
||||
// event as well. Note, these may overlap with the known worker properties
|
||||
// above, but MaybeDispatchStateChangeEvent() will ignore duplicated calls.
|
||||
for (auto& oldWorker : oldWorkerList) {
|
||||
if (!oldWorker) {
|
||||
continue;
|
||||
}
|
||||
|
||||
oldWorker->MaybeDispatchStateChangeEvent();
|
||||
}
|
||||
});
|
||||
|
||||
// Clear all workers if the registration has been detached from the global.
|
||||
// Also, we cannot expose ServiceWorker objects on worker threads yet, so
|
||||
// do the same on when off-main-thread. This main thread check should be
|
||||
// removed as part of bug 1113522.
|
||||
if (!global || !NS_IsMainThread()) {
|
||||
mInstallingWorker = nullptr;
|
||||
mWaitingWorker = nullptr;
|
||||
mActiveWorker = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor> active = aDescriptor.GetActive();
|
||||
if (active.isSome()) {
|
||||
mActiveWorker = global->GetOrCreateServiceWorker(active.ref());
|
||||
mActiveWorker->SetState(active.ref().State());
|
||||
} else {
|
||||
mActiveWorker = nullptr;
|
||||
}
|
||||
@ -161,6 +212,7 @@ ServiceWorkerRegistration::UpdateState(const ServiceWorkerRegistrationDescriptor
|
||||
Maybe<ServiceWorkerDescriptor> waiting = aDescriptor.GetWaiting();
|
||||
if (waiting.isSome()) {
|
||||
mWaitingWorker = global->GetOrCreateServiceWorker(waiting.ref());
|
||||
mWaitingWorker->SetState(waiting.ref().State());
|
||||
} else {
|
||||
mWaitingWorker = nullptr;
|
||||
}
|
||||
@ -168,6 +220,7 @@ ServiceWorkerRegistration::UpdateState(const ServiceWorkerRegistrationDescriptor
|
||||
Maybe<ServiceWorkerDescriptor> installing = aDescriptor.GetInstalling();
|
||||
if (installing.isSome()) {
|
||||
mInstallingWorker = global->GetOrCreateServiceWorker(installing.ref());
|
||||
mInstallingWorker->SetState(installing.ref().State());
|
||||
} else {
|
||||
mInstallingWorker = nullptr;
|
||||
}
|
||||
@ -345,5 +398,11 @@ ServiceWorkerRegistration::GetNotifications(const GetNotificationOptions& aOptio
|
||||
return Notification::WorkerGet(worker, aOptions, scope, aRv);
|
||||
}
|
||||
|
||||
const ServiceWorkerRegistrationDescriptor&
|
||||
ServiceWorkerRegistration::Descriptor() const
|
||||
{
|
||||
return mDescriptor;
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
@ -116,6 +116,9 @@ public:
|
||||
GetNotifications(const GetNotificationOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
const ServiceWorkerRegistrationDescriptor&
|
||||
Descriptor() const;
|
||||
|
||||
private:
|
||||
ServiceWorkerRegistration(nsIGlobalObject* aGlobal,
|
||||
const ServiceWorkerRegistrationDescriptor& aDescriptor,
|
||||
|
@ -197,6 +197,17 @@ ServiceWorkerRegistrationDescriptor::Newest() const
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerRegistrationDescriptor::HasWorker(const ServiceWorkerDescriptor& aDescriptor) const
|
||||
{
|
||||
Maybe<ServiceWorkerDescriptor> installing = GetInstalling();
|
||||
Maybe<ServiceWorkerDescriptor> waiting = GetWaiting();
|
||||
Maybe<ServiceWorkerDescriptor> active = GetActive();
|
||||
return (installing.isSome() && installing.ref().Matches(aDescriptor)) ||
|
||||
(waiting.isSome() && waiting.ref().Matches(aDescriptor)) ||
|
||||
(active.isSome() && active.ref().Matches(aDescriptor));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool
|
||||
|
@ -91,6 +91,9 @@ public:
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
Newest() const;
|
||||
|
||||
bool
|
||||
HasWorker(const ServiceWorkerDescriptor& aDescriptor) const;
|
||||
|
||||
bool
|
||||
IsValid() const;
|
||||
|
||||
|
@ -105,8 +105,23 @@ ServiceWorkerRegistrationMainThread::UpdateFound()
|
||||
void
|
||||
ServiceWorkerRegistrationMainThread::UpdateState(const ServiceWorkerRegistrationDescriptor& aDescriptor)
|
||||
{
|
||||
mDescriptor = aDescriptor;
|
||||
mOuter->UpdateState(aDescriptor);
|
||||
NS_ENSURE_TRUE_VOID(mOuter);
|
||||
|
||||
nsIGlobalObject* global = mOuter->GetParentObject();
|
||||
NS_ENSURE_TRUE_VOID(global);
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationMainThread> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
"ServiceWorkerRegistrationMainThread::UpdateState",
|
||||
[self, desc = std::move(aDescriptor)] () mutable {
|
||||
self->mDescriptor = std::move(desc);
|
||||
NS_ENSURE_TRUE_VOID(self->mOuter);
|
||||
self->mOuter->UpdateState(self->mDescriptor);
|
||||
});
|
||||
|
||||
Unused <<
|
||||
global->EventTargetFor(TaskCategory::Other)->Dispatch(r.forget(),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -56,8 +56,6 @@ ServiceWorkerRegistrationInfo::Clear()
|
||||
RefPtr<ServiceWorkerInfo> waiting = mWaitingWorker.forget();
|
||||
RefPtr<ServiceWorkerInfo> active = mActiveWorker.forget();
|
||||
|
||||
UpdateRegistrationState();
|
||||
|
||||
if (installing) {
|
||||
installing->UpdateState(ServiceWorkerState::Redundant);
|
||||
installing->UpdateRedundantTime();
|
||||
@ -77,6 +75,7 @@ ServiceWorkerRegistrationInfo::Clear()
|
||||
active->WorkerPrivate()->NoteDeadServiceWorkerInfo();
|
||||
}
|
||||
|
||||
UpdateRegistrationState();
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
@ -366,6 +365,7 @@ ServiceWorkerRegistrationInfo::FinishActivate(bool aSuccess)
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
UpdateRegistrationState();
|
||||
NotifyChromeRegistrationListeners();
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
@ -418,16 +418,10 @@ ServiceWorkerRegistrationInfo::UpdateRegistrationState()
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> self(this);
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
"ServiceWorkerRegistrationInfo::UpdateRegistrationState",
|
||||
[self = std::move(self)] {
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (swm) {
|
||||
swm->UpdateRegistrationListeners(self);
|
||||
}
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
NS_ENSURE_TRUE_VOID(swm);
|
||||
|
||||
swm->UpdateRegistrationListeners(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -571,12 +565,10 @@ ServiceWorkerRegistrationInfo::ClearInstalling()
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerInfo> installing = mInstallingWorker.forget();
|
||||
|
||||
UpdateRegistrationState();
|
||||
|
||||
installing->UpdateState(ServiceWorkerState::Redundant);
|
||||
installing->UpdateRedundantTime();
|
||||
|
||||
UpdateRegistrationState();
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
@ -588,11 +580,9 @@ ServiceWorkerRegistrationInfo::TransitionEvaluatingToInstalling()
|
||||
MOZ_ASSERT(!mInstallingWorker);
|
||||
|
||||
mInstallingWorker = mEvaluatingWorker.forget();
|
||||
|
||||
UpdateRegistrationState();
|
||||
|
||||
mInstallingWorker->UpdateState(ServiceWorkerState::Installing);
|
||||
|
||||
UpdateRegistrationState();
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
@ -609,12 +599,10 @@ ServiceWorkerRegistrationInfo::TransitionInstallingToWaiting()
|
||||
}
|
||||
|
||||
mWaitingWorker = mInstallingWorker.forget();
|
||||
|
||||
UpdateRegistrationState();
|
||||
|
||||
mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
|
||||
mWaitingWorker->UpdateInstalledTime();
|
||||
|
||||
UpdateRegistrationState();
|
||||
NotifyChromeRegistrationListeners();
|
||||
|
||||
// TODO: When bug 1426401 is implemented we will need to call
|
||||
@ -650,7 +638,6 @@ ServiceWorkerRegistrationInfo::SetActive(ServiceWorkerInfo* aServiceWorker)
|
||||
// We don't need to update activated time when we load registration from
|
||||
// registrar.
|
||||
UpdateRegistrationState();
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
@ -669,9 +656,6 @@ ServiceWorkerRegistrationInfo::TransitionWaitingToActive()
|
||||
// We are transitioning from waiting to active normally, so go to
|
||||
// the activating state.
|
||||
mActiveWorker = mWaitingWorker.forget();
|
||||
|
||||
UpdateRegistrationState();
|
||||
|
||||
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
|
||||
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
@ -684,6 +668,7 @@ ServiceWorkerRegistrationInfo::TransitionWaitingToActive()
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
|
||||
|
||||
UpdateRegistrationState();
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user