| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h" | |
| 6 | |
| 7 #include <stdint.h> | |
| 8 | |
| 9 #include <utility> | |
| 10 #include <vector> | |
| 11 | |
| 12 #include "base/bind.h" | |
| 13 #include "base/callback.h" | |
| 14 #include "base/command_line.h" | |
| 15 #include "base/files/file_path.h" | |
| 16 #include "base/logging.h" | |
| 17 #include "base/memory/ptr_util.h" | |
| 18 #include "base/metrics/histogram.h" | |
| 19 #include "base/process/process_metrics.h" | |
| 20 #include "base/rand_util.h" | |
| 21 #include "base/strings/string16.h" | |
| 22 #include "base/threading/platform_thread.h" | |
| 23 #include "components/crash/core/common/crash_keys.h" | |
| 24 #include "components/metrics/call_stack_profile_metrics_provider.h" | |
| 25 #include "components/metrics/drive_metrics_provider.h" | |
| 26 #include "components/metrics/metrics_pref_names.h" | |
| 27 #include "components/metrics/metrics_reporting_default_state.h" | |
| 28 #include "components/metrics/metrics_service.h" | |
| 29 #include "components/metrics/net/cellular_logic_helper.h" | |
| 30 #include "components/metrics/net/net_metrics_log_uploader.h" | |
| 31 #include "components/metrics/net/network_metrics_provider.h" | |
| 32 #include "components/metrics/net/version_utils.h" | |
| 33 #include "components/metrics/profiler/profiler_metrics_provider.h" | |
| 34 #include "components/metrics/profiler/tracking_synchronizer.h" | |
| 35 #include "components/metrics/stability_metrics_helper.h" | |
| 36 #include "components/metrics/ui/screen_info_metrics_provider.h" | |
| 37 #include "components/metrics/url_constants.h" | |
| 38 #include "components/omnibox/browser/omnibox_metrics_provider.h" | |
| 39 #include "components/prefs/pref_registry_simple.h" | |
| 40 #include "components/prefs/pref_service.h" | |
| 41 #include "components/signin/core/browser/signin_status_metrics_provider.h" | |
| 42 #include "components/sync/device_info/device_count_metrics_provider.h" | |
| 43 #include "components/translate/core/browser/translate_ranker_metrics_provider.h" | |
| 44 #include "components/variations/variations_associated_data.h" | |
| 45 #include "components/version_info/version_info.h" | |
| 46 #include "ios/chrome/browser/application_context.h" | |
| 47 #include "ios/chrome/browser/chrome_paths.h" | |
| 48 #include "ios/chrome/browser/google/google_brand.h" | |
| 49 #include "ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h" | |
| 50 #include "ios/chrome/browser/metrics/mobile_session_shutdown_metrics_provider.h" | |
| 51 #include "ios/chrome/browser/signin/ios_chrome_signin_status_metrics_provider_de
legate.h" | |
| 52 #include "ios/chrome/browser/sync/ios_chrome_sync_client.h" | |
| 53 #include "ios/chrome/browser/tab_parenting_global_observer.h" | |
| 54 #include "ios/chrome/browser/ui/browser_otr_state.h" | |
| 55 #include "ios/chrome/common/channel_info.h" | |
| 56 #include "ios/web/public/web_thread.h" | |
| 57 | |
| 58 IOSChromeMetricsServiceClient::IOSChromeMetricsServiceClient( | |
| 59 metrics::MetricsStateManager* state_manager) | |
| 60 : metrics_state_manager_(state_manager), | |
| 61 stability_metrics_provider_(nullptr), | |
| 62 profiler_metrics_provider_(nullptr), | |
| 63 drive_metrics_provider_(nullptr), | |
| 64 start_time_(base::TimeTicks::Now()), | |
| 65 has_uploaded_profiler_data_(false), | |
| 66 weak_ptr_factory_(this) { | |
| 67 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 68 RegisterForNotifications(); | |
| 69 } | |
| 70 | |
| 71 IOSChromeMetricsServiceClient::~IOSChromeMetricsServiceClient() { | |
| 72 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 73 } | |
| 74 | |
| 75 // static | |
| 76 std::unique_ptr<IOSChromeMetricsServiceClient> | |
| 77 IOSChromeMetricsServiceClient::Create( | |
| 78 metrics::MetricsStateManager* state_manager) { | |
| 79 // Perform two-phase initialization so that |client->metrics_service_| only | |
| 80 // receives pointers to fully constructed objects. | |
| 81 std::unique_ptr<IOSChromeMetricsServiceClient> client( | |
| 82 new IOSChromeMetricsServiceClient(state_manager)); | |
| 83 client->Initialize(); | |
| 84 | |
| 85 return client; | |
| 86 } | |
| 87 | |
| 88 // static | |
| 89 void IOSChromeMetricsServiceClient::RegisterPrefs( | |
| 90 PrefRegistrySimple* registry) { | |
| 91 metrics::MetricsService::RegisterPrefs(registry); | |
| 92 metrics::StabilityMetricsHelper::RegisterPrefs(registry); | |
| 93 metrics::RegisterMetricsReportingStatePrefs(registry); | |
| 94 } | |
| 95 | |
| 96 metrics::MetricsService* IOSChromeMetricsServiceClient::GetMetricsService() { | |
| 97 return metrics_service_.get(); | |
| 98 } | |
| 99 | |
| 100 void IOSChromeMetricsServiceClient::SetMetricsClientId( | |
| 101 const std::string& client_id) { | |
| 102 crash_keys::SetMetricsClientIdFromGUID(client_id); | |
| 103 } | |
| 104 | |
| 105 int32_t IOSChromeMetricsServiceClient::GetProduct() { | |
| 106 return metrics::ChromeUserMetricsExtension::CHROME; | |
| 107 } | |
| 108 | |
| 109 std::string IOSChromeMetricsServiceClient::GetApplicationLocale() { | |
| 110 return GetApplicationContext()->GetApplicationLocale(); | |
| 111 } | |
| 112 | |
| 113 bool IOSChromeMetricsServiceClient::GetBrand(std::string* brand_code) { | |
| 114 return ios::google_brand::GetBrand(brand_code); | |
| 115 } | |
| 116 | |
| 117 metrics::SystemProfileProto::Channel | |
| 118 IOSChromeMetricsServiceClient::GetChannel() { | |
| 119 return metrics::AsProtobufChannel(::GetChannel()); | |
| 120 } | |
| 121 | |
| 122 std::string IOSChromeMetricsServiceClient::GetVersionString() { | |
| 123 return metrics::GetVersionString(); | |
| 124 } | |
| 125 | |
| 126 void IOSChromeMetricsServiceClient::OnLogUploadComplete() {} | |
| 127 | |
| 128 void IOSChromeMetricsServiceClient::InitializeSystemProfileMetrics( | |
| 129 const base::Closure& done_callback) { | |
| 130 finished_init_task_callback_ = done_callback; | |
| 131 drive_metrics_provider_->GetDriveMetrics( | |
| 132 base::Bind(&IOSChromeMetricsServiceClient::OnInitTaskGotDriveMetrics, | |
| 133 weak_ptr_factory_.GetWeakPtr())); | |
| 134 } | |
| 135 | |
| 136 void IOSChromeMetricsServiceClient::CollectFinalMetricsForLog( | |
| 137 const base::Closure& done_callback) { | |
| 138 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 139 | |
| 140 collect_final_metrics_done_callback_ = done_callback; | |
| 141 | |
| 142 if (ShouldIncludeProfilerDataInLog()) { | |
| 143 // Fetch profiler data. This will call into | |
| 144 // |FinishedReceivingProfilerData()| when the task completes. | |
| 145 metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously( | |
| 146 weak_ptr_factory_.GetWeakPtr()); | |
| 147 } else { | |
| 148 CollectFinalHistograms(); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 std::unique_ptr<metrics::MetricsLogUploader> | |
| 153 IOSChromeMetricsServiceClient::CreateUploader( | |
| 154 const base::Callback<void(int)>& on_upload_complete) { | |
| 155 return std::unique_ptr<metrics::MetricsLogUploader>( | |
| 156 new metrics::NetMetricsLogUploader( | |
| 157 GetApplicationContext()->GetSystemURLRequestContext(), | |
| 158 metrics::kDefaultMetricsServerUrl, metrics::kDefaultMetricsMimeType, | |
| 159 on_upload_complete)); | |
| 160 } | |
| 161 | |
| 162 base::TimeDelta IOSChromeMetricsServiceClient::GetStandardUploadInterval() { | |
| 163 return metrics::GetUploadInterval(); | |
| 164 } | |
| 165 | |
| 166 base::string16 IOSChromeMetricsServiceClient::GetRegistryBackupKey() { | |
| 167 return base::string16(); | |
| 168 } | |
| 169 | |
| 170 void IOSChromeMetricsServiceClient::OnRendererProcessCrash() { | |
| 171 stability_metrics_provider_->LogRendererCrash(); | |
| 172 } | |
| 173 | |
| 174 void IOSChromeMetricsServiceClient::WebStateDidStartLoading( | |
| 175 web::WebState* web_state) { | |
| 176 metrics_service_->OnApplicationNotIdle(); | |
| 177 } | |
| 178 | |
| 179 void IOSChromeMetricsServiceClient::WebStateDidStopLoading( | |
| 180 web::WebState* web_state) { | |
| 181 metrics_service_->OnApplicationNotIdle(); | |
| 182 } | |
| 183 | |
| 184 void IOSChromeMetricsServiceClient::Initialize() { | |
| 185 metrics_service_.reset(new metrics::MetricsService( | |
| 186 metrics_state_manager_, this, GetApplicationContext()->GetLocalState())); | |
| 187 | |
| 188 // Register metrics providers. | |
| 189 metrics_service_->RegisterMetricsProvider( | |
| 190 std::unique_ptr<metrics::MetricsProvider>( | |
| 191 new metrics::NetworkMetricsProvider( | |
| 192 web::WebThread::GetBlockingPool()))); | |
| 193 | |
| 194 // Currently, we configure OmniboxMetricsProvider to not log events to UMA | |
| 195 // if there is a single incognito session visible. In the future, it may | |
| 196 // be worth revisiting this to still log events from non-incognito sessions. | |
| 197 metrics_service_->RegisterMetricsProvider( | |
| 198 std::unique_ptr<metrics::MetricsProvider>(new OmniboxMetricsProvider( | |
| 199 base::Bind(&::IsOffTheRecordSessionActive)))); | |
| 200 | |
| 201 stability_metrics_provider_ = new IOSChromeStabilityMetricsProvider( | |
| 202 GetApplicationContext()->GetLocalState()); | |
| 203 metrics_service_->RegisterMetricsProvider( | |
| 204 std::unique_ptr<metrics::MetricsProvider>(stability_metrics_provider_)); | |
| 205 | |
| 206 metrics_service_->RegisterMetricsProvider( | |
| 207 std::unique_ptr<metrics::MetricsProvider>( | |
| 208 new metrics::ScreenInfoMetricsProvider)); | |
| 209 | |
| 210 drive_metrics_provider_ = new metrics::DriveMetricsProvider( | |
| 211 web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE), | |
| 212 ios::FILE_LOCAL_STATE); | |
| 213 metrics_service_->RegisterMetricsProvider( | |
| 214 std::unique_ptr<metrics::MetricsProvider>(drive_metrics_provider_)); | |
| 215 | |
| 216 profiler_metrics_provider_ = new metrics::ProfilerMetricsProvider( | |
| 217 base::Bind(&metrics::IsCellularLogicEnabled)); | |
| 218 metrics_service_->RegisterMetricsProvider( | |
| 219 std::unique_ptr<metrics::MetricsProvider>(profiler_metrics_provider_)); | |
| 220 | |
| 221 metrics_service_->RegisterMetricsProvider( | |
| 222 std::unique_ptr<metrics::MetricsProvider>( | |
| 223 new metrics::CallStackProfileMetricsProvider)); | |
| 224 | |
| 225 metrics_service_->RegisterMetricsProvider( | |
| 226 std::unique_ptr<metrics::MetricsProvider>( | |
| 227 SigninStatusMetricsProvider::CreateInstance(base::WrapUnique( | |
| 228 new IOSChromeSigninStatusMetricsProviderDelegate)))); | |
| 229 | |
| 230 metrics_service_->RegisterMetricsProvider( | |
| 231 std::unique_ptr<metrics::MetricsProvider>( | |
| 232 new MobileSessionShutdownMetricsProvider(metrics_service_.get()))); | |
| 233 | |
| 234 metrics_service_->RegisterMetricsProvider( | |
| 235 std::unique_ptr<metrics::MetricsProvider>( | |
| 236 new syncer::DeviceCountMetricsProvider( | |
| 237 base::Bind(&IOSChromeSyncClient::GetDeviceInfoTrackers)))); | |
| 238 | |
| 239 metrics_service_->RegisterMetricsProvider( | |
| 240 std::unique_ptr<metrics::MetricsProvider>( | |
| 241 new translate::TranslateRankerMetricsProvider())); | |
| 242 } | |
| 243 | |
| 244 void IOSChromeMetricsServiceClient::OnInitTaskGotDriveMetrics() { | |
| 245 finished_init_task_callback_.Run(); | |
| 246 } | |
| 247 | |
| 248 bool IOSChromeMetricsServiceClient::ShouldIncludeProfilerDataInLog() { | |
| 249 // Upload profiler data at most once per session. | |
| 250 if (has_uploaded_profiler_data_) | |
| 251 return false; | |
| 252 | |
| 253 // For each log, flip a fair coin. Thus, profiler data is sent with the first | |
| 254 // log with probability 50%, with the second log with probability 25%, and so | |
| 255 // on. As a result, uploaded data is biased toward earlier logs. | |
| 256 // TODO(isherman): Explore other possible algorithms, and choose one that | |
| 257 // might be more appropriate. For example, it might be reasonable to include | |
| 258 // profiler data with some fixed probability, so that a given client might | |
| 259 // upload profiler data more than once; but on average, clients won't upload | |
| 260 // too much data. | |
| 261 if (base::RandDouble() < 0.5) | |
| 262 return false; | |
| 263 | |
| 264 has_uploaded_profiler_data_ = true; | |
| 265 return true; | |
| 266 } | |
| 267 | |
| 268 void IOSChromeMetricsServiceClient::ReceivedProfilerData( | |
| 269 const metrics::ProfilerDataAttributes& attributes, | |
| 270 const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, | |
| 271 const metrics::ProfilerEvents& past_events) { | |
| 272 profiler_metrics_provider_->RecordProfilerData( | |
| 273 process_data_phase, attributes.process_id, attributes.process_type, | |
| 274 attributes.profiling_phase, attributes.phase_start - start_time_, | |
| 275 attributes.phase_finish - start_time_, past_events); | |
| 276 } | |
| 277 | |
| 278 void IOSChromeMetricsServiceClient::FinishedReceivingProfilerData() { | |
| 279 CollectFinalHistograms(); | |
| 280 } | |
| 281 | |
| 282 void IOSChromeMetricsServiceClient::CollectFinalHistograms() { | |
| 283 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 284 | |
| 285 // TODO(ios): Try to extract the flow below into a utility function that is | |
| 286 // shared between the iOS port's usage and | |
| 287 // ChromeMetricsServiceClient::CollectFinalHistograms()'s usage of | |
| 288 // MetricsMemoryDetails. | |
| 289 std::unique_ptr<base::ProcessMetrics> process_metrics( | |
| 290 base::ProcessMetrics::CreateProcessMetrics( | |
| 291 base::GetCurrentProcessHandle())); | |
| 292 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", | |
| 293 process_metrics->GetWorkingSetSize() / 1024); | |
| 294 collect_final_metrics_done_callback_.Run(); | |
| 295 } | |
| 296 | |
| 297 void IOSChromeMetricsServiceClient::RegisterForNotifications() { | |
| 298 tab_parented_subscription_ = | |
| 299 TabParentingGlobalObserver::GetInstance()->RegisterCallback( | |
| 300 base::Bind(&IOSChromeMetricsServiceClient::OnTabParented, | |
| 301 base::Unretained(this))); | |
| 302 omnibox_url_opened_subscription_ = | |
| 303 OmniboxEventGlobalTracker::GetInstance()->RegisterCallback( | |
| 304 base::Bind(&IOSChromeMetricsServiceClient::OnURLOpenedFromOmnibox, | |
| 305 base::Unretained(this))); | |
| 306 } | |
| 307 | |
| 308 void IOSChromeMetricsServiceClient::OnTabParented(web::WebState* web_state) { | |
| 309 metrics_service_->OnApplicationNotIdle(); | |
| 310 } | |
| 311 | |
| 312 void IOSChromeMetricsServiceClient::OnURLOpenedFromOmnibox(OmniboxLog* log) { | |
| 313 metrics_service_->OnApplicationNotIdle(); | |
| 314 } | |
| 315 | |
| 316 metrics::EnableMetricsDefault | |
| 317 IOSChromeMetricsServiceClient::GetMetricsReportingDefaultState() { | |
| 318 return metrics::GetMetricsReportingDefaultState( | |
| 319 GetApplicationContext()->GetLocalState()); | |
| 320 } | |
| OLD | NEW |