1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/app/chrome_crash_reporter_client.h"
7 #include "base/command_line.h"
8 #include "base/environment.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/no_destructor.h"
12 #include "base/path_service.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "build/branding_buildflags.h"
16 #include "build/build_config.h"
17 #include "build/chromeos_buildflags.h"
18 #include "chrome/common/channel_info.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/chrome_paths_internal.h"
21 #include "chrome/common/chrome_result_codes.h"
22 #include "chrome/common/env_vars.h"
23 #include "chrome/installer/util/google_update_settings.h"
24 #include "components/crash/core/common/crash_keys.h"
25 #include "content/public/common/content_switches.h"
27 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
28 #include "components/upload_list/crash_upload_list.h"
29 #include "components/version_info/version_info.h"
30 #include "components/version_info/version_info_values.h"
33 #if BUILDFLAG(IS_POSIX)
34 #include "base/debug/dump_without_crashing.h"
37 #if BUILDFLAG(IS_ANDROID)
38 #include "chrome/common/chrome_descriptors.h"
41 #if BUILDFLAG(IS_CHROMEOS_ASH)
42 #include "ash/constants/ash_switches.h"
45 void ChromeCrashReporterClient::Create() {
46 static base::NoDestructor<ChromeCrashReporterClient> crash_client;
47 crash_reporter::SetCrashReporterClient(crash_client.get());
49 // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
50 // location to write crash dumps can be set.
51 std::unique_ptr<base::Environment> env(base::Environment::Create());
52 std::string alternate_crash_dump_location;
53 base::FilePath crash_dumps_dir_path;
54 if (env->GetVar("BREAKPAD_DUMP_LOCATION", &alternate_crash_dump_location)) {
55 crash_dumps_dir_path =
56 base::FilePath::FromUTF8Unsafe(alternate_crash_dump_location);
57 } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
58 "breakpad-dump-location")) {
59 // This is needed for Android tests, where we want dumps to go to a location
60 // where they don't get uploaded/deleted, but we can't use environment
62 crash_dumps_dir_path =
63 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
64 "breakpad-dump-location");
66 if (!crash_dumps_dir_path.empty()) {
67 base::PathService::Override(chrome::DIR_CRASH_DUMPS, crash_dumps_dir_path);
71 #if BUILDFLAG(IS_CHROMEOS_ASH)
73 bool ChromeCrashReporterClient::ShouldPassCrashLoopBefore(
74 const std::string& process_type) {
75 if (process_type == ::switches::kRendererProcess ||
76 process_type == ::switches::kUtilityProcess ||
77 process_type == ::switches::kPpapiPluginProcess ||
78 process_type == ::switches::kZygoteProcess) {
79 // These process types never cause a log-out, even if they crash. So the
80 // normal crash handling process should work fine; we shouldn't need to
81 // invoke the special crash-loop mode.
88 ChromeCrashReporterClient::ChromeCrashReporterClient() {}
90 ChromeCrashReporterClient::~ChromeCrashReporterClient() {}
92 #if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
93 void ChromeCrashReporterClient::SetCrashReporterClientIdFromGUID(
94 const std::string& client_guid) {
95 crash_keys::SetMetricsClientIdFromGUID(client_guid);
99 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
100 void ChromeCrashReporterClient::GetProductNameAndVersion(
101 const char** product_name,
102 const char** version) {
103 DCHECK(product_name);
105 #if BUILDFLAG(IS_ANDROID)
106 *product_name = "Chrome_Android";
107 #elif BUILDFLAG(IS_CHROMEOS_ASH)
108 *product_name = "Chrome_ChromeOS";
109 #elif BUILDFLAG(IS_CHROMEOS_LACROS)
110 *product_name = "Chrome_Lacros";
111 #else // BUILDFLAG(IS_ANDROID)
112 #if !defined(ADDRESS_SANITIZER)
113 *product_name = "Chrome_Linux";
115 *product_name = "Chrome_Linux_ASan";
119 *version = PRODUCT_VERSION;
122 void ChromeCrashReporterClient::GetProductNameAndVersion(
123 std::string* product_name,
124 std::string* version,
125 std::string* channel) {
126 const char* c_product_name;
127 const char* c_version;
128 GetProductNameAndVersion(&c_product_name, &c_version);
129 *product_name = c_product_name;
130 *version = c_version;
131 *channel = chrome::GetChannelName(chrome::WithExtendedStable(true));
134 base::FilePath ChromeCrashReporterClient::GetReporterLogFilename() {
135 return base::FilePath(CrashUploadList::kReporterLogFilename);
138 bool ChromeCrashReporterClient::GetShouldDumpLargerDumps() {
139 return chrome::GetChannel() != version_info::Channel::STABLE;
141 #endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
143 bool ChromeCrashReporterClient::GetCrashDumpLocation(
144 base::FilePath* crash_dir) {
145 return base::PathService::Get(chrome::DIR_CRASH_DUMPS, crash_dir);
148 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
149 bool ChromeCrashReporterClient::GetCrashMetricsLocation(
150 base::FilePath* metrics_dir) {
151 if (!GetCollectStatsConsent())
153 return base::PathService::Get(chrome::DIR_USER_DATA, metrics_dir);
155 #endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
157 bool ChromeCrashReporterClient::IsRunningUnattended() {
158 std::unique_ptr<base::Environment> env(base::Environment::Create());
159 return env->HasVar(env_vars::kHeadless);
162 bool ChromeCrashReporterClient::GetCollectStatsConsent() {
163 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
164 bool is_official_chrome_build = true;
166 bool is_official_chrome_build = false;
169 #if BUILDFLAG(IS_CHROMEOS_ASH)
170 bool is_guest_session = base::CommandLine::ForCurrentProcess()->HasSwitch(
171 ash::switches::kGuestSession);
172 bool is_stable_channel =
173 chrome::GetChannel() == version_info::Channel::STABLE;
175 if (is_guest_session && is_stable_channel) {
176 VLOG(1) << "GetCollectStatsConsent(): is_guest_session " << is_guest_session
177 << " && is_stable_channel " << is_stable_channel
178 << " so returning false";
181 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
183 #if BUILDFLAG(IS_ANDROID)
184 // TODO(jcivelli): we should not initialize the crash-reporter when it was not
185 // enabled. Right now if it is disabled we still generate the minidumps but we
186 // do not upload them.
187 return is_official_chrome_build;
188 #else // !BUILDFLAG(IS_ANDROID)
189 if (!is_official_chrome_build) {
190 VLOG(1) << "GetCollectStatsConsent(): is_official_chrome_build is false "
191 << "so returning false";
194 bool settings_consent = GoogleUpdateSettings::GetCollectStatsConsent();
195 VLOG(1) << "GetCollectStatsConsent(): settings_consent: " << settings_consent
196 << " so returning that";
197 return settings_consent;
198 #endif // BUILDFLAG(IS_ANDROID)
201 #if BUILDFLAG(IS_ANDROID)
202 int ChromeCrashReporterClient::GetAndroidMinidumpDescriptor() {
203 return kAndroidMinidumpDescriptor;
207 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
208 bool ChromeCrashReporterClient::ShouldMonitorCrashHandlerExpensively() {
209 // TODO(jperaza): Turn this on less frequently for stable channels when
210 // Crashpad is always enabled on Linux. Consider combining with the
211 // macOS implementation.
214 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
216 bool ChromeCrashReporterClient::EnableBreakpadForProcess(
217 const std::string& process_type) {
218 return process_type == switches::kRendererProcess ||
219 process_type == switches::kPpapiPluginProcess ||
220 process_type == switches::kZygoteProcess ||
221 process_type == switches::kGpuProcess ||
222 process_type == switches::kUtilityProcess;