UtilityProcessManager.h (7478B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #ifndef _include_ipc_glue_UtilityProcessManager_h_ 7 #define _include_ipc_glue_UtilityProcessManager_h_ 8 #include "mozilla/MozPromise.h" 9 #include "mozilla/dom/ipc/IdType.h" 10 #include "mozilla/ipc/UtilityProcessHost.h" 11 #include "mozilla/EnumeratedArray.h" 12 #include "mozilla/ProcInfo.h" 13 #include "nsIObserver.h" 14 #include "nsTArray.h" 15 16 #include "mozilla/PRemoteMediaManagerChild.h" 17 18 namespace mozilla { 19 20 class MemoryReportingProcess; 21 22 namespace dom { 23 class JSOracleParent; 24 class WindowsUtilsParent; 25 } // namespace dom 26 27 namespace widget::filedialog { 28 class ProcessProxy; 29 } // namespace widget::filedialog 30 31 namespace ipc { 32 33 class UtilityProcessParent; 34 35 // The UtilityProcessManager is a singleton responsible for creating 36 // Utility-bound objects that may live in another process. Currently, it 37 // provides access to the Utility process via ContentParent. 38 class UtilityProcessManager final : public UtilityProcessHost::Listener { 39 friend class UtilityProcessParent; 40 41 public: 42 template <typename T> 43 using LaunchPromise = MozPromise<T, LaunchError, true>; 44 template <typename T> 45 using SharedLaunchPromise = MozPromise<T, LaunchError, false>; 46 47 using StartRemoteDecodingUtilityPromise = 48 LaunchPromise<Endpoint<PRemoteMediaManagerChild>>; 49 using JSOraclePromise = GenericNonExclusivePromise; 50 51 #ifdef XP_WIN 52 using WindowsUtilsPromise = LaunchPromise<RefPtr<dom::WindowsUtilsParent>>; 53 using WinFileDialogPromise = LaunchPromise<widget::filedialog::ProcessProxy>; 54 #endif 55 56 static RefPtr<UtilityProcessManager> GetSingleton(); 57 58 static RefPtr<UtilityProcessManager> GetIfExists(); 59 60 // Launch a new Utility process asynchronously 61 RefPtr<SharedLaunchPromise<Ok>> LaunchProcess(SandboxingKind aSandbox); 62 63 template <typename Actor> 64 RefPtr<LaunchPromise<Ok>> StartUtility(RefPtr<Actor> aActor, 65 SandboxingKind aSandbox); 66 67 RefPtr<StartRemoteDecodingUtilityPromise> StartProcessForRemoteMediaDecoding( 68 EndpointProcInfo aOtherProcess, dom::ContentParentId aChildId, 69 SandboxingKind aSandbox); 70 71 RefPtr<JSOraclePromise> StartJSOracle(mozilla::dom::JSOracleParent* aParent); 72 73 #ifdef XP_WIN 74 // Get the (possibly already resolved) promise for the Windows utility 75 // process actor. Creates the process if it is not running. 76 RefPtr<WindowsUtilsPromise> GetWindowsUtilsPromise(); 77 // Releases the WindowsUtils actor so that it can be destroyed. 78 // Subsequent attempts to use WindowsUtils will create a new process. 79 void ReleaseWindowsUtils(); 80 81 // Get a new Windows file-dialog utility-process actor. These are never 82 // reused; this will always return a fresh actor. 83 RefPtr<WinFileDialogPromise> CreateWinFileDialogActor(); 84 #endif 85 86 void OnProcessUnexpectedShutdown(UtilityProcessHost* aHost); 87 88 // Returns the platform pid for this utility sandbox process. 89 Maybe<base::ProcessId> ProcessPid(SandboxingKind aSandbox); 90 91 // Create a MemoryReportingProcess object for this utility process 92 RefPtr<MemoryReportingProcess> GetProcessMemoryReporter( 93 UtilityProcessParent* parent); 94 95 // Returns access to the PUtility protocol if a Utility process for that 96 // sandbox is present. 97 RefPtr<UtilityProcessParent> GetProcessParent(SandboxingKind aSandbox) { 98 RefPtr<ProcessFields> p = GetProcess(aSandbox); 99 if (!p) { 100 return nullptr; 101 } 102 return p->mProcessParent; 103 } 104 105 // Get a list of all valid utility process parent references 106 nsTArray<RefPtr<UtilityProcessParent>> GetAllProcessesProcessParent() { 107 nsTArray<RefPtr<UtilityProcessParent>> rv; 108 for (auto& p : mProcesses) { 109 if (p && p->mProcessParent) { 110 rv.AppendElement(p->mProcessParent); 111 } 112 } 113 return rv; 114 } 115 116 // Returns the Utility Process for that sandbox 117 UtilityProcessHost* Process(SandboxingKind aSandbox) { 118 RefPtr<ProcessFields> p = GetProcess(aSandbox); 119 if (!p) { 120 return nullptr; 121 } 122 return p->mProcess; 123 } 124 125 void RegisterActor(const RefPtr<UtilityProcessParent>& aParent, 126 UtilityActorName aActorName) { 127 for (auto& p : mProcesses) { 128 if (p && p->mProcessParent && p->mProcessParent == aParent) { 129 p->mActors.AppendElement(aActorName); 130 return; 131 } 132 } 133 } 134 135 Span<const UtilityActorName> GetActors( 136 const RefPtr<UtilityProcessParent>& aParent) { 137 for (auto& p : mProcesses) { 138 if (p && p->mProcessParent && p->mProcessParent == aParent) { 139 return p->mActors; 140 } 141 } 142 return {}; 143 } 144 145 Span<const UtilityActorName> GetActors(GeckoChildProcessHost* aHost) { 146 for (auto& p : mProcesses) { 147 if (p && p->mProcess == aHost) { 148 return p->mActors; 149 } 150 } 151 return {}; 152 } 153 154 Span<const UtilityActorName> GetActors(SandboxingKind aSbKind) { 155 auto proc = GetProcess(aSbKind); 156 if (!proc) { 157 return {}; 158 } 159 return proc->mActors; 160 } 161 162 // Shutdown the Utility process for that sandbox. 163 void CleanShutdown(SandboxingKind aSandbox); 164 165 // Shutdown all utility processes 166 void CleanShutdownAllProcesses(); 167 168 uint16_t AliveProcesses(); 169 170 private: 171 ~UtilityProcessManager(); 172 173 bool IsProcessLaunching(SandboxingKind aSandbox); 174 bool IsProcessDestroyed(SandboxingKind aSandbox); 175 176 // Called from our xpcom-shutdown observer. 177 void OnXPCOMShutdown(); 178 void OnPreferenceChange(const char16_t* aData); 179 180 UtilityProcessManager(); 181 182 void Init(); 183 184 void DestroyProcess(SandboxingKind aSandbox); 185 186 bool IsShutdown() const; 187 188 class Observer final : public nsIObserver { 189 public: 190 NS_DECL_ISUPPORTS 191 NS_DECL_NSIOBSERVER 192 explicit Observer(UtilityProcessManager* aManager); 193 194 protected: 195 ~Observer() = default; 196 197 RefPtr<UtilityProcessManager> mManager; 198 }; 199 friend class Observer; 200 201 RefPtr<Observer> mObserver; 202 203 class ProcessFields final { 204 public: 205 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProcessFields); 206 207 explicit ProcessFields(SandboxingKind aSandbox) : mSandbox(aSandbox) {}; 208 209 // Promise will be resolved when this Utility process has been fully started 210 // and configured. Only accessed on the main thread. 211 RefPtr<SharedLaunchPromise<Ok>> mLaunchPromise; 212 213 uint32_t mNumProcessAttempts = 0; 214 uint32_t mNumUnexpectedCrashes = 0; 215 216 // Fields that are associated with the current Utility process. 217 UtilityProcessHost* mProcess = nullptr; 218 RefPtr<UtilityProcessParent> mProcessParent = nullptr; 219 220 // Collects any pref changes that occur during process launch (after 221 // the initial map is passed in command-line arguments) to be sent 222 // when the process can receive IPC messages. 223 nsTArray<dom::Pref> mQueuedPrefs; 224 225 nsTArray<UtilityActorName> mActors; 226 227 SandboxingKind mSandbox = SandboxingKind::COUNT; 228 229 protected: 230 ~ProcessFields() = default; 231 }; 232 233 EnumeratedArray<SandboxingKind, RefPtr<ProcessFields>, 234 size_t(SandboxingKind::COUNT)> 235 mProcesses; 236 237 RefPtr<ProcessFields> GetProcess(SandboxingKind); 238 bool NoMoreProcesses(); 239 240 #ifdef XP_WIN 241 RefPtr<dom::WindowsUtilsParent> mWindowsUtils; 242 #endif // XP_WIN 243 }; 244 245 } // namespace ipc 246 247 } // namespace mozilla 248 249 #endif // _include_ipc_glue_UtilityProcessManager_h_