Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: components/metrics/metrics_state_manager.cc

Issue 372473004: Retrieve client_id from GoogleUpdateSettings when its missing from Local State. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review:isherman Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 #include "components/metrics/metrics_state_manager.h" 5 #include "components/metrics/metrics_state_manager.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/guid.h" 8 #include "base/guid.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/metrics/sparse_histogram.h" 10 #include "base/metrics/sparse_histogram.h"
(...skipping 27 matching lines...) Expand all
38 return base::RandInt(0, kMaxLowEntropySize - 1); 38 return base::RandInt(0, kMaxLowEntropySize - 1);
39 } 39 }
40 40
41 } // namespace 41 } // namespace
42 42
43 // static 43 // static
44 bool MetricsStateManager::instance_exists_ = false; 44 bool MetricsStateManager::instance_exists_ = false;
45 45
46 MetricsStateManager::MetricsStateManager( 46 MetricsStateManager::MetricsStateManager(
47 PrefService* local_state, 47 PrefService* local_state,
48 const base::Callback<bool(void)>& is_reporting_enabled_callback) 48 const base::Callback<bool(void)>& is_reporting_enabled_callback,
49 const StoreClientInfoCallback& store_client_info,
50 const LoadClientInfoCallback& retrieve_client_info)
49 : local_state_(local_state), 51 : local_state_(local_state),
50 is_reporting_enabled_callback_(is_reporting_enabled_callback), 52 is_reporting_enabled_callback_(is_reporting_enabled_callback),
53 store_client_info_(store_client_info),
54 load_client_info_(retrieve_client_info),
51 low_entropy_source_(kLowEntropySourceNotSet), 55 low_entropy_source_(kLowEntropySourceNotSet),
52 entropy_source_returned_(ENTROPY_SOURCE_NONE) { 56 entropy_source_returned_(ENTROPY_SOURCE_NONE) {
53 ResetMetricsIDsIfNecessary(); 57 ResetMetricsIDsIfNecessary();
54 if (IsMetricsReportingEnabled()) 58 if (IsMetricsReportingEnabled())
55 ForceClientIdCreation(); 59 ForceClientIdCreation();
56 60
57 DCHECK(!instance_exists_); 61 DCHECK(!instance_exists_);
58 instance_exists_ = true; 62 instance_exists_ = true;
59 } 63 }
60 64
61 MetricsStateManager::~MetricsStateManager() { 65 MetricsStateManager::~MetricsStateManager() {
62 DCHECK(instance_exists_); 66 DCHECK(instance_exists_);
63 instance_exists_ = false; 67 instance_exists_ = false;
64 } 68 }
65 69
66 bool MetricsStateManager::IsMetricsReportingEnabled() { 70 bool MetricsStateManager::IsMetricsReportingEnabled() {
67 return is_reporting_enabled_callback_.Run(); 71 return is_reporting_enabled_callback_.Run();
68 } 72 }
69 73
70 void MetricsStateManager::ForceClientIdCreation() { 74 void MetricsStateManager::ForceClientIdCreation() {
71 if (!client_id_.empty()) 75 if (!client_id_.empty())
72 return; 76 return;
73 77
74 client_id_ = local_state_->GetString(prefs::kMetricsClientID); 78 client_id_ = local_state_->GetString(prefs::kMetricsClientID);
75 if (!client_id_.empty()) 79 if (!client_id_.empty()) {
80 // It is technically sufficient to only save a backup of the client id when
81 // it is initially generated below, but since the backup was only introduced
82 // in M38, seed it explicitly from here for some time.
83 BackUpCurrentClientInfo();
76 return; 84 return;
85 }
77 86
87 const scoped_ptr<ClientInfo> client_info_backup =
88 LoadClientInfoAndMaybeMigrate();
89 if (client_info_backup) {
90 client_id_ = client_info_backup->client_id;
91
92 const base::Time now(base::Time::Now());
93
94 // Save the recovered client id and also try to reinstantiate the backup
95 // values for the dates corresponding with that client id in order to avoid
96 // weird scenarios where we could report an old client id with a recent
97 // install date.
98 local_state_->SetString(prefs::kMetricsClientID, client_id_);
99 local_state_->SetInt64(prefs::kInstallDate,
100 client_info_backup->installation_date ?
101 client_info_backup->installation_date :
102 now.ToTimeT());
103 local_state_->SetInt64(prefs::kMetricsReportingEnabledTimestamp,
104 client_info_backup->reporting_enabled_date ?
105 client_info_backup->reporting_enabled_date :
106 now.ToTimeT());
107
108 base::TimeDelta recovered_installation_age;
109 if (client_info_backup->installation_date != 0) {
110 recovered_installation_age =
111 now - base::Time::FromTimeT(client_info_backup->installation_date);
112 }
113 UMA_HISTOGRAM_COUNTS_10000("UMA.ClientIdBackupRecoveredWithAge",
114 recovered_installation_age.InHours());
115
116 // Flush the backup back to persistent storage in case we re-generated
117 // missing data above.
118 BackUpCurrentClientInfo();
119 return;
120 }
121
122 // Failing attempts at getting an existing client ID, generate a new one.
78 client_id_ = base::GenerateGUID(); 123 client_id_ = base::GenerateGUID();
79 local_state_->SetString(prefs::kMetricsClientID, client_id_); 124 local_state_->SetString(prefs::kMetricsClientID, client_id_);
80 125
81 if (local_state_->GetString(prefs::kMetricsOldClientID).empty()) { 126 if (local_state_->GetString(prefs::kMetricsOldClientID).empty()) {
82 // Record the timestamp of when the user opted in to UMA. 127 // Record the timestamp of when the user opted in to UMA.
83 local_state_->SetInt64(prefs::kMetricsReportingEnabledTimestamp, 128 local_state_->SetInt64(prefs::kMetricsReportingEnabledTimestamp,
84 base::Time::Now().ToTimeT()); 129 base::Time::Now().ToTimeT());
85 } else { 130 } else {
86 UMA_HISTOGRAM_BOOLEAN("UMA.ClientIdMigrated", true); 131 UMA_HISTOGRAM_BOOLEAN("UMA.ClientIdMigrated", true);
87 } 132 }
88 local_state_->ClearPref(prefs::kMetricsOldClientID); 133 local_state_->ClearPref(prefs::kMetricsOldClientID);
134
135 BackUpCurrentClientInfo();
89 } 136 }
90 137
91 void MetricsStateManager::CheckForClonedInstall( 138 void MetricsStateManager::CheckForClonedInstall(
92 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { 139 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
93 DCHECK(!cloned_install_detector_); 140 DCHECK(!cloned_install_detector_);
94 141
95 MachineIdProvider* provider = MachineIdProvider::CreateInstance(); 142 MachineIdProvider* provider = MachineIdProvider::CreateInstance();
96 if (!provider) 143 if (!provider)
97 return; 144 return;
98 145
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 #else 181 #else
135 return scoped_ptr<const base::FieldTrial::EntropyProvider>( 182 return scoped_ptr<const base::FieldTrial::EntropyProvider>(
136 new PermutedEntropyProvider(low_entropy_source_value, 183 new PermutedEntropyProvider(low_entropy_source_value,
137 kMaxLowEntropySize)); 184 kMaxLowEntropySize));
138 #endif 185 #endif
139 } 186 }
140 187
141 // static 188 // static
142 scoped_ptr<MetricsStateManager> MetricsStateManager::Create( 189 scoped_ptr<MetricsStateManager> MetricsStateManager::Create(
143 PrefService* local_state, 190 PrefService* local_state,
144 const base::Callback<bool(void)>& is_reporting_enabled_callback) { 191 const base::Callback<bool(void)>& is_reporting_enabled_callback,
192 const StoreClientInfoCallback& store_client_info,
193 const LoadClientInfoCallback& retrieve_client_info) {
145 scoped_ptr<MetricsStateManager> result; 194 scoped_ptr<MetricsStateManager> result;
146 // Note: |instance_exists_| is updated in the constructor and destructor. 195 // Note: |instance_exists_| is updated in the constructor and destructor.
147 if (!instance_exists_) { 196 if (!instance_exists_) {
148 result.reset( 197 result.reset(new MetricsStateManager(local_state,
149 new MetricsStateManager(local_state, is_reporting_enabled_callback)); 198 is_reporting_enabled_callback,
199 store_client_info,
200 retrieve_client_info));
150 } 201 }
151 return result.Pass(); 202 return result.Pass();
152 } 203 }
153 204
154 // static 205 // static
155 void MetricsStateManager::RegisterPrefs(PrefRegistrySimple* registry) { 206 void MetricsStateManager::RegisterPrefs(PrefRegistrySimple* registry) {
156 registry->RegisterBooleanPref(prefs::kMetricsResetIds, false); 207 registry->RegisterBooleanPref(prefs::kMetricsResetIds, false);
157 registry->RegisterStringPref(prefs::kMetricsClientID, std::string()); 208 registry->RegisterStringPref(prefs::kMetricsClientID, std::string());
158 registry->RegisterInt64Pref(prefs::kMetricsReportingEnabledTimestamp, 0); 209 registry->RegisterInt64Pref(prefs::kMetricsReportingEnabledTimestamp, 0);
159 registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource, 210 registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource,
160 kLowEntropySourceNotSet); 211 kLowEntropySourceNotSet);
161 212
162 ClonedInstallDetector::RegisterPrefs(registry); 213 ClonedInstallDetector::RegisterPrefs(registry);
163 CachingPermutedEntropyProvider::RegisterPrefs(registry); 214 CachingPermutedEntropyProvider::RegisterPrefs(registry);
164 215
165 // TODO(asvitkine): Remove these once a couple of releases have passed. 216 // TODO(asvitkine): Remove these once a couple of releases have passed.
166 // http://crbug.com/357704 217 // http://crbug.com/357704
167 registry->RegisterStringPref(prefs::kMetricsOldClientID, std::string()); 218 registry->RegisterStringPref(prefs::kMetricsOldClientID, std::string());
168 registry->RegisterIntegerPref(prefs::kMetricsOldLowEntropySource, 0); 219 registry->RegisterIntegerPref(prefs::kMetricsOldLowEntropySource, 0);
169 } 220 }
170 221
222 void MetricsStateManager::BackUpCurrentClientInfo() {
223 ClientInfo client_info;
224 client_info.client_id = client_id_;
225 client_info.installation_date = local_state_->GetInt64(prefs::kInstallDate);
226 client_info.reporting_enabled_date =
227 local_state_->GetInt64(prefs::kMetricsReportingEnabledTimestamp);
228 store_client_info_.Run(client_info);
229 }
230
231 scoped_ptr<ClientInfo> MetricsStateManager::LoadClientInfoAndMaybeMigrate() {
232 scoped_ptr<metrics::ClientInfo> client_info = load_client_info_.Run();
233
234 // Prior to 2014-07, the client ID was stripped of its dashes before being
235 // saved. Migrate back to a proper GUID if this is the case. This migration
236 // code can be removed in M41+.
237 const size_t kGUIDLengthWithoutDashes = 32U;
238 if (client_info &&
239 client_info->client_id.length() == kGUIDLengthWithoutDashes) {
240 DCHECK(client_info->client_id.find('-') == std::string::npos);
241
242 std::string client_id_with_dashes;
243 client_id_with_dashes.reserve(kGUIDLengthWithoutDashes + 4U);
244 std::string::const_iterator client_id_it = client_info->client_id.begin();
245 for (size_t i = 0; i < kGUIDLengthWithoutDashes + 4U; ++i) {
246 if (i == 8U || i == 13U || i == 18U || i == 23U) {
247 client_id_with_dashes.push_back('-');
248 } else {
249 client_id_with_dashes.push_back(*client_id_it);
250 ++client_id_it;
251 }
252 }
253 DCHECK(client_id_it == client_info->client_id.end());
254 client_info->client_id.assign(client_id_with_dashes);
255 }
256
257 // The GUID retrieved (and possibly fixed above) should be valid unless
258 // retrieval failed.
259 DCHECK(!client_info || base::IsValidGUID(client_info->client_id));
260
261 return client_info.Pass();
262 }
263
264
171 int MetricsStateManager::GetLowEntropySource() { 265 int MetricsStateManager::GetLowEntropySource() {
172 // Note that the default value for the low entropy source and the default pref 266 // Note that the default value for the low entropy source and the default pref
173 // value are both kLowEntropySourceNotSet, which is used to identify if the 267 // value are both kLowEntropySourceNotSet, which is used to identify if the
174 // value has been set or not. 268 // value has been set or not.
175 if (low_entropy_source_ != kLowEntropySourceNotSet) 269 if (low_entropy_source_ != kLowEntropySourceNotSet)
176 return low_entropy_source_; 270 return low_entropy_source_;
177 271
178 const CommandLine* command_line(CommandLine::ForCurrentProcess()); 272 const CommandLine* command_line(CommandLine::ForCurrentProcess());
179 // Only try to load the value from prefs if the user did not request a 273 // Only try to load the value from prefs if the user did not request a
180 // reset. 274 // reset.
(...skipping 23 matching lines...) Expand all
204 if (!local_state_->GetBoolean(prefs::kMetricsResetIds)) 298 if (!local_state_->GetBoolean(prefs::kMetricsResetIds))
205 return; 299 return;
206 300
207 UMA_HISTOGRAM_BOOLEAN("UMA.MetricsIDsReset", true); 301 UMA_HISTOGRAM_BOOLEAN("UMA.MetricsIDsReset", true);
208 302
209 DCHECK(client_id_.empty()); 303 DCHECK(client_id_.empty());
210 DCHECK_EQ(kLowEntropySourceNotSet, low_entropy_source_); 304 DCHECK_EQ(kLowEntropySourceNotSet, low_entropy_source_);
211 305
212 local_state_->ClearPref(prefs::kMetricsClientID); 306 local_state_->ClearPref(prefs::kMetricsClientID);
213 local_state_->ClearPref(prefs::kMetricsLowEntropySource); 307 local_state_->ClearPref(prefs::kMetricsLowEntropySource);
214 local_state_->ClearPref(prefs::kMetricsResetIds); 308 local_state_->ClearPref(prefs::kMetricsResetIds);
Ilya Sherman 2014/07/11 23:25:00 This should clear the backup as well. (Looks like
gab 2014/07/14 19:17:14 Done (and sorry I missed that previously, definite
215 } 309 }
216 310
217 } // namespace metrics 311 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698