Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / ipc / glue / UtilityProcessManager.cpp
blobb8c28cbfcc294ce305fe38df623061edf442e6cc
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 #include "UtilityProcessManager.h"
8 #include "JSOracleParent.h"
9 #include "mozilla/ipc/UtilityProcessHost.h"
10 #include "mozilla/MemoryReportingProcess.h"
11 #include "mozilla/Preferences.h"
12 #include "mozilla/ProfilerMarkers.h"
13 #include "mozilla/StaticPrefs_media.h"
14 #include "mozilla/SyncRunnable.h" // for LaunchUtilityProcess
15 #include "mozilla/ipc/UtilityProcessParent.h"
16 #include "mozilla/ipc/UtilityAudioDecoderChild.h"
17 #include "mozilla/ipc/UtilityAudioDecoderParent.h"
18 #include "mozilla/dom/ContentParent.h"
19 #include "mozilla/ipc/Endpoint.h"
20 #include "mozilla/ipc/UtilityProcessSandboxing.h"
21 #include "mozilla/ipc/ProcessChild.h"
22 #include "nsAppRunner.h"
23 #include "nsContentUtils.h"
25 #ifdef XP_WIN
26 # include "mozilla/dom/WindowsUtilsParent.h"
27 # include "mozilla/widget/filedialog/WinFileDialogParent.h"
28 #endif
30 #include "mozilla/GeckoArgs.h"
32 namespace mozilla::ipc {
34 extern LazyLogModule gUtilityProcessLog;
35 #define LOGD(...) MOZ_LOG(gUtilityProcessLog, LogLevel::Debug, (__VA_ARGS__))
37 static StaticRefPtr<UtilityProcessManager> sSingleton;
39 static bool sXPCOMShutdown = false;
41 bool UtilityProcessManager::IsShutdown() const {
42 MOZ_ASSERT(NS_IsMainThread());
43 return sXPCOMShutdown || !sSingleton;
46 RefPtr<UtilityProcessManager> UtilityProcessManager::GetSingleton() {
47 MOZ_ASSERT(XRE_IsParentProcess());
48 MOZ_ASSERT(NS_IsMainThread());
50 if (!sXPCOMShutdown && sSingleton == nullptr) {
51 sSingleton = new UtilityProcessManager();
52 sSingleton->Init();
54 return sSingleton;
57 RefPtr<UtilityProcessManager> UtilityProcessManager::GetIfExists() {
58 MOZ_ASSERT(NS_IsMainThread());
59 return sSingleton;
62 UtilityProcessManager::UtilityProcessManager() {
63 LOGD("[%p] UtilityProcessManager::UtilityProcessManager", this);
66 void UtilityProcessManager::Init() {
67 // Start listening for pref changes so we can
68 // forward them to the process once it is running.
69 mObserver = new Observer(this);
70 nsContentUtils::RegisterShutdownObserver(mObserver);
71 Preferences::AddStrongObserver(mObserver, "");
74 UtilityProcessManager::~UtilityProcessManager() {
75 LOGD("[%p] UtilityProcessManager::~UtilityProcessManager", this);
77 // The Utility process should ALL have already been shut down.
78 MOZ_ASSERT(NoMoreProcesses());
81 NS_IMPL_ISUPPORTS(UtilityProcessManager::Observer, nsIObserver);
83 UtilityProcessManager::Observer::Observer(UtilityProcessManager* aManager)
84 : mManager(aManager) {}
86 NS_IMETHODIMP
87 UtilityProcessManager::Observer::Observe(nsISupports* aSubject,
88 const char* aTopic,
89 const char16_t* aData) {
90 if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
91 mManager->OnXPCOMShutdown();
92 } else if (!strcmp(aTopic, "nsPref:changed")) {
93 mManager->OnPreferenceChange(aData);
95 return NS_OK;
98 void UtilityProcessManager::OnXPCOMShutdown() {
99 LOGD("[%p] UtilityProcessManager::OnXPCOMShutdown", this);
101 MOZ_ASSERT(NS_IsMainThread());
102 sXPCOMShutdown = true;
103 nsContentUtils::UnregisterShutdownObserver(mObserver);
104 CleanShutdownAllProcesses();
107 void UtilityProcessManager::OnPreferenceChange(const char16_t* aData) {
108 MOZ_ASSERT(NS_IsMainThread());
109 if (NoMoreProcesses()) {
110 // Process hasn't been launched yet
111 return;
113 // We know prefs are ASCII here.
114 NS_LossyConvertUTF16toASCII strData(aData);
116 mozilla::dom::Pref pref(strData, /* isLocked */ false,
117 /* isSanitized */ false, Nothing(), Nothing());
118 Preferences::GetPreference(&pref, GeckoProcessType_Utility,
119 /* remoteType */ ""_ns);
121 for (auto& p : mProcesses) {
122 if (!p) {
123 continue;
126 if (p->mProcessParent) {
127 Unused << p->mProcessParent->SendPreferenceUpdate(pref);
128 } else if (IsProcessLaunching(p->mSandbox)) {
129 p->mQueuedPrefs.AppendElement(pref);
134 RefPtr<UtilityProcessManager::ProcessFields> UtilityProcessManager::GetProcess(
135 SandboxingKind aSandbox) {
136 if (!mProcesses[aSandbox]) {
137 return nullptr;
140 return mProcesses[aSandbox];
143 RefPtr<UtilityProcessManager::SharedLaunchPromise<Ok>>
144 UtilityProcessManager::LaunchProcess(SandboxingKind aSandbox) {
145 LOGD("[%p] UtilityProcessManager::LaunchProcess SandboxingKind=%" PRIu64,
146 this, aSandbox);
147 using RetPromise = SharedLaunchPromise<Ok>;
149 MOZ_ASSERT(NS_IsMainThread());
151 if (IsShutdown()) {
152 NS_WARNING("Reject early LaunchProcess() for Shutdown");
153 return RetPromise::CreateAndReject(
154 LaunchError("UPM::LaunchProcess(): IsShutdown()"), __func__);
157 RefPtr<ProcessFields> p = GetProcess(aSandbox);
158 if (p && p->mNumProcessAttempts) {
159 // We failed to start the Utility process earlier, abort now.
160 NS_WARNING("Reject LaunchProcess() for earlier mNumProcessAttempts");
161 return RetPromise::CreateAndReject(
162 LaunchError("UPM::LaunchProcess(): p->mNumProcessAttempts"), __func__);
165 if (p && p->mLaunchPromise && p->mProcess) {
166 return p->mLaunchPromise;
169 if (!p) {
170 p = new ProcessFields(aSandbox);
171 mProcesses[aSandbox] = p;
174 geckoargs::ChildProcessArgs extraArgs;
175 ProcessChild::AddPlatformBuildID(extraArgs);
176 geckoargs::sSandboxingKind.Put(aSandbox, extraArgs);
178 // The subprocess is launched asynchronously, so we
179 // wait for the promise to be resolved to acquire the IPDL actor.
180 p->mProcess = new UtilityProcessHost(aSandbox, this);
181 if (!p->mProcess->Launch(std::move(extraArgs))) {
182 p->mNumProcessAttempts++;
183 DestroyProcess(aSandbox);
184 NS_WARNING("Reject LaunchProcess() for mNumProcessAttempts++");
185 return RetPromise::CreateAndReject(
186 LaunchError("UPM::LaunchProcess(): mNumProcessAttempts++"), __func__);
189 RefPtr<UtilityProcessManager> self = this;
190 p->mLaunchPromise = p->mProcess->LaunchPromise()->Then(
191 GetMainThreadSerialEventTarget(), __func__,
192 [self, p, aSandbox](Ok) -> RefPtr<RetPromise> {
193 if (self->IsShutdown()) {
194 NS_WARNING(
195 "Reject LaunchProcess() after LaunchPromise() for Shutdown");
196 return RetPromise::CreateAndReject(
197 LaunchError("UPM::LaunchProcess(): post-await IsShutdown()"),
198 __func__);
201 if (self->IsProcessDestroyed(aSandbox)) {
202 NS_WARNING(
203 "Reject LaunchProcess() after LaunchPromise() for destroyed "
204 "process");
205 return RetPromise::CreateAndReject(
206 LaunchError(
207 "UPM::LaunchProcess(): post-await IsProcessDestroyed()"),
208 __func__);
211 p->mProcessParent = p->mProcess->GetActor();
213 // Flush any pref updates that happened during
214 // launch and weren't included in the blobs set
215 // up in LaunchUtilityProcess.
216 for (const mozilla::dom::Pref& pref : p->mQueuedPrefs) {
217 Unused << NS_WARN_IF(!p->mProcessParent->SendPreferenceUpdate(pref));
219 p->mQueuedPrefs.Clear();
221 CrashReporter::RecordAnnotationCString(
222 CrashReporter::Annotation::UtilityProcessStatus, "Running");
224 return RetPromise::CreateAndResolve(Ok{}, __func__);
226 [self, p, aSandbox](LaunchError error) {
227 if (GetSingleton()) {
228 p->mNumProcessAttempts++;
229 self->DestroyProcess(aSandbox);
231 NS_WARNING("Reject LaunchProcess() for LaunchPromise() rejection");
232 return RetPromise::CreateAndReject(std::move(error), __func__);
235 return p->mLaunchPromise;
238 template <typename Actor>
239 RefPtr<UtilityProcessManager::LaunchPromise<Ok>>
240 UtilityProcessManager::StartUtility(RefPtr<Actor> aActor,
241 SandboxingKind aSandbox) {
242 using RetPromise = LaunchPromise<Ok>;
244 LOGD(
245 "[%p] UtilityProcessManager::StartUtility actor=%p "
246 "SandboxingKind=%" PRIu64,
247 this, aActor.get(), aSandbox);
249 TimeStamp utilityStart = TimeStamp::Now();
251 if (!aActor) {
252 MOZ_ASSERT(false, "Actor singleton failure");
253 return RetPromise::CreateAndReject(
254 LaunchError("UPM::StartUtility: aActor is null"), __func__);
257 if (aActor->CanSend()) {
258 // Actor has already been setup, so we:
259 // - know the process has been launched
260 // - the ipc actors are ready
261 PROFILER_MARKER_TEXT(
262 "UtilityProcessManager::StartUtility", IPC,
263 MarkerOptions(MarkerTiming::InstantNow()),
264 nsPrintfCString("SandboxingKind=%" PRIu64 " aActor->CanSend()",
265 aSandbox));
266 return RetPromise::CreateAndResolve(Ok{}, __func__);
269 RefPtr<UtilityProcessManager> self = this;
270 return LaunchProcess(aSandbox)->Then(
271 GetMainThreadSerialEventTarget(), __func__,
272 [self, aActor, aSandbox, utilityStart]() -> RefPtr<RetPromise> {
273 RefPtr<UtilityProcessParent> utilityParent =
274 self->GetProcessParent(aSandbox);
275 if (!utilityParent) {
276 NS_WARNING("Missing parent in StartUtility");
277 return RetPromise::CreateAndReject(
278 LaunchError("UPM::GetProcessParent"), __func__);
281 // It is possible if multiple processes concurrently request a utility
282 // actor that the previous CanSend() check returned false for both but
283 // that by the time we have started our process for real, one of them
284 // has already been able to establish the IPC connection and thus we
285 // would perform more than one Open() call.
287 // The tests within browser_utility_multipleAudio.js should be able to
288 // catch that behavior.
289 if (!aActor->CanSend()) {
290 nsresult rv = aActor->BindToUtilityProcess(utilityParent);
291 if (NS_FAILED(rv)) {
292 MOZ_ASSERT(false, "Protocol endpoints failure");
293 return RetPromise::CreateAndReject(
294 LaunchError("BindToUtilityProcess", rv), __func__);
297 MOZ_DIAGNOSTIC_ASSERT(aActor->CanSend(), "IPC established for actor");
298 self->RegisterActor(utilityParent, aActor->GetActorName());
301 PROFILER_MARKER_TEXT(
302 "UtilityProcessManager::StartUtility", IPC,
303 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(utilityStart)),
304 nsPrintfCString("SandboxingKind=%" PRIu64 " Resolve", aSandbox));
305 return RetPromise::CreateAndResolve(Ok{}, __func__);
307 [self, aSandbox, utilityStart](LaunchError const& error) {
308 NS_WARNING("Reject StartUtility() for LaunchProcess() rejection");
309 if (!self->IsShutdown()) {
310 NS_WARNING("Reject StartUtility() when !IsShutdown()");
312 PROFILER_MARKER_TEXT(
313 "UtilityProcessManager::StartUtility", IPC,
314 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(utilityStart)),
315 nsPrintfCString("SandboxingKind=%" PRIu64 " Reject", aSandbox));
316 return RetPromise::CreateAndReject(error, __func__);
320 RefPtr<UtilityProcessManager::StartRemoteDecodingUtilityPromise>
321 UtilityProcessManager::StartProcessForRemoteMediaDecoding(
322 EndpointProcInfo aOtherProcess, dom::ContentParentId aChildId,
323 SandboxingKind aSandbox) {
324 using RetPromise = StartRemoteDecodingUtilityPromise;
326 // Not supported kinds.
327 if (aSandbox != SandboxingKind::GENERIC_UTILITY
328 #ifdef MOZ_APPLEMEDIA
329 && aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA
330 #endif
331 #ifdef XP_WIN
332 && aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_WMF
333 #endif
334 #ifdef MOZ_WMF_MEDIA_ENGINE
335 && aSandbox != SandboxingKind::MF_MEDIA_ENGINE_CDM
336 #endif
338 return RetPromise::CreateAndReject(
339 LaunchError("Start...MediaDecoding: bad sandbox type"), __func__);
341 TimeStamp remoteDecodingStart = TimeStamp::Now();
343 RefPtr<UtilityProcessManager> self = this;
344 RefPtr<UtilityAudioDecoderChild> uadc =
345 UtilityAudioDecoderChild::GetSingleton(aSandbox);
346 MOZ_ASSERT(uadc, "Unable to get a singleton for UtilityAudioDecoderChild");
347 return StartUtility(uadc, aSandbox)
348 ->Then(
349 GetMainThreadSerialEventTarget(), __func__,
350 [self, uadc, aOtherProcess, aChildId, aSandbox,
351 remoteDecodingStart]() {
352 RefPtr<UtilityProcessParent> parent =
353 self->GetProcessParent(aSandbox);
354 if (!parent) {
355 NS_WARNING("UtilityAudioDecoderParent lost in the middle");
356 return RetPromise::CreateAndReject(
357 LaunchError("Start...MediaDecoding: parent lost"), __func__);
360 if (!uadc->CanSend()) {
361 NS_WARNING("UtilityAudioDecoderChild lost in the middle");
362 return RetPromise::CreateAndReject(
363 LaunchError("Start...MediaDecoding: child lost"), __func__);
366 EndpointProcInfo process = parent->OtherEndpointProcInfo();
368 Endpoint<PRemoteDecoderManagerChild> childPipe;
369 Endpoint<PRemoteDecoderManagerParent> parentPipe;
370 if (nsresult const rv = PRemoteDecoderManager::CreateEndpoints(
371 process, aOtherProcess, &parentPipe, &childPipe);
372 NS_FAILED(rv)) {
373 MOZ_ASSERT(false, "Could not create content remote decoder");
374 return RetPromise::CreateAndReject(
375 LaunchError("PRemoteDecoderManager::CreateEndpoints", rv),
376 __func__);
379 if (!uadc->SendNewContentRemoteDecoderManager(std::move(parentPipe),
380 aChildId)) {
381 MOZ_ASSERT(false, "SendNewContentRemoteDecoderManager failure");
382 return RetPromise::CreateAndReject(
383 LaunchError("UADC::SendNewCRDM"), __func__);
386 #ifdef MOZ_WMF_MEDIA_ENGINE
387 if (aSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM &&
388 !uadc->CreateVideoBridge()) {
389 MOZ_ASSERT(false, "Failed to create video bridge");
390 return RetPromise::CreateAndReject(
391 LaunchError("UADC::CreateVideoBridge"), __func__);
393 #endif
394 PROFILER_MARKER_TEXT(
395 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
396 MEDIA,
397 MarkerOptions(
398 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart)),
399 "Resolve"_ns);
400 return RetPromise::CreateAndResolve(std::move(childPipe), __func__);
402 [self, remoteDecodingStart](LaunchError&& error) {
403 NS_WARNING(
404 "Reject StartProcessForRemoteMediaDecoding() for "
405 "StartUtility() rejection");
406 PROFILER_MARKER_TEXT(
407 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
408 MEDIA,
409 MarkerOptions(
410 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart)),
411 "Reject"_ns);
412 return RetPromise::CreateAndReject(std::move(error), __func__);
416 RefPtr<UtilityProcessManager::JSOraclePromise>
417 UtilityProcessManager::StartJSOracle(dom::JSOracleParent* aParent) {
418 using RetPromise = JSOraclePromise;
419 return StartUtility(RefPtr{aParent}, SandboxingKind::GENERIC_UTILITY)
420 ->Then(
421 GetCurrentSerialEventTarget(), __func__,
422 []() { return RetPromise::CreateAndResolve(true, __func__); },
423 [](LaunchError const&) {
424 return RetPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
425 __func__);
429 #ifdef XP_WIN
431 // Windows Utils
433 RefPtr<UtilityProcessManager::WindowsUtilsPromise>
434 UtilityProcessManager::GetWindowsUtilsPromise() {
435 TimeStamp windowsUtilsStart = TimeStamp::Now();
436 RefPtr<UtilityProcessManager> self = this;
437 if (!mWindowsUtils) {
438 mWindowsUtils = new dom::WindowsUtilsParent();
441 RefPtr<dom::WindowsUtilsParent> wup = mWindowsUtils;
442 MOZ_ASSERT(wup, "Unable to get a singleton for WindowsUtils");
443 return StartUtility(wup, SandboxingKind::WINDOWS_UTILS)
444 ->Then(
445 GetMainThreadSerialEventTarget(), __func__,
446 [self, wup, windowsUtilsStart]() {
447 if (!wup->CanSend()) {
448 MOZ_ASSERT(false, "WindowsUtilsParent can't send");
449 return WindowsUtilsPromise::CreateAndReject(
450 LaunchError("GetWindowsUtilsPromise: !wup->CanSend()"),
451 __func__);
453 PROFILER_MARKER_TEXT(
454 "UtilityProcessManager::GetWindowsUtilsPromise", OTHER,
455 MarkerOptions(
456 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart)),
457 "Resolve"_ns);
458 return WindowsUtilsPromise::CreateAndResolve(wup, __func__);
460 [self, windowsUtilsStart](LaunchError&& error) {
461 NS_WARNING("StartUtility rejected promise for PWindowsUtils");
462 PROFILER_MARKER_TEXT(
463 "UtilityProcessManager::GetWindowsUtilsPromise", OTHER,
464 MarkerOptions(
465 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart)),
466 "Reject"_ns);
467 return WindowsUtilsPromise::CreateAndReject(std::move(error),
468 __func__);
472 void UtilityProcessManager::ReleaseWindowsUtils() { mWindowsUtils = nullptr; }
474 RefPtr<UtilityProcessManager::WinFileDialogPromise>
475 UtilityProcessManager::CreateWinFileDialogActor() {
476 using RetPromise = WinFileDialogPromise;
477 TimeStamp startTime = TimeStamp::Now();
478 auto wfdp = MakeRefPtr<widget::filedialog::WinFileDialogParent>();
480 return StartUtility(wfdp, SandboxingKind::WINDOWS_FILE_DIALOG)
481 ->Then(
482 GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
483 [wfdp, startTime]() mutable {
484 LOGD("CreateWinFileDialogAsync() resolve: wfdp = [%p]", wfdp.get());
485 if (!wfdp->CanSend()) {
486 MOZ_ASSERT(false, "WinFileDialogParent can't send");
487 return RetPromise::CreateAndReject(
488 LaunchError("CreateWinFileDialogActor: !wfdp->CanSend()"),
489 __PRETTY_FUNCTION__);
491 PROFILER_MARKER_TEXT(
492 "UtilityProcessManager::CreateWinFileDialogAsync", OTHER,
493 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(startTime)),
494 "Resolve"_ns);
496 return RetPromise::CreateAndResolve(
497 widget::filedialog::ProcessProxy(std::move(wfdp)),
498 __PRETTY_FUNCTION__);
500 [self = RefPtr(this), startTime](LaunchError&& error) {
501 LOGD("CreateWinFileDialogAsync() reject");
502 if (!self->IsShutdown()) {
503 MOZ_ASSERT_UNREACHABLE("failure when starting file-dialog actor");
505 PROFILER_MARKER_TEXT(
506 "UtilityProcessManager::CreateWinFileDialogAsync", OTHER,
507 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(startTime)),
508 "Reject"_ns);
510 return RetPromise::CreateAndReject(std::move(error),
511 __PRETTY_FUNCTION__);
515 #endif // XP_WIN
517 bool UtilityProcessManager::IsProcessLaunching(SandboxingKind aSandbox) {
518 MOZ_ASSERT(NS_IsMainThread());
520 RefPtr<ProcessFields> p = GetProcess(aSandbox);
521 if (!p) {
522 MOZ_CRASH("Cannot check process launching with no process");
523 return false;
526 return p->mProcess && !(p->mProcessParent);
529 bool UtilityProcessManager::IsProcessDestroyed(SandboxingKind aSandbox) {
530 MOZ_ASSERT(NS_IsMainThread());
531 RefPtr<ProcessFields> p = GetProcess(aSandbox);
532 if (!p) {
533 MOZ_CRASH("Cannot check process destroyed with no process");
534 return false;
536 return !p->mProcess && !p->mProcessParent;
539 void UtilityProcessManager::OnProcessUnexpectedShutdown(
540 UtilityProcessHost* aHost) {
541 MOZ_ASSERT(NS_IsMainThread());
543 for (auto& it : mProcesses) {
544 if (it && it->mProcess && it->mProcess == aHost) {
545 it->mNumUnexpectedCrashes++;
546 DestroyProcess(it->mSandbox);
547 return;
551 MOZ_CRASH(
552 "Called UtilityProcessManager::OnProcessUnexpectedShutdown with invalid "
553 "aHost");
556 void UtilityProcessManager::CleanShutdownAllProcesses() {
557 LOGD("[%p] UtilityProcessManager::CleanShutdownAllProcesses", this);
559 for (auto& it : mProcesses) {
560 if (it) {
561 DestroyProcess(it->mSandbox);
566 void UtilityProcessManager::CleanShutdown(SandboxingKind aSandbox) {
567 LOGD("[%p] UtilityProcessManager::CleanShutdown SandboxingKind=%" PRIu64,
568 this, aSandbox);
570 DestroyProcess(aSandbox);
573 uint16_t UtilityProcessManager::AliveProcesses() {
574 uint16_t alive = 0;
575 for (auto& p : mProcesses) {
576 if (p != nullptr) {
577 alive++;
580 return alive;
583 bool UtilityProcessManager::NoMoreProcesses() { return AliveProcesses() == 0; }
585 void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) {
586 LOGD("[%p] UtilityProcessManager::DestroyProcess SandboxingKind=%" PRIu64,
587 this, aSandbox);
589 MOZ_RELEASE_ASSERT(NS_IsMainThread());
591 if (AliveProcesses() <= 1) {
592 if (mObserver) {
593 Preferences::RemoveObserver(mObserver, "");
596 mObserver = nullptr;
599 RefPtr<ProcessFields> p = GetProcess(aSandbox);
600 if (!p) {
601 return;
604 p->mQueuedPrefs.Clear();
605 p->mProcessParent = nullptr;
607 if (!p->mProcess) {
608 return;
611 p->mProcess->Shutdown();
612 p->mProcess = nullptr;
614 mProcesses[aSandbox] = nullptr;
616 CrashReporter::RecordAnnotationCString(
617 CrashReporter::Annotation::UtilityProcessStatus, "Destroyed");
619 if (NoMoreProcesses()) {
620 sSingleton = nullptr;
624 Maybe<base::ProcessId> UtilityProcessManager::ProcessPid(
625 SandboxingKind aSandbox) {
626 MOZ_ASSERT(NS_IsMainThread());
627 RefPtr<ProcessFields> p = GetProcess(aSandbox);
628 if (!p) {
629 return Nothing();
631 if (p->mProcessParent) {
632 return Some(p->mProcessParent->OtherPid());
634 return Nothing();
637 class UtilityMemoryReporter : public MemoryReportingProcess {
638 public:
639 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UtilityMemoryReporter, override)
641 explicit UtilityMemoryReporter(UtilityProcessParent* aParent) {
642 mParent = aParent;
645 bool IsAlive() const override { return bool(GetParent()); }
647 bool SendRequestMemoryReport(
648 const uint32_t& aGeneration, const bool& aAnonymize,
649 const bool& aMinimizeMemoryUsage,
650 const Maybe<ipc::FileDescriptor>& aDMDFile) override {
651 RefPtr<UtilityProcessParent> parent = GetParent();
652 if (!parent) {
653 return false;
656 return parent->SendRequestMemoryReport(aGeneration, aAnonymize,
657 aMinimizeMemoryUsage, aDMDFile);
660 int32_t Pid() const override {
661 if (RefPtr<UtilityProcessParent> parent = GetParent()) {
662 return (int32_t)parent->OtherPid();
664 return 0;
667 private:
668 RefPtr<UtilityProcessParent> GetParent() const { return mParent; }
670 RefPtr<UtilityProcessParent> mParent = nullptr;
672 protected:
673 ~UtilityMemoryReporter() = default;
676 RefPtr<MemoryReportingProcess> UtilityProcessManager::GetProcessMemoryReporter(
677 UtilityProcessParent* parent) {
678 return new UtilityMemoryReporter(parent);
681 } // namespace mozilla::ipc