diff options
Diffstat (limited to 'dom/ipc/ContentParent.h')
-rw-r--r-- | dom/ipc/ContentParent.h | 1699 |
1 files changed, 1699 insertions, 0 deletions
diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h new file mode 100644 index 0000000000..53994e45e7 --- /dev/null +++ b/dom/ipc/ContentParent.h @@ -0,0 +1,1699 @@ +/* -*- 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_ContentParent_h +#define mozilla_dom_ContentParent_h + +#include "mozilla/dom/PContentParent.h" +#include "mozilla/dom/ipc/IdType.h" +#include "mozilla/dom/MessageManagerCallback.h" +#include "mozilla/dom/MediaSessionBinding.h" +#include "mozilla/dom/RemoteBrowser.h" +#include "mozilla/dom/RemoteType.h" +#include "mozilla/dom/JSProcessActorParent.h" +#include "mozilla/dom/ProcessActor.h" +#include "mozilla/dom/UserActivation.h" +#include "mozilla/gfx/gfxVarReceiver.h" +#include "mozilla/gfx/GPUProcessListener.h" +#include "mozilla/ipc/BackgroundUtils.h" +#include "mozilla/ipc/GeckoChildProcessHost.h" +#include "mozilla/ipc/InputStreamUtils.h" +#include "mozilla/Attributes.h" +#include "mozilla/DataMutex.h" +#include "mozilla/HalTypes.h" +#include "mozilla/LinkedList.h" +#include "mozilla/Maybe.h" +#include "mozilla/MemoryReportingProcess.h" +#include "mozilla/MozPromise.h" +#include "mozilla/RecursiveMutex.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/UniquePtr.h" + +#include "MainThreadUtils.h" +#include "nsClassHashtable.h" +#include "nsTHashMap.h" +#include "nsTHashSet.h" +#include "nsHashKeys.h" +#include "nsIAsyncShutdown.h" +#include "nsIDOMProcessParent.h" +#include "nsIInterfaceRequestor.h" +#include "nsIObserver.h" +#include "nsIRemoteTab.h" +#include "nsIDOMGeoPositionCallback.h" +#include "nsIDOMGeoPositionErrorCallback.h" +#include "nsRefPtrHashtable.h" +#include "PermissionMessageUtils.h" +#include "DriverCrashGuard.h" +#include "nsIReferrerInfo.h" + +#define CHILD_PROCESS_SHUTDOWN_MESSAGE u"child-process-shutdown"_ns + +class nsConsoleService; +class nsIContentProcessInfo; +class nsICycleCollectorLogSink; +class nsIDumpGCAndCCLogsCallback; +class nsIRemoteTab; +class nsITimer; +class ParentIdleListener; +class nsIWidget; +class nsIX509Cert; + +namespace mozilla { +class PClipboardWriteRequestParent; +class PRemoteSpellcheckEngineParent; + +#if defined(XP_LINUX) && defined(MOZ_SANDBOX) +class SandboxBroker; +class SandboxBrokerPolicyFactory; +#endif + +class PreallocatedProcessManagerImpl; +class BenchmarkStorageParent; + +using mozilla::loader::PScriptCacheParent; + +namespace ipc { +class CrashReporterHost; +class TestShellParent; +class SharedPreferenceSerializer; +} // namespace ipc + +namespace layers { +struct TextureFactoryIdentifier; +} // namespace layers + +namespace dom { + +class BrowsingContextGroup; +class Element; +class BrowserParent; +class ClonedMessageData; +class MemoryReport; +class TabContext; +class GetFilesHelper; +class MemoryReportRequestHost; +class RemoteWorkerManager; +class ThreadsafeContentParentHandle; +struct CancelContentJSOptions; + +#define NS_CONTENTPARENT_IID \ + { \ + 0xeeec9ebf, 0x8ecf, 0x4e38, { \ + 0x81, 0xda, 0xb7, 0x34, 0x13, 0x7e, 0xac, 0xf3 \ + } \ + } + +class ContentParent final : public PContentParent, + public nsIDOMProcessParent, + public nsIObserver, + public nsIDOMGeoPositionCallback, + public nsIDOMGeoPositionErrorCallback, + public nsIAsyncShutdownBlocker, + public nsIInterfaceRequestor, + public gfx::gfxVarReceiver, + public mozilla::LinkedListElement<ContentParent>, + public gfx::GPUProcessListener, + public mozilla::MemoryReportingProcess, + public mozilla::dom::ipc::MessageManagerCallback, + public mozilla::ipc::IShmemAllocator, + public ProcessActor { + typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost; + typedef mozilla::ipc::TestShellParent TestShellParent; + typedef mozilla::ipc::PrincipalInfo PrincipalInfo; + typedef mozilla::dom::ClonedMessageData ClonedMessageData; + typedef mozilla::dom::BrowsingContextGroup BrowsingContextGroup; + + friend class mozilla::PreallocatedProcessManagerImpl; + friend class PContentParent; + friend class mozilla::dom::RemoteWorkerManager; + + public: + using LaunchPromise = + mozilla::MozPromise<RefPtr<ContentParent>, nsresult, false>; + + NS_DECLARE_STATIC_IID_ACCESSOR(NS_CONTENTPARENT_IID) + + static LogModule* GetLog(); + + static ContentParent* Cast(PContentParent* aActor) { + return static_cast<ContentParent*>(aActor); + } + + /** + * Create a ContentParent suitable for use later as a content process. + */ + static already_AddRefed<ContentParent> MakePreallocProcess(); + + /** + * Start up the content-process machinery. This might include + * scheduling pre-launch tasks. + */ + static void StartUp(); + + /** Shut down the content-process machinery. */ + static void ShutDown(); + + static uint32_t GetPoolSize(const nsACString& aContentProcessType); + + static uint32_t GetMaxProcessCount(const nsACString& aContentProcessType); + + static bool IsMaxProcessCountReached(const nsACString& aContentProcessType); + + static void ReleaseCachedProcesses(); + + static void LogAndAssertFailedPrincipalValidationInfo( + nsIPrincipal* aPrincipal, const char* aMethod); + + /** + * Picks a random content parent from |aContentParents| respecting the index + * limit set by |aMaxContentParents|. + * Returns null if non available. + */ + static already_AddRefed<ContentParent> MinTabSelect( + const nsTArray<ContentParent*>& aContentParents, + int32_t maxContentParents); + + /** + * Get or create a content process for: + * 1. browser iframe + * 2. remote xul <browser> + * 3. normal iframe + */ + static RefPtr<ContentParent::LaunchPromise> GetNewOrUsedBrowserProcessAsync( + const nsACString& aRemoteType, BrowsingContextGroup* aGroup = nullptr, + hal::ProcessPriority aPriority = + hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND, + bool aPreferUsed = false); + static already_AddRefed<ContentParent> GetNewOrUsedBrowserProcess( + const nsACString& aRemoteType, BrowsingContextGroup* aGroup = nullptr, + hal::ProcessPriority aPriority = + hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND, + bool aPreferUsed = false); + + /** + * Get or create a content process, but without waiting for the process + * launch to have completed. The returned `ContentParent` may still be in the + * "Launching" state. + * + * Can return `nullptr` in the case of an error. + * + * Use the `WaitForLaunchAsync` or `WaitForLaunchSync` methods to wait for + * the process to be fully launched. + */ + static already_AddRefed<ContentParent> GetNewOrUsedLaunchingBrowserProcess( + const nsACString& aRemoteType, BrowsingContextGroup* aGroup = nullptr, + hal::ProcessPriority aPriority = + hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND, + bool aPreferUsed = false); + + RefPtr<ContentParent::LaunchPromise> WaitForLaunchAsync( + hal::ProcessPriority aPriority = + hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND); + bool WaitForLaunchSync(hal::ProcessPriority aPriority = + hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND); + + /** + * Get or create a content process for the given TabContext. aFrameElement + * should be the frame/iframe element with which this process will + * associated. + */ + static already_AddRefed<RemoteBrowser> CreateBrowser( + const TabContext& aContext, Element* aFrameElement, + const nsACString& aRemoteType, BrowsingContext* aBrowsingContext, + ContentParent* aOpenerContentParent); + + /** + * Get all content parents. + * + * # Lifetime + * + * These pointers are ONLY valid for synchronous use from the main thread. + * + * Do NOT attempt to use them after the main thread has had a chance to handle + * messages or you could end up with dangling pointers. + */ + static void GetAll(nsTArray<ContentParent*>& aArray); + + static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray); + + static void BroadcastStringBundle(const StringBundleDescriptor&); + + static void BroadcastFontListChanged(); + static void BroadcastShmBlockAdded(uint32_t aGeneration, uint32_t aIndex); + + static void BroadcastThemeUpdate(widget::ThemeChangeKind); + + static void BroadcastMediaCodecsSupportedUpdate( + RemoteDecodeIn aLocation, const media::MediaCodecsSupported& aSupported); + + const nsACString& GetRemoteType() const override; + + virtual void DoGetRemoteType(nsACString& aRemoteType, + ErrorResult& aError) const override { + aRemoteType = GetRemoteType(); + } + + enum CPIteratorPolicy { eLive, eAll }; + + class ContentParentIterator { + private: + ContentParent* mCurrent; + CPIteratorPolicy mPolicy; + + public: + ContentParentIterator(CPIteratorPolicy aPolicy, ContentParent* aCurrent) + : mCurrent(aCurrent), mPolicy(aPolicy) {} + + ContentParentIterator begin() { + // Move the cursor to the first element that matches the policy. + while (mPolicy != eAll && mCurrent && !mCurrent->IsAlive()) { + mCurrent = mCurrent->LinkedListElement<ContentParent>::getNext(); + } + + return *this; + } + ContentParentIterator end() { + return ContentParentIterator(mPolicy, nullptr); + } + + const ContentParentIterator& operator++() { + MOZ_ASSERT(mCurrent); + do { + mCurrent = mCurrent->LinkedListElement<ContentParent>::getNext(); + } while (mPolicy != eAll && mCurrent && !mCurrent->IsAlive()); + + return *this; + } + + bool operator!=(const ContentParentIterator& aOther) const { + MOZ_ASSERT(mPolicy == aOther.mPolicy); + return mCurrent != aOther.mCurrent; + } + + ContentParent* operator*() { return mCurrent; } + }; + + static ContentParentIterator AllProcesses(CPIteratorPolicy aPolicy) { + ContentParent* first = + sContentParents ? sContentParents->getFirst() : nullptr; + return ContentParentIterator(aPolicy, first); + } + + static void NotifyUpdatedDictionaries(); + + // Tell content processes the font list has changed. If aFullRebuild is true, + // the shared list has been rebuilt and must be freshly mapped by child + // processes; if false, existing mappings are still valid but the data has + // been updated and so full reflows are in order. + static void NotifyUpdatedFonts(bool aFullRebuild); + + mozilla::ipc::IPCResult RecvCreateGMPService(); + + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver) + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_NSIDOMPROCESSPARENT + NS_DECL_NSIOBSERVER + NS_DECL_NSIDOMGEOPOSITIONCALLBACK + NS_DECL_NSIDOMGEOPOSITIONERRORCALLBACK + NS_DECL_NSIASYNCSHUTDOWNBLOCKER + NS_DECL_NSIINTERFACEREQUESTOR + + /** + * MessageManagerCallback methods that we override. + */ + virtual bool DoLoadMessageManagerScript(const nsAString& aURL, + bool aRunInGlobalScope) override; + + virtual nsresult DoSendAsyncMessage(const nsAString& aMessage, + StructuredCloneData& aData) override; + + RecursiveMutex& ThreadsafeHandleMutex(); + + /** Notify that a tab is about to send Destroy to its child. */ + void NotifyTabWillDestroy(); + + /** Notify that a tab is beginning its destruction sequence. */ + void NotifyTabDestroying(); + + /** Notify that a tab was destroyed during normal operation. */ + void NotifyTabDestroyed(const TabId& aTabId, bool aNotifiedDestroying); + + // Manage the set of `KeepAlive`s on this ContentParent which are preventing + // it from being destroyed. + void AddKeepAlive(); + void RemoveKeepAlive(); + + TestShellParent* CreateTestShell(); + + bool DestroyTestShell(TestShellParent* aTestShell); + + TestShellParent* GetTestShellSingleton(); + + // This method can be called on any thread. + void RegisterRemoteWorkerActor(); + + // This method _must_ be called on main-thread because it can start the + // shutting down of the content process. + void UnregisterRemoveWorkerActor(); + + void ReportChildAlreadyBlocked(); + + bool RequestRunToCompletion(); + + void UpdateCookieStatus(nsIChannel* aChannel); + + bool IsLaunching() const { + return mLifecycleState == LifecycleState::LAUNCHING; + } + bool IsAlive() const override; + bool IsInitialized() const; + bool IsSignaledImpendingShutdown() const { + return mIsSignaledImpendingShutdown; + } + bool IsShuttingDown() const { + return IsDead() || IsSignaledImpendingShutdown(); + } + bool IsDead() const { return mLifecycleState == LifecycleState::DEAD; } + + bool IsForBrowser() const { return mIsForBrowser; } + + GeckoChildProcessHost* Process() const { return mSubprocess; } + + nsIContentProcessInfo* ScriptableHelper() const { return mScriptableHelper; } + + mozilla::dom::ProcessMessageManager* GetMessageManager() const { + return mMessageManager; + } + + bool NeedsPermissionsUpdate(const nsACString& aPermissionKey) const; + + // Getter for which permission keys should signal that a content + // process needs to know about the change of a permission with this as the + // secondary key, like for 3rdPartyFrameStorage^https://secondary.com + bool NeedsSecondaryKeyPermissionsUpdate( + const nsACString& aPermissionKey) const; + + // Manage pending load states which have been sent to this process, and are + // expected to be used to start a load imminently. + already_AddRefed<nsDocShellLoadState> TakePendingLoadStateForId( + uint64_t aLoadIdentifier); + void StorePendingLoadState(nsDocShellLoadState* aLoadState); + + /** + * Kill our subprocess and make sure it dies. Should only be used + * in emergency situations since it bypasses the normal shutdown + * process. + * + * WARNING: aReason appears in telemetry, so any new value passed in requires + * data review. + */ + void KillHard(const char* aWhy); + + ContentParentId ChildID() const { return mChildID; } + + /** + * Get a user-friendly name for this ContentParent. We make no guarantees + * about this name: It might not be unique, apps can spoof special names, + * etc. So please don't use this name to make any decisions about the + * ContentParent based on the value returned here. + */ + void FriendlyName(nsAString& aName, bool aAnonymize = false); + + virtual void OnChannelError() override; + + mozilla::ipc::IPCResult RecvInitCrashReporter( + const NativeThreadId& aThreadId); + + already_AddRefed<PNeckoParent> AllocPNeckoParent(); + + virtual mozilla::ipc::IPCResult RecvPNeckoConstructor( + PNeckoParent* aActor) override { + return PContentParent::RecvPNeckoConstructor(aActor); + } + + mozilla::ipc::IPCResult RecvInitStreamFilter( + const uint64_t& aChannelId, const nsAString& aAddonId, + InitStreamFilterResolver&& aResolver); + + PHalParent* AllocPHalParent(); + + virtual mozilla::ipc::IPCResult RecvPHalConstructor( + PHalParent* aActor) override { + return PContentParent::RecvPHalConstructor(aActor); + } + + PHeapSnapshotTempFileHelperParent* AllocPHeapSnapshotTempFileHelperParent(); + + PRemoteSpellcheckEngineParent* AllocPRemoteSpellcheckEngineParent(); + + bool CycleCollectWithLogs(bool aDumpAllTraces, + nsICycleCollectorLogSink* aSink, + nsIDumpGCAndCCLogsCallback* aCallback); + + mozilla::ipc::IPCResult RecvNotifyTabDestroying(const TabId& aTabId, + const ContentParentId& aCpId); + + mozilla::ipc::IPCResult RecvFinishShutdown(); + + mozilla::ipc::IPCResult RecvNotifyShutdownSuccess(); + + void MaybeInvokeDragSession(BrowserParent* aParent, EventMessage aMessage); + + PContentPermissionRequestParent* AllocPContentPermissionRequestParent( + const nsTArray<PermissionRequest>& aRequests, nsIPrincipal* aPrincipal, + nsIPrincipal* aTopLevelPrincipal, const bool& aIsHandlingUserInput, + const bool& aMaybeUnsafePermissionDelegate, const TabId& aTabId); + + bool DeallocPContentPermissionRequestParent( + PContentPermissionRequestParent* actor); + + void ForkNewProcess(bool aBlocking); + + mozilla::ipc::IPCResult RecvCreateWindow( + PBrowserParent* aThisBrowserParent, + const MaybeDiscarded<BrowsingContext>& aParent, PBrowserParent* aNewTab, + const uint32_t& aChromeFlags, const bool& aCalledFromJS, + const bool& aForPrinting, const bool& aForWindowDotPrint, + nsIURI* aURIToLoad, const nsACString& aFeatures, + const UserActivation::Modifiers& aModifiers, + nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, + nsIReferrerInfo* aReferrerInfo, const OriginAttributes& aOriginAttributes, + CreateWindowResolver&& aResolve); + + mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess( + PBrowserParent* aThisTab, const MaybeDiscarded<BrowsingContext>& aParent, + const uint32_t& aChromeFlags, const bool& aCalledFromJS, + nsIURI* aURIToLoad, const nsACString& aFeatures, + const UserActivation::Modifiers& aModifiers, const nsAString& aName, + nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, + nsIReferrerInfo* aReferrerInfo, + const OriginAttributes& aOriginAttributes); + + static void BroadcastBlobURLRegistration( + const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal, + const nsCString& aPartitionKey, ContentParent* aIgnoreThisCP = nullptr); + + static void BroadcastBlobURLUnregistration( + const nsACString& aURI, nsIPrincipal* aPrincipal, + ContentParent* aIgnoreThisCP = nullptr); + + mozilla::ipc::IPCResult RecvStoreAndBroadcastBlobURLRegistration( + const nsACString& aURI, const IPCBlob& aBlob, nsIPrincipal* aPrincipal, + const nsCString& aPartitionKey); + + mozilla::ipc::IPCResult RecvUnstoreAndBroadcastBlobURLUnregistration( + const nsACString& aURI, nsIPrincipal* aPrincipal); + + virtual int32_t Pid() const override; + + // PURLClassifierParent. + PURLClassifierParent* AllocPURLClassifierParent(nsIPrincipal* aPrincipal, + bool* aSuccess); + virtual mozilla::ipc::IPCResult RecvPURLClassifierConstructor( + PURLClassifierParent* aActor, nsIPrincipal* aPrincipal, + bool* aSuccess) override; + + // PURLClassifierLocalParent. + PURLClassifierLocalParent* AllocPURLClassifierLocalParent( + nsIURI* aURI, const nsTArray<IPCURLClassifierFeature>& aFeatures); + + virtual mozilla::ipc::IPCResult RecvPURLClassifierLocalConstructor( + PURLClassifierLocalParent* aActor, nsIURI* aURI, + nsTArray<IPCURLClassifierFeature>&& aFeatures) override; + + PSessionStorageObserverParent* AllocPSessionStorageObserverParent(); + + virtual mozilla::ipc::IPCResult RecvPSessionStorageObserverConstructor( + PSessionStorageObserverParent* aActor) override; + + bool DeallocPSessionStorageObserverParent( + PSessionStorageObserverParent* aActor); + + bool DeallocPURLClassifierLocalParent(PURLClassifierLocalParent* aActor); + + bool DeallocPURLClassifierParent(PURLClassifierParent* aActor); + + // Use the PHangMonitor channel to ask the child to repaint a tab. + void PaintTabWhileInterruptingJS(BrowserParent*); + + void UnloadLayersWhileInterruptingJS(BrowserParent*); + + void CancelContentJSExecutionIfRunning( + BrowserParent* aBrowserParent, + nsIRemoteTab::NavigationType aNavigationType, + const CancelContentJSOptions& aCancelContentJSOptions); + + void SetMainThreadQoSPriority(nsIThread::QoSPriority aQoSPriority); + + // This function is called when we are about to load a document from an + // HTTP(S) or FTP channel for a content process. It is a useful place + // to start to kick off work as early as possible in response to such + // document loads. + // aShouldWaitForPermissionCookieUpdate is set to true if main thread IPCs for + // updating permissions/cookies are sent. + nsresult AboutToLoadHttpFtpDocumentForChild( + nsIChannel* aChannel, + bool* aShouldWaitForPermissionCookieUpdate = nullptr); + + // Send Blob URLs for this aPrincipal if they are not already known to this + // content process and mark the process to receive any new/revoked Blob URLs + // to this content process forever. + void TransmitBlobURLsForPrincipal(nsIPrincipal* aPrincipal); + + nsresult TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal); + + // Whenever receiving a Principal we need to validate that Principal case + // by case, where we grant individual callsites to customize the checks! + enum class ValidatePrincipalOptions { + AllowNullPtr, // Not a NullPrincipal but a nullptr as Principal. + AllowSystem, + AllowExpanded, + }; + bool ValidatePrincipal( + nsIPrincipal* aPrincipal, + const EnumSet<ValidatePrincipalOptions>& aOptions = {}); + + // This function is called in BrowsingContext immediately before IPC call to + // load a URI. If aURI is a BlobURL, this method transmits all BlobURLs for + // aURI's principal that were previously not transmitted. This allows for + // opening a locally created BlobURL in a new tab. + // + // The reason all previously untransmitted Blobs are transmitted is that the + // current BlobURL could contain html code, referring to another untransmitted + // BlobURL. + // + // Should eventually be made obsolete by broader design changes that only + // store BlobURLs in the parent process. + void TransmitBlobDataIfBlobURL(nsIURI* aURI); + + void OnCompositorDeviceReset() override; + + // Control the priority of the IPC messages for input events. + void SetInputPriorityEventEnabled(bool aEnabled); + bool IsInputPriorityEventEnabled() { return mIsInputPriorityEventEnabled; } + + static bool IsInputEventQueueSupported(); + + mozilla::ipc::IPCResult RecvCreateBrowsingContext( + uint64_t aGroupId, BrowsingContext::IPCInitializer&& aInit); + + mozilla::ipc::IPCResult RecvDiscardBrowsingContext( + const MaybeDiscarded<BrowsingContext>& aContext, bool aDoDiscard, + DiscardBrowsingContextResolver&& aResolve); + + mozilla::ipc::IPCResult RecvWindowClose( + const MaybeDiscarded<BrowsingContext>& aContext, bool aTrustedCaller); + mozilla::ipc::IPCResult RecvWindowFocus( + const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType, + uint64_t aActionId); + mozilla::ipc::IPCResult RecvWindowBlur( + const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType); + mozilla::ipc::IPCResult RecvRaiseWindow( + const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType, + uint64_t aActionId); + mozilla::ipc::IPCResult RecvAdjustWindowFocus( + const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible, + uint64_t aActionId); + mozilla::ipc::IPCResult RecvClearFocus( + const MaybeDiscarded<BrowsingContext>& aContext); + mozilla::ipc::IPCResult RecvSetFocusedBrowsingContext( + const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId); + mozilla::ipc::IPCResult RecvSetActiveBrowsingContext( + const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId); + mozilla::ipc::IPCResult RecvUnsetActiveBrowsingContext( + const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId); + mozilla::ipc::IPCResult RecvSetFocusedElement( + const MaybeDiscarded<BrowsingContext>& aContext, bool aNeedsFocus); + mozilla::ipc::IPCResult RecvFinalizeFocusOuter( + const MaybeDiscarded<BrowsingContext>& aContext, bool aCanFocus, + CallerType aCallerType); + mozilla::ipc::IPCResult RecvInsertNewFocusActionId(uint64_t aActionId); + mozilla::ipc::IPCResult RecvBlurToParent( + const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext, + const MaybeDiscarded<BrowsingContext>& aBrowsingContextToClear, + const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus, + bool aIsLeavingDocument, bool aAdjustWidget, + bool aBrowsingContextToClearHandled, + bool aAncestorBrowsingContextToFocusHandled, uint64_t aActionId); + mozilla::ipc::IPCResult RecvMaybeExitFullscreen( + const MaybeDiscarded<BrowsingContext>& aContext); + + mozilla::ipc::IPCResult RecvWindowPostMessage( + const MaybeDiscarded<BrowsingContext>& aContext, + const ClonedOrErrorMessageData& aMessage, const PostMessageData& aData); + + FORWARD_SHMEM_ALLOCATOR_TO(PContentParent) + + mozilla::ipc::IPCResult RecvBlobURLDataRequest( + const nsACString& aBlobURL, nsIPrincipal* pTriggeringPrincipal, + nsIPrincipal* pLoadingPrincipal, + const OriginAttributes& aOriginAttributes, uint64_t aInnerWindowId, + const nsCString& aPartitionKey, BlobURLDataRequestResolver&& aResolver); + + protected: + bool CheckBrowsingContextEmbedder(CanonicalBrowsingContext* aBC, + const char* aOperation) const; + + void ActorDestroy(ActorDestroyReason why) override; + + bool ShouldContinueFromReplyTimeout() override; + + void OnVarChanged(const GfxVarUpdate& aVar) override; + void OnCompositorUnexpectedShutdown() override; + + private: + /** + * A map of the remote content process type to a list of content parents + * currently available to host *new* tabs/frames of that type. + * + * If a content process is identified as troubled or dead, it will be + * removed from this list, but will still be in the sContentParents list for + * the GetAll/GetAllEvenIfDead APIs. + */ + static nsClassHashtable<nsCStringHashKey, nsTArray<ContentParent*>>* + sBrowserContentParents; + static mozilla::StaticAutoPtr<LinkedList<ContentParent>> sContentParents; + + /** + * In order to avoid rapidly creating and destroying content processes when + * running under e10s, we may keep alive a single unused "web" content + * process if it previously had a very short lifetime. + * + * This process will be re-used during process selection, avoiding spawning a + * new process, if the "web" remote type is being requested. + */ + static StaticRefPtr<ContentParent> sRecycledE10SProcess; + + void AddShutdownBlockers(); + void RemoveShutdownBlockers(); + +#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) + // Cached Mac sandbox params used when launching content processes. + static mozilla::StaticAutoPtr<std::vector<std::string>> sMacSandboxParams; +#endif + + // Set aLoadUri to true to load aURIToLoad and to false to only create the + // window. aURIToLoad should always be provided, if available, to ensure + // compatibility with GeckoView. + mozilla::ipc::IPCResult CommonCreateWindow( + PBrowserParent* aThisTab, BrowsingContext& aParent, bool aSetOpener, + const uint32_t& aChromeFlags, const bool& aCalledFromJS, + const bool& aForPrinting, const bool& aForWindowDotPrint, + nsIURI* aURIToLoad, const nsACString& aFeatures, + const UserActivation::Modifiers& aModifiers, + BrowserParent* aNextRemoteBrowser, const nsAString& aName, + nsresult& aResult, nsCOMPtr<nsIRemoteTab>& aNewRemoteTab, + bool* aWindowIsNew, int32_t& aOpenLocation, + nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, + bool aLoadUri, nsIContentSecurityPolicy* aCsp, + const OriginAttributes& aOriginAttributes); + + explicit ContentParent(const nsACString& aRemoteType); + + // Launch the subprocess and associated initialization. + // Returns false if the process fails to start. + // Deprecated in favor of LaunchSubprocessAsync. + bool LaunchSubprocessSync(hal::ProcessPriority aInitialPriority); + + // Launch the subprocess and associated initialization; + // returns a promise and signals failure by rejecting. + // OS-level launching work is dispatched to another thread, but some + // initialization (creating IPDL actors, etc.; see Init()) is run on + // the main thread. + RefPtr<LaunchPromise> LaunchSubprocessAsync( + hal::ProcessPriority aInitialPriority); + + // Common implementation of LaunchSubprocess{Sync,Async}. + // Return `true` in case of success, `false` if launch was + // aborted because of shutdown. + bool BeginSubprocessLaunch(ProcessPriority aPriority); + void LaunchSubprocessReject(); + bool LaunchSubprocessResolve(bool aIsSync, ProcessPriority aPriority); + + // Common initialization after sub process launch. + bool InitInternal(ProcessPriority aPriority); + + // Generate a minidump for the child process and one for the main process + void GeneratePairedMinidump(const char* aReason); + void HandleOrphanedMinidump(nsString* aDumpId); + + virtual ~ContentParent(); + + void Init(); + + // Some information could be sent to content very early, it + // should be send from this function. This function should only be + // called after the process has been transformed to browser. + void ForwardKnownInfo(); + + /** + * We might want to reuse barely used content processes if certain criteria + * are met. + * + * With Fission this is a no-op. + */ + bool TryToRecycleE10SOnly(); + + /** + * If this process is currently being recycled, unmark it as the recycled + * content process. + * If `aForeground` is true, will also restore the process' foreground + * priority if it was previously the recycled content process. + * + * With Fission this is a no-op. + */ + void StopRecyclingE10SOnly(bool aForeground); + + /** + * Removing it from the static array so it won't be returned for new tabs in + * GetNewOrUsedBrowserProcess. + */ + void RemoveFromList(); + + /** + * Return if the process has an active worker. + */ + bool HasActiveWorker(); + + /** + * 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(); + + /** + * Mark this ContentParent as dead for the purposes of Get*(). + * This method is idempotent. + */ + void MarkAsDead(); + + /** + * Let the process know we are about to send a shutdown through a + * non-mainthread side channel in order to bypass mainthread congestion. + * This potentially cancels mainthread content JS execution. + */ + void SignalImpendingShutdownToContentJS(); + + bool CheckTabDestroyWillKeepAlive(uint32_t aExpectedBrowserCount); + + /** + * Check if this process is ready to be shut down, and if it is, begin the + * shutdown process. Should be called whenever a change occurs which could + * cause the decisions made by `ShouldKeepProcessAlive` to change. + * + * @param aExpectedBrowserCount The number of PBrowser actors which should + * not block shutdown. This should usually be 0. + * @param aSendShutDown If true, will send the shutdown message in addition + * to marking the process as dead and starting the force + * kill timer. + */ + void MaybeBeginShutDown(uint32_t aExpectedBrowserCount = 0, + bool aSendShutDown = true); + + /** + * How we will shut down this ContentParent and its subprocess. + */ + enum ShutDownMethod { + // Send a shutdown message and wait for FinishShutdown call back. + SEND_SHUTDOWN_MESSAGE, + // Close the channel ourselves and let the subprocess clean up itself. + CLOSE_CHANNEL, + }; + + void AsyncSendShutDownMessage(); + + /** + * Exit the subprocess and vamoose. After this call IsAlive() + * will return false and this ContentParent will not be returned + * by the Get*() funtions. However, the shutdown sequence itself + * may be asynchronous. + */ + bool ShutDownProcess(ShutDownMethod aMethod); + + // Perform any steps necesssary to gracefully shtudown the message + // manager and null out mMessageManager. + void ShutDownMessageManager(); + + // Start the send shutdown timer on shutdown. + void StartSendShutdownTimer(); + + // Start the force-kill timer on shutdown. + void StartForceKillTimer(); + + // Ensure that the permissions for the giben Permission key are set in the + // content process. + // + // See nsIPermissionManager::GetPermissionsForKey for more information on + // these keys. + void EnsurePermissionsByKey(const nsACString& aKey, + const nsACString& aOrigin); + + static void SendShutdownTimerCallback(nsITimer* aTimer, void* aClosure); + static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure); + + bool CanOpenBrowser(const IPCTabContext& aContext); + + /** + * Get or create the corresponding content parent array to + * |aContentProcessType|. + */ + static nsTArray<ContentParent*>& GetOrCreatePool( + const nsACString& aContentProcessType); + + mozilla::ipc::IPCResult RecvInitBackground( + Endpoint<mozilla::ipc::PBackgroundStarterParent>&& aEndpoint); + + mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport); + + bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*); + + mozilla::ipc::IPCResult RecvCloneDocumentTreeInto( + const MaybeDiscarded<BrowsingContext>& aSource, + const MaybeDiscarded<BrowsingContext>& aTarget, PrintData&& aPrintData); + + mozilla::ipc::IPCResult RecvUpdateRemotePrintSettings( + const MaybeDiscarded<BrowsingContext>& aTarget, PrintData&& aPrintData); + + mozilla::ipc::IPCResult RecvConstructPopupBrowser( + ManagedEndpoint<PBrowserParent>&& actor, + ManagedEndpoint<PWindowGlobalParent>&& windowEp, const TabId& tabId, + const IPCTabContext& context, const WindowGlobalInit& initialWindowInit, + const uint32_t& chromeFlags); + + mozilla::ipc::IPCResult RecvIsSecureURI( + nsIURI* aURI, const OriginAttributes& aOriginAttributes, + bool* aIsSecureURI); + + mozilla::ipc::IPCResult RecvAccumulateMixedContentHSTS( + nsIURI* aURI, const bool& aActive, + const OriginAttributes& aOriginAttributes); + + bool DeallocPHalParent(PHalParent*); + + bool DeallocPHeapSnapshotTempFileHelperParent( + PHeapSnapshotTempFileHelperParent*); + + PCycleCollectWithLogsParent* AllocPCycleCollectWithLogsParent( + const bool& aDumpAllTraces, const FileDescriptor& aGCLog, + const FileDescriptor& aCCLog); + + bool DeallocPCycleCollectWithLogsParent(PCycleCollectWithLogsParent* aActor); + + PScriptCacheParent* AllocPScriptCacheParent(const FileDescOrError& cacheFile, + const bool& wantCacheData); + + bool DeallocPScriptCacheParent(PScriptCacheParent* shell); + + already_AddRefed<PExternalHelperAppParent> AllocPExternalHelperAppParent( + nsIURI* aUri, const mozilla::net::LoadInfoArgs& aLoadInfoArgs, + const nsACString& aMimeContentType, const nsACString& aContentDisposition, + const uint32_t& aContentDispositionHint, + const nsAString& aContentDispositionFilename, const bool& aForceSave, + const int64_t& aContentLength, const bool& aWasFileChannel, + nsIURI* aReferrer, const MaybeDiscarded<BrowsingContext>& aContext, + const bool& aShouldCloseWindow); + + mozilla::ipc::IPCResult RecvPExternalHelperAppConstructor( + PExternalHelperAppParent* actor, nsIURI* uri, + const LoadInfoArgs& loadInfoArgs, const nsACString& aMimeContentType, + const nsACString& aContentDisposition, + const uint32_t& aContentDispositionHint, + const nsAString& aContentDispositionFilename, const bool& aForceSave, + const int64_t& aContentLength, const bool& aWasFileChannel, + nsIURI* aReferrer, const MaybeDiscarded<BrowsingContext>& aContext, + const bool& aShouldCloseWindow) override; + + already_AddRefed<PHandlerServiceParent> AllocPHandlerServiceParent(); + + PMediaParent* AllocPMediaParent(); + + bool DeallocPMediaParent(PMediaParent* aActor); + + PBenchmarkStorageParent* AllocPBenchmarkStorageParent(); + + bool DeallocPBenchmarkStorageParent(PBenchmarkStorageParent* aActor); + +#ifdef MOZ_WEBSPEECH + already_AddRefed<PSpeechSynthesisParent> AllocPSpeechSynthesisParent(); + + virtual mozilla::ipc::IPCResult RecvPSpeechSynthesisConstructor( + PSpeechSynthesisParent* aActor) override; +#endif + + already_AddRefed<PWebBrowserPersistDocumentParent> + AllocPWebBrowserPersistDocumentParent( + PBrowserParent* aBrowser, + const MaybeDiscarded<BrowsingContext>& aContext); + + mozilla::ipc::IPCResult RecvSetClipboard(const IPCTransferable& aTransferable, + const int32_t& aWhichClipboard); + + mozilla::ipc::IPCResult RecvGetClipboard( + nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard, + const MaybeDiscarded<WindowContext>& aRequestingWindowContext, + IPCTransferableData* aTransferableData); + + mozilla::ipc::IPCResult RecvEmptyClipboard(const int32_t& aWhichClipboard); + + mozilla::ipc::IPCResult RecvClipboardHasType(nsTArray<nsCString>&& aTypes, + const int32_t& aWhichClipboard, + bool* aHasType); + + mozilla::ipc::IPCResult RecvGetExternalClipboardFormats( + const int32_t& aWhichClipboard, const bool& aPlainTextOnly, + nsTArray<nsCString>* aTypes); + + mozilla::ipc::IPCResult RecvGetClipboardAsync( + nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard, + const MaybeDiscarded<WindowContext>& aRequestingWindowContext, + mozilla::NotNull<nsIPrincipal*> aRequestingPrincipal, + GetClipboardAsyncResolver&& aResolver); + + already_AddRefed<PClipboardWriteRequestParent> + AllocPClipboardWriteRequestParent(const int32_t& aClipboardType); + + mozilla::ipc::IPCResult RecvGetIconForExtension(const nsACString& aFileExt, + const uint32_t& aIconSize, + nsTArray<uint8_t>* bits); + + mozilla::ipc::IPCResult RecvStartVisitedQueries( + const nsTArray<RefPtr<nsIURI>>&); + + mozilla::ipc::IPCResult RecvSetURITitle(nsIURI* uri, const nsAString& title); + + mozilla::ipc::IPCResult RecvShowAlert(nsIAlertNotification* aAlert); + + mozilla::ipc::IPCResult RecvCloseAlert(const nsAString& aName, + bool aContextClosed); + + mozilla::ipc::IPCResult RecvDisableNotifications(nsIPrincipal* aPrincipal); + + mozilla::ipc::IPCResult RecvOpenNotificationSettings( + nsIPrincipal* aPrincipal); + + mozilla::ipc::IPCResult RecvNotificationEvent( + const nsAString& aType, const NotificationEventData& aData); + + mozilla::ipc::IPCResult RecvLoadURIExternal( + nsIURI* uri, nsIPrincipal* triggeringPrincipal, + nsIPrincipal* redirectPrincipal, + const MaybeDiscarded<BrowsingContext>& aContext, + bool aWasExternallyTriggered, bool aHasValidUserGestureActivation); + mozilla::ipc::IPCResult RecvExtProtocolChannelConnectParent( + const uint64_t& registrarId); + + mozilla::ipc::IPCResult RecvSyncMessage( + const nsAString& aMsg, const ClonedMessageData& aData, + nsTArray<StructuredCloneData>* aRetvals); + + mozilla::ipc::IPCResult RecvAsyncMessage(const nsAString& aMsg, + const ClonedMessageData& aData); + + // MOZ_CAN_RUN_SCRIPT_BOUNDARY because we don't have MOZ_CAN_RUN_SCRIPT bits + // in IPC code yet. + MOZ_CAN_RUN_SCRIPT_BOUNDARY + mozilla::ipc::IPCResult RecvAddGeolocationListener(const bool& aHighAccuracy); + mozilla::ipc::IPCResult RecvRemoveGeolocationListener(); + + // MOZ_CAN_RUN_SCRIPT_BOUNDARY because we don't have MOZ_CAN_RUN_SCRIPT bits + // in IPC code yet. + MOZ_CAN_RUN_SCRIPT_BOUNDARY + mozilla::ipc::IPCResult RecvSetGeolocationHigherAccuracy(const bool& aEnable); + + mozilla::ipc::IPCResult RecvConsoleMessage(const nsAString& aMessage); + + mozilla::ipc::IPCResult RecvScriptError( + const nsAString& aMessage, const nsAString& aSourceName, + const nsAString& aSourceLine, const uint32_t& aLineNumber, + const uint32_t& aColNumber, const uint32_t& aFlags, + const nsACString& aCategory, const bool& aIsFromPrivateWindow, + const uint64_t& aInnerWindowId, const bool& aIsFromChromeContext); + + mozilla::ipc::IPCResult RecvReportFrameTimingData( + const LoadInfoArgs& loadInfoArgs, const nsAString& entryName, + const nsAString& initiatorType, UniquePtr<PerformanceTimingData>&& aData); + + mozilla::ipc::IPCResult RecvScriptErrorWithStack( + const nsAString& aMessage, const nsAString& aSourceName, + const nsAString& aSourceLine, const uint32_t& aLineNumber, + const uint32_t& aColNumber, const uint32_t& aFlags, + const nsACString& aCategory, const bool& aIsFromPrivateWindow, + const bool& aIsFromChromeContext, const ClonedMessageData& aStack); + + private: + mozilla::ipc::IPCResult RecvScriptErrorInternal( + const nsAString& aMessage, const nsAString& aSourceName, + const nsAString& aSourceLine, const uint32_t& aLineNumber, + const uint32_t& aColNumber, const uint32_t& aFlags, + const nsACString& aCategory, const bool& aIsFromPrivateWindow, + const bool& aIsFromChromeContext, + const ClonedMessageData* aStack = nullptr); + + public: + mozilla::ipc::IPCResult RecvCommitBrowsingContextTransaction( + const MaybeDiscarded<BrowsingContext>& aContext, + BrowsingContext::BaseTransaction&& aTransaction, uint64_t aEpoch); + + mozilla::ipc::IPCResult RecvCommitWindowContextTransaction( + const MaybeDiscarded<WindowContext>& aContext, + WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch); + + mozilla::ipc::IPCResult RecvAddSecurityState( + const MaybeDiscarded<WindowContext>& aContext, uint32_t aStateFlags); + + mozilla::ipc::IPCResult RecvFirstIdle(); + + mozilla::ipc::IPCResult RecvDeviceReset(); + + mozilla::ipc::IPCResult RecvCopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI, + const bool& aInPrivateBrowsing); + + mozilla::ipc::IPCResult RecvFindImageText(IPCImage&&, nsTArray<nsCString>&&, + FindImageTextResolver&&); + + virtual void ProcessingError(Result aCode, const char* aMsgName) override; + + mozilla::ipc::IPCResult RecvGraphicsError(const nsACString& aError); + + mozilla::ipc::IPCResult RecvBeginDriverCrashGuard(const uint32_t& aGuardType, + bool* aOutCrashed); + + mozilla::ipc::IPCResult RecvEndDriverCrashGuard(const uint32_t& aGuardType); + + mozilla::ipc::IPCResult RecvAddIdleObserver(const uint64_t& observerId, + const uint32_t& aIdleTimeInS); + + mozilla::ipc::IPCResult RecvRemoveIdleObserver(const uint64_t& observerId, + const uint32_t& aIdleTimeInS); + + mozilla::ipc::IPCResult RecvBackUpXResources( + const FileDescriptor& aXSocketFd); + + mozilla::ipc::IPCResult RecvRequestAnonymousTemporaryFile( + const uint64_t& aID); + + mozilla::ipc::IPCResult RecvCreateAudioIPCConnection( + CreateAudioIPCConnectionResolver&& aResolver); + + already_AddRefed<extensions::PExtensionsParent> AllocPExtensionsParent(); + +#ifdef MOZ_WEBRTC + PWebrtcGlobalParent* AllocPWebrtcGlobalParent(); + bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent* aActor); +#endif + + mozilla::ipc::IPCResult RecvUpdateDropEffect(const uint32_t& aDragAction, + const uint32_t& aDropEffect); + + mozilla::ipc::IPCResult RecvShutdownProfile(const nsACString& aProfile); + + mozilla::ipc::IPCResult RecvShutdownPerfStats(const nsACString& aPerfStats); + + mozilla::ipc::IPCResult RecvGetFontListShmBlock( + const uint32_t& aGeneration, const uint32_t& aIndex, + base::SharedMemoryHandle* aOut); + + mozilla::ipc::IPCResult RecvInitializeFamily(const uint32_t& aGeneration, + const uint32_t& aFamilyIndex, + const bool& aLoadCmaps); + + mozilla::ipc::IPCResult RecvSetCharacterMap(const uint32_t& aGeneration, + const uint32_t& aFamilyIndex, + const bool& aAlias, + const uint32_t& aFaceIndex, + const gfxSparseBitSet& aMap); + + mozilla::ipc::IPCResult RecvInitOtherFamilyNames(const uint32_t& aGeneration, + const bool& aDefer, + bool* aLoaded); + + mozilla::ipc::IPCResult RecvSetupFamilyCharMap(const uint32_t& aGeneration, + const uint32_t& aIndex, + const bool& aAlias); + + mozilla::ipc::IPCResult RecvStartCmapLoading(const uint32_t& aGeneration, + const uint32_t& aStartIndex); + + mozilla::ipc::IPCResult RecvGetHyphDict(nsIURI* aURIParams, + base::SharedMemoryHandle* aOutHandle, + uint32_t* aOutSize); + + mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsAString& aCodecName, + const uint32_t& aDecodeFPS); + + mozilla::ipc::IPCResult RecvNotifyPushObservers(const nsACString& aScope, + nsIPrincipal* aPrincipal, + const nsAString& aMessageId); + + mozilla::ipc::IPCResult RecvNotifyPushObserversWithData( + const nsACString& aScope, nsIPrincipal* aPrincipal, + const nsAString& aMessageId, nsTArray<uint8_t>&& aData); + + mozilla::ipc::IPCResult RecvNotifyPushSubscriptionChangeObservers( + const nsACString& aScope, nsIPrincipal* aPrincipal); + + mozilla::ipc::IPCResult RecvPushError(const nsACString& aScope, + nsIPrincipal* aPrincipal, + const nsAString& aMessage, + const uint32_t& aFlags); + + mozilla::ipc::IPCResult RecvNotifyPushSubscriptionModifiedObservers( + const nsACString& aScope, nsIPrincipal* aPrincipal); + + mozilla::ipc::IPCResult RecvGetFilesRequest(const nsID& aID, + const nsAString& aDirectoryPath, + const bool& aRecursiveFlag); + + mozilla::ipc::IPCResult RecvDeleteGetFilesRequest(const nsID& aID); + + mozilla::ipc::IPCResult RecvAccumulateChildHistograms( + nsTArray<HistogramAccumulation>&& aAccumulations); + mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms( + nsTArray<KeyedHistogramAccumulation>&& aAccumulations); + mozilla::ipc::IPCResult RecvUpdateChildScalars( + nsTArray<ScalarAction>&& aScalarActions); + mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars( + nsTArray<KeyedScalarAction>&& aScalarActions); + mozilla::ipc::IPCResult RecvRecordChildEvents( + nsTArray<ChildEventData>&& events); + mozilla::ipc::IPCResult RecvRecordDiscardedData( + const DiscardedData& aDiscardedData); + mozilla::ipc::IPCResult RecvRecordPageLoadEvent( + const mozilla::glean::perf::PageLoadExtra& aPageLoadEventExtra); + mozilla::ipc::IPCResult RecvRecordOrigin(const uint32_t& aMetricId, + const nsACString& aOrigin); + mozilla::ipc::IPCResult RecvReportContentBlockingLog( + const IPCStream& aIPCStream); + + mozilla::ipc::IPCResult RecvBHRThreadHang(const HangDetails& aHangDetails); + + mozilla::ipc::IPCResult RecvAddCertException( + nsIX509Cert* aCert, const nsACString& aHostName, int32_t aPort, + const OriginAttributes& aOriginAttributes, bool aIsTemporary, + AddCertExceptionResolver&& aResolver); + + mozilla::ipc::IPCResult RecvAutomaticStorageAccessPermissionCanBeGranted( + nsIPrincipal* aPrincipal, + AutomaticStorageAccessPermissionCanBeGrantedResolver&& aResolver); + + mozilla::ipc::IPCResult RecvStorageAccessPermissionGrantedForOrigin( + uint64_t aTopLevelWindowId, + const MaybeDiscarded<BrowsingContext>& aParentContext, + nsIPrincipal* aTrackingPrincipal, const nsACString& aTrackingOrigin, + const int& aAllowMode, + const Maybe< + ContentBlockingNotifier::StorageAccessPermissionGrantedReason>& + aReason, + const bool& aFrameOnly, + StorageAccessPermissionGrantedForOriginResolver&& aResolver); + + mozilla::ipc::IPCResult RecvCompleteAllowAccessFor( + const MaybeDiscarded<BrowsingContext>& aParentContext, + uint64_t aTopLevelWindowId, nsIPrincipal* aTrackingPrincipal, + const nsACString& aTrackingOrigin, uint32_t aCookieBehavior, + const ContentBlockingNotifier::StorageAccessPermissionGrantedReason& + aReason, + CompleteAllowAccessForResolver&& aResolver); + + mozilla::ipc::IPCResult RecvSetAllowStorageAccessRequestFlag( + nsIPrincipal* aEmbeddedPrincipal, nsIURI* aEmbeddingOrigin, + SetAllowStorageAccessRequestFlagResolver&& aResolver); + + mozilla::ipc::IPCResult RecvTestAllowStorageAccessRequestFlag( + nsIPrincipal* aEmbeddingPrincipal, nsIURI* aEmbeddedOrigin, + TestAllowStorageAccessRequestFlagResolver&& aResolver); + + mozilla::ipc::IPCResult RecvStoreUserInteractionAsPermission( + nsIPrincipal* aPrincipal); + + mozilla::ipc::IPCResult RecvTestCookiePermissionDecided( + const MaybeDiscarded<BrowsingContext>& aContext, nsIPrincipal* aPrincipal, + const TestCookiePermissionDecidedResolver&& aResolver); + + mozilla::ipc::IPCResult RecvTestStorageAccessPermission( + nsIPrincipal* aEmbeddingPrincipal, const nsCString& aEmbeddedOrigin, + const TestStorageAccessPermissionResolver&& aResolver); + + mozilla::ipc::IPCResult RecvNotifyMediaPlaybackChanged( + const MaybeDiscarded<BrowsingContext>& aContext, + MediaPlaybackState aState); + + mozilla::ipc::IPCResult RecvNotifyMediaAudibleChanged( + const MaybeDiscarded<BrowsingContext>& aContext, + MediaAudibleState aState); + + mozilla::ipc::IPCResult RecvNotifyPictureInPictureModeChanged( + const MaybeDiscarded<BrowsingContext>& aContext, bool aEnabled); + + mozilla::ipc::IPCResult RecvNotifyMediaSessionUpdated( + const MaybeDiscarded<BrowsingContext>& aContext, bool aIsCreated); + + mozilla::ipc::IPCResult RecvNotifyUpdateMediaMetadata( + const MaybeDiscarded<BrowsingContext>& aContext, + const Maybe<MediaMetadataBase>& aMetadata); + + mozilla::ipc::IPCResult RecvNotifyMediaSessionPlaybackStateChanged( + const MaybeDiscarded<BrowsingContext>& aContext, + MediaSessionPlaybackState aPlaybackState); + + mozilla::ipc::IPCResult RecvNotifyMediaSessionSupportedActionChanged( + const MaybeDiscarded<BrowsingContext>& aContext, + MediaSessionAction aAction, bool aEnabled); + + mozilla::ipc::IPCResult RecvNotifyMediaFullScreenState( + const MaybeDiscarded<BrowsingContext>& aContext, bool aIsInFullScreen); + + mozilla::ipc::IPCResult RecvNotifyPositionStateChanged( + const MaybeDiscarded<BrowsingContext>& aContext, + const PositionState& aState); + + mozilla::ipc::IPCResult RecvAddOrRemovePageAwakeRequest( + const MaybeDiscarded<BrowsingContext>& aContext, + const bool& aShouldAddCount); + +#if defined(XP_WIN) + mozilla::ipc::IPCResult RecvGetModulesTrust( + ModulePaths&& aModPaths, bool aRunAtNormalPriority, + GetModulesTrustResolver&& aResolver); +#endif // defined(XP_WIN) + + mozilla::ipc::IPCResult RecvReportServiceWorkerShutdownProgress( + uint32_t aShutdownStateId, + ServiceWorkerShutdownState::Progress aProgress); + + mozilla::ipc::IPCResult RecvRawMessage( + const JSActorMessageMeta& aMeta, const Maybe<ClonedMessageData>& aData, + const Maybe<ClonedMessageData>& aStack); + + mozilla::ipc::IPCResult RecvAbortOtherOrientationPendingPromises( + const MaybeDiscarded<BrowsingContext>& aContext); + + mozilla::ipc::IPCResult RecvNotifyOnHistoryReload( + const MaybeDiscarded<BrowsingContext>& aContext, const bool& aForceReload, + NotifyOnHistoryReloadResolver&& aResolver); + + mozilla::ipc::IPCResult RecvHistoryCommit( + const MaybeDiscarded<BrowsingContext>& aContext, const uint64_t& aLoadID, + const nsID& aChangeID, const uint32_t& aLoadType, const bool& aPersist, + const bool& aCloneEntryChildren, const bool& aChannelExpired, + const uint32_t& aCacheKey); + + mozilla::ipc::IPCResult RecvHistoryGo( + const MaybeDiscarded<BrowsingContext>& aContext, int32_t aOffset, + uint64_t aHistoryEpoch, bool aRequireUserInteraction, + bool aUserActivation, HistoryGoResolver&& aResolveRequestedIndex); + + mozilla::ipc::IPCResult RecvSynchronizeLayoutHistoryState( + const MaybeDiscarded<BrowsingContext>& aContext, + nsILayoutHistoryState* aState); + + mozilla::ipc::IPCResult RecvSessionHistoryEntryTitle( + const MaybeDiscarded<BrowsingContext>& aContext, const nsAString& aTitle); + + mozilla::ipc::IPCResult RecvSessionHistoryEntryScrollRestorationIsManual( + const MaybeDiscarded<BrowsingContext>& aContext, const bool& aIsManual); + + mozilla::ipc::IPCResult RecvSessionHistoryEntryScrollPosition( + const MaybeDiscarded<BrowsingContext>& aContext, const int32_t& aX, + const int32_t& aY); + + mozilla::ipc::IPCResult RecvSessionHistoryEntryCacheKey( + const MaybeDiscarded<BrowsingContext>& aContext, + const uint32_t& aCacheKey); + + mozilla::ipc::IPCResult RecvSessionHistoryEntryWireframe( + const MaybeDiscarded<BrowsingContext>& aContext, + const Wireframe& aWireframe); + + mozilla::ipc::IPCResult + RecvSessionHistoryEntryStoreWindowNameInContiguousEntries( + const MaybeDiscarded<BrowsingContext>& aContext, const nsAString& aName); + + mozilla::ipc::IPCResult RecvGetLoadingSessionHistoryInfoFromParent( + const MaybeDiscarded<BrowsingContext>& aContext, + GetLoadingSessionHistoryInfoFromParentResolver&& aResolver); + + mozilla::ipc::IPCResult RecvRemoveFromBFCache( + const MaybeDiscarded<BrowsingContext>& aContext); + + mozilla::ipc::IPCResult RecvSetActiveSessionHistoryEntry( + const MaybeDiscarded<BrowsingContext>& aContext, + const Maybe<nsPoint>& aPreviousScrollPos, SessionHistoryInfo&& aInfo, + uint32_t aLoadType, uint32_t aUpdatedCacheKey, const nsID& aChangeID); + + mozilla::ipc::IPCResult RecvReplaceActiveSessionHistoryEntry( + const MaybeDiscarded<BrowsingContext>& aContext, + SessionHistoryInfo&& aInfo); + + mozilla::ipc::IPCResult RecvRemoveDynEntriesFromActiveSessionHistoryEntry( + const MaybeDiscarded<BrowsingContext>& aContext); + + mozilla::ipc::IPCResult RecvRemoveFromSessionHistory( + const MaybeDiscarded<BrowsingContext>& aContext, const nsID& aChangeID); + + mozilla::ipc::IPCResult RecvHistoryReload( + const MaybeDiscarded<BrowsingContext>& aContext, + const uint32_t aReloadFlags); + + mozilla::ipc::IPCResult RecvCleanupPendingLoadState(uint64_t aLoadIdentifier); + + // Notify the ContentChild to enable the input event prioritization when + // initializing. + void MaybeEnableRemoteInputEventQueue(); + +#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) + void AppendSandboxParams(std::vector<std::string>& aArgs); + void AppendDynamicSandboxParams(std::vector<std::string>& aArgs); +#endif + + mozilla::ipc::IPCResult RecvFOGData(ByteBuf&& buf); + + mozilla::ipc::IPCResult RecvSetContainerFeaturePolicy( + const MaybeDiscardedBrowsingContext& aContainerContext, + FeaturePolicy* aContainerFeaturePolicy); + + mozilla::ipc::IPCResult RecvGetSystemIcon(nsIURI* aURI, + GetSystemIconResolver&& aResolver); + +#ifdef FUZZING_SNAPSHOT + mozilla::ipc::IPCResult RecvSignalFuzzingReady(); +#endif + + public: + void SendGetFilesResponseAndForget(const nsID& aID, + const GetFilesResponseResult& aResult); + + bool SendRequestMemoryReport(const uint32_t& aGeneration, + const bool& aAnonymize, + const bool& aMinimizeMemoryUsage, + const Maybe<FileDescriptor>& aDMDFile) override; + + void AddBrowsingContextGroup(BrowsingContextGroup* aGroup); + void RemoveBrowsingContextGroup(BrowsingContextGroup* aGroup); + + // See `BrowsingContext::mEpochs` for an explanation of this field. + uint64_t GetBrowsingContextFieldEpoch() const { + return mBrowsingContextFieldEpoch; + } + + void UpdateNetworkLinkType(); + + already_AddRefed<JSActor> InitJSActor(JS::Handle<JSObject*> aMaybeActor, + const nsACString& aName, + ErrorResult& aRv) override; + mozilla::ipc::IProtocol* AsNativeActor() override { return this; } + + static already_AddRefed<nsIPrincipal> CreateRemoteTypeIsolationPrincipal( + const nsACString& aRemoteType); + +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + bool IsBlockingShutdown() { return mBlockShutdownCalled; } +#endif + + ThreadsafeContentParentHandle* ThreadsafeHandle() const { + return mThreadsafeHandle; + } + + void GetIPCTransferableData(nsIDragSession* aSession, BrowserParent* aParent, + nsTArray<IPCTransferableData>& aIPCTransferables); + + private: + // Return an existing ContentParent if possible. Otherwise, `nullptr`. + static already_AddRefed<ContentParent> GetUsedBrowserProcess( + const nsACString& aRemoteType, nsTArray<ContentParent*>& aContentParents, + uint32_t aMaxContentParents, bool aPreferUsed, ProcessPriority aPriority); + + void AddToPool(nsTArray<ContentParent*>&); + void RemoveFromPool(nsTArray<ContentParent*>&); + void AssertNotInPool(); + + void AssertAlive(); + + private: + // If you add strong pointers to cycle collected objects here, be sure to + // release these objects in ShutDownProcess. See the comment there for more + // details. + + GeckoChildProcessHost* mSubprocess; + const TimeStamp mLaunchTS; // used to calculate time to start content process + TimeStamp mLaunchYieldTS; // used to calculate async launch main thread time + TimeStamp mActivateTS; + + bool mIsAPreallocBlocker; // We called AddBlocker for this ContentParent + + nsCString mRemoteType; + nsCString mProfile; + nsCOMPtr<nsIPrincipal> mRemoteTypeIsolationPrincipal; + + ContentParentId mChildID; + int32_t mGeolocationWatchID; + + // After we destroy the last Browser, we also start a timer to ensure + // that even content processes that are not responding will get a + // second chance and a shutdown message. + nsCOMPtr<nsITimer> mSendShutdownTimer; + bool mSentShutdownMessage = false; + + // After we initiate shutdown, we also start a timer to ensure + // that even content processes that are 100% blocked (say from + // SIGSTOP), are still killed eventually. This task enforces that + // timer. + nsCOMPtr<nsITimer> mForceKillTimer; + + // Threadsafe handle object which can be used by actors like PBackground to + // track the identity and other relevant information about the content process + // they're attached to. + const RefPtr<ThreadsafeContentParentHandle> mThreadsafeHandle; + + // How many tabs we're waiting to finish their destruction + // sequence. Precisely, how many BrowserParents have called + // NotifyTabDestroying() but not called NotifyTabDestroyed(). + int32_t mNumDestroyingTabs; + + uint32_t mNumKeepaliveCalls; + + // The process starts in the LAUNCHING state, and transitions to + // ALIVE once it can accept IPC messages. It remains ALIVE only + // while remote content is being actively used from this process. + // After the state becaomes DEAD, some previously scheduled IPC + // traffic may still pass through. + enum class LifecycleState : uint8_t { + LAUNCHING, + ALIVE, + INITIALIZED, + DEAD, + }; + + LifecycleState mLifecycleState; + + uint8_t mIsForBrowser : 1; + + // These variables track whether we've called Close() and KillHard() on our + // channel. + uint8_t mCalledClose : 1; + uint8_t mCalledKillHard : 1; + uint8_t mCreatedPairedMinidumps : 1; + uint8_t mShutdownPending : 1; + + // Whether or not `LaunchSubprocessResolve` has been called, and whether or + // not it returned `true` when called. + uint8_t mLaunchResolved : 1; + uint8_t mLaunchResolvedOk : 1; + + // True if the input event queue on the main thread of the content process is + // enabled. + uint8_t mIsRemoteInputEventQueueEnabled : 1; + + // True if we send input events with input priority. Otherwise, we send input + // events with normal priority. + uint8_t mIsInputPriorityEventEnabled : 1; + + uint8_t mIsInPool : 1; + + // True if we already created a GMP service. + uint8_t mGMPCreated : 1; + +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + bool mNotifiedImpendingShutdownOnTabWillDestroy = false; + bool mBlockShutdownCalled; +#endif + + nsCOMPtr<nsIContentProcessInfo> mScriptableHelper; + + nsTArray<nsCOMPtr<nsIObserver>> mIdleListeners; + +#ifdef MOZ_X11 + // Dup of child's X socket, used to scope its resources to this + // object instead of the child process's lifetime. + UniqueFileHandle mChildXSocketFdDup; +#endif + + RefPtr<PProcessHangMonitorParent> mHangMonitorActor; + + UniquePtr<gfx::DriverCrashGuard> mDriverCrashGuard; + UniquePtr<MemoryReportRequestHost> mMemoryReportRequest; + +#if defined(XP_LINUX) && defined(MOZ_SANDBOX) + mozilla::UniquePtr<SandboxBroker> mSandboxBroker; + static mozilla::StaticAutoPtr<SandboxBrokerPolicyFactory> + sSandboxBrokerPolicyFactory; +#endif + + // This hashtable is used to run GetFilesHelper objects in the parent process. + // GetFilesHelper can be aborted by receiving RecvDeleteGetFilesRequest. + nsRefPtrHashtable<nsIDHashKey, GetFilesHelper> mGetFilesPendingRequests; + + nsTHashSet<nsCString> mActivePermissionKeys; + nsTHashSet<nsCString> mActiveSecondaryPermissionKeys; + + nsTArray<nsCString> mBlobURLs; + + // This is intended to be a memory and time efficient means of determining + // whether an origin has ever existed in a process so that Blob URL broadcast + // doesn't need to transmit every Blob URL to every content process. False + // positives are acceptable because receiving a Blob URL does not grant access + // to its contents, and the act of creating/revoking a Blob is currently + // viewed as an acceptable side-channel leak. In the future bug 1491018 will + // moot the need for this structure. + nsTArray<uint64_t> mLoadedOriginHashes; + + UniquePtr<mozilla::ipc::CrashReporterHost> mCrashReporter; + + // Collects any pref changes that occur during process launch (after + // the initial map is passed in command-line arguments) to be sent + // when the process can receive IPC messages. + nsTArray<Pref> mQueuedPrefs; + + RefPtr<mozilla::dom::ProcessMessageManager> mMessageManager; + +#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) + // When set to true, indicates that content processes should + // initialize their sandbox during startup instead of waiting + // for the SetProcessSandbox IPDL message. + static bool sEarlySandboxInit; +#endif + + nsTHashSet<RefPtr<BrowsingContextGroup>> mGroups; + + // When we request a content process to load a document on our behalf, we'll + // record the nsDocShellLoadState we sent to the content process mapped by the + // load ID. If the load is then requested from the content process, we can + // compare the load state and ensure it matches. + nsTHashMap<uint64_t, RefPtr<nsDocShellLoadState>> mPendingLoadStates; + + // See `BrowsingContext::mEpochs` for an explanation of this field. + uint64_t mBrowsingContextFieldEpoch = 0; + + // A preference serializer used to share preferences with the process. + // Cleared once startup is complete. + UniquePtr<mozilla::ipc::SharedPreferenceSerializer> mPrefSerializer; + + static uint32_t sMaxContentProcesses; + static uint32_t sPageLoadEventCounter; + + bool mIsSignaledImpendingShutdown = false; + bool mIsNotifiedShutdownSuccess = false; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(ContentParent, NS_CONTENTPARENT_IID) + +// Threadsafe handle object allowing off-main-thread code to get some +// information and maintain a weak reference to a ContentParent. +class ThreadsafeContentParentHandle final { + friend class ContentParent; + + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ThreadsafeContentParentHandle); + + // Get the ChildID of this process. Safe to call from any thread. + ContentParentId ChildID() const { return mChildID; } + + // Get the current RemoteType of this ContentParent. Safe to call from any + // thread. If the returned RemoteType is PREALLOC_REMOTE_TYPE, it may change + // again in the future. + nsCString GetRemoteType() MOZ_EXCLUDES(mMutex); + + // Try to get a reference to the real `ContentParent` object from this weak + // reference. This may only be called on the main thread. + already_AddRefed<ContentParent> GetContentParent() + MOZ_REQUIRES(sMainThreadCapability) { + return do_AddRef(mWeakActor); + } + + // Calls `aCallback` with the current remote worker count and whether or not + // shutdown has been started. If the callback returns `true`, registers a new + // actor, and returns `true`, otherwise returns `false`. + // + // NOTE: The internal mutex is held while evaluating `aCallback`. + bool MaybeRegisterRemoteWorkerActor( + MoveOnlyFunction<bool(uint32_t, bool)> aCallback) MOZ_EXCLUDES(mMutex); + + // Like `MaybeRegisterRemoteWorkerActor`, but unconditional. + void RegisterRemoteWorkerActor() MOZ_EXCLUDES(mMutex) { + MaybeRegisterRemoteWorkerActor([](uint32_t, bool) { return true; }); + } + + RecursiveMutex& Mutex() { return mMutex; } + + private: + ThreadsafeContentParentHandle(ContentParent* aActor, ContentParentId aChildID, + const nsACString& aRemoteType) + : mChildID(aChildID), mRemoteType(aRemoteType), mWeakActor(aActor) {} + ~ThreadsafeContentParentHandle() { MOZ_ASSERT(!mWeakActor); } + + mozilla::RecursiveMutex mMutex{"ContentParentIdentity"}; + + const ContentParentId mChildID; + + nsCString mRemoteType MOZ_GUARDED_BY(mMutex); + uint32_t mRemoteWorkerActorCount MOZ_GUARDED_BY(mMutex) = 0; + bool mShutdownStarted MOZ_GUARDED_BY(mMutex) = false; + + // Weak reference to the actual ContentParent actor. Only touched on the main + // thread to read or clear. + ContentParent* mWeakActor MOZ_GUARDED_BY(sMainThreadCapability); +}; + +// This is the C++ version of remoteTypePrefix in E10SUtils.sys.mjs. +const nsDependentCSubstring RemoteTypePrefix( + const nsACString& aContentProcessType); + +// This is based on isWebRemoteType in E10SUtils.sys.mjs. +bool IsWebRemoteType(const nsACString& aContentProcessType); + +bool IsWebCoopCoepRemoteType(const nsACString& aContentProcessType); + +bool IsExtensionRemoteType(const nsACString& aContentProcessType); + +inline nsISupports* ToSupports(mozilla::dom::ContentParent* aContentParent) { + return static_cast<nsIDOMProcessParent*>(aContentParent); +} + +} // namespace dom +} // namespace mozilla + +class ParentIdleListener : public nsIObserver { + friend class mozilla::dom::ContentParent; + + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + ParentIdleListener(mozilla::dom::ContentParent* aParent, uint64_t aObserver, + uint32_t aTime) + : mParent(aParent), mObserver(aObserver), mTime(aTime) {} + + private: + virtual ~ParentIdleListener() = default; + + RefPtr<mozilla::dom::ContentParent> mParent; + uint64_t mObserver; + uint32_t mTime; +}; + +#endif // mozilla_dom_ContentParent_h |