diff options
-rw-r--r-- | chrome/app/breakpad.cc | 37 | ||||
-rw-r--r-- | chrome/app/chrome_exe.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/browser_main.cc | 12 | ||||
-rw-r--r-- | chrome/browser/metrics_log.cc | 12 | ||||
-rw-r--r-- | chrome/browser/metrics_service.cc | 74 | ||||
-rw-r--r-- | chrome/browser/metrics_service.h | 11 | ||||
-rw-r--r-- | chrome/common/env_vars.cc | 12 | ||||
-rw-r--r-- | chrome/common/env_vars.h | 1 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 16 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 5 |
10 files changed, 131 insertions, 57 deletions
diff --git a/chrome/app/breakpad.cc b/chrome/app/breakpad.cc index dd0aebf..bd66618 100644 --- a/chrome/app/breakpad.cc +++ b/chrome/app/breakpad.cc @@ -42,6 +42,7 @@ #include "base/win_util.h" #include "chrome/app/google_update_client.h" #include "chrome/app/google_update_settings.h" +#include "chrome/common/env_vars.h" #include "breakpad/src/client/windows/handler/exception_handler.h" namespace { @@ -100,15 +101,6 @@ struct CrashReporterInfo { std::wstring process_type; }; -// Environment variable name that has the actual dialog strings. -const wchar_t kEnvRestartInfo[] = L"CHROME_RESTART"; -// If this environment variable is present, chrome has crashed. -const wchar_t kEnvShowRestart[] = L"CHROME_CRASHED"; -// The following two names correspond to the text directionality for the -// current locale. -const wchar_t kRtlLocaleDirection[] = L"RIGHT_TO_LEFT"; -const wchar_t kLtrLocaleDirection[] = L"LEFT_TO_RIGHT"; - // This callback is executed when the browser process has crashed, after // the crash dump has been created. We need to minimize the amount of work // done here since we have potentially corrupted process. Our job is to @@ -120,9 +112,9 @@ bool DumpDoneCallback(const wchar_t*, const wchar_t*, void*, MDRawAssertionInfo*, bool) { // We set CHROME_CRASHED env var. If the CHROME_RESTART is present. // This signals the child process to show the 'chrome has crashed' dialog. - if (!::GetEnvironmentVariableW(kEnvRestartInfo, NULL, 0)) + if (!::GetEnvironmentVariableW(env_vars::kRestartInfo, NULL, 0)) return true; - ::SetEnvironmentVariableW(kEnvShowRestart, L"1"); + ::SetEnvironmentVariableW(env_vars::kShowRestart, L"1"); // Now we just start chrome browser with the same command line. STARTUPINFOW si = {sizeof(si)}; PROCESS_INFORMATION pi; @@ -157,13 +149,13 @@ long WINAPI ChromeExceptionFilter(EXCEPTION_POINTERS* info) { // spawned and basically just shows the 'chrome has crashed' dialog if // the CHROME_CRASHED environment variable is present. bool ShowRestartDialogIfCrashed(bool* exit_now) { - if (!::GetEnvironmentVariableW(kEnvShowRestart, NULL, 0)) + if (!::GetEnvironmentVariableW(env_vars::kShowRestart, NULL, 0)) return false; - DWORD len = ::GetEnvironmentVariableW(kEnvRestartInfo, NULL, 0); + DWORD len = ::GetEnvironmentVariableW(env_vars::kRestartInfo, NULL, 0); if (!len) return false; wchar_t* restart_data = new wchar_t[len + 1]; - ::GetEnvironmentVariableW(kEnvRestartInfo, restart_data, len); + ::GetEnvironmentVariableW(env_vars::kRestartInfo, restart_data, len); restart_data[len] = 0; // The CHROME_RESTART var contains the dialog strings separated by '|'. // See PrepareRestartOnCrashEnviroment() function for details. @@ -176,7 +168,7 @@ bool ShowRestartDialogIfCrashed(bool* exit_now) { // If the UI layout is right-to-left, we need to pass the appropriate MB_XXX // flags so that an RTL message box is displayed. UINT flags = MB_OKCANCEL | MB_ICONWARNING; - if (dlg_strings[2] == kRtlLocaleDirection) + if (dlg_strings[2] == env_vars::kRtlLocale) flags |= MB_RIGHT | MB_RTLREADING; // Show the dialog now. It is ok if another chrome is started by the @@ -237,13 +229,18 @@ unsigned __stdcall InitCrashReporterThread(void* param) { NULL, google_breakpad::ExceptionHandler::HANDLER_ALL, dump_type, pipe_name.c_str(), info->custom_info); - // Tells breakpad to handle breakpoint and single step exceptions. - // This might break JIT debuggers, but at least it will always - // generate a crashdump for these exceptions. - g_breakpad->set_handle_debug_exceptions(true); + if (!g_breakpad->IsOutOfProcess()) { + // The out-of-process handler is unavailable. + ::SetEnvironmentVariable(env_vars::kNoOOBreakpad, + info->process_type.c_str()); + } else { + // Tells breakpad to handle breakpoint and single step exceptions. + // This might break JIT debuggers, but at least it will always + // generate a crashdump for these exceptions. + g_breakpad->set_handle_debug_exceptions(true); + } delete info; - return 0; } diff --git a/chrome/app/chrome_exe.vcproj b/chrome/app/chrome_exe.vcproj index 61110a0..321814d 100644 --- a/chrome/app/chrome_exe.vcproj +++ b/chrome/app/chrome_exe.vcproj @@ -197,6 +197,14 @@ > </File> <File + RelativePath="..\common\env_vars.cc" + > + </File> + <File + RelativePath="..\common\env_vars.h" + > + </File> + <File RelativePath=".\google_update_client.cc" > </File> diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 45308d9..c3531a2 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -61,6 +61,7 @@ #include "chrome/browser/shell_integration.h" #include "chrome/browser/url_fixer_upper.h" #include "chrome/browser/user_data_dir_dialog.h" +#include "chrome/browser/user_metrics.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -247,6 +248,15 @@ bool CreateUniqueChromeEvent() { return already_running; } +// We record in UMA the conditions that can prevent breakpad from generating +// and sending crash reports. Namely that the crash reporting registration +// failed and that the process is being debugged. +void RecordBreakpadStatusUMA(MetricsService* metrics) { + DWORD len = ::GetEnvironmentVariableW(env_vars::kNoOOBreakpad, NULL, 0); + metrics->RecordBreakpadRegistration((len == 0)); + metrics->RecordBreakpadHasDebugger(TRUE == ::IsDebuggerPresent()); +} + } // namespace // Main routine for running as the Browser process. @@ -488,6 +498,8 @@ int BrowserMain(CommandLine &parsed_command_line, int show_command, HandleErrorTestParameters(parsed_command_line); + RecordBreakpadStatusUMA(metrics); + int result_code = ResultCodes::NORMAL_EXIT; if (BrowserInit::ProcessCommandLine(parsed_command_line, L"", local_state, show_command, true, profile, diff --git a/chrome/browser/metrics_log.cc b/chrome/browser/metrics_log.cc index a563ed5..eb0b5be 100644 --- a/chrome/browser/metrics_log.cc +++ b/chrome/browser/metrics_log.cc @@ -362,6 +362,18 @@ void MetricsLog::WriteStabilityElement() { WriteIntAttribute("rendererhangcount", pref->GetInteger(prefs::kStabilityRendererHangCount)); pref->SetInteger(prefs::kStabilityRendererHangCount, 0); + WriteIntAttribute("breakpadregistrationok", + pref->GetInteger(prefs::kStabilityBreakpadRegistrationSuccess)); + pref->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0); + WriteIntAttribute("breakpadregistrationfail", + pref->GetInteger(prefs::kStabilityBreakpadRegistrationFail)); + pref->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0); + WriteIntAttribute("debuggerpresent", + pref->GetInteger(prefs::kStabilityDebuggerPresent)); + pref->SetInteger(prefs::kStabilityDebuggerPresent, 0); + WriteIntAttribute("debuggernotpresent", + pref->GetInteger(prefs::kStabilityDebuggerNotPresent)); + pref->SetInteger(prefs::kStabilityDebuggerNotPresent, 0); // Uptime is stored as a string, since there's no int64 in Value/JSON. WriteAttribute("uptimesec", diff --git a/chrome/browser/metrics_service.cc b/chrome/browser/metrics_service.cc index 268e57d..85690a8 100644 --- a/chrome/browser/metrics_service.cc +++ b/chrome/browser/metrics_service.cc @@ -327,6 +327,13 @@ void MetricsService::RegisterPrefs(PrefService* local_state) { local_state->RegisterIntegerPref(prefs::kSecurityRendererOnDefaultDesktop, 0); local_state->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0); local_state->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0); + local_state->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationFail, + 0); + local_state->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationSuccess, + 0); + local_state->RegisterIntegerPref(prefs::kStabilityDebuggerPresent, 0); + local_state->RegisterIntegerPref(prefs::kStabilityDebuggerNotPresent, 0); + local_state->RegisterDictionaryPref(prefs::kProfileMetrics); local_state->RegisterIntegerPref(prefs::kNumBookmarksOnBookmarkBar, 0); local_state->RegisterIntegerPref(prefs::kNumFoldersOnBookmarkBar, 0); @@ -486,6 +493,20 @@ void MetricsService::RecordCompletedSessionEnd() { RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true); } +void MetricsService:: RecordBreakpadRegistration(bool success) { + if (!success) + IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail); + else + IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess); +} + +void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { + if (!has_debugger) + IncrementPrefValue(prefs::kStabilityDebuggerNotPresent); + else + IncrementPrefValue(prefs::kStabilityDebuggerPresent); +} + //------------------------------------------------------------------------------ // private methods //------------------------------------------------------------------------------ @@ -517,23 +538,17 @@ void MetricsService::InitializeMetricsState() { DCHECK(done); // Stability bookkeeping - int launches = pref->GetInteger(prefs::kStabilityLaunchCount); - pref->SetInteger(prefs::kStabilityLaunchCount, launches + 1); + IncrementPrefValue(prefs::kStabilityLaunchCount); - bool exited_cleanly = pref->GetBoolean(prefs::kStabilityExitedCleanly); - if (!exited_cleanly) { - int crashes = pref->GetInteger(prefs::kStabilityCrashCount); - pref->SetInteger(prefs::kStabilityCrashCount, crashes + 1); + if (!pref->GetBoolean(prefs::kStabilityExitedCleanly)) { + IncrementPrefValue(prefs::kStabilityCrashCount); } + + // This will be set to 'true' if we exit cleanly. pref->SetBoolean(prefs::kStabilityExitedCleanly, false); - bool shutdown_cleanly = - pref->GetBoolean(prefs::kStabilitySessionEndCompleted); - if (!shutdown_cleanly) { - int incomplete_session_end_count = pref->GetInteger( - prefs::kStabilityIncompleteSessionEndCount); - pref->SetInteger(prefs::kStabilityIncompleteSessionEndCount, - incomplete_session_end_count + 1); + if (!pref->GetBoolean(prefs::kStabilitySessionEndCompleted)) { + IncrementPrefValue(prefs::kStabilityIncompleteSessionEndCount); } // This is marked false when we get a WM_ENDSESSION. pref->SetBoolean(prefs::kStabilitySessionEndCompleted, true); @@ -1219,11 +1234,15 @@ void MetricsService::LogLoadComplete(NotificationType type, load_details->load_time()); } +void MetricsService::IncrementPrefValue(const wchar_t* path) { + PrefService* pref = g_browser_process->local_state(); + DCHECK(pref); + int value = pref->GetInteger(path); + pref->SetInteger(path, value + 1); +} + void MetricsService::LogLoadStarted() { - PrefService* prefs = g_browser_process->local_state(); - DCHECK(prefs); - int loads = prefs->GetInteger(prefs::kStabilityPageLoadCount); - prefs->SetInteger(prefs::kStabilityPageLoadCount, loads + 1); + IncrementPrefValue(prefs::kStabilityPageLoadCount); // We need to save the prefs, as page load count is a critical stat, and // it might be lost due to a crash :-(. } @@ -1231,27 +1250,18 @@ void MetricsService::LogLoadStarted() { void MetricsService::LogRendererInSandbox(bool on_sandbox_desktop) { PrefService* prefs = g_browser_process->local_state(); DCHECK(prefs); - if (on_sandbox_desktop) { - int count = prefs->GetInteger(prefs::kSecurityRendererOnSboxDesktop); - prefs->SetInteger(prefs::kSecurityRendererOnSboxDesktop, count + 1); - } else { - int count = prefs->GetInteger(prefs::kSecurityRendererOnDefaultDesktop); - prefs->SetInteger(prefs::kSecurityRendererOnDefaultDesktop, count + 1); - } + if (on_sandbox_desktop) + IncrementPrefValue(prefs::kSecurityRendererOnSboxDesktop); + else + IncrementPrefValue(prefs::kSecurityRendererOnDefaultDesktop); } void MetricsService::LogRendererCrash() { - PrefService* prefs = g_browser_process->local_state(); - DCHECK(prefs); - int crashes = prefs->GetInteger(prefs::kStabilityRendererCrashCount); - prefs->SetInteger(prefs::kStabilityRendererCrashCount, crashes + 1); + IncrementPrefValue(prefs::kStabilityRendererCrashCount); } void MetricsService::LogRendererHang() { - PrefService* prefs = g_browser_process->local_state(); - DCHECK(prefs); - int hangs = prefs->GetInteger(prefs::kStabilityRendererHangCount); - prefs->SetInteger(prefs::kStabilityRendererHangCount, hangs + 1); + IncrementPrefValue(prefs::kStabilityRendererHangCount); } void MetricsService::LogPluginChange(NotificationType type, diff --git a/chrome/browser/metrics_service.h b/chrome/browser/metrics_service.h index dc65d45..4524bc6 100644 --- a/chrome/browser/metrics_service.h +++ b/chrome/browser/metrics_service.h @@ -116,6 +116,14 @@ class MetricsService : public NotificationObserver, // that session end was successful. void RecordCompletedSessionEnd(); + // Saves in the preferences if the crash report registration was successful. + // This count is eventually send via UMA logs. + void RecordBreakpadRegistration(bool success); + + // Saves in the preferences if the browser is running under a debugger. + // This count is eventually send via UMA logs. + void RecordBreakpadHasDebugger(bool has_debugger); + // Callback to let us knew that the plugin list is warmed up. void OnGetPluginListTaskComplete(); @@ -226,6 +234,9 @@ class MetricsService : public NotificationObserver, const NotificationSource& source, const NotificationDetails& details); + // Reads, increments and then sets the specified integer preference. + void IncrementPrefValue(const wchar_t* path); + // Records a renderer process crash. void LogRendererCrash(); diff --git a/chrome/common/env_vars.cc b/chrome/common/env_vars.cc index 17ac68f..971669f 100644 --- a/chrome/common/env_vars.cc +++ b/chrome/common/env_vars.cc @@ -42,15 +42,17 @@ const wchar_t kLogFileName[] = L"CHROME_LOG_FILE"; // CHROME_CRASHED exists if a previous instance of chrome has crashed. This // triggers the 'restart chrome' dialog. CHROME_RESTART contains the strings // that are needed to show the dialog. -// +const wchar_t kShowRestart[] = L"CHROME_CRASHED"; +const wchar_t kRestartInfo[] = L"CHROME_RESTART"; + // The strings RIGHT_TO_LEFT and LEFT_TO_RIGHT indicate the locale direction. // For example, for Hebrew and Arabic locales, we use RIGHT_TO_LEFT so that the // dialog is displayed using the right orientation. -// -// If you modify these constants, you also need to modify them in breakpad.cc. -const wchar_t kShowRestart[] = L"CHROME_CRASHED"; -const wchar_t kRestartInfo[] = L"CHROME_RESTART"; const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT"; const wchar_t kLtrLocale[] = L"LEFT_TO_RIGHT"; +// If the out-of-process breakpad could not be installed, we set this variable +// according to the process. +const wchar_t kNoOOBreakpad[] = L"NO_OO_BREAKPAD"; + } // namespace env_vars diff --git a/chrome/common/env_vars.h b/chrome/common/env_vars.h index 51b18ad..5ba9743 100644 --- a/chrome/common/env_vars.h +++ b/chrome/common/env_vars.h @@ -40,6 +40,7 @@ extern const wchar_t kShowRestart[]; extern const wchar_t kRestartInfo[]; extern const wchar_t kRtlLocale[]; extern const wchar_t kLtrLocale[]; +extern const wchar_t kNoOOBreakpad[]; } // namespace env_vars diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index ea7ec00..123cdee 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -325,6 +325,22 @@ const wchar_t kStabilityPluginStats[] = const wchar_t kStabilityRendererHangCount[] = L"user_experience_metrics.stability.renderer_hang_count"; +// Number of times the browser has been able to register crash reporting. +const wchar_t kStabilityBreakpadRegistrationSuccess[] = + L"user_experience_metrics.stability.breakpad_registration_ok"; + +// Number of times the browser has failed to register crash reporting. +const wchar_t kStabilityBreakpadRegistrationFail[] = + L"user_experience_metrics.stability.breakpad_registration_fail"; + +// Number of times the browser has been run under a debugger. +const wchar_t kStabilityDebuggerPresent[] = + L"user_experience_metrics.stability.debugger_present"; + +// Number of times the browser has not been run under a debugger. +const wchar_t kStabilityDebuggerNotPresent[] = + L"user_experience_metrics.stability.debugger_not_present"; + // The keys below are used for the dictionaries in the // kStabilityPluginStats list. const wchar_t kStabilityPluginPath[] = L"path"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 610f2ed..ceb3a9b 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -115,6 +115,11 @@ extern const wchar_t kStabilityLastTimestampSec[]; extern const wchar_t kStabilityUptimeSec[]; extern const wchar_t kStabilityRendererHangCount[]; +extern const wchar_t kStabilityBreakpadRegistrationSuccess[]; +extern const wchar_t kStabilityBreakpadRegistrationFail[]; +extern const wchar_t kStabilityDebuggerPresent[]; +extern const wchar_t kStabilityDebuggerNotPresent[]; + extern const wchar_t kSecurityRendererOnSboxDesktop[]; extern const wchar_t kSecurityRendererOnDefaultDesktop[]; |