/* -*- 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 _include_ipc_glue_UtilityProcessManager_h_ #define _include_ipc_glue_UtilityProcessManager_h_ #include "mozilla/MozPromise.h" #include "mozilla/dom/ipc/IdType.h" #include "mozilla/ipc/UtilityProcessHost.h" #include "mozilla/EnumeratedArray.h" #include "mozilla/ProcInfo.h" #include "nsIObserver.h" #include "nsTArray.h" #include "mozilla/PRemoteDecoderManagerChild.h" namespace mozilla { class MemoryReportingProcess; namespace dom { class JSOracleParent; class WindowsUtilsParent; } // namespace dom namespace ipc { class UtilityProcessParent; // The UtilityProcessManager is a singleton responsible for creating // Utility-bound objects that may live in another process. Currently, it // provides access to the Utility process via ContentParent. class UtilityProcessManager final : public UtilityProcessHost::Listener { friend class UtilityProcessParent; public: using StartRemoteDecodingUtilityPromise = MozPromise, nsresult, true>; using JSOraclePromise = GenericNonExclusivePromise; using WindowsUtilsPromise = MozPromise, nsresult, true>; static void Initialize(); static void Shutdown(); static RefPtr GetSingleton(); static RefPtr GetIfExists(); // Launch a new Utility process asynchronously RefPtr LaunchProcess(SandboxingKind aSandbox); template RefPtr StartUtility(RefPtr aActor, SandboxingKind aSandbox); RefPtr StartProcessForRemoteMediaDecoding( base::ProcessId aOtherProcess, dom::ContentParentId aChildId, SandboxingKind aSandbox); RefPtr StartJSOracle(mozilla::dom::JSOracleParent* aParent); #ifdef XP_WIN // Get the (possibly already resolved) promise for the Windows utility // process actor. Creates the process if it is not running. RefPtr GetWindowsUtilsPromise(); // Releases the WindowsUtils actor so that it can be destroyed. // Subsequent attempts to use WindowsUtils will create a new process. void ReleaseWindowsUtils(); #endif void OnProcessUnexpectedShutdown(UtilityProcessHost* aHost); // Returns the platform pid for this utility sandbox process. Maybe ProcessPid(SandboxingKind aSandbox); // Create a MemoryReportingProcess object for this utility process RefPtr GetProcessMemoryReporter( UtilityProcessParent* parent); // Returns access to the PUtility protocol if a Utility process for that // sandbox is present. RefPtr GetProcessParent(SandboxingKind aSandbox) { RefPtr p = GetProcess(aSandbox); if (!p) { return nullptr; } return p->mProcessParent; } // Get a list of all valid utility process parent references nsTArray> GetAllProcessesProcessParent() { nsTArray> rv; for (auto& p : mProcesses) { if (p && p->mProcessParent) { rv.AppendElement(p->mProcessParent); } } return rv; } // Returns the Utility Process for that sandbox UtilityProcessHost* Process(SandboxingKind aSandbox) { RefPtr p = GetProcess(aSandbox); if (!p) { return nullptr; } return p->mProcess; } void RegisterActor(const RefPtr& aParent, UtilityActorName aActorName) { for (auto& p : mProcesses) { if (p && p->mProcessParent && p->mProcessParent == aParent) { p->mActors.AppendElement(aActorName); return; } } } Span GetActors( const RefPtr& aParent) { for (auto& p : mProcesses) { if (p && p->mProcessParent && p->mProcessParent == aParent) { return p->mActors; } } return {}; } Span GetActors(GeckoChildProcessHost* aHost) { for (auto& p : mProcesses) { if (p && p->mProcess == aHost) { return p->mActors; } } return {}; } Span GetActors(SandboxingKind aSbKind) { auto proc = GetProcess(aSbKind); if (!proc) { return {}; } return proc->mActors; } // Shutdown the Utility process for that sandbox. void CleanShutdown(SandboxingKind aSandbox); // Shutdown all utility processes void CleanShutdownAllProcesses(); uint16_t AliveProcesses(); private: ~UtilityProcessManager(); bool IsProcessLaunching(SandboxingKind aSandbox); bool IsProcessDestroyed(SandboxingKind aSandbox); // Called from our xpcom-shutdown observer. void OnXPCOMShutdown(); void OnPreferenceChange(const char16_t* aData); UtilityProcessManager(); void DestroyProcess(SandboxingKind aSandbox); bool IsShutdown() const; class Observer final : public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER explicit Observer(RefPtr aManager); protected: ~Observer() = default; RefPtr mManager; }; friend class Observer; RefPtr mObserver; class ProcessFields final { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProcessFields); explicit ProcessFields(SandboxingKind aSandbox) : mSandbox(aSandbox){}; // Promise will be resolved when this Utility process has been fully started // and configured. Only accessed on the main thread. RefPtr mLaunchPromise; uint32_t mNumProcessAttempts = 0; uint32_t mNumUnexpectedCrashes = 0; // Fields that are associated with the current Utility process. UtilityProcessHost* mProcess = nullptr; RefPtr mProcessParent = nullptr; // 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; nsTArray mActors; SandboxingKind mSandbox = SandboxingKind::COUNT; protected: ~ProcessFields() = default; }; EnumeratedArray> mProcesses; RefPtr GetProcess(SandboxingKind); bool NoMoreProcesses(); #ifdef XP_WIN RefPtr mWindowsUtils; #endif // XP_WIN }; } // namespace ipc } // namespace mozilla #endif // _include_ipc_glue_UtilityProcessManager_h_