diff options
Diffstat (limited to 'ipc/glue/UtilityProcessManager.h')
-rw-r--r-- | ipc/glue/UtilityProcessManager.h | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/ipc/glue/UtilityProcessManager.h b/ipc/glue/UtilityProcessManager.h new file mode 100644 index 0000000000..2ad3f5041c --- /dev/null +++ b/ipc/glue/UtilityProcessManager.h @@ -0,0 +1,234 @@ +/* -*- 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<Endpoint<PRemoteDecoderManagerChild>, nsresult, true>; + using JSOraclePromise = GenericNonExclusivePromise; + + using WindowsUtilsPromise = + MozPromise<RefPtr<dom::WindowsUtilsParent>, nsresult, true>; + + static void Initialize(); + static void Shutdown(); + + static RefPtr<UtilityProcessManager> GetSingleton(); + + static RefPtr<UtilityProcessManager> GetIfExists(); + + // Launch a new Utility process asynchronously + RefPtr<GenericNonExclusivePromise> LaunchProcess(SandboxingKind aSandbox); + + template <typename Actor> + RefPtr<GenericNonExclusivePromise> StartUtility(RefPtr<Actor> aActor, + SandboxingKind aSandbox); + + RefPtr<StartRemoteDecodingUtilityPromise> StartProcessForRemoteMediaDecoding( + base::ProcessId aOtherProcess, dom::ContentParentId aChildId, + SandboxingKind aSandbox); + + RefPtr<JSOraclePromise> 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<WindowsUtilsPromise> 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<base::ProcessId> ProcessPid(SandboxingKind aSandbox); + + // Create a MemoryReportingProcess object for this utility process + RefPtr<MemoryReportingProcess> GetProcessMemoryReporter( + UtilityProcessParent* parent); + + // Returns access to the PUtility protocol if a Utility process for that + // sandbox is present. + RefPtr<UtilityProcessParent> GetProcessParent(SandboxingKind aSandbox) { + RefPtr<ProcessFields> p = GetProcess(aSandbox); + if (!p) { + return nullptr; + } + return p->mProcessParent; + } + + // Get a list of all valid utility process parent references + nsTArray<RefPtr<UtilityProcessParent>> GetAllProcessesProcessParent() { + nsTArray<RefPtr<UtilityProcessParent>> 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<ProcessFields> p = GetProcess(aSandbox); + if (!p) { + return nullptr; + } + return p->mProcess; + } + + void RegisterActor(const RefPtr<UtilityProcessParent>& aParent, + UtilityActorName aActorName) { + for (auto& p : mProcesses) { + if (p && p->mProcessParent && p->mProcessParent == aParent) { + p->mActors.AppendElement(aActorName); + return; + } + } + } + + Span<const UtilityActorName> GetActors( + const RefPtr<UtilityProcessParent>& aParent) { + for (auto& p : mProcesses) { + if (p && p->mProcessParent && p->mProcessParent == aParent) { + return p->mActors; + } + } + return {}; + } + + Span<const UtilityActorName> GetActors(GeckoChildProcessHost* aHost) { + for (auto& p : mProcesses) { + if (p && p->mProcess == aHost) { + return p->mActors; + } + } + return {}; + } + + Span<const UtilityActorName> 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<UtilityProcessManager> aManager); + + protected: + ~Observer() = default; + + RefPtr<UtilityProcessManager> mManager; + }; + friend class Observer; + + RefPtr<Observer> 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<GenericNonExclusivePromise> mLaunchPromise; + + uint32_t mNumProcessAttempts = 0; + uint32_t mNumUnexpectedCrashes = 0; + + // Fields that are associated with the current Utility process. + UtilityProcessHost* mProcess = nullptr; + RefPtr<UtilityProcessParent> 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<dom::Pref> mQueuedPrefs; + + nsTArray<UtilityActorName> mActors; + + SandboxingKind mSandbox = SandboxingKind::COUNT; + + protected: + ~ProcessFields() = default; + }; + + EnumeratedArray<SandboxingKind, SandboxingKind::COUNT, RefPtr<ProcessFields>> + mProcesses; + + RefPtr<ProcessFields> GetProcess(SandboxingKind); + bool NoMoreProcesses(); + +#ifdef XP_WIN + RefPtr<dom::WindowsUtilsParent> mWindowsUtils; +#endif // XP_WIN +}; + +} // namespace ipc + +} // namespace mozilla + +#endif // _include_ipc_glue_UtilityProcessManager_h_ |