chrome_metrics_service_client.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/chrome_metrics_service_client.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <vector>
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/command_line.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/histogram.h"
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/prefs/pref_service.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/string16.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/string_util.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/threading/platform_thread.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/time/time.h"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/browser_process.h"
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chrome_notification_types.h"
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/google/google_brand.h"
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/memory_details.h"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/extensions_metrics_provider.h"
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/metrics_service.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/ui/browser_otr_state.h"
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/crash_keys.h"
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/common/pref_names.h"
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/render_messages.h"
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/metrics/net/net_metrics_log_uploader.h"
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/histogram_fetcher.h"
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/notification_service.h"
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(OS_ANDROID)
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/service_process/service_process_control.h"
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_CHROMEOS)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/chromeos_metrics_provider.h"
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_WIN)
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <windows.h>
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/win/registry.h"
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/google_update_metrics_provider_win.h"
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This specifies the amount of time to wait for all renderers to send their
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// data.
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const int kMaxHistogramGatheringWaitDuration = 60000;  // 60 seconds.
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)metrics::SystemProfileProto::Channel AsProtobufChannel(
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    chrome::VersionInfo::Channel channel) {
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (channel) {
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_UNKNOWN:
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_CANARY:
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return metrics::SystemProfileProto::CHANNEL_CANARY;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_DEV:
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return metrics::SystemProfileProto::CHANNEL_DEV;
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_BETA:
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return metrics::SystemProfileProto::CHANNEL_BETA;
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::VersionInfo::CHANNEL_STABLE:
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return metrics::SystemProfileProto::CHANNEL_STABLE;
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Handles asynchronous fetching of memory details.
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Will run the provided task after finished.
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class MetricsMemoryDetails : public MemoryDetails {
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  explicit MetricsMemoryDetails(const base::Closure& callback)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : callback_(callback) {}
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnDetailsAvailable() OVERRIDE {
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE, callback_);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~MetricsMemoryDetails() {}
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::Closure callback_;
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetails);
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ChromeMetricsServiceClient::ChromeMetricsServiceClient(
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metrics::MetricsStateManager* state_manager)
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : metrics_state_manager_(state_manager),
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chromeos_metrics_provider_(NULL),
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      waiting_for_collect_final_metrics_step_(false),
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      num_async_histogram_fetches_in_progress_(0),
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      weak_ptr_factory_(this) {
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RecordCommandLineMetrics();
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RegisterForNotifications();
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_WIN)
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CountBrowserCrashDumpAttempts();
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  // defined(OS_WIN)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ChromeMetricsServiceClient::~ChromeMetricsServiceClient() {
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<ChromeMetricsServiceClient> ChromeMetricsServiceClient::Create(
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metrics::MetricsStateManager* state_manager,
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PrefService* local_state) {
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Perform two-phase initialization so that |client->metrics_service_| only
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // receives pointers to fully constructed objects.
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<ChromeMetricsServiceClient> client(
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new ChromeMetricsServiceClient(state_manager));
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  client->Initialize();
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return client.Pass();
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::Initialize() {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics_service_.reset(new MetricsService(
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      metrics_state_manager_, this, g_browser_process->local_state()));
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Register metrics providers.
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics_service_->RegisterMetricsProvider(
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<metrics::MetricsProvider>(
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          new ExtensionsMetricsProvider(metrics_state_manager_)));
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_CHROMEOS)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ChromeOSMetricsProvider* chromeos_metrics_provider =
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new ChromeOSMetricsProvider;
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos_metrics_provider_ = chromeos_metrics_provider;
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics_service_->RegisterMetricsProvider(
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<metrics::MetricsProvider>(chromeos_metrics_provider));
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::SetClientID(const std::string& client_id) {
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crash_keys::SetClientID(client_id);
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ChromeMetricsServiceClient::IsOffTheRecordSessionActive() {
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return !chrome::IsOffTheRecordSessionActive();
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string ChromeMetricsServiceClient::GetApplicationLocale() {
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return g_browser_process->GetApplicationLocale();
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ChromeMetricsServiceClient::GetBrand(std::string* brand_code) {
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return google_brand::GetBrand(brand_code);
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)metrics::SystemProfileProto::Channel ChromeMetricsServiceClient::GetChannel() {
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return AsProtobufChannel(chrome::VersionInfo::GetChannel());
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string ChromeMetricsServiceClient::GetVersionString() {
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chrome::VersionInfo version_info;
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!version_info.is_valid()) {
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NOTREACHED();
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return std::string();
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string version = version_info.Version();
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(ARCH_CPU_64_BITS)
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  version += "-64";
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  // defined(ARCH_CPU_64_BITS)
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!version_info.IsOfficialBuild())
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    version.append("-devel");
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return version;
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int64 ChromeMetricsServiceClient::GetInstallDate() {
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return g_browser_process->local_state()->GetInt64(prefs::kInstallDate);
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::OnLogUploadComplete() {
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Collect network stats after each UMA upload.
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  network_stats_uploader_.CollectAndReportNetworkStats();
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ChromeMetricsServiceClient::StartGatheringMetrics(
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::Closure& done_callback) {
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// TODO(blundell): Move all metrics gathering tasks from MetricsService to
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// here.
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(OS_CHROMEOS)
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  chromeos_metrics_provider_->InitTaskGetHardwareClass(done_callback);
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#else
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  done_callback.Run();
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::CollectFinalMetrics(
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::Closure& done_callback) {
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  collect_final_metrics_done_callback_ = done_callback;
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Begin the multi-step process of collecting memory usage histograms:
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // First spawn a task to collect the memory details; when that task is
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // finished, it will call OnMemoryDetailCollectionDone. That will in turn
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // call HistogramSynchronization to collect histograms from all renderers and
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // then call OnHistogramSynchronizationDone to continue processing.
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!waiting_for_collect_final_metrics_step_);
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  waiting_for_collect_final_metrics_step_ = true;
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::Closure callback =
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&ChromeMetricsServiceClient::OnMemoryDetailCollectionDone,
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr());
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<MetricsMemoryDetails> details(
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new MetricsMemoryDetails(callback));
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  details->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Collect WebCore cache information to put into a histogram.
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (content::RenderProcessHost::iterator i(
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          content::RenderProcessHost::AllHostsIterator());
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       !i.IsAtEnd(); i.Advance()) {
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats());
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_ptr<metrics::MetricsLogUploader>
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ChromeMetricsServiceClient::CreateUploader(
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& server_url,
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& mime_type,
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::Callback<void(int)>& on_upload_complete) {
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return scoped_ptr<metrics::MetricsLogUploader>(
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new metrics::NetMetricsLogUploader(
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          g_browser_process->system_request_context(), server_url, mime_type,
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          on_upload_complete));
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() {
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // This function should only be called as the callback from an ansynchronous
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // step.
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(waiting_for_collect_final_metrics_step_);
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create a callback_task for OnHistogramSynchronizationDone.
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::Closure callback = base::Bind(
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      &ChromeMetricsServiceClient::OnHistogramSynchronizationDone,
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      weak_ptr_factory_.GetWeakPtr());
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::TimeDelta timeout =
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration);
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(num_async_histogram_fetches_in_progress_, 0);
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_ANDROID)
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Android has no service process.
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  num_async_histogram_fetches_in_progress_ = 1;
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else  // OS_ANDROID
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  num_async_histogram_fetches_in_progress_ = 2;
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Run requests to service and content in parallel.
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!ServiceProcessControl::GetInstance()->GetHistograms(callback, timeout)) {
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Assume |num_async_histogram_fetches_in_progress_| is not changed by
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // |GetHistograms()|.
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK_EQ(num_async_histogram_fetches_in_progress_, 2);
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Assign |num_async_histogram_fetches_in_progress_| above and decrement it
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // here to make code work even if |GetHistograms()| fired |callback|.
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    --num_async_histogram_fetches_in_progress_;
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  // OS_ANDROID
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set up the callback to task to call after we receive histograms from all
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // child processes. |timeout| specifies how long to wait before absolutely
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // calling us back on the task.
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  content::FetchHistogramsAsynchronously(base::MessageLoop::current(), callback,
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         timeout);
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::OnHistogramSynchronizationDone() {
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // This function should only be called as the callback from an ansynchronous
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // step.
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(waiting_for_collect_final_metrics_step_);
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_GT(num_async_histogram_fetches_in_progress_, 0);
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check if all expected requests finished.
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (--num_async_histogram_fetches_in_progress_ > 0)
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  waiting_for_collect_final_metrics_step_ = false;
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  collect_final_metrics_done_callback_.Run();
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::RecordCommandLineMetrics() {
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get stats on use of command line.
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const CommandLine* command_line(CommandLine::ForCurrentProcess());
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t common_commands = 0;
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (command_line->HasSwitch(switches::kUserDataDir)) {
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ++common_commands;
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1);
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (command_line->HasSwitch(switches::kApp)) {
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ++common_commands;
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1);
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(rohitrao): Should these be logged on iOS as well?
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // http://crbug.com/375794
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t switch_count = command_line->GetSwitches().size();
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count);
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           switch_count - common_commands);
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::RegisterForNotifications() {
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllBrowserContextsAndSources());
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED,
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING,
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_LOAD_START,
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 content::NotificationService::AllSources());
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::Observe(
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int type,
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const content::NotificationSource& source,
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const content::NotificationDetails& details) {
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (type) {
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::NOTIFICATION_BROWSER_OPENED:
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::NOTIFICATION_BROWSER_CLOSED:
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::NOTIFICATION_TAB_PARENTED:
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case chrome::NOTIFICATION_TAB_CLOSING:
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case content::NOTIFICATION_LOAD_STOP:
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case content::NOTIFICATION_LOAD_START:
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case content::NOTIFICATION_RENDERER_PROCESS_CLOSED:
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      metrics_service_->OnApplicationNotIdle();
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    default:
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NOTREACHED();
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_WIN)
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeMetricsServiceClient::CountBrowserCrashDumpAttempts() {
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Open the registry key for iteration.
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::win::RegKey regkey;
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (regkey.Open(HKEY_CURRENT_USER,
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  chrome::kBrowserCrashDumpAttemptsRegistryPath,
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  KEY_ALL_ACCESS) != ERROR_SUCCESS) {
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The values we're interested in counting are all prefixed with the version.
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::string16 chrome_version(base::ASCIIToUTF16(chrome::kChromeVersion));
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Track a list of values to delete. We don't modify the registry key while
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we're iterating over its values.
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  typedef std::vector<base::string16> StringVector;
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StringVector to_delete;
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Iterate over the values in the key counting dumps with and without crashes.
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We directly walk the values instead of using RegistryValueIterator in order
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // to read all of the values as DWORDS instead of strings.
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::string16 name;
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DWORD value = 0;
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int dumps_with_crash = 0;
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int dumps_with_no_crash = 0;
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int i = regkey.GetValueCount() - 1; i >= 0; --i) {
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (regkey.GetValueNameAt(i, &name) == ERROR_SUCCESS &&
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        StartsWith(name, chrome_version, false) &&
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        regkey.ReadValueDW(name.c_str(), &value) == ERROR_SUCCESS) {
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      to_delete.push_back(name);
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (value == 0)
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ++dumps_with_no_crash;
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      else
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ++dumps_with_crash;
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Delete the registry keys we've just counted.
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (StringVector::iterator i = to_delete.begin(); i != to_delete.end(); ++i)
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    regkey.DeleteValue(i->c_str());
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Capture the histogram samples.
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (dumps_with_crash != 0)
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithCrash", dumps_with_crash);
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (dumps_with_no_crash != 0)
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithNoCrash", dumps_with_no_crash);
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int total_dumps = dumps_with_crash + dumps_with_no_crash;
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (total_dumps != 0)
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("Chrome.BrowserCrashDumpAttempts", total_dumps);
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  // defined(OS_WIN)
420