Remove 'RemoveTrailingSeparators' function from SimpleMenuModel
[chromium-blink-merge.git] / chrome / browser / metrics / chrome_metrics_service_client.cc
blob39354d11b969d73c83df3ae859b83e14a9e850ab
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/metrics/chrome_metrics_service_client.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_registry_simple.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string16.h"
19 #include "base/threading/platform_thread.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/google/google_brand.h"
23 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
24 #include "chrome/browser/metrics/drive_metrics_provider.h"
25 #include "chrome/browser/metrics/omnibox_metrics_provider.h"
26 #include "chrome/browser/metrics/time_ticks_experiment_win.h"
27 #include "chrome/browser/ui/browser_otr_state.h"
28 #include "chrome/common/chrome_constants.h"
29 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/crash_keys.h"
31 #include "chrome/common/metrics/version_utils.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/common/render_messages.h"
34 #include "components/metrics/call_stack_profile_metrics_provider.h"
35 #include "components/metrics/gpu/gpu_metrics_provider.h"
36 #include "components/metrics/metrics_service.h"
37 #include "components/metrics/net/net_metrics_log_uploader.h"
38 #include "components/metrics/net/network_metrics_provider.h"
39 #include "components/metrics/profiler/profiler_metrics_provider.h"
40 #include "components/metrics/profiler/tracking_synchronizer.h"
41 #include "components/metrics/url_constants.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/histogram_fetcher.h"
44 #include "content/public/browser/notification_service.h"
45 #include "content/public/browser/render_process_host.h"
47 #if defined(OS_ANDROID)
48 #include "chrome/browser/metrics/android_metrics_provider.h"
49 #endif
51 #if defined(ENABLE_PRINT_PREVIEW)
52 #include "chrome/browser/service_process/service_process_control.h"
53 #endif
55 #if defined(ENABLE_EXTENSIONS)
56 #include "chrome/browser/metrics/extensions_metrics_provider.h"
57 #endif
59 #if defined(ENABLE_PLUGINS)
60 #include "chrome/browser/metrics/plugin_metrics_provider.h"
61 #endif
63 #if defined(OS_CHROMEOS)
64 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
65 #include "chrome/browser/metrics/signin_status_metrics_provider_chromeos.h"
66 #endif
68 #if defined(OS_WIN)
69 #include <windows.h>
70 #include "chrome/browser/metrics/google_update_metrics_provider_win.h"
71 #include "components/browser_watcher/watcher_metrics_provider_win.h"
72 #endif
74 #if !defined(OS_CHROMEOS) && !defined(OS_IOS)
75 #include "chrome/browser/metrics/signin_status_metrics_provider.h"
76 #endif // !defined(OS_CHROMEOS) && !defined(OS_IOS)
78 namespace {
80 // This specifies the amount of time to wait for all renderers to send their
81 // data.
82 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds.
84 // Standard interval between log uploads, in seconds.
85 #if defined(OS_ANDROID) || defined(OS_IOS)
86 const int kStandardUploadIntervalSeconds = 5 * 60; // Five minutes.
87 const int kStandardUploadIntervalCellularSeconds = 15 * 60; // Fifteen minutes.
88 #else
89 const int kStandardUploadIntervalSeconds = 30 * 60; // Thirty minutes.
90 #endif
92 #if defined(OS_ANDROID) || defined(OS_IOS)
93 // Returns true if the user is assigned to the experiment group for enabled
94 // cellular uploads.
95 bool IsCellularEnabledByExperiment() {
96 const std::string group_name =
97 base::FieldTrialList::FindFullName("UMA_EnableCellularLogUpload");
98 return group_name == "Enabled";
100 #endif
102 } // namespace
104 ChromeMetricsServiceClient::ChromeMetricsServiceClient(
105 metrics::MetricsStateManager* state_manager)
106 : metrics_state_manager_(state_manager),
107 chromeos_metrics_provider_(nullptr),
108 waiting_for_collect_final_metrics_step_(false),
109 num_async_histogram_fetches_in_progress_(0),
110 profiler_metrics_provider_(nullptr),
111 #if defined(ENABLE_PLUGINS)
112 plugin_metrics_provider_(nullptr),
113 #endif
114 #if defined(OS_WIN)
115 google_update_metrics_provider_(nullptr),
116 #endif
117 drive_metrics_provider_(nullptr),
118 weak_ptr_factory_(this) {
119 DCHECK(thread_checker_.CalledOnValidThread());
120 RecordCommandLineMetrics();
121 RegisterForNotifications();
124 ChromeMetricsServiceClient::~ChromeMetricsServiceClient() {
125 DCHECK(thread_checker_.CalledOnValidThread());
128 // static
129 scoped_ptr<ChromeMetricsServiceClient> ChromeMetricsServiceClient::Create(
130 metrics::MetricsStateManager* state_manager,
131 PrefService* local_state) {
132 // Perform two-phase initialization so that |client->metrics_service_| only
133 // receives pointers to fully constructed objects.
134 scoped_ptr<ChromeMetricsServiceClient> client(
135 new ChromeMetricsServiceClient(state_manager));
136 client->Initialize();
138 return client.Pass();
141 // static
142 void ChromeMetricsServiceClient::RegisterPrefs(PrefRegistrySimple* registry) {
143 registry->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0);
144 registry->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0);
146 metrics::MetricsService::RegisterPrefs(registry);
147 ChromeStabilityMetricsProvider::RegisterPrefs(registry);
149 #if defined(OS_ANDROID)
150 AndroidMetricsProvider::RegisterPrefs(registry);
151 #endif // defined(OS_ANDROID)
153 #if defined(ENABLE_PLUGINS)
154 PluginMetricsProvider::RegisterPrefs(registry);
155 #endif // defined(ENABLE_PLUGINS)
158 void ChromeMetricsServiceClient::SetMetricsClientId(
159 const std::string& client_id) {
160 crash_keys::SetMetricsClientIdFromGUID(client_id);
163 void ChromeMetricsServiceClient::OnRecordingDisabled() {
164 crash_keys::ClearMetricsClientId();
167 bool ChromeMetricsServiceClient::IsOffTheRecordSessionActive() {
168 return chrome::IsOffTheRecordSessionActive();
171 int32 ChromeMetricsServiceClient::GetProduct() {
172 return metrics::ChromeUserMetricsExtension::CHROME;
175 std::string ChromeMetricsServiceClient::GetApplicationLocale() {
176 return g_browser_process->GetApplicationLocale();
179 bool ChromeMetricsServiceClient::GetBrand(std::string* brand_code) {
180 return google_brand::GetBrand(brand_code);
183 metrics::SystemProfileProto::Channel ChromeMetricsServiceClient::GetChannel() {
184 return metrics::AsProtobufChannel(chrome::VersionInfo::GetChannel());
187 std::string ChromeMetricsServiceClient::GetVersionString() {
188 return metrics::GetVersionString();
191 void ChromeMetricsServiceClient::OnLogUploadComplete() {
192 // Collect time ticks stats after each UMA upload.
193 #if defined(OS_WIN)
194 chrome::CollectTimeTicksStats();
195 #endif
198 void ChromeMetricsServiceClient::StartGatheringMetrics(
199 const base::Closure& done_callback) {
200 finished_gathering_initial_metrics_callback_ = done_callback;
201 base::Closure got_hardware_class_callback =
202 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotHardwareClass,
203 weak_ptr_factory_.GetWeakPtr());
204 #if defined(OS_CHROMEOS)
205 chromeos_metrics_provider_->InitTaskGetHardwareClass(
206 got_hardware_class_callback);
207 #else
208 got_hardware_class_callback.Run();
209 #endif // defined(OS_CHROMEOS)
212 void ChromeMetricsServiceClient::CollectFinalMetrics(
213 const base::Closure& done_callback) {
214 DCHECK(thread_checker_.CalledOnValidThread());
216 collect_final_metrics_done_callback_ = done_callback;
218 // Begin the multi-step process of collecting memory usage histograms:
219 // First spawn a task to collect the memory details; when that task is
220 // finished, it will call OnMemoryDetailCollectionDone. That will in turn
221 // call HistogramSynchronization to collect histograms from all renderers and
222 // then call OnHistogramSynchronizationDone to continue processing.
223 DCHECK(!waiting_for_collect_final_metrics_step_);
224 waiting_for_collect_final_metrics_step_ = true;
226 base::Closure callback =
227 base::Bind(&ChromeMetricsServiceClient::OnMemoryDetailCollectionDone,
228 weak_ptr_factory_.GetWeakPtr());
230 scoped_refptr<MetricsMemoryDetails> details(
231 new MetricsMemoryDetails(callback, &memory_growth_tracker_));
232 details->StartFetch(MemoryDetails::FROM_CHROME_ONLY);
234 // Collect WebCore cache information to put into a histogram.
235 for (content::RenderProcessHost::iterator i(
236 content::RenderProcessHost::AllHostsIterator());
237 !i.IsAtEnd(); i.Advance()) {
238 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats());
242 scoped_ptr<metrics::MetricsLogUploader>
243 ChromeMetricsServiceClient::CreateUploader(
244 const base::Callback<void(int)>& on_upload_complete) {
245 return scoped_ptr<metrics::MetricsLogUploader>(
246 new metrics::NetMetricsLogUploader(
247 g_browser_process->system_request_context(),
248 metrics::kDefaultMetricsServerUrl,
249 metrics::kDefaultMetricsMimeType,
250 on_upload_complete));
253 base::TimeDelta ChromeMetricsServiceClient::GetStandardUploadInterval() {
254 #if defined(OS_ANDROID) || defined(OS_IOS)
255 bool is_cellular = false;
256 cellular_callback_.Run(&is_cellular);
258 if (is_cellular && IsCellularEnabledByExperiment())
259 return base::TimeDelta::FromSeconds(kStandardUploadIntervalCellularSeconds);
260 #endif
261 return base::TimeDelta::FromSeconds(kStandardUploadIntervalSeconds);
264 base::string16 ChromeMetricsServiceClient::GetRegistryBackupKey() {
265 #if defined(OS_WIN)
266 return L"Software\\" PRODUCT_STRING_PATH L"\\StabilityMetrics";
267 #else
268 return base::string16();
269 #endif
272 void ChromeMetricsServiceClient::LogPluginLoadingError(
273 const base::FilePath& plugin_path) {
274 #if defined(ENABLE_PLUGINS)
275 plugin_metrics_provider_->LogPluginLoadingError(plugin_path);
276 #else
277 NOTREACHED();
278 #endif // defined(ENABLE_PLUGINS)
281 void ChromeMetricsServiceClient::Initialize() {
282 metrics_service_.reset(new metrics::MetricsService(
283 metrics_state_manager_, this, g_browser_process->local_state()));
285 // Register metrics providers.
286 #if defined(ENABLE_EXTENSIONS)
287 metrics_service_->RegisterMetricsProvider(
288 scoped_ptr<metrics::MetricsProvider>(
289 new ExtensionsMetricsProvider(metrics_state_manager_)));
290 #endif
291 scoped_ptr<metrics::NetworkMetricsProvider> network_metrics_provider(
292 new metrics::NetworkMetricsProvider(
293 content::BrowserThread::GetBlockingPool()));
294 cellular_callback_ = network_metrics_provider->GetConnectionCallback();
295 metrics_service_->RegisterMetricsProvider(network_metrics_provider.Pass());
297 metrics_service_->RegisterMetricsProvider(
298 scoped_ptr<metrics::MetricsProvider>(new OmniboxMetricsProvider));
299 metrics_service_->RegisterMetricsProvider(
300 scoped_ptr<metrics::MetricsProvider>(new ChromeStabilityMetricsProvider));
301 metrics_service_->RegisterMetricsProvider(
302 scoped_ptr<metrics::MetricsProvider>(new metrics::GPUMetricsProvider));
304 drive_metrics_provider_ = new DriveMetricsProvider;
305 metrics_service_->RegisterMetricsProvider(
306 scoped_ptr<metrics::MetricsProvider>(drive_metrics_provider_));
308 profiler_metrics_provider_ =
309 new metrics::ProfilerMetricsProvider(cellular_callback_);
310 metrics_service_->RegisterMetricsProvider(
311 scoped_ptr<metrics::MetricsProvider>(profiler_metrics_provider_));
313 metrics_service_->RegisterMetricsProvider(
314 scoped_ptr<metrics::MetricsProvider>(
315 new metrics::CallStackProfileMetricsProvider));
317 #if defined(OS_ANDROID)
318 metrics_service_->RegisterMetricsProvider(
319 scoped_ptr<metrics::MetricsProvider>(
320 new AndroidMetricsProvider(g_browser_process->local_state())));
321 #endif // defined(OS_ANDROID)
323 #if defined(OS_WIN)
324 google_update_metrics_provider_ = new GoogleUpdateMetricsProviderWin;
325 metrics_service_->RegisterMetricsProvider(
326 scoped_ptr<metrics::MetricsProvider>(google_update_metrics_provider_));
328 // Report exit funnels for canary and dev only.
329 bool report_exit_funnels = false;
330 switch (chrome::VersionInfo::GetChannel()) {
331 case chrome::VersionInfo::CHANNEL_CANARY:
332 case chrome::VersionInfo::CHANNEL_DEV:
333 report_exit_funnels = true;
334 break;
337 metrics_service_->RegisterMetricsProvider(
338 scoped_ptr<metrics::MetricsProvider>(
339 new browser_watcher::WatcherMetricsProviderWin(
340 chrome::kBrowserExitCodesRegistryPath, report_exit_funnels)));
341 #endif // defined(OS_WIN)
343 #if defined(ENABLE_PLUGINS)
344 plugin_metrics_provider_ =
345 new PluginMetricsProvider(g_browser_process->local_state());
346 metrics_service_->RegisterMetricsProvider(
347 scoped_ptr<metrics::MetricsProvider>(plugin_metrics_provider_));
348 #endif // defined(ENABLE_PLUGINS)
350 #if defined(OS_CHROMEOS)
351 ChromeOSMetricsProvider* chromeos_metrics_provider =
352 new ChromeOSMetricsProvider;
353 chromeos_metrics_provider_ = chromeos_metrics_provider;
354 metrics_service_->RegisterMetricsProvider(
355 scoped_ptr<metrics::MetricsProvider>(chromeos_metrics_provider));
357 SigninStatusMetricsProviderChromeOS* signin_metrics_provider_cros =
358 new SigninStatusMetricsProviderChromeOS;
359 metrics_service_->RegisterMetricsProvider(
360 scoped_ptr<metrics::MetricsProvider>(signin_metrics_provider_cros));
361 #endif // defined(OS_CHROMEOS)
363 #if !defined(OS_CHROMEOS) && !defined(OS_IOS)
364 metrics_service_->RegisterMetricsProvider(
365 scoped_ptr<metrics::MetricsProvider>(
366 SigninStatusMetricsProvider::CreateInstance()));
367 #endif // !defined(OS_CHROMEOS) && !defined(OS_IOS)
370 void ChromeMetricsServiceClient::OnInitTaskGotHardwareClass() {
371 const base::Closure got_plugin_info_callback =
372 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotPluginInfo,
373 weak_ptr_factory_.GetWeakPtr());
375 #if defined(ENABLE_PLUGINS)
376 plugin_metrics_provider_->GetPluginInformation(got_plugin_info_callback);
377 #else
378 got_plugin_info_callback.Run();
379 #endif // defined(ENABLE_PLUGINS)
382 void ChromeMetricsServiceClient::OnInitTaskGotPluginInfo() {
383 const base::Closure got_metrics_callback =
384 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData,
385 weak_ptr_factory_.GetWeakPtr());
387 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
388 google_update_metrics_provider_->GetGoogleUpdateData(got_metrics_callback);
389 #else
390 got_metrics_callback.Run();
391 #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
394 void ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData() {
395 // Start the next part of the init task: fetching performance data. This will
396 // call into |FinishedReceivingProfilerData()| when the task completes.
397 metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously(
398 weak_ptr_factory_.GetWeakPtr());
401 // TODO(vadimt): Consider wrapping params in a struct after the list of params
402 // to ReceivedProfilerData settles. crbug/456354.
403 void ChromeMetricsServiceClient::ReceivedProfilerData(
404 const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase,
405 base::ProcessId process_id,
406 content::ProcessType process_type,
407 int profiling_phase,
408 base::TimeDelta phase_start,
409 base::TimeDelta phase_finish,
410 const metrics::ProfilerEvents& past_events) {
411 profiler_metrics_provider_->RecordProfilerData(
412 process_data_phase, process_id, process_type, profiling_phase,
413 phase_start, phase_finish, past_events);
416 void ChromeMetricsServiceClient::FinishedReceivingProfilerData() {
417 drive_metrics_provider_->GetDriveMetrics(
418 finished_gathering_initial_metrics_callback_);
421 void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() {
422 DCHECK(thread_checker_.CalledOnValidThread());
424 // This function should only be called as the callback from an ansynchronous
425 // step.
426 DCHECK(waiting_for_collect_final_metrics_step_);
428 // Create a callback_task for OnHistogramSynchronizationDone.
429 base::Closure callback = base::Bind(
430 &ChromeMetricsServiceClient::OnHistogramSynchronizationDone,
431 weak_ptr_factory_.GetWeakPtr());
433 base::TimeDelta timeout =
434 base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration);
436 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 0);
438 #if !defined(ENABLE_PRINT_PREVIEW)
439 num_async_histogram_fetches_in_progress_ = 1;
440 #else // !ENABLE_PRINT_PREVIEW
441 num_async_histogram_fetches_in_progress_ = 2;
442 // Run requests to service and content in parallel.
443 if (!ServiceProcessControl::GetInstance()->GetHistograms(callback, timeout)) {
444 // Assume |num_async_histogram_fetches_in_progress_| is not changed by
445 // |GetHistograms()|.
446 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 2);
447 // Assign |num_async_histogram_fetches_in_progress_| above and decrement it
448 // here to make code work even if |GetHistograms()| fired |callback|.
449 --num_async_histogram_fetches_in_progress_;
451 #endif // !ENABLE_PRINT_PREVIEW
453 // Set up the callback to task to call after we receive histograms from all
454 // child processes. |timeout| specifies how long to wait before absolutely
455 // calling us back on the task.
456 content::FetchHistogramsAsynchronously(base::MessageLoop::current(), callback,
457 timeout);
460 void ChromeMetricsServiceClient::OnHistogramSynchronizationDone() {
461 DCHECK(thread_checker_.CalledOnValidThread());
463 // This function should only be called as the callback from an ansynchronous
464 // step.
465 DCHECK(waiting_for_collect_final_metrics_step_);
466 DCHECK_GT(num_async_histogram_fetches_in_progress_, 0);
468 // Check if all expected requests finished.
469 if (--num_async_histogram_fetches_in_progress_ > 0)
470 return;
472 waiting_for_collect_final_metrics_step_ = false;
473 collect_final_metrics_done_callback_.Run();
476 void ChromeMetricsServiceClient::RecordCommandLineMetrics() {
477 // Get stats on use of command line.
478 const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
479 size_t common_commands = 0;
480 if (command_line->HasSwitch(switches::kUserDataDir)) {
481 ++common_commands;
482 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1);
485 if (command_line->HasSwitch(switches::kApp)) {
486 ++common_commands;
487 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1);
490 // TODO(rohitrao): Should these be logged on iOS as well?
491 // http://crbug.com/375794
492 size_t switch_count = command_line->GetSwitches().size();
493 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count);
494 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
495 switch_count - common_commands);
498 void ChromeMetricsServiceClient::RegisterForNotifications() {
499 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
500 content::NotificationService::AllBrowserContextsAndSources());
501 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
502 content::NotificationService::AllSources());
503 registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED,
504 content::NotificationService::AllSources());
505 registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING,
506 content::NotificationService::AllSources());
507 registrar_.Add(this, content::NOTIFICATION_LOAD_START,
508 content::NotificationService::AllSources());
509 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
510 content::NotificationService::AllSources());
511 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
512 content::NotificationService::AllSources());
513 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
514 content::NotificationService::AllSources());
515 registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
516 content::NotificationService::AllSources());
519 void ChromeMetricsServiceClient::Observe(
520 int type,
521 const content::NotificationSource& source,
522 const content::NotificationDetails& details) {
523 DCHECK(thread_checker_.CalledOnValidThread());
525 switch (type) {
526 case chrome::NOTIFICATION_BROWSER_OPENED:
527 case chrome::NOTIFICATION_BROWSER_CLOSED:
528 case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
529 case chrome::NOTIFICATION_TAB_PARENTED:
530 case chrome::NOTIFICATION_TAB_CLOSING:
531 case content::NOTIFICATION_LOAD_STOP:
532 case content::NOTIFICATION_LOAD_START:
533 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED:
534 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
535 metrics_service_->OnApplicationNotIdle();
536 break;
538 default:
539 NOTREACHED();