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