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. 4 5 #include "chrome/app/chrome_breakpad_client.h" 6 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/memory/scoped_ptr.h" 12 #include "base/path_service.h" 13 #include "base/strings/string_split.h" 14 #include "base/strings/utf_string_conversions.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 21 #if defined(OS_WIN) 22 #include <windows.h> 23 24 #include "base/file_version_info.h" 25 #include "chrome/installer/util/google_chrome_sxs_distribution.h" 26 #include "chrome/installer/util/install_util.h" 27 #endif 28 29 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) 30 #include "chrome/browser/crash_upload_list.h" 31 #include "chrome/common/chrome_version_info_posix.h" 32 #endif 33 34 #if defined(OS_POSIX) 35 #include "chrome/common/dump_without_crashing.h" 36 #endif 37 38 #if defined(OS_WIN) || defined(OS_MACOSX) 39 #include "chrome/installer/util/google_update_settings.h" 40 #endif 41 42 #if defined(OS_ANDROID) 43 #include "chrome/common/descriptors_android.h" 44 #endif 45 46 namespace chrome { 47 48 namespace { 49 50 #if defined(OS_WIN) 51 // This is the minimum version of google update that is required for deferred 52 // crash uploads to work. 53 const char kMinUpdateVersion[] = "1.3.21.115"; 54 #endif 55 56 } // namespace 57 58 ChromeBreakpadClient::ChromeBreakpadClient() {} 59 60 ChromeBreakpadClient::~ChromeBreakpadClient() {} 61 62 #if defined(OS_WIN) 63 bool ChromeBreakpadClient::GetAlternativeCrashDumpLocation( 64 base::FilePath* crash_dir) { 65 // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate 66 // location to write breakpad crash dumps can be set. 67 scoped_ptr<base::Environment> env(base::Environment::Create()); 68 std::string alternate_crash_dump_location; 69 if (env->GetVar("BREAKPAD_DUMP_LOCATION", &alternate_crash_dump_location)) { 70 *crash_dir = base::FilePath::FromUTF8Unsafe(alternate_crash_dump_location); 71 return true; 72 } 73 74 return false; 75 } 76 77 void ChromeBreakpadClient::GetProductNameAndVersion( 78 const base::FilePath& exe_path, 79 base::string16* product_name, 80 base::string16* version, 81 base::string16* special_build, 82 base::string16* channel_name) { 83 DCHECK(product_name); 84 DCHECK(version); 85 DCHECK(special_build); 86 DCHECK(channel_name); 87 88 scoped_ptr<FileVersionInfo> version_info( 89 FileVersionInfo::CreateFileVersionInfo(exe_path)); 90 91 if (version_info.get()) { 92 // Get the information from the file. 93 *version = version_info->product_version(); 94 if (!version_info->is_official_build()) 95 version->append(base::ASCIIToUTF16("-devel")); 96 97 const CommandLine& command = *CommandLine::ForCurrentProcess(); 98 if (command.HasSwitch(switches::kChromeFrame)) { 99 *product_name = base::ASCIIToUTF16("ChromeFrame"); 100 } else { 101 *product_name = version_info->product_short_name(); 102 } 103 104 *special_build = version_info->special_build(); 105 } else { 106 // No version info found. Make up the values. 107 *product_name = base::ASCIIToUTF16("Chrome"); 108 *version = base::ASCIIToUTF16("0.0.0.0-devel"); 109 } 110 111 std::wstring channel_string; 112 GoogleUpdateSettings::GetChromeChannelAndModifiers( 113 !GetIsPerUserInstall(exe_path), &channel_string); 114 *channel_name = base::WideToUTF16(channel_string); 115 } 116 117 bool ChromeBreakpadClient::ShouldShowRestartDialog(base::string16* title, 118 base::string16* message, 119 bool* is_rtl_locale) { 120 scoped_ptr<base::Environment> env(base::Environment::Create()); 121 if (!env->HasVar(env_vars::kShowRestart) || 122 !env->HasVar(env_vars::kRestartInfo)) { 123 return false; 124 } 125 126 std::string restart_info; 127 env->GetVar(env_vars::kRestartInfo, &restart_info); 128 129 // The CHROME_RESTART var contains the dialog strings separated by '|'. 130 // See ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment() 131 // for details. 132 std::vector<std::string> dlg_strings; 133 base::SplitString(restart_info, '|', &dlg_strings); 134 135 if (dlg_strings.size() < 3) 136 return false; 137 138 *title = base::ASCIIToUTF16(dlg_strings[0]); 139 *message = base::ASCIIToUTF16(dlg_strings[1]); 140 *is_rtl_locale = dlg_strings[2] == env_vars::kRtlLocale; 141 return true; 142 } 143 144 bool ChromeBreakpadClient::AboutToRestart() { 145 scoped_ptr<base::Environment> env(base::Environment::Create()); 146 if (!env->HasVar(env_vars::kRestartInfo)) 147 return false; 148 149 env->SetVar(env_vars::kShowRestart, "1"); 150 return true; 151 } 152 153 base::string16 ChromeBreakpadClient::GetCrashGUID() { 154 std::wstring guid; 155 GoogleUpdateSettings::GetMetricsId(&guid); 156 return base::WideToUTF16(guid); 157 } 158 159 bool ChromeBreakpadClient::GetDeferredUploadsSupported( 160 bool is_per_user_install) { 161 Version update_version = GoogleUpdateSettings::GetGoogleUpdateVersion( 162 !is_per_user_install); 163 if (!update_version.IsValid() || 164 update_version.IsOlderThan(std::string(kMinUpdateVersion))) 165 return false; 166 167 return true; 168 } 169 170 bool ChromeBreakpadClient::GetIsPerUserInstall(const base::FilePath& exe_path) { 171 return InstallUtil::IsPerUserInstall(exe_path.value().c_str()); 172 } 173 174 bool ChromeBreakpadClient::GetShouldDumpLargerDumps(bool is_per_user_install) { 175 base::string16 channel_name(base::WideToUTF16( 176 GoogleUpdateSettings::GetChromeChannel(!is_per_user_install))); 177 178 // Capture more detail in crash dumps for beta and dev channel builds. 179 if (channel_name == base::ASCIIToUTF16("dev") || 180 channel_name == base::ASCIIToUTF16("beta") || 181 channel_name == GoogleChromeSxSDistribution::ChannelName()) 182 return true; 183 return false; 184 } 185 186 int ChromeBreakpadClient::GetResultCodeRespawnFailed() { 187 return chrome::RESULT_CODE_RESPAWN_FAILED; 188 } 189 #endif 190 191 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) 192 void ChromeBreakpadClient::GetProductNameAndVersion(std::string* product_name, 193 std::string* version) { 194 DCHECK(product_name); 195 DCHECK(version); 196 #if defined(OS_ANDROID) 197 *product_name = "Chrome_Android"; 198 #elif defined(OS_CHROMEOS) 199 *product_name = "Chrome_ChromeOS"; 200 #else // OS_LINUX 201 #if !defined(ADDRESS_SANITIZER) 202 *product_name = "Chrome_Linux"; 203 #else 204 *product_name = "Chrome_Linux_ASan"; 205 #endif 206 #endif 207 208 *version = PRODUCT_VERSION; 209 } 210 211 base::FilePath ChromeBreakpadClient::GetReporterLogFilename() { 212 return base::FilePath(CrashUploadList::kReporterLogFilename); 213 } 214 #endif 215 216 bool ChromeBreakpadClient::GetCrashDumpLocation(base::FilePath* crash_dir) { 217 // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate 218 // location to write breakpad crash dumps can be set. 219 scoped_ptr<base::Environment> env(base::Environment::Create()); 220 std::string alternate_crash_dump_location; 221 if (env->GetVar("BREAKPAD_DUMP_LOCATION", &alternate_crash_dump_location)) { 222 base::FilePath crash_dumps_dir_path = 223 base::FilePath::FromUTF8Unsafe(alternate_crash_dump_location); 224 PathService::Override(chrome::DIR_CRASH_DUMPS, crash_dumps_dir_path); 225 } 226 227 return PathService::Get(chrome::DIR_CRASH_DUMPS, crash_dir); 228 } 229 230 #if defined(OS_POSIX) 231 void ChromeBreakpadClient::SetDumpWithoutCrashingFunction(void (*function)()) { 232 logging::SetDumpWithoutCrashingFunction(function); 233 } 234 #endif 235 236 size_t ChromeBreakpadClient::RegisterCrashKeys() { 237 return crash_keys::RegisterChromeCrashKeys(); 238 } 239 240 bool ChromeBreakpadClient::IsRunningUnattended() { 241 scoped_ptr<base::Environment> env(base::Environment::Create()); 242 return env->HasVar(env_vars::kHeadless); 243 } 244 245 #if defined(OS_WIN) || defined(OS_MACOSX) 246 bool ChromeBreakpadClient::GetCollectStatsConsent() { 247 return GoogleUpdateSettings::GetCollectStatsConsent(); 248 } 249 #endif 250 251 #if defined(OS_ANDROID) 252 int ChromeBreakpadClient::GetAndroidMinidumpDescriptor() { 253 return kAndroidMinidumpDescriptor; 254 } 255 #endif 256 257 } // namespace chrome 258