1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
/* -*- 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/PRemoteMediaManagerChild.h"
namespace mozilla {
class MemoryReportingProcess;
namespace dom {
class JSOracleParent;
class WindowsUtilsParent;
} // namespace dom
namespace widget::filedialog {
class ProcessProxy;
} // namespace widget::filedialog
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:
template <typename T>
using LaunchPromise = MozPromise<T, LaunchError, true>;
template <typename T>
using SharedLaunchPromise = MozPromise<T, LaunchError, false>;
using StartRemoteDecodingUtilityPromise =
LaunchPromise<Endpoint<PRemoteMediaManagerChild>>;
using JSOraclePromise = GenericNonExclusivePromise;
#ifdef XP_WIN
using WindowsUtilsPromise = LaunchPromise<RefPtr<dom::WindowsUtilsParent>>;
using WinFileDialogPromise = LaunchPromise<widget::filedialog::ProcessProxy>;
#endif
static RefPtr<UtilityProcessManager> GetSingleton();
static RefPtr<UtilityProcessManager> GetIfExists();
// Launch a new Utility process asynchronously
RefPtr<SharedLaunchPromise<Ok>> LaunchProcess(SandboxingKind aSandbox);
template <typename Actor>
RefPtr<LaunchPromise<Ok>> StartUtility(RefPtr<Actor> aActor,
SandboxingKind aSandbox);
RefPtr<StartRemoteDecodingUtilityPromise> StartProcessForRemoteMediaDecoding(
EndpointProcInfo 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();
// Get a new Windows file-dialog utility-process actor. These are never
// reused; this will always return a fresh actor.
RefPtr<WinFileDialogPromise> CreateWinFileDialogActor();
#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 Init();
void DestroyProcess(SandboxingKind aSandbox);
bool IsShutdown() const;
class Observer final : public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
explicit Observer(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<SharedLaunchPromise<Ok>> 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, RefPtr<ProcessFields>,
size_t(SandboxingKind::COUNT)>
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_
|