Fire an error if a pref used in the UI is missing once all prefs are fetched.
[chromium-blink-merge.git] / chrome / browser / metrics / chrome_metrics_service_client.cc
blobf7bdca93b1a7c5bac6c1e0bf58b8c15af2baab7d
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_metrics_service_client.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_registry_simple.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/threading/platform_thread.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/chrome_notification_types.h"
24 #include "chrome/browser/google/google_brand.h"
25 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
26 #include "chrome/browser/metrics/drive_metrics_provider.h"
27 #include "chrome/browser/metrics/omnibox_metrics_provider.h"
28 #include "chrome/browser/ui/browser_otr_state.h"
29 #include "chrome/common/chrome_constants.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/chrome_version_info.h"
32 #include "chrome/common/crash_keys.h"
33 #include "chrome/common/pref_names.h"
34 #include "chrome/common/render_messages.h"
35 #include "components/metrics/call_stack_profile_metrics_provider.h"
36 #include "components/metrics/gpu/gpu_metrics_provider.h"
37 #include "components/metrics/metrics_service.h"
38 #include "components/metrics/net/net_metrics_log_uploader.h"
39 #include "components/metrics/net/network_metrics_provider.h"
40 #include "components/metrics/profiler/profiler_metrics_provider.h"
41 #include "components/metrics/profiler/tracking_synchronizer.h"
42 #include "components/metrics/url_constants.h"
43 #include "content/public/browser/browser_thread.h"
44 #include "content/public/browser/histogram_fetcher.h"
45 #include "content/public/browser/notification_service.h"
46 #include "content/public/browser/render_process_host.h"
48 #if defined(OS_ANDROID)
49 #include "chrome/browser/metrics/android_metrics_provider.h"
50 #endif
52 #if defined(ENABLE_PRINT_PREVIEW)
53 #include "chrome/browser/service_process/service_process_control.h"
54 #endif
56 #if defined(ENABLE_EXTENSIONS)
57 #include "chrome/browser/metrics/extensions_metrics_provider.h"
58 #endif
60 #if defined(ENABLE_PLUGINS)
61 #include "chrome/browser/metrics/plugin_metrics_provider.h"
62 #endif
64 #if defined(OS_CHROMEOS)
65 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
66 #include "chrome/browser/metrics/signin_status_metrics_provider_chromeos.h"
67 #endif
69 #if defined(OS_WIN)
70 #include <windows.h>
71 #include "base/win/registry.h"
72 #include "chrome/browser/metrics/google_update_metrics_provider_win.h"
73 #include "components/browser_watcher/watcher_metrics_provider_win.h"
74 #endif
76 #if !defined(OS_CHROMEOS) && !defined(OS_IOS)
77 #include "chrome/browser/metrics/signin_status_metrics_provider.h"
78 #endif // !defined(OS_CHROMEOS) && !defined(OS_IOS)
80 namespace {
82 // This specifies the amount of time to wait for all renderers to send their
83 // data.
84 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds.
86 metrics::SystemProfileProto::Channel AsProtobufChannel(
87 chrome::VersionInfo::Channel channel) {
88 switch (channel) {
89 case chrome::VersionInfo::CHANNEL_UNKNOWN:
90 return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
91 case chrome::VersionInfo::CHANNEL_CANARY:
92 return metrics::SystemProfileProto::CHANNEL_CANARY;
93 case chrome::VersionInfo::CHANNEL_DEV:
94 return metrics::SystemProfileProto::CHANNEL_DEV;
95 case chrome::VersionInfo::CHANNEL_BETA:
96 return metrics::SystemProfileProto::CHANNEL_BETA;
97 case chrome::VersionInfo::CHANNEL_STABLE:
98 return metrics::SystemProfileProto::CHANNEL_STABLE;
100 NOTREACHED();
101 return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
104 // Standard interval between log uploads, in seconds.
105 #if defined(OS_ANDROID) || defined(OS_IOS)
106 const int kStandardUploadIntervalSeconds = 5 * 60; // Five minutes.
107 const int kStandardUploadIntervalCellularSeconds = 15 * 60; // Fifteen minutes.
108 #else
109 const int kStandardUploadIntervalSeconds = 30 * 60; // Thirty minutes.
110 #endif
112 #if defined(OS_ANDROID) || defined(OS_IOS)
113 // Returns true if the user is assigned to the experiment group for enabled
114 // cellular uploads.
115 bool IsCellularEnabledByExperiment() {
116 const std::string group_name =
117 base::FieldTrialList::FindFullName("UMA_EnableCellularLogUpload");
118 return group_name == "Enabled";
120 #endif
122 } // namespace
124 ChromeMetricsServiceClient::ChromeMetricsServiceClient(
125 metrics::MetricsStateManager* state_manager)
126 : metrics_state_manager_(state_manager),
127 chromeos_metrics_provider_(nullptr),
128 waiting_for_collect_final_metrics_step_(false),
129 num_async_histogram_fetches_in_progress_(0),
130 profiler_metrics_provider_(nullptr),
131 #if defined(ENABLE_PLUGINS)
132 plugin_metrics_provider_(nullptr),
133 #endif
134 #if defined(OS_WIN)
135 google_update_metrics_provider_(nullptr),
136 #endif
137 drive_metrics_provider_(nullptr),
138 weak_ptr_factory_(this) {
139 DCHECK(thread_checker_.CalledOnValidThread());
140 RecordCommandLineMetrics();
141 RegisterForNotifications();
143 #if defined(OS_WIN)
144 CountBrowserCrashDumpAttempts();
145 #endif // defined(OS_WIN)
148 ChromeMetricsServiceClient::~ChromeMetricsServiceClient() {
149 DCHECK(thread_checker_.CalledOnValidThread());
152 // static
153 scoped_ptr<ChromeMetricsServiceClient> ChromeMetricsServiceClient::Create(
154 metrics::MetricsStateManager* state_manager,
155 PrefService* local_state) {
156 // Perform two-phase initialization so that |client->metrics_service_| only
157 // receives pointers to fully constructed objects.
158 scoped_ptr<ChromeMetricsServiceClient> client(
159 new ChromeMetricsServiceClient(state_manager));
160 client->Initialize();
162 return client.Pass();
165 // static
166 void ChromeMetricsServiceClient::RegisterPrefs(PrefRegistrySimple* registry) {
167 registry->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0);
168 registry->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0);
170 metrics::MetricsService::RegisterPrefs(registry);
171 ChromeStabilityMetricsProvider::RegisterPrefs(registry);
173 #if defined(OS_ANDROID)
174 AndroidMetricsProvider::RegisterPrefs(registry);
175 #endif // defined(OS_ANDROID)
177 #if defined(ENABLE_PLUGINS)
178 PluginMetricsProvider::RegisterPrefs(registry);
179 #endif // defined(ENABLE_PLUGINS)
182 void ChromeMetricsServiceClient::SetMetricsClientId(
183 const std::string& client_id) {
184 crash_keys::SetMetricsClientIdFromGUID(client_id);
187 void ChromeMetricsServiceClient::OnRecordingDisabled() {
188 crash_keys::ClearMetricsClientId();
191 bool ChromeMetricsServiceClient::IsOffTheRecordSessionActive() {
192 return chrome::IsOffTheRecordSessionActive();
195 int32 ChromeMetricsServiceClient::GetProduct() {
196 return metrics::ChromeUserMetricsExtension::CHROME;
199 std::string ChromeMetricsServiceClient::GetApplicationLocale() {
200 return g_browser_process->GetApplicationLocale();
203 bool ChromeMetricsServiceClient::GetBrand(std::string* brand_code) {
204 return google_brand::GetBrand(brand_code);
207 metrics::SystemProfileProto::Channel ChromeMetricsServiceClient::GetChannel() {
208 return AsProtobufChannel(chrome::VersionInfo::GetChannel());
211 std::string ChromeMetricsServiceClient::GetVersionString() {
212 chrome::VersionInfo version_info;
213 std::string version = version_info.Version();
214 #if defined(ARCH_CPU_64_BITS)
215 version += "-64";
216 #endif // defined(ARCH_CPU_64_BITS)
217 if (!version_info.IsOfficialBuild())
218 version.append("-devel");
219 return version;
222 void ChromeMetricsServiceClient::OnLogUploadComplete() {
223 // Collect network stats after each UMA upload.
224 network_stats_uploader_.CollectAndReportNetworkStats();
227 void ChromeMetricsServiceClient::StartGatheringMetrics(
228 const base::Closure& done_callback) {
229 finished_gathering_initial_metrics_callback_ = done_callback;
230 base::Closure got_hardware_class_callback =
231 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotHardwareClass,
232 weak_ptr_factory_.GetWeakPtr());
233 #if defined(OS_CHROMEOS)
234 chromeos_metrics_provider_->InitTaskGetHardwareClass(
235 got_hardware_class_callback);
236 #else
237 got_hardware_class_callback.Run();
238 #endif // defined(OS_CHROMEOS)
241 void ChromeMetricsServiceClient::CollectFinalMetrics(
242 const base::Closure& done_callback) {
243 DCHECK(thread_checker_.CalledOnValidThread());
245 collect_final_metrics_done_callback_ = done_callback;
247 // Begin the multi-step process of collecting memory usage histograms:
248 // First spawn a task to collect the memory details; when that task is
249 // finished, it will call OnMemoryDetailCollectionDone. That will in turn
250 // call HistogramSynchronization to collect histograms from all renderers and
251 // then call OnHistogramSynchronizationDone to continue processing.
252 DCHECK(!waiting_for_collect_final_metrics_step_);
253 waiting_for_collect_final_metrics_step_ = true;
255 base::Closure callback =
256 base::Bind(&ChromeMetricsServiceClient::OnMemoryDetailCollectionDone,
257 weak_ptr_factory_.GetWeakPtr());
259 scoped_refptr<MetricsMemoryDetails> details(
260 new MetricsMemoryDetails(callback, &memory_growth_tracker_));
261 details->StartFetch(MemoryDetails::FROM_CHROME_ONLY);
263 // Collect WebCore cache information to put into a histogram.
264 for (content::RenderProcessHost::iterator i(
265 content::RenderProcessHost::AllHostsIterator());
266 !i.IsAtEnd(); i.Advance()) {
267 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats());
271 scoped_ptr<metrics::MetricsLogUploader>
272 ChromeMetricsServiceClient::CreateUploader(
273 const base::Callback<void(int)>& on_upload_complete) {
274 return scoped_ptr<metrics::MetricsLogUploader>(
275 new metrics::NetMetricsLogUploader(
276 g_browser_process->system_request_context(),
277 metrics::kDefaultMetricsServerUrl,
278 metrics::kDefaultMetricsMimeType,
279 on_upload_complete));
282 base::TimeDelta ChromeMetricsServiceClient::GetStandardUploadInterval() {
283 #if defined(OS_ANDROID) || defined(OS_IOS)
284 bool is_cellular = false;
285 cellular_callback_.Run(&is_cellular);
287 if (is_cellular && IsCellularEnabledByExperiment())
288 return base::TimeDelta::FromSeconds(kStandardUploadIntervalCellularSeconds);
289 #endif
290 return base::TimeDelta::FromSeconds(kStandardUploadIntervalSeconds);
293 base::string16 ChromeMetricsServiceClient::GetRegistryBackupKey() {
294 #if defined(OS_WIN)
295 return L"Software\\" PRODUCT_STRING_PATH L"\\StabilityMetrics";
296 #else
297 return base::string16();
298 #endif
301 void ChromeMetricsServiceClient::LogPluginLoadingError(
302 const base::FilePath& plugin_path) {
303 #if defined(ENABLE_PLUGINS)
304 plugin_metrics_provider_->LogPluginLoadingError(plugin_path);
305 #else
306 NOTREACHED();
307 #endif // defined(ENABLE_PLUGINS)
310 void ChromeMetricsServiceClient::Initialize() {
311 metrics_service_.reset(new metrics::MetricsService(
312 metrics_state_manager_, this, g_browser_process->local_state()));
314 // Register metrics providers.
315 #if defined(ENABLE_EXTENSIONS)
316 metrics_service_->RegisterMetricsProvider(
317 scoped_ptr<metrics::MetricsProvider>(
318 new ExtensionsMetricsProvider(metrics_state_manager_)));
319 #endif
320 scoped_ptr<metrics::NetworkMetricsProvider> network_metrics_provider(
321 new metrics::NetworkMetricsProvider(
322 content::BrowserThread::GetBlockingPool()));
323 cellular_callback_ = network_metrics_provider->GetConnectionCallback();
324 metrics_service_->RegisterMetricsProvider(network_metrics_provider.Pass());
326 metrics_service_->RegisterMetricsProvider(
327 scoped_ptr<metrics::MetricsProvider>(new OmniboxMetricsProvider));
328 metrics_service_->RegisterMetricsProvider(
329 scoped_ptr<metrics::MetricsProvider>(new ChromeStabilityMetricsProvider));
330 metrics_service_->RegisterMetricsProvider(
331 scoped_ptr<metrics::MetricsProvider>(new metrics::GPUMetricsProvider));
333 drive_metrics_provider_ = new DriveMetricsProvider;
334 metrics_service_->RegisterMetricsProvider(
335 scoped_ptr<metrics::MetricsProvider>(drive_metrics_provider_));
337 profiler_metrics_provider_ =
338 new metrics::ProfilerMetricsProvider(cellular_callback_);
339 metrics_service_->RegisterMetricsProvider(
340 scoped_ptr<metrics::MetricsProvider>(profiler_metrics_provider_));
342 metrics_service_->RegisterMetricsProvider(
343 scoped_ptr<metrics::MetricsProvider>(
344 new metrics::CallStackProfileMetricsProvider));
346 #if defined(OS_ANDROID)
347 metrics_service_->RegisterMetricsProvider(
348 scoped_ptr<metrics::MetricsProvider>(
349 new AndroidMetricsProvider(g_browser_process->local_state())));
350 #endif // defined(OS_ANDROID)
352 #if defined(OS_WIN)
353 google_update_metrics_provider_ = new GoogleUpdateMetricsProviderWin;
354 metrics_service_->RegisterMetricsProvider(
355 scoped_ptr<metrics::MetricsProvider>(google_update_metrics_provider_));
357 // Report exit funnels for canary and dev only.
358 bool report_exit_funnels = false;
359 switch (chrome::VersionInfo::GetChannel()) {
360 case chrome::VersionInfo::CHANNEL_CANARY:
361 case chrome::VersionInfo::CHANNEL_DEV:
362 report_exit_funnels = true;
363 break;
366 metrics_service_->RegisterMetricsProvider(
367 scoped_ptr<metrics::MetricsProvider>(
368 new browser_watcher::WatcherMetricsProviderWin(
369 chrome::kBrowserExitCodesRegistryPath, report_exit_funnels)));
370 #endif // defined(OS_WIN)
372 #if defined(ENABLE_PLUGINS)
373 plugin_metrics_provider_ =
374 new PluginMetricsProvider(g_browser_process->local_state());
375 metrics_service_->RegisterMetricsProvider(
376 scoped_ptr<metrics::MetricsProvider>(plugin_metrics_provider_));
377 #endif // defined(ENABLE_PLUGINS)
379 #if defined(OS_CHROMEOS)
380 ChromeOSMetricsProvider* chromeos_metrics_provider =
381 new ChromeOSMetricsProvider;
382 chromeos_metrics_provider_ = chromeos_metrics_provider;
383 metrics_service_->RegisterMetricsProvider(
384 scoped_ptr<metrics::MetricsProvider>(chromeos_metrics_provider));
386 SigninStatusMetricsProviderChromeOS* signin_metrics_provider_cros =
387 new SigninStatusMetricsProviderChromeOS;
388 metrics_service_->RegisterMetricsProvider(
389 scoped_ptr<metrics::MetricsProvider>(signin_metrics_provider_cros));
390 #endif // defined(OS_CHROMEOS)
392 #if !defined(OS_CHROMEOS) && !defined(OS_IOS)
393 metrics_service_->RegisterMetricsProvider(
394 scoped_ptr<metrics::MetricsProvider>(
395 SigninStatusMetricsProvider::CreateInstance()));
396 #endif // !defined(OS_CHROMEOS) && !defined(OS_IOS)
399 void ChromeMetricsServiceClient::OnInitTaskGotHardwareClass() {
400 const base::Closure got_plugin_info_callback =
401 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotPluginInfo,
402 weak_ptr_factory_.GetWeakPtr());
404 #if defined(ENABLE_PLUGINS)
405 plugin_metrics_provider_->GetPluginInformation(got_plugin_info_callback);
406 #else
407 got_plugin_info_callback.Run();
408 #endif // defined(ENABLE_PLUGINS)
411 void ChromeMetricsServiceClient::OnInitTaskGotPluginInfo() {
412 const base::Closure got_metrics_callback =
413 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData,
414 weak_ptr_factory_.GetWeakPtr());
416 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
417 google_update_metrics_provider_->GetGoogleUpdateData(got_metrics_callback);
418 #else
419 got_metrics_callback.Run();
420 #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
423 void ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData() {
424 // Start the next part of the init task: fetching performance data. This will
425 // call into |FinishedReceivingProfilerData()| when the task completes.
426 metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously(
427 weak_ptr_factory_.GetWeakPtr());
430 void ChromeMetricsServiceClient::ReceivedProfilerData(
431 const tracked_objects::ProcessDataSnapshot& process_data,
432 int process_type) {
433 profiler_metrics_provider_->RecordProfilerData(process_data, process_type);
436 void ChromeMetricsServiceClient::FinishedReceivingProfilerData() {
437 drive_metrics_provider_->GetDriveMetrics(
438 finished_gathering_initial_metrics_callback_);
441 void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() {
442 DCHECK(thread_checker_.CalledOnValidThread());
444 // This function should only be called as the callback from an ansynchronous
445 // step.
446 DCHECK(waiting_for_collect_final_metrics_step_);
448 // Create a callback_task for OnHistogramSynchronizationDone.
449 base::Closure callback = base::Bind(
450 &ChromeMetricsServiceClient::OnHistogramSynchronizationDone,
451 weak_ptr_factory_.GetWeakPtr());
453 base::TimeDelta timeout =
454 base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration);
456 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 0);
458 #if !defined(ENABLE_PRINT_PREVIEW)
459 num_async_histogram_fetches_in_progress_ = 1;
460 #else // !ENABLE_PRINT_PREVIEW
461 num_async_histogram_fetches_in_progress_ = 2;
462 // Run requests to service and content in parallel.
463 if (!ServiceProcessControl::GetInstance()->GetHistograms(callback, timeout)) {
464 // Assume |num_async_histogram_fetches_in_progress_| is not changed by
465 // |GetHistograms()|.
466 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 2);
467 // Assign |num_async_histogram_fetches_in_progress_| above and decrement it
468 // here to make code work even if |GetHistograms()| fired |callback|.
469 --num_async_histogram_fetches_in_progress_;
471 #endif // !ENABLE_PRINT_PREVIEW
473 // Set up the callback to task to call after we receive histograms from all
474 // child processes. |timeout| specifies how long to wait before absolutely
475 // calling us back on the task.
476 content::FetchHistogramsAsynchronously(base::MessageLoop::current(), callback,
477 timeout);
480 void ChromeMetricsServiceClient::OnHistogramSynchronizationDone() {
481 DCHECK(thread_checker_.CalledOnValidThread());
483 // This function should only be called as the callback from an ansynchronous
484 // step.
485 DCHECK(waiting_for_collect_final_metrics_step_);
486 DCHECK_GT(num_async_histogram_fetches_in_progress_, 0);
488 // Check if all expected requests finished.
489 if (--num_async_histogram_fetches_in_progress_ > 0)
490 return;
492 waiting_for_collect_final_metrics_step_ = false;
493 collect_final_metrics_done_callback_.Run();
496 void ChromeMetricsServiceClient::RecordCommandLineMetrics() {
497 // Get stats on use of command line.
498 const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
499 size_t common_commands = 0;
500 if (command_line->HasSwitch(switches::kUserDataDir)) {
501 ++common_commands;
502 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1);
505 if (command_line->HasSwitch(switches::kApp)) {
506 ++common_commands;
507 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1);
510 // TODO(rohitrao): Should these be logged on iOS as well?
511 // http://crbug.com/375794
512 size_t switch_count = command_line->GetSwitches().size();
513 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count);
514 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
515 switch_count - common_commands);
518 void ChromeMetricsServiceClient::RegisterForNotifications() {
519 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
520 content::NotificationService::AllBrowserContextsAndSources());
521 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
522 content::NotificationService::AllSources());
523 registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED,
524 content::NotificationService::AllSources());
525 registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING,
526 content::NotificationService::AllSources());
527 registrar_.Add(this, content::NOTIFICATION_LOAD_START,
528 content::NotificationService::AllSources());
529 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
530 content::NotificationService::AllSources());
531 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
532 content::NotificationService::AllSources());
533 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
534 content::NotificationService::AllSources());
535 registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
536 content::NotificationService::AllSources());
539 void ChromeMetricsServiceClient::Observe(
540 int type,
541 const content::NotificationSource& source,
542 const content::NotificationDetails& details) {
543 DCHECK(thread_checker_.CalledOnValidThread());
545 switch (type) {
546 case chrome::NOTIFICATION_BROWSER_OPENED:
547 case chrome::NOTIFICATION_BROWSER_CLOSED:
548 case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
549 case chrome::NOTIFICATION_TAB_PARENTED:
550 case chrome::NOTIFICATION_TAB_CLOSING:
551 case content::NOTIFICATION_LOAD_STOP:
552 case content::NOTIFICATION_LOAD_START:
553 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED:
554 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
555 metrics_service_->OnApplicationNotIdle();
556 break;
558 default:
559 NOTREACHED();
563 #if defined(OS_WIN)
564 void ChromeMetricsServiceClient::CountBrowserCrashDumpAttempts() {
565 // Open the registry key for iteration.
566 base::win::RegKey regkey;
567 if (regkey.Open(HKEY_CURRENT_USER,
568 chrome::kBrowserCrashDumpAttemptsRegistryPath,
569 KEY_ALL_ACCESS) != ERROR_SUCCESS) {
570 return;
573 // The values we're interested in counting are all prefixed with the version.
574 base::string16 chrome_version(base::ASCIIToUTF16(chrome::kChromeVersion));
576 // Track a list of values to delete. We don't modify the registry key while
577 // we're iterating over its values.
578 typedef std::vector<base::string16> StringVector;
579 StringVector to_delete;
581 // Iterate over the values in the key counting dumps with and without crashes.
582 // We directly walk the values instead of using RegistryValueIterator in order
583 // to read all of the values as DWORDS instead of strings.
584 base::string16 name;
585 DWORD value = 0;
586 int dumps_with_crash = 0;
587 int dumps_with_no_crash = 0;
588 for (int i = regkey.GetValueCount() - 1; i >= 0; --i) {
589 if (regkey.GetValueNameAt(i, &name) == ERROR_SUCCESS &&
590 StartsWith(name, chrome_version, false) &&
591 regkey.ReadValueDW(name.c_str(), &value) == ERROR_SUCCESS) {
592 to_delete.push_back(name);
593 if (value == 0)
594 ++dumps_with_no_crash;
595 else
596 ++dumps_with_crash;
600 // Delete the registry keys we've just counted.
601 for (StringVector::iterator i = to_delete.begin(); i != to_delete.end(); ++i)
602 regkey.DeleteValue(i->c_str());
604 // Capture the histogram samples.
605 if (dumps_with_crash != 0)
606 UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithCrash", dumps_with_crash);
607 if (dumps_with_no_crash != 0)
608 UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithNoCrash", dumps_with_no_crash);
609 int total_dumps = dumps_with_crash + dumps_with_no_crash;
610 if (total_dumps != 0)
611 UMA_HISTOGRAM_COUNTS("Chrome.BrowserCrashDumpAttempts", total_dumps);
613 #endif // defined(OS_WIN)