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"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/prefs/pref_registry_simple.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/strings/string16.h"
18 #include "base/threading/platform_thread.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chrome_notification_types.h"
21 #include "chrome/browser/google/google_brand.h"
22 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
23 #include "chrome/browser/metrics/omnibox_metrics_provider.h"
24 #include "chrome/browser/metrics/time_ticks_experiment_win.h"
25 #include "chrome/browser/process_resource_usage.h"
26 #include "chrome/browser/ui/browser_otr_state.h"
27 #include "chrome/common/channel_info.h"
28 #include "chrome/common/chrome_constants.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/crash_keys.h"
32 #include "chrome/common/metrics/version_utils.h"
33 #include "chrome/common/pref_names.h"
34 #include "components/metrics/call_stack_profile_metrics_provider.h"
35 #include "components/metrics/drive_metrics_provider.h"
36 #include "components/metrics/gpu/gpu_metrics_provider.h"
37 #include "components/metrics/metrics_service.h"
38 #include "components/metrics/net/net_metrics_log_uploader.h"
39 #include "components/metrics/net/network_metrics_provider.h"
40 #include "components/metrics/profiler/profiler_metrics_provider.h"
41 #include "components/metrics/profiler/tracking_synchronizer.h"
42 #include "components/metrics/url_constants.h"
43 #include "components/variations/variations_associated_data.h"
44 #include "components/version_info/version_info.h"
45 #include "content/public/browser/browser_thread.h"
46 #include "content/public/browser/histogram_fetcher.h"
47 #include "content/public/browser/notification_service.h"
48 #include "content/public/browser/render_process_host.h"
49 #include "content/public/common/service_registry.h"
51 #if defined(OS_ANDROID)
52 #include "chrome/browser/metrics/android_metrics_provider.h"
55 #if defined(ENABLE_PRINT_PREVIEW)
56 #include "chrome/browser/service_process/service_process_control.h"
59 #if defined(ENABLE_EXTENSIONS)
60 #include "chrome/browser/metrics/extensions_metrics_provider.h"
63 #if defined(ENABLE_PLUGINS)
64 #include "chrome/browser/metrics/plugin_metrics_provider.h"
67 #if defined(OS_CHROMEOS)
68 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
69 #include "chrome/browser/metrics/signin_status_metrics_provider_chromeos.h"
74 #include "chrome/browser/metrics/google_update_metrics_provider_win.h"
75 #include "components/browser_watcher/watcher_metrics_provider_win.h"
78 #if !defined(OS_CHROMEOS)
79 #include "chrome/browser/metrics/signin_status_metrics_provider.h"
80 #endif // !defined(OS_CHROMEOS)
84 // This specifies the amount of time to wait for all renderers to send their
86 const int kMaxHistogramGatheringWaitDuration
= 60000; // 60 seconds.
88 // Standard interval between log uploads, in seconds.
89 #if defined(OS_ANDROID) || defined(OS_IOS)
90 const int kStandardUploadIntervalSeconds
= 5 * 60; // Five minutes.
91 const int kStandardUploadIntervalCellularSeconds
= 15 * 60; // Fifteen minutes.
93 const int kStandardUploadIntervalSeconds
= 30 * 60; // Thirty minutes.
96 // Returns true if current connection type is cellular and user is assigned to
97 // experimental group for enabled cellular uploads.
98 bool IsCellularLogicEnabled() {
99 if (variations::GetVariationParamValue("UMA_EnableCellularLogUpload",
100 "Enabled") != "true" ||
101 variations::GetVariationParamValue("UMA_EnableCellularLogUpload",
102 "Optimize") == "false") {
106 return net::NetworkChangeNotifier::IsConnectionCellular(
107 net::NetworkChangeNotifier::GetConnectionType());
110 // Checks whether it is the first time that cellular uploads logic should be
111 // enabled based on whether the the preference for that logic is initialized.
112 // This should happen only once as the used preference will be initialized
113 // afterwards in |UmaSessionStats.java|.
114 bool ShouldClearSavedMetrics() {
115 #if defined(OS_ANDROID)
116 PrefService
* local_state
= g_browser_process
->local_state();
117 return !local_state
->HasPrefPath(prefs::kMetricsReportingEnabled
) &&
118 variations::GetVariationParamValue("UMA_EnableCellularLogUpload",
119 "Enabled") == "true";
128 ChromeMetricsServiceClient::ChromeMetricsServiceClient(
129 metrics::MetricsStateManager
* state_manager
)
130 : metrics_state_manager_(state_manager
),
131 chromeos_metrics_provider_(nullptr),
132 waiting_for_collect_final_metrics_step_(false),
133 num_async_histogram_fetches_in_progress_(0),
134 profiler_metrics_provider_(nullptr),
135 #if defined(ENABLE_PLUGINS)
136 plugin_metrics_provider_(nullptr),
139 google_update_metrics_provider_(nullptr),
141 drive_metrics_provider_(nullptr),
142 start_time_(base::TimeTicks::Now()),
143 weak_ptr_factory_(this) {
144 DCHECK(thread_checker_
.CalledOnValidThread());
145 RecordCommandLineMetrics();
146 RegisterForNotifications();
149 ChromeMetricsServiceClient::~ChromeMetricsServiceClient() {
150 DCHECK(thread_checker_
.CalledOnValidThread());
154 scoped_ptr
<ChromeMetricsServiceClient
> ChromeMetricsServiceClient::Create(
155 metrics::MetricsStateManager
* state_manager
,
156 PrefService
* local_state
) {
157 // Perform two-phase initialization so that |client->metrics_service_| only
158 // receives pointers to fully constructed objects.
159 scoped_ptr
<ChromeMetricsServiceClient
> client(
160 new ChromeMetricsServiceClient(state_manager
));
161 client
->Initialize();
163 return client
.Pass();
167 void ChromeMetricsServiceClient::RegisterPrefs(PrefRegistrySimple
* registry
) {
168 registry
->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec
, 0);
169 registry
->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec
, 0);
171 metrics::MetricsService::RegisterPrefs(registry
);
172 ChromeStabilityMetricsProvider::RegisterPrefs(registry
);
174 #if defined(OS_ANDROID)
175 AndroidMetricsProvider::RegisterPrefs(registry
);
176 #endif // defined(OS_ANDROID)
178 #if defined(ENABLE_PLUGINS)
179 PluginMetricsProvider::RegisterPrefs(registry
);
180 #endif // defined(ENABLE_PLUGINS)
183 void ChromeMetricsServiceClient::SetMetricsClientId(
184 const std::string
& client_id
) {
185 crash_keys::SetMetricsClientIdFromGUID(client_id
);
188 void ChromeMetricsServiceClient::OnRecordingDisabled() {
189 crash_keys::ClearMetricsClientId();
192 bool ChromeMetricsServiceClient::IsOffTheRecordSessionActive() {
193 return chrome::IsOffTheRecordSessionActive();
196 int32
ChromeMetricsServiceClient::GetProduct() {
197 return metrics::ChromeUserMetricsExtension::CHROME
;
200 std::string
ChromeMetricsServiceClient::GetApplicationLocale() {
201 return g_browser_process
->GetApplicationLocale();
204 bool ChromeMetricsServiceClient::GetBrand(std::string
* brand_code
) {
205 return google_brand::GetBrand(brand_code
);
208 metrics::SystemProfileProto::Channel
ChromeMetricsServiceClient::GetChannel() {
209 return metrics::AsProtobufChannel(chrome::GetChannel());
212 std::string
ChromeMetricsServiceClient::GetVersionString() {
213 return metrics::GetVersionString();
216 void ChromeMetricsServiceClient::OnLogUploadComplete() {
217 // Collect time ticks stats after each UMA upload.
219 chrome::CollectTimeTicksStats();
223 void ChromeMetricsServiceClient::StartGatheringMetrics(
224 const base::Closure
& done_callback
) {
225 finished_gathering_initial_metrics_callback_
= done_callback
;
226 base::Closure got_hardware_class_callback
=
227 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotHardwareClass
,
228 weak_ptr_factory_
.GetWeakPtr());
229 #if defined(OS_CHROMEOS)
230 chromeos_metrics_provider_
->InitTaskGetHardwareClass(
231 got_hardware_class_callback
);
233 got_hardware_class_callback
.Run();
234 #endif // defined(OS_CHROMEOS)
237 void ChromeMetricsServiceClient::CollectFinalMetrics(
238 const base::Closure
& done_callback
) {
239 DCHECK(thread_checker_
.CalledOnValidThread());
241 collect_final_metrics_done_callback_
= done_callback
;
243 // Begin the multi-step process of collecting memory usage histograms:
244 // First spawn a task to collect the memory details; when that task is
245 // finished, it will call OnMemoryDetailCollectionDone. That will in turn
246 // call HistogramSynchronization to collect histograms from all renderers and
247 // then call OnHistogramSynchronizationDone to continue processing.
248 DCHECK(!waiting_for_collect_final_metrics_step_
);
249 waiting_for_collect_final_metrics_step_
= true;
251 base::Closure callback
=
252 base::Bind(&ChromeMetricsServiceClient::OnMemoryDetailCollectionDone
,
253 weak_ptr_factory_
.GetWeakPtr());
255 scoped_refptr
<MetricsMemoryDetails
> details(
256 new MetricsMemoryDetails(callback
, &memory_growth_tracker_
));
257 details
->StartFetch(MemoryDetails::FROM_CHROME_ONLY
);
259 base::ScopedPtrMap
<int, scoped_ptr
<ProcessResourceUsage
>> current_map
;
260 host_resource_usage_map_
.swap(current_map
);
262 // Collect WebCore cache information to put into a histogram.
263 for (content::RenderProcessHost::iterator
i(
264 content::RenderProcessHost::AllHostsIterator());
265 !i
.IsAtEnd(); i
.Advance()) {
266 content::RenderProcessHost
* host
= i
.GetCurrentValue();
267 int host_id
= host
->GetID();
268 ProcessResourceUsage
* resource_usage
= nullptr;
269 auto iter
= current_map
.find(host_id
);
270 if (iter
!= current_map
.end()) {
271 resource_usage
= iter
->second
;
272 host_resource_usage_map_
.set(host_id
, current_map
.take_and_erase(iter
));
274 content::ServiceRegistry
* service_registry
= host
->GetServiceRegistry();
275 if (service_registry
) {
276 ResourceUsageReporterPtr service
;
277 service_registry
->ConnectToRemoteService(mojo::GetProxy(&service
));
278 resource_usage
= new ProcessResourceUsage(service
.Pass());
279 host_resource_usage_map_
.set(host_id
, make_scoped_ptr(resource_usage
));
282 if (resource_usage
) {
283 resource_usage
->Refresh(
284 base::Bind(&ChromeMetricsServiceClient::OnWebCacheStatsRefresh
,
285 weak_ptr_factory_
.GetWeakPtr(), host_id
));
290 scoped_ptr
<metrics::MetricsLogUploader
>
291 ChromeMetricsServiceClient::CreateUploader(
292 const base::Callback
<void(int)>& on_upload_complete
) {
293 return scoped_ptr
<metrics::MetricsLogUploader
>(
294 new metrics::NetMetricsLogUploader(
295 g_browser_process
->system_request_context(),
296 metrics::kDefaultMetricsServerUrl
,
297 metrics::kDefaultMetricsMimeType
,
298 on_upload_complete
));
301 base::TimeDelta
ChromeMetricsServiceClient::GetStandardUploadInterval() {
302 #if defined(OS_ANDROID) || defined(OS_IOS)
303 if (IsCellularLogicEnabled())
304 return base::TimeDelta::FromSeconds(kStandardUploadIntervalCellularSeconds
);
306 return base::TimeDelta::FromSeconds(kStandardUploadIntervalSeconds
);
309 base::string16
ChromeMetricsServiceClient::GetRegistryBackupKey() {
311 return L
"Software\\" PRODUCT_STRING_PATH L
"\\StabilityMetrics";
313 return base::string16();
317 void ChromeMetricsServiceClient::LogPluginLoadingError(
318 const base::FilePath
& plugin_path
) {
319 #if defined(ENABLE_PLUGINS)
320 plugin_metrics_provider_
->LogPluginLoadingError(plugin_path
);
323 #endif // defined(ENABLE_PLUGINS)
326 void ChromeMetricsServiceClient::Initialize() {
327 // Clear metrics reports if it is the first time cellular upload logic should
328 // apply to avoid sudden bulk uploads. It needs to be done before initializing
329 // metrics service so that metrics log manager is initialized correctly.
330 if (ShouldClearSavedMetrics()) {
331 PrefService
* local_state
= g_browser_process
->local_state();
332 local_state
->ClearPref(metrics::prefs::kMetricsInitialLogs
);
333 local_state
->ClearPref(metrics::prefs::kMetricsOngoingLogs
);
336 metrics_service_
.reset(new metrics::MetricsService(
337 metrics_state_manager_
, this, g_browser_process
->local_state()));
339 // Register metrics providers.
340 #if defined(ENABLE_EXTENSIONS)
341 metrics_service_
->RegisterMetricsProvider(
342 scoped_ptr
<metrics::MetricsProvider
>(
343 new ExtensionsMetricsProvider(metrics_state_manager_
)));
345 metrics_service_
->RegisterMetricsProvider(
346 scoped_ptr
<metrics::MetricsProvider
>(new metrics::NetworkMetricsProvider(
347 content::BrowserThread::GetBlockingPool())));
349 // Currently, we configure OmniboxMetricsProvider to not log events to UMA
350 // if there is a single incognito session visible. In the future, it may
351 // be worth revisiting this to still log events from non-incognito sessions.
352 metrics_service_
->RegisterMetricsProvider(
353 scoped_ptr
<metrics::MetricsProvider
>(new OmniboxMetricsProvider(
354 base::Bind(&chrome::IsOffTheRecordSessionActive
))));
355 metrics_service_
->RegisterMetricsProvider(
356 scoped_ptr
<metrics::MetricsProvider
>(new ChromeStabilityMetricsProvider
));
357 metrics_service_
->RegisterMetricsProvider(
358 scoped_ptr
<metrics::MetricsProvider
>(new metrics::GPUMetricsProvider
));
360 drive_metrics_provider_
= new metrics::DriveMetricsProvider(
361 content::BrowserThread::GetMessageLoopProxyForThread(
362 content::BrowserThread::FILE),
363 chrome::FILE_LOCAL_STATE
);
364 metrics_service_
->RegisterMetricsProvider(
365 scoped_ptr
<metrics::MetricsProvider
>(drive_metrics_provider_
));
367 profiler_metrics_provider_
=
368 new metrics::ProfilerMetricsProvider(base::Bind(&IsCellularLogicEnabled
));
369 metrics_service_
->RegisterMetricsProvider(
370 scoped_ptr
<metrics::MetricsProvider
>(profiler_metrics_provider_
));
372 metrics_service_
->RegisterMetricsProvider(
373 scoped_ptr
<metrics::MetricsProvider
>(
374 new metrics::CallStackProfileMetricsProvider
));
376 #if defined(OS_ANDROID)
377 metrics_service_
->RegisterMetricsProvider(
378 scoped_ptr
<metrics::MetricsProvider
>(
379 new AndroidMetricsProvider(g_browser_process
->local_state())));
380 #endif // defined(OS_ANDROID)
383 google_update_metrics_provider_
= new GoogleUpdateMetricsProviderWin
;
384 metrics_service_
->RegisterMetricsProvider(
385 scoped_ptr
<metrics::MetricsProvider
>(google_update_metrics_provider_
));
387 // Report exit funnels for canary and dev only.
388 bool report_exit_funnels
= false;
389 switch (chrome::GetChannel()) {
390 case version_info::Channel::CANARY
:
391 case version_info::Channel::DEV
:
392 report_exit_funnels
= true;
396 metrics_service_
->RegisterMetricsProvider(
397 scoped_ptr
<metrics::MetricsProvider
>(
398 new browser_watcher::WatcherMetricsProviderWin(
399 chrome::kBrowserExitCodesRegistryPath
, report_exit_funnels
)));
400 #endif // defined(OS_WIN)
402 #if defined(ENABLE_PLUGINS)
403 plugin_metrics_provider_
=
404 new PluginMetricsProvider(g_browser_process
->local_state());
405 metrics_service_
->RegisterMetricsProvider(
406 scoped_ptr
<metrics::MetricsProvider
>(plugin_metrics_provider_
));
407 #endif // defined(ENABLE_PLUGINS)
409 #if defined(OS_CHROMEOS)
410 ChromeOSMetricsProvider
* chromeos_metrics_provider
=
411 new ChromeOSMetricsProvider
;
412 chromeos_metrics_provider_
= chromeos_metrics_provider
;
413 metrics_service_
->RegisterMetricsProvider(
414 scoped_ptr
<metrics::MetricsProvider
>(chromeos_metrics_provider
));
416 SigninStatusMetricsProviderChromeOS
* signin_metrics_provider_cros
=
417 new SigninStatusMetricsProviderChromeOS
;
418 metrics_service_
->RegisterMetricsProvider(
419 scoped_ptr
<metrics::MetricsProvider
>(signin_metrics_provider_cros
));
420 #endif // defined(OS_CHROMEOS)
422 #if !defined(OS_CHROMEOS)
423 metrics_service_
->RegisterMetricsProvider(
424 scoped_ptr
<metrics::MetricsProvider
>(
425 SigninStatusMetricsProvider::CreateInstance()));
426 #endif // !defined(OS_CHROMEOS)
428 // Clear stability metrics if it is the first time cellular upload logic
429 // should apply to avoid sudden bulk uploads. It needs to be done after all
430 // providers are registered.
431 if (ShouldClearSavedMetrics())
432 metrics_service_
->ClearSavedStabilityMetrics();
435 void ChromeMetricsServiceClient::OnInitTaskGotHardwareClass() {
436 const base::Closure got_plugin_info_callback
=
437 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotPluginInfo
,
438 weak_ptr_factory_
.GetWeakPtr());
440 #if defined(ENABLE_PLUGINS)
441 plugin_metrics_provider_
->GetPluginInformation(got_plugin_info_callback
);
443 got_plugin_info_callback
.Run();
444 #endif // defined(ENABLE_PLUGINS)
447 void ChromeMetricsServiceClient::OnInitTaskGotPluginInfo() {
448 const base::Closure got_metrics_callback
=
449 base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData
,
450 weak_ptr_factory_
.GetWeakPtr());
452 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
453 google_update_metrics_provider_
->GetGoogleUpdateData(got_metrics_callback
);
455 got_metrics_callback
.Run();
456 #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
459 void ChromeMetricsServiceClient::OnInitTaskGotGoogleUpdateData() {
460 // Start the next part of the init task: fetching performance data. This will
461 // call into |FinishedReceivingProfilerData()| when the task completes.
462 metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously(
463 weak_ptr_factory_
.GetWeakPtr());
466 void ChromeMetricsServiceClient::OnWebCacheStatsRefresh(int host_id
) {
467 DCHECK(thread_checker_
.CalledOnValidThread());
469 auto iter
= host_resource_usage_map_
.find(host_id
);
470 if (iter
!= host_resource_usage_map_
.end()) {
471 blink::WebCache::ResourceTypeStats stats
=
472 iter
->second
->GetWebCoreCacheStats();
473 LOCAL_HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB",
474 static_cast<int>(stats
.images
.size
/ 1024));
475 LOCAL_HISTOGRAM_COUNTS("WebCoreCache.CSSStylesheetsSizeKB",
476 static_cast<int>(stats
.cssStyleSheets
.size
/ 1024));
477 LOCAL_HISTOGRAM_COUNTS("WebCoreCache.ScriptsSizeKB",
478 static_cast<int>(stats
.scripts
.size
/ 1024));
479 LOCAL_HISTOGRAM_COUNTS("WebCoreCache.XSLStylesheetsSizeKB",
480 static_cast<int>(stats
.xslStyleSheets
.size
/ 1024));
481 LOCAL_HISTOGRAM_COUNTS("WebCoreCache.FontsSizeKB",
482 static_cast<int>(stats
.fonts
.size
/ 1024));
486 void ChromeMetricsServiceClient::ReceivedProfilerData(
487 const metrics::ProfilerDataAttributes
& attributes
,
488 const tracked_objects::ProcessDataPhaseSnapshot
& process_data_phase
,
489 const metrics::ProfilerEvents
& past_events
) {
490 profiler_metrics_provider_
->RecordProfilerData(
491 process_data_phase
, attributes
.process_id
, attributes
.process_type
,
492 attributes
.profiling_phase
, attributes
.phase_start
- start_time_
,
493 attributes
.phase_finish
- start_time_
, past_events
);
496 void ChromeMetricsServiceClient::FinishedReceivingProfilerData() {
497 drive_metrics_provider_
->GetDriveMetrics(
498 finished_gathering_initial_metrics_callback_
);
501 void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() {
502 DCHECK(thread_checker_
.CalledOnValidThread());
504 // This function should only be called as the callback from an ansynchronous
506 DCHECK(waiting_for_collect_final_metrics_step_
);
508 // Create a callback_task for OnHistogramSynchronizationDone.
509 base::Closure callback
= base::Bind(
510 &ChromeMetricsServiceClient::OnHistogramSynchronizationDone
,
511 weak_ptr_factory_
.GetWeakPtr());
513 base::TimeDelta timeout
=
514 base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration
);
516 DCHECK_EQ(num_async_histogram_fetches_in_progress_
, 0);
518 #if !defined(ENABLE_PRINT_PREVIEW)
519 num_async_histogram_fetches_in_progress_
= 1;
520 #else // !ENABLE_PRINT_PREVIEW
521 num_async_histogram_fetches_in_progress_
= 2;
522 // Run requests to service and content in parallel.
523 if (!ServiceProcessControl::GetInstance()->GetHistograms(callback
, timeout
)) {
524 // Assume |num_async_histogram_fetches_in_progress_| is not changed by
525 // |GetHistograms()|.
526 DCHECK_EQ(num_async_histogram_fetches_in_progress_
, 2);
527 // Assign |num_async_histogram_fetches_in_progress_| above and decrement it
528 // here to make code work even if |GetHistograms()| fired |callback|.
529 --num_async_histogram_fetches_in_progress_
;
531 #endif // !ENABLE_PRINT_PREVIEW
533 // Set up the callback to task to call after we receive histograms from all
534 // child processes. |timeout| specifies how long to wait before absolutely
535 // calling us back on the task.
536 content::FetchHistogramsAsynchronously(base::MessageLoop::current(), callback
,
540 void ChromeMetricsServiceClient::OnHistogramSynchronizationDone() {
541 DCHECK(thread_checker_
.CalledOnValidThread());
543 // This function should only be called as the callback from an ansynchronous
545 DCHECK(waiting_for_collect_final_metrics_step_
);
546 DCHECK_GT(num_async_histogram_fetches_in_progress_
, 0);
548 // Check if all expected requests finished.
549 if (--num_async_histogram_fetches_in_progress_
> 0)
552 waiting_for_collect_final_metrics_step_
= false;
553 collect_final_metrics_done_callback_
.Run();
556 void ChromeMetricsServiceClient::RecordCommandLineMetrics() {
557 // Get stats on use of command line.
558 const base::CommandLine
* command_line(base::CommandLine::ForCurrentProcess());
559 size_t common_commands
= 0;
560 if (command_line
->HasSwitch(switches::kUserDataDir
)) {
562 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1);
565 if (command_line
->HasSwitch(switches::kApp
)) {
567 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1);
570 // TODO(rohitrao): Should these be logged on iOS as well?
571 // http://crbug.com/375794
572 size_t switch_count
= command_line
->GetSwitches().size();
573 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count
);
574 UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
575 switch_count
- common_commands
);
578 void ChromeMetricsServiceClient::RegisterForNotifications() {
579 registrar_
.Add(this, chrome::NOTIFICATION_BROWSER_OPENED
,
580 content::NotificationService::AllBrowserContextsAndSources());
581 registrar_
.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED
,
582 content::NotificationService::AllSources());
583 registrar_
.Add(this, chrome::NOTIFICATION_TAB_PARENTED
,
584 content::NotificationService::AllSources());
585 registrar_
.Add(this, chrome::NOTIFICATION_TAB_CLOSING
,
586 content::NotificationService::AllSources());
587 registrar_
.Add(this, content::NOTIFICATION_LOAD_START
,
588 content::NotificationService::AllSources());
589 registrar_
.Add(this, content::NOTIFICATION_LOAD_STOP
,
590 content::NotificationService::AllSources());
591 registrar_
.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED
,
592 content::NotificationService::AllSources());
593 registrar_
.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG
,
594 content::NotificationService::AllSources());
596 omnibox_url_opened_subscription_
=
597 OmniboxEventGlobalTracker::GetInstance()->RegisterCallback(
598 base::Bind(&ChromeMetricsServiceClient::OnURLOpenedFromOmnibox
,
599 base::Unretained(this)));
602 void ChromeMetricsServiceClient::Observe(
604 const content::NotificationSource
& source
,
605 const content::NotificationDetails
& details
) {
606 DCHECK(thread_checker_
.CalledOnValidThread());
609 case chrome::NOTIFICATION_BROWSER_OPENED
:
610 case chrome::NOTIFICATION_BROWSER_CLOSED
:
611 case chrome::NOTIFICATION_TAB_PARENTED
:
612 case chrome::NOTIFICATION_TAB_CLOSING
:
613 case content::NOTIFICATION_LOAD_STOP
:
614 case content::NOTIFICATION_LOAD_START
:
615 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED
:
616 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG
:
617 metrics_service_
->OnApplicationNotIdle();
625 void ChromeMetricsServiceClient::OnURLOpenedFromOmnibox(OmniboxLog
* log
) {
626 metrics_service_
->OnApplicationNotIdle();