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