Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 //------------------------------------------------------------------------------ | 5 //------------------------------------------------------------------------------ |
| 6 // Description of the life cycle of a instance of MetricsService. | 6 // Description of the life cycle of a instance of MetricsService. |
| 7 // | 7 // |
| 8 // OVERVIEW | 8 // OVERVIEW |
| 9 // | 9 // |
| 10 // A MetricsService instance is typically created at application startup. It is | 10 // A MetricsService instance is typically created at application startup. It is |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 #include "base/strings/utf_string_conversions.h" | 178 #include "base/strings/utf_string_conversions.h" |
| 179 #include "base/threading/platform_thread.h" | 179 #include "base/threading/platform_thread.h" |
| 180 #include "base/threading/thread.h" | 180 #include "base/threading/thread.h" |
| 181 #include "base/threading/thread_restrictions.h" | 181 #include "base/threading/thread_restrictions.h" |
| 182 #include "base/tracked_objects.h" | 182 #include "base/tracked_objects.h" |
| 183 #include "base/values.h" | 183 #include "base/values.h" |
| 184 #include "chrome/browser/browser_process.h" | 184 #include "chrome/browser/browser_process.h" |
| 185 #include "chrome/browser/chrome_notification_types.h" | 185 #include "chrome/browser/chrome_notification_types.h" |
| 186 #include "chrome/browser/io_thread.h" | 186 #include "chrome/browser/io_thread.h" |
| 187 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h" | 187 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h" |
| 188 #include "chrome/browser/metrics/compression_utils.h" | |
| 189 #include "chrome/browser/metrics/gpu_metrics_provider.h" | 188 #include "chrome/browser/metrics/gpu_metrics_provider.h" |
| 190 #include "chrome/browser/metrics/metrics_log.h" | 189 #include "chrome/browser/metrics/metrics_log.h" |
| 191 #include "chrome/browser/metrics/metrics_state_manager.h" | 190 #include "chrome/browser/metrics/metrics_state_manager.h" |
| 192 #include "chrome/browser/metrics/network_metrics_provider.h" | 191 #include "chrome/browser/metrics/network_metrics_provider.h" |
| 193 #include "chrome/browser/metrics/omnibox_metrics_provider.h" | 192 #include "chrome/browser/metrics/omnibox_metrics_provider.h" |
| 194 #include "chrome/browser/metrics/tracking_synchronizer.h" | 193 #include "chrome/browser/metrics/tracking_synchronizer.h" |
| 195 #include "chrome/common/pref_names.h" | 194 #include "chrome/common/pref_names.h" |
| 196 #include "chrome/common/variations/variations_util.h" | 195 #include "chrome/common/variations/variations_util.h" |
| 197 #include "components/metrics/metrics_log_base.h" | 196 #include "components/metrics/metrics_log_base.h" |
| 198 #include "components/metrics/metrics_log_manager.h" | 197 #include "components/metrics/metrics_log_manager.h" |
| 199 #include "components/metrics/metrics_pref_names.h" | 198 #include "components/metrics/metrics_pref_names.h" |
| 200 #include "components/metrics/metrics_reporting_scheduler.h" | 199 #include "components/metrics/metrics_reporting_scheduler.h" |
| 201 #include "components/metrics/metrics_service_client.h" | 200 #include "components/metrics/metrics_service_client.h" |
| 201 #include "components/metrics/net/compression_utils.h" | |
| 202 #include "components/variations/entropy_provider.h" | 202 #include "components/variations/entropy_provider.h" |
| 203 #include "net/base/load_flags.h" | |
| 204 #include "net/url_request/url_fetcher.h" | |
| 205 | 203 |
| 206 #if defined(ENABLE_PLUGINS) | 204 #if defined(ENABLE_PLUGINS) |
| 207 // TODO(asvitkine): Move this out of MetricsService. | 205 // TODO(asvitkine): Move this out of MetricsService. |
| 208 #include "chrome/browser/metrics/plugin_metrics_provider.h" | 206 #include "chrome/browser/metrics/plugin_metrics_provider.h" |
| 209 #endif | 207 #endif |
| 210 | 208 |
| 211 #if defined(OS_CHROMEOS) | 209 #if defined(OS_CHROMEOS) |
| 212 #include "chrome/browser/chromeos/settings/cros_settings.h" | 210 #include "chrome/browser/chromeos/settings/cros_settings.h" |
| 213 #include "chrome/browser/metrics/chromeos_metrics_provider.h" | 211 #include "chrome/browser/metrics/chromeos_metrics_provider.h" |
| 214 #include "chromeos/system/statistics_provider.h" | 212 #include "chromeos/system/statistics_provider.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 enum ResponseStatus { | 268 enum ResponseStatus { |
| 271 UNKNOWN_FAILURE, | 269 UNKNOWN_FAILURE, |
| 272 SUCCESS, | 270 SUCCESS, |
| 273 BAD_REQUEST, // Invalid syntax or log too large. | 271 BAD_REQUEST, // Invalid syntax or log too large. |
| 274 NO_RESPONSE, | 272 NO_RESPONSE, |
| 275 NUM_RESPONSE_STATUSES | 273 NUM_RESPONSE_STATUSES |
| 276 }; | 274 }; |
| 277 | 275 |
| 278 ResponseStatus ResponseCodeToStatus(int response_code) { | 276 ResponseStatus ResponseCodeToStatus(int response_code) { |
| 279 switch (response_code) { | 277 switch (response_code) { |
| 278 case -1: | |
| 279 return NO_RESPONSE; | |
| 280 case 200: | 280 case 200: |
| 281 return SUCCESS; | 281 return SUCCESS; |
| 282 case 400: | 282 case 400: |
| 283 return BAD_REQUEST; | 283 return BAD_REQUEST; |
| 284 case net::URLFetcher::RESPONSE_CODE_INVALID: | |
| 285 return NO_RESPONSE; | |
| 286 default: | 284 default: |
| 287 return UNKNOWN_FAILURE; | 285 return UNKNOWN_FAILURE; |
| 288 } | 286 } |
| 289 } | 287 } |
| 290 | 288 |
| 291 void MarkAppCleanShutdownAndCommit() { | 289 void MarkAppCleanShutdownAndCommit() { |
| 292 PrefService* pref = g_browser_process->local_state(); | 290 PrefService* pref = g_browser_process->local_state(); |
| 293 pref->SetBoolean(prefs::kStabilityExitedCleanly, true); | 291 pref->SetBoolean(prefs::kStabilityExitedCleanly, true); |
| 294 pref->SetInteger(prefs::kStabilityExecutionPhase, | 292 pref->SetInteger(prefs::kStabilityExecutionPhase, |
| 295 MetricsService::SHUTDOWN_COMPLETE); | 293 MetricsService::SHUTDOWN_COMPLETE); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 : log_manager_(g_browser_process->local_state(), | 369 : log_manager_(g_browser_process->local_state(), |
| 372 kUploadLogAvoidRetransmitSize), | 370 kUploadLogAvoidRetransmitSize), |
| 373 histogram_snapshot_manager_(this), | 371 histogram_snapshot_manager_(this), |
| 374 state_manager_(state_manager), | 372 state_manager_(state_manager), |
| 375 client_(client), | 373 client_(client), |
| 376 recording_active_(false), | 374 recording_active_(false), |
| 377 reporting_active_(false), | 375 reporting_active_(false), |
| 378 test_mode_active_(false), | 376 test_mode_active_(false), |
| 379 state_(INITIALIZED), | 377 state_(INITIALIZED), |
| 380 has_initial_stability_log_(false), | 378 has_initial_stability_log_(false), |
| 379 log_upload_in_progress_(false), | |
| 381 idle_since_last_transmission_(false), | 380 idle_since_last_transmission_(false), |
| 382 session_id_(-1), | 381 session_id_(-1), |
| 383 next_window_id_(0), | 382 next_window_id_(0), |
| 384 self_ptr_factory_(this), | 383 self_ptr_factory_(this), |
| 385 state_saver_factory_(this), | 384 state_saver_factory_(this) { |
| 386 waiting_for_asynchronous_reporting_step_(false) { | |
| 387 DCHECK(IsSingleThreaded()); | 385 DCHECK(IsSingleThreaded()); |
| 388 DCHECK(state_manager_); | 386 DCHECK(state_manager_); |
| 389 DCHECK(client_); | 387 DCHECK(client_); |
| 390 | 388 |
| 391 #if defined(OS_ANDROID) | 389 #if defined(OS_ANDROID) |
| 392 // TODO(asvitkine): Move this out of MetricsService. | 390 // TODO(asvitkine): Move this out of MetricsService. |
| 393 RegisterMetricsProvider( | 391 RegisterMetricsProvider( |
| 394 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider( | 392 scoped_ptr<metrics::MetricsProvider>(new AndroidMetricsProvider( |
| 395 g_browser_process->local_state()))); | 393 g_browser_process->local_state()))); |
| 396 #endif // defined(OS_ANDROID) | 394 #endif // defined(OS_ANDROID) |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 924 log_manager_.FinishCurrentLog(); | 922 log_manager_.FinishCurrentLog(); |
| 925 } | 923 } |
| 926 | 924 |
| 927 void MetricsService::PushPendingLogsToPersistentStorage() { | 925 void MetricsService::PushPendingLogsToPersistentStorage() { |
| 928 if (state_ < SENDING_INITIAL_STABILITY_LOG) | 926 if (state_ < SENDING_INITIAL_STABILITY_LOG) |
| 929 return; // We didn't and still don't have time to get plugin list etc. | 927 return; // We didn't and still don't have time to get plugin list etc. |
| 930 | 928 |
| 931 if (log_manager_.has_staged_log()) { | 929 if (log_manager_.has_staged_log()) { |
| 932 // We may race here, and send second copy of the log later. | 930 // We may race here, and send second copy of the log later. |
| 933 metrics::PersistedLogs::StoreType store_type; | 931 metrics::PersistedLogs::StoreType store_type; |
| 934 if (current_fetch_.get()) | 932 if (log_upload_in_progress_) |
| 935 store_type = metrics::PersistedLogs::PROVISIONAL_STORE; | 933 store_type = metrics::PersistedLogs::PROVISIONAL_STORE; |
| 936 else | 934 else |
| 937 store_type = metrics::PersistedLogs::NORMAL_STORE; | 935 store_type = metrics::PersistedLogs::NORMAL_STORE; |
| 938 log_manager_.StoreStagedLogAsUnsent(store_type); | 936 log_manager_.StoreStagedLogAsUnsent(store_type); |
| 939 } | 937 } |
| 940 DCHECK(!log_manager_.has_staged_log()); | 938 DCHECK(!log_manager_.has_staged_log()); |
| 941 CloseCurrentLog(); | 939 CloseCurrentLog(); |
| 942 log_manager_.PersistUnsentLogs(); | 940 log_manager_.PersistUnsentLogs(); |
| 943 | 941 |
| 944 // If there was a staged and/or current log, then there is now at least one | 942 // If there was a staged and/or current log, then there is now at least one |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1002 client_->CollectFinalMetrics( | 1000 client_->CollectFinalMetrics( |
| 1003 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone, | 1001 base::Bind(&MetricsService::OnFinalLogInfoCollectionDone, |
| 1004 self_ptr_factory_.GetWeakPtr())); | 1002 self_ptr_factory_.GetWeakPtr())); |
| 1005 } | 1003 } |
| 1006 } | 1004 } |
| 1007 | 1005 |
| 1008 void MetricsService::OnFinalLogInfoCollectionDone() { | 1006 void MetricsService::OnFinalLogInfoCollectionDone() { |
| 1009 // If somehow there is a fetch in progress, we return and hope things work | 1007 // If somehow there is a fetch in progress, we return and hope things work |
| 1010 // out. The scheduler isn't informed since if this happens, the scheduler | 1008 // out. The scheduler isn't informed since if this happens, the scheduler |
| 1011 // will get a response from the upload. | 1009 // will get a response from the upload. |
| 1012 DCHECK(!current_fetch_.get()); | 1010 DCHECK(!log_upload_in_progress_); |
| 1013 if (current_fetch_.get()) | 1011 if (log_upload_in_progress_) |
| 1014 return; | 1012 return; |
| 1015 | 1013 |
| 1016 // Abort if metrics were turned off during the final info gathering. | 1014 // Abort if metrics were turned off during the final info gathering. |
| 1017 if (!recording_active()) { | 1015 if (!recording_active()) { |
| 1018 scheduler_->Stop(); | 1016 scheduler_->Stop(); |
| 1019 scheduler_->UploadCancelled(); | 1017 scheduler_->UploadCancelled(); |
| 1020 return; | 1018 return; |
| 1021 } | 1019 } |
| 1022 | 1020 |
| 1023 StageNewLog(); | 1021 StageNewLog(); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1153 | 1151 |
| 1154 log_manager_.FinishCurrentLog(); | 1152 log_manager_.FinishCurrentLog(); |
| 1155 log_manager_.ResumePausedLog(); | 1153 log_manager_.ResumePausedLog(); |
| 1156 | 1154 |
| 1157 DCHECK(!log_manager_.has_staged_log()); | 1155 DCHECK(!log_manager_.has_staged_log()); |
| 1158 log_manager_.StageNextLogForUpload(); | 1156 log_manager_.StageNextLogForUpload(); |
| 1159 } | 1157 } |
| 1160 | 1158 |
| 1161 void MetricsService::SendStagedLog() { | 1159 void MetricsService::SendStagedLog() { |
| 1162 DCHECK(log_manager_.has_staged_log()); | 1160 DCHECK(log_manager_.has_staged_log()); |
| 1161 if (!log_manager_.has_staged_log()) | |
| 1162 return; | |
| 1163 | 1163 |
| 1164 PrepareFetchWithStagedLog(); | 1164 DCHECK(!log_upload_in_progress_); |
| 1165 log_upload_in_progress_ = true; | |
| 1165 | 1166 |
| 1166 bool upload_created = (current_fetch_.get() != NULL); | 1167 if (!log_uploader_) { |
| 1167 UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", upload_created); | 1168 log_uploader_ = client_->CreateUploader( |
| 1168 if (!upload_created) { | 1169 kServerUrl, kMimeType, |
| 1170 base::Bind(&MetricsService::OnLogUploadComplete, | |
| 1171 self_ptr_factory_.GetWeakPtr())); | |
| 1172 } | |
| 1173 | |
| 1174 const std::string hash = | |
| 1175 base::HexEncode(log_manager_.staged_log_hash().data(), | |
| 1176 log_manager_.staged_log_hash().size()); | |
| 1177 bool success = log_uploader_->UploadLog(log_manager_.staged_log(), hash); | |
| 1178 UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", success); | |
| 1179 if (!success) { | |
| 1169 // Compression failed, and log discarded :-/. | 1180 // Compression failed, and log discarded :-/. |
|
blundell
2014/05/26 07:56:56
is this comment a little out of date now?
Alexei Svitkine (slow)
2014/05/26 20:04:10
Done.
| |
| 1170 // Skip this upload and hope things work out next time. | 1181 // Skip this upload and hope things work out next time. |
| 1171 log_manager_.DiscardStagedLog(); | 1182 log_manager_.DiscardStagedLog(); |
| 1172 scheduler_->UploadCancelled(); | 1183 scheduler_->UploadCancelled(); |
| 1173 return; | 1184 return; |
| 1174 } | 1185 } |
| 1175 | 1186 |
| 1176 DCHECK(!waiting_for_asynchronous_reporting_step_); | |
| 1177 waiting_for_asynchronous_reporting_step_ = true; | |
| 1178 | |
| 1179 current_fetch_->Start(); | |
| 1180 | |
| 1181 HandleIdleSinceLastTransmission(true); | 1187 HandleIdleSinceLastTransmission(true); |
| 1182 } | 1188 } |
| 1183 | 1189 |
| 1184 void MetricsService::PrepareFetchWithStagedLog() { | |
| 1185 DCHECK(log_manager_.has_staged_log()); | |
| 1186 | 1190 |
| 1187 // Prepare the protobuf version. | 1191 void MetricsService::OnLogUploadComplete(int response_code) { |
| 1188 DCHECK(!current_fetch_.get()); | 1192 DCHECK(log_upload_in_progress_); |
| 1189 if (log_manager_.has_staged_log()) { | 1193 log_upload_in_progress_ = false; |
| 1190 current_fetch_.reset(net::URLFetcher::Create( | |
| 1191 GURL(kServerUrl), net::URLFetcher::POST, this)); | |
| 1192 current_fetch_->SetRequestContext( | |
| 1193 g_browser_process->system_request_context()); | |
| 1194 | |
| 1195 std::string log_text = log_manager_.staged_log(); | |
| 1196 std::string compressed_log_text; | |
| 1197 bool compression_successful = chrome::GzipCompress(log_text, | |
| 1198 &compressed_log_text); | |
| 1199 DCHECK(compression_successful); | |
| 1200 if (compression_successful) { | |
| 1201 current_fetch_->SetUploadData(kMimeType, compressed_log_text); | |
| 1202 // Tell the server that we're uploading gzipped protobufs. | |
| 1203 current_fetch_->SetExtraRequestHeaders("content-encoding: gzip"); | |
| 1204 const std::string hash = | |
| 1205 base::HexEncode(log_manager_.staged_log_hash().data(), | |
| 1206 log_manager_.staged_log_hash().size()); | |
| 1207 DCHECK(!hash.empty()); | |
| 1208 current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + hash); | |
| 1209 UMA_HISTOGRAM_PERCENTAGE( | |
| 1210 "UMA.ProtoCompressionRatio", | |
| 1211 100 * compressed_log_text.size() / log_text.size()); | |
| 1212 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 1213 "UMA.ProtoGzippedKBSaved", | |
| 1214 (log_text.size() - compressed_log_text.size()) / 1024, | |
| 1215 1, 2000, 50); | |
| 1216 } | |
| 1217 | |
| 1218 // We already drop cookies server-side, but we might as well strip them out | |
| 1219 // client-side as well. | |
| 1220 current_fetch_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | |
| 1221 net::LOAD_DO_NOT_SEND_COOKIES); | |
| 1222 } | |
| 1223 } | |
| 1224 | |
| 1225 void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) { | |
| 1226 DCHECK(waiting_for_asynchronous_reporting_step_); | |
| 1227 | |
| 1228 // We're not allowed to re-use the existing |URLFetcher|s, so free them here. | |
| 1229 // Note however that |source| is aliased to the fetcher, so we should be | |
| 1230 // careful not to delete it too early. | |
| 1231 DCHECK_EQ(current_fetch_.get(), source); | |
| 1232 scoped_ptr<net::URLFetcher> s(current_fetch_.Pass()); | |
| 1233 | |
| 1234 int response_code = source->GetResponseCode(); | |
| 1235 | 1194 |
| 1236 // Log a histogram to track response success vs. failure rates. | 1195 // Log a histogram to track response success vs. failure rates. |
| 1237 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf", | 1196 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf", |
| 1238 ResponseCodeToStatus(response_code), | 1197 ResponseCodeToStatus(response_code), |
| 1239 NUM_RESPONSE_STATUSES); | 1198 NUM_RESPONSE_STATUSES); |
| 1240 | 1199 |
| 1241 // If the upload was provisionally stored, drop it now that the upload is | 1200 // If the upload was provisionally stored, drop it now that the upload is |
| 1242 // known to have gone through. | 1201 // known to have gone through. |
| 1243 log_manager_.DiscardLastProvisionalStore(); | 1202 log_manager_.DiscardLastProvisionalStore(); |
| 1244 | 1203 |
| 1245 bool upload_succeeded = response_code == 200; | 1204 bool upload_succeeded = response_code == 200; |
| 1246 | 1205 |
| 1247 // Provide boolean for error recovery (allow us to ignore response_code). | 1206 // Provide boolean for error recovery (allow us to ignore response_code). |
| 1248 bool discard_log = false; | 1207 bool discard_log = false; |
| 1249 const size_t log_size = log_manager_.staged_log().length(); | 1208 const size_t log_size = log_manager_.staged_log().length(); |
| 1250 if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) { | 1209 if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) { |
| 1251 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", | 1210 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", |
| 1252 static_cast<int>(log_size)); | 1211 static_cast<int>(log_size)); |
| 1253 discard_log = true; | 1212 discard_log = true; |
| 1254 } else if (response_code == 400) { | 1213 } else if (response_code == 400) { |
| 1255 // Bad syntax. Retransmission won't work. | 1214 // Bad syntax. Retransmission won't work. |
| 1256 discard_log = true; | 1215 discard_log = true; |
| 1257 } | 1216 } |
| 1258 | 1217 |
| 1259 if (upload_succeeded || discard_log) | 1218 if (upload_succeeded || discard_log) |
| 1260 log_manager_.DiscardStagedLog(); | 1219 log_manager_.DiscardStagedLog(); |
| 1261 | 1220 |
| 1262 waiting_for_asynchronous_reporting_step_ = false; | |
| 1263 | |
| 1264 if (!log_manager_.has_staged_log()) { | 1221 if (!log_manager_.has_staged_log()) { |
| 1265 switch (state_) { | 1222 switch (state_) { |
| 1266 case SENDING_INITIAL_STABILITY_LOG: | 1223 case SENDING_INITIAL_STABILITY_LOG: |
| 1267 // Store the updated list to disk now that the removed log is uploaded. | 1224 // Store the updated list to disk now that the removed log is uploaded. |
| 1268 log_manager_.PersistUnsentLogs(); | 1225 log_manager_.PersistUnsentLogs(); |
| 1269 PrepareInitialMetricsLog(); | 1226 PrepareInitialMetricsLog(); |
| 1270 SendStagedLog(); | 1227 SendStagedLog(); |
| 1271 state_ = SENDING_INITIAL_METRICS_LOG; | 1228 state_ = SENDING_INITIAL_METRICS_LOG; |
| 1272 break; | 1229 break; |
| 1273 | 1230 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1429 RecordCurrentState(pref); | 1386 RecordCurrentState(pref); |
| 1430 } | 1387 } |
| 1431 | 1388 |
| 1432 void MetricsService::RecordCurrentState(PrefService* pref) { | 1389 void MetricsService::RecordCurrentState(PrefService* pref) { |
| 1433 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT()); | 1390 pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT()); |
| 1434 | 1391 |
| 1435 #if defined(ENABLE_PLUGINS) | 1392 #if defined(ENABLE_PLUGINS) |
| 1436 plugin_metrics_provider_->RecordPluginChanges(); | 1393 plugin_metrics_provider_->RecordPluginChanges(); |
| 1437 #endif | 1394 #endif |
| 1438 } | 1395 } |
| OLD | NEW |