no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / ipc / glue / CrashReporterHost.cpp
blob9fee9187a69ea741b69d0dbdc2ffd7365d9f18dd
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;
32 FinalizeCrashReport();
33 RecordCrash(mProcessType, nsICrashService::CRASH_TYPE_CRASH, mDumpID);
34 return true;
37 RefPtr<nsIFile> CrashReporterHost::TakeCrashedChildMinidump(
38 base::ProcessId aPid, uint32_t* aOutSequence) {
39 CrashReporter::AnnotationTable annotations;
40 MOZ_ASSERT(!HasMinidump());
42 RefPtr<nsIFile> crashDump;
43 if (!CrashReporter::TakeMinidumpForChild(aPid, getter_AddRefs(crashDump),
44 annotations, aOutSequence)) {
45 return nullptr;
47 if (!AdoptMinidump(crashDump, annotations)) {
48 return nullptr;
50 return crashDump;
53 bool CrashReporterHost::AdoptMinidump(nsIFile* aFile,
54 const AnnotationTable& aAnnotations) {
55 if (!CrashReporter::GetIDFromMinidump(aFile, mDumpID)) {
56 return false;
59 MergeCrashAnnotations(mExtraAnnotations, aAnnotations);
60 return true;
63 void CrashReporterHost::FinalizeCrashReport() {
64 MOZ_ASSERT(!mFinalized);
65 MOZ_ASSERT(HasMinidump());
67 mExtraAnnotations[CrashReporter::Annotation::ProcessType] =
68 XRE_ChildProcessTypeToAnnotation(mProcessType);
70 char startTime[32];
71 SprintfLiteral(startTime, "%lld", static_cast<long long>(mStartTime));
72 mExtraAnnotations[CrashReporter::Annotation::StartupTime] =
73 nsDependentCString(startTime);
75 CrashReporter::WriteExtraFile(mDumpID, mExtraAnnotations);
76 mFinalized = true;
79 void CrashReporterHost::DeleteCrashReport() {
80 if (mFinalized && HasMinidump()) {
81 CrashReporter::DeleteMinidumpFilesForID(mDumpID, Some(u"browser"_ns));
85 /* static */
86 void CrashReporterHost::RecordCrash(GeckoProcessType aProcessType,
87 int32_t aCrashType,
88 const nsString& aChildDumpID) {
89 if (!NS_IsMainThread()) {
90 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
91 "ipc::CrashReporterHost::RecordCrash", [&]() -> void {
92 CrashReporterHost::RecordCrash(aProcessType, aCrashType,
93 aChildDumpID);
94 });
95 RefPtr<nsIThread> mainThread = do_GetMainThread();
96 SyncRunnable::DispatchToThread(mainThread, runnable);
97 return;
100 RecordCrashWithTelemetry(aProcessType, aCrashType);
101 NotifyCrashService(aProcessType, aCrashType, aChildDumpID);
104 /* static */
105 void CrashReporterHost::RecordCrashWithTelemetry(GeckoProcessType aProcessType,
106 int32_t aCrashType) {
107 nsCString key;
109 switch (aProcessType) {
110 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
111 process_bin_type, procinfo_typename, \
112 webidl_typename, allcaps_name) \
113 case GeckoProcessType_##enum_name: \
114 key.AssignLiteral(string_name); \
115 break;
116 #include "mozilla/GeckoProcessTypes.h"
117 #undef GECKO_PROCESS_TYPE
118 // We can't really hit this, thanks to the above switch, but having it
119 // here will placate the compiler.
120 default:
121 MOZ_ASSERT_UNREACHABLE("unknown process type");
124 Telemetry::Accumulate(Telemetry::SUBPROCESS_CRASHES_WITH_DUMP, key, 1);
127 /* static */
128 void CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType,
129 int32_t aCrashType,
130 const nsString& aChildDumpID) {
131 MOZ_ASSERT(!aChildDumpID.IsEmpty());
133 nsCOMPtr<nsICrashService> crashService =
134 do_GetService("@mozilla.org/crashservice;1");
135 if (!crashService) {
136 return;
139 int32_t processType;
141 switch (aProcessType) {
142 case GeckoProcessType_IPDLUnitTest:
143 case GeckoProcessType_Default:
144 NS_ERROR("unknown process type");
145 return;
146 default:
147 processType = (int)aProcessType;
148 break;
151 RefPtr<dom::Promise> promise;
152 crashService->AddCrash(processType, aCrashType, aChildDumpID,
153 getter_AddRefs(promise));
156 void CrashReporterHost::AddAnnotationBool(CrashReporter::Annotation aKey,
157 bool aValue) {
158 MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::Boolean,
159 "Wrong annotation type");
160 mExtraAnnotations[aKey] = aValue ? "1"_ns : "0"_ns;
163 void CrashReporterHost::AddAnnotationU32(CrashReporter::Annotation aKey,
164 uint32_t aValue) {
165 MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::U32,
166 "Wrong annotation type");
167 nsAutoCString valueString;
168 valueString.AppendInt(aValue);
169 mExtraAnnotations[aKey] = valueString;
172 void CrashReporterHost::AddAnnotationNSCString(CrashReporter::Annotation aKey,
173 const nsACString& aValue) {
174 MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::String,
175 "Wrong annotation type");
176 mExtraAnnotations[aKey] = aValue;
179 } // namespace ipc
180 } // namespace mozilla