UtilityProcessParent.cpp (6921B)
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 "mozilla/ipc/UtilityProcessParent.h" 7 #include "mozilla/GeckoTrace.h" 8 #include "mozilla/ipc/UtilityProcessManager.h" 9 10 #if defined(XP_WIN) 11 # include <dwrite.h> 12 # include <process.h> 13 # include "mozilla/WinDllServices.h" 14 #endif 15 16 #include "mozilla/ipc/ProcessChild.h" 17 #include "mozilla/FOGIPC.h" 18 19 #include "mozilla/Telemetry.h" 20 #include "mozilla/TelemetryIPC.h" 21 22 #include "nsHashPropertyBag.h" 23 #include "mozilla/Services.h" 24 #include "nsIObserverService.h" 25 26 namespace mozilla::ipc { 27 28 UtilityProcessParent::UtilityProcessParent(UtilityProcessHost* aHost) 29 : mHost(aHost) { 30 MOZ_ASSERT(NS_IsMainThread()); 31 MOZ_ASSERT(mHost); 32 } 33 34 UtilityProcessParent::~UtilityProcessParent() = default; 35 36 bool UtilityProcessParent::SendRequestMemoryReport( 37 const uint32_t& aGeneration, const bool& aAnonymize, 38 const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile) { 39 mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration); 40 41 PUtilityProcessParent::SendRequestMemoryReport( 42 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, 43 [self = RefPtr{this}](const uint32_t& aGeneration2) { 44 if (self->mMemoryReportRequest) { 45 self->mMemoryReportRequest->Finish(aGeneration2); 46 self->mMemoryReportRequest = nullptr; 47 } 48 }, 49 [self = RefPtr{this}](mozilla::ipc::ResponseRejectReason) { 50 self->mMemoryReportRequest = nullptr; 51 }); 52 53 return true; 54 } 55 56 mozilla::ipc::IPCResult UtilityProcessParent::RecvAddMemoryReport( 57 const MemoryReport& aReport) { 58 if (mMemoryReportRequest) { 59 mMemoryReportRequest->RecvReport(aReport); 60 } 61 return IPC_OK(); 62 } 63 64 mozilla::ipc::IPCResult UtilityProcessParent::RecvFOGData(ByteBuf&& aBuf) { 65 glean::FOGData(std::move(aBuf)); 66 return IPC_OK(); 67 } 68 69 mozilla::ipc::IPCResult UtilityProcessParent::RecvGeckoTraceExport( 70 ByteBuf&& aBuf) { 71 recv_gecko_trace_export(aBuf.mData, aBuf.mLen); 72 return IPC_OK(); 73 } 74 75 #if defined(XP_WIN) 76 mozilla::ipc::IPCResult UtilityProcessParent::RecvGetModulesTrust( 77 ModulePaths&& aModPaths, bool aRunAtNormalPriority, 78 GetModulesTrustResolver&& aResolver) { 79 RefPtr<DllServices> dllSvc(DllServices::Get()); 80 dllSvc->GetModulesTrust(std::move(aModPaths), aRunAtNormalPriority) 81 ->Then( 82 GetMainThreadSerialEventTarget(), __func__, 83 [aResolver](ModulesMapResult&& aResult) { 84 aResolver(Some(ModulesMapResult(std::move(aResult)))); 85 }, 86 [aResolver](nsresult aRv) { aResolver(Nothing()); }); 87 return IPC_OK(); 88 } 89 #endif // defined(XP_WIN) 90 91 mozilla::ipc::IPCResult UtilityProcessParent::RecvAccumulateChildHistograms( 92 nsTArray<HistogramAccumulation>&& aAccumulations) { 93 TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Utility, 94 aAccumulations); 95 return IPC_OK(); 96 } 97 98 mozilla::ipc::IPCResult 99 UtilityProcessParent::RecvAccumulateChildKeyedHistograms( 100 nsTArray<KeyedHistogramAccumulation>&& aAccumulations) { 101 TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Utility, 102 aAccumulations); 103 return IPC_OK(); 104 } 105 106 mozilla::ipc::IPCResult UtilityProcessParent::RecvUpdateChildScalars( 107 nsTArray<ScalarAction>&& aScalarActions) { 108 TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Utility, 109 aScalarActions); 110 return IPC_OK(); 111 } 112 113 mozilla::ipc::IPCResult UtilityProcessParent::RecvUpdateChildKeyedScalars( 114 nsTArray<KeyedScalarAction>&& aScalarActions) { 115 TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Utility, 116 aScalarActions); 117 return IPC_OK(); 118 } 119 120 mozilla::ipc::IPCResult UtilityProcessParent::RecvRecordChildEvents( 121 nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents) { 122 TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Utility, aEvents); 123 return IPC_OK(); 124 } 125 126 mozilla::ipc::IPCResult UtilityProcessParent::RecvRecordDiscardedData( 127 const mozilla::Telemetry::DiscardedData& aDiscardedData) { 128 TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Utility, 129 aDiscardedData); 130 return IPC_OK(); 131 } 132 133 mozilla::ipc::IPCResult UtilityProcessParent::RecvInitCompleted() { 134 MOZ_ASSERT(mHost); 135 mHost->ResolvePromise(); 136 return IPC_OK(); 137 } 138 139 void UtilityProcessParent::ActorDestroy(ActorDestroyReason aWhy) { 140 RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag(); 141 142 if (aWhy == AbnormalShutdown) { 143 nsAutoString dumpID; 144 145 if (mCrashReporter) { 146 #if defined(MOZ_SANDBOX) 147 RefPtr<mozilla::ipc::UtilityProcessManager> upm = 148 mozilla::ipc::UtilityProcessManager::GetSingleton(); 149 if (upm) { 150 Span<const UtilityActorName> actors = upm->GetActors(this); 151 nsAutoCString actorsName; 152 if (!actors.IsEmpty()) { 153 actorsName += GetUtilityActorName(actors.First<1>()[0]); 154 for (const auto& actor : actors.From(1)) { 155 actorsName += ", "_ns + GetUtilityActorName(actor); 156 } 157 } 158 mCrashReporter->AddAnnotationNSCString( 159 CrashReporter::Annotation::UtilityActorsName, actorsName); 160 } 161 #endif 162 } 163 164 GenerateCrashReport(&dumpID); 165 166 // It's okay for dumpID to be empty if there was no minidump generated 167 // tests like ipc/glue/test/browser/browser_utility_crashReporter.js are 168 // there to verify this 169 if (!dumpID.IsEmpty()) { 170 props->SetPropertyAsAString(u"dumpID"_ns, dumpID); 171 } 172 173 MaybeTerminateProcess(); 174 } 175 176 nsAutoString pid; 177 pid.AppendInt(static_cast<uint64_t>(OtherPid())); 178 179 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 180 if (obs) { 181 obs->NotifyObservers((nsIPropertyBag2*)props, "ipc:utility-shutdown", 182 pid.get()); 183 } else { 184 NS_WARNING("Could not get a nsIObserverService, ipc:utility-shutdown skip"); 185 } 186 187 mHost->OnChannelClosed(aWhy); 188 } 189 190 // To ensure that IPDL is finished before UtilityParent gets deleted. 191 class DeferredDeleteUtilityProcessParent : public Runnable { 192 public: 193 explicit DeferredDeleteUtilityProcessParent( 194 RefPtr<UtilityProcessParent> aParent) 195 : Runnable("ipc::glue::DeferredDeleteUtilityProcessParent"), 196 mParent(std::move(aParent)) {} 197 198 NS_IMETHODIMP Run() override { return NS_OK; } 199 200 private: 201 RefPtr<UtilityProcessParent> mParent; 202 }; 203 204 /* static */ 205 void UtilityProcessParent::Destroy(RefPtr<UtilityProcessParent> aParent) { 206 NS_DispatchToMainThread( 207 new DeferredDeleteUtilityProcessParent(std::move(aParent))); 208 } 209 210 } // namespace mozilla::ipc