Backed out 8 changesets (bug 1873776) for causing vendor failures. CLOSED TREE
[gecko.git] / ipc / glue / UtilityProcessManager.cpp
blobe24fed476baee99d99b9101e26380494d7d9f6ff
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, dom::ContentParentId aChildId,
315 SandboxingKind aSandbox) {
316 // Not supported kinds.
317 if (aSandbox != SandboxingKind::GENERIC_UTILITY
318 #ifdef MOZ_APPLEMEDIA
319 && aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA
320 #endif
321 #ifdef XP_WIN
322 && aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_WMF
323 #endif
324 #ifdef MOZ_WMF_MEDIA_ENGINE
325 && aSandbox != SandboxingKind::MF_MEDIA_ENGINE_CDM
326 #endif
328 return StartRemoteDecodingUtilityPromise::CreateAndReject(NS_ERROR_FAILURE,
329 __func__);
331 TimeStamp remoteDecodingStart = TimeStamp::Now();
333 RefPtr<UtilityProcessManager> self = this;
334 RefPtr<UtilityAudioDecoderChild> uadc =
335 UtilityAudioDecoderChild::GetSingleton(aSandbox);
336 MOZ_ASSERT(uadc, "Unable to get a singleton for UtilityAudioDecoderChild");
337 return StartUtility(uadc, aSandbox)
338 ->Then(
339 GetMainThreadSerialEventTarget(), __func__,
340 [self, uadc, aOtherProcess, aChildId, aSandbox,
341 remoteDecodingStart]() {
342 RefPtr<UtilityProcessParent> parent =
343 self->GetProcessParent(aSandbox);
344 if (!parent) {
345 NS_WARNING("UtilityAudioDecoderParent lost in the middle");
346 return StartRemoteDecodingUtilityPromise::CreateAndReject(
347 NS_ERROR_FAILURE, __func__);
350 if (!uadc->CanSend()) {
351 NS_WARNING("UtilityAudioDecoderChild lost in the middle");
352 return StartRemoteDecodingUtilityPromise::CreateAndReject(
353 NS_ERROR_FAILURE, __func__);
356 base::ProcessId process = parent->OtherPid();
358 Endpoint<PRemoteDecoderManagerChild> childPipe;
359 Endpoint<PRemoteDecoderManagerParent> parentPipe;
360 nsresult rv = PRemoteDecoderManager::CreateEndpoints(
361 process, aOtherProcess, &parentPipe, &childPipe);
362 if (NS_FAILED(rv)) {
363 MOZ_ASSERT(false, "Could not create content remote decoder");
364 return StartRemoteDecodingUtilityPromise::CreateAndReject(
365 rv, __func__);
368 if (!uadc->SendNewContentRemoteDecoderManager(std::move(parentPipe),
369 aChildId)) {
370 MOZ_ASSERT(false, "SendNewContentRemoteDecoderManager failure");
371 return StartRemoteDecodingUtilityPromise::CreateAndReject(
372 NS_ERROR_FAILURE, __func__);
375 #ifdef MOZ_WMF_MEDIA_ENGINE
376 if (aSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM &&
377 !uadc->CreateVideoBridge()) {
378 MOZ_ASSERT(false, "Failed to create video bridge");
379 return StartRemoteDecodingUtilityPromise::CreateAndReject(
380 NS_ERROR_FAILURE, __func__);
382 #endif
383 PROFILER_MARKER_TEXT(
384 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
385 MEDIA,
386 MarkerOptions(
387 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart)),
388 "Resolve"_ns);
389 return StartRemoteDecodingUtilityPromise::CreateAndResolve(
390 std::move(childPipe), __func__);
392 [self, remoteDecodingStart](nsresult aError) {
393 NS_WARNING(
394 "Reject StartProcessForRemoteMediaDecoding() for "
395 "StartUtility() rejection");
396 PROFILER_MARKER_TEXT(
397 "UtilityProcessManager::StartProcessForRemoteMediaDecoding",
398 MEDIA,
399 MarkerOptions(
400 MarkerTiming::IntervalUntilNowFrom(remoteDecodingStart)),
401 "Reject"_ns);
402 return StartRemoteDecodingUtilityPromise::CreateAndReject(aError,
403 __func__);
407 RefPtr<UtilityProcessManager::JSOraclePromise>
408 UtilityProcessManager::StartJSOracle(dom::JSOracleParent* aParent) {
409 return StartUtility(RefPtr{aParent}, SandboxingKind::GENERIC_UTILITY);
412 #ifdef XP_WIN
414 // Windows Utils
416 RefPtr<UtilityProcessManager::WindowsUtilsPromise>
417 UtilityProcessManager::GetWindowsUtilsPromise() {
418 TimeStamp windowsUtilsStart = TimeStamp::Now();
419 RefPtr<UtilityProcessManager> self = this;
420 if (!mWindowsUtils) {
421 mWindowsUtils = new dom::WindowsUtilsParent();
424 RefPtr<dom::WindowsUtilsParent> wup = mWindowsUtils;
425 MOZ_ASSERT(wup, "Unable to get a singleton for WindowsUtils");
426 return StartUtility(wup, SandboxingKind::WINDOWS_UTILS)
427 ->Then(
428 GetMainThreadSerialEventTarget(), __func__,
429 [self, wup, windowsUtilsStart]() {
430 if (!wup->CanSend()) {
431 MOZ_ASSERT(false, "WindowsUtilsParent can't send");
432 return WindowsUtilsPromise::CreateAndReject(NS_ERROR_FAILURE,
433 __func__);
435 PROFILER_MARKER_TEXT(
436 "UtilityProcessManager::GetWindowsUtilsPromise", OTHER,
437 MarkerOptions(
438 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart)),
439 "Resolve"_ns);
440 return WindowsUtilsPromise::CreateAndResolve(wup, __func__);
442 [self, windowsUtilsStart](nsresult aError) {
443 NS_WARNING("StartUtility rejected promise for PWindowsUtils");
444 PROFILER_MARKER_TEXT(
445 "UtilityProcessManager::GetWindowsUtilsPromise", OTHER,
446 MarkerOptions(
447 MarkerTiming::IntervalUntilNowFrom(windowsUtilsStart)),
448 "Reject"_ns);
449 return WindowsUtilsPromise::CreateAndReject(aError, __func__);
453 void UtilityProcessManager::ReleaseWindowsUtils() { mWindowsUtils = nullptr; }
455 RefPtr<UtilityProcessManager::WinFileDialogPromise>
456 UtilityProcessManager::CreateWinFileDialogActor() {
457 using Promise = WinFileDialogPromise;
458 TimeStamp startTime = TimeStamp::Now();
459 auto wfdp = MakeRefPtr<widget::filedialog::WinFileDialogParent>();
461 return StartUtility(wfdp, SandboxingKind::WINDOWS_FILE_DIALOG)
462 ->Then(
463 GetMainThreadSerialEventTarget(), __PRETTY_FUNCTION__,
464 [wfdp, startTime]() mutable {
465 LOGD("CreateWinFileDialogAsync() resolve: wfdp = [%p]", wfdp.get());
466 if (!wfdp->CanSend()) {
467 MOZ_ASSERT(false, "WinFileDialogParent can't send");
468 return Promise::CreateAndReject(NS_ERROR_FAILURE,
469 __PRETTY_FUNCTION__);
471 PROFILER_MARKER_TEXT(
472 "UtilityProcessManager::CreateWinFileDialogAsync", OTHER,
473 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(startTime)),
474 "Resolve"_ns);
476 return Promise::CreateAndResolve(
477 widget::filedialog::ProcessProxy(std::move(wfdp)),
478 __PRETTY_FUNCTION__);
480 [self = RefPtr(this), startTime](nsresult error) {
481 LOGD("CreateWinFileDialogAsync() reject");
482 if (!self->IsShutdown()) {
483 MOZ_ASSERT_UNREACHABLE("failure when starting file-dialog actor");
485 PROFILER_MARKER_TEXT(
486 "UtilityProcessManager::CreateWinFileDialogAsync", OTHER,
487 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(startTime)),
488 "Reject"_ns);
490 return Promise::CreateAndReject(error, __PRETTY_FUNCTION__);
494 #endif // XP_WIN
496 bool UtilityProcessManager::IsProcessLaunching(SandboxingKind aSandbox) {
497 MOZ_ASSERT(NS_IsMainThread());
499 RefPtr<ProcessFields> p = GetProcess(aSandbox);
500 if (!p) {
501 MOZ_CRASH("Cannot check process launching with no process");
502 return false;
505 return p->mProcess && !(p->mProcessParent);
508 bool UtilityProcessManager::IsProcessDestroyed(SandboxingKind aSandbox) {
509 MOZ_ASSERT(NS_IsMainThread());
510 RefPtr<ProcessFields> p = GetProcess(aSandbox);
511 if (!p) {
512 MOZ_CRASH("Cannot check process destroyed with no process");
513 return false;
515 return !p->mProcess && !p->mProcessParent;
518 void UtilityProcessManager::OnProcessUnexpectedShutdown(
519 UtilityProcessHost* aHost) {
520 MOZ_ASSERT(NS_IsMainThread());
522 for (auto& it : mProcesses) {
523 if (it && it->mProcess && it->mProcess == aHost) {
524 it->mNumUnexpectedCrashes++;
525 DestroyProcess(it->mSandbox);
526 return;
530 MOZ_CRASH(
531 "Called UtilityProcessManager::OnProcessUnexpectedShutdown with invalid "
532 "aHost");
535 void UtilityProcessManager::CleanShutdownAllProcesses() {
536 LOGD("[%p] UtilityProcessManager::CleanShutdownAllProcesses", this);
538 for (auto& it : mProcesses) {
539 if (it) {
540 DestroyProcess(it->mSandbox);
545 void UtilityProcessManager::CleanShutdown(SandboxingKind aSandbox) {
546 LOGD("[%p] UtilityProcessManager::CleanShutdown SandboxingKind=%" PRIu64,
547 this, aSandbox);
549 DestroyProcess(aSandbox);
552 uint16_t UtilityProcessManager::AliveProcesses() {
553 uint16_t alive = 0;
554 for (auto& p : mProcesses) {
555 if (p != nullptr) {
556 alive++;
559 return alive;
562 bool UtilityProcessManager::NoMoreProcesses() { return AliveProcesses() == 0; }
564 void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) {
565 LOGD("[%p] UtilityProcessManager::DestroyProcess SandboxingKind=%" PRIu64,
566 this, aSandbox);
568 MOZ_RELEASE_ASSERT(NS_IsMainThread());
570 if (AliveProcesses() <= 1) {
571 if (mObserver) {
572 Preferences::RemoveObserver(mObserver, "");
575 mObserver = nullptr;
578 RefPtr<ProcessFields> p = GetProcess(aSandbox);
579 if (!p) {
580 return;
583 p->mQueuedPrefs.Clear();
584 p->mProcessParent = nullptr;
586 if (!p->mProcess) {
587 return;
590 p->mProcess->Shutdown();
591 p->mProcess = nullptr;
593 mProcesses[aSandbox] = nullptr;
595 CrashReporter::AnnotateCrashReport(
596 CrashReporter::Annotation::UtilityProcessStatus, "Destroyed"_ns);
598 if (NoMoreProcesses()) {
599 sSingleton = nullptr;
603 Maybe<base::ProcessId> UtilityProcessManager::ProcessPid(
604 SandboxingKind aSandbox) {
605 MOZ_ASSERT(NS_IsMainThread());
606 RefPtr<ProcessFields> p = GetProcess(aSandbox);
607 if (!p) {
608 return Nothing();
610 if (p->mProcessParent) {
611 return Some(p->mProcessParent->OtherPid());
613 return Nothing();
616 class UtilityMemoryReporter : public MemoryReportingProcess {
617 public:
618 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UtilityMemoryReporter, override)
620 explicit UtilityMemoryReporter(UtilityProcessParent* aParent) {
621 mParent = aParent;
624 bool IsAlive() const override { return bool(GetParent()); }
626 bool SendRequestMemoryReport(
627 const uint32_t& aGeneration, const bool& aAnonymize,
628 const bool& aMinimizeMemoryUsage,
629 const Maybe<ipc::FileDescriptor>& aDMDFile) override {
630 RefPtr<UtilityProcessParent> parent = GetParent();
631 if (!parent) {
632 return false;
635 return parent->SendRequestMemoryReport(aGeneration, aAnonymize,
636 aMinimizeMemoryUsage, aDMDFile);
639 int32_t Pid() const override {
640 if (RefPtr<UtilityProcessParent> parent = GetParent()) {
641 return (int32_t)parent->OtherPid();
643 return 0;
646 private:
647 RefPtr<UtilityProcessParent> GetParent() const { return mParent; }
649 RefPtr<UtilityProcessParent> mParent = nullptr;
651 protected:
652 ~UtilityMemoryReporter() = default;
655 RefPtr<MemoryReportingProcess> UtilityProcessManager::GetProcessMemoryReporter(
656 UtilityProcessParent* parent) {
657 return new UtilityMemoryReporter(parent);
660 } // namespace mozilla::ipc