Home | History | Annotate | Download | only in app
      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