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"
26 # include "mozilla/dom/WindowsUtilsParent.h"
27 # include "mozilla/widget/filedialog/WinFileDialogParent.h"
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();
57 RefPtr
<UtilityProcessManager
> UtilityProcessManager::GetIfExists() {
58 MOZ_ASSERT(NS_IsMainThread());
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
) {}
87 UtilityProcessManager::Observer::Observe(nsISupports
* aSubject
,
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
);
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
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
) {
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
]) {
140 return mProcesses
[aSandbox
];
143 RefPtr
<UtilityProcessManager::SharedLaunchPromise
<Ok
>>
144 UtilityProcessManager::LaunchProcess(SandboxingKind aSandbox
) {
145 LOGD("[%p] UtilityProcessManager::LaunchProcess SandboxingKind=%" PRIu64
,
147 using RetPromise
= SharedLaunchPromise
<Ok
>;
149 MOZ_ASSERT(NS_IsMainThread());
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
;
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()) {
195 "Reject LaunchProcess() after LaunchPromise() for Shutdown");
196 return RetPromise::CreateAndReject(
197 LaunchError("UPM::LaunchProcess(): post-await IsShutdown()"),
201 if (self
->IsProcessDestroyed(aSandbox
)) {
203 "Reject LaunchProcess() after LaunchPromise() for destroyed "
205 return RetPromise::CreateAndReject(
207 "UPM::LaunchProcess(): post-await IsProcessDestroyed()"),
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
>;
245 "[%p] UtilityProcessManager::StartUtility actor=%p "
246 "SandboxingKind=%" PRIu64
,
247 this, aActor
.get(), aSandbox
);
249 TimeStamp utilityStart
= TimeStamp::Now();
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()",
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
);
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
332 && aSandbox
!= SandboxingKind::UTILITY_AUDIO_DECODING_WMF
334 #ifdef MOZ_WMF_MEDIA_ENGINE
335 && aSandbox
!= SandboxingKind::MF_MEDIA_ENGINE_CDM
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
)
349 GetMainThreadSerialEventTarget(), __func__
,
350 [self
, uadc
, aOtherProcess
, aChildId
, aSandbox
,
351 remoteDecodingStart
]() {
352 RefPtr
<UtilityProcessParent
> parent
=
353 self
->GetProcessParent(aSandbox
);
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
);
373 MOZ_ASSERT(false, "Could not create content remote decoder");
374 return RetPromise::CreateAndReject(
375 LaunchError("PRemoteDecoderManager::CreateEndpoints", rv
),
379 if (!uadc
->SendNewContentRemoteDecoderManager(std::move(parentPipe
),
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__
);
394 PROFILER_MARKER_TEXT(
395 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
398 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart
)),
400 return RetPromise::CreateAndResolve(std::move(childPipe
), __func__
);
402 [self
, remoteDecodingStart
](LaunchError
&& error
) {
404 "Reject StartProcessForRemoteMediaDecoding() for "
405 "StartUtility() rejection");
406 PROFILER_MARKER_TEXT(
407 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
410 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart
)),
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
)
421 GetCurrentSerialEventTarget(), __func__
,
422 []() { return RetPromise::CreateAndResolve(true, __func__
); },
423 [](LaunchError
const&) {
424 return RetPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE
,
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
)
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()"),
453 PROFILER_MARKER_TEXT(
454 "UtilityProcessManager::GetWindowsUtilsPromise", OTHER
,
456 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart
)),
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
,
465 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart
)),
467 return WindowsUtilsPromise::CreateAndReject(std::move(error
),
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
)
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
)),
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
)),
510 return RetPromise::CreateAndReject(std::move(error
),
511 __PRETTY_FUNCTION__
);
517 bool UtilityProcessManager::IsProcessLaunching(SandboxingKind aSandbox
) {
518 MOZ_ASSERT(NS_IsMainThread());
520 RefPtr
<ProcessFields
> p
= GetProcess(aSandbox
);
522 MOZ_CRASH("Cannot check process launching with no process");
526 return p
->mProcess
&& !(p
->mProcessParent
);
529 bool UtilityProcessManager::IsProcessDestroyed(SandboxingKind aSandbox
) {
530 MOZ_ASSERT(NS_IsMainThread());
531 RefPtr
<ProcessFields
> p
= GetProcess(aSandbox
);
533 MOZ_CRASH("Cannot check process destroyed with no process");
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
);
552 "Called UtilityProcessManager::OnProcessUnexpectedShutdown with invalid "
556 void UtilityProcessManager::CleanShutdownAllProcesses() {
557 LOGD("[%p] UtilityProcessManager::CleanShutdownAllProcesses", this);
559 for (auto& it
: mProcesses
) {
561 DestroyProcess(it
->mSandbox
);
566 void UtilityProcessManager::CleanShutdown(SandboxingKind aSandbox
) {
567 LOGD("[%p] UtilityProcessManager::CleanShutdown SandboxingKind=%" PRIu64
,
570 DestroyProcess(aSandbox
);
573 uint16_t UtilityProcessManager::AliveProcesses() {
575 for (auto& p
: mProcesses
) {
583 bool UtilityProcessManager::NoMoreProcesses() { return AliveProcesses() == 0; }
585 void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox
) {
586 LOGD("[%p] UtilityProcessManager::DestroyProcess SandboxingKind=%" PRIu64
,
589 MOZ_RELEASE_ASSERT(NS_IsMainThread());
591 if (AliveProcesses() <= 1) {
593 Preferences::RemoveObserver(mObserver
, "");
599 RefPtr
<ProcessFields
> p
= GetProcess(aSandbox
);
604 p
->mQueuedPrefs
.Clear();
605 p
->mProcessParent
= nullptr;
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
);
631 if (p
->mProcessParent
) {
632 return Some(p
->mProcessParent
->OtherPid());
637 class UtilityMemoryReporter
: public MemoryReportingProcess
{
639 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UtilityMemoryReporter
, override
)
641 explicit UtilityMemoryReporter(UtilityProcessParent
* 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();
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();
668 RefPtr
<UtilityProcessParent
> GetParent() const { return mParent
; }
670 RefPtr
<UtilityProcessParent
> mParent
= nullptr;
673 ~UtilityMemoryReporter() = default;
676 RefPtr
<MemoryReportingProcess
> UtilityProcessManager::GetProcessMemoryReporter(
677 UtilityProcessParent
* parent
) {
678 return new UtilityMemoryReporter(parent
);
681 } // namespace mozilla::ipc