/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
class ContinueActivateRunnable final : public LifeCycleEventCallback {
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration; bool mSuccess;
void ServiceWorkerRegistrationInfo::AddInstance(
ServiceWorkerRegistrationListener* aInstance, const ServiceWorkerRegistrationDescriptor& aDescriptor) {
MOZ_DIAGNOSTIC_ASSERT(aInstance);
MOZ_ASSERT(!mInstanceList.Contains(aInstance));
MOZ_DIAGNOSTIC_ASSERT(aDescriptor.Id() == mDescriptor.Id());
MOZ_DIAGNOSTIC_ASSERT(aDescriptor.PrincipalInfo() ==
mDescriptor.PrincipalInfo());
MOZ_DIAGNOSTIC_ASSERT(aDescriptor.Scope() == mDescriptor.Scope());
MOZ_DIAGNOSTIC_ASSERT(aDescriptor.Version() <= mDescriptor.Version());
uint64_t lastVersion = aDescriptor.Version(); for (auto& entry : mVersionList) { if (lastVersion > entry->mDescriptor.Version()) { continue;
}
lastVersion = entry->mDescriptor.Version();
aInstance->UpdateState(entry->mDescriptor);
} // Note, the mDescriptor may be contained in the version list. Since the // version list is aged out, though, it may also not be in the version list. // So always check for the mDescriptor update here. if (lastVersion < mDescriptor.Version()) {
aInstance->UpdateState(mDescriptor);
}
mInstanceList.AppendElement(aInstance);
}
// This value is actually stored on SWM's internal-only // RegistrationDataPerPrincipal structure, but we expose it here for // simplicity for our consumers, so we have to ask SWM to look it up for us.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
RefPtr<ServiceWorkerInfo> info = GetServiceWorkerInfoById(aID); // It is ok to return null for a missing service worker info.
info.forget(aResult); return NS_OK;
}
// now < mLastUpdateTime if the system time is reset between storing // and loading mLastUpdateTime from ServiceWorkerRegistrar. if (nowMicros < mLastUpdateTime ||
(nowMicros - mLastUpdateTime) / PR_USEC_PER_SEC > kSecondsPerDay) { returntrue;
} returnfalse;
}
TimeStamp oldest = TimeStamp::Now() - TimeDuration::FromSeconds(30); if (!mVersionList.IsEmpty() && mVersionList[0]->mTimeStamp < oldest) {
nsTArray<UniquePtr<VersionEntry>> list = std::move(mVersionList); for (auto& entry : list) { if (entry->mTimeStamp >= oldest) {
mVersionList.AppendElement(std::move(entry));
}
}
}
mVersionList.AppendElement(MakeUnique<VersionEntry>(mDescriptor));
// We are going to modify the descriptor, so increase its version number.
mDescriptor.SetVersion(GetNextVersion());
// Note, this also sets the new version number on the ServiceWorkerInfo // objects before we copy over their updated descriptors.
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
mDescriptor.SetUpdateViaCache(aUpdateViaCache);
for (RefPtr<ServiceWorkerRegistrationListener> pinnedTarget :
mInstanceList.ForwardRange()) {
pinnedTarget->UpdateState(mDescriptor);
}
}
void ServiceWorkerRegistrationInfo::NotifyChromeRegistrationListeners() {
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> listeners(
mListeners.Clone()); for (size_t index = 0; index < listeners.Length(); ++index) {
listeners[index]->OnChange();
}
}
// We don't call UpdateRegistrationState() here because the evaluating worker // is currently not exposed to content on the registration, so calling it here // would produce redundant IPC traffic.
NotifyChromeRegistrationListeners();
}
mEvaluatingWorker->UpdateState(ServiceWorkerState::Redundant); // We don't update the redundant time for the sw here, since we've not expose // evalutingWorker yet.
mEvaluatingWorker = nullptr;
// As for SetEvaluating, UpdateRegistrationState() does not need to be called.
NotifyChromeRegistrationListeners();
}
// 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);
mActiveWorker->UpdateRedundantTime();
}
// 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);
// We don't need to update activated time when we load registration from // registrar.
UpdateRegistrationState();
NotifyChromeRegistrationListeners();
}
if (mActiveWorker) {
MOZ_ASSERT(mWaitingWorker->CacheName() != mActiveWorker->CacheName());
mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
mActiveWorker->UpdateRedundantTime();
}
// We are transitioning from waiting to active normally, so go to // the activating state.
mActiveWorker = std::move(mWaitingWorker);
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
// This can potentially happen if you spam registration->Update(). We don't // want to wrap to a lower value. if (mDelayMultiplier >= INT_MAX / (delay ? delay : 1)) { return INT_MAX;
}
/** * Although a Service Worker will transition to idle many times during its * lifetime, the promise is only resolved once `GetIdlePromise` has been * called, populating the `MozPromiseHolder`. Additionally, this is the only * time this method will be called for the given ServiceWorker. This means we * will be notified to the transition we are interested in, and there are no * other callers to get confused. * * Note that because we are using `MozPromise`, our callback will be invoked * as a separate task, so there is a small potential for races in the event * code if things are still holding onto the ServiceWorker binding and using * `postMessage()` or other mechanisms to schedule new events on it, which * would make it non-idle. However, this is a race inherent in the spec which * does not deal with the reality of multiple threads in "Try Clear * Registration".
*/
GetActive()->WorkerPrivate()->GetIdlePromise()->Then(
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr<ServiceWorkerRegistrationInfo>(this)]( const GenericPromise::ResolveOrRejectValue& aResult) {
MOZ_ASSERT(aResult.IsResolve()); // This registration was already unregistered and not controlling // clients when `ClearWhenIdle` was called, so there should be no way // that more clients were acquired.
MOZ_ASSERT(!self->IsControllingClients());
MOZ_ASSERT(self->IsIdle());
self->Clear();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.