Bug 1758813 [wpt PR 33142] - Implement RP sign out, a=testonly
[gecko.git] / ipc / glue / CrashReporterHost.cpp
blob959b8b3f71370b1f6f2ce6dc0194b33f21ddea94
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/. */
7 #include "CrashReporterHost.h"
8 #include "mozilla/dom/Promise.h"
9 #include "mozilla/Sprintf.h"
10 #include "mozilla/SyncRunnable.h"
11 #include "mozilla/Telemetry.h"
12 #include "nsServiceManagerUtils.h"
13 #include "nsICrashService.h"
14 #include "nsXULAppAPI.h"
15 #include "nsIFile.h"
17 namespace mozilla {
18 namespace ipc {
20 CrashReporterHost::CrashReporterHost(GeckoProcessType aProcessType,
21 CrashReporter::ThreadId aThreadId)
22 : mProcessType(aProcessType),
23 mThreadId(aThreadId),
24 mStartTime(::time(nullptr)),
25 mFinalized(false) {}
27 bool CrashReporterHost::GenerateCrashReport(base::ProcessId aPid) {
28 if (!TakeCrashedChildMinidump(aPid, nullptr)) {
29 return false;
31 return FinalizeCrashReport();
34 RefPtr<nsIFile> CrashReporterHost::TakeCrashedChildMinidump(
35 base::ProcessId aPid, uint32_t* aOutSequence) {
36 CrashReporter::AnnotationTable annotations;
37 MOZ_ASSERT(!HasMinidump());
39 RefPtr<nsIFile> crashDump;
40 if (!CrashReporter::TakeMinidumpForChild(aPid, getter_AddRefs(crashDump),
41 annotations, aOutSequence)) {
42 return nullptr;
44 if (!AdoptMinidump(crashDump, annotations)) {
45 return nullptr;
47 return crashDump;
50 bool CrashReporterHost::AdoptMinidump(nsIFile* aFile,
51 const AnnotationTable& aAnnotations) {
52 if (!CrashReporter::GetIDFromMinidump(aFile, mDumpID)) {
53 return false;
56 MergeCrashAnnotations(mExtraAnnotations, aAnnotations);
57 return true;
60 bool CrashReporterHost::FinalizeCrashReport() {
61 MOZ_ASSERT(!mFinalized);
62 MOZ_ASSERT(HasMinidump());
64 mExtraAnnotations[CrashReporter::Annotation::ProcessType] =
65 XRE_ChildProcessTypeToAnnotation(mProcessType);
67 char startTime[32];
68 SprintfLiteral(startTime, "%lld", static_cast<long long>(mStartTime));
69 mExtraAnnotations[CrashReporter::Annotation::StartupTime] =
70 nsDependentCString(startTime);
72 CrashReporter::WriteExtraFile(mDumpID, mExtraAnnotations);
74 RecordCrash(mProcessType, nsICrashService::CRASH_TYPE_CRASH, mDumpID);
76 mFinalized = true;
77 return true;
80 /* static */
81 void CrashReporterHost::RecordCrash(GeckoProcessType aProcessType,
82 int32_t aCrashType,
83 const nsString& aChildDumpID) {
84 if (!NS_IsMainThread()) {
85 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
86 "ipc::CrashReporterHost::RecordCrash", [&]() -> void {
87 CrashReporterHost::RecordCrash(aProcessType, aCrashType,
88 aChildDumpID);
89 });
90 RefPtr<nsIThread> mainThread = do_GetMainThread();
91 SyncRunnable::DispatchToThread(mainThread, runnable);
92 return;
95 RecordCrashWithTelemetry(aProcessType, aCrashType);
96 NotifyCrashService(aProcessType, aCrashType, aChildDumpID);
99 /* static */
100 void CrashReporterHost::RecordCrashWithTelemetry(GeckoProcessType aProcessType,
101 int32_t aCrashType) {
102 nsCString key;
104 switch (aProcessType) {
105 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
106 process_bin_type, procinfo_typename, \
107 webidl_typename, allcaps_name) \
108 case GeckoProcessType_##enum_name: \
109 key.AssignLiteral(string_name); \
110 break;
111 #include "mozilla/GeckoProcessTypes.h"
112 #undef GECKO_PROCESS_TYPE
113 // We can't really hit this, thanks to the above switch, but having it
114 // here will placate the compiler.
115 default:
116 MOZ_ASSERT_UNREACHABLE("unknown process type");
119 Telemetry::Accumulate(Telemetry::SUBPROCESS_CRASHES_WITH_DUMP, key, 1);
122 /* static */
123 void CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType,
124 int32_t aCrashType,
125 const nsString& aChildDumpID) {
126 MOZ_ASSERT(!aChildDumpID.IsEmpty());
128 nsCOMPtr<nsICrashService> crashService =
129 do_GetService("@mozilla.org/crashservice;1");
130 if (!crashService) {
131 return;
134 int32_t processType;
136 switch (aProcessType) {
137 case GeckoProcessType_IPDLUnitTest:
138 case GeckoProcessType_Default:
139 NS_ERROR("unknown process type");
140 return;
141 default:
142 processType = (int)aProcessType;
143 break;
146 RefPtr<dom::Promise> promise;
147 crashService->AddCrash(processType, aCrashType, aChildDumpID,
148 getter_AddRefs(promise));
151 void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey,
152 bool aValue) {
153 mExtraAnnotations[aKey] = aValue ? "1"_ns : "0"_ns;
156 void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey,
157 int aValue) {
158 nsAutoCString valueString;
159 valueString.AppendInt(aValue);
160 mExtraAnnotations[aKey] = valueString;
163 void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey,
164 unsigned int aValue) {
165 nsAutoCString valueString;
166 valueString.AppendInt(aValue);
167 mExtraAnnotations[aKey] = valueString;
170 void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey,
171 const nsACString& aValue) {
172 mExtraAnnotations[aKey] = aValue;
175 bool CrashReporterHost::IsLikelyOOM() {
176 // The data is only populated during the call to `FinalizeCrashReport()`.
177 MOZ_ASSERT(mFinalized);
179 // If `OOMAllocationSize` was set, we know that the crash happened
180 // because an allocation failed (`malloc` returned `nullptr`).
182 // As Unix systems generally allow `malloc` to return a non-null value
183 // even when no virtual memory is available, this doesn't cover all
184 // cases of OOM under Unix (far from it).
185 return mExtraAnnotations[CrashReporter::Annotation::OOMAllocationSize]
186 .Length() > 0;
189 } // namespace ipc
190 } // namespace mozilla