gecko-dev/dom/serviceworkers/ServiceWorkerInfo.cpp
Natalia Csoregi 8c2521e9d5 Backed out 13 changesets (bug 1640839) for causing bustage on Element.cpp CLOSED TREE
Backed out changeset 179ceb82c9e5 (bug 1640839)
Backed out changeset 73f498a821f0 (bug 1640839)
Backed out changeset dc2d3d0e0365 (bug 1640839)
Backed out changeset ddc989ac0509 (bug 1640839)
Backed out changeset e595bb3feea8 (bug 1640839)
Backed out changeset c85aca04e27f (bug 1640839)
Backed out changeset 98e8e3a4047a (bug 1640839)
Backed out changeset 59ef180517db (bug 1640839)
Backed out changeset af2f5e293662 (bug 1640839)
Backed out changeset 89aa6d9dc598 (bug 1640839)
Backed out changeset 67b722a722f9 (bug 1640839)
Backed out changeset 24a9665c6ced (bug 1640839)
Backed out changeset d93f199385e9 (bug 1640839)
2024-03-01 18:23:08 +02:00

287 lines
9.6 KiB
C++

/* -*- 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/. */
#include "ServiceWorkerInfo.h"
#include "ServiceWorkerUtils.h"
#include "ServiceWorkerPrivate.h"
#include "ServiceWorkerScriptCache.h"
#include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/dom/ClientState.h"
#include "mozilla/dom/RemoteWorkerTypes.h"
#include "mozilla/dom/WorkerPrivate.h"
namespace mozilla::dom {
using mozilla::ipc::PrincipalInfo;
static_assert(nsIServiceWorkerInfo::STATE_PARSED ==
static_cast<uint16_t>(ServiceWorkerState::Parsed),
"ServiceWorkerState enumeration value should match state values "
"from nsIServiceWorkerInfo.");
static_assert(nsIServiceWorkerInfo::STATE_INSTALLING ==
static_cast<uint16_t>(ServiceWorkerState::Installing),
"ServiceWorkerState enumeration value should match state values "
"from nsIServiceWorkerInfo.");
static_assert(nsIServiceWorkerInfo::STATE_INSTALLED ==
static_cast<uint16_t>(ServiceWorkerState::Installed),
"ServiceWorkerState enumeration value should match state values "
"from nsIServiceWorkerInfo.");
static_assert(nsIServiceWorkerInfo::STATE_ACTIVATING ==
static_cast<uint16_t>(ServiceWorkerState::Activating),
"ServiceWorkerState enumeration value should match state values "
"from nsIServiceWorkerInfo.");
static_assert(nsIServiceWorkerInfo::STATE_ACTIVATED ==
static_cast<uint16_t>(ServiceWorkerState::Activated),
"ServiceWorkerState enumeration value should match state values "
"from nsIServiceWorkerInfo.");
static_assert(nsIServiceWorkerInfo::STATE_REDUNDANT ==
static_cast<uint16_t>(ServiceWorkerState::Redundant),
"ServiceWorkerState enumeration value should match state values "
"from nsIServiceWorkerInfo.");
static_assert(nsIServiceWorkerInfo::STATE_UNKNOWN ==
ServiceWorkerStateValues::Count,
"ServiceWorkerState enumeration value should match state values "
"from nsIServiceWorkerInfo.");
NS_IMPL_ISUPPORTS(ServiceWorkerInfo, nsIServiceWorkerInfo)
NS_IMETHODIMP
ServiceWorkerInfo::GetId(nsAString& aId) {
MOZ_ASSERT(NS_IsMainThread());
aId = mWorkerPrivateId;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetScriptSpec(nsAString& aScriptSpec) {
MOZ_ASSERT(NS_IsMainThread());
CopyUTF8toUTF16(mDescriptor.ScriptURL(), aScriptSpec);
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetCacheName(nsAString& aCacheName) {
MOZ_ASSERT(NS_IsMainThread());
aCacheName = mCacheName;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetState(uint16_t* aState) {
MOZ_ASSERT(aState);
MOZ_ASSERT(NS_IsMainThread());
*aState = static_cast<uint16_t>(State());
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetDebugger(nsIWorkerDebugger** aResult) {
if (NS_WARN_IF(!aResult)) {
return NS_ERROR_FAILURE;
}
return mServiceWorkerPrivate->GetDebugger(aResult);
}
NS_IMETHODIMP
ServiceWorkerInfo::GetHandlesFetchEvents(bool* aValue) {
MOZ_ASSERT(aValue);
MOZ_ASSERT(NS_IsMainThread());
if (mHandlesFetch == Unknown) {
return NS_ERROR_FAILURE;
}
*aValue = HandlesFetch();
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetInstalledTime(PRTime* _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(_retval);
*_retval = mInstalledTime;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetActivatedTime(PRTime* _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(_retval);
*_retval = mActivatedTime;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetRedundantTime(PRTime* _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(_retval);
*_retval = mRedundantTime;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetNavigationFaultCount(uint32_t* aNavigationFaultCount) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aNavigationFaultCount);
*aNavigationFaultCount = mNavigationFaultCount;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::GetTestingInjectCancellation(
nsresult* aTestingInjectCancellation) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aTestingInjectCancellation);
*aTestingInjectCancellation = mTestingInjectCancellation;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::SetTestingInjectCancellation(
nsresult aTestingInjectCancellation) {
MOZ_ASSERT(NS_IsMainThread());
mTestingInjectCancellation = aTestingInjectCancellation;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerInfo::AttachDebugger() {
return mServiceWorkerPrivate->AttachDebugger();
}
NS_IMETHODIMP
ServiceWorkerInfo::DetachDebugger() {
return mServiceWorkerPrivate->DetachDebugger();
}
void ServiceWorkerInfo::UpdateState(ServiceWorkerState aState) {
MOZ_ASSERT(NS_IsMainThread());
#ifdef DEBUG
// Any state can directly transition to redundant, but everything else is
// ordered.
if (aState != ServiceWorkerState::Redundant) {
MOZ_ASSERT_IF(State() == ServiceWorkerState::EndGuard_,
aState == ServiceWorkerState::Installing);
MOZ_ASSERT_IF(State() == ServiceWorkerState::Installing,
aState == ServiceWorkerState::Installed);
MOZ_ASSERT_IF(State() == ServiceWorkerState::Installed,
aState == ServiceWorkerState::Activating);
MOZ_ASSERT_IF(State() == ServiceWorkerState::Activating,
aState == ServiceWorkerState::Activated);
}
// Activated can only go to redundant.
MOZ_ASSERT_IF(State() == ServiceWorkerState::Activated,
aState == ServiceWorkerState::Redundant);
#endif
// Flush any pending functional events to the worker when it transitions to
// the activated state.
// TODO: Do we care that these events will race with the propagation of the
// state change?
if (State() != aState) {
mServiceWorkerPrivate->UpdateState(aState);
}
mDescriptor.SetState(aState);
if (State() == ServiceWorkerState::Redundant) {
serviceWorkerScriptCache::PurgeCache(mPrincipal, mCacheName);
mServiceWorkerPrivate->NoteDeadServiceWorkerInfo();
}
}
ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
const nsACString& aScope,
uint64_t aRegistrationId,
uint64_t aRegistrationVersion,
const nsACString& aScriptSpec,
const nsAString& aCacheName,
nsLoadFlags aImportsLoadFlags)
: mPrincipal(aPrincipal),
mDescriptor(GetNextID(), aRegistrationId, aRegistrationVersion,
aPrincipal, aScope, aScriptSpec, ServiceWorkerState::Parsed),
mCacheName(aCacheName),
mWorkerPrivateId(ComputeWorkerPrivateId()),
mImportsLoadFlags(aImportsLoadFlags),
mCreationTime(PR_Now()),
mCreationTimeStamp(TimeStamp::Now()),
mInstalledTime(0),
mActivatedTime(0),
mRedundantTime(0),
mServiceWorkerPrivate(new ServiceWorkerPrivate(this)),
mSkipWaitingFlag(false),
mHandlesFetch(Unknown),
mNavigationFaultCount(0),
mTestingInjectCancellation(NS_OK) {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(mPrincipal);
// cache origin attributes so we can use them off main thread
mOriginAttributes = mPrincipal->OriginAttributesRef();
MOZ_ASSERT(!mDescriptor.ScriptURL().IsEmpty());
MOZ_ASSERT(!mCacheName.IsEmpty());
MOZ_ASSERT(!mWorkerPrivateId.IsEmpty());
// Scripts of a service worker should always be loaded bypass service workers.
// Otherwise, we might not be able to update a service worker correctly, if
// there is a service worker generating the script.
MOZ_DIAGNOSTIC_ASSERT(mImportsLoadFlags &
nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
}
ServiceWorkerInfo::~ServiceWorkerInfo() {
MOZ_ASSERT(mServiceWorkerPrivate);
mServiceWorkerPrivate->NoteDeadServiceWorkerInfo();
}
static uint64_t gServiceWorkerInfoCurrentID = 0;
uint64_t ServiceWorkerInfo::GetNextID() const {
return ++gServiceWorkerInfoCurrentID;
}
void ServiceWorkerInfo::PostMessage(RefPtr<ServiceWorkerCloneData>&& aData,
const ClientInfo& aClientInfo,
const ClientState& aClientState) {
mServiceWorkerPrivate->SendMessageEvent(
std::move(aData),
ClientInfoAndState(aClientInfo.ToIPC(), aClientState.ToIPC()));
}
void ServiceWorkerInfo::UpdateInstalledTime() {
MOZ_ASSERT(State() == ServiceWorkerState::Installed);
MOZ_ASSERT(mInstalledTime == 0);
mInstalledTime =
mCreationTime +
static_cast<PRTime>(
(TimeStamp::Now() - mCreationTimeStamp).ToMicroseconds());
}
void ServiceWorkerInfo::UpdateActivatedTime() {
MOZ_ASSERT(State() == ServiceWorkerState::Activated);
MOZ_ASSERT(mActivatedTime == 0);
mActivatedTime =
mCreationTime +
static_cast<PRTime>(
(TimeStamp::Now() - mCreationTimeStamp).ToMicroseconds());
}
void ServiceWorkerInfo::UpdateRedundantTime() {
MOZ_ASSERT(State() == ServiceWorkerState::Redundant);
MOZ_ASSERT(mRedundantTime == 0);
mRedundantTime =
mCreationTime +
static_cast<PRTime>(
(TimeStamp::Now() - mCreationTimeStamp).ToMicroseconds());
}
void ServiceWorkerInfo::SetRegistrationVersion(uint64_t aVersion) {
mDescriptor.SetRegistrationVersion(aVersion);
}
} // namespace mozilla::dom