diff --git a/dom/abort/moz.build b/dom/abort/moz.build index aea70cbc0c08..99e8f4b3bc7c 100644 --- a/dom/abort/moz.build +++ b/dom/abort/moz.build @@ -19,6 +19,4 @@ UNIFIED_SOURCES += [ 'AbortSignal.cpp', ] -include('/ipc/chromium/chromium-config.mozbuild') - FINAL_LIBRARY = 'xul' diff --git a/dom/console/moz.build b/dom/console/moz.build index 93dd64e4bc82..f591dc76f9c2 100644 --- a/dom/console/moz.build +++ b/dom/console/moz.build @@ -52,6 +52,4 @@ MOCHITEST_MANIFESTS += [ 'tests/mochitest.ini' ] MOCHITEST_CHROME_MANIFESTS += [ 'tests/chrome.ini' ] XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini'] -include('/ipc/chromium/chromium-config.mozbuild') - FINAL_LIBRARY = 'xul' diff --git a/dom/fetch/FetchTypes.ipdlh b/dom/fetch/FetchTypes.ipdlh index e3d92c844589..19f47a0a7fac 100644 --- a/dom/fetch/FetchTypes.ipdlh +++ b/dom/fetch/FetchTypes.ipdlh @@ -7,57 +7,15 @@ include ChannelInfo; include PBackgroundSharedTypes; using HeadersGuardEnum from "mozilla/dom/FetchIPCTypes.h"; -using ReferrerPolicy from "mozilla/dom/FetchIPCTypes.h"; -using RequestCache from "mozilla/dom/FetchIPCTypes.h"; -using RequestCredentials from "mozilla/dom/FetchIPCTypes.h"; -using RequestMode from "mozilla/dom/FetchIPCTypes.h"; -using RequestRedirect from "mozilla/dom/FetchIPCTypes.h"; -using ResponseType from "mozilla/dom/FetchIPCTypes.h"; namespace mozilla { namespace dom { -struct HeadersEntry { +struct HeadersEntry +{ nsCString name; nsCString value; }; -struct IPCInternalRequest { - nsCString method; - nsCString[] urlList; - HeadersGuardEnum headersGuard; - HeadersEntry[] headers; - IPCStream? body; - int64_t bodySize; - nsCString preferredAlternativeDataType; - uint32_t contentPolicyType; - nsString referrer; - ReferrerPolicy referrerPolicy; - RequestMode requestMode; - RequestCredentials requestCredentials; - RequestCache cacheMode; - RequestRedirect requestRedirect; - nsString integrity; - nsCString fragment; - bool createdByFetchEvent; - PrincipalInfo? principalInfo; -}; - -struct IPCInternalResponse { - ResponseType type; - nsCString[] urlList; - uint16_t status; - nsCString statusText; - HeadersGuardEnum headersGuard; - HeadersEntry[] headers; - IPCStream? body; - int64_t bodySize; - nsresult errorCode; - nsCString alternativeDataType; - IPCStream? alternativeBody; - IPCChannelInfo channelInfo; - PrincipalInfo? principalInfo; -}; - } // namespace ipc } // namespace mozilla diff --git a/dom/fetch/InternalRequest.cpp b/dom/fetch/InternalRequest.cpp index cf457016a2a4..6456fe55c9aa 100644 --- a/dom/fetch/InternalRequest.cpp +++ b/dom/fetch/InternalRequest.cpp @@ -16,8 +16,6 @@ #include "mozilla/dom/WorkerCommon.h" #include "mozilla/dom/WorkerPrivate.h" -#include "mozilla/ipc/IPCStreamUtils.h" -#include "mozilla/ipc/PBackgroundChild.h" namespace mozilla { namespace dom { @@ -173,73 +171,8 @@ InternalRequest::InternalRequest(const InternalRequest& aOther) // NOTE: does not copy body stream... use the fallible Clone() for that } -InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest) - : mMethod(aIPCRequest.method()), - mURLList(aIPCRequest.urlList()), - mHeaders(new InternalHeaders(aIPCRequest.headers(), - aIPCRequest.headersGuard())), - mBodyStream(mozilla::ipc::DeserializeIPCStream(aIPCRequest.body())), - mBodyLength(aIPCRequest.bodySize()), - mPreferredAlternativeDataType(aIPCRequest.preferredAlternativeDataType()), - mContentPolicyType( - static_cast(aIPCRequest.contentPolicyType())), - mReferrer(aIPCRequest.referrer()), - mReferrerPolicy(aIPCRequest.referrerPolicy()), - mMode(aIPCRequest.requestMode()), - mCredentialsMode(aIPCRequest.requestCredentials()), - mCacheMode(aIPCRequest.cacheMode()), - mRedirectMode(aIPCRequest.requestRedirect()), - mIntegrity(aIPCRequest.integrity()), - mFragment(aIPCRequest.fragment()), - mCreatedByFetchEvent(aIPCRequest.createdByFetchEvent()) { - if (aIPCRequest.principalInfo()) { - mPrincipalInfo = MakeUnique( - aIPCRequest.principalInfo().ref()); - } -} - InternalRequest::~InternalRequest() {} -template void InternalRequest::ToIPC( - IPCInternalRequest* aIPCRequest, mozilla::ipc::PBackgroundChild* aManager, - UniquePtr& aAutoStream); - -template -void InternalRequest::ToIPC( - IPCInternalRequest* aIPCRequest, M* aManager, - UniquePtr& aAutoStream) { - MOZ_ASSERT(aIPCRequest); - MOZ_ASSERT(aManager); - MOZ_ASSERT(!mURLList.IsEmpty()); - - aIPCRequest->method() = mMethod; - aIPCRequest->urlList() = mURLList; - mHeaders->ToIPC(aIPCRequest->headers(), aIPCRequest->headersGuard()); - - if (mBodyStream) { - aAutoStream.reset(new mozilla::ipc::AutoIPCStream(aIPCRequest->body())); - DebugOnly ok = aAutoStream->Serialize(mBodyStream, aManager); - MOZ_ASSERT(ok); - } - - aIPCRequest->bodySize() = mBodyLength; - aIPCRequest->preferredAlternativeDataType() = mPreferredAlternativeDataType; - aIPCRequest->contentPolicyType() = static_cast(mContentPolicyType); - aIPCRequest->referrer() = mReferrer; - aIPCRequest->referrerPolicy() = mReferrerPolicy; - aIPCRequest->requestMode() = mMode; - aIPCRequest->requestCredentials() = mCredentialsMode; - aIPCRequest->cacheMode() = mCacheMode; - aIPCRequest->requestRedirect() = mRedirectMode; - aIPCRequest->integrity() = mIntegrity; - aIPCRequest->fragment() = mFragment; - aIPCRequest->createdByFetchEvent() = mCreatedByFetchEvent; - - if (mPrincipalInfo) { - aIPCRequest->principalInfo().emplace(*mPrincipalInfo); - } -} - void InternalRequest::SetContentPolicyType( nsContentPolicyType aContentPolicyType) { mContentPolicyType = aContentPolicyType; diff --git a/dom/fetch/InternalRequest.h b/dom/fetch/InternalRequest.h index a5755bfdf083..e9e0b1fab9bb 100644 --- a/dom/fetch/InternalRequest.h +++ b/dom/fetch/InternalRequest.h @@ -12,7 +12,6 @@ #include "mozilla/dom/RequestBinding.h" #include "mozilla/LoadTainting.h" #include "mozilla/net/ReferrerPolicy.h" -#include "mozilla/UniquePtr.h" #include "nsIContentPolicy.h" #include "nsIInputStream.h" @@ -27,7 +26,6 @@ namespace mozilla { namespace ipc { class PrincipalInfo; -class AutoIPCStream; } // namespace ipc namespace dom { @@ -70,7 +68,6 @@ namespace dom { * */ -class IPCInternalRequest; class Request; #define kFETCH_CLIENT_REFERRER_STR "about:client" @@ -90,12 +87,6 @@ class InternalRequest final { nsContentPolicyType aContentPolicyType, const nsAString& aIntegrity); - explicit InternalRequest(const IPCInternalRequest& aIPCRequest); - - template - void ToIPC(IPCInternalRequest* aIPCRequest, M* aManager, - UniquePtr& aAutoStream); - already_AddRefed Clone(); void GetMethod(nsCString& aMethod) const { aMethod.Assign(mMethod); } diff --git a/dom/fetch/InternalResponse.cpp b/dom/fetch/InternalResponse.cpp index 5cbd7eb0cc3e..922ade82767c 100644 --- a/dom/fetch/InternalResponse.cpp +++ b/dom/fetch/InternalResponse.cpp @@ -7,8 +7,6 @@ #include "InternalResponse.h" #include "mozilla/Assertions.h" -#include "mozilla/RefPtr.h" -#include "mozilla/dom/FetchTypes.h" #include "mozilla/dom/InternalHeaders.h" #include "mozilla/dom/cache/CacheTypes.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" @@ -41,112 +39,8 @@ InternalResponse::InternalResponse(uint16_t aStatus, mErrorCode(NS_OK), mCredentialsMode(aCredentialsMode) {} -/* static */ RefPtr InternalResponse::FromIPC( - const IPCInternalResponse& aIPCResponse) { - if (aIPCResponse.type() == ResponseType::Error) { - return InternalResponse::NetworkError(aIPCResponse.errorCode()); - } - - RefPtr response = - new InternalResponse(aIPCResponse.status(), aIPCResponse.statusText()); - - response->SetURLList(aIPCResponse.urlList()); - response->mHeaders = - new InternalHeaders(aIPCResponse.headers(), aIPCResponse.headersGuard()); - - nsCOMPtr body = - mozilla::ipc::DeserializeIPCStream(aIPCResponse.body()); - response->SetBody(body, aIPCResponse.bodySize()); - - response->SetAlternativeDataType(aIPCResponse.alternativeDataType()); - - nsCOMPtr alternativeBody = - mozilla::ipc::DeserializeIPCStream(aIPCResponse.alternativeBody()); - response->SetAlternativeBody(alternativeBody); - - response->InitChannelInfo(aIPCResponse.channelInfo()); - - if (aIPCResponse.principalInfo()) { - response->SetPrincipalInfo(MakeUnique( - aIPCResponse.principalInfo().ref())); - } - - switch (aIPCResponse.type()) { - case ResponseType::Basic: - response = response->BasicResponse(); - break; - case ResponseType::Cors: - response = response->CORSResponse(); - break; - case ResponseType::Default: - break; - case ResponseType::Opaque: - response = response->OpaqueResponse(); - break; - case ResponseType::Opaqueredirect: - response = response->OpaqueRedirectResponse(); - break; - default: - MOZ_CRASH("Unexpected ResponseType!"); - } - - MOZ_ASSERT(response); - - return response; -} - InternalResponse::~InternalResponse() {} -template void InternalResponse::ToIPC( - IPCInternalResponse* aIPCResponse, mozilla::ipc::PBackgroundChild* aManager, - UniquePtr& aAutoBodyStream, - UniquePtr& aAutoAlternativeBodyStream); - -template -void InternalResponse::ToIPC( - IPCInternalResponse* aIPCResponse, M* aManager, - UniquePtr& aAutoBodyStream, - UniquePtr& aAutoAlternativeBodyStream) { - MOZ_ASSERT(aIPCResponse); - - aIPCResponse->type() = mType; - GetUnfilteredURLList(aIPCResponse->urlList()); - aIPCResponse->status() = GetUnfilteredStatus(); - aIPCResponse->statusText() = GetUnfilteredStatusText(); - UnfilteredHeaders()->ToIPC(aIPCResponse->headers(), - aIPCResponse->headersGuard()); - - nsCOMPtr body; - int64_t bodySize; - GetUnfilteredBody(getter_AddRefs(body), &bodySize); - - if (body) { - aAutoBodyStream.reset( - new mozilla::ipc::AutoIPCStream(aIPCResponse->body())); - DebugOnly ok = aAutoBodyStream->Serialize(body, aManager); - MOZ_ASSERT(ok); - } - - aIPCResponse->bodySize() = bodySize; - aIPCResponse->errorCode() = mErrorCode; - aIPCResponse->alternativeDataType() = GetAlternativeDataType(); - - nsCOMPtr alternativeBody = TakeAlternativeBody(); - if (alternativeBody) { - aAutoAlternativeBodyStream.reset( - new mozilla::ipc::AutoIPCStream(aIPCResponse->alternativeBody())); - DebugOnly ok = - aAutoAlternativeBodyStream->Serialize(alternativeBody, aManager); - MOZ_ASSERT(ok); - } - - aIPCResponse->channelInfo() = mChannelInfo.AsIPCChannelInfo(); - - if (mPrincipalInfo) { - aIPCResponse->principalInfo().emplace(*mPrincipalInfo); - } -} - already_AddRefed InternalResponse::Clone( CloneType aCloneType) { RefPtr clone = CreateIncompleteCopy(); diff --git a/dom/fetch/InternalResponse.h b/dom/fetch/InternalResponse.h index b1e1c81d899f..408f18e02ec7 100644 --- a/dom/fetch/InternalResponse.h +++ b/dom/fetch/InternalResponse.h @@ -26,7 +26,6 @@ class AutoIPCStream; namespace dom { -class IPCInternalResponse; class InternalHeaders; class InternalResponse final { @@ -39,15 +38,6 @@ class InternalResponse final { uint16_t aStatus, const nsACString& aStatusText, RequestCredentials aCredentialsMode = RequestCredentials::Omit); - static RefPtr FromIPC( - const IPCInternalResponse& aIPCResponse); - - template - void ToIPC( - IPCInternalResponse* aIPCResponse, M* aManager, - UniquePtr& aAutoBodyStream, - UniquePtr& aAutoAlternativeBodyStream); - enum CloneType { eCloneInputStream, eDontCloneInputStream, @@ -221,24 +211,6 @@ class InternalResponse final { void SetPaddingSize(int64_t aPaddingSize); - void SetAlternativeDataType(const nsACString& aAltDataType) { - if (mWrappedResponse) { - return mWrappedResponse->SetAlternativeDataType(aAltDataType); - } - - MOZ_DIAGNOSTIC_ASSERT(mAlternativeDataType.IsEmpty()); - - mAlternativeDataType.Assign(aAltDataType); - } - - const nsCString& GetAlternativeDataType() { - if (mWrappedResponse) { - return mWrappedResponse->GetAlternativeDataType(); - } - - return mAlternativeDataType; - } - void SetAlternativeBody(nsIInputStream* aAlternativeBody) { if (mWrappedResponse) { return mWrappedResponse->SetAlternativeBody(aAlternativeBody); @@ -351,7 +323,6 @@ class InternalResponse final { RequestCredentials mCredentialsMode; // For alternative data such as JS Bytecode cached in the HTTP cache. - nsCString mAlternativeDataType; nsCOMPtr mAlternativeBody; nsMainThreadPtrHandle mCacheInfoChannel; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 2ddb20053df1..06938de1f5f0 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1382,32 +1382,6 @@ RemoteWindowContext::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) { } // namespace -void ContentParent::MaybeAsyncSendShutDownMessage() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!TryToRecycle()); - -#ifdef DEBUG - // Calling this below while the lock is acquired will deadlock. - bool shouldKeepProcessAlive = ShouldKeepProcessAlive(); -#endif - - auto lock = mRemoteWorkerActorData.Lock(); - MOZ_ASSERT_IF(!lock->mCount, !shouldKeepProcessAlive); - - if (lock->mCount) { - return; - } - - MOZ_ASSERT(!lock->mShutdownStarted); - lock->mShutdownStarted = true; - - // In the case of normal shutdown, send a shutdown message to child to - // allow it to perform shutdown tasks. - MessageLoop::current()->PostTask(NewRunnableMethod( - "dom::ContentParent::ShutDownProcess", this, - &ContentParent::ShutDownProcess, SEND_SHUTDOWN_MESSAGE)); -} - void ContentParent::ShutDownProcess(ShutDownMethod aMethod) { if (mScriptableHelper) { static_cast(mScriptableHelper.get())->ProcessDied(); @@ -1752,17 +1726,14 @@ bool ContentParent::TryToRecycle() { return true; } -bool ContentParent::ShouldKeepProcessAlive() { +bool ContentParent::ShouldKeepProcessAlive() const { if (IsForJSPlugin()) { return true; } // If we have active workers, we need to stay alive. - { - const auto lock = mRemoteWorkerActorData.Lock(); - if (lock->mCount) { - return true; - } + if (mRemoteWorkerActors) { + return true; } if (!sBrowserContentParents) { @@ -1874,7 +1845,11 @@ void ContentParent::NotifyTabDestroyed(const TabId& aTabId, // us down. if (ManagedPBrowserParent().Count() == 1 && !ShouldKeepProcessAlive() && !TryToRecycle()) { - MaybeAsyncSendShutDownMessage(); + // In the case of normal shutdown, send a shutdown message to child to + // allow it to perform shutdown tasks. + MessageLoop::current()->PostTask(NewRunnableMethod( + "dom::ContentParent::ShutDownProcess", this, + &ContentParent::ShutDownProcess, SEND_SHUTDOWN_MESSAGE)); } } @@ -2299,7 +2274,7 @@ ContentParent::ContentParent(ContentParent* aOpener, mChildID(gContentChildID++), mGeolocationWatchID(-1), mJSPluginID(aJSPluginID), - mRemoteWorkerActorData("ContentParent::mRemoteWorkerActorData"), + mRemoteWorkerActors(0), mNumDestroyingTabs(0), mLifecycleState(LifecycleState::LAUNCHING), mIsForBrowser(!mRemoteType.IsEmpty()), @@ -5934,25 +5909,23 @@ mozilla::ipc::IPCResult ContentParent::RecvRestoreBrowsingContextChildren( return IPC_OK(); } -void ContentParent::RegisterRemoteWorkerActor() { - auto lock = mRemoteWorkerActorData.Lock(); - ++lock->mCount; -} +void ContentParent::RegisterRemoteWorkerActor() { ++mRemoteWorkerActors; } void ContentParent::UnregisterRemoveWorkerActor() { MOZ_ASSERT(NS_IsMainThread()); - { - auto lock = mRemoteWorkerActorData.Lock(); - if (--lock->mCount) { - return; - } + if (--mRemoteWorkerActors) { + return; } ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); if (!cpm->GetBrowserParentCountByProcessId(ChildID()) && !ShouldKeepProcessAlive() && !TryToRecycle()) { - MaybeAsyncSendShutDownMessage(); + // In the case of normal shutdown, send a shutdown message to child to + // allow it to perform shutdown tasks. + MessageLoop::current()->PostTask(NewRunnableMethod( + "dom::ContentParent::ShutDownProcess", this, + &ContentParent::ShutDownProcess, SEND_SHUTDOWN_MESSAGE)); } } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 0f9bbf510555..4b7b57b7d4dd 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -18,7 +18,6 @@ #include "mozilla/ipc/PParentToChildStreamParent.h" #include "mozilla/ipc/PChildToParentStreamParent.h" #include "mozilla/Attributes.h" -#include "mozilla/DataMutex.h" #include "mozilla/FileUtils.h" #include "mozilla/HalTypes.h" #include "mozilla/LinkedList.h" @@ -115,7 +114,6 @@ class MemoryReport; class TabContext; class GetFilesHelper; class MemoryReportRequestHost; -class RemoteWorkerManager; struct CancelContentJSOptions; #define NS_CONTENTPARENT_IID \ @@ -147,7 +145,6 @@ class ContentParent final : public PContentParent, friend class mozilla::PreallocatedProcessManagerImpl; friend class PContentParent; - friend class mozilla::dom::RemoteWorkerManager; #ifdef FUZZING friend class mozilla::ipc::ProtocolFuzzerHelper; #endif @@ -751,7 +748,7 @@ class ContentParent final : public PContentParent, * Decide whether the process should be kept alive even when it would normally * be shut down, for example when all its tabs are closed. */ - bool ShouldKeepProcessAlive(); + bool ShouldKeepProcessAlive() const; /** * Mark this ContentParent as "troubled". This means that it is still alive, @@ -777,8 +774,6 @@ class ContentParent final : public PContentParent, CLOSE_CHANNEL_WITH_ERROR, }; - void MaybeAsyncSendShutDownMessage(); - /** * Exit the subprocess and vamoose. After this call IsAlive() * will return false and this ContentParent will not be returned @@ -1241,24 +1236,11 @@ class ContentParent final : public PContentParent, // timer. nsCOMPtr mForceKillTimer; - // `mCount` is increased when a RemoteWorkerParent actor is created for this - // ContentProcess and it is decreased when the actor is destroyed. - // - // `mShutdownStarted` is flipped to `true` when a runnable that calls - // `ShutDownProcess` is dispatched; it's needed because the corresponding - // Content Process may be shutdown if there's no remote worker actors, and - // decrementing `mCount` and the call to `ShutDownProcess` are async. So, - // when a worker is going to be spawned and we see that `mCount` is 0, - // we can decide whether or not to use that process based on the value of - // `mShutdownStarted.` - // + // Number of active remote workers. This value is increased when a + // RemoteWorkerParent actor is created for this ContentProcess and it is + // decreased when the actor is destroyed. // It's touched on PBackground thread and on main-thread. - struct RemoteWorkerActorData { - uint32_t mCount = 0; - bool mShutdownStarted = false; - }; - - DataMutex mRemoteWorkerActorData; + Atomic mRemoteWorkerActors; // How many tabs we're waiting to finish their destruction // sequence. Precisely, how many BrowserParents have called diff --git a/dom/ipc/URLClassifierParent.h b/dom/ipc/URLClassifierParent.h index 37689e9c268b..549e7398a0b1 100644 --- a/dom/ipc/URLClassifierParent.h +++ b/dom/ipc/URLClassifierParent.h @@ -16,8 +16,6 @@ namespace mozilla { namespace dom { -class IPCURLClassifierFeature; - ////////////////////////////////////////////////////////////// // URLClassifierParent diff --git a/dom/media/webrtc/PMediaTransport.ipdl b/dom/media/webrtc/PMediaTransport.ipdl index 5ccaf6040d81..9ec8894286b1 100644 --- a/dom/media/webrtc/PMediaTransport.ipdl +++ b/dom/media/webrtc/PMediaTransport.ipdl @@ -23,7 +23,6 @@ using TabId from "mozilla/dom/ipc/IdType.h"; // ParamTraits stuff for our own classes using MediaPacket from "mtransport/mediapacket.h"; -include "mozilla/net/NrIceStunAddrMessageUtils.h"; using net::NrIceStunAddrArray from "mozilla/net/PStunAddrsParams.h"; #endif // MOZ_WEBRTC diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp index 7650d84d2e7a..112c08e9e984 100644 --- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -27,7 +27,6 @@ #include "mozilla/dom/PromiseWorkerProxy.h" #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" #include "mozilla/dom/ServiceWorkerManager.h" -#include "mozilla/dom/ServiceWorkerUtils.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRunnable.h" #include "mozilla/dom/WorkerScope.h" diff --git a/dom/performance/moz.build b/dom/performance/moz.build index 5e53327d684f..d588c26794aa 100644 --- a/dom/performance/moz.build +++ b/dom/performance/moz.build @@ -42,8 +42,6 @@ UNIFIED_SOURCES += [ 'PerformanceWorker.cpp', ] -include('/ipc/chromium/chromium-config.mozbuild') - MOCHITEST_MANIFESTS += [ 'tests/mochitest.ini' ] FINAL_LIBRARY = 'xul' diff --git a/dom/serviceworkers/FetchEventOpChild.cpp b/dom/serviceworkers/FetchEventOpChild.cpp deleted file mode 100644 index 6d249482f096..000000000000 --- a/dom/serviceworkers/FetchEventOpChild.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* -*- 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 "FetchEventOpChild.h" - -#include - -#include "MainThreadUtils.h" -#include "nsContentPolicyUtils.h" -#include "nsContentUtils.h" -#include "nsDebug.h" -#include "nsError.h" -#include "nsIChannel.h" -#include "nsIConsoleReportCollector.h" -#include "nsIContentPolicy.h" -#include "nsIInputStream.h" -#include "nsILoadInfo.h" -#include "nsINetworkInterceptController.h" -#include "nsIObserverService.h" -#include "nsIScriptError.h" -#include "nsISupportsImpl.h" -#include "nsIURI.h" -#include "nsNetUtil.h" -#include "nsProxyRelease.h" -#include "nsTArray.h" -#include "nsThreadUtils.h" - -#include "ServiceWorkerPrivate.h" -#include "mozilla/Assertions.h" -#include "mozilla/LoadInfo.h" -#include "mozilla/Services.h" -#include "mozilla/Telemetry.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/InternalHeaders.h" -#include "mozilla/dom/InternalResponse.h" -#include "mozilla/dom/PRemoteWorkerControllerChild.h" -#include "mozilla/dom/ServiceWorkerRegistrationInfo.h" -#include "mozilla/net/NeckoChannelParams.h" - -namespace mozilla { -namespace dom { - -namespace { - -bool CSPPermitsResponse(nsILoadInfo* aLoadInfo, InternalResponse* aResponse, - const nsACString& aWorkerScriptSpec) { - AssertIsOnMainThread(); - MOZ_ASSERT(aLoadInfo); - - nsCString url = aResponse->GetUnfilteredURL(); - if (url.IsEmpty()) { - // Synthetic response. - url = aWorkerScriptSpec; - } - - nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - int16_t decision = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(uri, aLoadInfo, EmptyCString(), &decision); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - return decision == nsIContentPolicy::ACCEPT; -} - -void AsyncLog(nsIInterceptedChannel* aChannel, const nsACString& aScriptSpec, - uint32_t aLineNumber, uint32_t aColumnNumber, - const nsACString& aMessageName, nsTArray&& aParams) { - AssertIsOnMainThread(); - MOZ_ASSERT(aChannel); - - nsCOMPtr reporter = - aChannel->GetConsoleReportCollector(); - - if (reporter) { - // NOTE: is appears that `const nsTArray&` is required for - // nsIConsoleReportCollector::AddConsoleReport to resolve to the correct - // overload. - const nsTArray params = std::move(aParams); - - reporter->AddConsoleReport( - nsIScriptError::errorFlag, - NS_LITERAL_CSTRING("Service Worker Interception"), - nsContentUtils::eDOM_PROPERTIES, aScriptSpec, aLineNumber, - aColumnNumber, aMessageName, params); - } -} - -class SynthesizeResponseWatcher final : public nsIInterceptedBodyCallback { - public: - NS_DECL_THREADSAFE_ISUPPORTS - - SynthesizeResponseWatcher( - const nsMainThreadPtrHandle& aInterceptedChannel, - const nsMainThreadPtrHandle& aRegistration, - const bool aIsNonSubresourceRequest, - FetchEventRespondWithClosure&& aClosure, nsAString&& aRequestURL) - : mInterceptedChannel(aInterceptedChannel), - mRegistration(aRegistration), - mIsNonSubresourceRequest(aIsNonSubresourceRequest), - mClosure(std::move(aClosure)), - mRequestURL(std::move(aRequestURL)) { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - MOZ_ASSERT(mRegistration); - } - - NS_IMETHOD - BodyComplete(nsresult aRv) override { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - - if (NS_WARN_IF(NS_FAILED(aRv))) { - AsyncLog(mInterceptedChannel, mClosure.respondWithScriptSpec(), - mClosure.respondWithLineNumber(), - mClosure.respondWithColumnNumber(), - NS_LITERAL_CSTRING("InterceptionFailedWithURL"), {mRequestURL}); - - CancelInterception(NS_ERROR_INTERCEPTION_FAILED); - - return NS_OK; - } - - nsresult rv = mInterceptedChannel->FinishSynthesizedResponse(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - CancelInterception(rv); - } - - mInterceptedChannel = nullptr; - - return NS_OK; - } - - // See FetchEventOpChild::MaybeScheduleRegistrationUpdate() for comments. - void CancelInterception(nsresult aStatus) { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - MOZ_ASSERT(mRegistration); - - mInterceptedChannel->CancelInterception(aStatus); - - if (mIsNonSubresourceRequest) { - mRegistration->MaybeScheduleUpdate(); - } else { - mRegistration->MaybeScheduleTimeCheckAndUpdate(); - } - - mInterceptedChannel = nullptr; - mRegistration = nullptr; - } - - private: - ~SynthesizeResponseWatcher() { - if (NS_WARN_IF(mInterceptedChannel)) { - CancelInterception(NS_ERROR_DOM_ABORT_ERR); - } - } - - nsMainThreadPtrHandle mInterceptedChannel; - nsMainThreadPtrHandle mRegistration; - const bool mIsNonSubresourceRequest; - const FetchEventRespondWithClosure mClosure; - const nsString mRequestURL; -}; - -NS_IMPL_ISUPPORTS(SynthesizeResponseWatcher, nsIInterceptedBodyCallback) - -} // anonymous namespace - -/* static */ RefPtr FetchEventOpChild::Create( - PRemoteWorkerControllerChild* aManager, - ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr aInterceptedChannel, - RefPtr aRegistration, - RefPtr&& aKeepAliveToken) { - AssertIsOnMainThread(); - MOZ_ASSERT(aManager); - MOZ_ASSERT(aInterceptedChannel); - MOZ_ASSERT(aKeepAliveToken); - - FetchEventOpChild* actor = new FetchEventOpChild( - std::move(aArgs), std::move(aInterceptedChannel), - std::move(aRegistration), std::move(aKeepAliveToken)); - Unused << aManager->SendPFetchEventOpConstructor(actor, actor->mArgs); - return actor->mPromiseHolder.Ensure(__func__); -} - -FetchEventOpChild::~FetchEventOpChild() { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannelHandled); - MOZ_DIAGNOSTIC_ASSERT(mPromiseHolder.IsEmpty()); -} - -FetchEventOpChild::FetchEventOpChild( - ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr&& aInterceptedChannel, - RefPtr&& aRegistration, - RefPtr&& aKeepAliveToken) - : mArgs(std::move(aArgs)), - mInterceptedChannel(std::move(aInterceptedChannel)), - mRegistration(std::move(aRegistration)), - mKeepAliveToken(std::move(aKeepAliveToken)) {} - -mozilla::ipc::IPCResult FetchEventOpChild::RecvAsyncLog( - const nsCString& aScriptSpec, const uint32_t& aLineNumber, - const uint32_t& aColumnNumber, const nsCString& aMessageName, - nsTArray&& aParams) { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - - AsyncLog(mInterceptedChannel, aScriptSpec, aLineNumber, aColumnNumber, - aMessageName, std::move(aParams)); - - return IPC_OK(); -} - -mozilla::ipc::IPCResult FetchEventOpChild::RecvRespondWith( - IPCFetchEventRespondWithResult&& aResult) { - AssertIsOnMainThread(); - - switch (aResult.type()) { - case IPCFetchEventRespondWithResult::TIPCSynthesizeResponseArgs: - SynthesizeResponse(std::move(aResult.get_IPCSynthesizeResponseArgs())); - break; - case IPCFetchEventRespondWithResult::TResetInterceptionArgs: - ResetInterception(); - break; - case IPCFetchEventRespondWithResult::TCancelInterceptionArgs: - CancelInterception(aResult.get_CancelInterceptionArgs().status()); - break; - default: - MOZ_CRASH("Unknown IPCFetchEventRespondWithResult type!"); - break; - } - - return IPC_OK(); -} - -mozilla::ipc::IPCResult FetchEventOpChild::Recv__delete__( - const ServiceWorkerFetchEventOpResult& aResult) { - AssertIsOnMainThread(); - MOZ_ASSERT(mRegistration); - - if (NS_WARN_IF(!mInterceptedChannelHandled)) { - MOZ_ASSERT(NS_FAILED(aResult.rv())); - NS_WARNING( - "Failed to handle intercepted network request; canceling " - "interception!"); - - CancelInterception(aResult.rv()); - } - - mPromiseHolder.ResolveIfExists(true, __func__); - - /** - * This corresponds to the "Fire Functional Event" algorithm's step 9: - * - * "If the time difference in seconds calculated by the current time minus - * registration's last update check time is greater than 84600, invoke Soft - * Update algorithm with registration." - * - * TODO: this is probably being called later than it should be; it should be - * called ASAP after dispatching the FetchEvent. - */ - mRegistration->MaybeScheduleTimeCheckAndUpdate(); - - return IPC_OK(); -} - -void FetchEventOpChild::ActorDestroy(ActorDestroyReason) { - AssertIsOnMainThread(); - - // If `Recv__delete__` was called, it would have resolved the promise already. - mPromiseHolder.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__); - - if (NS_WARN_IF(!mInterceptedChannelHandled)) { - Unused << Recv__delete__(NS_ERROR_DOM_ABORT_ERR); - } -} - -nsresult FetchEventOpChild::StartSynthesizedResponse( - IPCSynthesizeResponseArgs&& aArgs) { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - MOZ_ASSERT(!mInterceptedChannelHandled); - MOZ_ASSERT(mRegistration); - - /** - * TODO: moving the IPCInternalResponse won't do anything right now because - * there isn't a prefect-forwarding or rvalue-ref-parameter overload of - * `InternalResponse::FromIPC().` - */ - RefPtr response = - InternalResponse::FromIPC(aArgs.internalResponse()); - if (NS_WARN_IF(!response)) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr underlyingChannel; - nsresult rv = - mInterceptedChannel->GetChannel(getter_AddRefs(underlyingChannel)); - if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!underlyingChannel)) { - return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE; - } - - nsCOMPtr loadInfo = underlyingChannel->LoadInfo(); - if (!CSPPermitsResponse(loadInfo, response, mArgs.workerScriptSpec())) { - return NS_ERROR_CONTENT_BLOCKED; - } - - MOZ_ASSERT(response->GetChannelInfo().IsInitialized()); - ChannelInfo channelInfo = response->GetChannelInfo(); - rv = mInterceptedChannel->SetChannelInfo(&channelInfo); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_ERROR_INTERCEPTION_FAILED; - } - - rv = mInterceptedChannel->SynthesizeStatus( - response->GetUnfilteredStatus(), response->GetUnfilteredStatusText()); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - AutoTArray entries; - response->UnfilteredHeaders()->GetEntries(entries); - for (auto& entry : entries) { - mInterceptedChannel->SynthesizeHeader(entry.mName, entry.mValue); - } - - auto castLoadInfo = static_cast(loadInfo.get()); - castLoadInfo->SynthesizeServiceWorkerTainting(response->GetTainting()); - - // Get the preferred alternative data type of the outer channel - nsAutoCString preferredAltDataType(EmptyCString()); - nsCOMPtr outerChannel = - do_QueryInterface(underlyingChannel); - if (outerChannel && - !outerChannel->PreferredAlternativeDataTypes().IsEmpty()) { - preferredAltDataType.Assign( - outerChannel->PreferredAlternativeDataTypes()[0].type()); - } - - nsCOMPtr body; - if (preferredAltDataType.Equals(response->GetAlternativeDataType())) { - body = response->TakeAlternativeBody(); - } - if (!body) { - response->GetUnfilteredBody(getter_AddRefs(body)); - } else { - Telemetry::ScalarAdd(Telemetry::ScalarID::SW_ALTERNATIVE_BODY_USED_COUNT, - 1); - } - - // Propagate the URL to the content if the request mode is not "navigate". - // Note that, we only reflect the final URL if the response.redirected is - // false. We propagate all the URLs if the response.redirected is true. - const IPCInternalRequest& request = mArgs.internalRequest(); - nsAutoCString responseURL; - if (request.requestMode() != RequestMode::Navigate) { - responseURL = response->GetUnfilteredURL(); - - // Similar to how we apply the request fragment to redirects automatically - // we also want to apply it automatically when propagating the response - // URL from a service worker interception. Currently response.url strips - // the fragment, so this will never conflict with an existing fragment - // on the response. In the future we will have to check for a response - // fragment and avoid overriding in that case. - if (!request.fragment().IsEmpty() && !responseURL.IsEmpty()) { - MOZ_ASSERT(!responseURL.Contains('#')); - responseURL.AppendLiteral("#"); - responseURL.Append(request.fragment()); - } - } - - nsMainThreadPtrHandle interceptedChannel( - new nsMainThreadPtrHolder( - "nsIInterceptedChannel", mInterceptedChannel, false)); - - nsMainThreadPtrHandle registration( - new nsMainThreadPtrHolder( - "ServiceWorkerRegistrationInfo", mRegistration, false)); - - nsCString requestURL = request.urlList().LastElement(); - if (!request.fragment().IsEmpty()) { - requestURL.AppendLiteral("#"); - requestURL.Append(request.fragment()); - } - - RefPtr watcher = new SynthesizeResponseWatcher( - interceptedChannel, registration, mArgs.isNonSubresourceRequest(), - std::move(aArgs.closure()), NS_ConvertUTF8toUTF16(responseURL)); - - rv = mInterceptedChannel->StartSynthesizedResponse( - body, watcher, nullptr /* TODO */, responseURL, response->IsRedirected()); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr obsService = services::GetObserverService(); - if (obsService) { - obsService->NotifyObservers(underlyingChannel, - "service-worker-synthesized-response", nullptr); - } - - return rv; -} - -void FetchEventOpChild::SynthesizeResponse(IPCSynthesizeResponseArgs&& aArgs) { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - MOZ_ASSERT(!mInterceptedChannelHandled); - - nsresult rv = StartSynthesizedResponse(std::move(aArgs)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - NS_WARNING("Failed to synthesize response!"); - - mInterceptedChannel->CancelInterception(rv); - } - - mInterceptedChannelHandled = true; - - MaybeScheduleRegistrationUpdate(); -} - -void FetchEventOpChild::ResetInterception() { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - MOZ_ASSERT(!mInterceptedChannelHandled); - - nsresult rv = mInterceptedChannel->ResetInterception(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - NS_WARNING("Failed to resume intercepted network request!"); - - mInterceptedChannel->CancelInterception(rv); - } - - mInterceptedChannelHandled = true; - - MaybeScheduleRegistrationUpdate(); -} - -void FetchEventOpChild::CancelInterception(nsresult aStatus) { - AssertIsOnMainThread(); - MOZ_ASSERT(mInterceptedChannel); - MOZ_ASSERT(!mInterceptedChannelHandled); - MOZ_ASSERT(NS_FAILED(aStatus)); - - mInterceptedChannel->CancelInterception(aStatus); - mInterceptedChannelHandled = true; - - MaybeScheduleRegistrationUpdate(); -} - -/** - * This corresponds to the "Handle Fetch" algorithm's steps 20.3, 21.2, and - * 22.2: - * - * "If request is a non-subresource request, or request is a subresource - * request and the time difference in seconds calculated by the current time - * minus registration's last update check time is greater than 86400, invoke - * Soft Update algorithm with registration." - */ -void FetchEventOpChild::MaybeScheduleRegistrationUpdate() const { - AssertIsOnMainThread(); - MOZ_ASSERT(mRegistration); - MOZ_ASSERT(mInterceptedChannelHandled); - - if (mArgs.isNonSubresourceRequest()) { - mRegistration->MaybeScheduleUpdate(); - } else { - mRegistration->MaybeScheduleTimeCheckAndUpdate(); - } -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/FetchEventOpChild.h b/dom/serviceworkers/FetchEventOpChild.h deleted file mode 100644 index c96ef73552a2..000000000000 --- a/dom/serviceworkers/FetchEventOpChild.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_fetcheventopchild_h__ -#define mozilla_dom_fetcheventopchild_h__ - -#include "nsCOMPtr.h" - -#include "mozilla/MozPromise.h" -#include "mozilla/RefPtr.h" -#include "mozilla/dom/PFetchEventOpChild.h" -#include "mozilla/dom/ServiceWorkerOpArgs.h" - -class nsIInterceptedChannel; - -namespace mozilla { -namespace dom { - -class KeepAliveToken; -class PRemoteWorkerControllerChild; -class ServiceWorkerRegistrationInfo; - -/** - * FetchEventOpChild represents an in-flight FetchEvent operation. - */ -class FetchEventOpChild final : public PFetchEventOpChild { - friend class PFetchEventOpChild; - - public: - static RefPtr Create( - PRemoteWorkerControllerChild* aManager, - ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr aInterceptedChannel, - RefPtr aRegistrationInfo, - RefPtr&& aKeepAliveToken); - - ~FetchEventOpChild(); - - private: - FetchEventOpChild(ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr&& aInterceptedChannel, - RefPtr&& aRegistrationInfo, - RefPtr&& aKeepAliveToken); - - mozilla::ipc::IPCResult RecvAsyncLog(const nsCString& aScriptSpec, - const uint32_t& aLineNumber, - const uint32_t& aColumnNumber, - const nsCString& aMessageName, - nsTArray&& aParams); - - mozilla::ipc::IPCResult RecvRespondWith( - IPCFetchEventRespondWithResult&& aResult); - - mozilla::ipc::IPCResult Recv__delete__( - const ServiceWorkerFetchEventOpResult& aResult) override; - - void ActorDestroy(ActorDestroyReason) override; - - nsresult StartSynthesizedResponse(IPCSynthesizeResponseArgs&& aArgs); - - void SynthesizeResponse(IPCSynthesizeResponseArgs&& aArgs); - - void ResetInterception(); - - void CancelInterception(nsresult aStatus); - - void MaybeScheduleRegistrationUpdate() const; - - const ServiceWorkerFetchEventOpArgs mArgs; - nsCOMPtr mInterceptedChannel; - RefPtr mRegistration; - RefPtr mKeepAliveToken; - bool mInterceptedChannelHandled = false; - MozPromiseHolder mPromiseHolder; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_fetcheventopchild_h__ diff --git a/dom/serviceworkers/FetchEventOpParent.cpp b/dom/serviceworkers/FetchEventOpParent.cpp deleted file mode 100644 index 016b46e34ce2..000000000000 --- a/dom/serviceworkers/FetchEventOpParent.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- 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 "FetchEventOpParent.h" - -#include "nsDebug.h" - -#include "mozilla/Assertions.h" -#include "mozilla/RefPtr.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/FetchEventOpProxyParent.h" -#include "mozilla/dom/RemoteWorkerControllerParent.h" -#include "mozilla/dom/RemoteWorkerParent.h" -#include "mozilla/ipc/BackgroundParent.h" - -namespace mozilla { - -using namespace ipc; - -namespace dom { - -void FetchEventOpParent::Initialize( - const ServiceWorkerFetchEventOpArgs& aArgs) { - AssertIsInMainProcess(); - AssertIsOnBackgroundThread(); - - RemoteWorkerControllerParent* manager = - static_cast(Manager()); - MOZ_ASSERT(manager); - - // This will be null when the manager's RemoteWorkerController has shutdown. - RefPtr proxyManager = manager->GetRemoteWorkerParent(); - if (NS_WARN_IF(!proxyManager)) { - Unused << Send__delete__(this, NS_ERROR_DOM_ABORT_ERR); - - return; - } - - FetchEventOpProxyParent::Create(proxyManager.get(), aArgs, this); -} - -void FetchEventOpParent::ActorDestroy(ActorDestroyReason) { - AssertIsOnBackgroundThread(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/FetchEventOpParent.h b/dom/serviceworkers/FetchEventOpParent.h deleted file mode 100644 index e59f1697559d..000000000000 --- a/dom/serviceworkers/FetchEventOpParent.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_fetcheventopparent_h__ -#define mozilla_dom_fetcheventopparent_h__ - -#include "nsISupports.h" - -#include "mozilla/dom/PFetchEventOpParent.h" - -namespace mozilla { -namespace dom { - -class ServiceWorkerFetchEventOpArgs; - -class FetchEventOpParent final : public PFetchEventOpParent { - friend class PFetchEventOpParent; - - public: - NS_INLINE_DECL_REFCOUNTING(FetchEventOpParent) - - FetchEventOpParent() = default; - - void Initialize(const ServiceWorkerFetchEventOpArgs& aArgs); - - private: - ~FetchEventOpParent() = default; - - void ActorDestroy(ActorDestroyReason) override; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_fetcheventopparent_h__ diff --git a/dom/serviceworkers/FetchEventOpProxyChild.cpp b/dom/serviceworkers/FetchEventOpProxyChild.cpp deleted file mode 100644 index c4a5f7a9e9c5..000000000000 --- a/dom/serviceworkers/FetchEventOpProxyChild.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* -*- 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 "FetchEventOpProxyChild.h" - -#include - -#include "nsCOMPtr.h" -#include "nsDebug.h" -#include "nsThreadUtils.h" - -#include "mozilla/Assertions.h" -#include "mozilla/RefPtr.h" -#include "mozilla/UniquePtr.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/RemoteWorkerChild.h" -#include "mozilla/dom/RemoteWorkerService.h" -#include "mozilla/dom/ServiceWorkerOp.h" -#include "mozilla/dom/WorkerCommon.h" -#include "mozilla/ipc/BackgroundChild.h" -#include "mozilla/ipc/IPCStreamUtils.h" - -namespace mozilla { - -using namespace ipc; - -namespace dom { - -namespace { - -nsresult GetIPCSynthesizeResponseArgs( - IPCSynthesizeResponseArgs* aIPCArgs, SynthesizeResponseArgs&& aArgs, - UniquePtr& aAutoBodyStream, - UniquePtr& aAutoAlternativeBodyStream) { - MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - - PBackgroundChild* bgChild = BackgroundChild::GetOrCreateForCurrentThread(); - - if (NS_WARN_IF(!bgChild)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - aArgs.first()->ToIPC(&aIPCArgs->internalResponse(), bgChild, aAutoBodyStream, - aAutoAlternativeBodyStream); - aIPCArgs->closure() = std::move(aArgs.second()); - - return NS_OK; -} - -} // anonymous namespace - -void FetchEventOpProxyChild::Initialize( - const ServiceWorkerFetchEventOpArgs& aArgs) { - MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - MOZ_ASSERT(!mOp); - - mInternalRequest = new InternalRequest(aArgs.internalRequest()); - - RemoteWorkerChild* manager = static_cast(Manager()); - MOZ_ASSERT(manager); - - RefPtr self = this; - - auto callback = [self](const ServiceWorkerOpResult& aResult) { - if (!self->CanSend()) { - return; - } - - if (NS_WARN_IF(aResult.type() == ServiceWorkerOpResult::Tnsresult)) { - Unused << self->Send__delete__(self, aResult.get_nsresult()); - return; - } - - MOZ_ASSERT(aResult.type() == - ServiceWorkerOpResult::TServiceWorkerFetchEventOpResult); - - Unused << self->Send__delete__(self, aResult); - }; - - RefPtr op = ServiceWorkerOp::Create(aArgs, std::move(callback)) - .template downcast(); - - MOZ_ASSERT(op); - - op->SetActor(this); - mOp = op; - - op->GetRespondWithPromise() - ->Then(GetCurrentThreadSerialEventTarget(), __func__, - [self = std::move(self)]( - FetchEventRespondWithPromise::ResolveOrRejectValue&& aResult) { - self->mRespondWithPromiseRequestHolder.Complete(); - - if (NS_WARN_IF(aResult.IsReject())) { - MOZ_ASSERT(NS_FAILED(aResult.RejectValue())); - - Unused << self->SendRespondWith( - CancelInterceptionArgs(aResult.RejectValue())); - return; - } - - auto& result = aResult.ResolveValue(); - - if (result.is()) { - IPCSynthesizeResponseArgs ipcArgs; - UniquePtr autoBodyStream = - MakeUnique(); - UniquePtr autoAlternativeBodyStream = - MakeUnique(); - nsresult rv = GetIPCSynthesizeResponseArgs( - &ipcArgs, result.extract(), - autoBodyStream, autoAlternativeBodyStream); - - if (NS_WARN_IF(NS_FAILED(rv))) { - Unused << self->SendRespondWith(CancelInterceptionArgs(rv)); - return; - } - - Unused << self->SendRespondWith(ipcArgs); - autoBodyStream->TakeOptionalValue(); - autoAlternativeBodyStream->TakeOptionalValue(); - } else if (result.is()) { - Unused << self->SendRespondWith( - result.extract()); - } else { - Unused << self->SendRespondWith( - result.extract()); - } - }) - ->Track(mRespondWithPromiseRequestHolder); - - manager->MaybeStartOp(std::move(op)); -} - -RefPtr FetchEventOpProxyChild::ExtractInternalRequest() { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(mInternalRequest); - - return RefPtr(std::move(mInternalRequest)); -} - -void FetchEventOpProxyChild::ActorDestroy(ActorDestroyReason) { - Unused << NS_WARN_IF(mRespondWithPromiseRequestHolder.Exists()); - mRespondWithPromiseRequestHolder.DisconnectIfExists(); - - mOp->RevokeActor(this); - mOp = nullptr; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/FetchEventOpProxyChild.h b/dom/serviceworkers/FetchEventOpProxyChild.h deleted file mode 100644 index 80b0c053e359..000000000000 --- a/dom/serviceworkers/FetchEventOpProxyChild.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_fetcheventopproxychild_h__ -#define mozilla_dom_fetcheventopproxychild_h__ - -#include "nsISupportsImpl.h" - -#include "ServiceWorkerOp.h" -#include "ServiceWorkerOpPromise.h" -#include "mozilla/RefPtr.h" -#include "mozilla/dom/InternalRequest.h" -#include "mozilla/dom/PFetchEventOpProxyChild.h" - -namespace mozilla { -namespace dom { - -class InternalRequest; -class ServiceWorkerFetchEventOpArgs; - -class FetchEventOpProxyChild final : public PFetchEventOpProxyChild { - friend class PFetchEventOpProxyChild; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchEventOpProxyChild) - - FetchEventOpProxyChild() = default; - - void Initialize(const ServiceWorkerFetchEventOpArgs& aArgs); - - // Must only be called once and on a worker thread. - RefPtr ExtractInternalRequest(); - - private: - ~FetchEventOpProxyChild() = default; - - void ActorDestroy(ActorDestroyReason) override; - - MozPromiseRequestHolder - mRespondWithPromiseRequestHolder; - - RefPtr mOp; - - // Initialized on RemoteWorkerService::Thread, read on a worker thread. - RefPtr mInternalRequest; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_fetcheventopproxychild_h__ diff --git a/dom/serviceworkers/FetchEventOpProxyParent.cpp b/dom/serviceworkers/FetchEventOpProxyParent.cpp deleted file mode 100644 index a00201873929..000000000000 --- a/dom/serviceworkers/FetchEventOpProxyParent.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* -*- 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 "FetchEventOpProxyParent.h" - -#include - -#include "nsCOMPtr.h" -#include "nsIInputStream.h" - -#include "mozilla/Assertions.h" -#include "mozilla/DebugOnly.h" -#include "mozilla/UniquePtr.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/FetchEventOpParent.h" -#include "mozilla/ipc/BackgroundParent.h" -#include "mozilla/ipc/IPCStreamUtils.h" - -namespace mozilla { - -using namespace ipc; - -namespace dom { - -namespace { - -void MaybeDeserializeAndReserialize(const Maybe& aDeserialize, - Maybe& aReserialize, - UniquePtr& aAutoStream, - PBackgroundParent* aManager) { - nsCOMPtr maybeDeserialized = - DeserializeIPCStream(aDeserialize); - - if (!maybeDeserialized) { - return; - } - - aAutoStream.reset(new AutoIPCStream(aReserialize)); - DebugOnly ok = aAutoStream->Serialize(maybeDeserialized, aManager); - MOZ_ASSERT(ok); -} - -} // anonymous namespace - -/* static */ void FetchEventOpProxyParent::Create( - PRemoteWorkerParent* aManager, const ServiceWorkerFetchEventOpArgs& aArgs, - RefPtr aReal) { - AssertIsInMainProcess(); - AssertIsOnBackgroundThread(); - MOZ_ASSERT(aManager); - MOZ_ASSERT(aReal); - - FetchEventOpProxyParent* actor = - new FetchEventOpProxyParent(std::move(aReal)); - - if (aArgs.internalRequest().body().isNothing()) { - Unused << aManager->SendPFetchEventOpProxyConstructor(actor, aArgs); - return; - } - - ServiceWorkerFetchEventOpArgs copyArgs = aArgs; - IPCInternalRequest& copyRequest = copyArgs.internalRequest(); - - PBackgroundParent* bgParent = aManager->Manager(); - MOZ_ASSERT(bgParent); - - UniquePtr autoBodyStream = MakeUnique(); - MaybeDeserializeAndReserialize(aArgs.internalRequest().body(), - copyRequest.body(), autoBodyStream, bgParent); - - Unused << aManager->SendPFetchEventOpProxyConstructor(actor, copyArgs); - autoBodyStream->TakeOptionalValue(); -} - -FetchEventOpProxyParent::~FetchEventOpProxyParent() { - AssertIsOnBackgroundThread(); -} - -FetchEventOpProxyParent::FetchEventOpProxyParent( - RefPtr&& aReal) - : mReal(std::move(aReal)) {} - -mozilla::ipc::IPCResult FetchEventOpProxyParent::RecvAsyncLog( - const nsCString& aScriptSpec, const uint32_t& aLineNumber, - const uint32_t& aColumnNumber, const nsCString& aMessageName, - nsTArray&& aParams) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mReal); - - Unused << mReal->SendAsyncLog(aScriptSpec, aLineNumber, aColumnNumber, - aMessageName, aParams); - - return IPC_OK(); -} - -mozilla::ipc::IPCResult FetchEventOpProxyParent::RecvRespondWith( - const IPCFetchEventRespondWithResult& aResult) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mReal); - - // IPCSynthesizeResponseArgs possibly contains an IPCStream. If so, - // deserialize it and reserialize it before forwarding it to the main thread. - if (aResult.type() == - IPCFetchEventRespondWithResult::TIPCSynthesizeResponseArgs) { - const IPCSynthesizeResponseArgs& originalArgs = - aResult.get_IPCSynthesizeResponseArgs(); - const IPCInternalResponse& originalResponse = - originalArgs.internalResponse(); - - // Do nothing if neither the body nor the alt. body can be deserialized. - if (!originalResponse.body() && !originalResponse.alternativeBody()) { - Unused << mReal->SendRespondWith(aResult); - return IPC_OK(); - } - - IPCSynthesizeResponseArgs copyArgs = originalArgs; - IPCInternalResponse& copyResponse = copyArgs.internalResponse(); - - PRemoteWorkerControllerParent* manager = mReal->Manager(); - MOZ_ASSERT(manager); - - PBackgroundParent* bgParent = manager->Manager(); - MOZ_ASSERT(bgParent); - - UniquePtr autoBodyStream = MakeUnique(); - UniquePtr autoAlternativeBodyStream = - MakeUnique(); - - MaybeDeserializeAndReserialize(originalResponse.body(), copyResponse.body(), - autoBodyStream, bgParent); - MaybeDeserializeAndReserialize(originalResponse.alternativeBody(), - copyResponse.alternativeBody(), - autoAlternativeBodyStream, bgParent); - - Unused << mReal->SendRespondWith(copyArgs); - - autoBodyStream->TakeOptionalValue(); - autoAlternativeBodyStream->TakeOptionalValue(); - } else { - Unused << mReal->SendRespondWith(aResult); - } - - return IPC_OK(); -} - -mozilla::ipc::IPCResult FetchEventOpProxyParent::Recv__delete__( - const ServiceWorkerFetchEventOpResult& aResult) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mReal); - - Unused << mReal->Send__delete__(mReal, aResult); - mReal = nullptr; - - return IPC_OK(); -} - -void FetchEventOpProxyParent::ActorDestroy(ActorDestroyReason) { - AssertIsOnBackgroundThread(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/FetchEventOpProxyParent.h b/dom/serviceworkers/FetchEventOpProxyParent.h deleted file mode 100644 index 72a48ec6942a..000000000000 --- a/dom/serviceworkers/FetchEventOpProxyParent.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_fetcheventopproxyparent_h__ -#define mozilla_dom_fetcheventopproxyparent_h__ - -#include "mozilla/RefPtr.h" -#include "mozilla/dom/PFetchEventOpProxyParent.h" - -namespace mozilla { -namespace dom { - -class FetchEventOpParent; -class PRemoteWorkerParent; -class ServiceWorkerFetchEventOpArgs; - -/** - * FetchEventOpProxyParent owns a FetchEventOpParent and is responsible for - * calling PFetchEventOpParent::Send__delete__. - */ -class FetchEventOpProxyParent final : public PFetchEventOpProxyParent { - friend class PFetchEventOpProxyParent; - - public: - static void Create(PRemoteWorkerParent* aManager, - const ServiceWorkerFetchEventOpArgs& aArgs, - RefPtr aReal); - - ~FetchEventOpProxyParent(); - - private: - explicit FetchEventOpProxyParent(RefPtr&& aReal); - - mozilla::ipc::IPCResult RecvAsyncLog(const nsCString& aScriptSpec, - const uint32_t& aLineNumber, - const uint32_t& aColumnNumber, - const nsCString& aMessageName, - nsTArray&& aParams); - - mozilla::ipc::IPCResult RecvRespondWith( - const IPCFetchEventRespondWithResult& aResult); - - mozilla::ipc::IPCResult Recv__delete__( - const ServiceWorkerFetchEventOpResult& aResult) override; - - void ActorDestroy(ActorDestroyReason) override; - - RefPtr mReal; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_fetcheventopproxyparent_h__ diff --git a/dom/serviceworkers/PFetchEventOp.ipdl b/dom/serviceworkers/PFetchEventOp.ipdl deleted file mode 100644 index 07d376c05fd6..000000000000 --- a/dom/serviceworkers/PFetchEventOp.ipdl +++ /dev/null @@ -1,26 +0,0 @@ -/* 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 protocol PRemoteWorkerController; - -include ServiceWorkerOpArgs; - -namespace mozilla { -namespace dom { - -protocol PFetchEventOp { - manager PRemoteWorkerController; - - child: - async AsyncLog(nsCString aScriptSpec, uint32_t aLineNumber, - uint32_t aColumnNumber, nsCString aMessageName, - nsString[] aParams); - - async RespondWith(IPCFetchEventRespondWithResult aResult); - - async __delete__(ServiceWorkerFetchEventOpResult aResult); -}; - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/PFetchEventOpProxy.ipdl b/dom/serviceworkers/PFetchEventOpProxy.ipdl deleted file mode 100644 index 7182eef03e84..000000000000 --- a/dom/serviceworkers/PFetchEventOpProxy.ipdl +++ /dev/null @@ -1,26 +0,0 @@ -/* 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 protocol PRemoteWorker; - -include ServiceWorkerOpArgs; - -namespace mozilla { -namespace dom { - -protocol PFetchEventOpProxy { - manager PRemoteWorker; - - parent: - async AsyncLog(nsCString aScriptSpec, uint32_t aLineNumber, - uint32_t aColumnNumber, nsCString aMessageName, - nsString[] aParams); - - async RespondWith(IPCFetchEventRespondWithResult aResult); - - async __delete__(ServiceWorkerFetchEventOpResult aResult); -}; - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/ServiceWorkerEvents.cpp b/dom/serviceworkers/ServiceWorkerEvents.cpp index 335b40a2a4f6..4bdf7b0aa6c5 100644 --- a/dom/serviceworkers/ServiceWorkerEvents.cpp +++ b/dom/serviceworkers/ServiceWorkerEvents.cpp @@ -6,8 +6,6 @@ #include "ServiceWorkerEvents.h" -#include - #include "nsAutoPtr.h" #include "nsContentUtils.h" #include "nsIConsoleReportCollector.h" @@ -43,7 +41,6 @@ #include "mozilla/dom/PushMessageDataBinding.h" #include "mozilla/dom/PushUtil.h" #include "mozilla/dom/Request.h" -#include "mozilla/dom/ServiceWorkerOp.h" #include "mozilla/dom/TypedArray.h" #include "mozilla/dom/Response.h" #include "mozilla/dom/WorkerScope.h" @@ -139,14 +136,6 @@ void FetchEvent::PostInit( mScriptSpec.Assign(aScriptSpec); } -void FetchEvent::PostInit(const nsACString& aScriptSpec, - RefPtr aRespondWithHandler) { - MOZ_ASSERT(aRespondWithHandler); - - mScriptSpec.Assign(aScriptSpec); - mRespondWithHandler = std::move(aRespondWithHandler); -} - /*static*/ already_AddRefed FetchEvent::Constructor( const GlobalObject& aGlobal, const nsAString& aType, @@ -806,21 +795,11 @@ void FetchEvent::RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv) { StopImmediatePropagation(); mWaitToRespond = true; - - if (mChannel) { - RefPtr handler = new RespondWithHandler( - mChannel, mRegistration, mRequest->Mode(), ir->IsClientRequest(), - mRequest->Redirect(), mScriptSpec, NS_ConvertUTF8toUTF16(requestURL), - ir->GetFragment(), spec, line, column); - - aArg.AppendNativeHandler(handler); - } else { - MOZ_ASSERT(mRespondWithHandler); - - mRespondWithHandler->RespondWithCalledAt(spec, line, column); - aArg.AppendNativeHandler(mRespondWithHandler); - mRespondWithHandler = nullptr; - } + RefPtr handler = new RespondWithHandler( + mChannel, mRegistration, mRequest->Mode(), ir->IsClientRequest(), + mRequest->Redirect(), mScriptSpec, NS_ConvertUTF8toUTF16(requestURL), + ir->GetFragment(), spec, line, column); + aArg.AppendNativeHandler(handler); if (!WaitOnPromise(aArg)) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); @@ -859,16 +838,9 @@ void FetchEvent::ReportCanceled() { // nsString requestURL; // CopyUTF8toUTF16(url, requestURL); - if (mChannel) { - ::AsyncLog(mChannel.get(), mPreventDefaultScriptSpec, - mPreventDefaultLineNumber, mPreventDefaultColumnNumber, - NS_LITERAL_CSTRING("InterceptionCanceledWithURL"), requestURL); - } else { - mRespondWithHandler->ReportCanceled(mPreventDefaultScriptSpec, - mPreventDefaultLineNumber, - mPreventDefaultColumnNumber); - mRespondWithHandler = nullptr; - } + ::AsyncLog(mChannel.get(), mPreventDefaultScriptSpec, + mPreventDefaultLineNumber, mPreventDefaultColumnNumber, + NS_LITERAL_CSTRING("InterceptionCanceledWithURL"), requestURL); } namespace { diff --git a/dom/serviceworkers/ServiceWorkerEvents.h b/dom/serviceworkers/ServiceWorkerEvents.h index 85b504914a0b..48965206bf12 100644 --- a/dom/serviceworkers/ServiceWorkerEvents.h +++ b/dom/serviceworkers/ServiceWorkerEvents.h @@ -26,7 +26,6 @@ namespace dom { class Blob; class Client; -class FetchEventOp; class MessagePort; struct PushEventInit; class Request; @@ -51,15 +50,6 @@ class CancelChannelRunnable final : public Runnable { NS_IMETHOD Run() override; }; -enum ExtendableEventResult { Rejected = 0, Resolved }; - -class ExtendableEventCallback { - public: - virtual void FinishedWithResult(ExtendableEventResult aResult) = 0; - - NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING -}; - class ExtendableEvent : public Event { public: class ExtensionsHandler { @@ -76,7 +66,7 @@ class ExtendableEvent : public Event { bool WaitOnPromise(Promise& aPromise); explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner); - ~ExtendableEvent() = default; + ~ExtendableEvent() {} public: NS_DECL_ISUPPORTS_INHERITED @@ -112,7 +102,6 @@ class ExtendableEvent : public Event { }; class FetchEvent final : public ExtendableEvent { - RefPtr mRespondWithHandler; nsMainThreadPtrHandle mChannel; nsMainThreadPtrHandle mRegistration; RefPtr mRequest; @@ -143,9 +132,6 @@ class FetchEvent final : public ExtendableEvent { nsMainThreadPtrHandle& aRegistration, const nsACString& aScriptSpec); - void PostInit(const nsACString& aScriptSpec, - RefPtr aRespondWithHandler); - static already_AddRefed Constructor( const GlobalObject& aGlobal, const nsAString& aType, const FetchEventInit& aOptions, ErrorResult& aRv); @@ -167,6 +153,10 @@ class FetchEvent final : public ExtendableEvent { void RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv); + already_AddRefed ForwardTo(const nsAString& aUrl); + + already_AddRefed Default(); + // Pull in the Event version of PreventDefault so we don't get // shadowing warnings. using Event::PreventDefault; @@ -209,7 +199,7 @@ class PushEvent final : public ExtendableEvent { protected: explicit PushEvent(mozilla::dom::EventTarget* aOwner); - ~PushEvent() = default; + ~PushEvent() {} public: NS_DECL_ISUPPORTS_INHERITED diff --git a/dom/serviceworkers/ServiceWorkerInfo.cpp b/dom/serviceworkers/ServiceWorkerInfo.cpp index 0bd50f54bd1b..b3747ec512dd 100644 --- a/dom/serviceworkers/ServiceWorkerInfo.cpp +++ b/dom/serviceworkers/ServiceWorkerInfo.cpp @@ -6,11 +6,7 @@ #include "ServiceWorkerInfo.h" -#include "ServiceWorkerPrivate.h" #include "ServiceWorkerScriptCache.h" -#include "mozilla/dom/ClientIPCTypes.h" -#include "mozilla/dom/ClientState.h" -#include "mozilla/dom/RemoteWorkerTypes.h" namespace mozilla { namespace dom { @@ -150,7 +146,6 @@ void ServiceWorkerInfo::UpdateState(ServiceWorkerState aState) { mDescriptor.SetState(aState); if (State() == ServiceWorkerState::Redundant) { serviceWorkerScriptCache::PurgeCache(mPrincipal, mCacheName); - mServiceWorkerPrivate->NoteDeadServiceWorkerInfo(); } } diff --git a/dom/serviceworkers/ServiceWorkerManager.cpp b/dom/serviceworkers/ServiceWorkerManager.cpp index 36aaa7bfb55a..762883a463f8 100644 --- a/dom/serviceworkers/ServiceWorkerManager.cpp +++ b/dom/serviceworkers/ServiceWorkerManager.cpp @@ -25,7 +25,6 @@ #include "nsDebug.h" #include "nsISupportsPrimitives.h" #include "nsIPermissionManager.h" -#include "nsXULAppAPI.h" #include "jsapi.h" @@ -77,7 +76,6 @@ #include "ServiceWorkerRegistrar.h" #include "ServiceWorkerRegistration.h" #include "ServiceWorkerScriptCache.h" -#include "ServiceWorkerShutdownBlocker.h" #include "ServiceWorkerEvents.h" #include "ServiceWorkerUnregisterJob.h" #include "ServiceWorkerUpdateJob.h" @@ -261,36 +259,6 @@ class TeardownRunnable final : public Runnable { RefPtr mActor; }; -bool ServiceWorkersAreCrossProcess() { - return ServiceWorkerParentInterceptEnabled() && XRE_IsE10sParentProcess(); -} - -const char* GetXPCOMShutdownTopic() { - if (ServiceWorkersAreCrossProcess()) { - return "profile-change-teardown"; - } - - return NS_XPCOM_SHUTDOWN_OBSERVER_ID; -} - -already_AddRefed GetAsyncShutdownBarrier() { - AssertIsOnMainThread(); - - if (!ServiceWorkersAreCrossProcess()) { - return nullptr; - } - - nsCOMPtr svc = services::GetAsyncShutdown(); - MOZ_ASSERT(svc); - - nsCOMPtr barrier; - DebugOnly rv = - svc->GetProfileChangeTeardown(getter_AddRefs(barrier)); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - - return barrier.forget(); -} - } // namespace ////////////////////////// @@ -312,40 +280,15 @@ ServiceWorkerManager::ServiceWorkerManager() ServiceWorkerManager::~ServiceWorkerManager() { // The map will assert if it is not empty when destroyed. mRegistrationInfos.Clear(); - - if (!ServiceWorkersAreCrossProcess()) { - MOZ_ASSERT(!mActor); - } -} - -void ServiceWorkerManager::BlockShutdownOn( - GenericNonExclusivePromise* aPromise) { - AssertIsOnMainThread(); - - // This may be called when in non-e10s mode with parent-intercept enabled. - if (!ServiceWorkersAreCrossProcess()) { - return; - } - - MOZ_ASSERT(mShutdownBlocker); - MOZ_ASSERT(aPromise); - - mShutdownBlocker->WaitOnPromise(aPromise); + MOZ_ASSERT(!mActor); } void ServiceWorkerManager::Init(ServiceWorkerRegistrar* aRegistrar) { - nsCOMPtr shutdownBarrier = GetAsyncShutdownBarrier(); - - if (shutdownBarrier) { - mShutdownBlocker = - ServiceWorkerShutdownBlocker::CreateAndRegisterOn(shutdownBarrier); - MOZ_ASSERT(mShutdownBlocker); - } - nsCOMPtr obs = mozilla::services::GetObserverService(); if (obs) { DebugOnly rv; - rv = obs->AddObserver(this, GetXPCOMShutdownTopic(), false /* ownsWeak */); + rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, + false /* ownsWeak */); MOZ_ASSERT(NS_SUCCEEDED(rv)); } @@ -508,13 +451,9 @@ void ServiceWorkerManager::MaybeStartShutdown() { it1.UserData()->mInfos.Clear(); } - if (mShutdownBlocker) { - mShutdownBlocker->StopAcceptingPromises(); - } - nsCOMPtr obs = mozilla::services::GetObserverService(); if (obs) { - obs->RemoveObserver(this, GetXPCOMShutdownTopic()); + obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); if (XRE_IsParentProcess()) { obs->RemoveObserver(this, CLEAR_ORIGIN_DATA); @@ -2336,6 +2275,19 @@ void ServiceWorkerManager::Update( actor, aPrincipal->OriginAttributesRef(), nsCString(aScope)); } +namespace { + +void RejectUpdateWithInvalidStateError( + ServiceWorkerUpdateFinishCallback& aCallback) { + ErrorResult error(NS_ERROR_DOM_INVALID_STATE_ERR); + aCallback.UpdateFailed(error); + + // In case the callback does not consume the exception + error.SuppressException(); +} + +} // namespace + void ServiceWorkerManager::UpdateInternal( nsIPrincipal* aPrincipal, const nsACString& aScope, ServiceWorkerUpdateFinishCallback* aCallback) { @@ -2351,20 +2303,22 @@ void ServiceWorkerManager::UpdateInternal( RefPtr registration = GetRegistration(scopeKey, aScope); if (NS_WARN_IF(!registration)) { - ErrorResult error; - error.ThrowTypeError( - NS_ConvertUTF8toUTF16(aScope), NS_LITERAL_STRING("uninstalled")); - aCallback->UpdateFailed(error); - - // In case the callback does not consume the exception - error.SuppressException(); return; } + // "Let newestWorker be the result of running Get Newest Worker algorithm + // passing registration as its argument. + // If newestWorker is null, return a promise rejected with "InvalidStateError" RefPtr newest = registration->Newest(); - MOZ_DIAGNOSTIC_ASSERT(newest, - "The Update algorithm should have been aborted already " - "if there wasn't a newest worker"); + if (!newest) { + RejectUpdateWithInvalidStateError(*aCallback); + return; + } + + if (newest->State() == ServiceWorkerState::Installing) { + RejectUpdateWithInvalidStateError(*aCallback); + return; + } RefPtr queue = GetOrCreateJobQueue(scopeKey, aScope); @@ -2783,7 +2737,7 @@ ServiceWorkerManager::Observe(nsISupports* aSubject, const char* aTopic, return NS_OK; } - if (strcmp(aTopic, GetXPCOMShutdownTopic()) == 0) { + if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { MaybeStartShutdown(); return NS_OK; } diff --git a/dom/serviceworkers/ServiceWorkerManager.h b/dom/serviceworkers/ServiceWorkerManager.h index b334400387b7..702b1820ed98 100644 --- a/dom/serviceworkers/ServiceWorkerManager.h +++ b/dom/serviceworkers/ServiceWorkerManager.h @@ -51,7 +51,6 @@ class ServiceWorkerJobQueue; class ServiceWorkerManagerChild; class ServiceWorkerPrivate; class ServiceWorkerRegistrar; -class ServiceWorkerShutdownBlocker; class ServiceWorkerUpdateFinishCallback { protected: @@ -281,8 +280,6 @@ class ServiceWorkerManager final : public nsIServiceWorkerManager, void NoteInheritedController(const ClientInfo& aClientInfo, const ServiceWorkerDescriptor& aController); - void BlockShutdownOn(GenericNonExclusivePromise* aPromise); - nsresult GetClientRegistration( const ClientInfo& aClientInfo, ServiceWorkerRegistrationInfo** aRegistrationInfo); @@ -388,8 +385,6 @@ class ServiceWorkerManager final : public nsIServiceWorkerManager, const nsAString& aTag, const nsAString& aIcon, const nsAString& aData, const nsAString& aBehavior); - - RefPtr mShutdownBlocker; }; } // namespace dom diff --git a/dom/serviceworkers/ServiceWorkerOp.cpp b/dom/serviceworkers/ServiceWorkerOp.cpp deleted file mode 100644 index d2896d8807a6..000000000000 --- a/dom/serviceworkers/ServiceWorkerOp.cpp +++ /dev/null @@ -1,1699 +0,0 @@ -/* -*- 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 "ServiceWorkerOp.h" - -#include - -#include "jsapi.h" - -#include "nsCOMPtr.h" -#include "nsContentUtils.h" -#include "nsDebug.h" -#include "nsError.h" -#include "nsINamed.h" -#include "nsIPushErrorReporter.h" -#include "nsISupportsImpl.h" -#include "nsITimer.h" -#include "nsProxyRelease.h" -#include "nsServiceManagerUtils.h" -#include "nsTArray.h" -#include "nsThreadUtils.h" - -#include "ServiceWorkerCloneData.h" -#include "mozilla/Assertions.h" -#include "mozilla/CycleCollectedJSContext.h" -#include "mozilla/DebugOnly.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/OwningNonNull.h" -#include "mozilla/ScopeExit.h" -#include "mozilla/SystemGroup.h" -#include "mozilla/Telemetry.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/BindingDeclarations.h" -#include "mozilla/dom/Client.h" -#include "mozilla/dom/ExtendableMessageEventBinding.h" -#include "mozilla/dom/FetchEventBinding.h" -#include "mozilla/dom/FetchEventOpProxyChild.h" -#include "mozilla/dom/InternalHeaders.h" -#include "mozilla/dom/InternalRequest.h" -#include "mozilla/dom/InternalResponse.h" -#include "mozilla/dom/Notification.h" -#include "mozilla/dom/PushEventBinding.h" -#include "mozilla/dom/RemoteWorkerChild.h" -#include "mozilla/dom/RemoteWorkerService.h" -#include "mozilla/dom/Request.h" -#include "mozilla/dom/Response.h" -#include "mozilla/dom/RootedDictionary.h" -#include "mozilla/dom/ServiceWorkerBinding.h" -#include "mozilla/dom/WorkerCommon.h" -#include "mozilla/dom/WorkerRef.h" -#include "mozilla/ipc/IPCStreamUtils.h" - -namespace mozilla { -namespace dom { - -namespace { - -class ExtendableEventKeepAliveHandler final - : public ExtendableEvent::ExtensionsHandler, - public PromiseNativeHandler { - public: - NS_DECL_ISUPPORTS - - static RefPtr Create( - RefPtr aCallback) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - - RefPtr self = - new ExtendableEventKeepAliveHandler(std::move(aCallback)); - - self->mWorkerRef = StrongWorkerRef::Create( - GetCurrentThreadWorkerPrivate(), "ExtendableEventKeepAliveHandler", - [self]() { self->Cleanup(); }); - - if (NS_WARN_IF(!self->mWorkerRef)) { - return nullptr; - } - - return self; - } - - /** - * ExtendableEvent::ExtensionsHandler interface - */ - bool WaitOnPromise(Promise& aPromise) override { - if (!mAcceptingPromises) { - MOZ_ASSERT(!mSelfRef, "We shouldn't be holding a self reference!"); - return false; - } - - if (!mSelfRef) { - MOZ_ASSERT(!mPendingPromisesCount); - mSelfRef = this; - } - - ++mPendingPromisesCount; - aPromise.AppendNativeHandler(this); - - return true; - } - - /** - * PromiseNativeHandler interface - */ - void ResolvedCallback(JSContext* aCx, JS::Handle aValue) override { - RemovePromise(Resolved); - } - - void RejectedCallback(JSContext* aCx, JS::Handle aValue) override { - RemovePromise(Rejected); - } - - void MaybeDone() { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - - if (mPendingPromisesCount) { - return; - } - - if (mCallback) { - mCallback->FinishedWithResult(mRejected ? Rejected : Resolved); - } - - Cleanup(); - } - - private: - /** - * This class is useful for the case where pending microtasks will continue - * extending the event, which means that the event is not "done." For example: - * - * // `e` is an ExtendableEvent, `p` is a Promise - * e.waitUntil(p); - * p.then(() => e.waitUntil(otherPromise)); - */ - class MaybeDoneRunner : public MicroTaskRunnable { - public: - explicit MaybeDoneRunner(RefPtr aHandler) - : mHandler(std::move(aHandler)) {} - - void Run(AutoSlowOperation& /* unused */) override { - mHandler->MaybeDone(); - } - - private: - RefPtr mHandler; - }; - - explicit ExtendableEventKeepAliveHandler( - RefPtr aCallback) - : mCallback(std::move(aCallback)) {} - - ~ExtendableEventKeepAliveHandler() { Cleanup(); } - - void Cleanup() { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - - mSelfRef = nullptr; - mWorkerRef = nullptr; - mCallback = nullptr; - mAcceptingPromises = false; - } - - void RemovePromise(ExtendableEventResult aResult) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_DIAGNOSTIC_ASSERT(mPendingPromisesCount > 0); - - // NOTE: mSelfRef can be nullptr here if MaybeCleanup() was just called - // before a promise settled. This can happen, for example, if the worker - // thread is being terminated for running too long, browser shutdown, etc. - - mRejected |= (aResult == Rejected); - - --mPendingPromisesCount; - if (mPendingPromisesCount) { - return; - } - - CycleCollectedJSContext* cx = CycleCollectedJSContext::Get(); - MOZ_ASSERT(cx); - - RefPtr r = new MaybeDoneRunner(this); - cx->DispatchToMicroTask(r.forget()); - } - - /** - * We start holding a self reference when the first extension promise is - * added, and this reference is released when the last promise settles or - * when the worker is shutting down. - * - * This is needed in the case that we're waiting indefinitely on a to-be-GC'ed - * promise that's no longer reachable and will never be settled. - */ - RefPtr mSelfRef; - - RefPtr mWorkerRef; - - RefPtr mCallback; - - uint32_t mPendingPromisesCount = 0; - - bool mRejected = false; - bool mAcceptingPromises = true; -}; - -NS_IMPL_ISUPPORTS0(ExtendableEventKeepAliveHandler) - -nsresult DispatchExtendableEventOnWorkerScope( - JSContext* aCx, WorkerGlobalScope* aWorkerScope, ExtendableEvent* aEvent, - RefPtr aCallback) { - MOZ_ASSERT(aCx); - MOZ_ASSERT(aWorkerScope); - MOZ_ASSERT(aEvent); - - nsCOMPtr globalObject = aWorkerScope; - WidgetEvent* internalEvent = aEvent->WidgetEventPtr(); - - RefPtr keepAliveHandler = - ExtendableEventKeepAliveHandler::Create(std::move(aCallback)); - if (NS_WARN_IF(!keepAliveHandler)) { - return NS_ERROR_FAILURE; - } - - // This must be always set *before* dispatching the event, otherwise - // waitUntil() calls will fail. - aEvent->SetKeepAliveHandler(keepAliveHandler); - - ErrorResult result; - aWorkerScope->DispatchEvent(*aEvent, result); - if (NS_WARN_IF(result.Failed())) { - result.SuppressException(); - return NS_ERROR_FAILURE; - } - - keepAliveHandler->MaybeDone(); - - // We don't block the event when getting an exception but still report the - // error message. NOTE: this will not stop the event. - if (internalEvent->mFlags.mExceptionWasRaised) { - return NS_ERROR_XPC_JS_THREW_EXCEPTION; - } - - return NS_OK; -} - -bool DispatchFailed(nsresult aStatus) { - return NS_FAILED(aStatus) && aStatus != NS_ERROR_XPC_JS_THREW_EXCEPTION; -} - -} // anonymous namespace - -class ServiceWorkerOp::ServiceWorkerOpRunnable : public WorkerRunnable { - public: - NS_DECL_ISUPPORTS_INHERITED - - ServiceWorkerOpRunnable(RefPtr aOwner, - WorkerPrivate* aWorkerPrivate) - : WorkerRunnable(aWorkerPrivate), mOwner(std::move(aOwner)) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOwner); - MOZ_ASSERT(aWorkerPrivate); - } - - private: - ~ServiceWorkerOpRunnable() = default; - - bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(mOwner); - - bool rv = mOwner->Exec(aCx, aWorkerPrivate); - Unused << NS_WARN_IF(!rv); - mOwner = nullptr; - - return rv; - } - - nsresult Cancel() override { - MOZ_ASSERT(mOwner); - - mOwner->RejectAll(NS_ERROR_DOM_ABORT_ERR); - mOwner = nullptr; - - return WorkerRunnable::Cancel(); - } - - RefPtr mOwner; -}; - -NS_IMPL_ISUPPORTS_INHERITED0(ServiceWorkerOp::ServiceWorkerOpRunnable, - WorkerRunnable) - -bool ServiceWorkerOp::MaybeStart(RemoteWorkerChild* aOwner, - RemoteWorkerChild::State& aState) { - MOZ_ASSERT(!mStarted); - MOZ_ASSERT(aOwner); - MOZ_ASSERT(aOwner->GetOwningEventTarget()->IsOnCurrentThread()); - - MOZ_ACCESS_THREAD_BOUND(aOwner->mLauncherData, launcherData); - - if (NS_WARN_IF(!launcherData->mIPCActive)) { - RejectAll(NS_ERROR_DOM_ABORT_ERR); - mStarted = true; - return true; - } - - // Allow termination to happen while the Service Worker is initializing. - if (aState.is() && !IsTerminationOp()) { - return false; - } - - if (NS_WARN_IF(aState.is()) || - NS_WARN_IF(aState.is())) { - RejectAll(NS_ERROR_DOM_INVALID_STATE_ERR); - mStarted = true; - return true; - } - - MOZ_ASSERT(aState.is() || IsTerminationOp()); - - RefPtr self = this; - - if (IsTerminationOp()) { - aOwner->GetTerminationPromise()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [self]( - const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) { - MOZ_ASSERT(!self->mPromiseHolder.IsEmpty()); - - if (NS_WARN_IF(aResult.IsReject())) { - self->mPromiseHolder.Reject(aResult.RejectValue(), __func__); - return; - } - - self->mPromiseHolder.Resolve(NS_OK, __func__); - }); - } - - RefPtr owner = aOwner; - - nsCOMPtr r = NS_NewRunnableFunction( - __func__, [self = std::move(self), owner = std::move(owner)]() mutable { - auto lock = owner->mState.Lock(); - auto& state = lock.ref(); - - if (NS_WARN_IF(!state.is() && !self->IsTerminationOp())) { - self->RejectAll(NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - - if (self->IsTerminationOp()) { - owner->CloseWorkerOnMainThread(state); - } else { - MOZ_ASSERT(state.is()); - - if (NS_WARN_IF( - state.as().mWorkerPrivate->ParentStatusProtected() > - Running)) { - owner->GetTerminationPromise()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [self = std::move(self)]( - const GenericNonExclusivePromise::ResolveOrRejectValue&) { - MOZ_ASSERT(!self->mPromiseHolder.IsEmpty()); - self->RejectAll(NS_ERROR_DOM_ABORT_ERR); - }); - - owner->CloseWorkerOnMainThread(state); - return; - } - - RefPtr workerRunnable = - self->GetRunnable(state.as().mWorkerPrivate); - - if (NS_WARN_IF(!workerRunnable->Dispatch())) { - self->RejectAll(NS_ERROR_FAILURE); - } - } - - nsCOMPtr target = owner->GetOwningEventTarget(); - NS_ProxyRelease(__func__, target, owner.forget()); - }); - - mStarted = true; - - MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget())); - - return true; -} - -void ServiceWorkerOp::Cancel() { RejectAll(NS_ERROR_DOM_ABORT_ERR); } - -ServiceWorkerOp::ServiceWorkerOp( - const ServiceWorkerOpArgs& aArgs, - std::function&& aCallback) - : mArgs(aArgs) { - MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - - RefPtr promise = mPromiseHolder.Ensure(__func__); - - promise->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [callback = std::move(aCallback)]( - ServiceWorkerOpPromise::ResolveOrRejectValue&& aResult) mutable { - if (NS_WARN_IF(aResult.IsReject())) { - MOZ_ASSERT(NS_FAILED(aResult.RejectValue())); - callback(aResult.RejectValue()); - return; - } - - callback(aResult.ResolveValue()); - }); -} - -ServiceWorkerOp::~ServiceWorkerOp() { - Unused << NS_WARN_IF(!mPromiseHolder.IsEmpty()); - mPromiseHolder.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__); -} - -bool ServiceWorkerOp::Started() const { - MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - - return mStarted; -} - -bool ServiceWorkerOp::IsTerminationOp() const { - return mArgs.type() == - ServiceWorkerOpArgs::TServiceWorkerTerminateWorkerOpArgs; -} - -RefPtr ServiceWorkerOp::GetRunnable( - WorkerPrivate* aWorkerPrivate) { - AssertIsOnMainThread(); - MOZ_ASSERT(aWorkerPrivate); - - return new ServiceWorkerOpRunnable(this, aWorkerPrivate); -} - -void ServiceWorkerOp::RejectAll(nsresult aStatus) { - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - mPromiseHolder.Reject(aStatus, __func__); -} - -class CheckScriptEvaluationOp final : public ServiceWorkerOp { - using ServiceWorkerOp::ServiceWorkerOp; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CheckScriptEvaluationOp, override) - - private: - ~CheckScriptEvaluationOp() = default; - - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - ServiceWorkerCheckScriptEvaluationOpResult result; - result.workerScriptExecutedSuccessfully() = - aWorkerPrivate->WorkerScriptExecutedSuccessfully(); - result.fetchHandlerWasAdded() = aWorkerPrivate->FetchHandlerWasAdded(); - - mPromiseHolder.Resolve(result, __func__); - - return true; - } -}; - -class TerminateServiceWorkerOp final : public ServiceWorkerOp { - using ServiceWorkerOp::ServiceWorkerOp; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TerminateServiceWorkerOp, override) - - private: - ~TerminateServiceWorkerOp() = default; - - bool Exec(JSContext*, WorkerPrivate*) override { - MOZ_ASSERT_UNREACHABLE( - "Worker termination should be handled in " - "`ServiceWorkerOp::MaybeStart()`"); - - return false; - } -}; - -class UpdateServiceWorkerStateOp final : public ServiceWorkerOp { - using ServiceWorkerOp::ServiceWorkerOp; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UpdateServiceWorkerStateOp, override); - - private: - class UpdateStateOpRunnable final : public MainThreadWorkerControlRunnable { - public: - NS_DECL_ISUPPORTS_INHERITED - - UpdateStateOpRunnable(RefPtr aOwner, - WorkerPrivate* aWorkerPrivate) - : MainThreadWorkerControlRunnable(aWorkerPrivate), - mOwner(std::move(aOwner)) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOwner); - MOZ_ASSERT(aWorkerPrivate); - } - - private: - ~UpdateStateOpRunnable() = default; - - bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(mOwner); - - Unused << mOwner->Exec(aCx, aWorkerPrivate); - mOwner = nullptr; - - return true; - } - - nsresult Cancel() override { - MOZ_ASSERT(mOwner); - - mOwner->RejectAll(NS_ERROR_DOM_ABORT_ERR); - mOwner = nullptr; - - return MainThreadWorkerControlRunnable::Cancel(); - } - - RefPtr mOwner; - }; - - ~UpdateServiceWorkerStateOp() = default; - - RefPtr GetRunnable(WorkerPrivate* aWorkerPrivate) override { - AssertIsOnMainThread(); - MOZ_ASSERT(aWorkerPrivate); - MOZ_ASSERT(mArgs.type() == - ServiceWorkerOpArgs::TServiceWorkerUpdateStateOpArgs); - - return new UpdateStateOpRunnable(this, aWorkerPrivate); - } - - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - ServiceWorkerState state = - mArgs.get_ServiceWorkerUpdateStateOpArgs().state(); - aWorkerPrivate->UpdateServiceWorkerState(state); - - mPromiseHolder.Resolve(NS_OK, __func__); - - return true; - } -}; - -NS_IMPL_ISUPPORTS_INHERITED0(UpdateServiceWorkerStateOp::UpdateStateOpRunnable, - MainThreadWorkerControlRunnable) - -void ExtendableEventOp::FinishedWithResult(ExtendableEventResult aResult) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - mPromiseHolder.Resolve(aResult == Resolved ? NS_OK : NS_ERROR_FAILURE, - __func__); -} - -class LifeCycleEventOp final : public ExtendableEventOp { - using ExtendableEventOp::ExtendableEventOp; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LifeCycleEventOp, override) - - private: - ~LifeCycleEventOp() = default; - - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - RefPtr event; - RefPtr target = aWorkerPrivate->GlobalScope(); - - const nsString& eventName = - mArgs.get_ServiceWorkerLifeCycleEventOpArgs().eventName(); - - if (eventName.EqualsASCII("install") || eventName.EqualsASCII("activate")) { - ExtendableEventInit init; - init.mBubbles = false; - init.mCancelable = false; - event = ExtendableEvent::Constructor(target, eventName, init); - } else { - MOZ_CRASH("Unexpected lifecycle event"); - } - - event->SetTrusted(true); - - nsresult rv = DispatchExtendableEventOnWorkerScope( - aCx, aWorkerPrivate->GlobalScope(), event, this); - - if (NS_WARN_IF(DispatchFailed(rv))) { - RejectAll(rv); - } - - return DispatchFailed(rv); - } -}; - -/** - * PushEventOp - */ -class PushEventOp final : public ExtendableEventOp { - using ExtendableEventOp::ExtendableEventOp; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PushEventOp, override) - - private: - ~PushEventOp() = default; - - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - ErrorResult result; - - auto scopeExit = MakeScopeExit([&] { - MOZ_ASSERT(result.Failed()); - - RejectAll(result.StealNSResult()); - ReportError(aWorkerPrivate); - }); - - const ServiceWorkerPushEventOpArgs& args = - mArgs.get_ServiceWorkerPushEventOpArgs(); - - PushEventInit pushEventInit; - - if (args.data().type() != OptionalPushData::Tvoid_t) { - auto& bytes = args.data().get_ArrayOfuint8_t(); - JSObject* data = - Uint8Array::Create(aCx, bytes.Length(), bytes.Elements()); - - if (!data) { - result = ErrorResult(NS_ERROR_FAILURE); - return false; - } - - DebugOnly inited = - pushEventInit.mData.Construct().SetAsArrayBufferView().Init(data); - MOZ_ASSERT(inited); - } - - pushEventInit.mBubbles = false; - pushEventInit.mCancelable = false; - - GlobalObject globalObj(aCx, aWorkerPrivate->GlobalScope()->GetWrapper()); - RefPtr pushEvent = PushEvent::Constructor( - globalObj, NS_LITERAL_STRING("push"), pushEventInit, result); - - if (NS_WARN_IF(result.Failed())) { - return false; - } - - pushEvent->SetTrusted(true); - - scopeExit.release(); - - nsresult rv = DispatchExtendableEventOnWorkerScope( - aCx, aWorkerPrivate->GlobalScope(), pushEvent, this); - - if (NS_FAILED(rv)) { - if (NS_WARN_IF(DispatchFailed(rv))) { - RejectAll(rv); - } - - // We don't cancel WorkerPrivate when catching an exception. - ReportError(aWorkerPrivate, - nsIPushErrorReporter::DELIVERY_UNCAUGHT_EXCEPTION); - } - - return DispatchFailed(rv); - } - - void FinishedWithResult(ExtendableEventResult aResult) override { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - - if (aResult == Rejected) { - ReportError(workerPrivate, - nsIPushErrorReporter::DELIVERY_UNHANDLED_REJECTION); - } - - ExtendableEventOp::FinishedWithResult(aResult); - } - - void ReportError( - WorkerPrivate* aWorkerPrivate, - uint16_t aError = nsIPushErrorReporter::DELIVERY_INTERNAL_ERROR) { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - - if (NS_WARN_IF(aError > nsIPushErrorReporter::DELIVERY_INTERNAL_ERROR) || - mArgs.get_ServiceWorkerPushEventOpArgs().messageId().IsEmpty()) { - return; - } - - nsString messageId = mArgs.get_ServiceWorkerPushEventOpArgs().messageId(); - nsCOMPtr r = NS_NewRunnableFunction( - __func__, [messageId = std::move(messageId), error = aError] { - nsCOMPtr reporter = - do_GetService("@mozilla.org/push/Service;1"); - - if (reporter) { - nsresult rv = reporter->ReportDeliveryError(messageId, error); - Unused << NS_WARN_IF(NS_FAILED(rv)); - } - }); - - MOZ_ALWAYS_SUCCEEDS(aWorkerPrivate->DispatchToMainThread(r.forget())); - } -}; - -class PushSubscriptionChangeEventOp final : public ExtendableEventOp { - using ExtendableEventOp::ExtendableEventOp; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PushSubscriptionChangeEventOp, override) - - private: - ~PushSubscriptionChangeEventOp() = default; - - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - RefPtr target = aWorkerPrivate->GlobalScope(); - - ExtendableEventInit init; - init.mBubbles = false; - init.mCancelable = false; - - RefPtr event = ExtendableEvent::Constructor( - target, NS_LITERAL_STRING("pushsubscriptionchange"), init); - event->SetTrusted(true); - - nsresult rv = DispatchExtendableEventOnWorkerScope( - aCx, aWorkerPrivate->GlobalScope(), event, this); - - if (NS_WARN_IF(DispatchFailed(rv))) { - RejectAll(rv); - } - - return DispatchFailed(rv); - } -}; - -class NotificationEventOp : public ExtendableEventOp, - public nsITimerCallback, - public nsINamed { - using ExtendableEventOp::ExtendableEventOp; - - public: - NS_DECL_THREADSAFE_ISUPPORTS - - private: - ~NotificationEventOp() { - MOZ_DIAGNOSTIC_ASSERT(!mTimer); - MOZ_DIAGNOSTIC_ASSERT(!mWorkerRef); - } - - void ClearWindowAllowed(WorkerPrivate* aWorkerPrivate) { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - - if (!mTimer) { - return; - } - - // This might be executed after the global was unrooted, in which case - // GlobalScope() will return null. Making the check here just to be safe. - WorkerGlobalScope* globalScope = aWorkerPrivate->GlobalScope(); - if (!globalScope) { - return; - } - - globalScope->ConsumeWindowInteraction(); - mTimer->Cancel(); - mTimer = nullptr; - - mWorkerRef = nullptr; - } - - void StartClearWindowTimer(WorkerPrivate* aWorkerPrivate) { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(!mTimer); - - nsresult rv; - nsCOMPtr timer = - NS_NewTimer(aWorkerPrivate->ControlEventTarget()); - if (NS_WARN_IF(!timer)) { - return; - } - - MOZ_ASSERT(!mWorkerRef); - RefPtr self = this; - mWorkerRef = StrongWorkerRef::Create( - aWorkerPrivate, "NotificationEventOp", [self = std::move(self)] { - // We could try to hold the worker alive until the timer fires, but - // other APIs are not likely to work in this partially shutdown state. - // We might as well let the worker thread exit. - self->ClearWindowAllowed(self->mWorkerRef->Private()); - }); - - if (!mWorkerRef) { - return; - } - - aWorkerPrivate->GlobalScope()->AllowWindowInteraction(); - timer.swap(mTimer); - - // We swap first and then initialize the timer so that even if initializing - // fails, we still clean the busy count and interaction count correctly. - // The timer can't be initialized before modyfing the busy count since the - // timer thread could run and call the timeout but the worker may - // already be terminating and modifying the busy count could fail. - uint32_t delay = mArgs.get_ServiceWorkerNotificationEventOpArgs() - .disableOpenClickDelay(); - rv = mTimer->InitWithCallback(this, delay, nsITimer::TYPE_ONE_SHOT); - - if (NS_WARN_IF(NS_FAILED(rv))) { - ClearWindowAllowed(aWorkerPrivate); - return; - } - } - - // ExtendableEventOp interface - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - RefPtr target = aWorkerPrivate->GlobalScope(); - - ServiceWorkerNotificationEventOpArgs& args = - mArgs.get_ServiceWorkerNotificationEventOpArgs(); - - ErrorResult result; - RefPtr notification = Notification::ConstructFromFields( - aWorkerPrivate->GlobalScope(), args.id(), args.title(), args.dir(), - args.lang(), args.body(), args.tag(), args.icon(), args.data(), - args.scope(), result); - - if (NS_WARN_IF(result.Failed())) { - return false; - } - - NotificationEventInit init; - init.mNotification = notification; - init.mBubbles = false; - init.mCancelable = false; - - RefPtr notificationEvent = - NotificationEvent::Constructor(target, args.eventName(), init, result); - - if (NS_WARN_IF(result.Failed())) { - return false; - } - - notificationEvent->SetTrusted(true); - - if (args.eventName().EqualsLiteral("notificationclick")) { - StartClearWindowTimer(aWorkerPrivate); - } - - nsresult rv = DispatchExtendableEventOnWorkerScope( - aCx, aWorkerPrivate->GlobalScope(), notificationEvent, this); - - if (NS_WARN_IF(DispatchFailed(rv))) { - // This will reject mPromiseHolder. - FinishedWithResult(Rejected); - } - - return DispatchFailed(rv); - } - - void FinishedWithResult(ExtendableEventResult aResult) override { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - - ClearWindowAllowed(workerPrivate); - - ExtendableEventOp::FinishedWithResult(aResult); - } - - // nsITimerCallback interface - NS_IMETHOD Notify(nsITimer* aTimer) override { - MOZ_DIAGNOSTIC_ASSERT(mTimer == aTimer); - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - ClearWindowAllowed(workerPrivate); - return NS_OK; - } - - // nsINamed interface - NS_IMETHOD GetName(nsACString& aName) override { - aName.AssignLiteral("NotificationEventOp"); - return NS_OK; - } - - nsCOMPtr mTimer; - RefPtr mWorkerRef; -}; - -NS_IMPL_ISUPPORTS(NotificationEventOp, nsITimerCallback, nsINamed) - -class MessageEventOp final : public ExtendableEventOp { - using ExtendableEventOp::ExtendableEventOp; - - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MessageEventOp, override) - - MessageEventOp(const ServiceWorkerOpArgs& aArgs, - std::function&& aCallback) - : ExtendableEventOp(aArgs, std::move(aCallback)), - mData(new ServiceWorkerCloneData()) { - mData->CopyFromClonedMessageDataForBackgroundChild( - mArgs.get_ServiceWorkerMessageEventOpArgs().clonedData()); - } - - private: - ~MessageEventOp() = default; - - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - JS::Rooted messageData(aCx); - nsCOMPtr sgo = aWorkerPrivate->GlobalScope(); - ErrorResult rv; - mData->Read(aCx, &messageData, rv); - - // If deserialization fails, we will fire a messageerror event - bool deserializationFailed = rv.ErrorCodeIs(NS_ERROR_DOM_DATA_CLONE_ERR); - - if (!deserializationFailed && NS_WARN_IF(rv.Failed())) { - RejectAll(rv.StealNSResult()); - return true; - } - - Sequence> ports; - if (!mData->TakeTransferredPortsAsSequence(ports)) { - RejectAll(NS_ERROR_FAILURE); - return true; - } - - RootedDictionary init(aCx); - - init.mBubbles = false; - init.mCancelable = false; - - // On a messageerror event, we disregard ports: - // https://w3c.github.io/ServiceWorker/#service-worker-postmessage - if (!deserializationFailed) { - init.mData = messageData; - init.mPorts = ports; - } - - init.mSource.SetValue().SetAsClient() = new Client( - sgo, mArgs.get_ServiceWorkerMessageEventOpArgs().clientInfoAndState()); - - rv = NS_OK; - RefPtr target = aWorkerPrivate->GlobalScope(); - RefPtr extendableEvent = - ExtendableMessageEvent::Constructor( - target, - deserializationFailed ? NS_LITERAL_STRING("messageerror") - : NS_LITERAL_STRING("message"), - init, rv); - if (NS_WARN_IF(rv.Failed())) { - RejectAll(rv.StealNSResult()); - return false; - } - - extendableEvent->SetTrusted(true); - - nsresult rv2 = DispatchExtendableEventOnWorkerScope( - aCx, aWorkerPrivate->GlobalScope(), extendableEvent, this); - - if (NS_WARN_IF(DispatchFailed(rv2))) { - RejectAll(rv2); - } - - return DispatchFailed(rv2); - } - - RefPtr mData; -}; - -/** - * Used for ScopeExit-style network request cancelation in - * `ResolvedCallback()` (e.g. if `FetchEvent::RespondWith()` is resolved with - * a non-JS object). - */ -class MOZ_STACK_CLASS FetchEventOp::AutoCancel { - public: - explicit AutoCancel(FetchEventOp* aOwner) - : mOwner(aOwner), - mLine(0), - mColumn(0), - mMessageName(NS_LITERAL_CSTRING("InterceptionFailedWithURL")) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(mOwner); - - nsAutoString requestURL; - mOwner->GetRequestURL(requestURL); - mParams.AppendElement(requestURL); - } - - ~AutoCancel() { - if (mOwner) { - if (mSourceSpec.IsEmpty()) { - mOwner->AsyncLog(mMessageName, std::move(mParams)); - } else { - mOwner->AsyncLog(mSourceSpec, mLine, mColumn, mMessageName, - std::move(mParams)); - } - - MOZ_ASSERT(!mOwner->mRespondWithPromiseHolder.IsEmpty()); - mOwner->mRespondWithPromiseHolder.Reject(NS_ERROR_INTERCEPTION_FAILED, - __func__); - } - } - - // This function steals the error message from a ErrorResult. - void SetCancelErrorResult(JSContext* aCx, ErrorResult& aRv) { - MOZ_DIAGNOSTIC_ASSERT(aRv.Failed()); - MOZ_DIAGNOSTIC_ASSERT(!JS_IsExceptionPending(aCx)); - - // Storing the error as exception in the JSContext. - if (!aRv.MaybeSetPendingException(aCx)) { - return; - } - - MOZ_ASSERT(!aRv.Failed()); - - // Let's take the pending exception. - JS::Rooted exn(aCx); - if (!JS_GetPendingException(aCx, &exn)) { - return; - } - - JS_ClearPendingException(aCx); - - // Converting the exception in a js::ErrorReport. - js::ErrorReport report(aCx); - if (!report.init(aCx, exn, js::ErrorReport::WithSideEffects)) { - JS_ClearPendingException(aCx); - return; - } - - MOZ_ASSERT(mOwner); - MOZ_ASSERT(mMessageName.EqualsLiteral("InterceptionFailedWithURL")); - MOZ_ASSERT(mParams.Length() == 1); - - // Let's store the error message here. - mMessageName.Assign(report.toStringResult().c_str()); - mParams.Clear(); - } - - template - void SetCancelMessage(const nsACString& aMessageName, Params&&... aParams) { - MOZ_ASSERT(mOwner); - MOZ_ASSERT(mMessageName.EqualsLiteral("InterceptionFailedWithURL")); - MOZ_ASSERT(mParams.Length() == 1); - mMessageName = aMessageName; - mParams.Clear(); - StringArrayAppender::Append(mParams, sizeof...(Params), - std::forward(aParams)...); - } - - template - void SetCancelMessageAndLocation(const nsACString& aSourceSpec, - uint32_t aLine, uint32_t aColumn, - const nsACString& aMessageName, - Params&&... aParams) { - MOZ_ASSERT(mOwner); - MOZ_ASSERT(mMessageName.EqualsLiteral("InterceptionFailedWithURL")); - MOZ_ASSERT(mParams.Length() == 1); - - mSourceSpec = aSourceSpec; - mLine = aLine; - mColumn = aColumn; - - mMessageName = aMessageName; - mParams.Clear(); - StringArrayAppender::Append(mParams, sizeof...(Params), - std::forward(aParams)...); - } - - void Reset() { mOwner = nullptr; } - - private: - FetchEventOp* MOZ_NON_OWNING_REF mOwner; - nsCString mSourceSpec; - uint32_t mLine; - uint32_t mColumn; - nsCString mMessageName; - nsTArray mParams; -}; - -NS_IMPL_ISUPPORTS0(FetchEventOp) - -void FetchEventOp::SetActor(RefPtr aActor) { - MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - MOZ_ASSERT(!Started()); - MOZ_ASSERT(!mActor); - - mActor = std::move(aActor); -} - -void FetchEventOp::RevokeActor(FetchEventOpProxyChild* aActor) { - MOZ_ASSERT(aActor); - MOZ_ASSERT_IF(mActor, mActor == aActor); - - mActor = nullptr; -} - -RefPtr FetchEventOp::GetRespondWithPromise() { - MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - MOZ_ASSERT(!Started()); - MOZ_ASSERT(mRespondWithPromiseHolder.IsEmpty()); - - return mRespondWithPromiseHolder.Ensure(__func__); -} - -void FetchEventOp::RespondWithCalledAt(const nsCString& aRespondWithScriptSpec, - uint32_t aRespondWithLineNumber, - uint32_t aRespondWithColumnNumber) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(!mRespondWithClosure); - - mRespondWithClosure.emplace(aRespondWithScriptSpec, aRespondWithLineNumber, - aRespondWithColumnNumber); -} - -void FetchEventOp::ReportCanceled(const nsCString& aPreventDefaultScriptSpec, - uint32_t aPreventDefaultLineNumber, - uint32_t aPreventDefaultColumnNumber) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(mActor); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - nsString requestURL; - GetRequestURL(requestURL); - - AsyncLog(aPreventDefaultScriptSpec, aPreventDefaultLineNumber, - aPreventDefaultColumnNumber, - NS_LITERAL_CSTRING("InterceptionCanceledWithURL"), - {std::move(requestURL)}); -} - -FetchEventOp::~FetchEventOp() { - mRespondWithPromiseHolder.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__); - - if (mActor) { - NS_ProxyRelease("FetchEventOp::mActor", RemoteWorkerService::Thread(), - mActor.forget()); - } -} - -void FetchEventOp::RejectAll(nsresult aStatus) { - MOZ_ASSERT(!mRespondWithPromiseHolder.IsEmpty()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - mRespondWithPromiseHolder.Reject(aStatus, __func__); - mPromiseHolder.Reject(aStatus, __func__); -} - -void FetchEventOp::FinishedWithResult(ExtendableEventResult aResult) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - MOZ_ASSERT(!mResult); - - mResult.emplace(aResult); - - /** - * This should only return early if neither waitUntil() nor respondWith() - * are called. The early return is so that mRespondWithPromiseHolder has a - * chance to settle before mPromiseHolder does. - */ - if (!mPostDispatchChecksDone) { - return; - } - - MaybeFinished(); -} - -void FetchEventOp::MaybeFinished() { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - if (mResult) { - // mRespondWithPromiseHolder should have been settled in - // {Resolve,Reject}Callback by now. - MOZ_DIAGNOSTIC_ASSERT(mRespondWithPromiseHolder.IsEmpty()); - - ServiceWorkerFetchEventOpResult result( - mResult.value() == Resolved ? NS_OK : NS_ERROR_FAILURE); - - mPromiseHolder.Resolve(result, __func__); - } -} - -bool FetchEventOp::Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) { - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - MOZ_ASSERT(!mRespondWithPromiseHolder.IsEmpty()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - nsresult rv = DispatchFetchEvent(aCx, aWorkerPrivate); - - if (NS_WARN_IF(NS_FAILED(rv))) { - RejectAll(rv); - } - - return NS_SUCCEEDED(rv); -} - -void FetchEventOp::AsyncLog(const nsCString& aMessageName, - nsTArray aParams) { - MOZ_ASSERT(mActor); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - MOZ_ASSERT(mRespondWithClosure); - - const FetchEventRespondWithClosure& closure = mRespondWithClosure.ref(); - - AsyncLog(closure.respondWithScriptSpec(), closure.respondWithLineNumber(), - closure.respondWithColumnNumber(), aMessageName, std::move(aParams)); -} - -void FetchEventOp::AsyncLog(const nsCString& aScriptSpec, uint32_t aLineNumber, - uint32_t aColumnNumber, - const nsCString& aMessageName, - nsTArray aParams) { - MOZ_ASSERT(mActor); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - // Capture `this` because FetchEventOpProxyChild (mActor) is not thread - // safe, so an AddRef from RefPtr's constructor will - // assert. - RefPtr self = this; - - nsCOMPtr r = NS_NewRunnableFunction( - __func__, [self = std::move(self), spec = aScriptSpec, line = aLineNumber, - column = aColumnNumber, messageName = aMessageName, - params = std::move(aParams)] { - if (NS_WARN_IF(!self->mActor)) { - return; - } - - Unused << self->mActor->SendAsyncLog(spec, line, column, messageName, - params); - }); - - MOZ_ALWAYS_SUCCEEDS( - RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL)); -} - -void FetchEventOp::GetRequestURL(nsAString& aOutRequestURL) { - nsTArray& urls = - mArgs.get_ServiceWorkerFetchEventOpArgs().internalRequest().urlList(); - MOZ_ASSERT(!urls.IsEmpty()); - - aOutRequestURL = NS_ConvertUTF8toUTF16(urls.LastElement()); -} - -void FetchEventOp::ResolvedCallback(JSContext* aCx, - JS::Handle aValue) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(mRespondWithClosure); - MOZ_ASSERT(!mRespondWithPromiseHolder.IsEmpty()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - nsAutoString requestURL; - GetRequestURL(requestURL); - - AutoCancel autoCancel(this); - - if (!aValue.isObject()) { - NS_WARNING( - "FetchEvent::RespondWith was passed a promise resolved to a " - "non-Object " - "value"); - - nsCString sourceSpec; - uint32_t line = 0; - uint32_t column = 0; - nsString valueString; - nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, - valueString); - - autoCancel.SetCancelMessageAndLocation( - sourceSpec, line, column, - NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"), requestURL, - valueString); - return; - } - - RefPtr response; - nsresult rv = UNWRAP_OBJECT(Response, &aValue.toObject(), response); - if (NS_FAILED(rv)) { - nsCString sourceSpec; - uint32_t line = 0; - uint32_t column = 0; - nsString valueString; - nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, - valueString); - - autoCancel.SetCancelMessageAndLocation( - sourceSpec, line, column, - NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"), requestURL, - valueString); - return; - } - - WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(worker); - worker->AssertIsOnWorkerThread(); - - // Section "HTTP Fetch", step 3.3: - // If one of the following conditions is true, return a network error: - // * response's type is "error". - // * request's mode is not "no-cors" and response's type is "opaque". - // * request's redirect mode is not "manual" and response's type is - // "opaqueredirect". - // * request's redirect mode is not "follow" and response's url list - // has more than one item. - - if (response->Type() == ResponseType::Error) { - autoCancel.SetCancelMessage( - NS_LITERAL_CSTRING("InterceptedErrorResponseWithURL"), requestURL); - return; - } - - const ServiceWorkerFetchEventOpArgs& args = - mArgs.get_ServiceWorkerFetchEventOpArgs(); - const RequestMode requestMode = args.internalRequest().requestMode(); - - if (response->Type() == ResponseType::Opaque && - requestMode != RequestMode::No_cors) { - uint32_t mode = static_cast(requestMode); - NS_ConvertASCIItoUTF16 modeString(RequestModeValues::strings[mode].value, - RequestModeValues::strings[mode].length); - - nsAutoString requestURL; - GetRequestURL(requestURL); - - autoCancel.SetCancelMessage( - NS_LITERAL_CSTRING("BadOpaqueInterceptionRequestModeWithURL"), - requestURL, modeString); - return; - } - - const RequestRedirect requestRedirectMode = - args.internalRequest().requestRedirect(); - - if (requestRedirectMode != RequestRedirect::Manual && - response->Type() == ResponseType::Opaqueredirect) { - autoCancel.SetCancelMessage( - NS_LITERAL_CSTRING("BadOpaqueRedirectInterceptionWithURL"), requestURL); - return; - } - - if (requestRedirectMode != RequestRedirect::Follow && - response->Redirected()) { - autoCancel.SetCancelMessage( - NS_LITERAL_CSTRING("BadRedirectModeInterceptionWithURL"), requestURL); - return; - } - - { - ErrorResult error; - bool bodyUsed = response->GetBodyUsed(error); - error.WouldReportJSException(); - if (NS_WARN_IF(error.Failed())) { - autoCancel.SetCancelErrorResult(aCx, error); - return; - } - if (NS_WARN_IF(bodyUsed)) { - autoCancel.SetCancelMessage( - NS_LITERAL_CSTRING("InterceptedUsedResponseWithURL"), requestURL); - return; - } - } - - RefPtr ir = response->GetInternalResponse(); - if (NS_WARN_IF(!ir)) { - return; - } - - // An extra safety check to make sure our invariant that opaque and cors - // responses always have a URL does not break. - if (NS_WARN_IF((response->Type() == ResponseType::Opaque || - response->Type() == ResponseType::Cors) && - ir->GetUnfilteredURL().IsEmpty())) { - MOZ_DIAGNOSTIC_ASSERT(false, "Cors or opaque Response without a URL"); - return; - } - - Telemetry::ScalarAdd(Telemetry::ScalarID::SW_SYNTHESIZED_RES_COUNT, 1); - - if (requestMode == RequestMode::Same_origin && - response->Type() == ResponseType::Cors) { - Telemetry::ScalarAdd(Telemetry::ScalarID::SW_CORS_RES_FOR_SO_REQ_COUNT, 1); - - // XXXtt: Will have a pref to enable the quirk response in bug 1419684. - // The variadic template provided by StringArrayAppender requires exactly - // an nsString. - NS_ConvertUTF8toUTF16 responseURL(ir->GetUnfilteredURL()); - autoCancel.SetCancelMessage( - NS_LITERAL_CSTRING("CorsResponseForSameOriginRequest"), requestURL, - responseURL); - return; - } - - nsCOMPtr body; - ir->GetUnfilteredBody(getter_AddRefs(body)); - // Errors and redirects may not have a body. - if (body) { - ErrorResult error; - response->SetBodyUsed(aCx, error); - error.WouldReportJSException(); - if (NS_WARN_IF(error.Failed())) { - autoCancel.SetCancelErrorResult(aCx, error); - return; - } - } - - if (!ir->GetChannelInfo().IsInitialized()) { - // This is a synthetic response (I think and hope so). - ir->InitChannelInfo(worker->GetChannelInfo()); - } - - autoCancel.Reset(); - - mRespondWithPromiseHolder.Resolve( - FetchEventRespondWithResult( - SynthesizeResponseArgs(ir, mRespondWithClosure.ref())), - __func__); -} - -void FetchEventOp::RejectedCallback(JSContext* aCx, - JS::Handle aValue) { - MOZ_ASSERT(IsCurrentThreadRunningWorker()); - MOZ_ASSERT(mRespondWithClosure); - MOZ_ASSERT(!mRespondWithPromiseHolder.IsEmpty()); - MOZ_ASSERT(!mPromiseHolder.IsEmpty()); - - FetchEventRespondWithClosure& closure = mRespondWithClosure.ref(); - - nsCString sourceSpec = closure.respondWithScriptSpec(); - uint32_t line = closure.respondWithLineNumber(); - uint32_t column = closure.respondWithColumnNumber(); - nsString valueString; - - nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, - valueString); - - nsString requestURL; - GetRequestURL(requestURL); - - AsyncLog(sourceSpec, line, column, - NS_LITERAL_CSTRING("InterceptionRejectedResponseWithURL"), - {std::move(requestURL), valueString}); - - mRespondWithPromiseHolder.Resolve( - FetchEventRespondWithResult( - CancelInterceptionArgs(NS_ERROR_INTERCEPTION_FAILED)), - __func__); -} - -nsresult FetchEventOp::DispatchFetchEvent(JSContext* aCx, - WorkerPrivate* aWorkerPrivate) { - MOZ_ASSERT(aCx); - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - - ServiceWorkerFetchEventOpArgs& args = - mArgs.get_ServiceWorkerFetchEventOpArgs(); - - /** - * Step 1: get the InternalRequest. The InternalRequest can't be constructed - * here from mArgs because the IPCStream has to be deserialized on the - * thread receiving the ServiceWorkerFetchEventOpArgs. - * FetchEventOpProxyChild will have already deserialized the stream on the - * correct thread before creating this op, so we can take its saved - * InternalRequest. - */ - RefPtr internalRequest = mActor->ExtractInternalRequest(); - - /** - * Step 2: get the worker's global object - */ - GlobalObject globalObject(aCx, aWorkerPrivate->GlobalScope()->GetWrapper()); - nsCOMPtr globalObjectAsSupports = - do_QueryInterface(globalObject.GetAsSupports()); - if (NS_WARN_IF(!globalObjectAsSupports)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - /** - * Step 3: create the public DOM Request object - * TODO: this Request object should be created with an AbortSignal object - * which should be aborted if the loading is aborted. See but 1394102. - */ - RefPtr request = - new Request(globalObjectAsSupports, internalRequest, nullptr); - MOZ_ASSERT_IF(internalRequest->IsNavigationRequest(), - request->Redirect() == RequestRedirect::Manual); - - /** - * Step 4a: create the FetchEventInit - */ - RootedDictionary fetchEventInit(aCx); - fetchEventInit.mRequest = request; - fetchEventInit.mBubbles = false; - fetchEventInit.mCancelable = true; - fetchEventInit.mIsReload = args.isReload(); - - /** - * TODO: only expose the FetchEvent.clientId on subresource requests for - * now. Once we implement .targetClientId we can then start exposing - * .clientId on non-subresource requests as well. See bug 1487534. - */ - if (!args.clientId().IsEmpty() && !internalRequest->IsNavigationRequest()) { - fetchEventInit.mClientId = args.clientId(); - } - - /* - * https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm - * - * "If request is a non-subresource request and request’s - * destination is not "report", initialize e’s resultingClientId attribute - * to reservedClient’s [resultingClient's] id, and to the empty string - * otherwise." (Step 18.8) - */ - if (!args.resultingClientId().IsEmpty() && args.isNonSubresourceRequest() && - internalRequest->Destination() != RequestDestination::Report) { - fetchEventInit.mResultingClientId = args.resultingClientId(); - } - - /** - * Step 4b: create the FetchEvent - */ - ErrorResult result; - RefPtr fetchEvent = FetchEvent::Constructor( - globalObject, NS_LITERAL_STRING("fetch"), fetchEventInit, result); - if (NS_WARN_IF(result.Failed())) { - return result.StealNSResult(); - } - fetchEvent->SetTrusted(true); - fetchEvent->PostInit(args.workerScriptSpec(), this); - - /** - * Step 5: Dispatch the FetchEvent to the worker's global object - */ - nsresult rv = DispatchExtendableEventOnWorkerScope( - aCx, aWorkerPrivate->GlobalScope(), fetchEvent, this); - bool dispatchFailed = NS_FAILED(rv) && rv != NS_ERROR_XPC_JS_THREW_EXCEPTION; - - if (NS_WARN_IF(dispatchFailed)) { - return rv; - } - - /** - * At this point, there are 4 (legal) scenarios: - * - * 1) If neither waitUntil() nor respondWith() are called, - * DispatchExtendableEventOnWorkerScope() will have already called - * FinishedWithResult(), but this call will have recorded the result - * (mResult) and returned early so that mRespondWithPromiseHolder can be - * settled first. mRespondWithPromiseHolder will be settled below, followed - * by a call to MaybeFinished() which settles mPromiseHolder. - * - * 2) If waitUntil() is called at least once, and respondWith() is not - * called, DispatchExtendableEventOnWorkerScope() will NOT have called - * FinishedWithResult(). We'll settle mRespondWithPromiseHolder first, and - * at some point in the future when the last waitUntil() promise settles, - * FinishedWithResult() will be called, settling mPromiseHolder. - * - * 3) If waitUntil() is not called, and respondWith() is called, - * DispatchExtendableEventOnWorkerScope() will NOT have called - * FinishedWithResult(). We can also guarantee that - * mRespondWithPromiseHolder will be settled before mPromiseHolder, due to - * the Promise::AppendNativeHandler() call ordering in - * FetchEvent::RespondWith(). - * - * 4) If waitUntil() is called at least once, and respondWith() is also - * called, the effect is similar to scenario 3), with the most imporant - * property being mRespondWithPromiseHolder settling before mPromiseHolder. - * - * Note that if mPromiseHolder is settled before mRespondWithPromiseHolder, - * FetchEventOpChild will cancel the interception. - */ - if (!fetchEvent->WaitToRespond()) { - MOZ_ASSERT(!mRespondWithPromiseHolder.IsEmpty()); - MOZ_ASSERT(!aWorkerPrivate->UsesSystemPrincipal(), - "We don't support system-principal serviceworkers"); - - if (fetchEvent->DefaultPrevented(CallerType::NonSystem)) { - mRespondWithPromiseHolder.Resolve( - FetchEventRespondWithResult( - CancelInterceptionArgs(NS_ERROR_INTERCEPTION_FAILED)), - __func__); - } else { - mRespondWithPromiseHolder.Resolve( - FetchEventRespondWithResult(ResetInterceptionArgs()), __func__); - } - } else { - MOZ_ASSERT(mRespondWithClosure); - } - - mPostDispatchChecksDone = true; - MaybeFinished(); - - return NS_OK; -} - -/* static */ already_AddRefed ServiceWorkerOp::Create( - const ServiceWorkerOpArgs& aArgs, - std::function&& aCallback) { - MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - - RefPtr op; - - switch (aArgs.type()) { - case ServiceWorkerOpArgs::TServiceWorkerCheckScriptEvaluationOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerUpdateStateOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerTerminateWorkerOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerLifeCycleEventOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerPushEventOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerPushSubscriptionChangeEventOpArgs: - op = MakeRefPtr(aArgs, - std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerNotificationEventOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerMessageEventOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - case ServiceWorkerOpArgs::TServiceWorkerFetchEventOpArgs: - op = MakeRefPtr(aArgs, std::move(aCallback)); - break; - default: - MOZ_CRASH("Unknown Service Worker operation!"); - return nullptr; - } - - return op.forget(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/ServiceWorkerOp.h b/dom/serviceworkers/ServiceWorkerOp.h deleted file mode 100644 index 3ab1b6ef6099..000000000000 --- a/dom/serviceworkers/ServiceWorkerOp.h +++ /dev/null @@ -1,172 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_serviceworkerop_h__ -#define mozilla_dom_serviceworkerop_h__ - -#include - -#include "nsISupportsImpl.h" - -#include "ServiceWorkerEvents.h" -#include "ServiceWorkerOpPromise.h" -#include "mozilla/Attributes.h" -#include "mozilla/Maybe.h" -#include "mozilla/RefPtr.h" -#include "mozilla/dom/PromiseNativeHandler.h" -#include "mozilla/dom/RemoteWorkerChild.h" -#include "mozilla/dom/ServiceWorkerOpArgs.h" -#include "mozilla/dom/WorkerRunnable.h" - -namespace mozilla { -namespace dom { - -class FetchEventOpProxyChild; - -class ServiceWorkerOp : public RemoteWorkerChild::Op { - public: - // `aCallback` will be called when the operation completes or is canceled. - static already_AddRefed Create( - const ServiceWorkerOpArgs& aArgs, - std::function&& aCallback); - - ServiceWorkerOp( - const ServiceWorkerOpArgs& aArgs, - std::function&& aCallback); - - ServiceWorkerOp(const ServiceWorkerOp&) = delete; - - ServiceWorkerOp& operator=(const ServiceWorkerOp&) = delete; - - ServiceWorkerOp(ServiceWorkerOp&&) = default; - - ServiceWorkerOp& operator=(ServiceWorkerOp&&) = default; - - // Returns `true` if the operation has started and `false` otherwise. - bool MaybeStart(RemoteWorkerChild* aOwner, - RemoteWorkerChild::State& aState) final; - - void Cancel() final; - - protected: - ~ServiceWorkerOp(); - - bool Started() const; - - bool IsTerminationOp() const; - - // Override to provide a runnable that's not a `ServiceWorkerOpRunnable.` - virtual RefPtr GetRunnable(WorkerPrivate* aWorkerPrivate); - - virtual bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) = 0; - - // Override to reject any additional MozPromises that subclasses may contain. - virtual void RejectAll(nsresult aStatus); - - ServiceWorkerOpArgs mArgs; - - // Subclasses must settle this promise when appropriate. - MozPromiseHolder mPromiseHolder; - - private: - class ServiceWorkerOpRunnable; - - bool mStarted = false; -}; - -class ExtendableEventOp : public ServiceWorkerOp, - public ExtendableEventCallback { - using ServiceWorkerOp::ServiceWorkerOp; - - protected: - ~ExtendableEventOp() = default; - - void FinishedWithResult(ExtendableEventResult aResult) override; -}; - -class FetchEventOp final : public ExtendableEventOp, - public PromiseNativeHandler { - using ExtendableEventOp::ExtendableEventOp; - - public: - NS_DECL_THREADSAFE_ISUPPORTS - - /** - * This must be called once and only once before the first call to - * `MaybeStart()`; `aActor` will be used for `AsyncLog()` and - * `ReportCanceled().` - */ - void SetActor(RefPtr aActor); - - void RevokeActor(FetchEventOpProxyChild* aActor); - - // This must be called at most once before the first call to `MaybeStart().` - RefPtr GetRespondWithPromise(); - - // This must be called when `FetchEvent::RespondWith()` is called. - void RespondWithCalledAt(const nsCString& aRespondWithScriptSpec, - uint32_t aRespondWithLineNumber, - uint32_t aRespondWithColumnNumber); - - void ReportCanceled(const nsCString& aPreventDefaultScriptSpec, - uint32_t aPreventDefaultLineNumber, - uint32_t aPreventDefaultColumnNumber); - - private: - class AutoCancel; - - ~FetchEventOp(); - - bool Exec(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override; - - void RejectAll(nsresult aStatus) override; - - void FinishedWithResult(ExtendableEventResult aResult) override; - - /** - * `{Resolved,Reject}Callback()` are use to handle the - * `FetchEvent::RespondWith()` promise. - */ - void ResolvedCallback(JSContext* aCx, JS::Handle aValue) override; - - void RejectedCallback(JSContext* aCx, JS::Handle aValue) override; - - void MaybeFinished(); - - // Requires mRespondWithClosure to be non-empty. - void AsyncLog(const nsCString& aMessageName, nsTArray aParams); - - void AsyncLog(const nsCString& aScriptSpec, uint32_t aLineNumber, - uint32_t aColumnNumber, const nsCString& aMessageName, - nsTArray aParams); - - void GetRequestURL(nsAString& aOutRequestURL); - - // A failure code means that the dispatch failed. - nsresult DispatchFetchEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate); - - // Worker Launcher thread only. Used for `AsyncLog().` - RefPtr mActor; - - /** - * Created on the Worker Launcher thread and settled on the worker thread. - * If this isn't settled before `mPromiseHolder` (which it should be), - * `FetchEventOpChild` will cancel the intercepted network request. - */ - MozPromiseHolder mRespondWithPromiseHolder; - - // Worker thread only. - Maybe mResult; - bool mPostDispatchChecksDone = false; - - // Worker thread only; set when `FetchEvent::RespondWith()` is called. - Maybe mRespondWithClosure; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_serviceworkerop_h__ diff --git a/dom/serviceworkers/ServiceWorkerOpArgs.ipdlh b/dom/serviceworkers/ServiceWorkerOpArgs.ipdlh deleted file mode 100644 index 40c8b7a9b9ca..000000000000 --- a/dom/serviceworkers/ServiceWorkerOpArgs.ipdlh +++ /dev/null @@ -1,129 +0,0 @@ -/* 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 ChannelInfo; -include ClientIPCTypes; -include DOMTypes; -include FetchTypes; - -using ServiceWorkerState from "mozilla/dom/ServiceWorkerIPCUtils.h"; - -namespace mozilla { -namespace dom { - -/** - * ServiceWorkerOpArgs - */ -struct ServiceWorkerCheckScriptEvaluationOpArgs {}; - -struct ServiceWorkerUpdateStateOpArgs { - ServiceWorkerState state; -}; - -struct ServiceWorkerTerminateWorkerOpArgs {}; - -struct ServiceWorkerLifeCycleEventOpArgs { - nsString eventName; -}; - -// Possibly need to differentiate an empty array from the absence of an array. -union OptionalPushData { - void_t; - uint8_t[]; -}; - -struct ServiceWorkerPushEventOpArgs { - nsString messageId; - OptionalPushData data; -}; - -struct ServiceWorkerPushSubscriptionChangeEventOpArgs {}; - -struct ServiceWorkerNotificationEventOpArgs { - nsString eventName; - nsString id; - nsString title; - nsString dir; - nsString lang; - nsString body; - nsString tag; - nsString icon; - nsString data; - nsString behavior; - nsString scope; - uint32_t disableOpenClickDelay; -}; - -struct ServiceWorkerMessageEventOpArgs { - ClientInfoAndState clientInfoAndState; - ClonedMessageData clonedData; -}; - -struct ServiceWorkerFetchEventOpArgs { - nsCString workerScriptSpec; - IPCInternalRequest internalRequest; - nsString clientId; - nsString resultingClientId; - bool isReload; - bool isNonSubresourceRequest; -}; - -union ServiceWorkerOpArgs { - ServiceWorkerCheckScriptEvaluationOpArgs; - ServiceWorkerUpdateStateOpArgs; - ServiceWorkerTerminateWorkerOpArgs; - ServiceWorkerLifeCycleEventOpArgs; - ServiceWorkerPushEventOpArgs; - ServiceWorkerPushSubscriptionChangeEventOpArgs; - ServiceWorkerNotificationEventOpArgs; - ServiceWorkerMessageEventOpArgs; - ServiceWorkerFetchEventOpArgs; -}; - -/** - * IPCFetchEventRespondWithResult - */ -struct FetchEventRespondWithClosure { - nsCString respondWithScriptSpec; - uint32_t respondWithLineNumber; - uint32_t respondWithColumnNumber; -}; - -struct IPCSynthesizeResponseArgs { - IPCInternalResponse internalResponse; - FetchEventRespondWithClosure closure; -}; - -struct ResetInterceptionArgs {}; - -struct CancelInterceptionArgs { - nsresult status; -}; - -union IPCFetchEventRespondWithResult { - IPCSynthesizeResponseArgs; - ResetInterceptionArgs; - CancelInterceptionArgs; -}; - -/** - * ServiceWorkerOpResult - */ -struct ServiceWorkerCheckScriptEvaluationOpResult { - bool workerScriptExecutedSuccessfully; - bool fetchHandlerWasAdded; -}; - -struct ServiceWorkerFetchEventOpResult { - nsresult rv; -}; - -union ServiceWorkerOpResult { - nsresult; - ServiceWorkerCheckScriptEvaluationOpResult; - ServiceWorkerFetchEventOpResult; -}; - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/ServiceWorkerOpPromise.h b/dom/serviceworkers/ServiceWorkerOpPromise.h deleted file mode 100644 index ff42e8907859..000000000000 --- a/dom/serviceworkers/ServiceWorkerOpPromise.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_serviceworkeroppromise_h__ -#define mozilla_dom_serviceworkeroppromise_h__ - -#include "mozilla/MozPromise.h" -#include "mozilla/Pair.h" -#include "mozilla/RefPtr.h" -#include "mozilla/dom/ServiceWorkerOpArgs.h" - -namespace mozilla { -namespace dom { - -class InternalResponse; - -using SynthesizeResponseArgs = - Pair, FetchEventRespondWithClosure>; - -using FetchEventRespondWithResult = - Variant; - -using FetchEventRespondWithPromise = - MozPromise; - -using ServiceWorkerOpPromise = - MozPromise; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_serviceworkeroppromise_h__ diff --git a/dom/serviceworkers/ServiceWorkerPrivate.cpp b/dom/serviceworkers/ServiceWorkerPrivate.cpp index 37388f21914c..2ff55b8317e8 100644 --- a/dom/serviceworkers/ServiceWorkerPrivate.cpp +++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp @@ -6,12 +6,8 @@ #include "ServiceWorkerPrivate.h" -#include - #include "ServiceWorkerCloneData.h" #include "ServiceWorkerManager.h" -#include "ServiceWorkerPrivateImpl.h" -#include "ServiceWorkerUtils.h" #include "nsContentUtils.h" #include "nsICacheInfoChannel.h" #include "nsIHttpChannelInternal.h" @@ -44,10 +40,8 @@ #include "mozilla/dom/WorkerRunnable.h" #include "mozilla/dom/WorkerScope.h" #include "mozilla/dom/ipc/StructuredCloneData.h" -#include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/net/CookieSettings.h" #include "mozilla/net/NeckoChannelParams.h" -#include "mozilla/Services.h" #include "mozilla/StaticPrefs_dom.h" #include "mozilla/Unused.h" #include "nsIReferrerInfo.h" @@ -74,17 +68,26 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(ServiceWorkerPrivate, Release) // still be a valid value since it was set prior to dispatching the runnable. Atomic gDOMDisableOpenClickDelay(0); -KeepAliveToken::KeepAliveToken(ServiceWorkerPrivate* aPrivate) - : mPrivate(aPrivate) { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aPrivate); - mPrivate->AddToken(); -} +// Used to keep track of pending waitUntil as well as in-flight extendable +// events. When the last token is released, we attempt to terminate the worker. +class KeepAliveToken final : public nsISupports { + public: + NS_DECL_ISUPPORTS -KeepAliveToken::~KeepAliveToken() { - MOZ_ASSERT(NS_IsMainThread()); - mPrivate->ReleaseToken(); -} + explicit KeepAliveToken(ServiceWorkerPrivate* aPrivate) : mPrivate(aPrivate) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aPrivate); + mPrivate->AddToken(); + } + + private: + ~KeepAliveToken() { + MOZ_ASSERT(NS_IsMainThread()); + mPrivate->ReleaseToken(); + } + + RefPtr mPrivate; +}; NS_IMPL_ISUPPORTS0(KeepAliveToken) @@ -95,20 +98,11 @@ ServiceWorkerPrivate::ServiceWorkerPrivate(ServiceWorkerInfo* aInfo) mIdleWorkerTimer = NS_NewTimer(); MOZ_ASSERT(mIdleWorkerTimer); - - if (ServiceWorkerParentInterceptEnabled()) { - RefPtr inner = new ServiceWorkerPrivateImpl(this); - nsresult rv = inner->Initialize(); - MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); - - mInner = inner.forget(); - } } ServiceWorkerPrivate::~ServiceWorkerPrivate() { MOZ_ASSERT(!mWorkerPrivate); MOZ_ASSERT(!mTokenCount); - MOZ_ASSERT(!mInner); MOZ_ASSERT(!mInfo); MOZ_ASSERT(mSupportsArray.IsEmpty()); MOZ_ASSERT(mIdlePromiseHolder.IsEmpty()); @@ -195,12 +189,6 @@ class CheckScriptEvaluationWithCallback final : public WorkerRunnable { nsresult ServiceWorkerPrivate::CheckScriptEvaluation( LifeCycleEventCallback* aScriptEvaluationCallback) { - MOZ_ASSERT(NS_IsMainThread()); - - if (mInner) { - return mInner->CheckScriptEvaluation(aScriptEvaluationCallback); - } - nsresult rv = SpawnWorkerIfNeeded(LifeCycleEvent); NS_ENSURE_SUCCESS(rv, rv); @@ -216,6 +204,15 @@ nsresult ServiceWorkerPrivate::CheckScriptEvaluation( namespace { +enum ExtendableEventResult { Rejected = 0, Resolved }; + +class ExtendableEventCallback { + public: + virtual void FinishedWithResult(ExtendableEventResult aResult) = 0; + + NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING +}; + class KeepAliveHandler final : public ExtendableEvent::ExtensionsHandler, public PromiseNativeHandler { // This class manages lifetime extensions added by calling WaitUntil() @@ -519,10 +516,6 @@ nsresult ServiceWorkerPrivate::SendMessageEvent( const ClientInfoAndState& aClientInfoAndState) { MOZ_ASSERT(NS_IsMainThread()); - if (mInner) { - return mInner->SendMessageEvent(std::move(aData), aClientInfoAndState); - } - nsresult rv = SpawnWorkerIfNeeded(MessageEvent); NS_ENSURE_SUCCESS(rv, rv); @@ -731,12 +724,6 @@ bool LifecycleEventWorkerRunnable::DispatchLifecycleEvent( nsresult ServiceWorkerPrivate::SendLifeCycleEvent( const nsAString& aEventType, LifeCycleEventCallback* aCallback) { - MOZ_ASSERT(NS_IsMainThread()); - - if (mInner) { - return mInner->SendLifeCycleEvent(aEventType, aCallback); - } - nsresult rv = SpawnWorkerIfNeeded(LifeCycleEvent); NS_ENSURE_SUCCESS(rv, rv); @@ -897,12 +884,6 @@ class SendPushSubscriptionChangeEventRunnable final nsresult ServiceWorkerPrivate::SendPushEvent( const nsAString& aMessageId, const Maybe>& aData, ServiceWorkerRegistrationInfo* aRegistration) { - MOZ_ASSERT(NS_IsMainThread()); - - if (mInner) { - return mInner->SendPushEvent(aRegistration, aMessageId, aData); - } - nsresult rv = SpawnWorkerIfNeeded(PushEvent); NS_ENSURE_SUCCESS(rv, rv); @@ -930,12 +911,6 @@ nsresult ServiceWorkerPrivate::SendPushEvent( } nsresult ServiceWorkerPrivate::SendPushSubscriptionChangeEvent() { - MOZ_ASSERT(NS_IsMainThread()); - - if (mInner) { - return mInner->SendPushSubscriptionChangeEvent(); - } - nsresult rv = SpawnWorkerIfNeeded(PushSubscriptionChangeEvent); NS_ENSURE_SUCCESS(rv, rv); @@ -1151,8 +1126,6 @@ nsresult ServiceWorkerPrivate::SendNotificationEvent( const nsAString& aDir, const nsAString& aLang, const nsAString& aBody, const nsAString& aTag, const nsAString& aIcon, const nsAString& aData, const nsAString& aBehavior, const nsAString& aScope) { - MOZ_ASSERT(NS_IsMainThread()); - WakeUpReason why; if (aEventName.EqualsLiteral(NOTIFICATION_CLICK_EVENT_NAME)) { why = NotificationClickEvent; @@ -1165,12 +1138,6 @@ nsresult ServiceWorkerPrivate::SendNotificationEvent( return NS_ERROR_FAILURE; } - if (mInner) { - return mInner->SendNotificationEvent(aEventName, aID, aTitle, aDir, aLang, - aBody, aTag, aIcon, aData, aBehavior, - aScope, gDOMDisableOpenClickDelay); - } - nsresult rv = SpawnWorkerIfNeeded(why); NS_ENSURE_SUCCESS(rv, rv); @@ -1620,11 +1587,6 @@ nsresult ServiceWorkerPrivate::SendFetchEvent( return NS_OK; } - if (mInner) { - return mInner->SendFetchEvent(std::move(registration), aChannel, aClientId, - aResultingClientId, aIsReload); - } - aChannel->SetLaunchServiceWorkerStart(TimeStamp::Now()); aChannel->SetDispatchFetchEventStart(TimeStamp::Now()); @@ -1672,7 +1634,6 @@ nsresult ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy, bool* aNewWorkerCreated, nsILoadGroup* aLoadGroup) { MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mInner); // Defaults to no new worker created, but if there is one, we'll set the value // to true at the end of this function. @@ -1829,10 +1790,6 @@ void ServiceWorkerPrivate::RemoveISupports(nsISupports* aSupports) { void ServiceWorkerPrivate::TerminateWorker() { MOZ_ASSERT(NS_IsMainThread()); - if (mInner) { - return mInner->TerminateWorker(); - } - mIdleWorkerTimer->Cancel(); mIdleKeepAliveToken = nullptr; if (mWorkerPrivate) { @@ -1860,15 +1817,8 @@ void ServiceWorkerPrivate::TerminateWorker() { void ServiceWorkerPrivate::NoteDeadServiceWorkerInfo() { MOZ_ASSERT(NS_IsMainThread()); - - if (mInner) { - mInner->NoteDeadOuter(); - mInner = nullptr; - } else { - TerminateWorker(); - } - mInfo = nullptr; + TerminateWorker(); } namespace { @@ -1894,10 +1844,6 @@ class UpdateStateControlRunnable final void ServiceWorkerPrivate::UpdateState(ServiceWorkerState aState) { MOZ_ASSERT(NS_IsMainThread()); - if (mInner) { - return mInner->UpdateState(aState); - } - if (!mWorkerPrivate) { MOZ_DIAGNOSTIC_ASSERT(mPendingFunctionalEvents.IsEmpty()); return; @@ -1926,11 +1872,6 @@ nsresult ServiceWorkerPrivate::GetDebugger(nsIWorkerDebugger** aResult) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aResult); - if (mInner) { - *aResult = nullptr; - return NS_ERROR_NOT_IMPLEMENTED; - } - if (!mDebuggerCount) { return NS_OK; } @@ -1946,10 +1887,6 @@ nsresult ServiceWorkerPrivate::GetDebugger(nsIWorkerDebugger** aResult) { nsresult ServiceWorkerPrivate::AttachDebugger() { MOZ_ASSERT(NS_IsMainThread()); - if (mInner) { - return NS_ERROR_NOT_IMPLEMENTED; - } - // When the first debugger attaches to a worker, we spawn a worker if needed, // and cancel the idle timeout. The idle timeout should not be reset until // the last debugger detached from the worker. @@ -1968,10 +1905,6 @@ nsresult ServiceWorkerPrivate::AttachDebugger() { nsresult ServiceWorkerPrivate::DetachDebugger() { MOZ_ASSERT(NS_IsMainThread()); - if (mInner) { - return NS_ERROR_NOT_IMPLEMENTED; - } - if (!mDebuggerCount) { return NS_ERROR_UNEXPECTED; } @@ -2053,10 +1986,7 @@ void ServiceWorkerPrivate::NoteIdleWorkerCallback(nsITimer* aTimer) { // Release ServiceWorkerPrivate's token, since the grace period has ended. mIdleKeepAliveToken = nullptr; - if (mWorkerPrivate || (mInner && !mInner->WorkerIsDead())) { - // There sould only be EITHER mWorkerPrivate or mInner (but not both). - MOZ_ASSERT(!(mWorkerPrivate && mInner)); - + if (mWorkerPrivate) { // If we still have a workerPrivate at this point it means there are pending // waitUntil promises. Wait a bit more until we forcibly terminate the // worker. @@ -2087,7 +2017,7 @@ void ServiceWorkerPrivate::TerminateWorkerCallback(nsITimer* aTimer) { void ServiceWorkerPrivate::RenewKeepAliveToken(WakeUpReason aWhy) { // We should have an active worker if we're renewing the keep alive token. - MOZ_ASSERT(mWorkerPrivate || (mInner && !mInner->WorkerIsDead())); + MOZ_ASSERT(mWorkerPrivate); // If there is at least one debugger attached to the worker, the idle worker // timeout was canceled when the first debugger attached to the worker. It @@ -2142,13 +2072,8 @@ void ServiceWorkerPrivate::ReleaseToken() { already_AddRefed ServiceWorkerPrivate::CreateEventKeepAliveToken() { MOZ_ASSERT(NS_IsMainThread()); - - // When the WorkerPrivate is in a separate process, we first hold a normal - // KeepAliveToken. Then, after we're notified that the worker is alive, we - // create the idle KeepAliveToken. - MOZ_ASSERT(mWorkerPrivate || (mInner && !mInner->WorkerIsDead())); - MOZ_ASSERT(mIdleKeepAliveToken || (mInner && !mInner->WorkerIsDead())); - + MOZ_ASSERT(mWorkerPrivate); + MOZ_ASSERT(mIdleKeepAliveToken); RefPtr ref = new KeepAliveToken(this); return ref.forget(); } diff --git a/dom/serviceworkers/ServiceWorkerPrivate.h b/dom/serviceworkers/ServiceWorkerPrivate.h index 76666793c6b7..065c442e5bf2 100644 --- a/dom/serviceworkers/ServiceWorkerPrivate.h +++ b/dom/serviceworkers/ServiceWorkerPrivate.h @@ -24,10 +24,9 @@ class JSObjectHolder; namespace dom { class ClientInfoAndState; +class KeepAliveToken; class ServiceWorkerCloneData; class ServiceWorkerInfo; -class ServiceWorkerPrivate; -class ServiceWorkerPrivateImpl; class ServiceWorkerRegistrationInfo; namespace ipc { @@ -42,20 +41,6 @@ class LifeCycleEventCallback : public Runnable { virtual void SetResult(bool aResult) = 0; }; -// Used to keep track of pending waitUntil as well as in-flight extendable -// events. When the last token is released, we attempt to terminate the worker. -class KeepAliveToken final : public nsISupports { - public: - NS_DECL_ISUPPORTS - - explicit KeepAliveToken(ServiceWorkerPrivate* aPrivate); - - private: - ~KeepAliveToken(); - - RefPtr mPrivate; -}; - // ServiceWorkerPrivate is a wrapper for managing the on-demand aspect of // service workers. It handles all event dispatching to the worker and ensures // the worker thread is running when needed. @@ -89,7 +74,6 @@ class KeepAliveToken final : public nsISupports { // ExtendableEventWorkerRunnable. class ServiceWorkerPrivate final { friend class KeepAliveToken; - friend class ServiceWorkerPrivateImpl; public: NS_IMETHOD_(MozExternalRefCountType) AddRef(); @@ -103,48 +87,6 @@ class ServiceWorkerPrivate final { NS_DECL_OWNINGTHREAD public: - class Inner { - public: - NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING - - virtual nsresult SendMessageEvent( - RefPtr&& aData, - const ClientInfoAndState& aClientInfoAndState) = 0; - - virtual nsresult CheckScriptEvaluation( - RefPtr aScriptEvaluationCallback) = 0; - - virtual nsresult SendLifeCycleEvent( - const nsAString& aEventName, - RefPtr aCallback) = 0; - - virtual nsresult SendPushEvent( - RefPtr aRegistration, - const nsAString& aMessageId, const Maybe>& aData) = 0; - - virtual nsresult SendPushSubscriptionChangeEvent() = 0; - - virtual nsresult SendNotificationEvent( - const nsAString& aEventName, const nsAString& aID, - const nsAString& aTitle, const nsAString& aDir, const nsAString& aLang, - const nsAString& aBody, const nsAString& aTag, const nsAString& aIcon, - const nsAString& aData, const nsAString& aBehavior, - const nsAString& aScope, uint32_t aDisableOpenClickDelay) = 0; - - virtual nsresult SendFetchEvent( - RefPtr aRegistration, - nsCOMPtr aChannel, const nsAString& aClientId, - const nsAString& aResultingClientId, bool aIsReload) = 0; - - virtual void TerminateWorker() = 0; - - virtual void UpdateState(ServiceWorkerState aState) = 0; - - virtual void NoteDeadOuter() = 0; - - virtual bool WorkerIsDead() const = 0; - }; - explicit ServiceWorkerPrivate(ServiceWorkerInfo* aInfo); nsresult SendMessageEvent(RefPtr&& aData, @@ -213,8 +155,7 @@ class ServiceWorkerPrivate final { NotificationClickEvent, NotificationCloseEvent, LifeCycleEvent, - AttachEvent, - Unknown + AttachEvent }; // Timer callbacks @@ -268,8 +209,6 @@ class ServiceWorkerPrivate final { // the worker activating. Main thread only. nsTArray> mPendingFunctionalEvents; - RefPtr mInner; - // Used by the owning `ServiceWorkerRegistrationInfo` when it wants to call // `Clear` after being unregistered and isn't controlling any clients but this // worker (i.e. the registration's active worker) isn't idle yet. Note that diff --git a/dom/serviceworkers/ServiceWorkerPrivateImpl.cpp b/dom/serviceworkers/ServiceWorkerPrivateImpl.cpp deleted file mode 100644 index 3d44882526a1..000000000000 --- a/dom/serviceworkers/ServiceWorkerPrivateImpl.cpp +++ /dev/null @@ -1,1110 +0,0 @@ -/* -*- 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 "ServiceWorkerPrivateImpl.h" - -#include - -#include "MainThreadUtils.h" -#include "js/ErrorReport.h" -#include "nsContentUtils.h" -#include "nsDebug.h" -#include "nsError.h" -#include "nsICacheInfoChannel.h" -#include "nsIChannel.h" -#include "nsIHttpChannel.h" -#include "nsIHttpChannelInternal.h" -#include "nsIHttpHeaderVisitor.h" -#include "nsIInputStream.h" -#include "nsILoadInfo.h" -#include "nsINetworkInterceptController.h" -#include "nsIObserverService.h" -#include "nsIPermissionManager.h" -#include "nsIURI.h" -#include "nsIUploadChannel2.h" -#include "nsPermissionManager.h" -#include "nsThreadUtils.h" - -#include "ServiceWorkerManager.h" -#include "ServiceWorkerRegistrationInfo.h" -#include "mozilla/Assertions.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/Maybe.h" -#include "mozilla/ScopeExit.h" -#include "mozilla/Services.h" -#include "mozilla/StaticPrefs_dom.h" -#include "mozilla/SystemGroup.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/ClientIPCTypes.h" -#include "mozilla/dom/DOMTypes.h" -#include "mozilla/dom/FetchEventOpChild.h" -#include "mozilla/dom/InternalHeaders.h" -#include "mozilla/dom/InternalRequest.h" -#include "mozilla/dom/ReferrerInfo.h" -#include "mozilla/dom/RemoteWorkerControllerChild.h" -#include "mozilla/dom/ServiceWorkerBinding.h" -#include "mozilla/ipc/BackgroundChild.h" -#include "mozilla/ipc/IPCStreamUtils.h" - -namespace mozilla { - -using namespace ipc; - -namespace dom { - -namespace { - -class HeaderFiller final : public nsIHttpHeaderVisitor { - public: - NS_DECL_ISUPPORTS - - explicit HeaderFiller(HeadersGuardEnum aGuard) - : mInternalHeaders(new InternalHeaders(aGuard)) { - MOZ_ASSERT(mInternalHeaders); - } - - NS_IMETHOD - VisitHeader(const nsACString& aHeader, const nsACString& aValue) override { - ErrorResult result; - mInternalHeaders->Append(aHeader, aValue, result); - - if (NS_WARN_IF(result.Failed())) { - return result.StealNSResult(); - } - - return NS_OK; - } - - RefPtr Extract() { - return RefPtr(std::move(mInternalHeaders)); - } - - private: - ~HeaderFiller() = default; - - RefPtr mInternalHeaders; -}; - -NS_IMPL_ISUPPORTS(HeaderFiller, nsIHttpHeaderVisitor) - -nsresult GetIPCInternalRequest(nsIInterceptedChannel* aChannel, - IPCInternalRequest* aOutRequest, - UniquePtr& aAutoStream) { - AssertIsOnMainThread(); - - nsCOMPtr uri; - nsresult rv = aChannel->GetSecureUpgradedChannelURI(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr uriNoFragment; - rv = NS_GetURIWithoutRef(uri, getter_AddRefs(uriNoFragment)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr underlyingChannel; - rv = aChannel->GetChannel(getter_AddRefs(underlyingChannel)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr httpChannel = do_QueryInterface(underlyingChannel); - MOZ_ASSERT(httpChannel, "How come we don't have an HTTP channel?"); - - nsCOMPtr internalChannel = - do_QueryInterface(httpChannel); - NS_ENSURE_TRUE(internalChannel, NS_ERROR_NOT_AVAILABLE); - - nsCOMPtr cacheInfoChannel = - do_QueryInterface(underlyingChannel); - - nsAutoCString spec; - rv = uriNoFragment->GetSpec(spec); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString fragment; - rv = uri->GetRef(fragment); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString method; - rv = httpChannel->GetRequestMethod(method); - NS_ENSURE_SUCCESS(rv, rv); - - // This is safe due to static_asserts in ServiceWorkerManager.cpp - uint32_t cacheModeInt; - rv = internalChannel->GetFetchCacheMode(&cacheModeInt); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - RequestCache cacheMode = static_cast(cacheModeInt); - - RequestMode requestMode = - InternalRequest::MapChannelToRequestMode(underlyingChannel); - - // This is safe due to static_asserts in ServiceWorkerManager.cpp - uint32_t redirectMode; - rv = internalChannel->GetRedirectMode(&redirectMode); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - RequestRedirect requestRedirect = static_cast(redirectMode); - - RequestCredentials requestCredentials = - InternalRequest::MapChannelToRequestCredentials(underlyingChannel); - - nsCString referrer = EmptyCString(); - uint32_t referrerPolicyInt = 0; - - nsCOMPtr referrerInfo = httpChannel->GetReferrerInfo(); - if (referrerInfo) { - referrerPolicyInt = referrerInfo->GetReferrerPolicy(); - nsCOMPtr computedReferrer = referrerInfo->GetComputedReferrer(); - if (computedReferrer) { - rv = computedReferrer->GetSpec(referrer); - NS_ENSURE_SUCCESS(rv, rv); - } - } - - ReferrerPolicy referrerPolicy; - switch (referrerPolicyInt) { - case nsIHttpChannel::REFERRER_POLICY_UNSET: - referrerPolicy = ReferrerPolicy::_empty; - break; - case nsIHttpChannel::REFERRER_POLICY_NO_REFERRER: - referrerPolicy = ReferrerPolicy::No_referrer; - break; - case nsIHttpChannel::REFERRER_POLICY_ORIGIN: - referrerPolicy = ReferrerPolicy::Origin; - break; - case nsIHttpChannel::REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE: - referrerPolicy = ReferrerPolicy::No_referrer_when_downgrade; - break; - case nsIHttpChannel::REFERRER_POLICY_ORIGIN_WHEN_XORIGIN: - referrerPolicy = ReferrerPolicy::Origin_when_cross_origin; - break; - case nsIHttpChannel::REFERRER_POLICY_UNSAFE_URL: - referrerPolicy = ReferrerPolicy::Unsafe_url; - break; - case nsIHttpChannel::REFERRER_POLICY_SAME_ORIGIN: - referrerPolicy = ReferrerPolicy::Same_origin; - break; - case nsIHttpChannel::REFERRER_POLICY_STRICT_ORIGIN_WHEN_XORIGIN: - referrerPolicy = ReferrerPolicy::Strict_origin_when_cross_origin; - break; - case nsIHttpChannel::REFERRER_POLICY_STRICT_ORIGIN: - referrerPolicy = ReferrerPolicy::Strict_origin; - break; - default: - MOZ_ASSERT_UNREACHABLE("Invalid Referrer Policy enum value?"); - break; - } - - uint32_t loadFlags; - rv = underlyingChannel->GetLoadFlags(&loadFlags); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr loadInfo; - rv = underlyingChannel->GetLoadInfo(getter_AddRefs(loadInfo)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_STATE(loadInfo); - - nsContentPolicyType contentPolicyType = loadInfo->InternalContentPolicyType(); - - nsAutoString integrity; - rv = internalChannel->GetIntegrityMetadata(integrity); - NS_ENSURE_SUCCESS(rv, rv); - - RefPtr headerFiller = - MakeRefPtr(HeadersGuardEnum::Request); - rv = httpChannel->VisitNonDefaultRequestHeaders(headerFiller); - NS_ENSURE_SUCCESS(rv, rv); - - RefPtr internalHeaders = headerFiller->Extract(); - - ErrorResult result; - internalHeaders->SetGuard(HeadersGuardEnum::Immutable, result); - if (NS_WARN_IF(result.Failed())) { - return result.StealNSResult(); - } - - nsCOMPtr uploadChannel = do_QueryInterface(httpChannel); - nsCOMPtr uploadStream; - int64_t uploadStreamContentLength = -1; - if (uploadChannel) { - rv = uploadChannel->CloneUploadStream(&uploadStreamContentLength, - getter_AddRefs(uploadStream)); - NS_ENSURE_SUCCESS(rv, rv); - } - - RefPtr internalRequest = new InternalRequest( - spec, fragment, method, internalHeaders.forget(), cacheMode, requestMode, - requestRedirect, requestCredentials, NS_ConvertUTF8toUTF16(referrer), - referrerPolicy, contentPolicyType, integrity); - internalRequest->SetBody(uploadStream, uploadStreamContentLength); - internalRequest->SetCreatedByFetchEvent(); - - nsAutoCString alternativeDataType; - if (cacheInfoChannel && - !cacheInfoChannel->PreferredAlternativeDataTypes().IsEmpty()) { - // TODO: the internal request probably needs all the preferred types. - alternativeDataType.Assign( - cacheInfoChannel->PreferredAlternativeDataTypes()[0].type()); - internalRequest->SetPreferredAlternativeDataType(alternativeDataType); - } - - PBackgroundChild* bgChild = BackgroundChild::GetForCurrentThread(); - - if (NS_WARN_IF(!bgChild)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - internalRequest->ToIPC(aOutRequest, bgChild, aAutoStream); - - return NS_OK; -} - -} // anonymous namespace - -ServiceWorkerPrivateImpl::RAIIActorPtrHolder::RAIIActorPtrHolder( - already_AddRefed aActor) - : mActor(aActor) { - AssertIsOnMainThread(); - MOZ_ASSERT(mActor); - MOZ_ASSERT(mActor->Manager()); -} - -ServiceWorkerPrivateImpl::RAIIActorPtrHolder::~RAIIActorPtrHolder() { - AssertIsOnMainThread(); - - mDestructorPromiseHolder.ResolveIfExists(true, __func__); - - mActor->MaybeSendDelete(); -} - -RemoteWorkerControllerChild* ServiceWorkerPrivateImpl::RAIIActorPtrHolder:: -operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { - AssertIsOnMainThread(); - - return get(); -} - -RemoteWorkerControllerChild* ServiceWorkerPrivateImpl::RAIIActorPtrHolder::get() - const { - AssertIsOnMainThread(); - - return mActor.get(); -} - -RefPtr -ServiceWorkerPrivateImpl::RAIIActorPtrHolder::OnDestructor() { - AssertIsOnMainThread(); - - return mDestructorPromiseHolder.Ensure(__func__); -} - -ServiceWorkerPrivateImpl::ServiceWorkerPrivateImpl( - RefPtr aOuter) - : mOuter(std::move(aOuter)) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(WorkerIsDead()); -} - -nsresult ServiceWorkerPrivateImpl::Initialize() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mOuter->mInfo); - - nsCOMPtr principal = mOuter->mInfo->Principal(); - - nsCOMPtr uri; - nsresult rv = principal->GetURI(getter_AddRefs(uri)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (NS_WARN_IF(!uri)) { - return NS_ERROR_FAILURE; - } - - URIParams baseScriptURL; - SerializeURI(uri, baseScriptURL); - - PrincipalInfo principalInfo; - rv = PrincipalToPrincipalInfo(principal, &principalInfo); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - RefPtr swm = ServiceWorkerManager::GetInstance(); - - if (NS_WARN_IF(!swm)) { - return NS_ERROR_DOM_ABORT_ERR; - } - - RefPtr regInfo = - swm->GetRegistration(principal, mOuter->mInfo->Scope()); - - if (NS_WARN_IF(!regInfo)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - nsCOMPtr cookieSettings = - mozilla::net::CookieSettings::Create(); - MOZ_ASSERT(cookieSettings); - - StorageAccess storageAccess = StorageAllowedForServiceWorker(principal, - cookieSettings); - - ServiceWorkerData serviceWorkerData; - serviceWorkerData.cacheName() = mOuter->mInfo->CacheName(); - serviceWorkerData.loadFlags() = - static_cast(mOuter->mInfo->GetImportsLoadFlags() | - nsIChannel::LOAD_BYPASS_SERVICE_WORKER); - - mRemoteWorkerData.originalScriptURL() = - NS_ConvertUTF8toUTF16(mOuter->mInfo->ScriptSpec()); - mRemoteWorkerData.baseScriptURL() = baseScriptURL; - mRemoteWorkerData.resolvedScriptURL() = baseScriptURL; - mRemoteWorkerData.name() = VoidString(); - - mRemoteWorkerData.loadingPrincipalInfo() = principalInfo; - mRemoteWorkerData.principalInfo() = principalInfo; - // storagePrincipalInfo for ServiceWorkers is equal to principalInfo because, - // at the moment, ServiceWorkers are not exposed in partitioned contexts. - mRemoteWorkerData.storagePrincipalInfo() = principalInfo; - - rv = uri->GetHost(mRemoteWorkerData.domain()); - NS_ENSURE_SUCCESS(rv, rv); - mRemoteWorkerData.isSecureContext() = true; - mRemoteWorkerData.referrerInfo() = MakeAndAddRef(); - mRemoteWorkerData.storageAccess() = storageAccess; - mRemoteWorkerData.serviceWorkerData() = std::move(serviceWorkerData); - - // This fills in the rest of mRemoteWorkerData.serviceWorkerData(). - rv = RefreshRemoteWorkerData(regInfo); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -RefPtr ServiceWorkerPrivateImpl::SetSkipWaitingFlag() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mOuter->mInfo); - - RefPtr swm = ServiceWorkerManager::GetInstance(); - - if (!swm) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - RefPtr regInfo = - swm->GetRegistration(mOuter->mInfo->Principal(), mOuter->mInfo->Scope()); - - if (!regInfo) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - mOuter->mInfo->SetSkipWaitingFlag(); - - RefPtr promise = - new GenericPromise::Private(__func__); - - regInfo->TryToActivateAsync([promise] { promise->Resolve(true, __func__); }); - - return promise; -} - -nsresult ServiceWorkerPrivateImpl::RefreshRemoteWorkerData( - const RefPtr& aRegistration) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mOuter->mInfo); - - nsTArray permissions; - nsCOMPtr permManager = services::GetPermissionManager(); - nsTArray keys = - nsPermissionManager::GetAllKeysForPrincipal(mOuter->mInfo->Principal()); - MOZ_ASSERT(!keys.IsEmpty()); - - for (auto& key : keys) { - nsTArray perms; - nsresult rv = permManager->GetPermissionsWithKey(key, perms); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - KeyAndPermissions kp; - kp.key() = nsCString(key); - kp.permissions() = std::move(perms); - - permissions.AppendElement(std::move(kp)); - } - - MOZ_ASSERT(!permissions.IsEmpty()); - - ServiceWorkerData& serviceWorkerData = - mRemoteWorkerData.serviceWorkerData().get_ServiceWorkerData(); - serviceWorkerData.permissionsByKey() = std::move(permissions); - serviceWorkerData.descriptor() = mOuter->mInfo->Descriptor().ToIPC(); - serviceWorkerData.registrationDescriptor() = - aRegistration->Descriptor().ToIPC(); - - return NS_OK; -} - -nsresult ServiceWorkerPrivateImpl::SpawnWorkerIfNeeded() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mOuter->mInfo); - - if (mControllerChild) { - return NS_OK; - } - - PBackgroundChild* bgChild = BackgroundChild::GetForCurrentThread(); - - if (NS_WARN_IF(!bgChild)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - RefPtr swm = ServiceWorkerManager::GetInstance(); - - if (NS_WARN_IF(!swm)) { - return NS_ERROR_DOM_ABORT_ERR; - } - - RefPtr regInfo = - swm->GetRegistration(mOuter->mInfo->Principal(), mOuter->mInfo->Scope()); - - if (NS_WARN_IF(!regInfo)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - nsresult rv = RefreshRemoteWorkerData(regInfo); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - RefPtr controllerChild = - new RemoteWorkerControllerChild(this); - - if (NS_WARN_IF(!bgChild->SendPRemoteWorkerControllerConstructor( - controllerChild, mRemoteWorkerData))) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - /** - * Manutally `AddRef()` because `DeallocPRemoteWorkerControllerChild()` - * calls `Release()` and the `AllocPRemoteWorkerControllerChild()` function - * is not called. - */ - // NOLINTNEXTLINE(readability-redundant-smartptr-get) - controllerChild.get()->AddRef(); - - mControllerChild = new RAIIActorPtrHolder(controllerChild.forget()); - - return NS_OK; -} - -ServiceWorkerPrivateImpl::~ServiceWorkerPrivateImpl() { - AssertIsOnMainThread(); - MOZ_ASSERT(!mOuter); - MOZ_ASSERT(WorkerIsDead()); -} - -nsresult ServiceWorkerPrivateImpl::SendMessageEvent( - RefPtr&& aData, - const ClientInfoAndState& aClientInfoAndState) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(aData); - - auto scopeExit = MakeScopeExit([&] { Shutdown(); }); - - PBackgroundChild* bgChild = BackgroundChild::GetForCurrentThread(); - - if (NS_WARN_IF(!bgChild)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - ServiceWorkerMessageEventOpArgs args; - args.clientInfoAndState() = aClientInfoAndState; - if (!aData->BuildClonedMessageDataForBackgroundChild(bgChild, - args.clonedData())) { - return NS_ERROR_DOM_DATA_CLONE_ERR; - } - - scopeExit.release(); - - return ExecServiceWorkerOp( - std::move(args), [](ServiceWorkerOpResult&& aResult) { - MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult); - }); -} - -nsresult ServiceWorkerPrivateImpl::CheckScriptEvaluation( - RefPtr aCallback) { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(aCallback); - - RefPtr self = this; - - /** - * We need to capture the actor associated with the current Service Worker so - * we can terminate it if script evaluation failed. - */ - nsresult rv = SpawnWorkerIfNeeded(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aCallback->SetResult(false); - aCallback->Run(); - - return rv; - } - - MOZ_ASSERT(mControllerChild); - - RefPtr holder = mControllerChild; - - return ExecServiceWorkerOp( - ServiceWorkerCheckScriptEvaluationOpArgs(), - [self = std::move(self), holder = std::move(holder), - callback = aCallback](ServiceWorkerOpResult&& aResult) mutable { - if (aResult.type() == ServiceWorkerOpResult:: - TServiceWorkerCheckScriptEvaluationOpResult) { - auto& result = - aResult.get_ServiceWorkerCheckScriptEvaluationOpResult(); - - if (result.workerScriptExecutedSuccessfully()) { - if (self->mOuter) { - self->mOuter->SetHandlesFetch(result.fetchHandlerWasAdded()); - } - - Unused << NS_WARN_IF(!self->mOuter); - - callback->SetResult(result.workerScriptExecutedSuccessfully()); - callback->Run(); - - return; - } - } - - /** - * If script evaluation failed, first terminate the Service Worker - * before invoking the callback. - */ - MOZ_ASSERT_IF(aResult.type() == ServiceWorkerOpResult::Tnsresult, - NS_FAILED(aResult.get_nsresult())); - - // If a termination operation was already issued using `holder`... - if (self->mControllerChild != holder) { - holder->OnDestructor()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [callback = std::move(callback)]( - const GenericPromise::ResolveOrRejectValue&) { - callback->SetResult(false); - callback->Run(); - }); - - return; - } - - RefPtr promise = self->ShutdownInternal(); - - RefPtr swm = ServiceWorkerManager::GetInstance(); - MOZ_ASSERT(swm); - - swm->BlockShutdownOn(promise); - - promise->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [callback = std::move(callback)]( - const GenericNonExclusivePromise::ResolveOrRejectValue&) { - callback->SetResult(false); - callback->Run(); - }); - }, - [callback = aCallback] { - callback->SetResult(false); - callback->Run(); - }); -} - -nsresult ServiceWorkerPrivateImpl::SendLifeCycleEvent( - const nsAString& aEventName, RefPtr aCallback) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(aCallback); - - return ExecServiceWorkerOp( - ServiceWorkerLifeCycleEventOpArgs(nsString(aEventName)), - [callback = aCallback](ServiceWorkerOpResult&& aResult) { - MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult); - - callback->SetResult(NS_SUCCEEDED(aResult.get_nsresult())); - callback->Run(); - }, - [callback = aCallback] { - callback->SetResult(false); - callback->Run(); - }); -} - -nsresult ServiceWorkerPrivateImpl::SendPushEvent( - RefPtr aRegistration, - const nsAString& aMessageId, const Maybe>& aData) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(aRegistration); - - ServiceWorkerPushEventOpArgs args; - args.messageId() = nsString(aMessageId); - - if (aData) { - args.data() = aData.ref(); - } else { - args.data() = void_t(); - } - - if (mOuter->mInfo->State() == ServiceWorkerState::Activating) { - UniquePtr pendingEvent = - MakeUnique(this, std::move(aRegistration), - std::move(args)); - - mPendingFunctionalEvents.AppendElement(std::move(pendingEvent)); - - return NS_OK; - } - - MOZ_ASSERT(mOuter->mInfo->State() == ServiceWorkerState::Activated); - - return SendPushEventInternal(std::move(aRegistration), std::move(args)); -} - -nsresult ServiceWorkerPrivateImpl::SendPushEventInternal( - RefPtr&& aRegistration, - ServiceWorkerPushEventOpArgs&& aArgs) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(aRegistration); - - return ExecServiceWorkerOp( - std::move(aArgs), - [registration = aRegistration](ServiceWorkerOpResult&& aResult) { - MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult); - - registration->MaybeScheduleTimeCheckAndUpdate(); - }, - [registration = aRegistration]() { - registration->MaybeScheduleTimeCheckAndUpdate(); - }); -} - -nsresult ServiceWorkerPrivateImpl::SendPushSubscriptionChangeEvent() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - - return ExecServiceWorkerOp( - ServiceWorkerPushSubscriptionChangeEventOpArgs(), - [](ServiceWorkerOpResult&& aResult) { - MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult); - }); -} - -nsresult ServiceWorkerPrivateImpl::SendNotificationEvent( - const nsAString& aEventName, const nsAString& aID, const nsAString& aTitle, - const nsAString& aDir, const nsAString& aLang, const nsAString& aBody, - const nsAString& aTag, const nsAString& aIcon, const nsAString& aData, - const nsAString& aBehavior, const nsAString& aScope, - uint32_t aDisableOpenClickDelay) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - - ServiceWorkerNotificationEventOpArgs args; - args.eventName() = nsString(aEventName); - args.id() = nsString(aID); - args.title() = nsString(aTitle); - args.dir() = nsString(aDir); - args.lang() = nsString(aLang); - args.body() = nsString(aBody); - args.tag() = nsString(aTag); - args.icon() = nsString(aIcon); - args.data() = nsString(aData); - args.behavior() = nsString(aBehavior); - args.scope() = nsString(aScope); - args.disableOpenClickDelay() = aDisableOpenClickDelay; - - return ExecServiceWorkerOp( - std::move(args), [](ServiceWorkerOpResult&& aResult) { - MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult); - }); -} - -ServiceWorkerPrivateImpl::PendingFunctionalEvent::PendingFunctionalEvent( - ServiceWorkerPrivateImpl* aOwner, - RefPtr&& aRegistration) - : mOwner(aOwner), mRegistration(std::move(aRegistration)) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOwner); - MOZ_ASSERT(mOwner->mOuter); - MOZ_ASSERT(mOwner->mOuter->mInfo); - MOZ_ASSERT(mOwner->mOuter->mInfo->State() == ServiceWorkerState::Activating); - MOZ_ASSERT(mRegistration); -} - -ServiceWorkerPrivateImpl::PendingFunctionalEvent::~PendingFunctionalEvent() { - AssertIsOnMainThread(); -} - -ServiceWorkerPrivateImpl::PendingPushEvent::PendingPushEvent( - ServiceWorkerPrivateImpl* aOwner, - RefPtr&& aRegistration, - ServiceWorkerPushEventOpArgs&& aArgs) - : PendingFunctionalEvent(aOwner, std::move(aRegistration)), - mArgs(std::move(aArgs)) { - AssertIsOnMainThread(); -} - -nsresult ServiceWorkerPrivateImpl::PendingPushEvent::Send() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOwner->mOuter); - MOZ_ASSERT(mOwner->mOuter->mInfo); - - return mOwner->SendPushEventInternal(std::move(mRegistration), - std::move(mArgs)); -} - -ServiceWorkerPrivateImpl::PendingFetchEvent::PendingFetchEvent( - ServiceWorkerPrivateImpl* aOwner, - RefPtr&& aRegistration, - ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr&& aChannel, - UniquePtr&& aAutoStream) - : PendingFunctionalEvent(aOwner, std::move(aRegistration)), - mArgs(std::move(aArgs)), - mChannel(std::move(aChannel)), - mAutoStream(std::move(aAutoStream)) { - AssertIsOnMainThread(); - MOZ_ASSERT(mChannel); - MOZ_ASSERT(mAutoStream); -} - -nsresult ServiceWorkerPrivateImpl::PendingFetchEvent::Send() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOwner->mOuter); - MOZ_ASSERT(mOwner->mOuter->mInfo); - - return mOwner->SendFetchEventInternal(std::move(mRegistration), - std::move(mArgs), std::move(mChannel), - std::move(mAutoStream)); -} - -ServiceWorkerPrivateImpl::PendingFetchEvent::~PendingFetchEvent() { - AssertIsOnMainThread(); - - if (NS_WARN_IF(mChannel)) { - mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED); - } -} - -nsresult ServiceWorkerPrivateImpl::SendFetchEvent( - RefPtr aRegistration, - nsCOMPtr aChannel, const nsAString& aClientId, - const nsAString& aResultingClientId, bool aIsReload) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(aRegistration); - MOZ_ASSERT(aChannel); - - auto scopeExit = MakeScopeExit([&] { - aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED); - Shutdown(); - }); - - nsCOMPtr channel; - nsresult rv = aChannel->GetChannel(getter_AddRefs(channel)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - IPCInternalRequest internalRequest; - UniquePtr autoStream = MakeUnique(); - rv = GetIPCInternalRequest(aChannel, &internalRequest, autoStream); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - scopeExit.release(); - - MOZ_ASSERT(mOuter->mInfo); - - ServiceWorkerFetchEventOpArgs args( - mOuter->mInfo->ScriptSpec(), internalRequest, nsString(aClientId), - nsString(aResultingClientId), aIsReload, - nsContentUtils::IsNonSubresourceRequest(channel)); - - if (mOuter->mInfo->State() == ServiceWorkerState::Activating) { - UniquePtr pendingEvent = - MakeUnique(this, std::move(aRegistration), - std::move(args), std::move(aChannel), - std::move(autoStream)); - - mPendingFunctionalEvents.AppendElement(std::move(pendingEvent)); - - return NS_OK; - } - - MOZ_ASSERT(mOuter->mInfo->State() == ServiceWorkerState::Activated); - - return SendFetchEventInternal(std::move(aRegistration), std::move(args), - std::move(aChannel), std::move(autoStream)); -} - -nsresult ServiceWorkerPrivateImpl::SendFetchEventInternal( - RefPtr&& aRegistration, - ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr&& aChannel, - UniquePtr&& aAutoStream) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - - auto scopeExit = MakeScopeExit([&] { Shutdown(); }); - - if (NS_WARN_IF(!mOuter->mInfo)) { - return NS_ERROR_DOM_INVALID_STATE_ERR; - } - - nsresult rv = SpawnWorkerIfNeeded(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - scopeExit.release(); - - MOZ_ASSERT(mControllerChild); - - RefPtr holder = mControllerChild; - - FetchEventOpChild::Create(mControllerChild->get(), std::move(aArgs), - std::move(aChannel), std::move(aRegistration), - mOuter->CreateEventKeepAliveToken()) - ->Then(GetCurrentThreadSerialEventTarget(), __func__, - [holder = std::move(holder)]( - const GenericPromise::ResolveOrRejectValue& aResult) { - Unused << NS_WARN_IF(aResult.IsReject()); - }); - - aAutoStream->TakeOptionalValue(); - - return NS_OK; -} - -void ServiceWorkerPrivateImpl::TerminateWorker() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - - mOuter->mIdleWorkerTimer->Cancel(); - mOuter->mIdleKeepAliveToken = nullptr; - - Shutdown(); -} - -void ServiceWorkerPrivateImpl::Shutdown() { - AssertIsOnMainThread(); - - if (!WorkerIsDead()) { - RefPtr swm = ServiceWorkerManager::GetInstance(); - - MOZ_ASSERT(swm, - "All Service Workers should start shutting down before the " - "ServiceWorkerManager does!"); - - RefPtr promise = ShutdownInternal(); - swm->BlockShutdownOn(promise); - } - - MOZ_ASSERT(WorkerIsDead()); -} - -RefPtr -ServiceWorkerPrivateImpl::ShutdownInternal() { - AssertIsOnMainThread(); - MOZ_ASSERT(mControllerChild); - - mPendingFunctionalEvents.Clear(); - - mControllerChild->get()->RevokeObserver(this); - - if (StaticPrefs::dom_serviceWorkers_testing_enabled()) { - nsCOMPtr os = services::GetObserverService(); - if (os) { - os->NotifyObservers(nullptr, "service-worker-shutdown", nullptr); - } - } - - RefPtr promise = - new GenericNonExclusivePromise::Private(__func__); - - Unused << ExecServiceWorkerOp( - ServiceWorkerTerminateWorkerOpArgs(), - [promise](ServiceWorkerOpResult&& aResult) { - MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult); - promise->Resolve(true, __func__); - }, - [promise]() { promise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__); }); - - /** - * After dispatching a termination operation, no new operations should - * be routed through this actor anymore. - */ - mControllerChild = nullptr; - - return promise; -} - -void ServiceWorkerPrivateImpl::UpdateState(ServiceWorkerState aState) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - - if (WorkerIsDead()) { - return; - } - - nsresult rv = ExecServiceWorkerOp( - ServiceWorkerUpdateStateOpArgs(aState), - [](ServiceWorkerOpResult&& aResult) { - MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult); - }); - - if (NS_WARN_IF(NS_FAILED(rv))) { - Shutdown(); - return; - } - - if (aState != ServiceWorkerState::Activated) { - return; - } - - for (auto& event : mPendingFunctionalEvents) { - Unused << NS_WARN_IF(NS_FAILED(event->Send())); - } - - mPendingFunctionalEvents.Clear(); -} - -void ServiceWorkerPrivateImpl::NoteDeadOuter() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - - Shutdown(); - mOuter = nullptr; -} - -void ServiceWorkerPrivateImpl::CreationFailed() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mControllerChild); - - Shutdown(); -} - -void ServiceWorkerPrivateImpl::CreationSucceeded() { - AssertIsOnMainThread(); - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mControllerChild); - - mOuter->RenewKeepAliveToken(ServiceWorkerPrivate::WakeUpReason::Unknown); -} - -void ServiceWorkerPrivateImpl::ErrorReceived(const ErrorValue& aError) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mOuter->mInfo); - MOZ_ASSERT(mControllerChild); - - RefPtr swm = ServiceWorkerManager::GetInstance(); - MOZ_ASSERT(swm); - - ServiceWorkerInfo* info = mOuter->mInfo; - - swm->HandleError(nullptr, info->Principal(), info->Scope(), - NS_ConvertUTF8toUTF16(info->ScriptSpec()), EmptyString(), - EmptyString(), EmptyString(), 0, 0, JSREPORT_ERROR, - JSEXN_ERR); -} - -void ServiceWorkerPrivateImpl::Terminated() { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT(mControllerChild); - - Shutdown(); -} - -bool ServiceWorkerPrivateImpl::WorkerIsDead() const { - AssertIsOnMainThread(); - - return !mControllerChild; -} - -nsresult ServiceWorkerPrivateImpl::ExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs, - std::function&& aSuccessCallback, - std::function&& aFailureCallback) { - AssertIsOnMainThread(); - MOZ_ASSERT(mOuter); - MOZ_ASSERT( - aArgs.type() != ServiceWorkerOpArgs::TServiceWorkerFetchEventOpArgs, - "FetchEvent operations should be sent through FetchEventOp(Proxy) " - "actors!"); - MOZ_ASSERT(aSuccessCallback); - - nsresult rv = SpawnWorkerIfNeeded(); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aFailureCallback(); - return rv; - } - - MOZ_ASSERT(mControllerChild); - - RefPtr self = this; - RefPtr holder = mControllerChild; - RefPtr token = - aArgs.type() == ServiceWorkerOpArgs::TServiceWorkerTerminateWorkerOpArgs - ? nullptr - : mOuter->CreateEventKeepAliveToken(); - - /** - * NOTE: moving `aArgs` won't do anything until IPDL `SendMethod()` methods - * can accept rvalue references rather than just const references. - */ - mControllerChild->get()->SendExecServiceWorkerOp(aArgs)->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [self = std::move(self), holder = std::move(holder), - token = std::move(token), onSuccess = std::move(aSuccessCallback), - onFailure = std::move(aFailureCallback)]( - PRemoteWorkerControllerChild::ExecServiceWorkerOpPromise:: - ResolveOrRejectValue&& aResult) { - if (NS_WARN_IF(aResult.IsReject())) { - onFailure(); - return; - } - - onSuccess(std::move(aResult.ResolveValue())); - }); - - return NS_OK; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/ServiceWorkerPrivateImpl.h b/dom/serviceworkers/ServiceWorkerPrivateImpl.h deleted file mode 100644 index 5f9792923812..000000000000 --- a/dom/serviceworkers/ServiceWorkerPrivateImpl.h +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_serviceworkerprivateimpl_h__ -#define mozilla_dom_serviceworkerprivateimpl_h__ - -#include - -#include "nsCOMPtr.h" -#include "nsISupportsImpl.h" -#include "nsTArray.h" - -#include "ServiceWorkerPrivate.h" -#include "mozilla/Attributes.h" -#include "mozilla/MozPromise.h" -#include "mozilla/RefPtr.h" -#include "mozilla/UniquePtr.h" -#include "mozilla/dom/RemoteWorkerController.h" -#include "mozilla/dom/RemoteWorkerTypes.h" -#include "mozilla/dom/ServiceWorkerOpArgs.h" - -class nsIInterceptedChannel; - -namespace mozilla { - -template -class Maybe; - -namespace ipc { - -class AutoIPCStream; - -} // namespace ipc - -namespace dom { - -class ClientInfoAndState; -class LifeCycleEventCallback; -class RemoteWorkerControllerChild; -class ServiceWorkerCloneData; -class ServiceWorkerRegistrationInfo; - -class ServiceWorkerPrivateImpl final : public ServiceWorkerPrivate::Inner, - public RemoteWorkerObserver { - public: - NS_INLINE_DECL_REFCOUNTING(ServiceWorkerPrivateImpl, override); - - explicit ServiceWorkerPrivateImpl(RefPtr aOuter); - - nsresult Initialize(); - - RefPtr SetSkipWaitingFlag(); - - private: - class RAIIActorPtrHolder; - - ~ServiceWorkerPrivateImpl(); - - /** - * ServiceWorkerPrivate::Inner - */ - nsresult SendMessageEvent( - RefPtr&& aData, - const ClientInfoAndState& aClientInfoAndState) override; - - nsresult CheckScriptEvaluation( - RefPtr aCallback) override; - - nsresult SendLifeCycleEvent( - const nsAString& aEventName, - RefPtr aCallback) override; - - nsresult SendPushEvent(RefPtr aRegistration, - const nsAString& aMessageId, - const Maybe>& aData) override; - - nsresult SendPushSubscriptionChangeEvent() override; - - nsresult SendNotificationEvent(const nsAString& aEventName, - const nsAString& aID, const nsAString& aTitle, - const nsAString& aDir, const nsAString& aLang, - const nsAString& aBody, const nsAString& aTag, - const nsAString& aIcon, const nsAString& aData, - const nsAString& aBehavior, - const nsAString& aScope, - uint32_t aDisableOpenClickDelay) override; - - nsresult SendFetchEvent(RefPtr aRegistration, - nsCOMPtr aChannel, - const nsAString& aClientId, - const nsAString& aResultingClientId, - bool aIsReload) override; - - void TerminateWorker() override; - - void UpdateState(ServiceWorkerState aState) override; - - void NoteDeadOuter() override; - - bool WorkerIsDead() const override; - - /** - * RemoteWorkerObserver - */ - void CreationFailed() override; - - void CreationSucceeded() override; - - void ErrorReceived(const ErrorValue& aError) override; - - void Terminated() override; - - // Refreshes only the parts of mRemoteWorkerData that may change over time. - nsresult RefreshRemoteWorkerData( - const RefPtr& aRegistration); - - nsresult SpawnWorkerIfNeeded(); - - nsresult SendPushEventInternal( - RefPtr&& aRegistration, - ServiceWorkerPushEventOpArgs&& aArgs); - - nsresult SendFetchEventInternal( - RefPtr&& aRegistration, - ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr&& aChannel, - UniquePtr&& aAutoStream); - - void Shutdown(); - - RefPtr ShutdownInternal(); - - nsresult ExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs, - std::function&& aSuccessCallback, - std::function&& aFailureCallback = [] {}); - - class PendingFunctionalEvent { - public: - PendingFunctionalEvent( - ServiceWorkerPrivateImpl* aOwner, - RefPtr&& aRegistration); - - virtual ~PendingFunctionalEvent(); - - virtual nsresult Send() = 0; - - protected: - ServiceWorkerPrivateImpl* const MOZ_NON_OWNING_REF mOwner; - RefPtr mRegistration; - }; - - class PendingPushEvent final : public PendingFunctionalEvent { - public: - PendingPushEvent(ServiceWorkerPrivateImpl* aOwner, - RefPtr&& aRegistration, - ServiceWorkerPushEventOpArgs&& aArgs); - - nsresult Send() override; - - private: - ServiceWorkerPushEventOpArgs mArgs; - }; - - class PendingFetchEvent final : public PendingFunctionalEvent { - public: - PendingFetchEvent(ServiceWorkerPrivateImpl* aOwner, - RefPtr&& aRegistration, - ServiceWorkerFetchEventOpArgs&& aArgs, - nsCOMPtr&& aChannel, - UniquePtr&& aAutoStream); - - nsresult Send() override; - - ~PendingFetchEvent(); - - private: - ServiceWorkerFetchEventOpArgs mArgs; - nsCOMPtr mChannel; - UniquePtr mAutoStream; - }; - - nsTArray> mPendingFunctionalEvents; - - /** - * It's possible that there are still in-progress operations when a - * a termination operation is issued. In this case, it's important to keep - * the RemoteWorkerControllerChild actor alive until all pending operations - * have completed before destroying it with Send__delete__(). - * - * RAIIActorPtrHolder holds a singular, owning reference to a - * RemoteWorkerControllerChild actor and is responsible for destroying the - * actor in its (i.e. the holder's) destructor. This implies that all - * in-progress operations must maintain a strong reference to their - * corresponding holders and release the reference once completed/canceled. - * - * Additionally a RAIIActorPtrHolder must be initialized with a non-null actor - * and cannot be moved or copied. Therefore, the identities of two held - * actors can be compared by simply comparing their holders' addresses. - */ - class RAIIActorPtrHolder final { - public: - NS_INLINE_DECL_REFCOUNTING(RAIIActorPtrHolder) - - explicit RAIIActorPtrHolder( - already_AddRefed aActor); - - RAIIActorPtrHolder(const RAIIActorPtrHolder& aOther) = delete; - RAIIActorPtrHolder& operator=(const RAIIActorPtrHolder& aOther) = delete; - - RAIIActorPtrHolder(RAIIActorPtrHolder&& aOther) = delete; - RAIIActorPtrHolder& operator=(RAIIActorPtrHolder&& aOther) = delete; - - RemoteWorkerControllerChild* operator->() const - MOZ_NO_ADDREF_RELEASE_ON_RETURN; - - RemoteWorkerControllerChild* get() const; - - RefPtr OnDestructor(); - - private: - ~RAIIActorPtrHolder(); - - MozPromiseHolder mDestructorPromiseHolder; - - const RefPtr mActor; - }; - - RefPtr mControllerChild; - - RefPtr mOuter; - - RemoteWorkerData mRemoteWorkerData; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_serviceworkerprivateimpl_h__ diff --git a/dom/serviceworkers/ServiceWorkerRegistration.cpp b/dom/serviceworkers/ServiceWorkerRegistration.cpp index 6ce9dbd34beb..9192d5ebb0b0 100644 --- a/dom/serviceworkers/ServiceWorkerRegistration.cpp +++ b/dom/serviceworkers/ServiceWorkerRegistration.cpp @@ -12,7 +12,6 @@ #include "mozilla/dom/PushManager.h" #include "mozilla/dom/ServiceWorker.h" #include "mozilla/dom/ServiceWorkerRegistrationBinding.h" -#include "mozilla/dom/ServiceWorkerUtils.h" #include "mozilla/dom/WorkerPrivate.h" #include "nsCycleCollectionParticipant.h" #include "nsISupportsPrimitives.h" @@ -200,41 +199,6 @@ already_AddRefed ServiceWorkerRegistration::Update(ErrorResult& aRv) { return nullptr; } - /** - * `ServiceWorker` objects are not exposed on worker threads yet, so calling - * `ServiceWorkerRegistration::Get{Installing,Waiting,Active}` won't work. - */ - const bool hasNewestWorker = mDescriptor.GetInstalling() || - mDescriptor.GetWaiting() || - mDescriptor.GetActive(); - - /** - * If newestWorker is null, return a promise rejected with an - * "InvalidStateError" DOMException and abort these steps. - */ - if (!hasNewestWorker) { - outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return outer.forget(); - } - - /** - * If the context object’s relevant settings object’s global object - * globalObject is a ServiceWorkerGlobalScope object, and globalObject’s - * associated service worker's state is "installing", return a promise - * rejected with an "InvalidStateError" DOMException and abort these steps. - */ - if (!NS_IsMainThread()) { - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - - if (workerPrivate->IsServiceWorker() && - (workerPrivate->GetServiceWorkerDescriptor().State() == - ServiceWorkerState::Installing)) { - outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return outer.forget(); - } - } - RefPtr self = this; mInner->Update( diff --git a/dom/serviceworkers/ServiceWorkerRegistrationChild.cpp b/dom/serviceworkers/ServiceWorkerRegistrationChild.cpp index 66eaa3662497..0ef4444905cf 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationChild.cpp +++ b/dom/serviceworkers/ServiceWorkerRegistrationChild.cpp @@ -7,7 +7,6 @@ #include "ServiceWorkerRegistrationChild.h" #include "RemoteServiceWorkerRegistrationImpl.h" -#include "mozilla/dom/WorkerRef.h" namespace mozilla { namespace dom { diff --git a/dom/serviceworkers/ServiceWorkerRegistrationInfo.cpp b/dom/serviceworkers/ServiceWorkerRegistrationInfo.cpp index 635c1e50214c..ba031b46e5f4 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationInfo.cpp +++ b/dom/serviceworkers/ServiceWorkerRegistrationInfo.cpp @@ -294,20 +294,16 @@ ServiceWorkerRegistrationInfo::GetServiceWorkerInfoById(uint64_t aId) { return serviceWorker.forget(); } -void ServiceWorkerRegistrationInfo::TryToActivateAsync( - TryToActivateCallback&& aCallback) { +void ServiceWorkerRegistrationInfo::TryToActivateAsync() { MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread( - NewRunnableMethod>( - "ServiceWorkerRegistrationInfo::TryToActivate", this, - &ServiceWorkerRegistrationInfo::TryToActivate, - std::move(aCallback)))); + NewRunnableMethod("ServiceWorkerRegistrationInfo::TryToActivate", this, + &ServiceWorkerRegistrationInfo::TryToActivate))); } /* * TryToActivate should not be called directly, use TryToActivateAsync instead. */ -void ServiceWorkerRegistrationInfo::TryToActivate( - TryToActivateCallback&& aCallback) { +void ServiceWorkerRegistrationInfo::TryToActivate() { MOZ_ASSERT(NS_IsMainThread()); bool controlling = IsControllingClients(); bool skipWaiting = mWaitingWorker && mWaitingWorker->SkipWaitingFlag(); @@ -315,10 +311,6 @@ void ServiceWorkerRegistrationInfo::TryToActivate( if (idle && (!controlling || skipWaiting)) { Activate(); } - - if (aCallback) { - aCallback(); - } } void ServiceWorkerRegistrationInfo::Activate() { @@ -709,14 +701,8 @@ uint64_t ServiceWorkerRegistrationInfo::Version() const { return mDescriptor.Version(); } -uint32_t ServiceWorkerRegistrationInfo::GetUpdateDelay( - const bool aWithMultiplier) { +uint32_t ServiceWorkerRegistrationInfo::GetUpdateDelay() { uint32_t delay = Preferences::GetInt("dom.serviceWorkers.update_delay", 1000); - - if (!aWithMultiplier) { - return delay; - } - // 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)) { diff --git a/dom/serviceworkers/ServiceWorkerRegistrationInfo.h b/dom/serviceworkers/ServiceWorkerRegistrationInfo.h index d30cf41bbafa..378b26de7219 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationInfo.h +++ b/dom/serviceworkers/ServiceWorkerRegistrationInfo.h @@ -7,8 +7,6 @@ #ifndef mozilla_dom_serviceworkerregistrationinfo_h #define mozilla_dom_serviceworkerregistrationinfo_h -#include - #include "mozilla/dom/ServiceWorkerInfo.h" #include "mozilla/dom/ServiceWorkerRegistrationBinding.h" #include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h" @@ -70,8 +68,6 @@ class ServiceWorkerRegistrationInfo final NS_DECL_ISUPPORTS NS_DECL_NSISERVICEWORKERREGISTRATIONINFO - typedef std::function TryToActivateCallback; - ServiceWorkerRegistrationInfo(const nsACString& aScope, nsIPrincipal* aPrincipal, ServiceWorkerUpdateViaCache aUpdateViaCache); @@ -124,9 +120,9 @@ class ServiceWorkerRegistrationInfo final bool IsCorrupt() const; - void TryToActivateAsync(TryToActivateCallback&& aCallback = nullptr); + void TryToActivateAsync(); - void TryToActivate(TryToActivateCallback&& aCallback); + void TryToActivate(); void Activate(); @@ -201,7 +197,7 @@ class ServiceWorkerRegistrationInfo final uint64_t Version() const; - uint32_t GetUpdateDelay(const bool aWithMultiplier = true); + uint32_t GetUpdateDelay(); void FireUpdateFound(); diff --git a/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp b/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp index 10e50fcba479..531c82c06f26 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp +++ b/dom/serviceworkers/ServiceWorkerRegistrationProxy.cpp @@ -31,9 +31,6 @@ class ServiceWorkerRegistrationProxy::DelayedUpdate final DelayedUpdate(RefPtr&& aProxy, RefPtr&& aPromise, uint32_t delay); - - void ChainTo(RefPtr aPromise); - void Reject(); }; @@ -267,15 +264,6 @@ ServiceWorkerRegistrationProxy::DelayedUpdate::DelayedUpdate( MOZ_DIAGNOSTIC_ASSERT(mTimer); } -void ServiceWorkerRegistrationProxy::DelayedUpdate::ChainTo( - RefPtr aPromise) { - AssertIsOnMainThread(); - MOZ_ASSERT(mProxy->mDelayedUpdate == this); - MOZ_ASSERT(mPromise); - - mPromise->ChainTo(aPromise.forget(), __func__); -} - void ServiceWorkerRegistrationProxy::DelayedUpdate::Reject() { MOZ_DIAGNOSTIC_ASSERT(mPromise); if (mTimer) { @@ -287,13 +275,9 @@ void ServiceWorkerRegistrationProxy::DelayedUpdate::Reject() { NS_IMETHODIMP ServiceWorkerRegistrationProxy::DelayedUpdate::Notify(nsITimer* aTimer) { - // Already shutting down. - if (mProxy->mDelayedUpdate != this) { - return NS_OK; - } - auto scopeExit = MakeScopeExit( [&] { mPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__); }); + MOZ_DIAGNOSTIC_ASSERT((mProxy->mDelayedUpdate == this)); NS_ENSURE_TRUE(mProxy->mReg, NS_ERROR_FAILURE); @@ -325,21 +309,14 @@ ServiceWorkerRegistrationProxy::Update() { // Get the delay value for the update NS_ENSURE_TRUE_VOID(self->mReg); - uint32_t delay = self->mReg->GetUpdateDelay(false); + uint32_t delay = self->mReg->GetUpdateDelay(); // If the delay value does not equal to 0, create a timer and a timer // callback to perform the delayed update. Otherwise, update directly. if (delay) { - if (self->mDelayedUpdate) { - // NOTE: if we `ChainTo(),` there will ultimately be a single - // update, and this update will resolve all promises that were - // issued while the update's timer was ticking down. - self->mDelayedUpdate->ChainTo(std::move(promise)); - } else { - RefPtr du = - new ServiceWorkerRegistrationProxy::DelayedUpdate( - std::move(self), std::move(promise), delay); - } + RefPtr du = + new ServiceWorkerRegistrationProxy::DelayedUpdate( + std::move(self), std::move(promise), delay); } else { RefPtr swm = ServiceWorkerManager::GetInstance(); diff --git a/dom/serviceworkers/ServiceWorkerShutdownBlocker.cpp b/dom/serviceworkers/ServiceWorkerShutdownBlocker.cpp deleted file mode 100644 index 534f83094200..000000000000 --- a/dom/serviceworkers/ServiceWorkerShutdownBlocker.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -*- 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 "ServiceWorkerShutdownBlocker.h" - -#include - -#include "MainThreadUtils.h" -#include "nsDebug.h" -#include "nsError.h" -#include "nsIWritablePropertyBag2.h" -#include "nsThreadUtils.h" - -#include "mozilla/Assertions.h" -#include "mozilla/RefPtr.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_ISUPPORTS(ServiceWorkerShutdownBlocker, nsIAsyncShutdownBlocker) - -NS_IMETHODIMP ServiceWorkerShutdownBlocker::GetName(nsAString& aNameOut) { - aNameOut = NS_LITERAL_STRING( - "ServiceWorkerShutdownBlocker: shutting down Service Workers"); - return NS_OK; -} - -NS_IMETHODIMP -ServiceWorkerShutdownBlocker::BlockShutdown(nsIAsyncShutdownClient* aClient) { - AssertIsOnMainThread(); - MOZ_ASSERT(!mShutdownClient); - - mShutdownClient = aClient; - MaybeUnblockShutdown(); - - return NS_OK; -} - -NS_IMETHODIMP ServiceWorkerShutdownBlocker::GetState(nsIPropertyBag** aBagOut) { - AssertIsOnMainThread(); - MOZ_ASSERT(aBagOut); - - nsCOMPtr propertyBag = - do_CreateInstance("@mozilla.org/hash-property-bag;1"); - - if (NS_WARN_IF(!propertyBag)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - nsresult rv = propertyBag->SetPropertyAsBool( - NS_LITERAL_STRING("acceptingPromises"), IsAcceptingPromises()); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = propertyBag->SetPropertyAsUint32(NS_LITERAL_STRING("pendingPromises"), - GetPendingPromises()); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - propertyBag.forget(aBagOut); - - return NS_OK; -} - -/* static */ already_AddRefed -ServiceWorkerShutdownBlocker::CreateAndRegisterOn( - nsIAsyncShutdownClient* aShutdownBarrier) { - AssertIsOnMainThread(); - MOZ_ASSERT(aShutdownBarrier); - - RefPtr blocker = - new ServiceWorkerShutdownBlocker(); - - nsresult rv = aShutdownBarrier->AddBlocker( - blocker.get(), NS_LITERAL_STRING(__FILE__), __LINE__, - NS_LITERAL_STRING("Service Workers shutdown")); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return nullptr; - } - - return blocker.forget(); -} - -void ServiceWorkerShutdownBlocker::WaitOnPromise( - GenericNonExclusivePromise* aPromise) { - AssertIsOnMainThread(); - MOZ_DIAGNOSTIC_ASSERT(IsAcceptingPromises()); - MOZ_ASSERT(aPromise); - - ++mState.as().mPendingPromises; - - RefPtr self = this; - - aPromise->Then(GetCurrentThreadSerialEventTarget(), __func__, - [self = std::move(self)]( - const GenericNonExclusivePromise::ResolveOrRejectValue&) { - if (!self->PromiseSettled()) { - self->MaybeUnblockShutdown(); - } - }); -} - -void ServiceWorkerShutdownBlocker::StopAcceptingPromises() { - AssertIsOnMainThread(); - MOZ_ASSERT(IsAcceptingPromises()); - - mState = AsVariant(NotAcceptingPromises(mState.as())); -} - -ServiceWorkerShutdownBlocker::ServiceWorkerShutdownBlocker() - : mState(VariantType()) { - AssertIsOnMainThread(); -} - -ServiceWorkerShutdownBlocker::~ServiceWorkerShutdownBlocker() { - MOZ_ASSERT(!IsAcceptingPromises()); - MOZ_ASSERT(!GetPendingPromises()); - MOZ_ASSERT(!mShutdownClient); -} - -void ServiceWorkerShutdownBlocker::MaybeUnblockShutdown() { - AssertIsOnMainThread(); - - if (!mShutdownClient || IsAcceptingPromises() || GetPendingPromises()) { - return; - } - - mShutdownClient->RemoveBlocker(this); - mShutdownClient = nullptr; -} - -uint32_t ServiceWorkerShutdownBlocker::PromiseSettled() { - AssertIsOnMainThread(); - MOZ_ASSERT(GetPendingPromises()); - - if (IsAcceptingPromises()) { - return --mState.as().mPendingPromises; - } - - return --mState.as().mPendingPromises; -} - -bool ServiceWorkerShutdownBlocker::IsAcceptingPromises() const { - AssertIsOnMainThread(); - - return mState.is(); -} - -uint32_t ServiceWorkerShutdownBlocker::GetPendingPromises() const { - AssertIsOnMainThread(); - - if (IsAcceptingPromises()) { - return mState.as().mPendingPromises; - } - - return mState.as().mPendingPromises; -} - -ServiceWorkerShutdownBlocker::NotAcceptingPromises::NotAcceptingPromises( - AcceptingPromises aPreviousState) - : mPendingPromises(aPreviousState.mPendingPromises) { - AssertIsOnMainThread(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/serviceworkers/ServiceWorkerShutdownBlocker.h b/dom/serviceworkers/ServiceWorkerShutdownBlocker.h deleted file mode 100644 index 87373da762e0..000000000000 --- a/dom/serviceworkers/ServiceWorkerShutdownBlocker.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_serviceworkershutdownblocker_h__ -#define mozilla_dom_serviceworkershutdownblocker_h__ - -#include "nsCOMPtr.h" -#include "nsIAsyncShutdown.h" -#include "nsISupportsImpl.h" - -#include "mozilla/MozPromise.h" - -namespace mozilla { -namespace dom { - -/** - * Main thread only. - */ -class ServiceWorkerShutdownBlocker final : public nsIAsyncShutdownBlocker { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIASYNCSHUTDOWNBLOCKER - - /** - * Returns the registered shutdown blocker if registration succeeded and - * nullptr otherwise. - */ - static already_AddRefed CreateAndRegisterOn( - nsIAsyncShutdownClient* aShutdownBarrier); - - /** - * Blocks shutdown until `aPromise` settles. - * - * Can be called multiple times, and shutdown will be blocked until all the - * calls' promises settle, but all of these calls must happen before - * `StopAcceptingPromises()` is called (assertions will enforce this). - */ - void WaitOnPromise(GenericNonExclusivePromise* aPromise); - - /** - * Once this is called, shutdown will be blocked until all promises - * passed to `WaitOnPromise()` settle, and there must be no more calls to - * `WaitOnPromise()` (assertions will enforce this). - */ - void StopAcceptingPromises(); - - private: - ServiceWorkerShutdownBlocker(); - - ~ServiceWorkerShutdownBlocker(); - - /** - * No-op if any of the following are true: - * 1) `BlockShutdown()` hasn't been called yet, or - * 2) `StopAcceptingPromises()` hasn't been called yet, or - * 3) `StopAcceptingPromises()` HAS been called, but there are still pending - * promises. - */ - void MaybeUnblockShutdown(); - - /** - * Returns the remaining pending promise count (i.e. excluding the promise - * that just settled). - */ - uint32_t PromiseSettled(); - - bool IsAcceptingPromises() const; - - uint32_t GetPendingPromises() const; - - struct AcceptingPromises { - uint32_t mPendingPromises = 0; - }; - - struct NotAcceptingPromises { - explicit NotAcceptingPromises(AcceptingPromises aPreviousState); - - uint32_t mPendingPromises = 0; - }; - - Variant mState; - - nsCOMPtr mShutdownClient; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_serviceworkershutdownblocker_h__ diff --git a/dom/serviceworkers/moz.build b/dom/serviceworkers/moz.build index baec0af91091..8a0780f65e99 100644 --- a/dom/serviceworkers/moz.build +++ b/dom/serviceworkers/moz.build @@ -9,13 +9,8 @@ with Files("**"): # Public stuff. EXPORTS.mozilla.dom += [ - 'FetchEventOpChild.h', - 'FetchEventOpParent.h', - 'FetchEventOpProxyChild.h', - 'FetchEventOpProxyParent.h', 'ServiceWorker.h', 'ServiceWorkerActors.h', - 'ServiceWorkerCloneData.h', 'ServiceWorkerContainer.h', 'ServiceWorkerDescriptor.h', 'ServiceWorkerEvents.h', @@ -25,8 +20,6 @@ EXPORTS.mozilla.dom += [ 'ServiceWorkerManager.h', 'ServiceWorkerManagerChild.h', 'ServiceWorkerManagerParent.h', - 'ServiceWorkerOp.h', - 'ServiceWorkerOpPromise.h', 'ServiceWorkerRegistrar.h', 'ServiceWorkerRegistration.h', 'ServiceWorkerRegistrationDescriptor.h', @@ -35,10 +28,6 @@ EXPORTS.mozilla.dom += [ ] UNIFIED_SOURCES += [ - 'FetchEventOpChild.cpp', - 'FetchEventOpParent.cpp', - 'FetchEventOpProxyChild.cpp', - 'FetchEventOpProxyParent.cpp', 'RemoteServiceWorkerContainerImpl.cpp', 'RemoteServiceWorkerImpl.cpp', 'RemoteServiceWorkerRegistrationImpl.cpp', @@ -62,10 +51,8 @@ UNIFIED_SOURCES += [ 'ServiceWorkerManagerChild.cpp', 'ServiceWorkerManagerParent.cpp', 'ServiceWorkerManagerService.cpp', - 'ServiceWorkerOp.cpp', 'ServiceWorkerParent.cpp', 'ServiceWorkerPrivate.cpp', - 'ServiceWorkerPrivateImpl.cpp', 'ServiceWorkerProxy.cpp', 'ServiceWorkerRegisterJob.cpp', 'ServiceWorkerRegistrar.cpp', @@ -77,7 +64,6 @@ UNIFIED_SOURCES += [ 'ServiceWorkerRegistrationParent.cpp', 'ServiceWorkerRegistrationProxy.cpp', 'ServiceWorkerScriptCache.cpp', - 'ServiceWorkerShutdownBlocker.cpp', 'ServiceWorkerUnregisterCallback.cpp', 'ServiceWorkerUnregisterJob.cpp', 'ServiceWorkerUpdateJob.cpp', @@ -89,14 +75,11 @@ UNIFIED_SOURCES += [ IPDL_SOURCES += [ 'IPCServiceWorkerDescriptor.ipdlh', 'IPCServiceWorkerRegistrationDescriptor.ipdlh', - 'PFetchEventOp.ipdl', - 'PFetchEventOpProxy.ipdl', 'PServiceWorker.ipdl', 'PServiceWorkerContainer.ipdl', 'PServiceWorkerManager.ipdl', 'PServiceWorkerRegistration.ipdl', 'PServiceWorkerUpdater.ipdl', - 'ServiceWorkerOpArgs.ipdlh', 'ServiceWorkerRegistrarTypes.ipdlh', ] @@ -105,7 +88,6 @@ include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ - '/extensions/permissions', '/js/xpconnect/loader', ] diff --git a/dom/workers/WorkerError.cpp b/dom/workers/WorkerError.cpp index b51d8cdc49f0..431970298389 100644 --- a/dom/workers/WorkerError.cpp +++ b/dom/workers/WorkerError.cpp @@ -11,7 +11,6 @@ #include "mozilla/dom/ErrorEventBinding.h" #include "mozilla/dom/RemoteWorkerChild.h" #include "mozilla/dom/ServiceWorkerManager.h" -#include "mozilla/dom/ServiceWorkerUtils.h" #include "mozilla/dom/SimpleGlobalObject.h" #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h" #include "mozilla/dom/WorkerGlobalScopeBinding.h" @@ -81,28 +80,15 @@ class ReportErrorRunnable final : public WorkerDebuggeeRunnable { // worker error reporting will crash. Instead, pass the error to // the ServiceWorkerManager to report on any controlled documents. if (aWorkerPrivate->IsServiceWorker()) { - if (ServiceWorkerParentInterceptEnabled()) { - RefPtr actor( - aWorkerPrivate->GetRemoteWorkerControllerWeakRef()); - - Unused << NS_WARN_IF(!actor); - - if (actor) { - actor->ErrorPropagationOnMainThread(nullptr, false); - } - - } else { - RefPtr swm = - ServiceWorkerManager::GetInstance(); - if (swm) { - swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(), - aWorkerPrivate->ServiceWorkerScope(), - aWorkerPrivate->ScriptURL(), EmptyString(), - EmptyString(), EmptyString(), 0, 0, JSREPORT_ERROR, - JSEXN_ERR); - } + RefPtr swm = ServiceWorkerManager::GetInstance(); + if (swm) { + swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(), + aWorkerPrivate->ServiceWorkerScope(), + aWorkerPrivate->ScriptURL(), mReport->mMessage, + mReport->mFilename, mReport->mLine, + mReport->mLineNumber, mReport->mColumnNumber, + mReport->mFlags, mReport->mExnType); } - return true; } @@ -173,27 +159,14 @@ class ReportGenericErrorRunnable final : public WorkerDebuggeeRunnable { } if (aWorkerPrivate->IsServiceWorker()) { - if (ServiceWorkerParentInterceptEnabled()) { - RefPtr actor( - aWorkerPrivate->GetRemoteWorkerControllerWeakRef()); - - Unused << NS_WARN_IF(!actor); - - if (actor) { - actor->ErrorPropagationOnMainThread(nullptr, false); - } - - } else { - RefPtr swm = ServiceWorkerManager::GetInstance(); - if (swm) { - swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(), - aWorkerPrivate->ServiceWorkerScope(), - aWorkerPrivate->ScriptURL(), EmptyString(), - EmptyString(), EmptyString(), 0, 0, JSREPORT_ERROR, - JSEXN_ERR); - } + RefPtr swm = ServiceWorkerManager::GetInstance(); + if (swm) { + swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(), + aWorkerPrivate->ServiceWorkerScope(), + aWorkerPrivate->ScriptURL(), EmptyString(), + EmptyString(), EmptyString(), 0, 0, JSREPORT_ERROR, + JSEXN_ERR); } - return true; } diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index efeaf833ea7d..8db98a591592 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -36,7 +36,6 @@ #include "mozilla/dom/PerformanceStorageWorker.h" #include "mozilla/dom/PromiseDebugging.h" #include "mozilla/dom/RemoteWorkerChild.h" -#include "mozilla/dom/RemoteWorkerService.h" #include "mozilla/dom/TimeoutHandler.h" #include "mozilla/dom/WorkerBinding.h" #include "mozilla/StorageAccess.h" @@ -54,7 +53,6 @@ #include "nsIURI.h" #include "nsIURL.h" #include "nsPrintfCString.h" -#include "nsProxyRelease.h" #include "nsQueryObject.h" #include "nsRFPService.h" #include "nsSandboxFlags.h" @@ -4848,40 +4846,6 @@ RemoteWorkerChild* WorkerPrivate::GetRemoteWorkerController() { return mRemoteWorkerController; } -void WorkerPrivate::SetRemoteWorkerControllerWeakRef( - ThreadSafeWeakPtr aWeakRef) { - MOZ_ASSERT(aWeakRef); - MOZ_ASSERT(!mRemoteWorkerControllerWeakRef); - MOZ_ASSERT(IsServiceWorker()); - - mRemoteWorkerControllerWeakRef = std::move(aWeakRef); -} - -ThreadSafeWeakPtr -WorkerPrivate::GetRemoteWorkerControllerWeakRef() { - MOZ_ASSERT(IsServiceWorker()); - return mRemoteWorkerControllerWeakRef; -} - -RefPtr WorkerPrivate::SetServiceWorkerSkipWaitingFlag() { - AssertIsOnWorkerThread(); - MOZ_ASSERT(IsServiceWorker()); - - RefPtr rwc(mRemoteWorkerControllerWeakRef); - - if (!rwc) { - return GenericPromise::CreateAndReject(NS_ERROR_DOM_ABORT_ERR, __func__); - } - - RefPtr promise = - rwc->MaybeSendSetServiceWorkerSkipWaitingFlag(); - - NS_ProxyRelease("WorkerPrivate::mRemoteWorkerControllerWeakRef", - RemoteWorkerService::Thread(), rwc.forget()); - - return promise; -} - nsAString& WorkerPrivate::Id() { AssertIsOnMainThread(); diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 3e6bd9f0c9ef..cc930bdecb0d 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -12,17 +12,14 @@ #include "mozilla/Attributes.h" #include "mozilla/CondVar.h" #include "mozilla/DOMEventTargetHelper.h" -#include "mozilla/MozPromise.h" #include "mozilla/RelativeTimeline.h" #include "mozilla/StorageAccess.h" -#include "mozilla/ThreadSafeWeakPtr.h" #include "nsContentUtils.h" #include "nsIContentSecurityPolicy.h" #include "nsIEventTarget.h" #include "nsTObserverArray.h" #include "js/ContextOptions.h" -#include "mozilla/dom/RemoteWorkerChild.h" #include "mozilla/dom/Worker.h" #include "mozilla/dom/WorkerLoadInfo.h" #include "mozilla/dom/workerinternals/JSSettings.h" @@ -46,6 +43,7 @@ class Function; class MessagePort; class MessagePortIdentifier; class PerformanceStorage; +class RemoteWorkerChild; class TimeoutHandler; class WorkerControlRunnable; class WorkerCSPEventListener; @@ -791,13 +789,6 @@ class WorkerPrivate : public RelativeTimeline { void SetRemoteWorkerController(RemoteWorkerChild* aController); - void SetRemoteWorkerControllerWeakRef( - ThreadSafeWeakPtr aWeakRef); - - ThreadSafeWeakPtr GetRemoteWorkerControllerWeakRef(); - - RefPtr SetServiceWorkerSkipWaitingFlag(); - // We can assume that an nsPIDOMWindow will be available for Freeze, Thaw // as these are only used for globals going in and out of the bfcache. bool Freeze(nsPIDOMWindowInner* aWindow); @@ -1074,9 +1065,6 @@ class WorkerPrivate : public RelativeTimeline { // Only touched on the parent thread. This is set only if IsSharedWorker(). RefPtr mRemoteWorkerController; - // This is set only if IsServiceWorker(). - ThreadSafeWeakPtr mRemoteWorkerControllerWeakRef; - JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init TimeStamp mKillTime; WorkerStatus mParentStatus; diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index c388be3ad598..fb1baad8e901 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -25,7 +25,6 @@ #include "mozilla/dom/Promise.h" #include "mozilla/dom/PromiseWorkerProxy.h" #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" -#include "mozilla/dom/ServiceWorkerUtils.h" #include "mozilla/dom/SharedWorkerGlobalScopeBinding.h" #include "mozilla/dom/SimpleGlobalObject.h" #include "mozilla/dom/TimeoutHandler.h" @@ -859,21 +858,6 @@ already_AddRefed ServiceWorkerGlobalScope::SkipWaiting( return nullptr; } - if (ServiceWorkerParentInterceptEnabled()) { - mWorkerPrivate->SetServiceWorkerSkipWaitingFlag()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [promise](bool aOk) { - Unused << NS_WARN_IF(!aOk); - promise->MaybeResolveWithUndefined(); - }, - [promise](nsresult aRv) { - MOZ_ASSERT(NS_FAILED(aRv)); - promise->MaybeResolveWithUndefined(); - }); - - return promise.forget(); - } - RefPtr promiseProxy = PromiseWorkerProxy::Create(mWorkerPrivate, promise); if (!promiseProxy) { diff --git a/dom/workers/moz.build b/dom/workers/moz.build index d546701fdf34..0587d7ab639e 100644 --- a/dom/workers/moz.build +++ b/dom/workers/moz.build @@ -71,7 +71,6 @@ LOCAL_INCLUDES += [ '/dom/base', '/dom/bindings', '/dom/system', - '/dom/workers/remoteworkers', '/js/xpconnect/loader', '/netwerk/base', '/xpcom/build', diff --git a/dom/workers/remoteworkers/PRemoteWorker.ipdl b/dom/workers/remoteworkers/PRemoteWorker.ipdl index 3b38a523c630..19450334ba62 100644 --- a/dom/workers/remoteworkers/PRemoteWorker.ipdl +++ b/dom/workers/remoteworkers/PRemoteWorker.ipdl @@ -3,10 +3,8 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PBackground; -include protocol PFetchEventOpProxy; include DOMTypes; -include ServiceWorkerOpArgs; include RemoteWorkerTypes; namespace mozilla { @@ -60,8 +58,6 @@ protocol PRemoteWorker { manager PBackground; - manages PFetchEventOpProxy; - parent: async Created(bool aStatus); @@ -69,17 +65,10 @@ parent: async Close(); - async SetServiceWorkerSkipWaitingFlag() returns (bool aOk); - child: - async PFetchEventOpProxy(ServiceWorkerFetchEventOpArgs aArgs); - async __delete__(); async ExecOp(RemoteWorkerOp op); - - async ExecServiceWorkerOp(ServiceWorkerOpArgs aArgs) - returns (ServiceWorkerOpResult aResult); }; } // namespace dom diff --git a/dom/workers/remoteworkers/PRemoteWorkerController.ipdl b/dom/workers/remoteworkers/PRemoteWorkerController.ipdl deleted file mode 100644 index 7deae7c8e1c0..000000000000 --- a/dom/workers/remoteworkers/PRemoteWorkerController.ipdl +++ /dev/null @@ -1,42 +0,0 @@ -/* 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 protocol PBackground; -include protocol PFetchEventOp; - -include RemoteWorkerTypes; -include ServiceWorkerOpArgs; - -namespace mozilla { -namespace dom { - -protocol PRemoteWorkerController { - manager PBackground; - - manages PFetchEventOp; - - child: - async CreationFailed(); - - async CreationSucceeded(); - - async ErrorReceived(ErrorValue aError); - - async Terminated(); - - async SetServiceWorkerSkipWaitingFlag() returns (bool aOk); - - parent: - async PFetchEventOp(ServiceWorkerFetchEventOpArgs aArgs); - - async __delete__(); - - async Shutdown() returns (bool aOk); - - async ExecServiceWorkerOp(ServiceWorkerOpArgs aArgs) - returns (ServiceWorkerOpResult aResult); -}; - -} // namespace dom -} // namespace mozilla diff --git a/dom/workers/remoteworkers/RemoteWorkerChild.cpp b/dom/workers/remoteworkers/RemoteWorkerChild.cpp index 7971b64b2db9..319db6b4a328 100644 --- a/dom/workers/remoteworkers/RemoteWorkerChild.cpp +++ b/dom/workers/remoteworkers/RemoteWorkerChild.cpp @@ -5,37 +5,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "RemoteWorkerChild.h" - -#include - -#include "MainThreadUtils.h" -#include "nsDebug.h" -#include "nsError.h" -#include "nsIConsoleReportCollector.h" -#include "nsIInterfaceRequestor.h" -#include "nsIPrincipal.h" -#include "nsIPermissionManager.h" -#include "nsNetUtil.h" -#include "nsProxyRelease.h" -#include "nsThreadUtils.h" -#include "nsXULAppAPI.h" - #include "RemoteWorkerService.h" -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" -#include "mozilla/BasePrincipal.h" -#include "mozilla/ErrorResult.h" -#include "mozilla/Services.h" -#include "mozilla/ScopeExit.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/FetchEventOpProxyChild.h" #include "mozilla/dom/IndexedDatabaseManager.h" #include "mozilla/dom/MessagePort.h" #include "mozilla/dom/RemoteWorkerTypes.h" -#include "mozilla/dom/ServiceWorkerDescriptor.h" #include "mozilla/dom/ServiceWorkerInterceptController.h" -#include "mozilla/dom/ServiceWorkerOp.h" -#include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h" #include "mozilla/dom/ServiceWorkerUtils.h" #include "mozilla/dom/workerinternals/ScriptLoader.h" #include "mozilla/dom/WorkerError.h" @@ -45,6 +19,10 @@ #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/net/CookieSettings.h" +#include "nsIConsoleReportCollector.h" +#include "nsIPrincipal.h" +#include "nsNetUtil.h" +#include "nsProxyRelease.h" namespace mozilla { @@ -93,53 +71,14 @@ NS_IMPL_ADDREF(SharedWorkerInterfaceRequestor) NS_IMPL_RELEASE(SharedWorkerInterfaceRequestor) NS_IMPL_QUERY_INTERFACE(SharedWorkerInterfaceRequestor, nsIInterfaceRequestor) -class SelfHolder { - public: - MOZ_IMPLICIT SelfHolder(RemoteWorkerChild* aSelf) : mSelf(aSelf) { - MOZ_ASSERT(mSelf); - } - - SelfHolder(const SelfHolder&) = default; - - SelfHolder& operator=(const SelfHolder&) = default; - - SelfHolder(SelfHolder&&) = default; - - SelfHolder& operator=(SelfHolder&&) = default; - - ~SelfHolder() { - if (!mSelf) { - return; - } - - nsCOMPtr target = mSelf->GetOwningEventTarget(); - NS_ProxyRelease("SelfHolder::mSelf", target, mSelf.forget()); - } - - RemoteWorkerChild* get() const { - MOZ_ASSERT(mSelf); - - return mSelf.get(); - } - - RemoteWorkerChild* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { - return get(); - } - - bool operator!() { return !mSelf.get(); } - - private: - RefPtr mSelf; -}; - // Normal runnable because AddPortIdentifier() is going to exec JS code. class MessagePortIdentifierRunnable final : public WorkerRunnable { public: MessagePortIdentifierRunnable(WorkerPrivate* aWorkerPrivate, - SelfHolder aActor, + RemoteWorkerChild* aActor, const MessagePortIdentifier& aPortIdentifier) : WorkerRunnable(aWorkerPrivate), - mActor(std::move(aActor)), + mActor(aActor), mPortIdentifier(aPortIdentifier) {} private: @@ -175,158 +114,77 @@ class MessagePortIdentifierRunnable final : public WorkerRunnable { return; } - SelfHolder mActor; + RefPtr mActor; MessagePortIdentifier mPortIdentifier; }; -class ReleaseWorkerRunnable final : public WorkerRunnable { - public: - ReleaseWorkerRunnable(RefPtr aWorkerPrivate, - already_AddRefed aWeakRef) - : WorkerRunnable(aWorkerPrivate), - mWorkerPrivate(std::move(aWorkerPrivate)), - mWeakRef(aWeakRef) {} - - private: - bool WorkerRun(JSContext*, WorkerPrivate*) override { - mWeakRef = nullptr; - mWorkerPrivate = nullptr; - - return true; - } - - nsresult Cancel() override { - mWeakRef = nullptr; - mWorkerPrivate = nullptr; - - return NS_OK; - } - - RefPtr mWorkerPrivate; - RefPtr mWeakRef; -}; - -} // anonymous namespace +} // namespace class RemoteWorkerChild::InitializeWorkerRunnable final : public WorkerRunnable { public: - InitializeWorkerRunnable(RefPtr aWorkerPrivate, - SelfHolder aActor) - : WorkerRunnable(aWorkerPrivate), - mWorkerPrivate(std::move(aWorkerPrivate)), - mActor(std::move(aActor)) { - MOZ_ASSERT(mWorkerPrivate); - MOZ_ASSERT(mActor); - } + InitializeWorkerRunnable(WorkerPrivate* aWorkerPrivate, + RemoteWorkerChild* aActor) + : WorkerRunnable(aWorkerPrivate), mActor(aActor) {} private: - ~InitializeWorkerRunnable() { MaybeAbort(); } - - bool WorkerRun(JSContext*, WorkerPrivate*) override { - mActor->InitializeOnWorker(mWorkerPrivate.forget()); + virtual bool WorkerRun(JSContext* aCx, + WorkerPrivate* aWorkerPrivate) override { + mActor->InitializeOnWorker(aWorkerPrivate); return true; } nsresult Cancel() override { - MaybeAbort(); - + mActor->CreationFailedOnAnyThread(); + mActor->ShutdownOnWorker(); return WorkerRunnable::Cancel(); } - // Slowly running out of synonyms for cancel, abort, terminate, etc... - void MaybeAbort() { - if (!mWorkerPrivate) { - return; - } - - nsCOMPtr target = - SystemGroup::EventTargetFor(TaskCategory::Other); - NS_ProxyRelease("InitializeWorkerRunnable::mWorkerPrivate", target, - mWorkerPrivate.forget()); - - mActor->TransitionStateToTerminated(); - mActor->CreationFailedOnAnyThread(); - mActor->ShutdownOnWorker(); - } - - RefPtr mWorkerPrivate; - SelfHolder mActor; + RefPtr mActor; }; -RemoteWorkerChild::RemoteWorkerChild(const RemoteWorkerData& aData) - : mState(VariantType(), "RemoteWorkerChild::mState"), - mIsServiceWorker(aData.serviceWorkerData().type() == - OptionalServiceWorkerData::TServiceWorkerData), - mOwningEventTarget(GetCurrentThreadSerialEventTarget()) { +RemoteWorkerChild::RemoteWorkerChild() + : mIPCActive(true), mSharedData("RemoteWorkerChild::mSharedData") { MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); - MOZ_ASSERT(mOwningEventTarget); } +RemoteWorkerChild::SharedData::SharedData() : mWorkerState(ePending) {} + RemoteWorkerChild::~RemoteWorkerChild() { -#ifdef DEBUG - MOZ_ASSERT(mTerminationPromise.IsEmpty()); - auto lock = mState.Lock(); - MOZ_ASSERT(lock->is()); -#endif + nsCOMPtr target = + SystemGroup::EventTargetFor(TaskCategory::Other); + + const auto lock = mSharedData.Lock(); + NS_ProxyRelease("RemoteWorkerChild::mWorkerPrivate", target, + lock->mWorkerPrivate.forget()); } -nsISerialEventTarget* RemoteWorkerChild::GetOwningEventTarget() const { - return mOwningEventTarget; -} - -void RemoteWorkerChild::ActorDestroy(ActorDestroyReason) { - Unused << NS_WARN_IF(!mTerminationPromise.IsEmpty()); - mTerminationPromise.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__); - - MOZ_ACCESS_THREAD_BOUND(mLauncherData, launcherData); - launcherData->mIPCActive = false; - - auto lock = mState.Lock(); - - Unused << NS_WARN_IF(!lock->is()); - - if (NS_WARN_IF(lock->is())) { - nsCOMPtr r = NS_NewRunnableFunction( - __func__, - [workerPrivate = std::move(lock->as().mWorkerPrivate), - workerRef = std::move(lock->as().mWorkerRef)]() mutable { - RefPtr r = - new ReleaseWorkerRunnable(workerPrivate, workerRef.forget()); - - Unused << NS_WARN_IF(!r->Dispatch()); - - workerPrivate->Cancel(); - }); - - MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget())); - } - - *lock = VariantType(); +void RemoteWorkerChild::ActorDestroy(ActorDestroyReason aWhy) { + MOZ_ACCESS_THREAD_BOUND(mLauncherData, data); + mIPCActive = false; + data->mPendingOps.Clear(); } void RemoteWorkerChild::ExecWorker(const RemoteWorkerData& aData) { -#ifdef DEBUG - MOZ_ASSERT(GetOwningEventTarget()->IsOnCurrentThread()); - MOZ_ACCESS_THREAD_BOUND(mLauncherData, launcherData); - MOZ_ASSERT(launcherData->mIPCActive); -#endif - - SelfHolder self = this; - - nsCOMPtr r = NS_NewRunnableFunction( - __func__, [self = std::move(self), data = aData]() mutable { - nsresult rv = self->ExecWorkerOnMainThread(std::move(data)); + MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); + MOZ_ASSERT(mIPCActive); + RefPtr self = this; + nsCOMPtr r = + NS_NewRunnableFunction("RemoteWorkerChild::ExecWorker", [self, aData]() { + nsresult rv = self->ExecWorkerOnMainThread(aData); if (NS_WARN_IF(NS_FAILED(rv))) { self->CreationFailedOnAnyThread(); } }); - MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget())); + nsCOMPtr target = + SystemGroup::EventTargetFor(TaskCategory::Other); + target->Dispatch(r.forget(), NS_DISPATCH_NORMAL); } -nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) { +nsresult RemoteWorkerChild::ExecWorkerOnMainThread( + const RemoteWorkerData& aData) { MOZ_ASSERT(NS_IsMainThread()); // Ensure that the IndexedDatabaseManager is initialized @@ -334,8 +192,6 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) { nsresult rv = NS_OK; - auto scopeExit = MakeScopeExit([&] { TransitionStateToTerminated(); }); - nsCOMPtr principal = PrincipalInfoToPrincipal(aData.principalInfo(), &rv); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -408,213 +264,98 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) { return rv; } - if (mIsServiceWorker) { - ServiceWorkerData& data = aData.serviceWorkerData().get_ServiceWorkerData(); - - nsCOMPtr permissionManager = - services::GetPermissionManager(); - - for (auto& keyAndPermissions : data.permissionsByKey()) { - permissionManager->SetPermissionsWithKey(keyAndPermissions.key(), - keyAndPermissions.permissions()); - } - - info.mServiceWorkerCacheName = data.cacheName(); - info.mServiceWorkerDescriptor.emplace(data.descriptor()); - info.mServiceWorkerRegistrationDescriptor.emplace( - data.registrationDescriptor()); - info.mLoadFlags = static_cast(data.loadFlags()); - } else { - // Top level workers' main script use the document charset for the script - // uri encoding. - rv = ChannelFromScriptURLMainThread( - info.mLoadingPrincipal, nullptr /* parent document */, info.mLoadGroup, - info.mResolvedScriptURI, clientInfo, - nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER, info.mCookieSettings, - info.mReferrerInfo, getter_AddRefs(info.mChannel)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } + // Top level workers' main script use the document charset for the script + // uri encoding. + rv = ChannelFromScriptURLMainThread( + info.mLoadingPrincipal, nullptr /* parent document */, info.mLoadGroup, + info.mResolvedScriptURI, clientInfo, + aData.isSharedWorker() ? nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER + : nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER, + info.mCookieSettings, info.mReferrerInfo, getter_AddRefs(info.mChannel)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; } AutoJSAPI jsapi; jsapi.Init(); ErrorResult error; - RefPtr workerPrivate = WorkerPrivate::Constructor( + const auto lock = mSharedData.Lock(); + lock->mWorkerPrivate = WorkerPrivate::Constructor( jsapi.cx(), aData.originalScriptURL(), false, - mIsServiceWorker ? WorkerTypeService : WorkerTypeShared, aData.name(), - VoidCString(), &info, error); - + aData.isSharedWorker() ? WorkerTypeShared : WorkerTypeService, + aData.name(), VoidCString(), &info, error); if (NS_WARN_IF(error.Failed())) { - MOZ_ASSERT(!workerPrivate); - - rv = error.StealNSResult(); - return rv; - } - - if (mIsServiceWorker) { - RefPtr self = this; - workerPrivate->SetRemoteWorkerControllerWeakRef( - ThreadSafeWeakPtr(self)); - } else { - workerPrivate->SetRemoteWorkerController(this); + return error.StealNSResult(); } RefPtr runnable = - new InitializeWorkerRunnable(std::move(workerPrivate), SelfHolder(this)); - + new InitializeWorkerRunnable(lock->mWorkerPrivate, this); if (NS_WARN_IF(!runnable->Dispatch())) { - rv = NS_ERROR_FAILURE; - return rv; + return NS_ERROR_FAILURE; } - scopeExit.release(); - + lock->mWorkerPrivate->SetRemoteWorkerController(this); return NS_OK; } -void RemoteWorkerChild::InitializeOnWorker( - already_AddRefed aWorkerPrivate) { - { - auto lock = mState.Lock(); - - if (lock->is()) { - nsCOMPtr target = - SystemGroup::EventTargetFor(TaskCategory::Other); - NS_ProxyRelease(__func__, target, std::move(aWorkerPrivate)); - - TransitionStateToTerminated(lock.ref()); - ShutdownOnWorker(); - return; - } - } - - RefPtr workerPrivate = aWorkerPrivate; - MOZ_ASSERT(workerPrivate); - workerPrivate->AssertIsOnWorkerThread(); +void RemoteWorkerChild::InitializeOnWorker(WorkerPrivate* aWorkerPrivate) { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); RefPtr self = this; - ThreadSafeWeakPtr selfWeakRef(self); + { + const auto lock = mSharedData.Lock(); + mWorkerRef = WeakWorkerRef::Create(lock->mWorkerPrivate, + [self]() { self->ShutdownOnWorker(); }); + } - auto scopeExit = MakeScopeExit([&] { - MOZ_ASSERT(self); - - NS_ProxyRelease(__func__, mOwningEventTarget, self.forget()); - }); - - RefPtr workerRef = WeakWorkerRef::Create( - workerPrivate, [selfWeakRef = std::move(selfWeakRef)]() mutable { - RefPtr self(selfWeakRef); - - if (NS_WARN_IF(!self)) { - return; - } - - self->TransitionStateToTerminated(); - self->ShutdownOnWorker(); - - nsCOMPtr target = self->GetOwningEventTarget(); - NS_ProxyRelease(__func__, target, self.forget()); - }); - - if (NS_WARN_IF(!workerRef)) { - TransitionStateToTerminated(); + if (NS_WARN_IF(!mWorkerRef)) { CreationFailedOnAnyThread(); ShutdownOnWorker(); - return; } - TransitionStateToRunning(workerPrivate.forget(), workerRef.forget()); CreationSucceededOnAnyThread(); } void RemoteWorkerChild::ShutdownOnWorker() { - RefPtr self = this; + const auto lock = mSharedData.Lock(); + MOZ_ASSERT(lock->mWorkerPrivate); + lock->mWorkerPrivate->AssertIsOnWorkerThread(); + // This will release the worker. + mWorkerRef = nullptr; + + nsCOMPtr target = + SystemGroup::EventTargetFor(TaskCategory::Other); + + NS_ProxyRelease("RemoteWorkerChild::mWorkerPrivate", target, + lock->mWorkerPrivate.forget()); + + RefPtr self = this; nsCOMPtr r = - NS_NewRunnableFunction(__func__, [self = std::move(self)] { - MOZ_ACCESS_THREAD_BOUND(self->mLauncherData, launcherData); + NS_NewRunnableFunction("RemoteWorkerChild::ShutdownOnWorker", + [self]() { self->WorkerTerminated(); }); - if (!launcherData->mIPCActive) { - return; - } - - launcherData->mIPCActive = false; - Unused << self->SendClose(); - }); - - GetOwningEventTarget()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); + RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); } -RefPtr RemoteWorkerChild::GetTerminationPromise() { - MOZ_ASSERT(GetOwningEventTarget()->IsOnCurrentThread()); +void RemoteWorkerChild::WorkerTerminated() { + MOZ_ACCESS_THREAD_BOUND(mLauncherData, data); - return mTerminationPromise.Ensure(__func__); -} + { + const auto lock = mSharedData.Lock(); + lock->mWorkerState = eTerminated; + } + data->mPendingOps.Clear(); -void RemoteWorkerChild::CreationSucceededOnAnyThread() { - CreationSucceededOrFailedOnAnyThread(true); -} - -void RemoteWorkerChild::CreationFailedOnAnyThread() { - CreationSucceededOrFailedOnAnyThread(false); -} - -void RemoteWorkerChild::CreationSucceededOrFailedOnAnyThread( - bool aDidCreationSucceed) { -#ifdef DEBUG - auto lock = mState.Lock(); - MOZ_ASSERT_IF(aDidCreationSucceed, lock->is()); - MOZ_ASSERT_IF(!aDidCreationSucceed, lock->is()); -#endif - - RefPtr self = this; - - nsCOMPtr r = NS_NewRunnableFunction( - __func__, - [self = std::move(self), didCreationSucceed = aDidCreationSucceed] { - MOZ_ACCESS_THREAD_BOUND(self->mLauncherData, launcherData); - - if (!launcherData->mIPCActive) { - return; - } - - Unused << self->SendCreated(didCreationSucceed); - }); - - Unused << GetOwningEventTarget()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); -} - -void RemoteWorkerChild::CloseWorkerOnMainThread(State& aState) { - AssertIsOnMainThread(); - MOZ_ASSERT(!aState.is()); - - if (aState.is()) { - TransitionStateToPendingTerminated(aState); + if (!mIPCActive) { return; } - // The holder will be notified by this. - if (aState.is()) { - aState.as().mWorkerPrivate->Cancel(); - } -} - -/** - * Error reporting method - */ -void RemoteWorkerChild::ErrorPropagation(const ErrorValue& aValue) { - MOZ_ASSERT(GetOwningEventTarget()->IsOnCurrentThread()); - - MOZ_ACCESS_THREAD_BOUND(mLauncherData, launcherData); - - if (!launcherData->mIPCActive) { - return; - } - - Unused << SendError(aValue); + Unused << SendClose(); + mIPCActive = false; } void RemoteWorkerChild::ErrorPropagationDispatch(nsresult aError) { @@ -623,14 +364,14 @@ void RemoteWorkerChild::ErrorPropagationDispatch(nsresult aError) { RefPtr self = this; nsCOMPtr r = NS_NewRunnableFunction( "RemoteWorkerChild::ErrorPropagationDispatch", - [self = std::move(self), aError]() { self->ErrorPropagation(aError); }); + [self, aError]() { self->ErrorPropagation(aError); }); - GetOwningEventTarget()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); + RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); } void RemoteWorkerChild::ErrorPropagationOnMainThread( const WorkerErrorReport* aReport, bool aIsErrorEvent) { - AssertIsOnMainThread(); + MOZ_ASSERT(NS_IsMainThread()); ErrorValue value; if (aIsErrorEvent) { @@ -652,14 +393,47 @@ void RemoteWorkerChild::ErrorPropagationOnMainThread( RefPtr self = this; nsCOMPtr r = NS_NewRunnableFunction( "RemoteWorkerChild::ErrorPropagationOnMainThread", - [self = std::move(self), value]() { self->ErrorPropagation(value); }); + [self, value]() { self->ErrorPropagation(value); }); - GetOwningEventTarget()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); + RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); +} + +void RemoteWorkerChild::ErrorPropagation(const ErrorValue& aValue) { + MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread()); + + if (!mIPCActive) { + return; + } + + Unused << SendError(aValue); +} + +void RemoteWorkerChild::CloseWorkerOnMainThread() { + MOZ_ASSERT(NS_IsMainThread()); + const auto lock = mSharedData.Lock(); + + if (lock->mWorkerState == ePending) { + lock->mWorkerState = ePendingTerminated; + // Already released. + return; + } + + // The holder will be notified by this. + if (lock->mWorkerState == eRunning) { + // FIXME: mWorkerState transition and each state's associated data should + // be improved/fixed in bug 1231213. `!lock->mWorkerPrivate` implies that + // the worker state is effectively `eTerminated.` + if (!lock->mWorkerPrivate) { + return; + } + + lock->mWorkerPrivate->Cancel(); + } } void RemoteWorkerChild::FlushReportsOnMainThread( nsIConsoleReportCollector* aReporter) { - AssertIsOnMainThread(); + MOZ_ASSERT(NS_IsMainThread()); bool reportErrorToBrowserConsole = true; @@ -679,208 +453,122 @@ void RemoteWorkerChild::FlushReportsOnMainThread( aReporter->ClearConsoleReports(); } -/** - * Worker state transition methods - */ -RemoteWorkerChild::Running::~Running() { - if (!mWorkerPrivate) { - return; +IPCResult RemoteWorkerChild::RecvExecOp(const RemoteWorkerOp& aOp) { + const auto lock = mSharedData.Lock(); + return ExecuteOperation(aOp, lock); +} + +template +IPCResult RemoteWorkerChild::ExecuteOperation(const RemoteWorkerOp& aOp, + const T& aLock) { + MOZ_ACCESS_THREAD_BOUND(mLauncherData, data); + + if (!mIPCActive) { + return IPC_OK(); } - nsCOMPtr target = - SystemGroup::EventTargetFor(TaskCategory::Other); - NS_ProxyRelease("RemoteWorkerChild::Running::mWorkerPrivate", target, - mWorkerPrivate.forget()); -} - -void RemoteWorkerChild::TransitionStateToPendingTerminated(State& aState) { - MOZ_ASSERT(aState.is()); - - CancelAllPendingOps(aState); - - aState = VariantType(); -} - -void RemoteWorkerChild::TransitionStateToRunning( - already_AddRefed aWorkerPrivate, - already_AddRefed aWorkerRef) { - RefPtr workerPrivate = aWorkerPrivate; - MOZ_ASSERT(workerPrivate); - - RefPtr workerRef = aWorkerRef; - MOZ_ASSERT(workerRef); - - auto lock = mState.Lock(); - - MOZ_ASSERT(lock->is()); - - auto pendingOps = std::move(lock->as().mPendingOps); - - /** - * I'd initialize the WorkerPrivate and WeakWorkerRef in the constructor, - * but mozilla::Variant attempts to call the thread-unsafe `AddRef()` on - * WorkerPrivate. - */ - *lock = VariantType(); - lock->as().mWorkerPrivate = std::move(workerPrivate); - lock->as().mWorkerRef = std::move(workerRef); - - SelfHolder self = this; - - nsCOMPtr r = NS_NewRunnableFunction( - __func__, [pendingOps = std::move(pendingOps), self = std::move(self)]() { - for (auto& op : pendingOps) { - auto lock = self->mState.Lock(); - - DebugOnly started = op->MaybeStart(self.get(), lock.ref()); - MOZ_ASSERT(started); - } - }); - - MOZ_ALWAYS_SUCCEEDS( - mOwningEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL)); -} - -void RemoteWorkerChild::TransitionStateToTerminated() { - auto lock = mState.Lock(); - - TransitionStateToTerminated(lock.ref()); -} - -void RemoteWorkerChild::TransitionStateToTerminated(State& aState) { - if (aState.is()) { - CancelAllPendingOps(aState); + // The worker is not ready yet. + if (aLock->mWorkerState == ePending) { + data->mPendingOps.AppendElement(aOp); + return IPC_OK(); } - mTerminationPromise.ResolveIfExists(true, __func__); + if (aLock->mWorkerState == eTerminated || + aLock->mWorkerState == ePendingTerminated) { + // No op. + return IPC_OK(); + } - aState = VariantType(); -} - -/** - * Operation execution classes/methods - */ -class RemoteWorkerChild::SharedWorkerOp : public RemoteWorkerChild::Op { - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedWorkerOp, override) - - explicit SharedWorkerOp(RemoteWorkerOp&& aOp) : mOp(std::move(aOp)) {} - - bool MaybeStart(RemoteWorkerChild* aOwner, - RemoteWorkerChild::State& aState) override { - MOZ_ASSERT(!mStarted); - MOZ_ASSERT(aOwner); - - MOZ_ACCESS_THREAD_BOUND(aOwner->mLauncherData, launcherData); - - if (NS_WARN_IF(!launcherData->mIPCActive)) { - Unused << NS_WARN_IF(!aState.is()); - -#ifdef DEBUG - mStarted = true; -#endif - - return true; - } - - if (aState.is() && !IsTerminationOp()) { - return false; - } - - if (aState.is() || aState.is()) { -#ifdef DEBUG - mStarted = true; -#endif - - return true; - } - - MOZ_ASSERT(aState.is() || IsTerminationOp()); - - RefPtr self = this; - SelfHolder owner = aOwner; + MOZ_ASSERT(aLock->mWorkerState == eRunning); + // Main-thread operations + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerSuspendOp || + aOp.type() == RemoteWorkerOp::TRemoteWorkerResumeOp || + aOp.type() == RemoteWorkerOp::TRemoteWorkerFreezeOp || + aOp.type() == RemoteWorkerOp::TRemoteWorkerThawOp || + aOp.type() == RemoteWorkerOp::TRemoteWorkerTerminateOp || + aOp.type() == RemoteWorkerOp::TRemoteWorkerAddWindowIDOp || + aOp.type() == RemoteWorkerOp::TRemoteWorkerRemoveWindowIDOp) { + RefPtr self = this; nsCOMPtr r = NS_NewRunnableFunction( - __func__, [self = std::move(self), owner = std::move(owner)]() mutable { - self->Exec(owner); - }); + "RemoteWorkerChild::RecvExecOp", + [self, aOp]() { self->RecvExecOpOnMainThread(aOp); }); - MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget())); - -#ifdef DEBUG - mStarted = true; -#endif - - return true; + nsCOMPtr target = + SystemGroup::EventTargetFor(TaskCategory::Other); + target->Dispatch(r.forget(), NS_DISPATCH_NORMAL); + return IPC_OK(); } - void Cancel() override { - MOZ_ASSERT(!mStarted); - -#ifdef DEBUG - mStarted = true; -#endif + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerPortIdentifierOp) { + const RemoteWorkerPortIdentifierOp& op = + aOp.get_RemoteWorkerPortIdentifierOp(); + RefPtr runnable = + new MessagePortIdentifierRunnable(aLock->mWorkerPrivate, this, + op.portIdentifier()); + if (NS_WARN_IF(!runnable->Dispatch())) { + ErrorPropagation(NS_ERROR_FAILURE); + } + return IPC_OK(); } - private: - ~SharedWorkerOp() { MOZ_ASSERT(mStarted); } + MOZ_CRASH("Unknown operation."); - bool IsTerminationOp() const { - return mOp.type() == RemoteWorkerOp::TRemoteWorkerTerminateOp; - } + return IPC_OK(); +} - void Exec(SelfHolder& aOwner) { - using Running = RemoteWorkerChild::Running; +void RemoteWorkerChild::RecvExecOpOnMainThread(const RemoteWorkerOp& aOp) { + MOZ_ASSERT(NS_IsMainThread()); - AssertIsOnMainThread(); + { + const auto lock = mSharedData.Lock(); - auto lock = aOwner->mState.Lock(); - - MOZ_ASSERT(lock->is() || IsTerminationOp()); - - if (IsTerminationOp()) { - aOwner->CloseWorkerOnMainThread(lock.ref()); + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerSuspendOp) { + if (lock->mWorkerPrivate) { + lock->mWorkerPrivate->ParentWindowPaused(); + } return; } - RefPtr workerPrivate = lock->as().mWorkerPrivate; - - MOZ_ASSERT(workerPrivate); - - if (mOp.type() == RemoteWorkerOp::TRemoteWorkerSuspendOp) { - workerPrivate->ParentWindowPaused(); - } else if (mOp.type() == RemoteWorkerOp::TRemoteWorkerResumeOp) { - workerPrivate->ParentWindowResumed(); - } else if (mOp.type() == RemoteWorkerOp::TRemoteWorkerFreezeOp) { - workerPrivate->Freeze(nullptr); - } else if (mOp.type() == RemoteWorkerOp::TRemoteWorkerThawOp) { - workerPrivate->Thaw(nullptr); - } else if (mOp.type() == RemoteWorkerOp::TRemoteWorkerPortIdentifierOp) { - RefPtr r = - new MessagePortIdentifierRunnable( - workerPrivate, aOwner, - mOp.get_RemoteWorkerPortIdentifierOp().portIdentifier()); - - if (NS_WARN_IF(!r->Dispatch())) { - aOwner->ErrorPropagation(NS_ERROR_FAILURE); + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerResumeOp) { + if (lock->mWorkerPrivate) { + lock->mWorkerPrivate->ParentWindowResumed(); } - } else if (mOp.type() == RemoteWorkerOp::TRemoteWorkerAddWindowIDOp) { - aOwner->mWindowIDs.AppendElement( - mOp.get_RemoteWorkerAddWindowIDOp().windowID()); - } else if (mOp.type() == RemoteWorkerOp::TRemoteWorkerRemoveWindowIDOp) { - aOwner->mWindowIDs.RemoveElement( - mOp.get_RemoteWorkerRemoveWindowIDOp().windowID()); - } else { - MOZ_CRASH("Unknown RemoteWorkerOp type!"); + return; + } + + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerFreezeOp) { + if (lock->mWorkerPrivate) { + lock->mWorkerPrivate->Freeze(nullptr); + } + return; + } + + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerThawOp) { + if (lock->mWorkerPrivate) { + lock->mWorkerPrivate->Thaw(nullptr); + } + return; } } - RemoteWorkerOp mOp; + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerTerminateOp) { + CloseWorkerOnMainThread(); + return; + } -#ifdef DEBUG - bool mStarted = false; -#endif -}; + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerAddWindowIDOp) { + mWindowIDs.AppendElement(aOp.get_RemoteWorkerAddWindowIDOp().windowID()); + return; + } + + if (aOp.type() == RemoteWorkerOp::TRemoteWorkerRemoveWindowIDOp) { + mWindowIDs.RemoveElement(aOp.get_RemoteWorkerRemoveWindowIDOp().windowID()); + return; + } + + MOZ_CRASH("No other operations should be scheduled on main-thread."); +} void RemoteWorkerChild::AddPortIdentifier( JSContext* aCx, WorkerPrivate* aWorkerPrivate, @@ -890,110 +578,68 @@ void RemoteWorkerChild::AddPortIdentifier( } } -void RemoteWorkerChild::CancelAllPendingOps(State& aState) { - MOZ_ASSERT(aState.is()); - - auto pendingOps = std::move(aState.as().mPendingOps); - - for (auto& op : pendingOps) { - op->Cancel(); - } -} - -void RemoteWorkerChild::MaybeStartOp(RefPtr&& aOp) { - MOZ_ASSERT(aOp); - - auto lock = mState.Lock(); - - if (!aOp->MaybeStart(this, lock.ref())) { - lock->as().mPendingOps.AppendElement(std::move(aOp)); - } -} - -IPCResult RemoteWorkerChild::RecvExecOp(RemoteWorkerOp&& aOp) { - MOZ_ASSERT(!mIsServiceWorker); - - MaybeStartOp(new SharedWorkerOp(std::move(aOp))); - - return IPC_OK(); -} - -IPCResult RemoteWorkerChild::RecvExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs, ExecServiceWorkerOpResolver&& aResolve) { - MOZ_ASSERT(mIsServiceWorker); - MOZ_ASSERT( - aArgs.type() != ServiceWorkerOpArgs::TServiceWorkerFetchEventOpArgs, - "FetchEvent operations should be sent via PFetchEventOp(Proxy) actors!"); - - MaybeStartOp(ServiceWorkerOp::Create(aArgs, std::move(aResolve))); - - return IPC_OK(); -} - -RefPtr -RemoteWorkerChild::MaybeSendSetServiceWorkerSkipWaitingFlag() { - RefPtr promise = - new GenericPromise::Private(__func__); - +void RemoteWorkerChild::CreationSucceededOnAnyThread() { RefPtr self = this; + nsCOMPtr r = + NS_NewRunnableFunction("RemoteWorkerChild::CreationSucceededOnAnyThread", + [self]() { self->CreationSucceeded(); }); - nsCOMPtr r = NS_NewRunnableFunction(__func__, [self = std::move( - self), - promise] { - MOZ_ACCESS_THREAD_BOUND(self->mLauncherData, launcherData); - - if (!launcherData->mIPCActive) { - promise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__); - return; - } - - self->SendSetServiceWorkerSkipWaitingFlag()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [promise]( - const SetServiceWorkerSkipWaitingFlagPromise::ResolveOrRejectValue& - aResult) { - if (NS_WARN_IF(aResult.IsReject())) { - promise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__); - return; - } - - promise->Resolve(aResult.ResolveValue(), __func__); - }); - }); - - GetOwningEventTarget()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); - - return promise; + RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); } -/** - * PFetchEventOpProxy methods - */ -PFetchEventOpProxyChild* RemoteWorkerChild::AllocPFetchEventOpProxyChild( - const ServiceWorkerFetchEventOpArgs& aArgs) { - RefPtr actor = new FetchEventOpProxyChild(); +void RemoteWorkerChild::CreationSucceeded() { + MOZ_ACCESS_THREAD_BOUND(mLauncherData, data); - return actor.forget().take(); + // The worker is created but we need to terminate it already. + const auto lock = mSharedData.Lock(); + if (lock->mWorkerState == ePendingTerminated) { + RefPtr self = this; + nsCOMPtr r = + NS_NewRunnableFunction("RemoteWorkerChild::CreationSucceeded", + [self]() { self->CloseWorkerOnMainThread(); }); + + nsCOMPtr target = + SystemGroup::EventTargetFor(TaskCategory::Other); + target->Dispatch(r.forget(), NS_DISPATCH_NORMAL); + return; + } + + lock->mWorkerState = eRunning; + + if (!mIPCActive) { + return; + } + + for (const RemoteWorkerOp& op : data->mPendingOps) { + ExecuteOperation(op, lock); + } + + data->mPendingOps.Clear(); + + Unused << SendCreated(true); } -IPCResult RemoteWorkerChild::RecvPFetchEventOpProxyConstructor( - PFetchEventOpProxyChild* aActor, - const ServiceWorkerFetchEventOpArgs& aArgs) { - MOZ_ASSERT(aActor); +void RemoteWorkerChild::CreationFailedOnAnyThread() { + RefPtr self = this; + nsCOMPtr r = + NS_NewRunnableFunction("RemoteWorkerChild::CreationFailedOnAnyThread", + [self]() { self->CreationFailed(); }); - (static_cast(aActor))->Initialize(aArgs); - - return IPC_OK(); + RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL); } -bool RemoteWorkerChild::DeallocPFetchEventOpProxyChild( - PFetchEventOpProxyChild* aActor) { - MOZ_ASSERT(aActor); +void RemoteWorkerChild::CreationFailed() { + MOZ_ACCESS_THREAD_BOUND(mLauncherData, data); - RefPtr actor = - dont_AddRef(static_cast(aActor)); + const auto lock = mSharedData.Lock(); + lock->mWorkerState = eTerminated; + data->mPendingOps.Clear(); - return true; + if (!mIPCActive) { + return; + } + + Unused << SendCreated(false); } } // namespace dom diff --git a/dom/workers/remoteworkers/RemoteWorkerChild.h b/dom/workers/remoteworkers/RemoteWorkerChild.h index 51ff75090529..8325b362974c 100644 --- a/dom/workers/remoteworkers/RemoteWorkerChild.h +++ b/dom/workers/remoteworkers/RemoteWorkerChild.h @@ -7,157 +7,114 @@ #ifndef mozilla_dom_RemoteWorkerChild_h #define mozilla_dom_RemoteWorkerChild_h -#include "nsCOMPtr.h" -#include "nsISupportsImpl.h" -#include "nsTArray.h" - -#include "mozilla/DataMutex.h" -#include "mozilla/MozPromise.h" -#include "mozilla/RefPtr.h" -#include "mozilla/ThreadBound.h" -#include "mozilla/ThreadSafeWeakPtr.h" #include "mozilla/dom/PRemoteWorkerChild.h" -#include "mozilla/dom/ServiceWorkerOpArgs.h" +#include "mozilla/DataMutex.h" +#include "mozilla/ThreadBound.h" +#include "mozilla/UniquePtr.h" +#include "nsISupportsImpl.h" -class nsISerialEventTarget; class nsIConsoleReportCollector; namespace mozilla { namespace dom { -class ErrorValue; -class FetchEventOpProxyChild; class RemoteWorkerData; -class ServiceWorkerOp; class WeakWorkerRef; class WorkerErrorReport; class WorkerPrivate; +class OptionalMessagePortIdentifier; -class RemoteWorkerChild final - : public SupportsThreadSafeWeakPtr, - public PRemoteWorkerChild { - friend class FetchEventOpProxyChild; +class RemoteWorkerChild final : public PRemoteWorkerChild { friend class PRemoteWorkerChild; - friend class ServiceWorkerOp; public: - MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(RemoteWorkerChild) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteWorkerChild) - MOZ_DECLARE_REFCOUNTED_TYPENAME(RemoteWorkerChild) - - explicit RemoteWorkerChild(const RemoteWorkerData& aData); - - ~RemoteWorkerChild(); - - nsISerialEventTarget* GetOwningEventTarget() const; + RemoteWorkerChild(); void ExecWorker(const RemoteWorkerData& aData); - void ErrorPropagationOnMainThread(const WorkerErrorReport* aReport, - bool aIsErrorEvent); + void InitializeOnWorker(WorkerPrivate* aWorkerPrivate); - void FlushReportsOnMainThread(nsIConsoleReportCollector* aReporter); + void ShutdownOnWorker(); void AddPortIdentifier(JSContext* aCx, WorkerPrivate* aWorkerPrivate, const MessagePortIdentifier& aPortIdentifier); - RefPtr GetTerminationPromise(); + void ErrorPropagationOnMainThread(const WorkerErrorReport* aReport, + bool aIsErrorEvent); - RefPtr MaybeSendSetServiceWorkerSkipWaitingFlag(); + void CloseWorkerOnMainThread(); + + void FlushReportsOnMainThread(nsIConsoleReportCollector* aReporter); private: class InitializeWorkerRunnable; - class Op; - class SharedWorkerOp; + ~RemoteWorkerChild(); - struct Pending { - nsTArray> mPendingOps; - }; + void ActorDestroy(ActorDestroyReason aWhy) override; - struct PendingTerminated {}; + mozilla::ipc::IPCResult RecvExecOp(const RemoteWorkerOp& aOp); - struct Running { - ~Running(); + // This member is a function template because DataMutex::AutoLock + // is private, yet it must be passed by const reference into ExecuteOperation. + // There should only be one instantiation of this template. + template + mozilla::ipc::IPCResult ExecuteOperation(const RemoteWorkerOp&, + const T& aLock); - RefPtr mWorkerPrivate; - RefPtr mWorkerRef; - }; + void RecvExecOpOnMainThread(const RemoteWorkerOp& aOp); - struct Terminated {}; - - using State = Variant; - - DataMutex mState; - - class Op { - public: - NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING - - virtual ~Op() = default; - - virtual bool MaybeStart(RemoteWorkerChild* aOwner, State& aState) = 0; - - virtual void Cancel() = 0; - }; - - void ActorDestroy(ActorDestroyReason) override; - - mozilla::ipc::IPCResult RecvExecOp(RemoteWorkerOp&& aOp); - - mozilla::ipc::IPCResult RecvExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs, ExecServiceWorkerOpResolver&& aResolve); - - PFetchEventOpProxyChild* AllocPFetchEventOpProxyChild( - const ServiceWorkerFetchEventOpArgs& aArgs); - - mozilla::ipc::IPCResult RecvPFetchEventOpProxyConstructor( - PFetchEventOpProxyChild* aActor, - const ServiceWorkerFetchEventOpArgs& aArgs) override; - - bool DeallocPFetchEventOpProxyChild(PFetchEventOpProxyChild* aActor); - - nsresult ExecWorkerOnMainThread(RemoteWorkerData&& aData); - - void InitializeOnWorker(already_AddRefed aWorkerPrivate); - - void ShutdownOnWorker(); - - void CreationSucceededOnAnyThread(); - - void CreationFailedOnAnyThread(); - - void CreationSucceededOrFailedOnAnyThread(bool aDidCreationSucceed); - - void CloseWorkerOnMainThread(State& aState); + nsresult ExecWorkerOnMainThread(const RemoteWorkerData& aData); void ErrorPropagation(const ErrorValue& aValue); void ErrorPropagationDispatch(nsresult aError); - void TransitionStateToPendingTerminated(State& aState); + void CreationSucceededOnAnyThread(); - void TransitionStateToRunning(already_AddRefed aWorkerPrivate, - already_AddRefed aWorkerRef); + void CreationSucceeded(); - void TransitionStateToTerminated(); + void CreationFailedOnAnyThread(); - void TransitionStateToTerminated(State& aState); + void CreationFailed(); - void CancelAllPendingOps(State& aState); - - void MaybeStartOp(RefPtr&& aOp); - - MozPromiseHolder mTerminationPromise; - - const bool mIsServiceWorker; - const nsCOMPtr mOwningEventTarget; + void WorkerTerminated(); // Touched on main-thread only. nsTArray mWindowIDs; + RefPtr mWorkerRef; + bool mIPCActive; + + enum WorkerState { + // CreationSucceeded/CreationFailed not called yet. + ePending, + + // The worker is not created yet, but we want to terminate as soon as + // possible. + ePendingTerminated, + + // Worker up and running. + eRunning, + + // Worker terminated. + eTerminated, + }; + + struct SharedData { + SharedData(); + + RefPtr mWorkerPrivate; + WorkerState mWorkerState; + }; + + DataMutex mSharedData; + + // Touched only on the owning thread (Worker Launcher). struct LauncherBoundData { - bool mIPCActive = true; + nsTArray mPendingOps; }; ThreadBound mLauncherData; diff --git a/dom/workers/remoteworkers/RemoteWorkerController.cpp b/dom/workers/remoteworkers/RemoteWorkerController.cpp index 087f2686e433..0f47ee260f7b 100644 --- a/dom/workers/remoteworkers/RemoteWorkerController.cpp +++ b/dom/workers/remoteworkers/RemoteWorkerController.cpp @@ -4,20 +4,10 @@ * 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 "RemoteWorkerController.h" - -#include - -#include "nsDebug.h" - -#include "mozilla/Assertions.h" -#include "mozilla/DebugOnly.h" -#include "mozilla/ScopeExit.h" +#include "mozilla/dom/MessagePort.h" #include "mozilla/dom/MessagePortParent.h" -#include "mozilla/dom/RemoteWorkerTypes.h" -#include "mozilla/dom/ServiceWorkerCloneData.h" #include "mozilla/ipc/BackgroundParent.h" -#include "RemoteWorkerControllerParent.h" +#include "RemoteWorkerController.h" #include "RemoteWorkerManager.h" #include "RemoteWorkerParent.h" @@ -31,12 +21,12 @@ namespace dom { already_AddRefed RemoteWorkerController::Create( const RemoteWorkerData& aData, RemoteWorkerObserver* aObserver, base::ProcessId aProcessId) { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aObserver); RefPtr controller = - new RemoteWorkerController(aData, aObserver); + new RemoteWorkerController(aObserver); RefPtr manager = RemoteWorkerManager::GetOrCreate(); MOZ_ASSERT(manager); @@ -46,44 +36,26 @@ already_AddRefed RemoteWorkerController::Create( return controller.forget(); } -RemoteWorkerController::RemoteWorkerController(const RemoteWorkerData& aData, - RemoteWorkerObserver* aObserver) - : mObserver(aObserver), - mState(ePending), - mIsServiceWorker(aData.serviceWorkerData().type() == - OptionalServiceWorkerData::TServiceWorkerData) { - AssertIsInMainProcess(); +RemoteWorkerController::RemoteWorkerController(RemoteWorkerObserver* aObserver) + : mObserver(aObserver), mState(ePending) { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); } RemoteWorkerController::~RemoteWorkerController() { AssertIsOnBackgroundThread(); - MOZ_DIAGNOSTIC_ASSERT(mPendingOps.IsEmpty()); + MOZ_ASSERT(XRE_IsParentProcess()); } void RemoteWorkerController::SetWorkerActor(RemoteWorkerParent* aActor) { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(!mActor); MOZ_ASSERT(aActor); mActor = aActor; } -void RemoteWorkerController::NoteDeadWorkerActor() { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mActor); - - // The actor has been destroyed without a proper close() notification. Let's - // inform the observer. - if (mState == eReady) { - mObserver->Terminated(); - } - - mActor = nullptr; - - Shutdown(); -} - void RemoteWorkerController::CreationFailed() { AssertIsOnBackgroundThread(); MOZ_ASSERT(XRE_IsParentProcess()); @@ -96,13 +68,13 @@ void RemoteWorkerController::CreationFailed() { return; } - NoteDeadWorker(); - + Shutdown(); mObserver->CreationFailed(); } void RemoteWorkerController::CreationSucceeded() { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(mState == ePending || mState == eTerminated); if (mState == eTerminated) { @@ -117,347 +89,238 @@ void RemoteWorkerController::CreationSucceeded() { mObserver->CreationSucceeded(); - auto pendingOps = std::move(mPendingOps); + for (UniquePtr& op : mPendingOps) { + switch (op->mType) { + case Op::eTerminate: + Terminate(); + break; - for (auto& op : pendingOps) { - DebugOnly started = op->MaybeStart(this); - MOZ_ASSERT(started); + case Op::eSuspend: + Suspend(); + break; + + case Op::eResume: + Resume(); + break; + + case Op::eFreeze: + Freeze(); + break; + + case Op::eThaw: + Thaw(); + break; + + case Op::ePortIdentifier: + AddPortIdentifier(op->mPortIdentifier); + break; + + case Op::eAddWindowID: + AddWindowID(op->mWindowID); + break; + + case Op::eRemoveWindowID: + RemoveWindowID(op->mWindowID); + break; + + default: + MOZ_CRASH("Unknown op."); + } + + op->Completed(); } + + mPendingOps.Clear(); } void RemoteWorkerController::ErrorPropagation(const ErrorValue& aValue) { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); mObserver->ErrorReceived(aValue); } void RemoteWorkerController::WorkerTerminated() { AssertIsOnBackgroundThread(); - - NoteDeadWorker(); + MOZ_ASSERT(XRE_IsParentProcess()); + MOZ_ASSERT(mState == eReady); mObserver->Terminated(); -} - -void RemoteWorkerController::CancelAllPendingOps() { - AssertIsOnBackgroundThread(); - - auto pendingOps = std::move(mPendingOps); - - for (auto& op : pendingOps) { - op->Cancel(); - } + Shutdown(); } void RemoteWorkerController::Shutdown() { AssertIsOnBackgroundThread(); - Unused << NS_WARN_IF(mIsServiceWorker && !mPendingOps.IsEmpty()); - - if (mState == eTerminated) { - MOZ_ASSERT(mPendingOps.IsEmpty()); - return; - } + MOZ_ASSERT(XRE_IsParentProcess()); + MOZ_ASSERT(mState == ePending || mState == eReady); mState = eTerminated; - CancelAllPendingOps(); + mPendingOps.Clear(); - if (!mActor) { - return; - } - - mActor->SetController(nullptr); - - /** - * The "non-remote-side" of the Service Worker will have ensured that the - * remote worker is terminated before calling `Shutdown().` - */ - if (mIsServiceWorker) { - mActor->MaybeSendDelete(); - } else { + if (mActor) { + mActor->SetController(nullptr); Unused << mActor->SendExecOp(RemoteWorkerTerminateOp()); - } - - mActor = nullptr; -} - -void RemoteWorkerController::NoteDeadWorker() { - AssertIsOnBackgroundThread(); - - CancelAllPendingOps(); - - /** - * The "non-remote-side" of the Service Worker will initiate `Shutdown()` - * once it's notified that all dispatched operations have either completed - * or canceled. That is, it'll explicitly call `Shutdown()` later. - */ - if (!mIsServiceWorker) { - Shutdown(); - } -} - -template -void RemoteWorkerController::MaybeStartSharedWorkerOp(Args&&... aArgs) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(!mIsServiceWorker); - - UniquePtr op = - MakeUnique(std::forward(aArgs)...); - - if (!op->MaybeStart(this)) { - mPendingOps.AppendElement(std::move(op)); + mActor = nullptr; } } void RemoteWorkerController::AddWindowID(uint64_t aWindowID) { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aWindowID); - MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eAddWindowID, aWindowID); + if (mState == ePending) { + mPendingOps.AppendElement(new Op(Op::eAddWindowID, aWindowID)); + return; + } + + if (mState == eTerminated) { + return; + } + + MOZ_ASSERT(mState == eReady); + Unused << mActor->SendExecOp(RemoteWorkerAddWindowIDOp(aWindowID)); } void RemoteWorkerController::RemoveWindowID(uint64_t aWindowID) { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aWindowID); - MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eRemoveWindowID, aWindowID); + if (mState == ePending) { + mPendingOps.AppendElement(new Op(Op::eRemoveWindowID, aWindowID)); + return; + } + + if (mState == eTerminated) { + return; + } + + MOZ_ASSERT(mState == eReady); + Unused << mActor->SendExecOp(RemoteWorkerRemoveWindowIDOp(aWindowID)); } void RemoteWorkerController::AddPortIdentifier( const MessagePortIdentifier& aPortIdentifier) { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); - MaybeStartSharedWorkerOp(aPortIdentifier); + if (mState == ePending) { + mPendingOps.AppendElement(new Op(aPortIdentifier)); + return; + } + + if (mState == eTerminated) { + return; + } + + MOZ_ASSERT(mState == eReady); + Unused << mActor->SendExecOp(RemoteWorkerPortIdentifierOp(aPortIdentifier)); +} + +void RemoteWorkerController::ForgetActorAndTerminate() { + AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); + + // The actor has been destroyed without a proper close() notification. Let's + // inform the observer. + if (mState == eReady) { + mObserver->Terminated(); + } + + mActor = nullptr; + Terminate(); } void RemoteWorkerController::Terminate() { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); - MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eTerminate); + if (mState == eTerminated) { + return; + } + + Shutdown(); } void RemoteWorkerController::Suspend() { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); - MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eSuspend); + if (mState == ePending) { + mPendingOps.AppendElement(new Op(Op::eSuspend)); + return; + } + + if (mState == eTerminated) { + return; + } + + MOZ_ASSERT(mState == eReady); + Unused << mActor->SendExecOp(RemoteWorkerSuspendOp()); } void RemoteWorkerController::Resume() { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); - MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eResume); + if (mState == ePending) { + mPendingOps.AppendElement(new Op(Op::eResume)); + return; + } + + if (mState == eTerminated) { + return; + } + + MOZ_ASSERT(mState == eReady); + Unused << mActor->SendExecOp(RemoteWorkerResumeOp()); } void RemoteWorkerController::Freeze() { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); - MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eFreeze); + if (mState == ePending) { + mPendingOps.AppendElement(new Op(Op::eFreeze)); + return; + } + + if (mState == eTerminated) { + return; + } + + MOZ_ASSERT(mState == eReady); + Unused << mActor->SendExecOp(RemoteWorkerFreezeOp()); } void RemoteWorkerController::Thaw() { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); - MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eThaw); -} - -RefPtr RemoteWorkerController::ExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mIsServiceWorker); - - RefPtr promise = - new ServiceWorkerOpPromise::Private(__func__); - - UniquePtr op = - MakeUnique(std::move(aArgs), promise); - - if (!op->MaybeStart(this)) { - mPendingOps.AppendElement(std::move(op)); + if (mState == ePending) { + mPendingOps.AppendElement(new Op(Op::eThaw)); + return; } - return promise; -} - -RefPtr RemoteWorkerController::SetServiceWorkerSkipWaitingFlag() - const { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mObserver); - - RefPtr promise = - new GenericPromise::Private(__func__); - - static_cast(mObserver.get()) - ->MaybeSendSetServiceWorkerSkipWaitingFlag( - [promise](bool aOk) { promise->Resolve(aOk, __func__); }); - - return promise; -} - -RemoteWorkerController::PendingSharedWorkerOp::PendingSharedWorkerOp( - Type aType, uint64_t aWindowID) - : mType(aType), mWindowID(aWindowID) { - AssertIsOnBackgroundThread(); -} - -RemoteWorkerController::PendingSharedWorkerOp::PendingSharedWorkerOp( - const MessagePortIdentifier& aPortIdentifier) - : mType(ePortIdentifier), mPortIdentifier(aPortIdentifier) { - AssertIsOnBackgroundThread(); -} - -RemoteWorkerController::PendingSharedWorkerOp::~PendingSharedWorkerOp() { - AssertIsOnBackgroundThread(); - MOZ_DIAGNOSTIC_ASSERT(mCompleted); -} - -bool RemoteWorkerController::PendingSharedWorkerOp::MaybeStart( - RemoteWorkerController* const aOwner) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(!mCompleted); - MOZ_ASSERT(aOwner); - - if (aOwner->mState == RemoteWorkerController::eTerminated) { - Cancel(); - return true; + if (mState == eTerminated) { + return; } - if (aOwner->mState == RemoteWorkerController::ePending && - mType != eTerminate) { - return false; - } - - switch (mType) { - case eTerminate: - aOwner->Shutdown(); - break; - case eSuspend: - Unused << aOwner->mActor->SendExecOp(RemoteWorkerSuspendOp()); - break; - case eResume: - Unused << aOwner->mActor->SendExecOp(RemoteWorkerResumeOp()); - break; - case eFreeze: - Unused << aOwner->mActor->SendExecOp(RemoteWorkerFreezeOp()); - break; - case eThaw: - Unused << aOwner->mActor->SendExecOp(RemoteWorkerThawOp()); - break; - case ePortIdentifier: - Unused << aOwner->mActor->SendExecOp( - RemoteWorkerPortIdentifierOp(mPortIdentifier)); - break; - case eAddWindowID: - Unused << aOwner->mActor->SendExecOp( - RemoteWorkerAddWindowIDOp(mWindowID)); - break; - case eRemoveWindowID: - Unused << aOwner->mActor->SendExecOp( - RemoteWorkerRemoveWindowIDOp(mWindowID)); - break; - default: - MOZ_CRASH("Unknown op."); - } - - mCompleted = true; - - return true; + MOZ_ASSERT(mState == eReady); + Unused << mActor->SendExecOp(RemoteWorkerThawOp()); } -void RemoteWorkerController::PendingSharedWorkerOp::Cancel() { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(!mCompleted); +RemoteWorkerController::Op::~Op() { + MOZ_COUNT_DTOR(Op); // We don't want to leak the port if the operation has not been processed. - if (mType == ePortIdentifier) { + if (!mCompleted && mType == ePortIdentifier) { MessagePortParent::ForceClose(mPortIdentifier.uuid(), mPortIdentifier.destinationUuid(), mPortIdentifier.sequenceId()); } - - mCompleted = true; -} - -RemoteWorkerController::PendingServiceWorkerOp::PendingServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs, - RefPtr aPromise) - : mArgs(std::move(aArgs)), mPromise(std::move(aPromise)) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mPromise); -} - -RemoteWorkerController::PendingServiceWorkerOp::~PendingServiceWorkerOp() { - AssertIsOnBackgroundThread(); - MOZ_DIAGNOSTIC_ASSERT(!mPromise); -} - -bool RemoteWorkerController::PendingServiceWorkerOp::MaybeStart( - RemoteWorkerController* const aOwner) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mPromise); - MOZ_ASSERT(aOwner); - - if (NS_WARN_IF(aOwner->mState == RemoteWorkerController::eTerminated)) { - mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__); - mPromise = nullptr; - return true; - } - - // The target content process must still be starting up. - if (!aOwner->mActor) { - return false; - } - - /** - * Allow termination operations to pass through while pending because the - * remote Service Worker can be terminated while still starting up. - */ - if (aOwner->mState == RemoteWorkerController::ePending && - mArgs.type() != - ServiceWorkerOpArgs::TServiceWorkerTerminateWorkerOpArgs) { - return false; - } - - if (mArgs.type() == ServiceWorkerOpArgs::TServiceWorkerMessageEventOpArgs) { - auto& args = mArgs.get_ServiceWorkerMessageEventOpArgs(); - - ServiceWorkerMessageEventOpArgs copyArgs; - copyArgs.clientInfoAndState() = std::move(args.clientInfoAndState()); - - RefPtr copyData = new ServiceWorkerCloneData(); - copyData->StealFromClonedMessageDataForBackgroundParent(args.clonedData()); - - if (!copyData->BuildClonedMessageDataForBackgroundParent( - aOwner->mActor->Manager(), copyArgs.clonedData())) { - mPromise->Reject(NS_ERROR_DOM_DATA_CLONE_ERR, __func__); - mPromise = nullptr; - return true; - } - - mArgs = std::move(copyArgs); - } - - aOwner->mActor->SendExecServiceWorkerOp(mArgs)->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [promise = std::move(mPromise)]( - PRemoteWorkerParent::ExecServiceWorkerOpPromise:: - ResolveOrRejectValue&& aResult) { - if (NS_WARN_IF(aResult.IsReject())) { - promise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__); - return; - } - - promise->Resolve(std::move(aResult.ResolveValue()), __func__); - }); - - return true; -} - -void RemoteWorkerController::PendingServiceWorkerOp::Cancel() { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mPromise); - - mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__); - mPromise = nullptr; } } // namespace dom diff --git a/dom/workers/remoteworkers/RemoteWorkerController.h b/dom/workers/remoteworkers/RemoteWorkerController.h index d81538a16273..a37898ff0d77 100644 --- a/dom/workers/remoteworkers/RemoteWorkerController.h +++ b/dom/workers/remoteworkers/RemoteWorkerController.h @@ -8,13 +8,6 @@ #define mozilla_dom_RemoteWorkerController_h #include "nsISupportsImpl.h" -#include "nsTArray.h" - -#include "mozilla/RefPtr.h" -#include "mozilla/UniquePtr.h" -#include "mozilla/dom/DOMTypes.h" -#include "mozilla/dom/ServiceWorkerOpArgs.h" -#include "mozilla/dom/ServiceWorkerOpPromise.h" namespace mozilla { namespace dom { @@ -86,8 +79,7 @@ namespace dom { */ class ErrorValue; -class RemoteWorkerControllerParent; -class RemoteWorkerData; +class MessagePortIdentifier; class RemoteWorkerManager; class RemoteWorkerParent; @@ -105,7 +97,6 @@ class RemoteWorkerObserver { }; class RemoteWorkerController final { - friend class RemoteWorkerControllerParent; friend class RemoteWorkerManager; friend class RemoteWorkerParent; @@ -132,38 +123,24 @@ class RemoteWorkerController final { void Thaw(); - RefPtr ExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs); - - RefPtr SetServiceWorkerSkipWaitingFlag() const; - private: - RemoteWorkerController(const RemoteWorkerData& aData, - RemoteWorkerObserver* aObserver); - + explicit RemoteWorkerController(RemoteWorkerObserver* aObserver); ~RemoteWorkerController(); void SetWorkerActor(RemoteWorkerParent* aActor); - void NoteDeadWorkerActor(); - void ErrorPropagation(const ErrorValue& aValue); void WorkerTerminated(); + void ForgetActorAndTerminate(); + void Shutdown(); void CreationFailed(); void CreationSucceeded(); - void CancelAllPendingOps(); - - template - void MaybeStartSharedWorkerOp(Args&&... aArgs); - - void NoteDeadWorker(); - RefPtr mObserver; RefPtr mActor; @@ -173,35 +150,7 @@ class RemoteWorkerController final { eTerminated, } mState; - const bool mIsServiceWorker; - - /** - * `PendingOp` is responsible for encapsulating logic for starting and - * canceling pending remote worker operations, as this logic may vary - * depending on the type of the remote worker and the type of the operation. - */ - class PendingOp { - public: - PendingOp() = default; - - PendingOp(const PendingOp&) = delete; - - PendingOp& operator=(const PendingOp&) = delete; - - virtual ~PendingOp() = default; - - /** - * Returns `true` if execution has started and `false` otherwise. - * - * Starting execution may depend the state of `aOwner.` - */ - virtual bool MaybeStart(RemoteWorkerController* const aOwner) = 0; - - virtual void Cancel() = 0; - }; - - class PendingSharedWorkerOp final : public PendingOp { - public: + struct Op { enum Type { eTerminate, eSuspend, @@ -213,41 +162,34 @@ class RemoteWorkerController final { eRemoveWindowID, }; - explicit PendingSharedWorkerOp(Type aType, uint64_t aWindowID = 0); + explicit Op(Type aType, uint64_t aWindowID = 0) + : mType(aType), mWindowID(aWindowID), mCompleted(false) { + MOZ_COUNT_CTOR(Op); + } - explicit PendingSharedWorkerOp( - const MessagePortIdentifier& aPortIdentifier); + explicit Op(const MessagePortIdentifier& aPortIdentifier) + : mType(ePortIdentifier), + mPortIdentifier(aPortIdentifier), + mCompleted(false) { + MOZ_COUNT_CTOR(Op); + } - ~PendingSharedWorkerOp(); + // This object cannot be copied. + Op(Op const&) = delete; + Op& operator=(Op const&) = delete; - bool MaybeStart(RemoteWorkerController* const aOwner) override; + ~Op(); - void Cancel() override; + void Completed() { mCompleted = true; } - private: - const Type mType; - const MessagePortIdentifier mPortIdentifier; - const uint64_t mWindowID = 0; - bool mCompleted = false; + Type mType; + + MessagePortIdentifier mPortIdentifier; + uint64_t mWindowID; + bool mCompleted; }; - class PendingServiceWorkerOp final : public PendingOp { - public: - PendingServiceWorkerOp(ServiceWorkerOpArgs&& aArgs, - RefPtr aPromise); - - ~PendingServiceWorkerOp(); - - bool MaybeStart(RemoteWorkerController* const aOwner) override; - - void Cancel() override; - - private: - ServiceWorkerOpArgs mArgs; - RefPtr mPromise; - }; - - nsTArray> mPendingOps; + nsTArray> mPendingOps; }; } // namespace dom diff --git a/dom/workers/remoteworkers/RemoteWorkerControllerChild.cpp b/dom/workers/remoteworkers/RemoteWorkerControllerChild.cpp deleted file mode 100644 index a346f4d0cb38..000000000000 --- a/dom/workers/remoteworkers/RemoteWorkerControllerChild.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* -*- 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 "RemoteWorkerControllerChild.h" - -#include - -#include "MainThreadUtils.h" -#include "nsError.h" -#include "nsThreadUtils.h" - -#include "ServiceWorkerPrivateImpl.h" -#include "mozilla/Assertions.h" -#include "mozilla/RefPtr.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/PFetchEventOpChild.h" - -namespace mozilla { - -using ipc::IPCResult; - -namespace dom { - -RemoteWorkerControllerChild::RemoteWorkerControllerChild( - RefPtr aObserver) - : mObserver(std::move(aObserver)) { - AssertIsOnMainThread(); - MOZ_ASSERT(mObserver); -} - -PFetchEventOpChild* RemoteWorkerControllerChild::AllocPFetchEventOpChild( - const ServiceWorkerFetchEventOpArgs& aArgs) { - MOZ_CRASH("PFetchEventOpChild actors must be manually constructed!"); - return nullptr; -} - -bool RemoteWorkerControllerChild::DeallocPFetchEventOpChild( - PFetchEventOpChild* aActor) { - AssertIsOnMainThread(); - MOZ_ASSERT(aActor); - - delete aActor; - return true; -} - -void RemoteWorkerControllerChild::ActorDestroy(ActorDestroyReason aReason) { - AssertIsOnMainThread(); - - mIPCActive = false; - - if (NS_WARN_IF(mObserver)) { - mObserver->ErrorReceived(NS_ERROR_DOM_ABORT_ERR); - } -} - -IPCResult RemoteWorkerControllerChild::RecvCreationFailed() { - AssertIsOnMainThread(); - - if (mObserver) { - mObserver->CreationFailed(); - } - - return IPC_OK(); -} - -IPCResult RemoteWorkerControllerChild::RecvCreationSucceeded() { - AssertIsOnMainThread(); - - if (mObserver) { - mObserver->CreationSucceeded(); - } - - return IPC_OK(); -} - -IPCResult RemoteWorkerControllerChild::RecvErrorReceived( - const ErrorValue& aError) { - AssertIsOnMainThread(); - - if (mObserver) { - mObserver->ErrorReceived(aError); - } - - return IPC_OK(); -} - -IPCResult RemoteWorkerControllerChild::RecvTerminated() { - AssertIsOnMainThread(); - - if (mObserver) { - mObserver->Terminated(); - } - - return IPC_OK(); -} - -IPCResult RemoteWorkerControllerChild::RecvSetServiceWorkerSkipWaitingFlag( - SetServiceWorkerSkipWaitingFlagResolver&& aResolve) { - AssertIsOnMainThread(); - - if (mObserver) { - static_cast(mObserver.get()) - ->SetSkipWaitingFlag() - ->Then(GetCurrentThreadSerialEventTarget(), __func__, - [resolve = std::move(aResolve)]( - const GenericPromise::ResolveOrRejectValue& aResult) { - resolve(aResult.IsResolve() ? aResult.ResolveValue() : false); - }); - - return IPC_OK(); - } - - aResolve(false); - - return IPC_OK(); -} - -void RemoteWorkerControllerChild::RevokeObserver( - RemoteWorkerObserver* aObserver) { - AssertIsOnMainThread(); - MOZ_ASSERT(aObserver); - MOZ_ASSERT(aObserver == mObserver); - - mObserver = nullptr; -} - -void RemoteWorkerControllerChild::MaybeSendDelete() { - AssertIsOnMainThread(); - - if (!mIPCActive) { - return; - } - - RefPtr self = this; - - SendShutdown()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [self = std::move(self)](const ShutdownPromise::ResolveOrRejectValue&) { - if (self->mIPCActive) { - Unused << self->Send__delete__(self); - } - }); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/workers/remoteworkers/RemoteWorkerControllerChild.h b/dom/workers/remoteworkers/RemoteWorkerControllerChild.h deleted file mode 100644 index a27f16a9f668..000000000000 --- a/dom/workers/remoteworkers/RemoteWorkerControllerChild.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_remoteworkercontrollerchild_h__ -#define mozilla_dom_remoteworkercontrollerchild_h__ - -#include "nsISupportsImpl.h" - -#include "RemoteWorkerController.h" -#include "mozilla/RefPtr.h" -#include "mozilla/dom/PRemoteWorkerControllerChild.h" - -namespace mozilla { -namespace dom { - -class RemoteWorkerControllerChild final : public PRemoteWorkerControllerChild { - friend class PRemoteWorkerControllerChild; - - public: - NS_INLINE_DECL_REFCOUNTING(RemoteWorkerControllerChild) - - explicit RemoteWorkerControllerChild(RefPtr aObserver); - - void Initialize(); - - void RevokeObserver(RemoteWorkerObserver* aObserver); - - void MaybeSendDelete(); - - private: - ~RemoteWorkerControllerChild() = default; - - PFetchEventOpChild* AllocPFetchEventOpChild( - const ServiceWorkerFetchEventOpArgs& aArgs); - - bool DeallocPFetchEventOpChild(PFetchEventOpChild* aActor); - - void ActorDestroy(ActorDestroyReason aReason) override; - - mozilla::ipc::IPCResult RecvCreationFailed(); - - mozilla::ipc::IPCResult RecvCreationSucceeded(); - - mozilla::ipc::IPCResult RecvErrorReceived(const ErrorValue& aError); - - mozilla::ipc::IPCResult RecvTerminated(); - - mozilla::ipc::IPCResult RecvSetServiceWorkerSkipWaitingFlag( - SetServiceWorkerSkipWaitingFlagResolver&& aResolve); - - RefPtr mObserver; - - bool mIPCActive = true; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_remoteworkercontrollerchild_h__ diff --git a/dom/workers/remoteworkers/RemoteWorkerControllerParent.cpp b/dom/workers/remoteworkers/RemoteWorkerControllerParent.cpp deleted file mode 100644 index 88282d38f202..000000000000 --- a/dom/workers/remoteworkers/RemoteWorkerControllerParent.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -*- 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 "RemoteWorkerControllerParent.h" - -#include - -#include "nsCOMPtr.h" -#include "nsDebug.h" -#include "nsError.h" -#include "nsThreadUtils.h" - -#include "mozilla/Assertions.h" -#include "mozilla/Unused.h" -#include "mozilla/dom/FetchEventOpParent.h" -#include "mozilla/dom/ServiceWorkerOpPromise.h" -#include "mozilla/ipc/BackgroundParent.h" - -namespace mozilla { - -using namespace ipc; - -namespace dom { - -RemoteWorkerControllerParent::RemoteWorkerControllerParent( - const RemoteWorkerData& aRemoteWorkerData) - : mRemoteWorkerController(RemoteWorkerController::Create( - aRemoteWorkerData, this, 0 /* random process ID */)) { - AssertIsInMainProcess(); - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mRemoteWorkerController); -} - -RefPtr RemoteWorkerControllerParent::GetRemoteWorkerParent() - const { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mRemoteWorkerController); - - return mRemoteWorkerController->mActor; -} - -void RemoteWorkerControllerParent::MaybeSendSetServiceWorkerSkipWaitingFlag( - std::function&& aCallback) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(aCallback); - - if (!mIPCActive) { - aCallback(false); - return; - } - - SendSetServiceWorkerSkipWaitingFlag()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [callback = std::move(aCallback)]( - const SetServiceWorkerSkipWaitingFlagPromise::ResolveOrRejectValue& - aResult) { - callback(aResult.IsResolve() ? aResult.ResolveValue() : false); - }); -} - -RemoteWorkerControllerParent::~RemoteWorkerControllerParent() { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(!mIPCActive); - MOZ_ASSERT(!mRemoteWorkerController); -} - -PFetchEventOpParent* RemoteWorkerControllerParent::AllocPFetchEventOpParent( - const ServiceWorkerFetchEventOpArgs& aArgs) { - AssertIsOnBackgroundThread(); - - RefPtr actor = new FetchEventOpParent(); - return actor.forget().take(); -} - -IPCResult RemoteWorkerControllerParent::RecvPFetchEventOpConstructor( - PFetchEventOpParent* aActor, const ServiceWorkerFetchEventOpArgs& aArgs) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(aActor); - - (static_cast(aActor))->Initialize(aArgs); - - return IPC_OK(); -} - -bool RemoteWorkerControllerParent::DeallocPFetchEventOpParent( - PFetchEventOpParent* aActor) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(aActor); - - RefPtr actor = - dont_AddRef(static_cast(aActor)); - return true; -} - -IPCResult RemoteWorkerControllerParent::RecvExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs, ExecServiceWorkerOpResolver&& aResolve) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mIPCActive); - MOZ_ASSERT(mRemoteWorkerController); - - mRemoteWorkerController->ExecServiceWorkerOp(std::move(aArgs)) - ->Then(GetCurrentThreadSerialEventTarget(), __func__, - [resolve = std::move(aResolve)]( - ServiceWorkerOpPromise::ResolveOrRejectValue&& aResult) { - if (NS_WARN_IF(aResult.IsReject())) { - MOZ_ASSERT(NS_FAILED(aResult.RejectValue())); - resolve(aResult.RejectValue()); - return; - } - - resolve(aResult.ResolveValue()); - }); - - return IPC_OK(); -} - -IPCResult RemoteWorkerControllerParent::RecvShutdown( - ShutdownResolver&& aResolve) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(mIPCActive); - MOZ_ASSERT(mRemoteWorkerController); - - mIPCActive = false; - - mRemoteWorkerController->Shutdown(); - mRemoteWorkerController = nullptr; - - aResolve(true); - - return IPC_OK(); -} - -IPCResult RemoteWorkerControllerParent::Recv__delete__() { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(!mIPCActive); - MOZ_ASSERT(!mRemoteWorkerController); - - return IPC_OK(); -} - -void RemoteWorkerControllerParent::ActorDestroy(ActorDestroyReason aReason) { - AssertIsOnBackgroundThread(); - - if (NS_WARN_IF(mIPCActive)) { - mIPCActive = false; - } - - if (NS_WARN_IF(mRemoteWorkerController)) { - mRemoteWorkerController->Shutdown(); - mRemoteWorkerController = nullptr; - } -} - -void RemoteWorkerControllerParent::CreationFailed() { - AssertIsOnBackgroundThread(); - - if (!mIPCActive) { - return; - } - - Unused << SendCreationFailed(); -} - -void RemoteWorkerControllerParent::CreationSucceeded() { - AssertIsOnBackgroundThread(); - - if (!mIPCActive) { - return; - } - - Unused << SendCreationSucceeded(); -} - -void RemoteWorkerControllerParent::ErrorReceived(const ErrorValue& aValue) { - AssertIsOnBackgroundThread(); - - if (!mIPCActive) { - return; - } - - Unused << SendErrorReceived(aValue); -} - -void RemoteWorkerControllerParent::Terminated() { - AssertIsOnBackgroundThread(); - - if (!mIPCActive) { - return; - } - - Unused << SendTerminated(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/workers/remoteworkers/RemoteWorkerControllerParent.h b/dom/workers/remoteworkers/RemoteWorkerControllerParent.h deleted file mode 100644 index 10a98472bbe5..000000000000 --- a/dom/workers/remoteworkers/RemoteWorkerControllerParent.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_dom_remoteworkercontrollerparent_h__ -#define mozilla_dom_remoteworkercontrollerparent_h__ - -#include - -#include "nsISupportsImpl.h" - -#include "RemoteWorkerController.h" -#include "mozilla/RefPtr.h" -#include "mozilla/dom/PRemoteWorkerControllerParent.h" - -namespace mozilla { -namespace dom { - -class RemoteWorkerControllerParent final : public PRemoteWorkerControllerParent, - public RemoteWorkerObserver { - friend class PRemoteWorkerControllerParent; - - public: - NS_INLINE_DECL_REFCOUNTING(RemoteWorkerControllerParent, override) - - explicit RemoteWorkerControllerParent( - const RemoteWorkerData& aRemoteWorkerData); - - // Returns the corresponding RemoteWorkerParent (if any). - RefPtr GetRemoteWorkerParent() const; - - void MaybeSendSetServiceWorkerSkipWaitingFlag( - std::function&& aCallback); - - private: - ~RemoteWorkerControllerParent(); - - PFetchEventOpParent* AllocPFetchEventOpParent( - const ServiceWorkerFetchEventOpArgs& aArgs); - - mozilla::ipc::IPCResult RecvPFetchEventOpConstructor( - PFetchEventOpParent* aActor, - const ServiceWorkerFetchEventOpArgs& aArgs) override; - - bool DeallocPFetchEventOpParent(PFetchEventOpParent* aActor); - - mozilla::ipc::IPCResult RecvExecServiceWorkerOp( - ServiceWorkerOpArgs&& aArgs, ExecServiceWorkerOpResolver&& aResolve); - - mozilla::ipc::IPCResult RecvShutdown(ShutdownResolver&& aResolve); - - mozilla::ipc::IPCResult Recv__delete__() override; - - void ActorDestroy(ActorDestroyReason aReason) override; - - void CreationFailed() override; - - void CreationSucceeded() override; - - void ErrorReceived(const ErrorValue& aValue) override; - - void Terminated() override; - - RefPtr mRemoteWorkerController; - - bool mIPCActive = true; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_remoteworkercontrollerparent_h__ diff --git a/dom/workers/remoteworkers/RemoteWorkerManager.cpp b/dom/workers/remoteworkers/RemoteWorkerManager.cpp index 1c43ad23f320..3fcc23a76251 100644 --- a/dom/workers/remoteworkers/RemoteWorkerManager.cpp +++ b/dom/workers/remoteworkers/RemoteWorkerManager.cpp @@ -6,19 +6,11 @@ #include "RemoteWorkerManager.h" -#include - -#include "mozilla/RefPtr.h" -#include "mozilla/ScopeExit.h" -#include "mozilla/SystemGroup.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/RemoteWorkerParent.h" #include "mozilla/ipc/BackgroundParent.h" #include "mozilla/ipc/PBackgroundParent.h" -#include "nsCOMPtr.h" #include "nsIXULRuntime.h" -#include "nsTArray.h" -#include "nsThreadUtils.h" #include "RemoteWorkerServiceParent.h" namespace mozilla { @@ -33,17 +25,12 @@ namespace { // actors. RemoteWorkerManager* sRemoteWorkerManager; -bool IsServiceWorker(const RemoteWorkerData& aData) { - return aData.serviceWorkerData().type() == - OptionalServiceWorkerData::TServiceWorkerData; -} - } // namespace /* static */ already_AddRefed RemoteWorkerManager::GetOrCreate() { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); if (!sRemoteWorkerManager) { sRemoteWorkerManager = new RemoteWorkerManager(); @@ -54,21 +41,21 @@ already_AddRefed RemoteWorkerManager::GetOrCreate() { } RemoteWorkerManager::RemoteWorkerManager() : mParentActor(nullptr) { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(!sRemoteWorkerManager); } RemoteWorkerManager::~RemoteWorkerManager() { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(sRemoteWorkerManager == this); sRemoteWorkerManager = nullptr; } void RemoteWorkerManager::RegisterActor(RemoteWorkerServiceParent* aActor) { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aActor); if (!BackgroundParent::IsOtherProcessActor(aActor->Manager())) { @@ -96,8 +83,8 @@ void RemoteWorkerManager::RegisterActor(RemoteWorkerServiceParent* aActor) { } void RemoteWorkerManager::UnregisterActor(RemoteWorkerServiceParent* aActor) { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aActor); if (aActor == mParentActor) { @@ -111,8 +98,8 @@ void RemoteWorkerManager::UnregisterActor(RemoteWorkerServiceParent* aActor) { void RemoteWorkerManager::Launch(RemoteWorkerController* aController, const RemoteWorkerData& aData, base::ProcessId aProcessId) { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); RemoteWorkerServiceParent* targetActor = SelectTargetActor(aData, aProcessId); @@ -133,20 +120,14 @@ void RemoteWorkerManager::Launch(RemoteWorkerController* aController, return; } - /** - * If a target actor for a Service Worker has been selected, the actor has - * already been registered with the corresponding ContentParent (see - * `SelectTargetActorForServiceWorker()`). - */ - LaunchInternal(aController, targetActor, aData, IsServiceWorker(aData)); + LaunchInternal(aController, targetActor, aData); } void RemoteWorkerManager::LaunchInternal( RemoteWorkerController* aController, - RemoteWorkerServiceParent* aTargetActor, const RemoteWorkerData& aData, - bool aRemoteWorkerAlreadyRegistered) { - AssertIsInMainProcess(); + RemoteWorkerServiceParent* aTargetActor, const RemoteWorkerData& aData) { AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aController); MOZ_ASSERT(aTargetActor); MOZ_ASSERT(aTargetActor == mParentActor || @@ -159,7 +140,7 @@ void RemoteWorkerManager::LaunchInternal( return; } - workerActor->Initialize(aRemoteWorkerAlreadyRegistered); + workerActor->Initialize(); // This makes the link better the 2 actors. aController->SetWorkerActor(workerActor); @@ -176,75 +157,10 @@ void RemoteWorkerManager::AsyncCreationFailed( NS_DispatchToCurrentThread(r.forget()); } -/** - * Service Workers can spawn even when their registering page/script isn't - * active (e.g. push notifications), so we don't attempt to spawn the worker - * in its registering script's process. We search linearly and choose the - * search's starting position randomly. - * - * Spawning the workers in a random process makes the process selection criteria - * a little tricky, as a candidate process may imminently shutdown due to a - * remove worker actor unregistering - * (see `ContentParent::UnregisterRemoveWorkerActor`). - * - * In `ContentParent::MaybeAsyncSendShutDownMessage` we only dispatch a runnable - * to call `ContentParent::ShutDownProcess` if there are no registered remote - * worker actors, and we ensure that the check for the number of registered - * actors and the dispatching of the runnable are atomic. That happens on the - * main thread, so here on the background thread, while - * `ContentParent::mRemoteWorkerActorData` is locked, if `mCount` > 0, we can - * register a remote worker actor "early" and guarantee that the corresponding - * content process will not shutdown. - */ -RemoteWorkerServiceParent* -RemoteWorkerManager::SelectTargetActorForServiceWorker() const { - AssertIsInMainProcess(); - AssertIsOnBackgroundThread(); - MOZ_ASSERT(!mChildActors.IsEmpty()); - - nsTArray> contentParents; - - auto scopeExit = MakeScopeExit([&] { - nsCOMPtr r = NS_NewRunnableFunction( - __func__, - [doomed = std::move(contentParents)]() mutable { doomed.Clear(); }); - - SystemGroup::Dispatch(TaskCategory::Other, r.forget()); - }); - - uint32_t random = uint32_t(rand() % mChildActors.Length()); - uint32_t i = random; - - do { - auto actor = mChildActors[i]; - PBackgroundParent* bgParent = actor->Manager(); - MOZ_ASSERT(bgParent); - - RefPtr contentParent = - BackgroundParent::GetContentParent(bgParent); - - auto scopeExit = MakeScopeExit( - [&] { contentParents.AppendElement(std::move(contentParent)); }); - - if (contentParent->GetRemoteType().EqualsLiteral(DEFAULT_REMOTE_TYPE)) { - auto lock = contentParent->mRemoteWorkerActorData.Lock(); - - if (lock->mCount || !lock->mShutdownStarted) { - ++lock->mCount; - return actor; - } - } - - i = (++i % mChildActors.Length()); - } while (i != random); - - return nullptr; -} - RemoteWorkerServiceParent* RemoteWorkerManager::SelectTargetActor( const RemoteWorkerData& aData, base::ProcessId aProcessId) { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); // System principal workers should run on the parent process. if (aData.principalInfo().type() == PrincipalInfo::TSystemPrincipalInfo) { @@ -265,10 +181,6 @@ RemoteWorkerServiceParent* RemoteWorkerManager::SelectTargetActor( return nullptr; } - if (IsServiceWorker(aData)) { - return SelectTargetActorForServiceWorker(); - } - for (RemoteWorkerServiceParent* actor : mChildActors) { // Let's execute the RemoteWorker on the same process. if (actor->OtherPid() == aProcessId) { @@ -282,8 +194,8 @@ RemoteWorkerServiceParent* RemoteWorkerManager::SelectTargetActor( } void RemoteWorkerManager::LaunchNewContentProcess() { - AssertIsInMainProcess(); AssertIsOnBackgroundThread(); + MOZ_ASSERT(XRE_IsParentProcess()); // This runnable will spawn a new process if it doesn't exist yet. nsCOMPtr r = diff --git a/dom/workers/remoteworkers/RemoteWorkerManager.h b/dom/workers/remoteworkers/RemoteWorkerManager.h index 509f62271c4d..2fe808c6bcfa 100644 --- a/dom/workers/remoteworkers/RemoteWorkerManager.h +++ b/dom/workers/remoteworkers/RemoteWorkerManager.h @@ -39,12 +39,9 @@ class RemoteWorkerManager final { RemoteWorkerServiceParent* SelectTargetActor(const RemoteWorkerData& aData, base::ProcessId aProcessId); - RemoteWorkerServiceParent* SelectTargetActorForServiceWorker() const; - void LaunchInternal(RemoteWorkerController* aController, RemoteWorkerServiceParent* aTargetActor, - const RemoteWorkerData& aData, - bool aRemoteWorkerAlreadyRegistered = false); + const RemoteWorkerData& aData); void LaunchNewContentProcess(); diff --git a/dom/workers/remoteworkers/RemoteWorkerParent.cpp b/dom/workers/remoteworkers/RemoteWorkerParent.cpp index 2f64588c4e6c..81ae3765fa19 100644 --- a/dom/workers/remoteworkers/RemoteWorkerParent.cpp +++ b/dom/workers/remoteworkers/RemoteWorkerParent.cpp @@ -7,7 +7,6 @@ #include "RemoteWorkerParent.h" #include "RemoteWorkerController.h" #include "mozilla/dom/ContentParent.h" -#include "mozilla/dom/PFetchEventOpProxyParent.h" #include "mozilla/ipc/BackgroundParent.h" #include "mozilla/Unused.h" #include "nsProxyRelease.h" @@ -53,14 +52,12 @@ RemoteWorkerParent::~RemoteWorkerParent() { MOZ_ASSERT(XRE_IsParentProcess()); } -void RemoteWorkerParent::Initialize(bool aAlreadyRegistered) { +void RemoteWorkerParent::Initialize() { RefPtr parent = BackgroundParent::GetContentParent(Manager()); // Parent is null if the child actor runs on the parent process. if (parent) { - if (!aAlreadyRegistered) { - parent->RegisterRemoteWorkerActor(); - } + parent->RegisterRemoteWorkerActor(); nsCOMPtr target = SystemGroup::EventTargetFor(TaskCategory::Other); @@ -70,22 +67,6 @@ void RemoteWorkerParent::Initialize(bool aAlreadyRegistered) { } } -PFetchEventOpProxyParent* RemoteWorkerParent::AllocPFetchEventOpProxyParent( - const ServiceWorkerFetchEventOpArgs& aArgs) { - MOZ_CRASH("PFetchEventOpProxyParent actors must be manually constructed!"); - return nullptr; -} - -bool RemoteWorkerParent::DeallocPFetchEventOpProxyParent( - PFetchEventOpProxyParent* aActor) { - MOZ_ASSERT(XRE_IsParentProcess()); - AssertIsOnBackgroundThread(); - MOZ_ASSERT(aActor); - - delete aActor; - return true; -} - void RemoteWorkerParent::ActorDestroy(IProtocol::ActorDestroyReason) { AssertIsOnBackgroundThread(); MOZ_ASSERT(XRE_IsParentProcess()); @@ -103,7 +84,7 @@ void RemoteWorkerParent::ActorDestroy(IProtocol::ActorDestroyReason) { } if (mController) { - mController->NoteDeadWorkerActor(); + mController->ForgetActorAndTerminate(); mController = nullptr; } } @@ -136,17 +117,6 @@ IPCResult RemoteWorkerParent::RecvError(const ErrorValue& aValue) { return IPC_OK(); } -void RemoteWorkerParent::MaybeSendDelete() { - if (mDeleteSent) { - return; - } - - // For some reason, if the following two lines are swapped, ASan says there's - // a UAF... - mDeleteSent = true; - Unused << Send__delete__(this); -} - IPCResult RemoteWorkerParent::RecvClose() { AssertIsOnBackgroundThread(); MOZ_ASSERT(XRE_IsParentProcess()); @@ -155,8 +125,7 @@ IPCResult RemoteWorkerParent::RecvClose() { mController->WorkerTerminated(); } - MaybeSendDelete(); - + Unused << Send__delete__(this); return IPC_OK(); } @@ -167,22 +136,5 @@ void RemoteWorkerParent::SetController(RemoteWorkerController* aController) { mController = aController; } -IPCResult RemoteWorkerParent::RecvSetServiceWorkerSkipWaitingFlag( - SetServiceWorkerSkipWaitingFlagResolver&& aResolve) { - AssertIsOnBackgroundThread(); - MOZ_ASSERT(XRE_IsParentProcess()); - - if (mController) { - mController->SetServiceWorkerSkipWaitingFlag()->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [resolve = aResolve](bool /* unused */) { resolve(true); }, - [resolve = aResolve](nsresult /* unused */) { resolve(false); }); - } else { - aResolve(false); - } - - return IPC_OK(); -} - } // namespace dom } // namespace mozilla diff --git a/dom/workers/remoteworkers/RemoteWorkerParent.h b/dom/workers/remoteworkers/RemoteWorkerParent.h index 1f4b850562bd..1db6816ae4cb 100644 --- a/dom/workers/remoteworkers/RemoteWorkerParent.h +++ b/dom/workers/remoteworkers/RemoteWorkerParent.h @@ -22,20 +22,13 @@ class RemoteWorkerParent final : public PRemoteWorkerParent { RemoteWorkerParent(); - void Initialize(bool aAlreadyRegistered = false); + void Initialize(); void SetController(RemoteWorkerController* aController); - void MaybeSendDelete(); - private: ~RemoteWorkerParent(); - PFetchEventOpProxyParent* AllocPFetchEventOpProxyParent( - const ServiceWorkerFetchEventOpArgs& aArgs); - - bool DeallocPFetchEventOpProxyParent(PFetchEventOpProxyParent* aActor); - void ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override; mozilla::ipc::IPCResult RecvError(const ErrorValue& aValue); @@ -44,10 +37,6 @@ class RemoteWorkerParent final : public PRemoteWorkerParent { mozilla::ipc::IPCResult RecvCreated(const bool& aStatus); - mozilla::ipc::IPCResult RecvSetServiceWorkerSkipWaitingFlag( - SetServiceWorkerSkipWaitingFlagResolver&& aResolve); - - bool mDeleteSent = false; RefPtr mController; }; diff --git a/dom/workers/remoteworkers/RemoteWorkerTypes.ipdlh b/dom/workers/remoteworkers/RemoteWorkerTypes.ipdlh index f7475de74001..610e82f222f7 100644 --- a/dom/workers/remoteworkers/RemoteWorkerTypes.ipdlh +++ b/dom/workers/remoteworkers/RemoteWorkerTypes.ipdlh @@ -3,37 +3,16 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ include ClientIPCTypes; -include IPCServiceWorkerDescriptor; -include IPCServiceWorkerRegistrationDescriptor; include PBackgroundSharedTypes; include URIParams; include DOMTypes; -using struct IPC::Permission from "mozilla/net/NeckoMessageUtils.h"; using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; using mozilla::StorageAccess from "mozilla/dom/ClientIPCUtils.h"; namespace mozilla { namespace dom { -struct KeyAndPermissions { - nsCString key; - Permission[] permissions; -}; - -struct ServiceWorkerData { - KeyAndPermissions[] permissionsByKey; - IPCServiceWorkerDescriptor descriptor; - IPCServiceWorkerRegistrationDescriptor registrationDescriptor; - nsString cacheName; - uint32_t loadFlags; -}; - -union OptionalServiceWorkerData { - void_t; - ServiceWorkerData; -}; - struct RemoteWorkerData { // This should only be used for devtools. @@ -66,7 +45,7 @@ struct RemoteWorkerData StorageAccess storageAccess; - OptionalServiceWorkerData serviceWorkerData; + bool isSharedWorker; }; // ErrorData/ErrorDataNote correspond to WorkerErrorReport/WorkerErrorNote diff --git a/dom/workers/remoteworkers/moz.build b/dom/workers/remoteworkers/moz.build index a512f8ed53f6..1460addee6dd 100644 --- a/dom/workers/remoteworkers/moz.build +++ b/dom/workers/remoteworkers/moz.build @@ -7,8 +7,6 @@ EXPORTS.mozilla.dom += [ 'RemoteWorkerChild.h', 'RemoteWorkerController.h', - 'RemoteWorkerControllerChild.h', - 'RemoteWorkerControllerParent.h', 'RemoteWorkerParent.h', 'RemoteWorkerService.h', 'RemoteWorkerServiceChild.h', @@ -18,8 +16,6 @@ EXPORTS.mozilla.dom += [ UNIFIED_SOURCES += [ 'RemoteWorkerChild.cpp', 'RemoteWorkerController.cpp', - 'RemoteWorkerControllerChild.cpp', - 'RemoteWorkerControllerParent.cpp', 'RemoteWorkerManager.cpp', 'RemoteWorkerParent.cpp', 'RemoteWorkerService.cpp', @@ -28,13 +24,11 @@ UNIFIED_SOURCES += [ ] LOCAL_INCLUDES += [ - '/dom/serviceworkers', '/xpcom/build', ] IPDL_SOURCES += [ 'PRemoteWorker.ipdl', - 'PRemoteWorkerController.ipdl', 'PRemoteWorkerService.ipdl', 'RemoteWorkerTypes.ipdlh', ] diff --git a/dom/workers/sharedworkers/SharedWorker.cpp b/dom/workers/sharedworkers/SharedWorker.cpp index a51098432af4..a95a87136905 100644 --- a/dom/workers/sharedworkers/SharedWorker.cpp +++ b/dom/workers/sharedworkers/SharedWorker.cpp @@ -195,7 +195,7 @@ already_AddRefed SharedWorker::Constructor( nsString(aScriptURL), baseURL, resolvedScriptURL, name, loadingPrincipalInfo, principalInfo, storagePrincipalInfo, loadInfo.mDomain, isSecureContext, ipcClientInfo, loadInfo.mReferrerInfo, - storageAllowed, void_t() /* OptionalServiceWorkerData */); + storageAllowed, true /* sharedWorker */); PSharedWorkerChild* pActor = actorChild->SendPSharedWorkerConstructor( remoteWorkerData, loadInfo.mWindowID, portIdentifier); diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index 4b20ed6ba73b..f3271a047896 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -35,7 +35,6 @@ #include "mozilla/dom/IPCBlobUtils.h" #include "mozilla/dom/quota/PQuotaChild.h" #include "mozilla/dom/RemoteWorkerChild.h" -#include "mozilla/dom/RemoteWorkerControllerChild.h" #include "mozilla/dom/RemoteWorkerServiceChild.h" #include "mozilla/dom/SharedWorkerChild.h" #include "mozilla/dom/StorageIPC.h" @@ -325,7 +324,7 @@ bool BackgroundChildImpl::DeallocPPendingIPCBlobChild( dom::PRemoteWorkerChild* BackgroundChildImpl::AllocPRemoteWorkerChild( const RemoteWorkerData& aData) { - RefPtr agent = new dom::RemoteWorkerChild(aData); + RefPtr agent = new dom::RemoteWorkerChild(); return agent.forget().take(); } @@ -343,23 +342,6 @@ bool BackgroundChildImpl::DeallocPRemoteWorkerChild( return true; } -dom::PRemoteWorkerControllerChild* -BackgroundChildImpl::AllocPRemoteWorkerControllerChild( - const dom::RemoteWorkerData& aRemoteWorkerData) { - MOZ_CRASH( - "PRemoteWorkerControllerChild actors must be manually constructed!"); - return nullptr; -} - -bool BackgroundChildImpl::DeallocPRemoteWorkerControllerChild( - dom::PRemoteWorkerControllerChild* aActor) { - MOZ_ASSERT(aActor); - - RefPtr actor = - dont_AddRef(static_cast(aActor)); - return true; -} - dom::PRemoteWorkerServiceChild* BackgroundChildImpl::AllocPRemoteWorkerServiceChild() { RefPtr agent = diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h index b1107d386e35..2f34499dff92 100644 --- a/ipc/glue/BackgroundChildImpl.h +++ b/ipc/glue/BackgroundChildImpl.h @@ -141,13 +141,6 @@ class BackgroundChildImpl : public PBackgroundChild { virtual bool DeallocPRemoteWorkerChild( mozilla::dom::PRemoteWorkerChild* aActor) override; - virtual mozilla::dom::PRemoteWorkerControllerChild* - AllocPRemoteWorkerControllerChild( - const mozilla::dom::RemoteWorkerData& aRemoteWorkerData) override; - - virtual bool DeallocPRemoteWorkerControllerChild( - mozilla::dom::PRemoteWorkerControllerChild* aActor) override; - virtual mozilla::dom::PRemoteWorkerServiceChild* AllocPRemoteWorkerServiceChild() override; diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index 811d079b559b..daf73ad88cb4 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -40,7 +40,6 @@ #include "mozilla/dom/quota/ActorsParent.h" #include "mozilla/dom/simpledb/ActorsParent.h" #include "mozilla/dom/RemoteWorkerParent.h" -#include "mozilla/dom/RemoteWorkerControllerParent.h" #include "mozilla/dom/RemoteWorkerServiceParent.h" #include "mozilla/dom/ReportingHeader.h" #include "mozilla/dom/SharedWorkerParent.h" @@ -498,29 +497,6 @@ bool BackgroundParentImpl::DeallocPRemoteWorkerParent( return true; } -dom::PRemoteWorkerControllerParent* -BackgroundParentImpl::AllocPRemoteWorkerControllerParent( - const dom::RemoteWorkerData& aRemoteWorkerData) { - RefPtr actor = - new dom::RemoteWorkerControllerParent(aRemoteWorkerData); - return actor.forget().take(); -} - -IPCResult BackgroundParentImpl::RecvPRemoteWorkerControllerConstructor( - dom::PRemoteWorkerControllerParent* aActor, - const dom::RemoteWorkerData& aRemoteWorkerData) { - MOZ_ASSERT(aActor); - - return IPC_OK(); -} - -bool BackgroundParentImpl::DeallocPRemoteWorkerControllerParent( - dom::PRemoteWorkerControllerParent* aActor) { - RefPtr actor = - dont_AddRef(static_cast(aActor)); - return true; -} - mozilla::dom::PRemoteWorkerServiceParent* BackgroundParentImpl::AllocPRemoteWorkerServiceParent() { return new mozilla::dom::RemoteWorkerServiceParent(); diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index 98d8148a7052..654912fdcbfa 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -171,17 +171,6 @@ class BackgroundParentImpl : public PBackgroundParent { virtual bool DeallocPRemoteWorkerParent(PRemoteWorkerParent* aActor) override; - virtual mozilla::dom::PRemoteWorkerControllerParent* - AllocPRemoteWorkerControllerParent( - const mozilla::dom::RemoteWorkerData& aRemoteWorkerData) override; - - virtual mozilla::ipc::IPCResult RecvPRemoteWorkerControllerConstructor( - mozilla::dom::PRemoteWorkerControllerParent* aActor, - const mozilla::dom::RemoteWorkerData& aRemoteWorkerData) override; - - virtual bool DeallocPRemoteWorkerControllerParent( - mozilla::dom::PRemoteWorkerControllerParent* aActor) override; - virtual mozilla::dom::PRemoteWorkerServiceParent* AllocPRemoteWorkerServiceParent() override; diff --git a/ipc/glue/IPCStreamSource.cpp b/ipc/glue/IPCStreamSource.cpp index 33d007bb914f..eecca5beb07a 100644 --- a/ipc/glue/IPCStreamSource.cpp +++ b/ipc/glue/IPCStreamSource.cpp @@ -6,7 +6,6 @@ #include "IPCStreamSource.h" #include "BackgroundParent.h" // for AssertIsOnBackgroundThread -#include "mozilla/dom/RemoteWorkerService.h" #include "mozilla/webrender/WebRenderTypes.h" #include "nsIAsyncInputStream.h" #include "nsICancelableRunnable.h" @@ -114,12 +113,11 @@ bool IPCStreamSource::Initialize() { } // A source can be used on any thread, but we only support IPCStream on - // main thread, Workers, Worker Launcher, and PBackground thread right now. - // This is due to the requirement that the thread be guaranteed to live long - // enough to receive messages. We can enforce this guarantee with a - // StrongWorkerRef on worker threads, but not other threads. Main-thread, - // PBackground, and Worker Launcher threads do not need anything special in - // order to be kept alive. + // main thread, Workers and PBackground thread right now. This is due + // to the requirement that the thread be guaranteed to live long enough to + // receive messages. We can enforce this guarantee with a StrongWorkerRef on + // worker threads, but not other threads. Main-thread and PBackground thread + // do not need anything special in order to be kept alive. if (!NS_IsMainThread()) { if (const auto workerPrivate = dom::GetCurrentThreadWorkerPrivate()) { RefPtr workerRef = @@ -131,9 +129,7 @@ bool IPCStreamSource::Initialize() { mWorkerRef = std::move(workerRef); } else { - MOZ_DIAGNOSTIC_ASSERT( - IsOnBackgroundThread() || - dom::RemoteWorkerService::Thread()->IsOnCurrentThread()); + AssertIsOnBackgroundThread(); } } @@ -243,13 +239,6 @@ void IPCStreamSource::OnStreamReady(Callback* aCallback) { MOZ_ASSERT(aCallback == mCallback); mCallback->ClearSource(); mCallback = nullptr; - - // Possibly closed if this callback is (indirectly) called by - // IPCStreamSourceParent::RecvRequestClose(). - if (mState == eClosed) { - return; - } - DoRead(); } diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 8804614fa133..4acb3bf1ab41 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -27,7 +27,6 @@ include protocol PIPCBlobInputStream; include protocol PMediaTransport; include protocol PPendingIPCBlob; include protocol PRemoteWorker; -include protocol PRemoteWorkerController; include protocol PRemoteWorkerService; include protocol PSharedWorker; include protocol PTemporaryIPCBlob; @@ -95,7 +94,6 @@ sync protocol PBackground manages PMediaTransport; manages PPendingIPCBlob; manages PRemoteWorker; - manages PRemoteWorkerController; manages PRemoteWorkerService; manages PSharedWorker; manages PTemporaryIPCBlob; @@ -218,8 +216,6 @@ parent: async PServiceWorker(IPCServiceWorkerDescriptor aDescriptor); - async PRemoteWorkerController(RemoteWorkerData aData); - async PRemoteWorkerService(); async PServiceWorkerContainer(); diff --git a/netwerk/base/nsBufferedStreams.cpp b/netwerk/base/nsBufferedStreams.cpp index 3c7f37a6ecab..4b0ad440cca9 100644 --- a/netwerk/base/nsBufferedStreams.cpp +++ b/netwerk/base/nsBufferedStreams.cpp @@ -9,7 +9,6 @@ #include "nsStreamUtils.h" #include "nsNetCID.h" #include "nsIClassInfoImpl.h" -#include "mozilla/DebugOnly.h" #include "mozilla/ipc/InputStreamUtils.h" #include @@ -39,7 +38,6 @@ static struct { #endif using namespace mozilla::ipc; -using mozilla::DebugOnly; using mozilla::Maybe; using mozilla::MutexAutoLock; using mozilla::Nothing; @@ -278,16 +276,7 @@ NS_IMPL_CLASSINFO(nsBufferedInputStream, nullptr, nsIClassInfo::THREADSAFE, NS_BUFFEREDINPUTSTREAM_CID) NS_INTERFACE_MAP_BEGIN(nsBufferedInputStream) - // Unfortunately there isn't a macro that combines ambiguous and conditional, - // and as far as I can tell, no other class would need such a macro. - if (mIsAsyncInputStream && aIID.Equals(NS_GET_IID(nsIInputStream))) { - foundInterface = - static_cast(static_cast(this)); - } else if (!mIsAsyncInputStream && aIID.Equals(NS_GET_IID(nsIInputStream))) { - foundInterface = static_cast( - static_cast(this)); - } else - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBufferedInputStream) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIInputStream, nsIBufferedInputStream) NS_INTERFACE_MAP_ENTRY(nsIBufferedInputStream) NS_INTERFACE_MAP_ENTRY(nsIStreamBufferAccess) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, @@ -359,19 +348,6 @@ nsBufferedInputStream::Init(nsIInputStream* stream, uint32_t bufferSize) { return NS_OK; } -already_AddRefed nsBufferedInputStream::GetInputStream() { - // A non-null mStream implies Init() has been called. - MOZ_ASSERT(mStream); - - nsIInputStream* out = nullptr; - DebugOnly rv = QueryInterface(NS_GET_IID(nsIInputStream), - reinterpret_cast(&out)); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - MOZ_ASSERT(out); - - return already_AddRefed(out); -} - NS_IMETHODIMP nsBufferedInputStream::Close() { nsresult rv1 = NS_OK, rv2; @@ -788,9 +764,7 @@ nsBufferedInputStream::Clone(nsIInputStream** aResult) { rv = bis->Init(clonedStream, mBufferSize); NS_ENSURE_SUCCESS(rv, rv); - *aResult = - static_cast(bis.get())->GetInputStream().take(); - + bis.forget(aResult); return NS_OK; } diff --git a/netwerk/base/nsBufferedStreams.h b/netwerk/base/nsBufferedStreams.h index a83afee75691..e51363bfdcc4 100644 --- a/netwerk/base/nsBufferedStreams.h +++ b/netwerk/base/nsBufferedStreams.h @@ -92,22 +92,6 @@ class nsBufferedInputStream final : public nsBufferedStream, nsIInputStream* Source() { return (nsIInputStream*)mStream.get(); } - /** - * If there's a reference/pointer to an nsBufferedInputStream BEFORE calling - * Init() AND the intent is to ultimately convert/assign that - * reference/pointer to an nsIInputStream, DO NOT use that initial - * reference/pointer. Instead, use the value of QueryInterface-ing to an - * nsIInputStream (and, again, the QueryInterface must be performed after - * Init()). This is because nsBufferedInputStream has multiple underlying - * nsIInputStreams (one from nsIBufferedInputStream and one from - * nsIAsyncInputStream), and the correct base nsIInputStream to use will be - * unknown until the final value of mIsAsyncInputStream is set in Init(). - * - * This method, however, does just that but also hides the QI details and - * will assert if called before Init(). - */ - already_AddRefed GetInputStream(); - protected: virtual ~nsBufferedInputStream() = default; diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index 24126a53226d..3ad499054d6e 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -30,7 +30,6 @@ #include "nsIAuthPrompt2.h" #include "nsIAuthPromptAdapterFactory.h" #include "nsIBufferedStreams.h" -#include "nsBufferedStreams.h" #include "nsIChannelEventSink.h" #include "nsIContentSniffer.h" #include "mozilla/dom/Document.h" @@ -1270,9 +1269,7 @@ MOZ_MUST_USE nsresult NS_NewBufferedInputStream( if (NS_SUCCEEDED(rv)) { rv = in->Init(inputStream, aBufferSize); if (NS_SUCCEEDED(rv)) { - *aResult = static_cast(in.get()) - ->GetInputStream() - .take(); + in.forget(aResult); } } return rv; diff --git a/netwerk/ipc/NeckoMessageUtils.h b/netwerk/ipc/NeckoMessageUtils.h index 919363b349ab..f87b9580a12f 100644 --- a/netwerk/ipc/NeckoMessageUtils.h +++ b/netwerk/ipc/NeckoMessageUtils.h @@ -37,12 +37,6 @@ struct Permission { capability(aCapability), expireType(aExpireType), expireTime(aExpireTime) {} - - bool operator==(const Permission& aOther) const { - return aOther.origin == origin && aOther.type == type && - aOther.capability == capability && aOther.expireType == expireType && - aOther.expireTime == expireTime; - } }; template <> diff --git a/testing/web-platform/meta/service-workers/service-worker/multiple-update.https.html.ini b/testing/web-platform/meta/service-workers/service-worker/multiple-update.https.html.ini index 894ead0dbf6d..86db4f2d01cc 100644 --- a/testing/web-platform/meta/service-workers/service-worker/multiple-update.https.html.ini +++ b/testing/web-platform/meta/service-workers/service-worker/multiple-update.https.html.ini @@ -1 +1,8 @@ [multiple-update.https.html] + disabled: + if sw-e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=1543316 + + [Trigger multiple updates.] + expected: + if sw-e10s: TIMEOUT + diff --git a/testing/web-platform/meta/service-workers/service-worker/update-not-allowed.https.html.ini b/testing/web-platform/meta/service-workers/service-worker/update-not-allowed.https.html.ini index 6f3fd0d956c0..dc05a9049b29 100644 --- a/testing/web-platform/meta/service-workers/service-worker/update-not-allowed.https.html.ini +++ b/testing/web-platform/meta/service-workers/service-worker/update-not-allowed.https.html.ini @@ -3,3 +3,11 @@ if (os == "android") and not e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=1499972 if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview) expected: ERROR + [ServiceWorkerRegistration.update() from active service worker succeeds while installing service worker.] + expected: + if sw-e10s: TIMEOUT + FAIL + + [ServiceWorkerRegistration.update() from client succeeds while installing service worker.] + expected: FAIL + diff --git a/testing/web-platform/tests/service-workers/service-worker/resources/update-during-installation-worker.js b/testing/web-platform/tests/service-workers/service-worker/resources/update-during-installation-worker.js index f1997bd824e8..3f89881c0438 100644 --- a/testing/web-platform/tests/service-workers/service-worker/resources/update-during-installation-worker.js +++ b/testing/web-platform/tests/service-workers/service-worker/resources/update-during-installation-worker.js @@ -14,9 +14,6 @@ addEventListener('install', event => { }); addEventListener('message', event => { - let resolveWaitUntil; - event.waitUntil(new Promise(resolve => { resolveWaitUntil = resolve; })); - // Use a dedicated MessageChannel for every request so senders can wait for // individual requests to finish, and concurrent requests (to different // workers) don't cause race conditions. @@ -26,13 +23,13 @@ addEventListener('message', event => { case 'awaitInstallEvent': installEventFired.then(() => { port.postMessage('installEventFired'); - }).finally(resolveWaitUntil); + }); break; case 'finishInstall': installFinished.then(() => { port.postMessage('installFinished'); - }).finally(resolveWaitUntil); + }); finishInstall(); break; @@ -47,14 +44,13 @@ addEventListener('message', event => { success: false, exception: exception.name, }); - }).finally(resolveWaitUntil); + }); port.postMessage(channel.port1, [channel.port1]); break; } default: port.postMessage('Unexpected command ' + event.data); - resolveWaitUntil(); break; } };