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"
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"
52 #if defined(ENABLE_PRINT_PREVIEW)
53 #include "chrome/browser/service_process/service_process_control.h"
56 #if defined(ENABLE_EXTENSIONS)
57 #include "chrome/browser/metrics/extensions_metrics_provider.h"
60 #if defined(ENABLE_PLUGINS)
61 #include "chrome/browser/metrics/plugin_metrics_provider.h"
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"
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"
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)
82 // This specifies the amount of time to wait for all renderers to send their
84 const int kMaxHistogramGatheringWaitDuration
= 60000; // 60 seconds.
86 metrics::SystemProfileProto::Channel
AsProtobufChannel(
87 chrome::VersionInfo::Channel 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
;
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.
109 const int kStandardUploadIntervalSeconds
= 30 * 60; // Thirty minutes.
112 #if defined(OS_ANDROID) || defined(OS_IOS)
113 // Returns true if the user is assigned to the experiment group for enabled
115 bool IsCellularEnabledByExperiment() {
116 const std::string group_name
=
117 base::FieldTrialList::FindFullName("UMA_EnableCellularLogUpload");
118 return group_name
== "Enabled";
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),
135 google_update_metrics_provider_(nullptr),
137 drive_metrics_provider_(nullptr),
138 weak_ptr_factory_(this) {
139 DCHECK(thread_checker_
.CalledOnValidThread());
140 RecordCommandLineMetrics();
141 RegisterForNotifications();
144 CountBrowserCrashDumpAttempts();
145 #endif // defined(OS_WIN)
148 ChromeMetricsServiceClient::~ChromeMetricsServiceClient() {
149 DCHECK(thread_checker_
.CalledOnValidThread());
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();
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)
216 #endif // defined(ARCH_CPU_64_BITS)
217 if (!version_info
.IsOfficialBuild())
218 version
.append("-devel");
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
);
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
);
290 return base::TimeDelta::FromSeconds(kStandardUploadIntervalSeconds
);
293 base::string16
ChromeMetricsServiceClient::GetRegistryBackupKey() {
295 return L
"Software\\" PRODUCT_STRING_PATH L
"\\StabilityMetrics";
297 return base::string16();
301 void ChromeMetricsServiceClient::LogPluginLoadingError(
302 const base::FilePath
& plugin_path
) {
303 #if defined(ENABLE_PLUGINS)
304 plugin_metrics_provider_
->LogPluginLoadingError(plugin_path
);
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_
)));
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)
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;
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
);
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
);
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
,
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
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
,
480 void ChromeMetricsServiceClient::OnHistogramSynchronizationDone() {
481 DCHECK(thread_checker_
.CalledOnValidThread());
483 // This function should only be called as the callback from an ansynchronous
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)
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
)) {
502 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1);
505 if (command_line
->HasSwitch(switches::kApp
)) {
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(
541 const content::NotificationSource
& source
,
542 const content::NotificationDetails
& details
) {
543 DCHECK(thread_checker_
.CalledOnValidThread());
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();
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
) {
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.
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
);
594 ++dumps_with_no_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)