Bug 1858509 add thread-safety annotations around MediaSourceDemuxer::mMonitor r=alwu
[gecko.git] / ipc / glue / UtilityProcessManager.cpp
blob8042cd49020f8fb2f4a9bdcaf5da3785350334c7
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<GenericNonExclusivePromise> UtilityProcessManager::LaunchProcess(
144 SandboxingKind aSandbox) {
145 LOGD("[%p] UtilityProcessManager::LaunchProcess SandboxingKind=%" PRIu64,
146 this, aSandbox);
148 MOZ_ASSERT(NS_IsMainThread());
150 if (IsShutdown()) {
151 NS_WARNING("Reject early LaunchProcess() for Shutdown");
152 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
153 __func__);
156 RefPtr<ProcessFields> p = GetProcess(aSandbox);
157 if (p && p->mNumProcessAttempts) {
158 // We failed to start the Utility process earlier, abort now.
159 NS_WARNING("Reject LaunchProcess() for earlier mNumProcessAttempts");
160 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
161 __func__);
164 if (p && p->mLaunchPromise && p->mProcess) {
165 return p->mLaunchPromise;
168 if (!p) {
169 p = new ProcessFields(aSandbox);
170 mProcesses[aSandbox] = p;
173 std::vector<std::string> extraArgs;
174 ProcessChild::AddPlatformBuildID(extraArgs);
175 geckoargs::sSandboxingKind.Put(aSandbox, extraArgs);
177 // The subprocess is launched asynchronously, so we
178 // wait for the promise to be resolved to acquire the IPDL actor.
179 p->mProcess = new UtilityProcessHost(aSandbox, this);
180 if (!p->mProcess->Launch(extraArgs)) {
181 p->mNumProcessAttempts++;
182 DestroyProcess(aSandbox);
183 NS_WARNING("Reject LaunchProcess() for mNumProcessAttempts++");
184 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
185 __func__);
188 RefPtr<UtilityProcessManager> self = this;
189 p->mLaunchPromise = p->mProcess->LaunchPromise()->Then(
190 GetMainThreadSerialEventTarget(), __func__,
191 [self, p, aSandbox](bool) {
192 if (self->IsShutdown()) {
193 NS_WARNING(
194 "Reject LaunchProcess() after LaunchPromise() for Shutdown");
195 return GenericNonExclusivePromise::CreateAndReject(
196 NS_ERROR_NOT_AVAILABLE, __func__);
199 if (self->IsProcessDestroyed(aSandbox)) {
200 NS_WARNING(
201 "Reject LaunchProcess() after LaunchPromise() for destroyed "
202 "process");
203 return GenericNonExclusivePromise::CreateAndReject(
204 NS_ERROR_NOT_AVAILABLE, __func__);
207 p->mProcessParent = p->mProcess->GetActor();
209 // Flush any pref updates that happened during
210 // launch and weren't included in the blobs set
211 // up in LaunchUtilityProcess.
212 for (const mozilla::dom::Pref& pref : p->mQueuedPrefs) {
213 Unused << NS_WARN_IF(!p->mProcessParent->SendPreferenceUpdate(pref));
215 p->mQueuedPrefs.Clear();
217 CrashReporter::AnnotateCrashReport(
218 CrashReporter::Annotation::UtilityProcessStatus, "Running"_ns);
220 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
222 [self, p, aSandbox](nsresult aError) {
223 if (GetSingleton()) {
224 p->mNumProcessAttempts++;
225 self->DestroyProcess(aSandbox);
227 NS_WARNING("Reject LaunchProcess() for LaunchPromise() rejection");
228 return GenericNonExclusivePromise::CreateAndReject(aError, __func__);
231 return p->mLaunchPromise;
234 template <typename Actor>
235 RefPtr<GenericNonExclusivePromise> UtilityProcessManager::StartUtility(
236 RefPtr<Actor> aActor, SandboxingKind aSandbox) {
237 LOGD(
238 "[%p] UtilityProcessManager::StartUtility actor=%p "
239 "SandboxingKind=%" PRIu64,
240 this, aActor.get(), aSandbox);
242 TimeStamp utilityStart = TimeStamp::Now();
244 if (!aActor) {
245 MOZ_ASSERT(false, "Actor singleton failure");
246 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
247 __func__);
250 if (aActor->CanSend()) {
251 // Actor has already been setup, so we:
252 // - know the process has been launched
253 // - the ipc actors are ready
254 PROFILER_MARKER_TEXT(
255 "UtilityProcessManager::StartUtility", IPC,
256 MarkerOptions(MarkerTiming::InstantNow()),
257 nsPrintfCString("SandboxingKind=%" PRIu64 " aActor->CanSend()",
258 aSandbox));
259 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
262 RefPtr<UtilityProcessManager> self = this;
263 return LaunchProcess(aSandbox)->Then(
264 GetMainThreadSerialEventTarget(), __func__,
265 [self, aActor, aSandbox, utilityStart]() {
266 RefPtr<UtilityProcessParent> utilityParent =
267 self->GetProcessParent(aSandbox);
268 if (!utilityParent) {
269 NS_WARNING("Missing parent in StartUtility");
270 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
271 __func__);
274 // It is possible if multiple processes concurrently request a utility
275 // actor that the previous CanSend() check returned false for both but
276 // that by the time we have started our process for real, one of them
277 // has already been able to establish the IPC connection and thus we
278 // would perform more than one Open() call.
280 // The tests within browser_utility_multipleAudio.js should be able to
281 // catch that behavior.
282 if (!aActor->CanSend()) {
283 nsresult rv = aActor->BindToUtilityProcess(utilityParent);
284 if (NS_FAILED(rv)) {
285 MOZ_ASSERT(false, "Protocol endpoints failure");
286 return GenericNonExclusivePromise::CreateAndReject(rv, __func__);
289 MOZ_DIAGNOSTIC_ASSERT(aActor->CanSend(), "IPC established for actor");
290 self->RegisterActor(utilityParent, aActor->GetActorName());
293 PROFILER_MARKER_TEXT(
294 "UtilityProcessManager::StartUtility", IPC,
295 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(utilityStart)),
296 nsPrintfCString("SandboxingKind=%" PRIu64 " Resolve", aSandbox));
297 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
299 [self, aSandbox, utilityStart](nsresult aError) {
300 NS_WARNING("Reject StartUtility() for LaunchProcess() rejection");
301 if (!self->IsShutdown()) {
302 NS_WARNING("Reject StartUtility() when !IsShutdown()");
304 PROFILER_MARKER_TEXT(
305 "UtilityProcessManager::StartUtility", IPC,
306 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(utilityStart)),
307 nsPrintfCString("SandboxingKind=%" PRIu64 " Reject", aSandbox));
308 return GenericNonExclusivePromise::CreateAndReject(aError, __func__);
312 RefPtr<UtilityProcessManager::StartRemoteDecodingUtilityPromise>
313 UtilityProcessManager::StartProcessForRemoteMediaDecoding(
314 base::ProcessId aOtherProcess, SandboxingKind aSandbox) {
315 // Not supported kinds.
316 if (aSandbox != SandboxingKind::GENERIC_UTILITY
317 #ifdef MOZ_APPLEMEDIA
318 && aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA
319 #endif
320 #ifdef XP_WIN
321 && aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_WMF
322 #endif
323 #ifdef MOZ_WMF_MEDIA_ENGINE
324 && aSandbox != SandboxingKind::MF_MEDIA_ENGINE_CDM
325 #endif
327 return StartRemoteDecodingUtilityPromise::CreateAndReject(NS_ERROR_FAILURE,
328 __func__);
330 TimeStamp remoteDecodingStart = TimeStamp::Now();
332 RefPtr<UtilityProcessManager> self = this;
333 RefPtr<UtilityAudioDecoderChild> uadc =
334 UtilityAudioDecoderChild::GetSingleton(aSandbox);
335 MOZ_ASSERT(uadc, "Unable to get a singleton for UtilityAudioDecoderChild");
336 return StartUtility(uadc, aSandbox)
337 ->Then(
338 GetMainThreadSerialEventTarget(), __func__,
339 [self, uadc, aOtherProcess, aSandbox, remoteDecodingStart]() {
340 RefPtr<UtilityProcessParent> parent =
341 self->GetProcessParent(aSandbox);
342 if (!parent) {
343 NS_WARNING("UtilityAudioDecoderParent lost in the middle");
344 return StartRemoteDecodingUtilityPromise::CreateAndReject(
345 NS_ERROR_FAILURE, __func__);
348 if (!uadc->CanSend()) {
349 NS_WARNING("UtilityAudioDecoderChild lost in the middle");
350 return StartRemoteDecodingUtilityPromise::CreateAndReject(
351 NS_ERROR_FAILURE, __func__);
354 base::ProcessId process = parent->OtherPid();
356 Endpoint<PRemoteDecoderManagerChild> childPipe;
357 Endpoint<PRemoteDecoderManagerParent> parentPipe;
358 nsresult rv = PRemoteDecoderManager::CreateEndpoints(
359 process, aOtherProcess, &parentPipe, &childPipe);
360 if (NS_FAILED(rv)) {
361 MOZ_ASSERT(false, "Could not create content remote decoder");
362 return StartRemoteDecodingUtilityPromise::CreateAndReject(
363 rv, __func__);
366 if (!uadc->SendNewContentRemoteDecoderManager(
367 std::move(parentPipe))) {
368 MOZ_ASSERT(false, "SendNewContentRemoteDecoderManager failure");
369 return StartRemoteDecodingUtilityPromise::CreateAndReject(
370 NS_ERROR_FAILURE, __func__);
373 #ifdef MOZ_WMF_MEDIA_ENGINE
374 if (aSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM &&
375 !uadc->CreateVideoBridge()) {
376 MOZ_ASSERT(false, "Failed to create video bridge");
377 return StartRemoteDecodingUtilityPromise::CreateAndReject(
378 NS_ERROR_FAILURE, __func__);
380 #endif
381 PROFILER_MARKER_TEXT(
382 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
383 MEDIA,
384 MarkerOptions(
385 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart)),
386 "Resolve"_ns);
387 return StartRemoteDecodingUtilityPromise::CreateAndResolve(
388 std::move(childPipe), __func__);
390 [self, remoteDecodingStart](nsresult aError) {
391 NS_WARNING(
392 "Reject StartProcessForRemoteMediaDecoding() for "
393 "StartUtility() rejection");
394 PROFILER_MARKER_TEXT(
395 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
396 MEDIA,
397 MarkerOptions(
398 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart)),
399 "Reject"_ns);
400 return StartRemoteDecodingUtilityPromise::CreateAndReject(aError,
401 __func__);
405 RefPtr<UtilityProcessManager::JSOraclePromise>
406 UtilityProcessManager::StartJSOracle(dom::JSOracleParent* aParent) {
407 return StartUtility(RefPtr{aParent}, SandboxingKind::GENERIC_UTILITY);
410 #ifdef XP_WIN
412 // Windows Utils
414 RefPtr<UtilityProcessManager::WindowsUtilsPromise>
415 UtilityProcessManager::GetWindowsUtilsPromise() {
416 TimeStamp windowsUtilsStart = TimeStamp::Now();
417 RefPtr<UtilityProcessManager> self = this;
418 if (!mWindowsUtils) {
419 mWindowsUtils = new dom::WindowsUtilsParent();
422 RefPtr<dom::WindowsUtilsParent> wup = mWindowsUtils;
423 MOZ_ASSERT(wup, "Unable to get a singleton for WindowsUtils");
424 return StartUtility(wup, SandboxingKind::WINDOWS_UTILS)
425 ->Then(
426 GetMainThreadSerialEventTarget(), __func__,
427 [self, wup, windowsUtilsStart]() {
428 if (!wup->CanSend()) {
429 MOZ_ASSERT(false, "WindowsUtilsParent can't send");
430 return WindowsUtilsPromise::CreateAndReject(NS_ERROR_FAILURE,
431 __func__);
433 PROFILER_MARKER_TEXT(
434 "UtilityProcessManager::GetWindowsUtilsPromise", OTHER,
435 MarkerOptions(
436 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart)),
437 "Resolve"_ns);
438 return WindowsUtilsPromise::CreateAndResolve(wup, __func__);
440 [self, windowsUtilsStart](nsresult aError) {
441 NS_WARNING("StartUtility rejected promise for PWindowsUtils");
442 PROFILER_MARKER_TEXT(
443 "UtilityProcessManager::GetWindowsUtilsPromise", OTHER,
444 MarkerOptions(
445 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart)),
446 "Reject"_ns);
447 return WindowsUtilsPromise::CreateAndReject(aError, __func__);
451 void UtilityProcessManager::ReleaseWindowsUtils() { mWindowsUtils = nullptr; }
453 RefPtr<UtilityProcessManager::WinFileDialogPromise>
454 UtilityProcessManager::CreateWinFileDialogAsync() {
455 using Promise = WinFileDialogPromise;
456 TimeStamp startTime = TimeStamp::Now();
457 auto wfdp = MakeRefPtr<widget::filedialog::WinFileDialogParent>();
459 return StartUtility(wfdp, SandboxingKind::WINDOWS_FILE_DIALOG)
460 ->Then(
461 GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
462 [wfdp, startTime]() mutable {
463 LOGD("CreateWinFileDialogAsync() resolve: wfdp = [%p]", wfdp.get());
464 if (!wfdp->CanSend()) {
465 MOZ_ASSERT(false, "WinFileDialogParent can't send");
466 return Promise::CreateAndReject(NS_ERROR_FAILURE,
467 __PRETTY_FUNCTION__);
469 PROFILER_MARKER_TEXT(
470 "UtilityProcessManager::CreateWinFileDialogAsync", OTHER,
471 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(startTime)),
472 "Resolve"_ns);
474 return Promise::CreateAndResolve(
475 widget::filedialog::ProcessProxy(std::move(wfdp)),
476 __PRETTY_FUNCTION__);
478 [self = RefPtr(this), startTime](nsresult error) {
479 LOGD("CreateWinFileDialogAsync() reject");
480 if (!self->IsShutdown()) {
481 MOZ_ASSERT_UNREACHABLE("failure when starting file-dialog actor");
483 PROFILER_MARKER_TEXT(
484 "UtilityProcessManager::CreateWinFileDialogAsync", OTHER,
485 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(startTime)),
486 "Reject"_ns);
488 return Promise::CreateAndReject(error, __PRETTY_FUNCTION__);
492 #endif // XP_WIN
494 bool UtilityProcessManager::IsProcessLaunching(SandboxingKind aSandbox) {
495 MOZ_ASSERT(NS_IsMainThread());
497 RefPtr<ProcessFields> p = GetProcess(aSandbox);
498 if (!p) {
499 MOZ_CRASH("Cannot check process launching with no process");
500 return false;
503 return p->mProcess && !(p->mProcessParent);
506 bool UtilityProcessManager::IsProcessDestroyed(SandboxingKind aSandbox) {
507 MOZ_ASSERT(NS_IsMainThread());
508 RefPtr<ProcessFields> p = GetProcess(aSandbox);
509 if (!p) {
510 MOZ_CRASH("Cannot check process destroyed with no process");
511 return false;
513 return !p->mProcess && !p->mProcessParent;
516 void UtilityProcessManager::OnProcessUnexpectedShutdown(
517 UtilityProcessHost* aHost) {
518 MOZ_ASSERT(NS_IsMainThread());
520 for (auto& it : mProcesses) {
521 if (it && it->mProcess && it->mProcess == aHost) {
522 it->mNumUnexpectedCrashes++;
523 DestroyProcess(it->mSandbox);
524 return;
528 MOZ_CRASH(
529 "Called UtilityProcessManager::OnProcessUnexpectedShutdown with invalid "
530 "aHost");
533 void UtilityProcessManager::CleanShutdownAllProcesses() {
534 LOGD("[%p] UtilityProcessManager::CleanShutdownAllProcesses", this);
536 for (auto& it : mProcesses) {
537 if (it) {
538 DestroyProcess(it->mSandbox);
543 void UtilityProcessManager::CleanShutdown(SandboxingKind aSandbox) {
544 LOGD("[%p] UtilityProcessManager::CleanShutdown SandboxingKind=%" PRIu64,
545 this, aSandbox);
547 DestroyProcess(aSandbox);
550 uint16_t UtilityProcessManager::AliveProcesses() {
551 uint16_t alive = 0;
552 for (auto& p : mProcesses) {
553 if (p != nullptr) {
554 alive++;
557 return alive;
560 bool UtilityProcessManager::NoMoreProcesses() { return AliveProcesses() == 0; }
562 void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) {
563 LOGD("[%p] UtilityProcessManager::DestroyProcess SandboxingKind=%" PRIu64,
564 this, aSandbox);
566 MOZ_RELEASE_ASSERT(NS_IsMainThread());
568 if (AliveProcesses() <= 1) {
569 if (mObserver) {
570 Preferences::RemoveObserver(mObserver, "");
573 mObserver = nullptr;
576 RefPtr<ProcessFields> p = GetProcess(aSandbox);
577 if (!p) {
578 return;
581 p->mQueuedPrefs.Clear();
582 p->mProcessParent = nullptr;
584 if (!p->mProcess) {
585 return;
588 p->mProcess->Shutdown();
589 p->mProcess = nullptr;
591 mProcesses[aSandbox] = nullptr;
593 CrashReporter::AnnotateCrashReport(
594 CrashReporter::Annotation::UtilityProcessStatus, "Destroyed"_ns);
596 if (NoMoreProcesses()) {
597 sSingleton = nullptr;
601 Maybe<base::ProcessId> UtilityProcessManager::ProcessPid(
602 SandboxingKind aSandbox) {
603 MOZ_ASSERT(NS_IsMainThread());
604 RefPtr<ProcessFields> p = GetProcess(aSandbox);
605 if (!p) {
606 return Nothing();
608 if (p->mProcessParent) {
609 return Some(p->mProcessParent->OtherPid());
611 return Nothing();
614 class UtilityMemoryReporter : public MemoryReportingProcess {
615 public:
616 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UtilityMemoryReporter, override)
618 explicit UtilityMemoryReporter(UtilityProcessParent* aParent) {
619 mParent = aParent;
622 bool IsAlive() const override { return bool(GetParent()); }
624 bool SendRequestMemoryReport(
625 const uint32_t& aGeneration, const bool& aAnonymize,
626 const bool& aMinimizeMemoryUsage,
627 const Maybe<ipc::FileDescriptor>& aDMDFile) override {
628 RefPtr<UtilityProcessParent> parent = GetParent();
629 if (!parent) {
630 return false;
633 return parent->SendRequestMemoryReport(aGeneration, aAnonymize,
634 aMinimizeMemoryUsage, aDMDFile);
637 int32_t Pid() const override {
638 if (RefPtr<UtilityProcessParent> parent = GetParent()) {
639 return (int32_t)parent->OtherPid();
641 return 0;
644 private:
645 RefPtr<UtilityProcessParent> GetParent() const { return mParent; }
647 RefPtr<UtilityProcessParent> mParent = nullptr;
649 protected:
650 ~UtilityMemoryReporter() = default;
653 RefPtr<MemoryReportingProcess> UtilityProcessManager::GetProcessMemoryReporter(
654 UtilityProcessParent* parent) {
655 return new UtilityMemoryReporter(parent);
658 } // namespace mozilla::ipc