1 // Copyright 2013 The Chromium Authors. All rights reserved.
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/path_service.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/common/chrome_constants.h"
15 #include "chrome/common/chrome_paths.h"
16 #include "chrome/common/chrome_result_codes.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/crash_keys.h"
19 #include "chrome/common/env_vars.h"
20 #include "chrome/installer/util/google_update_settings.h"
25 #include "base/file_version_info.h"
26 #include "base/win/registry.h"
27 #include "chrome/installer/util/google_chrome_sxs_distribution.h"
28 #include "chrome/installer/util/install_util.h"
29 #include "chrome/installer/util/util_constants.h"
30 #include "components/browser_watcher/crash_reporting_metrics_win.h"
31 #include "policy/policy_constants.h"
34 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
35 #include "components/upload_list/crash_upload_list.h"
36 #include "components/version_info/version_info_values.h"
40 #include "base/debug/dump_without_crashing.h"
43 #if defined(OS_ANDROID)
44 #include "chrome/common/descriptors_android.h"
47 #if defined(OS_CHROMEOS)
48 #include "chrome/common/channel_info.h"
49 #include "chromeos/chromeos_switches.h"
50 #include "components/version_info/version_info.h"
56 // This is the minimum version of google update that is required for deferred
57 // crash uploads to work.
58 const char kMinUpdateVersion
[] = "1.3.21.115";
63 ChromeCrashReporterClient::ChromeCrashReporterClient() {}
65 ChromeCrashReporterClient::~ChromeCrashReporterClient() {}
67 #if !defined(OS_MACOSX)
68 void ChromeCrashReporterClient::SetCrashReporterClientIdFromGUID(
69 const std::string
& client_guid
) {
70 crash_keys::SetMetricsClientIdFromGUID(client_guid
);
75 bool ChromeCrashReporterClient::GetAlternativeCrashDumpLocation(
76 base::FilePath
* crash_dir
) {
77 // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
78 // location to write breakpad crash dumps can be set.
79 scoped_ptr
<base::Environment
> env(base::Environment::Create());
80 std::string alternate_crash_dump_location
;
81 if (env
->GetVar("BREAKPAD_DUMP_LOCATION", &alternate_crash_dump_location
)) {
82 *crash_dir
= base::FilePath::FromUTF8Unsafe(alternate_crash_dump_location
);
89 void ChromeCrashReporterClient::GetProductNameAndVersion(
90 const base::FilePath
& exe_path
,
91 base::string16
* product_name
,
92 base::string16
* version
,
93 base::string16
* special_build
,
94 base::string16
* channel_name
) {
97 DCHECK(special_build
);
100 scoped_ptr
<FileVersionInfo
> version_info(
101 FileVersionInfo::CreateFileVersionInfo(exe_path
));
103 if (version_info
.get()) {
104 // Get the information from the file.
105 *version
= version_info
->product_version();
106 if (!version_info
->is_official_build())
107 version
->append(base::ASCIIToUTF16("-devel"));
109 *product_name
= version_info
->product_short_name();
110 *special_build
= version_info
->special_build();
112 // No version info found. Make up the values.
113 *product_name
= base::ASCIIToUTF16("Chrome");
114 *version
= base::ASCIIToUTF16("0.0.0.0-devel");
117 GoogleUpdateSettings::GetChromeChannelAndModifiers(
118 !GetIsPerUserInstall(exe_path
), channel_name
);
121 bool ChromeCrashReporterClient::ShouldShowRestartDialog(base::string16
* title
,
122 base::string16
* message
,
123 bool* is_rtl_locale
) {
124 scoped_ptr
<base::Environment
> env(base::Environment::Create());
125 if (!env
->HasVar(env_vars::kShowRestart
) ||
126 !env
->HasVar(env_vars::kRestartInfo
) ||
127 env
->HasVar(env_vars::kMetroConnected
)) {
131 std::string restart_info
;
132 env
->GetVar(env_vars::kRestartInfo
, &restart_info
);
134 // The CHROME_RESTART var contains the dialog strings separated by '|'.
135 // See ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment()
137 std::vector
<std::string
> dlg_strings
= base::SplitString(
138 restart_info
, "|", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
140 if (dlg_strings
.size() < 3)
143 *title
= base::UTF8ToUTF16(dlg_strings
[0]);
144 *message
= base::UTF8ToUTF16(dlg_strings
[1]);
145 *is_rtl_locale
= dlg_strings
[2] == env_vars::kRtlLocale
;
149 bool ChromeCrashReporterClient::AboutToRestart() {
150 scoped_ptr
<base::Environment
> env(base::Environment::Create());
151 if (!env
->HasVar(env_vars::kRestartInfo
))
154 env
->SetVar(env_vars::kShowRestart
, "1");
158 bool ChromeCrashReporterClient::GetDeferredUploadsSupported(
159 bool is_per_user_install
) {
160 Version update_version
= GoogleUpdateSettings::GetGoogleUpdateVersion(
161 !is_per_user_install
);
162 if (!update_version
.IsValid() ||
163 update_version
.IsOlderThan(std::string(kMinUpdateVersion
)))
169 bool ChromeCrashReporterClient::GetIsPerUserInstall(
170 const base::FilePath
& exe_path
) {
171 return InstallUtil::IsPerUserInstall(exe_path
);
174 bool ChromeCrashReporterClient::GetShouldDumpLargerDumps(
175 bool is_per_user_install
) {
176 base::string16 channel_name
=
177 GoogleUpdateSettings::GetChromeChannel(!is_per_user_install
);
179 // Capture more detail in crash dumps for beta and dev channel builds.
180 return (channel_name
== installer::kChromeChannelDev
||
181 channel_name
== installer::kChromeChannelBeta
||
182 channel_name
== GoogleChromeSxSDistribution::ChannelName());
185 int ChromeCrashReporterClient::GetResultCodeRespawnFailed() {
186 return chrome::RESULT_CODE_RESPAWN_FAILED
;
189 void ChromeCrashReporterClient::InitBrowserCrashDumpsRegKey() {
190 #if !defined(NACL_WIN64)
191 if (GetCollectStatsConsent()){
192 crash_reporting_metrics_
.reset(new browser_watcher::CrashReportingMetrics(
193 InstallUtil::IsChromeSxSProcess()
194 ? chrome::kBrowserCrashDumpAttemptsRegistryPathSxS
195 : chrome::kBrowserCrashDumpAttemptsRegistryPath
));
200 void ChromeCrashReporterClient::RecordCrashDumpAttempt(bool is_real_crash
) {
201 #if !defined(NACL_WIN64)
202 if (!crash_reporting_metrics_
)
206 crash_reporting_metrics_
->RecordCrashDumpAttempt();
208 crash_reporting_metrics_
->RecordDumpWithoutCrashAttempt();
212 void ChromeCrashReporterClient::RecordCrashDumpAttemptResult(bool is_real_crash
,
214 #if !defined(NACL_WIN64)
215 if (!crash_reporting_metrics_
)
219 crash_reporting_metrics_
->RecordCrashDumpAttemptResult(succeeded
);
221 crash_reporting_metrics_
->RecordDumpWithoutCrashAttemptResult(succeeded
);
225 bool ChromeCrashReporterClient::ReportingIsEnforcedByPolicy(
226 bool* breakpad_enabled
) {
227 // Determine whether configuration management allows loading the crash reporter.
228 // Since the configuration management infrastructure is not initialized at this
229 // point, we read the corresponding registry key directly. The return status
230 // indicates whether policy data was successfully read. If it is true,
231 // |breakpad_enabled| contains the value set by policy.
232 base::string16 key_name
=
233 base::UTF8ToUTF16(policy::key::kMetricsReportingEnabled
);
235 base::win::RegKey
hklm_policy_key(HKEY_LOCAL_MACHINE
,
236 policy::kRegistryChromePolicyKey
, KEY_READ
);
237 if (hklm_policy_key
.ReadValueDW(key_name
.c_str(), &value
) == ERROR_SUCCESS
) {
238 *breakpad_enabled
= value
!= 0;
242 base::win::RegKey
hkcu_policy_key(HKEY_CURRENT_USER
,
243 policy::kRegistryChromePolicyKey
, KEY_READ
);
244 if (hkcu_policy_key
.ReadValueDW(key_name
.c_str(), &value
) == ERROR_SUCCESS
) {
245 *breakpad_enabled
= value
!= 0;
251 #endif // defined(OS_WIN)
253 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
254 void ChromeCrashReporterClient::GetProductNameAndVersion(
255 const char** product_name
,
256 const char** version
) {
257 DCHECK(product_name
);
259 #if defined(OS_ANDROID)
260 *product_name
= "Chrome_Android";
261 #elif defined(OS_CHROMEOS)
262 *product_name
= "Chrome_ChromeOS";
264 #if !defined(ADDRESS_SANITIZER)
265 *product_name
= "Chrome_Linux";
267 *product_name
= "Chrome_Linux_ASan";
271 *version
= PRODUCT_VERSION
;
274 base::FilePath
ChromeCrashReporterClient::GetReporterLogFilename() {
275 return base::FilePath(CrashUploadList::kReporterLogFilename
);
279 bool ChromeCrashReporterClient::GetCrashDumpLocation(
280 base::FilePath
* crash_dir
) {
281 // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
282 // location to write breakpad crash dumps can be set.
283 scoped_ptr
<base::Environment
> env(base::Environment::Create());
284 std::string alternate_crash_dump_location
;
285 if (env
->GetVar("BREAKPAD_DUMP_LOCATION", &alternate_crash_dump_location
)) {
286 base::FilePath crash_dumps_dir_path
=
287 base::FilePath::FromUTF8Unsafe(alternate_crash_dump_location
);
288 PathService::Override(chrome::DIR_CRASH_DUMPS
, crash_dumps_dir_path
);
291 return PathService::Get(chrome::DIR_CRASH_DUMPS
, crash_dir
);
294 size_t ChromeCrashReporterClient::RegisterCrashKeys() {
295 // Note: On Windows this only affects the EXE. A separate invocation from
296 // child_process_logging_win.cc registers crash keys for Chrome.dll.
297 #if defined(OS_WIN) && defined(COMPONENT_BUILD)
298 // On Windows, this is not called in a component build, as in that case a
299 // single copy of 'base' is shared by the EXE and the various DLLs, and that
300 // copy is configured by child_process_logging_win.cc.
304 return crash_keys::RegisterChromeCrashKeys();
308 bool ChromeCrashReporterClient::IsRunningUnattended() {
309 scoped_ptr
<base::Environment
> env(base::Environment::Create());
310 return env
->HasVar(env_vars::kHeadless
);
313 bool ChromeCrashReporterClient::GetCollectStatsConsent() {
314 #if defined(GOOGLE_CHROME_BUILD)
315 bool is_official_chrome_build
= true;
317 bool is_official_chrome_build
= false;
320 #if defined(OS_CHROMEOS)
321 bool is_guest_session
= base::CommandLine::ForCurrentProcess()->HasSwitch(
322 chromeos::switches::kGuestSession
);
323 bool is_stable_channel
=
324 chrome::GetChannel() == version_info::Channel::STABLE
;
326 if (is_guest_session
&& is_stable_channel
)
328 #endif // defined(OS_CHROMEOS)
330 #if defined(OS_ANDROID)
331 // TODO(jcivelli): we should not initialize the crash-reporter when it was not
332 // enabled. Right now if it is disabled we still generate the minidumps but we
333 // do not upload them.
334 return is_official_chrome_build
;
335 #else // !defined(OS_ANDROID)
336 return is_official_chrome_build
&&
337 GoogleUpdateSettings::GetCollectStatsConsent();
338 #endif // defined(OS_ANDROID)
341 #if defined(OS_ANDROID)
342 int ChromeCrashReporterClient::GetAndroidMinidumpDescriptor() {
343 return kAndroidMinidumpDescriptor
;
347 bool ChromeCrashReporterClient::EnableBreakpadForProcess(
348 const std::string
& process_type
) {
349 return process_type
== switches::kRendererProcess
||
350 process_type
== switches::kPluginProcess
||
351 process_type
== switches::kPpapiPluginProcess
||
352 process_type
== switches::kZygoteProcess
||
353 process_type
== switches::kGpuProcess
;