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.
4
5 #include "chrome/browser/metrics/chrome_metrics_service_client.h"
6
7 #include <vector>
8
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/histogram.h"
15 #include "base/prefs/pref_registry_simple.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/threading/platform_thread.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/chrome_notification_types.h"
23 #include "chrome/browser/google/google_brand.h"
24 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
25 #include "chrome/browser/metrics/omnibox_metrics_provider.h"
26 #include "chrome/browser/ui/browser_otr_state.h"
27 #include "chrome/common/chrome_constants.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/chrome_version_info.h"
30 #include "chrome/common/crash_keys.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/render_messages.h"
33 #include "components/metrics/gpu/gpu_metrics_provider.h"
34 #include "components/metrics/metrics_service.h"
35 #include "components/metrics/net/net_metrics_log_uploader.h"
36 #include "components/metrics/net/network_metrics_provider.h"
37 #include "components/metrics/profiler/profiler_metrics_provider.h"
38 #include "components/metrics/profiler/tracking_synchronizer.h"
39 #include "content/public/browser/browser_thread.h"
40 #include "content/public/browser/histogram_fetcher.h"
41 #include "content/public/browser/notification_service.h"
42 #include "content/public/browser/render_process_host.h"
43
44 #if defined(OS_ANDROID)
45 #include "chrome/browser/metrics/android_metrics_provider.h"
46 #endif
47
48 #if defined(ENABLE_FULL_PRINTING)
49 #include "chrome/browser/service_process/service_process_control.h"
50 #endif
51
52 #if defined(ENABLE_EXTENSIONS)
53 #include "chrome/browser/metrics/extensions_metrics_provider.h"
54 #endif
55
56 #if defined(ENABLE_PLUGINS)
57 #include "chrome/browser/metrics/plugin_metrics_provider.h"
58 #endif
59
60 #if defined(OS_CHROMEOS)
61 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
62 #endif
63
64 #if defined(OS_WIN)
65 #include <windows.h>
66 #include "base/win/registry.h"
67 #include "chrome/browser/metrics/google_update_metrics_provider_win.h"
68 #endif
69
70 #if !defined(OS_CHROMEOS) && !defined(OS_IOS)
71 #include "chrome/browser/metrics/signin_status_metrics_provider.h"
72 #endif
73
74 namespace {
75
76 // This specifies the amount of time to wait for all renderers to send their
77 // data.
78 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds.
79
AsProtobufChannel(chrome::VersionInfo::Channel channel)80 metrics::SystemProfileProto::Channel AsProtobufChannel(
81 chrome::VersionInfo::Channel channel) {
82 switch (channel) {
83 case chrome::VersionInfo::CHANNEL_UNKNOWN:
84 return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
85 case chrome::VersionInfo::CHANNEL_CANARY:
86 return metrics::SystemProfileProto::CHANNEL_CANARY;
87 case chrome::VersionInfo::CHANNEL_DEV:
88 return metrics::SystemProfileProto::CHANNEL_DEV;
89 case chrome::VersionInfo::CHANNEL_BETA:
90 return metrics::SystemProfileProto::CHANNEL_BETA;
91 case chrome::VersionInfo::CHANNEL_STABLE:
92 return metrics::SystemProfileProto::CHANNEL_STABLE;
93 }
94 NOTREACHED();
95 return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
96 }
97
98 // Handles asynchronous fetching of memory details.
99 // Will run the provided task after finished.
100 class MetricsMemoryDetails : public MemoryDetails {
101 public:
MetricsMemoryDetails(const base::Closure & callback,MemoryGrowthTracker * memory_growth_tracker)102 MetricsMemoryDetails(
103 const base::Closure& callback,
104 MemoryGrowthTracker* memory_growth_tracker)
105 : callback_(callback) {
106 SetMemoryGrowthTracker(memory_growth_tracker);
107 }
108
OnDetailsAvailable()109 virtual void OnDetailsAvailable() OVERRIDE {
110 base::MessageLoop::current()->PostTask(FROM_HERE, callback_);
111 }
112
113 private:
~MetricsMemoryDetails()114 virtual ~MetricsMemoryDetails() {}
115
116 base::Closure callback_;
117
118 DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetails);
119 };
120
121 } // namespace
122
ChromeMetricsServiceClient(metrics::MetricsStateManager * state_manager)123 ChromeMetricsServiceClient::ChromeMetricsServiceClient(
124 metrics::MetricsStateManager* state_manager)
125 : metrics_state_manager_(state_manager),
126 chromeos_metrics_provider_(NULL),
127 waiting_for_collect_final_metrics_step_(false),
128 num_async_histogram_fetches_in_progress_(0),
129 weak_ptr_factory_(this) {
130 DCHECK(thread_checker_.CalledOnValidThread());
131 RecordCommandLineMetrics();
132 RegisterForNotifications();
133
134 #if defined(OS_WIN)
135 CountBrowserCrashDumpAttempts();
136 #endif // defined(OS_WIN)
137 }
138
~ChromeMetricsServiceClient()139 ChromeMetricsServiceClient::~ChromeMetricsServiceClient() {
140 DCHECK(thread_checker_.CalledOnValidThread());
141 }
142
143 // static
Create(metrics::MetricsStateManager * state_manager,PrefService * local_state)144 scoped_ptr<ChromeMetricsServiceClient> ChromeMetricsServiceClient::Create(
145 metrics::MetricsStateManager* state_manager,
146 PrefService* local_state) {
147 // Perform two-phase initialization so that |client->metrics_service_| only
148 // receives pointers to fully constructed objects.
149 scoped_ptr<ChromeMetricsServiceClient> client(
150 new ChromeMetricsServiceClient(state_manager));
151 client->Initialize();
152
153 return client.Pass();
154 }
155
156 // static
RegisterPrefs(PrefRegistrySimple * registry)157 void ChromeMetricsServiceClient::RegisterPrefs(PrefRegistrySimple* registry) {
158 registry->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0);
159 registry->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0);
160
161 metrics::MetricsService::RegisterPrefs(registry);
162 ChromeStabilityMetricsProvider::RegisterPrefs(registry);
163
164 #if defined(OS_ANDROID)
165 AndroidMetricsProvider::RegisterPrefs(registry);
166 #endif // defined(OS_ANDROID)
167
168 #if defined(ENABLE_PLUGINS)
169 PluginMetricsProvider::RegisterPrefs(registry);
170 #endif // defined(ENABLE_PLUGINS)
171 }
172
SetMetricsClientId(const std::string & client_id)173 void ChromeMetricsServiceClient::SetMetricsClientId(
174 const std::string& client_id) {
175 crash_keys::SetCrashClientIdFromGUID(client_id);
176 }
177
IsOffTheRecordSessionActive()178 bool ChromeMetricsServiceClient::IsOffTheRecordSessionActive() {
179 return chrome::IsOffTheRecordSessionActive();
180 }
181
GetApplicationLocale()182 std::string ChromeMetricsServiceClient::GetApplicationLocale() {
183 return g_browser_process->GetApplicationLocale();
184 }
185
GetBrand(std::string * brand_code)186 bool ChromeMetricsServiceClient::GetBrand(std::string* brand_code) {
187 return google_brand::GetBrand(brand_code);
188 }
189
GetChannel()190 metrics::SystemProfileProto::Channel ChromeMetricsServiceClient::GetChannel() {
191 return AsProtobufChannel(chrome::VersionInfo::GetChannel());
192 }
193
GetVersionString()194 std::string ChromeMetricsServiceClient::GetVersionString() {
195 chrome::VersionInfo version_info;
196 if (!version_info.is_valid()) {
197 NOTREACHED();
198 return std::string();
199 }
200
201 std::string version = version_info.Version();
202 #if defined(ARCH_CPU_64_BITS)
203 version += "-64";
204 #endif // defined(ARCH_CPU_64_BITS)
205 if (!version_info.IsOfficialBuild())
206 version.append("-devel");
207 return version;
208 }
209
OnLogUploadComplete()210 void ChromeMetricsServiceClient::OnLogUploadComplete() {
211 // Collect network stats after each UMA upload.
212 network_stats_uploader_.CollectAndReportNetworkStats();
213 }
214
StartGatheringMetrics(const base::Closure & done_callback)215 void ChromeMetricsServiceClient::StartGatheringMetrics(
216 const base::Closure& done_callback) {
217 finished_gathering_initial_metrics_callback_ = done_callback;
218 base::Closure got_hardware_class_callback =
219 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotHardwareClass,
220 weak_ptr_factory_.GetWeakPtr());
221 #if defined(OS_CHROMEOS)
222 chromeos_metrics_provider_->InitTaskGetHardwareClass(
223 got_hardware_class_callback);
224 #else
225 got_hardware_class_callback.Run();
226 #endif // defined(OS_CHROMEOS)
227 }
228
CollectFinalMetrics(const base::Closure & done_callback)229 void ChromeMetricsServiceClient::CollectFinalMetrics(
230 const base::Closure& done_callback) {
231 DCHECK(thread_checker_.CalledOnValidThread());
232
233 collect_final_metrics_done_callback_ = done_callback;
234
235 // Begin the multi-step process of collecting memory usage histograms:
236 // First spawn a task to collect the memory details; when that task is
237 // finished, it will call OnMemoryDetailCollectionDone. That will in turn
238 // call HistogramSynchronization to collect histograms from all renderers and
239 // then call OnHistogramSynchronizationDone to continue processing.
240 DCHECK(!waiting_for_collect_final_metrics_step_);
241 waiting_for_collect_final_metrics_step_ = true;
242
243 base::Closure callback =
244 base::Bind(&ChromeMetricsServiceClient::OnMemoryDetailCollectionDone,
245 weak_ptr_factory_.GetWeakPtr());
246
247 scoped_refptr<MetricsMemoryDetails> details(
248 new MetricsMemoryDetails(callback, &memory_growth_tracker_));
249 details->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
250
251 // Collect WebCore cache information to put into a histogram.
252 for (content::RenderProcessHost::iterator i(
253 content::RenderProcessHost::AllHostsIterator());
254 !i.IsAtEnd(); i.Advance()) {
255 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats());
256 }
257 }
258
259 scoped_ptr<metrics::MetricsLogUploader>
CreateUploader(const std::string & server_url,const std::string & mime_type,const base::Callback<void (int)> & on_upload_complete)260 ChromeMetricsServiceClient::CreateUploader(
261 const std::string& server_url,
262 const std::string& mime_type,
263 const base::Callback<void(int)>& on_upload_complete) {
264 return scoped_ptr<metrics::MetricsLogUploader>(
265 new metrics::NetMetricsLogUploader(
266 g_browser_process->system_request_context(), server_url, mime_type,
267 on_upload_complete));
268 }
269
GetRegistryBackupKey()270 base::string16 ChromeMetricsServiceClient::GetRegistryBackupKey() {
271 #if defined(OS_WIN)
272 return L"Software\\" PRODUCT_STRING_PATH L"\\StabilityMetrics";
273 #else
274 return base::string16();
275 #endif
276 }
277
LogPluginLoadingError(const base::FilePath & plugin_path)278 void ChromeMetricsServiceClient::LogPluginLoadingError(
279 const base::FilePath& plugin_path) {
280 #if defined(ENABLE_PLUGINS)
281 plugin_metrics_provider_->LogPluginLoadingError(plugin_path);
282 #else
283 NOTREACHED();
284 #endif // defined(ENABLE_PLUGINS)
285 }
286
Initialize()287 void ChromeMetricsServiceClient::Initialize() {
288 metrics_service_.reset(new metrics::MetricsService(
289 metrics_state_manager_, this, g_browser_process->local_state()));
290
291 // Register metrics providers.
292 #if defined(ENABLE_EXTENSIONS)
293 metrics_service_->RegisterMetricsProvider(
294 scoped_ptr<metrics::MetricsProvider>(
295 new ExtensionsMetricsProvider(metrics_state_manager_)));
296 #endif
297 metrics_service_->RegisterMetricsProvider(
298 scoped_ptr<metrics::MetricsProvider>(new NetworkMetricsProvider(
299 content::BrowserThread::GetBlockingPool())));
300 metrics_service_->RegisterMetricsProvider(
301 scoped_ptr<metrics::MetricsProvider>(new OmniboxMetricsProvider));
302 metrics_service_->RegisterMetricsProvider(
303 scoped_ptr<metrics::MetricsProvider>(new ChromeStabilityMetricsProvider));
304 metrics_service_->RegisterMetricsProvider(
305 scoped_ptr<metrics::MetricsProvider>(new metrics::GPUMetricsProvider()));
306 profiler_metrics_provider_ = new metrics::ProfilerMetricsProvider;
307 metrics_service_->RegisterMetricsProvider(
308 scoped_ptr<metrics::MetricsProvider>(profiler_metrics_provider_));
309
310 #if defined(OS_ANDROID)
311 metrics_service_->RegisterMetricsProvider(
312 scoped_ptr<metrics::MetricsProvider>(
313 new AndroidMetricsProvider(g_browser_process->local_state())));
314 #endif // defined(OS_ANDROID)
315
316 #if defined(OS_WIN)
317 google_update_metrics_provider_ = new GoogleUpdateMetricsProviderWin;
318 metrics_service_->RegisterMetricsProvider(
319 scoped_ptr<metrics::MetricsProvider>(google_update_metrics_provider_));
320 #endif // defined(OS_WIN)
321
322 #if defined(ENABLE_PLUGINS)
323 plugin_metrics_provider_ =
324 new PluginMetricsProvider(g_browser_process->local_state());
325 metrics_service_->RegisterMetricsProvider(
326 scoped_ptr<metrics::MetricsProvider>(plugin_metrics_provider_));
327 #endif // defined(ENABLE_PLUGINS)
328
329 #if defined(OS_CHROMEOS)
330 ChromeOSMetricsProvider* chromeos_metrics_provider =
331 new ChromeOSMetricsProvider;
332 chromeos_metrics_provider_ = chromeos_metrics_provider;
333 metrics_service_->RegisterMetricsProvider(
334 scoped_ptr<metrics::MetricsProvider>(chromeos_metrics_provider));
335 #endif // defined(OS_CHROMEOS)
336
337 #if !defined(OS_CHROMEOS) && !defined(OS_IOS)
338 metrics_service_->RegisterMetricsProvider(
339 scoped_ptr<metrics::MetricsProvider>(
340 SigninStatusMetricsProvider::CreateInstance()));
341 #endif
342 }
343
OnInitTaskGotHardwareClass()344 void ChromeMetricsServiceClient::OnInitTaskGotHardwareClass() {
345 const base::Closure got_plugin_info_callback =
346 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotPluginInfo,
347 weak_ptr_factory_.GetWeakPtr());
348
349 #if defined(ENABLE_PLUGINS)
350 plugin_metrics_provider_->GetPluginInformation(got_plugin_info_callback);
351 #else
352 got_plugin_info_callback.Run();
353 #endif // defined(ENABLE_PLUGINS)
354 }
355
OnInitTaskGotPluginInfo()356 void ChromeMetricsServiceClient::OnInitTaskGotPluginInfo() {
357 const base::Closure got_metrics_callback =
358 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData,
359 weak_ptr_factory_.GetWeakPtr());
360
361 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
362 google_update_metrics_provider_->GetGoogleUpdateData(got_metrics_callback);
363 #else
364 got_metrics_callback.Run();
365 #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
366 }
367
OnInitTaskGotGoogleUpdateData()368 void ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData() {
369 // Start the next part of the init task: fetching performance data. This will
370 // call into |FinishedReceivingProfilerData()| when the task completes.
371 metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously(
372 weak_ptr_factory_.GetWeakPtr());
373 }
374
ReceivedProfilerData(const tracked_objects::ProcessDataSnapshot & process_data,int process_type)375 void ChromeMetricsServiceClient::ReceivedProfilerData(
376 const tracked_objects::ProcessDataSnapshot& process_data,
377 int process_type) {
378 profiler_metrics_provider_->RecordProfilerData(process_data, process_type);
379 }
380
FinishedReceivingProfilerData()381 void ChromeMetricsServiceClient::FinishedReceivingProfilerData() {
382 finished_gathering_initial_metrics_callback_.Run();
383 }
384
OnMemoryDetailCollectionDone()385 void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() {
386 DCHECK(thread_checker_.CalledOnValidThread());
387
388 // This function should only be called as the callback from an ansynchronous
389 // step.
390 DCHECK(waiting_for_collect_final_metrics_step_);
391
392 // Create a callback_task for OnHistogramSynchronizationDone.
393 base::Closure callback = base::Bind(
394 &ChromeMetricsServiceClient::OnHistogramSynchronizationDone,
395 weak_ptr_factory_.GetWeakPtr());
396
397 base::TimeDelta timeout =
398 base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration);
399
400 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 0);
401
402 #if !defined(ENABLE_FULL_PRINTING)
403 num_async_histogram_fetches_in_progress_ = 1;
404 #else // !ENABLE_FULL_PRINTING
405 num_async_histogram_fetches_in_progress_ = 2;
406 // Run requests to service and content in parallel.
407 if (!ServiceProcessControl::GetInstance()->GetHistograms(callback, timeout)) {
408 // Assume |num_async_histogram_fetches_in_progress_| is not changed by
409 // |GetHistograms()|.
410 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 2);
411 // Assign |num_async_histogram_fetches_in_progress_| above and decrement it
412 // here to make code work even if |GetHistograms()| fired |callback|.
413 --num_async_histogram_fetches_in_progress_;
414 }
415 #endif // !ENABLE_FULL_PRINTING
416
417 // Set up the callback to task to call after we receive histograms from all
418 // child processes. |timeout| specifies how long to wait before absolutely
419 // calling us back on the task.
420 content::FetchHistogramsAsynchronously(base::MessageLoop::current(), callback,
421 timeout);
422 }
423
OnHistogramSynchronizationDone()424 void ChromeMetricsServiceClient::OnHistogramSynchronizationDone() {
425 DCHECK(thread_checker_.CalledOnValidThread());
426
427 // This function should only be called as the callback from an ansynchronous
428 // step.
429 DCHECK(waiting_for_collect_final_metrics_step_);
430 DCHECK_GT(num_async_histogram_fetches_in_progress_, 0);
431
432 // Check if all expected requests finished.
433 if (--num_async_histogram_fetches_in_progress_ > 0)
434 return;
435
436 waiting_for_collect_final_metrics_step_ = false;
437 collect_final_metrics_done_callback_.Run();
438 }
439
RecordCommandLineMetrics()440 void ChromeMetricsServiceClient::RecordCommandLineMetrics() {
441 // Get stats on use of command line.
442 const CommandLine* command_line(CommandLine::ForCurrentProcess());
443 size_t common_commands = 0;
444 if (command_line->HasSwitch(switches::kUserDataDir)) {
445 ++common_commands;
446 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1);
447 }
448
449 if (command_line->HasSwitch(switches::kApp)) {
450 ++common_commands;
451 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1);
452 }
453
454 // TODO(rohitrao): Should these be logged on iOS as well?
455 // http://crbug.com/375794
456 size_t switch_count = command_line->GetSwitches().size();
457 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count);
458 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
459 switch_count - common_commands);
460 }
461
RegisterForNotifications()462 void ChromeMetricsServiceClient::RegisterForNotifications() {
463 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
464 content::NotificationService::AllBrowserContextsAndSources());
465 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
466 content::NotificationService::AllSources());
467 registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED,
468 content::NotificationService::AllSources());
469 registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING,
470 content::NotificationService::AllSources());
471 registrar_.Add(this, content::NOTIFICATION_LOAD_START,
472 content::NotificationService::AllSources());
473 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
474 content::NotificationService::AllSources());
475 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
476 content::NotificationService::AllSources());
477 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
478 content::NotificationService::AllSources());
479 registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
480 content::NotificationService::AllSources());
481 }
482
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)483 void ChromeMetricsServiceClient::Observe(
484 int type,
485 const content::NotificationSource& source,
486 const content::NotificationDetails& details) {
487 DCHECK(thread_checker_.CalledOnValidThread());
488
489 switch (type) {
490 case chrome::NOTIFICATION_BROWSER_OPENED:
491 case chrome::NOTIFICATION_BROWSER_CLOSED:
492 case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
493 case chrome::NOTIFICATION_TAB_PARENTED:
494 case chrome::NOTIFICATION_TAB_CLOSING:
495 case content::NOTIFICATION_LOAD_STOP:
496 case content::NOTIFICATION_LOAD_START:
497 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED:
498 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
499 metrics_service_->OnApplicationNotIdle();
500 break;
501
502 default:
503 NOTREACHED();
504 }
505 }
506
507 #if defined(OS_WIN)
CountBrowserCrashDumpAttempts()508 void ChromeMetricsServiceClient::CountBrowserCrashDumpAttempts() {
509 // Open the registry key for iteration.
510 base::win::RegKey regkey;
511 if (regkey.Open(HKEY_CURRENT_USER,
512 chrome::kBrowserCrashDumpAttemptsRegistryPath,
513 KEY_ALL_ACCESS) != ERROR_SUCCESS) {
514 return;
515 }
516
517 // The values we're interested in counting are all prefixed with the version.
518 base::string16 chrome_version(base::ASCIIToUTF16(chrome::kChromeVersion));
519
520 // Track a list of values to delete. We don't modify the registry key while
521 // we're iterating over its values.
522 typedef std::vector<base::string16> StringVector;
523 StringVector to_delete;
524
525 // Iterate over the values in the key counting dumps with and without crashes.
526 // We directly walk the values instead of using RegistryValueIterator in order
527 // to read all of the values as DWORDS instead of strings.
528 base::string16 name;
529 DWORD value = 0;
530 int dumps_with_crash = 0;
531 int dumps_with_no_crash = 0;
532 for (int i = regkey.GetValueCount() - 1; i >= 0; --i) {
533 if (regkey.GetValueNameAt(i, &name) == ERROR_SUCCESS &&
534 StartsWith(name, chrome_version, false) &&
535 regkey.ReadValueDW(name.c_str(), &value) == ERROR_SUCCESS) {
536 to_delete.push_back(name);
537 if (value == 0)
538 ++dumps_with_no_crash;
539 else
540 ++dumps_with_crash;
541 }
542 }
543
544 // Delete the registry keys we've just counted.
545 for (StringVector::iterator i = to_delete.begin(); i != to_delete.end(); ++i)
546 regkey.DeleteValue(i->c_str());
547
548 // Capture the histogram samples.
549 if (dumps_with_crash != 0)
550 UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithCrash", dumps_with_crash);
551 if (dumps_with_no_crash != 0)
552 UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithNoCrash", dumps_with_no_crash);
553 int total_dumps = dumps_with_crash + dumps_with_no_crash;
554 if (total_dumps != 0)
555 UMA_HISTOGRAM_COUNTS("Chrome.BrowserCrashDumpAttempts", total_dumps);
556 }
557 #endif // defined(OS_WIN)
558