/* -*- 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 "BackgroundParentImpl.h" #include "BroadcastChannelParent.h" #ifdef MOZ_WEBRTC # include "CamerasParent.h" #endif #include "mozilla/Assertions.h" #include "mozilla/RDDProcessManager.h" #include "mozilla/ipc/UtilityProcessManager.h" #include "mozilla/RemoteDecodeUtils.h" #include "mozilla/RefPtr.h" #include "mozilla/dom/BackgroundSessionStorageServiceParent.h" #include "mozilla/dom/ClientManagerActors.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/DOMTypes.h" #include "mozilla/dom/EndpointForReportParent.h" #include "mozilla/dom/FetchParent.h" #include "mozilla/dom/FileCreatorParent.h" #include "mozilla/dom/FileSystemManagerParentFactory.h" #include "mozilla/dom/FileSystemRequestParent.h" #include "mozilla/dom/GamepadEventChannelParent.h" #include "mozilla/dom/GamepadTestChannelParent.h" #include "mozilla/dom/MIDIManagerParent.h" #include "mozilla/dom/MIDIPlatformService.h" #include "mozilla/dom/MIDIPortParent.h" #include "mozilla/dom/MediaTransportParent.h" #include "mozilla/dom/MessagePortParent.h" #include "mozilla/dom/PGamepadEventChannelParent.h" #include "mozilla/dom/PGamepadTestChannelParent.h" #include "mozilla/dom/RemoteWorkerControllerParent.h" #include "mozilla/dom/RemoteWorkerServiceParent.h" #include "mozilla/dom/ReportingHeader.h" #include "mozilla/dom/ServiceWorkerActors.h" #include "mozilla/dom/ServiceWorkerContainerParent.h" #include "mozilla/dom/ServiceWorkerManagerParent.h" #include "mozilla/dom/ServiceWorkerParent.h" #include "mozilla/dom/ServiceWorkerRegistrar.h" #include "mozilla/dom/ServiceWorkerRegistrationParent.h" #include "mozilla/dom/SessionStorageManager.h" #include "mozilla/dom/SharedWorkerParent.h" #include "mozilla/dom/StorageActivityService.h" #include "mozilla/dom/StorageIPC.h" #include "mozilla/dom/TemporaryIPCBlobParent.h" #include "mozilla/dom/WebAuthnTransactionParent.h" #include "mozilla/dom/WebTransportParent.h" #include "mozilla/dom/cache/ActorUtils.h" #include "mozilla/dom/indexedDB/ActorsParent.h" #include "mozilla/dom/locks/LockManagerParent.h" #include "mozilla/dom/localstorage/ActorsParent.h" #include "mozilla/dom/network/UDPSocketParent.h" #include "mozilla/dom/quota/ActorsParent.h" #include "mozilla/dom/simpledb/ActorsParent.h" #include "mozilla/dom/VsyncParent.h" #include "mozilla/ipc/BackgroundParent.h" #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/IdleSchedulerParent.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" #include "mozilla/ipc/PBackgroundTestParent.h" #include "mozilla/net/BackgroundDataBridgeParent.h" #include "mozilla/net/HttpBackgroundChannelParent.h" #include "mozilla/net/HttpConnectionMgrParent.h" #include "mozilla/net/WebSocketConnectionParent.h" #include "mozilla/psm/IPCClientCertsParent.h" #include "mozilla/psm/SelectTLSClientAuthCertParent.h" #include "mozilla/psm/VerifySSLServerCertParent.h" #include "nsIHttpChannelInternal.h" #include "nsIPrincipal.h" #include "nsProxyRelease.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" using mozilla::AssertIsOnMainThread; using mozilla::dom::FileSystemRequestParent; using mozilla::dom::MessagePortParent; using mozilla::dom::MIDIManagerParent; using mozilla::dom::MIDIPlatformService; using mozilla::dom::MIDIPortParent; using mozilla::dom::PMessagePortParent; using mozilla::dom::PMIDIManagerParent; using mozilla::dom::PMIDIPortParent; using mozilla::dom::PServiceWorkerContainerParent; using mozilla::dom::PServiceWorkerParent; using mozilla::dom::PServiceWorkerRegistrationParent; using mozilla::dom::ServiceWorkerParent; using mozilla::dom::UDPSocketParent; using mozilla::dom::WebAuthnTransactionParent; using mozilla::dom::cache::PCacheParent; using mozilla::dom::cache::PCacheStorageParent; using mozilla::dom::cache::PCacheStreamControlParent; using mozilla::ipc::AssertIsOnBackgroundThread; namespace { class TestParent final : public mozilla::ipc::PBackgroundTestParent { friend class mozilla::ipc::BackgroundParentImpl; MOZ_COUNTED_DEFAULT_CTOR(TestParent) protected: ~TestParent() override { MOZ_COUNT_DTOR(TestParent); } public: void ActorDestroy(ActorDestroyReason aWhy) override; }; } // namespace namespace mozilla::ipc { using mozilla::dom::BroadcastChannelParent; using mozilla::dom::ContentParent; using mozilla::dom::ThreadsafeContentParentHandle; // A PBackgroundParent is a normal "content" actor if both the parent // side lives in the parent process and it either connects in-process, or // to a content process. static bool IsContentActor(PBackgroundParent* aActor) { return XRE_IsParentProcess() && (!BackgroundParent::IsOtherProcessActor(aActor) || BackgroundParent::GetContentParentHandle(aActor)); } // The parent side of socket bridge actors is always in the socket process. static bool IsSocketBridgeActor(PBackgroundParent* aActor) { return XRE_IsSocketProcess(); } // The parent side of socket actors is the parent process, and it must // not have a content process. static bool IsSocketActor(PBackgroundParent* aActor) { return XRE_IsParentProcess() && !IsContentActor(aActor); } BackgroundParentImpl::BackgroundParentImpl() { AssertIsInMainOrSocketProcess(); MOZ_COUNT_CTOR(mozilla::ipc::BackgroundParentImpl); } BackgroundParentImpl::~BackgroundParentImpl() { AssertIsInMainOrSocketProcess(); AssertIsOnMainThread(); MOZ_COUNT_DTOR(mozilla::ipc::BackgroundParentImpl); } void BackgroundParentImpl::ActorDestroy(ActorDestroyReason aWhy) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); } already_AddRefed BackgroundParentImpl::AllocPBackgroundDataBridgeParent( const uint64_t& aChannelID) { if (!IsSocketBridgeActor(this)) { return nullptr; } MOZ_ASSERT(XRE_IsSocketProcess(), "Should be in socket process"); AssertIsOnBackgroundThread(); RefPtr actor = new net::BackgroundDataBridgeParent(aChannelID); return actor.forget(); } BackgroundParentImpl::PBackgroundTestParent* BackgroundParentImpl::AllocPBackgroundTestParent(const nsACString& aTestArg) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return new TestParent(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundTestConstructor( PBackgroundTestParent* aActor, const nsACString& aTestArg) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); if (!PBackgroundTestParent::Send__delete__(aActor, aTestArg)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } bool BackgroundParentImpl::DeallocPBackgroundTestParent( PBackgroundTestParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); delete static_cast(aActor); return true; } auto BackgroundParentImpl::AllocPBackgroundIDBFactoryParent( const LoggingInfo& aLoggingInfo) -> already_AddRefed { if (!IsContentActor(this)) { return nullptr; } using mozilla::dom::indexedDB::AllocPBackgroundIDBFactoryParent; AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return AllocPBackgroundIDBFactoryParent(aLoggingInfo); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor( PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } using mozilla::dom::indexedDB::RecvPBackgroundIDBFactoryConstructor; AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); if (!RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } auto BackgroundParentImpl::AllocPBackgroundIndexedDBUtilsParent() -> PBackgroundIndexedDBUtilsParent* { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::indexedDB::AllocPBackgroundIndexedDBUtilsParent(); } bool BackgroundParentImpl::DeallocPBackgroundIndexedDBUtilsParent( PBackgroundIndexedDBUtilsParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::indexedDB::DeallocPBackgroundIndexedDBUtilsParent( aActor); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvFlushPendingFileDeletions() { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (!mozilla::dom::indexedDB::RecvFlushPendingFileDeletions()) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } BackgroundParentImpl::PBackgroundSDBConnectionParent* BackgroundParentImpl::AllocPBackgroundSDBConnectionParent( const PersistenceType& aPersistenceType, const PrincipalInfo& aPrincipalInfo) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::AllocPBackgroundSDBConnectionParent(aPersistenceType, aPrincipalInfo); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundSDBConnectionConstructor( PBackgroundSDBConnectionParent* aActor, const PersistenceType& aPersistenceType, const PrincipalInfo& aPrincipalInfo) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); if (!mozilla::dom::RecvPBackgroundSDBConnectionConstructor( aActor, aPersistenceType, aPrincipalInfo)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } bool BackgroundParentImpl::DeallocPBackgroundSDBConnectionParent( PBackgroundSDBConnectionParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::DeallocPBackgroundSDBConnectionParent(aActor); } BackgroundParentImpl::PBackgroundLSDatabaseParent* BackgroundParentImpl::AllocPBackgroundLSDatabaseParent( const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId, const uint64_t& aDatastoreId) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::AllocPBackgroundLSDatabaseParent( aPrincipalInfo, aPrivateBrowsingId, aDatastoreId); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundLSDatabaseConstructor( PBackgroundLSDatabaseParent* aActor, const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId, const uint64_t& aDatastoreId) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); if (!mozilla::dom::RecvPBackgroundLSDatabaseConstructor( aActor, aPrincipalInfo, aPrivateBrowsingId, aDatastoreId)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } bool BackgroundParentImpl::DeallocPBackgroundLSDatabaseParent( PBackgroundLSDatabaseParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::DeallocPBackgroundLSDatabaseParent(aActor); } BackgroundParentImpl::PBackgroundLSObserverParent* BackgroundParentImpl::AllocPBackgroundLSObserverParent( const uint64_t& aObserverId) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::AllocPBackgroundLSObserverParent(aObserverId); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundLSObserverConstructor( PBackgroundLSObserverParent* aActor, const uint64_t& aObserverId) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); if (!mozilla::dom::RecvPBackgroundLSObserverConstructor(aActor, aObserverId)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } bool BackgroundParentImpl::DeallocPBackgroundLSObserverParent( PBackgroundLSObserverParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::DeallocPBackgroundLSObserverParent(aActor); } BackgroundParentImpl::PBackgroundLSRequestParent* BackgroundParentImpl::AllocPBackgroundLSRequestParent( const LSRequestParams& aParams) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::AllocPBackgroundLSRequestParent(this, aParams); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundLSRequestConstructor( PBackgroundLSRequestParent* aActor, const LSRequestParams& aParams) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); if (!mozilla::dom::RecvPBackgroundLSRequestConstructor(aActor, aParams)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } bool BackgroundParentImpl::DeallocPBackgroundLSRequestParent( PBackgroundLSRequestParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::DeallocPBackgroundLSRequestParent(aActor); } BackgroundParentImpl::PBackgroundLSSimpleRequestParent* BackgroundParentImpl::AllocPBackgroundLSSimpleRequestParent( const LSSimpleRequestParams& aParams) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::AllocPBackgroundLSSimpleRequestParent(this, aParams); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundLSSimpleRequestConstructor( PBackgroundLSSimpleRequestParent* aActor, const LSSimpleRequestParams& aParams) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); if (!mozilla::dom::RecvPBackgroundLSSimpleRequestConstructor(aActor, aParams)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } bool BackgroundParentImpl::DeallocPBackgroundLSSimpleRequestParent( PBackgroundLSSimpleRequestParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::DeallocPBackgroundLSSimpleRequestParent(aActor); } BackgroundParentImpl::PBackgroundLocalStorageCacheParent* BackgroundParentImpl::AllocPBackgroundLocalStorageCacheParent( const PrincipalInfo& aPrincipalInfo, const nsACString& aOriginKey, const uint32_t& aPrivateBrowsingId) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::AllocPBackgroundLocalStorageCacheParent( aPrincipalInfo, aOriginKey, aPrivateBrowsingId); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundLocalStorageCacheConstructor( PBackgroundLocalStorageCacheParent* aActor, const PrincipalInfo& aPrincipalInfo, const nsACString& aOriginKey, const uint32_t& aPrivateBrowsingId) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::RecvPBackgroundLocalStorageCacheConstructor( this, aActor, aPrincipalInfo, aOriginKey, aPrivateBrowsingId); } bool BackgroundParentImpl::DeallocPBackgroundLocalStorageCacheParent( PBackgroundLocalStorageCacheParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::DeallocPBackgroundLocalStorageCacheParent(aActor); } auto BackgroundParentImpl::AllocPBackgroundStorageParent( const nsAString& aProfilePath, const uint32_t& aPrivateBrowsingId) -> PBackgroundStorageParent* { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::AllocPBackgroundStorageParent(aProfilePath, aPrivateBrowsingId); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundStorageConstructor( PBackgroundStorageParent* aActor, const nsAString& aProfilePath, const uint32_t& aPrivateBrowsingId) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::RecvPBackgroundStorageConstructor(aActor, aProfilePath, aPrivateBrowsingId); } bool BackgroundParentImpl::DeallocPBackgroundStorageParent( PBackgroundStorageParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::DeallocPBackgroundStorageParent(aActor); } already_AddRefed BackgroundParentImpl::AllocPBackgroundSessionStorageManagerParent( const uint64_t& aTopContextId) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return dom::AllocPBackgroundSessionStorageManagerParent(aTopContextId); } already_AddRefed BackgroundParentImpl::AllocPBackgroundSessionStorageServiceParent() { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return MakeAndAddRef(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateFileSystemManagerParent( const PrincipalInfo& aPrincipalInfo, Endpoint&& aParentEndpoint, CreateFileSystemManagerParentResolver&& aResolver) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::CreateFileSystemManagerParent( aPrincipalInfo, std::move(aParentEndpoint), std::move(aResolver)); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateWebTransportParent( const nsAString& aURL, nsIPrincipal* aPrincipal, const mozilla::Maybe& aClientInfo, const bool& aDedicated, const bool& aRequireUnreliable, const uint32_t& aCongestionControl, // Sequence* aServerCertHashes, Endpoint&& aParentEndpoint, CreateWebTransportParentResolver&& aResolver) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainProcess(); AssertIsOnBackgroundThread(); RefPtr webt = new mozilla::dom::WebTransportParent(); webt->Create(aURL, aPrincipal, aClientInfo, aDedicated, aRequireUnreliable, aCongestionControl, /*aServerCertHashes, */ std::move(aParentEndpoint), std::move(aResolver)); return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPIdleSchedulerParent() { if (!IsContentActor(this)) { return nullptr; } AssertIsOnBackgroundThread(); RefPtr actor = new IdleSchedulerParent(); return actor.forget(); } dom::PRemoteWorkerControllerParent* BackgroundParentImpl::AllocPRemoteWorkerControllerParent( const dom::RemoteWorkerData& aRemoteWorkerData) { if (!IsContentActor(this)) { return nullptr; } RefPtr actor = new dom::RemoteWorkerControllerParent(aRemoteWorkerData); return actor.forget().take(); } IPCResult BackgroundParentImpl::RecvPRemoteWorkerControllerConstructor( dom::PRemoteWorkerControllerParent* aActor, const dom::RemoteWorkerData& aRemoteWorkerData) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } MOZ_ASSERT(aActor); return IPC_OK(); } bool BackgroundParentImpl::DeallocPRemoteWorkerControllerParent( dom::PRemoteWorkerControllerParent* aActor) { RefPtr actor = dont_AddRef(static_cast(aActor)); return true; } already_AddRefed BackgroundParentImpl::AllocPRemoteWorkerServiceParent() { if (!IsContentActor(this)) { return nullptr; } return MakeAndAddRef(); } IPCResult BackgroundParentImpl::RecvPRemoteWorkerServiceConstructor( PRemoteWorkerServiceParent* aActor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } mozilla::dom::RemoteWorkerServiceParent* actor = static_cast(aActor); RefPtr parent = BackgroundParent::GetContentParentHandle(this); // If the ContentParent is null we are dealing with a same-process actor. if (!parent) { actor->Initialize(NOT_REMOTE_TYPE); } else { actor->Initialize(parent->GetRemoteType()); } return IPC_OK(); } mozilla::dom::PSharedWorkerParent* BackgroundParentImpl::AllocPSharedWorkerParent( const mozilla::dom::RemoteWorkerData& aData, const uint64_t& aWindowID, const mozilla::dom::MessagePortIdentifier& aPortIdentifier) { if (!IsContentActor(this)) { return nullptr; } RefPtr agent = new mozilla::dom::SharedWorkerParent(); return agent.forget().take(); } IPCResult BackgroundParentImpl::RecvPSharedWorkerConstructor( PSharedWorkerParent* aActor, const mozilla::dom::RemoteWorkerData& aData, const uint64_t& aWindowID, const mozilla::dom::MessagePortIdentifier& aPortIdentifier) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } mozilla::dom::SharedWorkerParent* actor = static_cast(aActor); actor->Initialize(aData, aWindowID, aPortIdentifier); return IPC_OK(); } bool BackgroundParentImpl::DeallocPSharedWorkerParent( mozilla::dom::PSharedWorkerParent* aActor) { RefPtr actor = dont_AddRef(static_cast(aActor)); return true; } dom::PFileCreatorParent* BackgroundParentImpl::AllocPFileCreatorParent( const nsAString& aFullPath, const nsAString& aType, const nsAString& aName, const Maybe& aLastModified, const bool& aExistenceCheck, const bool& aIsFromNsIFile) { if (!IsContentActor(this)) { return nullptr; } RefPtr actor = new dom::FileCreatorParent(); return actor.forget().take(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPFileCreatorConstructor( dom::PFileCreatorParent* aActor, const nsAString& aFullPath, const nsAString& aType, const nsAString& aName, const Maybe& aLastModified, const bool& aExistenceCheck, const bool& aIsFromNsIFile) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } bool isFileRemoteType = false; // If the ContentParentHandle is null we are dealing with a same-process // actor. RefPtr parent = BackgroundParent::GetContentParentHandle(this); if (!parent) { isFileRemoteType = true; } else { isFileRemoteType = parent->GetRemoteType() == FILE_REMOTE_TYPE; } dom::FileCreatorParent* actor = static_cast(aActor); // We allow the creation of File via this IPC call only for the 'file' process // or for testing. if (!isFileRemoteType && !StaticPrefs::dom_file_createInChild()) { Unused << dom::FileCreatorParent::Send__delete__( actor, dom::FileCreationErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR)); return IPC_OK(); } return actor->CreateAndShareFile(aFullPath, aType, aName, aLastModified, aExistenceCheck, aIsFromNsIFile); } bool BackgroundParentImpl::DeallocPFileCreatorParent( dom::PFileCreatorParent* aActor) { RefPtr actor = dont_AddRef(static_cast(aActor)); return true; } dom::PTemporaryIPCBlobParent* BackgroundParentImpl::AllocPTemporaryIPCBlobParent() { if (!IsContentActor(this)) { return nullptr; } return new dom::TemporaryIPCBlobParent(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPTemporaryIPCBlobConstructor( dom::PTemporaryIPCBlobParent* aActor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } dom::TemporaryIPCBlobParent* actor = static_cast(aActor); return actor->CreateAndShareFile(); } bool BackgroundParentImpl::DeallocPTemporaryIPCBlobParent( dom::PTemporaryIPCBlobParent* aActor) { delete aActor; return true; } already_AddRefed BackgroundParentImpl::AllocPVsyncParent() { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); RefPtr actor = new mozilla::dom::VsyncParent(); RefPtr vsyncDispatcher = gfxPlatform::GetPlatform()->GetGlobalVsyncDispatcher(); actor->UpdateVsyncDispatcher(vsyncDispatcher); return actor.forget(); } camera::PCamerasParent* BackgroundParentImpl::AllocPCamerasParent() { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); #ifdef MOZ_WEBRTC RefPtr actor = mozilla::camera::CamerasParent::Create(); return actor.forget().take(); #else return nullptr; #endif } #ifdef MOZ_WEBRTC mozilla::ipc::IPCResult BackgroundParentImpl::RecvPCamerasConstructor( camera::PCamerasParent* aActor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return static_cast(aActor)->RecvPCamerasConstructor(); } #endif bool BackgroundParentImpl::DeallocPCamerasParent( camera::PCamerasParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); #ifdef MOZ_WEBRTC RefPtr actor = dont_AddRef(static_cast(aActor)); #endif return true; } auto BackgroundParentImpl::AllocPUDPSocketParent( const Maybe& /* unused */, const nsACString& /* unused */) -> PUDPSocketParent* { if (!IsContentActor(this)) { return nullptr; } RefPtr p = new UDPSocketParent(this); return p.forget().take(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPUDPSocketConstructor( PUDPSocketParent* aActor, const Maybe& aOptionalPrincipal, const nsACString& aFilter) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (aOptionalPrincipal.isSome()) { // Support for checking principals (for non-mtransport use) will be handled // in bug 1167039 return IPC_FAIL_NO_REASON(this); } // No principal - This must be from mtransport (WebRTC/ICE) - We'd want // to DispatchToMainThread() here, but if we do we must block RecvBind() // until Init() gets run. Since we don't have a principal, and we verify // we have a filter, we can safely skip the Dispatch and just invoke Init() // to install the filter. // For mtransport, this will always be "stun", which doesn't allow outbound // packets if they aren't STUN packets until a STUN response is seen. if (!aFilter.EqualsASCII(NS_NETWORK_SOCKET_FILTER_HANDLER_STUN_SUFFIX)) { return IPC_FAIL_NO_REASON(this); } if (!static_cast(aActor)->Init(nullptr, aFilter)) { MOZ_CRASH("UDPSocketCallback - failed init"); } return IPC_OK(); } bool BackgroundParentImpl::DeallocPUDPSocketParent(PUDPSocketParent* actor) { UDPSocketParent* p = static_cast(actor); p->Release(); return true; } already_AddRefed BackgroundParentImpl::AllocPVerifySSLServerCertParent( const nsTArray& aPeerCertChain, const nsACString& aHostName, const int32_t& aPort, const OriginAttributes& aOriginAttributes, const Maybe& aStapledOCSPResponse, const Maybe& aSctsFromTLSExtension, const Maybe& aDcInfo, const uint32_t& aProviderFlags, const uint32_t& aCertVerifierFlags) { if (!IsSocketActor(this)) { return nullptr; } RefPtr parent = new mozilla::psm::VerifySSLServerCertParent(); return parent.forget(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPVerifySSLServerCertConstructor( PVerifySSLServerCertParent* aActor, nsTArray&& aPeerCertChain, const nsACString& aHostName, const int32_t& aPort, const OriginAttributes& aOriginAttributes, const Maybe& aStapledOCSPResponse, const Maybe& aSctsFromTLSExtension, const Maybe& aDcInfo, const uint32_t& aProviderFlags, const uint32_t& aCertVerifierFlags) { if (!IsSocketActor(this)) { return IPC_FAIL(this, "must be a socket actor"); } mozilla::psm::VerifySSLServerCertParent* authCert = static_cast(aActor); if (!authCert->Dispatch(std::move(aPeerCertChain), aHostName, aPort, aOriginAttributes, aStapledOCSPResponse, aSctsFromTLSExtension, aDcInfo, aProviderFlags, aCertVerifierFlags)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPSelectTLSClientAuthCertParent( const nsACString& aHostName, const OriginAttributes& aOriginAttributes, const int32_t& aPort, const uint32_t& aProviderFlags, const uint32_t& aProviderTlsFlags, const ByteArray& aServerCertBytes, const nsTArray& aCANames) { if (!IsSocketActor(this)) { return nullptr; } RefPtr parent = new mozilla::psm::SelectTLSClientAuthCertParent(); return parent.forget(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPSelectTLSClientAuthCertConstructor( PSelectTLSClientAuthCertParent* actor, const nsACString& aHostName, const OriginAttributes& aOriginAttributes, const int32_t& aPort, const uint32_t& aProviderFlags, const uint32_t& aProviderTlsFlags, const ByteArray& aServerCertBytes, nsTArray&& aCANames) { if (!IsSocketActor(this)) { return IPC_FAIL(this, "must be a socket actor"); } mozilla::psm::SelectTLSClientAuthCertParent* selectTLSClientAuthCertParent = static_cast(actor); if (!selectTLSClientAuthCertParent->Dispatch( aHostName, aOriginAttributes, aPort, aProviderFlags, aProviderTlsFlags, aServerCertBytes, std::move(aCANames))) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } mozilla::dom::PBroadcastChannelParent* BackgroundParentImpl::AllocPBroadcastChannelParent( const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin, const nsAString& aChannel) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); nsString originChannelKey; // The format of originChannelKey is: // | originChannelKey.Assign(aChannel); originChannelKey.AppendLiteral("|"); originChannelKey.Append(NS_ConvertUTF8toUTF16(aOrigin)); return new BroadcastChannelParent(originChannelKey); } namespace { class CheckPrincipalRunnable final : public Runnable { public: CheckPrincipalRunnable( already_AddRefed aParent, const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin) : Runnable("ipc::CheckPrincipalRunnable"), mContentParent(aParent), mPrincipalInfo(aPrincipalInfo), mOrigin(aOrigin) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(mContentParent); } NS_IMETHOD Run() override { AssertIsOnMainThread(); RefPtr contentParent = mContentParent->GetContentParent(); if (!contentParent) { return NS_OK; } auto principalOrErr = PrincipalInfoToPrincipal(mPrincipalInfo); if (NS_WARN_IF(principalOrErr.isErr())) { contentParent->KillHard( "BroadcastChannel killed: PrincipalInfoToPrincipal failed."); return NS_OK; } nsAutoCString origin; nsresult rv = principalOrErr.unwrap()->GetOrigin(origin); if (NS_FAILED(rv)) { contentParent->KillHard( "BroadcastChannel killed: principal::GetOrigin failed."); return NS_OK; } if (NS_WARN_IF(!mOrigin.Equals(origin))) { contentParent->KillHard("BroadcastChannel killed: origins do not match."); return NS_OK; } return NS_OK; } private: RefPtr mContentParent; PrincipalInfo mPrincipalInfo; nsCString mOrigin; }; } // namespace mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBroadcastChannelConstructor( PBroadcastChannelParent* actor, const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin, const nsAString& aChannel) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); RefPtr parent = BackgroundParent::GetContentParentHandle(this); // If the ContentParent is null we are dealing with a same-process actor. if (!parent) { return IPC_OK(); } RefPtr runnable = new CheckPrincipalRunnable(parent.forget(), aPrincipalInfo, aOrigin); MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable)); return IPC_OK(); } bool BackgroundParentImpl::DeallocPBroadcastChannelParent( PBroadcastChannelParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); delete static_cast(aActor); return true; } mozilla::dom::PServiceWorkerManagerParent* BackgroundParentImpl::AllocPServiceWorkerManagerParent() { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); RefPtr agent = new dom::ServiceWorkerManagerParent(); return agent.forget().take(); } bool BackgroundParentImpl::DeallocPServiceWorkerManagerParent( PServiceWorkerManagerParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); RefPtr parent = dont_AddRef(static_cast(aActor)); MOZ_ASSERT(parent); return true; } mozilla::ipc::IPCResult BackgroundParentImpl::RecvShutdownServiceWorkerRegistrar() { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL_NO_REASON(this); } RefPtr service = dom::ServiceWorkerRegistrar::Get(); MOZ_ASSERT(service); service->Shutdown(); return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPCacheStorageParent( const Namespace& aNamespace, const PrincipalInfo& aPrincipalInfo) { if (!IsContentActor(this)) { return nullptr; } return dom::cache::AllocPCacheStorageParent(this, aNamespace, aPrincipalInfo); } PMessagePortParent* BackgroundParentImpl::AllocPMessagePortParent( const nsID& aUUID, const nsID& aDestinationUUID, const uint32_t& aSequenceID) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return new MessagePortParent(aUUID); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPMessagePortConstructor( PMessagePortParent* aActor, const nsID& aUUID, const nsID& aDestinationUUID, const uint32_t& aSequenceID) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MessagePortParent* mp = static_cast(aActor); if (!mp->Entangle(aDestinationUUID, aSequenceID)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPIPCClientCertsParent() { if (!IsSocketActor(this)) { return nullptr; } // This should only be called in the parent process with the socket process // as the child process, not any content processes, hence the check that the // child ID be 0. MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(mozilla::ipc::BackgroundParent::GetChildID(this) == 0); if (!XRE_IsParentProcess() || mozilla::ipc::BackgroundParent::GetChildID(this) != 0) { return nullptr; } RefPtr result = new psm::IPCClientCertsParent(); return result.forget(); } bool BackgroundParentImpl::DeallocPMessagePortParent( PMessagePortParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); delete static_cast(aActor); return true; } mozilla::ipc::IPCResult BackgroundParentImpl::RecvMessagePortForceClose( const nsID& aUUID, const nsID& aDestinationUUID, const uint32_t& aSequenceID) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (!MessagePortParent::ForceClose(aUUID, aDestinationUUID, aSequenceID)) { return IPC_FAIL(this, "MessagePortParent::ForceClose failed."); } return IPC_OK(); } BackgroundParentImpl::PQuotaParent* BackgroundParentImpl::AllocPQuotaParent() { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); return mozilla::dom::quota::AllocPQuotaParent(); } bool BackgroundParentImpl::DeallocPQuotaParent(PQuotaParent* aActor) { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); return mozilla::dom::quota::DeallocPQuotaParent(aActor); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvShutdownQuotaManager() { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL_NO_REASON(this); } if (!mozilla::dom::quota::RecvShutdownQuotaManager()) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvShutdownBackgroundSessionStorageManagers() { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL_NO_REASON(this); } if (!mozilla::dom::RecvShutdownBackgroundSessionStorageManagers()) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPropagateBackgroundSessionStorageManager( const uint64_t& aCurrentTopContextId, const uint64_t& aTargetTopContextId) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL(this, "Wrong actor"); } mozilla::dom::RecvPropagateBackgroundSessionStorageManager( aCurrentTopContextId, aTargetTopContextId); return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvRemoveBackgroundSessionStorageManager( const uint64_t& aTopContextId) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL_NO_REASON(this); } if (!mozilla::dom::RecvRemoveBackgroundSessionStorageManager(aTopContextId)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvGetSessionStorageManagerData( const uint64_t& aTopContextId, const uint32_t& aSizeLimit, const bool& aCancelSessionStoreTimer, GetSessionStorageManagerDataResolver&& aResolver) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainProcess(); AssertIsOnBackgroundThread(); if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL(this, "Wrong actor"); } if (!mozilla::dom::RecvGetSessionStorageData(aTopContextId, aSizeLimit, aCancelSessionStoreTimer, std::move(aResolver))) { return IPC_FAIL(this, "Couldn't get session storage data"); } return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvLoadSessionStorageManagerData( const uint64_t& aTopContextId, nsTArray&& aOriginCacheCopy) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainProcess(); AssertIsOnBackgroundThread(); if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL(this, "Wrong actor"); } if (!mozilla::dom::RecvLoadSessionStorageData(aTopContextId, std::move(aOriginCacheCopy))) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPFileSystemRequestParent( const FileSystemParams& aParams) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); RefPtr result = new FileSystemRequestParent(); if (NS_WARN_IF(!result->Initialize(aParams))) { return nullptr; } return result.forget(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPFileSystemRequestConstructor( PFileSystemRequestParent* aActor, const FileSystemParams& params) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } static_cast(aActor)->Start(); return IPC_OK(); } // Gamepad API Background IPC already_AddRefed BackgroundParentImpl::AllocPGamepadEventChannelParent() { if (!IsContentActor(this)) { return nullptr; } return dom::GamepadEventChannelParent::Create(); } already_AddRefed BackgroundParentImpl::AllocPGamepadTestChannelParent() { if (!IsContentActor(this)) { return nullptr; } return dom::GamepadTestChannelParent::Create(); } dom::PWebAuthnTransactionParent* BackgroundParentImpl::AllocPWebAuthnTransactionParent() { if (!IsContentActor(this)) { return nullptr; } return new dom::WebAuthnTransactionParent(); } bool BackgroundParentImpl::DeallocPWebAuthnTransactionParent( dom::PWebAuthnTransactionParent* aActor) { MOZ_ASSERT(aActor); delete aActor; return true; } already_AddRefed BackgroundParentImpl::AllocPHttpBackgroundChannelParent( const uint64_t& aChannelId) { if (!IsContentActor(this)) { return nullptr; } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); RefPtr actor = new net::HttpBackgroundChannelParent(); return actor.forget(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPHttpBackgroundChannelConstructor( net::PHttpBackgroundChannelParent* aActor, const uint64_t& aChannelId) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } MOZ_ASSERT(aActor); AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); net::HttpBackgroundChannelParent* aParent = static_cast(aActor); if (NS_WARN_IF(NS_FAILED(aParent->Init(aChannelId)))) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateMIDIPort( Endpoint&& aEndpoint, const MIDIPortInfo& aPortInfo, const bool& aSysexEnabled) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (!aEndpoint.IsValid()) { return IPC_FAIL(this, "invalid endpoint for MIDIPort"); } MIDIPlatformService::OwnerThread()->Dispatch(NS_NewRunnableFunction( "CreateMIDIPortRunnable", [=, endpoint = std::move(aEndpoint)]() mutable { RefPtr result = new MIDIPortParent(aPortInfo, aSysexEnabled); endpoint.Bind(result); })); return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateMIDIManager( Endpoint&& aEndpoint) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); if (!aEndpoint.IsValid()) { return IPC_FAIL(this, "invalid endpoint for MIDIManager"); } MIDIPlatformService::OwnerThread()->Dispatch(NS_NewRunnableFunction( "CreateMIDIManagerRunnable", [=, endpoint = std::move(aEndpoint)]() mutable { RefPtr result = new MIDIManagerParent(); endpoint.Bind(result); MIDIPlatformService::Get()->AddManager(result); })); return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvHasMIDIDevice( HasMIDIDeviceResolver&& aResolver) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); InvokeAsync(MIDIPlatformService::OwnerThread(), __func__, []() { bool hasDevice = MIDIPlatformService::Get()->HasDevice(); return BoolPromise::CreateAndResolve(hasDevice, __func__); }) ->Then(GetCurrentSerialEventTarget(), __func__, [resolver = std::move(aResolver)]( const BoolPromise::ResolveOrRejectValue& r) { resolver(r.IsResolve() && r.ResolveValue()); }); return IPC_OK(); } mozilla::dom::PClientManagerParent* BackgroundParentImpl::AllocPClientManagerParent() { if (!IsContentActor(this)) { return nullptr; } return mozilla::dom::AllocClientManagerParent(); } bool BackgroundParentImpl::DeallocPClientManagerParent( mozilla::dom::PClientManagerParent* aActor) { return mozilla::dom::DeallocClientManagerParent(aActor); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPClientManagerConstructor( mozilla::dom::PClientManagerParent* aActor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } mozilla::dom::InitClientManagerParent(aActor); return IPC_OK(); } IPCResult BackgroundParentImpl::RecvStorageActivity( const PrincipalInfo& aPrincipalInfo) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } dom::StorageActivityService::SendActivity(aPrincipalInfo); return IPC_OK(); } IPCResult BackgroundParentImpl::RecvPServiceWorkerManagerConstructor( PServiceWorkerManagerParent* const aActor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } // Only the parent process is allowed to construct this actor. if (BackgroundParent::IsOtherProcessActor(this)) { return IPC_FAIL_NO_REASON(aActor); } return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPServiceWorkerParent( const IPCServiceWorkerDescriptor&) { if (!IsContentActor(this)) { return nullptr; } return MakeAndAddRef(); } IPCResult BackgroundParentImpl::RecvPServiceWorkerConstructor( PServiceWorkerParent* aActor, const IPCServiceWorkerDescriptor& aDescriptor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } dom::InitServiceWorkerParent(aActor, aDescriptor); return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPServiceWorkerContainerParent() { if (!IsContentActor(this)) { return nullptr; } return MakeAndAddRef(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPServiceWorkerContainerConstructor( PServiceWorkerContainerParent* aActor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } dom::InitServiceWorkerContainerParent(aActor); return IPC_OK(); } already_AddRefed BackgroundParentImpl::AllocPServiceWorkerRegistrationParent( const IPCServiceWorkerRegistrationDescriptor&) { if (!IsContentActor(this)) { return nullptr; } return MakeAndAddRef(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPServiceWorkerRegistrationConstructor( PServiceWorkerRegistrationParent* aActor, const IPCServiceWorkerRegistrationDescriptor& aDescriptor) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } dom::InitServiceWorkerRegistrationParent(aActor, aDescriptor); return IPC_OK(); } dom::PEndpointForReportParent* BackgroundParentImpl::AllocPEndpointForReportParent( const nsAString& aGroupName, const PrincipalInfo& aPrincipalInfo) { if (!IsContentActor(this)) { return nullptr; } RefPtr actor = new dom::EndpointForReportParent(); return actor.forget().take(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPEndpointForReportConstructor( PEndpointForReportParent* aActor, const nsAString& aGroupName, const PrincipalInfo& aPrincipalInfo) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } static_cast(aActor)->Run(aGroupName, aPrincipalInfo); return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvEnsureRDDProcessAndCreateBridge( EnsureRDDProcessAndCreateBridgeResolver&& aResolver) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } using Type = std::tuple&&>; RefPtr parent = BackgroundParent::GetContentParentHandle(this); if (NS_WARN_IF(!parent)) { aResolver( Type(NS_ERROR_NOT_AVAILABLE, Endpoint())); return IPC_OK(); } RDDProcessManager* rdd = RDDProcessManager::Get(); if (!rdd) { aResolver( Type(NS_ERROR_NOT_AVAILABLE, Endpoint())); return IPC_OK(); } rdd->EnsureRDDProcessAndCreateBridge(OtherPid(), parent->ChildID()) ->Then(GetCurrentSerialEventTarget(), __func__, [resolver = std::move(aResolver)]( mozilla::RDDProcessManager::EnsureRDDPromise:: ResolveOrRejectValue&& aValue) mutable { if (aValue.IsReject()) { resolver(Type(aValue.RejectValue(), Endpoint())); return; } resolver(Type(NS_OK, std::move(aValue.ResolveValue()))); }); return IPC_OK(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvEnsureUtilityProcessAndCreateBridge( const RemoteDecodeIn& aLocation, EnsureUtilityProcessAndCreateBridgeResolver&& aResolver) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } base::ProcessId otherPid = OtherPid(); RefPtr parent = BackgroundParent::GetContentParentHandle(this); if (NS_WARN_IF(!parent)) { return IPC_FAIL_NO_REASON(this); } dom::ContentParentId childId = parent->ChildID(); nsCOMPtr managerThread = GetCurrentSerialEventTarget(); if (!managerThread) { return IPC_FAIL_NO_REASON(this); } NS_DispatchToMainThread(NS_NewRunnableFunction( "BackgroundParentImpl::RecvEnsureUtilityProcessAndCreateBridge()", [aResolver, managerThread, otherPid, childId, aLocation]() { RefPtr upm = UtilityProcessManager::GetSingleton(); using Type = std::tuple&&>; if (!upm) { managerThread->Dispatch(NS_NewRunnableFunction( "BackgroundParentImpl::RecvEnsureUtilityProcessAndCreateBridge::" "Failure", [aResolver]() { aResolver(Type(NS_ERROR_NOT_AVAILABLE, Endpoint())); })); } else { SandboxingKind sbKind = GetSandboxingKindFromLocation(aLocation); upm->StartProcessForRemoteMediaDecoding(otherPid, childId, sbKind) ->Then(managerThread, __func__, [resolver = aResolver]( mozilla::ipc::UtilityProcessManager:: StartRemoteDecodingUtilityPromise:: ResolveOrRejectValue&& aValue) mutable { if (aValue.IsReject()) { resolver(Type(aValue.RejectValue(), Endpoint())); return; } resolver(Type(NS_OK, std::move(aValue.ResolveValue()))); }); } })); return IPC_OK(); } bool BackgroundParentImpl::DeallocPEndpointForReportParent( PEndpointForReportParent* aActor) { RefPtr actor = dont_AddRef(static_cast(aActor)); return true; } mozilla::ipc::IPCResult BackgroundParentImpl::RecvRemoveEndpoint( const nsAString& aGroupName, const nsACString& aEndpointURL, const PrincipalInfo& aPrincipalInfo) { if (!IsContentActor(this)) { return IPC_FAIL(this, "must be a content actor"); } NS_DispatchToMainThread(NS_NewRunnableFunction( "BackgroundParentImpl::RecvRemoveEndpoint(", [aGroupName = nsString(aGroupName), aEndpointURL = nsCString(aEndpointURL), aPrincipalInfo]() { dom::ReportingHeader::RemoveEndpoint(aGroupName, aEndpointURL, aPrincipalInfo); })); return IPC_OK(); } dom::PMediaTransportParent* BackgroundParentImpl::AllocPMediaTransportParent() { #ifdef MOZ_WEBRTC if (!IsSocketBridgeActor(this)) { return nullptr; } return new MediaTransportParent; #else return nullptr; #endif } bool BackgroundParentImpl::DeallocPMediaTransportParent( dom::PMediaTransportParent* aActor) { #ifdef MOZ_WEBRTC delete aActor; #endif return true; } already_AddRefed BackgroundParentImpl::AllocPLockManagerParent( const ContentPrincipalInfo& aPrincipalInfo, const nsID& aClientId) { if (!IsContentActor(this)) { return nullptr; } return MakeAndAddRef(aPrincipalInfo, aClientId); } already_AddRefed BackgroundParentImpl::AllocPFetchParent() { if (!IsContentActor(this)) { return nullptr; } return MakeAndAddRef(); } already_AddRefed BackgroundParentImpl::AllocPWebSocketConnectionParent( const uint32_t& aListenerId) { if (!IsSocketActor(this)) { return nullptr; } Maybe> listener = net::HttpConnectionMgrParent::GetAndRemoveHttpUpgradeListener( aListenerId); if (!listener) { return nullptr; } RefPtr actor = new mozilla::net::WebSocketConnectionParent(*listener); return actor.forget(); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPWebSocketConnectionConstructor( PWebSocketConnectionParent* actor, const uint32_t& aListenerId) { if (!IsSocketActor(this)) { return IPC_FAIL(this, "must be a socket actor"); } return IPC_OK(); } } // namespace mozilla::ipc void TestParent::ActorDestroy(ActorDestroyReason aWhy) { mozilla::ipc::AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); }