/* -*- 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/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/FileUtils.h" #include "mozilla/HalTypes.h" #include "mozilla/LinkedList.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReportingProcess.h" #include "mozilla/MozPromise.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 "nsPluginTags.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, 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, nsresult, false>; NS_DECLARE_STATIC_IID_ACCESSOR(NS_CONTENTPARENT_IID) static LogModule* GetLog(); static ContentParent* Cast(PContentParent* aActor) { return static_cast(aActor); } /** * Create a ContentParent suitable for use later as a content process. */ static already_AddRefed 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 MinTabSelect( const nsTArray& aContentParents, int32_t maxContentParents); /** * Get or create a content process for: * 1. browser iframe * 2. remote xul * 3. normal iframe */ static RefPtr GetNewOrUsedBrowserProcessAsync( const nsACString& aRemoteType, BrowsingContextGroup* aGroup = nullptr, hal::ProcessPriority aPriority = hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND, bool aPreferUsed = false); static already_AddRefed 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 GetNewOrUsedLaunchingBrowserProcess( const nsACString& aRemoteType, BrowsingContextGroup* aGroup = nullptr, hal::ProcessPriority aPriority = hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND, bool aPreferUsed = false); RefPtr 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 a JS plugin. aPluginID is the id of the * JS plugin * (@see nsFakePlugin::mId). There is a maximum of one process per JS plugin. */ static already_AddRefed GetNewOrUsedJSPluginProcess( uint32_t aPluginID, const hal::ProcessPriority& aPriority); /** * 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 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& aArray); static void GetAllEvenIfDead(nsTArray& 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::getNext(); } return *this; } ContentParentIterator end() { return ContentParentIterator(mPolicy, nullptr); } const ContentParentIterator& operator++() { MOZ_ASSERT(mCurrent); do { mCurrent = mCurrent->LinkedListElement::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(); mozilla::ipc::IPCResult RecvRemovePermission( nsIPrincipal* aPrincipal, const nsACString& aPermissionType, nsresult* aRv); 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; /** 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; } bool IsForJSPlugin() const { return mJSPluginID != nsFakePluginTag::NOT_JSPLUGIN; } GeckoChildProcessHost* Process() const { return mSubprocess; } nsIContentProcessInfo* ScriptableHelper() const { return mScriptableHelper; } mozilla::dom::ProcessMessageManager* GetMessageManager() const { return mMessageManager; } bool NeedsPermissionsUpdate(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 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 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(); mozilla::ipc::IPCResult RecvRecordingDeviceEvents( const nsAString& aRecordingStatus, const nsAString& aPageURL, const bool& aIsAudio, const bool& aIsVideo); 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); PContentPermissionRequestParent* AllocPContentPermissionRequestParent( const nsTArray& 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& aParent, PBrowserParent* aNewTab, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aForPrinting, const bool& aForWindowDotPrint, nsIURI* aURIToLoad, const nsACString& aFeatures, nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, nsIReferrerInfo* aReferrerInfo, const OriginAttributes& aOriginAttributes, CreateWindowResolver&& aResolve); mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess( PBrowserParent* aThisTab, const MaybeDiscarded& aParent, const uint32_t& aChromeFlags, const bool& aCalledFromJS, nsIURI* aURIToLoad, const nsACString& aFeatures, const nsAString& aName, nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, nsIReferrerInfo* aReferrerInfo, const OriginAttributes& aOriginAttributes); static void BroadcastBlobURLRegistration( const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal, const Maybe& aAgentClusterId, 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 Maybe& aAgentCluster); 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& aFeatures); virtual mozilla::ipc::IPCResult RecvPURLClassifierLocalConstructor( PURLClassifierLocalParent* aActor, nsIURI* aURI, nsTArray&& aFeatures) override; PLoginReputationParent* AllocPLoginReputationParent(nsIURI* aURI); virtual mozilla::ipc::IPCResult RecvPLoginReputationConstructor( PLoginReputationParent* aActor, nsIURI* aURI) override; bool DeallocPLoginReputationParent(PLoginReputationParent* aActor); 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* aBrowserParent, const layers::LayersObserverEpoch& aEpoch); void UnloadLayersWhileInterruptingJS( BrowserParent* aBrowserParent, const layers::LayersObserverEpoch& aEpoch); void CancelContentJSExecutionIfRunning( BrowserParent* aBrowserParent, nsIRemoteTab::NavigationType aNavigationType, const CancelContentJSOptions& aCancelContentJSOptions); // 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& 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& aContext, bool aDoDiscard, DiscardBrowsingContextResolver&& aResolve); mozilla::ipc::IPCResult RecvWindowClose( const MaybeDiscarded& aContext, bool aTrustedCaller); mozilla::ipc::IPCResult RecvWindowFocus( const MaybeDiscarded& aContext, CallerType aCallerType, uint64_t aActionId); mozilla::ipc::IPCResult RecvWindowBlur( const MaybeDiscarded& aContext, CallerType aCallerType); mozilla::ipc::IPCResult RecvRaiseWindow( const MaybeDiscarded& aContext, CallerType aCallerType, uint64_t aActionId); mozilla::ipc::IPCResult RecvAdjustWindowFocus( const MaybeDiscarded& aContext, bool aIsVisible, uint64_t aActionId); mozilla::ipc::IPCResult RecvClearFocus( const MaybeDiscarded& aContext); mozilla::ipc::IPCResult RecvSetFocusedBrowsingContext( const MaybeDiscarded& aContext, uint64_t aActionId); mozilla::ipc::IPCResult RecvSetActiveBrowsingContext( const MaybeDiscarded& aContext, uint64_t aActionId); mozilla::ipc::IPCResult RecvUnsetActiveBrowsingContext( const MaybeDiscarded& aContext, uint64_t aActionId); mozilla::ipc::IPCResult RecvSetFocusedElement( const MaybeDiscarded& aContext, bool aNeedsFocus); mozilla::ipc::IPCResult RecvFinalizeFocusOuter( const MaybeDiscarded& aContext, bool aCanFocus, CallerType aCallerType); mozilla::ipc::IPCResult RecvInsertNewFocusActionId(uint64_t aActionId); mozilla::ipc::IPCResult RecvBlurToParent( const MaybeDiscarded& aFocusedBrowsingContext, const MaybeDiscarded& aBrowsingContextToClear, const MaybeDiscarded& aAncestorBrowsingContextToFocus, bool aIsLeavingDocument, bool aAdjustWidget, bool aBrowsingContextToClearHandled, bool aAncestorBrowsingContextToFocusHandled, uint64_t aActionId); mozilla::ipc::IPCResult RecvMaybeExitFullscreen( const MaybeDiscarded& aContext); mozilla::ipc::IPCResult RecvWindowPostMessage( const MaybeDiscarded& 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 Maybe& aAgentClusterId, 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>* sBrowserContentParents; static mozilla::StaticAutoPtr> sJSPluginContentParents; static mozilla::StaticAutoPtr> 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 sRecycledE10SProcess; void AddShutdownBlockers(); void RemoveShutdownBlockers(); #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) // Cached Mac sandbox params used when launching content processes. static mozilla::StaticAutoPtr> 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, BrowserParent* aNextRemoteBrowser, const nsAString& aName, nsresult& aResult, nsCOMPtr& aNewRemoteTab, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, nsIReferrerInfo* aReferrerInfo, bool aLoadUri, nsIContentSecurityPolicy* aCsp, const OriginAttributes& aOriginAttributes); explicit ContentParent(int32_t aPluginID) : ContentParent(""_ns, aPluginID) {} explicit ContentParent(const nsACString& aRemoteType) : ContentParent(aRemoteType, nsFakePluginTag::NOT_JSPLUGIN) {} ContentParent(const nsACString& aRemoteType, int32_t aPluginID); // 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 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 or JSPlugin */ bool HasActiveWorkerOrJSPlugin(); /** * 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, // Close the channel with error and let the subprocess clean up itself. CLOSE_CHANNEL_WITH_ERROR, }; void MaybeAsyncSendShutDownMessage(); /** * Exit the subprocess and vamoose. After this call IsAlive() * will return false and this ContentParent will not be returned * by the Get*() funtions. However, the shutdown sequence itself * may be asynchronous. * * If aMethod is CLOSE_CHANNEL_WITH_ERROR and this is the first call * to ShutDownProcess, then we'll close our channel using CloseWithError() * rather than vanilla Close(). CloseWithError() indicates to IPC that this * is an abnormal shutdown (e.g. a crash). */ bool ShutDownProcess(ShutDownMethod aMethod); // Perform any steps necesssary to gracefully shtudown the message // manager and null out mMessageManager. void ShutDownMessageManager(); // 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 ForceKillTimerCallback(nsITimer* aTimer, void* aClosure); bool CanOpenBrowser(const IPCTabContext& aContext); /** * Get or create the corresponding content parent array to * |aContentProcessType|. */ static nsTArray& GetOrCreatePool( const nsACString& aContentProcessType); mozilla::ipc::IPCResult RecvInitBackground( Endpoint&& aEndpoint); mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport); mozilla::ipc::IPCResult RecvAddPerformanceMetrics( const nsID& aID, nsTArray&& aMetrics); bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*); mozilla::ipc::IPCResult RecvCloneDocumentTreeInto( const MaybeDiscarded& aSource, const MaybeDiscarded& aTarget, PrintData&& aPrintData); mozilla::ipc::IPCResult RecvUpdateRemotePrintSettings( const MaybeDiscarded& aTarget, PrintData&& aPrintData); mozilla::ipc::IPCResult RecvConstructPopupBrowser( ManagedEndpoint&& actor, ManagedEndpoint&& 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); PTestShellParent* AllocPTestShellParent(); bool DeallocPTestShellParent(PTestShellParent* shell); PScriptCacheParent* AllocPScriptCacheParent(const FileDescOrError& cacheFile, const bool& wantCacheData); bool DeallocPScriptCacheParent(PScriptCacheParent* shell); already_AddRefed AllocPExternalHelperAppParent( nsIURI* aUri, const Maybe& 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& aContext, const bool& aShouldCloseWindow); mozilla::ipc::IPCResult RecvPExternalHelperAppConstructor( PExternalHelperAppParent* actor, nsIURI* uri, const Maybe& 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& aContext, const bool& aShouldCloseWindow) override; already_AddRefed AllocPHandlerServiceParent(); PMediaParent* AllocPMediaParent(); bool DeallocPMediaParent(PMediaParent* aActor); PBenchmarkStorageParent* AllocPBenchmarkStorageParent(); bool DeallocPBenchmarkStorageParent(PBenchmarkStorageParent* aActor); #ifdef MOZ_WEBSPEECH PSpeechSynthesisParent* AllocPSpeechSynthesisParent(); bool DeallocPSpeechSynthesisParent(PSpeechSynthesisParent* aActor); virtual mozilla::ipc::IPCResult RecvPSpeechSynthesisConstructor( PSpeechSynthesisParent* aActor) override; #endif PWebBrowserPersistDocumentParent* AllocPWebBrowserPersistDocumentParent( PBrowserParent* aBrowser, const MaybeDiscarded& aContext); bool DeallocPWebBrowserPersistDocumentParent( PWebBrowserPersistDocumentParent* aActor); mozilla::ipc::IPCResult RecvGetGfxVars(nsTArray* aVars); mozilla::ipc::IPCResult RecvSetClipboard(const IPCTransferable& aTransferable, const int32_t& aWhichClipboard); mozilla::ipc::IPCResult RecvGetClipboard( nsTArray&& aTypes, const int32_t& aWhichClipboard, IPCTransferableData* aTransferableData); mozilla::ipc::IPCResult RecvEmptyClipboard(const int32_t& aWhichClipboard); mozilla::ipc::IPCResult RecvClipboardHasType(nsTArray&& aTypes, const int32_t& aWhichClipboard, bool* aHasType); mozilla::ipc::IPCResult RecvClipboardHasTypesAsync( nsTArray&& aTypes, const int32_t& aWhichClipboard, ClipboardHasTypesAsyncResolver&& aResolver); mozilla::ipc::IPCResult RecvGetExternalClipboardFormats( const int32_t& aWhichClipboard, const bool& aPlainTextOnly, nsTArray* aTypes); mozilla::ipc::IPCResult RecvGetClipboardAsync( nsTArray&& aTypes, const int32_t& aWhichClipboard, GetClipboardAsyncResolver&& aResolver); already_AddRefed AllocPClipboardWriteRequestParent(const int32_t& aClipboardType); mozilla::ipc::IPCResult RecvPlaySound(nsIURI* aURI); mozilla::ipc::IPCResult RecvBeep(); mozilla::ipc::IPCResult RecvPlayEventSound(const uint32_t& aEventId); mozilla::ipc::IPCResult RecvGetIconForExtension(const nsACString& aFileExt, const uint32_t& aIconSize, nsTArray* bits); mozilla::ipc::IPCResult RecvStartVisitedQueries( const nsTArray>&); 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& aContext, bool aWasExternallyTriggered, bool aHasValidUserGestureActivation); mozilla::ipc::IPCResult RecvExtProtocolChannelConnectParent( const uint64_t& registrarId); mozilla::ipc::IPCResult RecvSyncMessage( const nsAString& aMsg, const ClonedMessageData& aData, nsTArray* 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 mozilla::Maybe& loadInfoArgs, const nsAString& entryName, const nsAString& initiatorType, UniquePtr&& 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& aContext, BrowsingContext::BaseTransaction&& aTransaction, uint64_t aEpoch); mozilla::ipc::IPCResult RecvCommitWindowContextTransaction( const MaybeDiscarded& aContext, WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch); mozilla::ipc::IPCResult RecvAddSecurityState( const MaybeDiscarded& 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&&, 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 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 RecvGetGraphicsDeviceInitData( ContentDeviceData* aOut); mozilla::ipc::IPCResult RecvGetOutputColorProfileData( nsTArray* aOutputColorProfileData); 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 mozilla::fontlist::Pointer& aFacePtr, 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 mozilla::fontlist::Pointer& aFamilyPtr); 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&& 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&& aAccumulations); mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms( nsTArray&& aAccumulations); mozilla::ipc::IPCResult RecvUpdateChildScalars( nsTArray&& aScalarActions); mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars( nsTArray&& aScalarActions); mozilla::ipc::IPCResult RecvRecordChildEvents( nsTArray&& 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& aParentContext, nsIPrincipal* aTrackingPrincipal, const nsACString& aTrackingOrigin, const int& aAllowMode, const Maybe< ContentBlockingNotifier::StorageAccessPermissionGrantedReason>& aReason, StorageAccessPermissionGrantedForOriginResolver&& aResolver); mozilla::ipc::IPCResult RecvCompleteAllowAccessFor( const MaybeDiscarded& 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& aContext, nsIPrincipal* aPrincipal, const TestCookiePermissionDecidedResolver&& aResolver); mozilla::ipc::IPCResult RecvTestStorageAccessPermission( nsIPrincipal* aEmbeddingPrincipal, const nsCString& aEmbeddedOrigin, const TestStorageAccessPermissionResolver&& aResolver); mozilla::ipc::IPCResult RecvNotifyMediaPlaybackChanged( const MaybeDiscarded& aContext, MediaPlaybackState aState); mozilla::ipc::IPCResult RecvNotifyMediaAudibleChanged( const MaybeDiscarded& aContext, MediaAudibleState aState); mozilla::ipc::IPCResult RecvNotifyPictureInPictureModeChanged( const MaybeDiscarded& aContext, bool aEnabled); mozilla::ipc::IPCResult RecvNotifyMediaSessionUpdated( const MaybeDiscarded& aContext, bool aIsCreated); mozilla::ipc::IPCResult RecvNotifyUpdateMediaMetadata( const MaybeDiscarded& aContext, const Maybe& aMetadata); mozilla::ipc::IPCResult RecvNotifyMediaSessionPlaybackStateChanged( const MaybeDiscarded& aContext, MediaSessionPlaybackState aPlaybackState); mozilla::ipc::IPCResult RecvNotifyMediaSessionSupportedActionChanged( const MaybeDiscarded& aContext, MediaSessionAction aAction, bool aEnabled); mozilla::ipc::IPCResult RecvNotifyMediaFullScreenState( const MaybeDiscarded& aContext, bool aIsInFullScreen); mozilla::ipc::IPCResult RecvNotifyPositionStateChanged( const MaybeDiscarded& aContext, const PositionState& aState); mozilla::ipc::IPCResult RecvAddOrRemovePageAwakeRequest( const MaybeDiscarded& 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& aData, const Maybe& aStack); mozilla::ipc::IPCResult RecvAbortOtherOrientationPendingPromises( const MaybeDiscarded& aContext); mozilla::ipc::IPCResult RecvNotifyOnHistoryReload( const MaybeDiscarded& aContext, const bool& aForceReload, NotifyOnHistoryReloadResolver&& aResolver); mozilla::ipc::IPCResult RecvHistoryCommit( const MaybeDiscarded& 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& aContext, int32_t aOffset, uint64_t aHistoryEpoch, bool aRequireUserInteraction, bool aUserActivation, HistoryGoResolver&& aResolveRequestedIndex); mozilla::ipc::IPCResult RecvSynchronizeLayoutHistoryState( const MaybeDiscarded& aContext, nsILayoutHistoryState* aState); mozilla::ipc::IPCResult RecvSessionHistoryEntryTitle( const MaybeDiscarded& aContext, const nsAString& aTitle); mozilla::ipc::IPCResult RecvSessionHistoryEntryScrollRestorationIsManual( const MaybeDiscarded& aContext, const bool& aIsManual); mozilla::ipc::IPCResult RecvSessionHistoryEntryScrollPosition( const MaybeDiscarded& aContext, const int32_t& aX, const int32_t& aY); mozilla::ipc::IPCResult RecvSessionHistoryEntryCacheKey( const MaybeDiscarded& aContext, const uint32_t& aCacheKey); mozilla::ipc::IPCResult RecvSessionHistoryEntryWireframe( const MaybeDiscarded& aContext, const Wireframe& aWireframe); mozilla::ipc::IPCResult RecvSessionHistoryEntryStoreWindowNameInContiguousEntries( const MaybeDiscarded& aContext, const nsAString& aName); mozilla::ipc::IPCResult RecvGetLoadingSessionHistoryInfoFromParent( const MaybeDiscarded& aContext, GetLoadingSessionHistoryInfoFromParentResolver&& aResolver); mozilla::ipc::IPCResult RecvRemoveFromBFCache( const MaybeDiscarded& aContext); mozilla::ipc::IPCResult RecvSetActiveSessionHistoryEntry( const MaybeDiscarded& aContext, const Maybe& aPreviousScrollPos, SessionHistoryInfo&& aInfo, uint32_t aLoadType, uint32_t aUpdatedCacheKey, const nsID& aChangeID); mozilla::ipc::IPCResult RecvReplaceActiveSessionHistoryEntry( const MaybeDiscarded& aContext, SessionHistoryInfo&& aInfo); mozilla::ipc::IPCResult RecvRemoveDynEntriesFromActiveSessionHistoryEntry( const MaybeDiscarded& aContext); mozilla::ipc::IPCResult RecvRemoveFromSessionHistory( const MaybeDiscarded& aContext, const nsID& aChangeID); mozilla::ipc::IPCResult RecvHistoryReload( const MaybeDiscarded& 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& aArgs); void AppendDynamicSandboxParams(std::vector& 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& 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 InitJSActor(JS::Handle aMaybeActor, const nsACString& aName, ErrorResult& aRv) override; mozilla::ipc::IProtocol* AsNativeActor() override { return this; } static already_AddRefed CreateRemoteTypeIsolationPrincipal( const nsACString& aRemoteType); #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED bool IsBlockingShutdown() { return mBlockShutdownCalled; } #endif ThreadsafeContentParentHandle* ThreadsafeHandle() const { return mThreadsafeHandle; } private: // Return an existing ContentParent if possible. Otherwise, `nullptr`. static already_AddRefed GetUsedBrowserProcess( const nsACString& aRemoteType, nsTArray& aContentParents, uint32_t aMaxContentParents, bool aPreferUsed, ProcessPriority aPriority); void AddToPool(nsTArray&); void RemoveFromPool(nsTArray&); 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 mRemoteTypeIsolationPrincipal; ContentParentId mChildID; int32_t mGeolocationWatchID; // This contains the id for the JS plugin (@see nsFakePluginTag) if this is // the ContentParent for a process containing iframes for that JS plugin. If // this is not a ContentParent for a JS plugin then it contains the value // nsFakePluginTag::NOT_JSPLUGIN. int32_t mJSPluginID; // 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 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 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 mScriptableHelper; nsTArray> 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. ScopedClose mChildXSocketFdDup; #endif RefPtr mHangMonitorActor; UniquePtr mDriverCrashGuard; UniquePtr mMemoryReportRequest; #if defined(XP_LINUX) && defined(MOZ_SANDBOX) mozilla::UniquePtr mSandboxBroker; static mozilla::StaticAutoPtr sSandboxBrokerPolicyFactory; #endif // This hashtable is used to run GetFilesHelper objects in the parent process. // GetFilesHelper can be aborted by receiving RecvDeleteGetFilesRequest. nsRefPtrHashtable mGetFilesPendingRequests; nsTHashSet mActivePermissionKeys; nsTArray 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 mLoadedOriginHashes; UniquePtr 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 mQueuedPrefs; RefPtr 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> 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> 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 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 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 aCallback) MOZ_EXCLUDES(mMutex); // Like `MaybeRegisterRemoteWorkerActor`, but unconditional. void RegisterRemoteWorkerActor() MOZ_EXCLUDES(mMutex) { MaybeRegisterRemoteWorkerActor([](uint32_t, bool) { return true; }); } private: ThreadsafeContentParentHandle(ContentParent* aActor, ContentParentId aChildID, const nsACString& aRemoteType) : mChildID(aChildID), mRemoteType(aRemoteType), mWeakActor(aActor) {} ~ThreadsafeContentParentHandle() { MOZ_ASSERT(!mWeakActor); } mozilla::Mutex 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 IsPrivilegedMozillaRemoteType(const nsACString& aContentProcessType); bool IsExtensionRemoteType(const nsACString& aContentProcessType); inline nsISupports* ToSupports(mozilla::dom::ContentParent* aContentParent) { return static_cast(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 mParent; uint64_t mObserver; uint32_t mTime; }; #endif // mozilla_dom_ContentParent_h