NaCl docs: add sanitizers to GSoC ideas
[chromium-blink-merge.git] / chrome / browser / metrics / chrome_stability_metrics_provider.cc
blobfcdc5d715840a1e8bb5a5774d99308ca97e48300
1 // Copyright 2014 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/browser/metrics/chrome_stability_metrics_provider.h"
7 #include <vector>
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/sparse_histogram.h"
12 #include "base/prefs/pref_registry_simple.h"
13 #include "base/prefs/pref_service.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/common/pref_names.h"
17 #include "components/metrics/proto/system_profile.pb.h"
18 #include "content/public/browser/child_process_data.h"
19 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/user_metrics.h"
22 #include "content/public/browser/web_contents.h"
24 #if defined(ENABLE_EXTENSIONS)
25 #include "extensions/browser/process_map.h"
26 #endif
28 #if defined(ENABLE_PLUGINS)
29 #include "chrome/browser/metrics/plugin_metrics_provider.h"
30 #endif
32 #if defined(OS_WIN)
33 #include <windows.h> // Needed for STATUS_* codes
34 #endif
36 namespace {
38 void IncrementPrefValue(const char* path) {
39 PrefService* pref = g_browser_process->local_state();
40 DCHECK(pref);
41 int value = pref->GetInteger(path);
42 pref->SetInteger(path, value + 1);
45 void IncrementLongPrefsValue(const char* path) {
46 PrefService* pref = g_browser_process->local_state();
47 DCHECK(pref);
48 int64 value = pref->GetInt64(path);
49 pref->SetInt64(path, value + 1);
52 // Converts an exit code into something that can be inserted into our
53 // histograms (which expect non-negative numbers less than MAX_INT).
54 int MapCrashExitCodeForHistogram(int exit_code) {
55 #if defined(OS_WIN)
56 // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in
57 // histograms.cc. Solve this by remapping it to a smaller value, which
58 // hopefully doesn't conflict with other codes.
59 if (exit_code == STATUS_GUARD_PAGE_VIOLATION)
60 return 0x1FCF7EC3; // Randomly picked number.
61 #endif
63 return std::abs(exit_code);
66 } // namespace
68 ChromeStabilityMetricsProvider::ChromeStabilityMetricsProvider() {
69 BrowserChildProcessObserver::Add(this);
72 ChromeStabilityMetricsProvider::~ChromeStabilityMetricsProvider() {
73 BrowserChildProcessObserver::Remove(this);
76 void ChromeStabilityMetricsProvider::OnRecordingEnabled() {
77 registrar_.Add(this,
78 content::NOTIFICATION_LOAD_START,
79 content::NotificationService::AllSources());
80 registrar_.Add(this,
81 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
82 content::NotificationService::AllSources());
83 registrar_.Add(this,
84 content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
85 content::NotificationService::AllSources());
88 void ChromeStabilityMetricsProvider::OnRecordingDisabled() {
89 registrar_.RemoveAll();
92 void ChromeStabilityMetricsProvider::ProvideStabilityMetrics(
93 metrics::SystemProfileProto* system_profile_proto) {
94 PrefService* pref = g_browser_process->local_state();
95 metrics::SystemProfileProto_Stability* stability_proto =
96 system_profile_proto->mutable_stability();
98 int count = pref->GetInteger(prefs::kStabilityPageLoadCount);
99 if (count) {
100 stability_proto->set_page_load_count(count);
101 pref->SetInteger(prefs::kStabilityPageLoadCount, 0);
104 count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
105 if (count) {
106 stability_proto->set_child_process_crash_count(count);
107 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
110 count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
111 if (count) {
112 stability_proto->set_renderer_crash_count(count);
113 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
116 count = pref->GetInteger(prefs::kStabilityExtensionRendererCrashCount);
117 if (count) {
118 stability_proto->set_extension_renderer_crash_count(count);
119 pref->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
122 count = pref->GetInteger(prefs::kStabilityRendererHangCount);
123 if (count) {
124 stability_proto->set_renderer_hang_count(count);
125 pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
129 void ChromeStabilityMetricsProvider::ClearSavedStabilityMetrics() {
130 PrefService* local_state = g_browser_process->local_state();
132 // Clear all the prefs used in this class in UMA reports (which doesn't
133 // include |kUninstallMetricsPageLoadCount| as it's not sent up by UMA).
134 local_state->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
135 local_state->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
136 local_state->SetInteger(prefs::kStabilityPageLoadCount, 0);
137 local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0);
138 local_state->SetInteger(prefs::kStabilityRendererHangCount, 0);
141 // static
142 void ChromeStabilityMetricsProvider::RegisterPrefs(
143 PrefRegistrySimple* registry) {
144 registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0);
145 registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount,
147 registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
148 registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
149 registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0);
151 registry->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0);
154 void ChromeStabilityMetricsProvider::Observe(
155 int type,
156 const content::NotificationSource& source,
157 const content::NotificationDetails& details) {
158 switch (type) {
159 case content::NOTIFICATION_LOAD_START: {
160 content::NavigationController* controller =
161 content::Source<content::NavigationController>(source).ptr();
162 content::WebContents* web_contents = controller->GetWebContents();
163 LogLoadStarted(web_contents);
164 break;
167 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
168 content::RenderProcessHost::RendererClosedDetails* process_details =
169 content::Details<content::RenderProcessHost::RendererClosedDetails>(
170 details).ptr();
171 content::RenderProcessHost* host =
172 content::Source<content::RenderProcessHost>(source).ptr();
173 LogRendererCrash(
174 host, process_details->status, process_details->exit_code);
175 break;
178 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
179 LogRendererHang();
180 break;
182 default:
183 NOTREACHED();
184 break;
188 void ChromeStabilityMetricsProvider::BrowserChildProcessCrashed(
189 const content::ChildProcessData& data) {
190 #if defined(ENABLE_PLUGINS)
191 // Exclude plugin crashes from the count below because we report them via
192 // a separate UMA metric.
193 if (PluginMetricsProvider::IsPluginProcess(data.process_type))
194 return;
195 #endif
197 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
200 void ChromeStabilityMetricsProvider::LogLoadStarted(
201 content::WebContents* web_contents) {
202 content::RecordAction(base::UserMetricsAction("PageLoad"));
203 // TODO(asvitkine): Check if this is used for anything and if not, remove.
204 LOCAL_HISTOGRAM_BOOLEAN("Chrome.UmaPageloadCounter", true);
205 IncrementPrefValue(prefs::kStabilityPageLoadCount);
206 IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
207 // We need to save the prefs, as page load count is a critical stat, and it
208 // might be lost due to a crash :-(.
211 void ChromeStabilityMetricsProvider::LogRendererCrash(
212 content::RenderProcessHost* host,
213 base::TerminationStatus status,
214 int exit_code) {
215 bool was_extension_process = false;
216 #if defined(ENABLE_EXTENSIONS)
217 was_extension_process =
218 extensions::ProcessMap::Get(host->GetBrowserContext())->Contains(
219 host->GetID());
220 #endif
221 if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
222 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
223 if (was_extension_process) {
224 IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount);
226 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Extension",
227 MapCrashExitCodeForHistogram(exit_code));
228 } else {
229 IncrementPrefValue(prefs::kStabilityRendererCrashCount);
231 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
232 MapCrashExitCodeForHistogram(exit_code));
235 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
236 was_extension_process ? 2 : 1);
237 } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
238 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
239 was_extension_process ? 2 : 1);
240 } else if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
241 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.DisconnectedAlive",
242 was_extension_process ? 2 : 1);
246 void ChromeStabilityMetricsProvider::LogRendererHang() {
247 IncrementPrefValue(prefs::kStabilityRendererHangCount);