metrics_state_manager.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/metrics/metrics_state_manager.h" 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/command_line.h" 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/guid.h" 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/metrics/histogram.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/metrics/sparse_histogram.h" 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/prefs/pref_service.h" 13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/rand_util.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/time/time.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/metrics/cloned_install_detector.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/metrics/machine_id_provider.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/metrics/metrics_pref_names.h" 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/metrics/metrics_switches.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/variations/caching_permuted_entropy_provider.h" 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace metrics { 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace { 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// The argument used to generate a non-identifying entropy source. We want no 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// more than 13 bits of entropy, so use this max to return a number in the range 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// [0, 7999] as the entropy source (12.97 bits of entropy). 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int kMaxLowEntropySize = 8000; 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Default prefs value for prefs::kMetricsLowEntropySource to indicate that 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// the value has not yet been set. 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int kLowEntropySourceNotSet = -1; 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Generates a new non-identifying entropy source used to seed persistent 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// activities. 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int GenerateLowEntropySource() { 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return base::RandInt(0, kMaxLowEntropySize - 1); 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace 42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool MetricsStateManager::instance_exists_ = false; 45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MetricsStateManager::MetricsStateManager( 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state, 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::Callback<bool(void)>& is_reporting_enabled_callback, 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const StoreClientInfoCallback& store_client_info, 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const LoadClientInfoCallback& retrieve_client_info) 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : local_state_(local_state), 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) is_reporting_enabled_callback_(is_reporting_enabled_callback), 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) store_client_info_(store_client_info), 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) load_client_info_(retrieve_client_info), 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) low_entropy_source_(kLowEntropySourceNotSet), 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entropy_source_returned_(ENTROPY_SOURCE_NONE) { 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ResetMetricsIDsIfNecessary(); 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (IsMetricsReportingEnabled()) 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ForceClientIdCreation(); 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!instance_exists_); 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) instance_exists_ = true; 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)MetricsStateManager::~MetricsStateManager() { 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(instance_exists_); 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) instance_exists_ = false; 68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool MetricsStateManager::IsMetricsReportingEnabled() { 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return is_reporting_enabled_callback_.Run(); 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MetricsStateManager::ForceClientIdCreation() { 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!client_id_.empty()) 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) client_id_ = local_state_->GetString(prefs::kMetricsClientID); 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!client_id_.empty()) { 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // It is technically sufficient to only save a backup of the client id when 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // it is initially generated below, but since the backup was only introduced 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // in M38, seed it explicitly from here for some time. 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BackUpCurrentClientInfo(); 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const scoped_ptr<ClientInfo> client_info_backup = 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LoadClientInfoAndMaybeMigrate(); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (client_info_backup) { 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_id_ = client_info_backup->client_id; 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::Time now = base::Time::Now(); 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Save the recovered client id and also try to reinstantiate the backup 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // values for the dates corresponding with that client id in order to avoid 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // weird scenarios where we could report an old client id with a recent 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // install date. 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) local_state_->SetString(prefs::kMetricsClientID, client_id_); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) local_state_->SetInt64(prefs::kInstallDate, 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_info_backup->installation_date != 0 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ? client_info_backup->installation_date 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : now.ToTimeT()); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) local_state_->SetInt64(prefs::kMetricsReportingEnabledTimestamp, 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_info_backup->reporting_enabled_date != 0 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ? client_info_backup->reporting_enabled_date 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : now.ToTimeT()); 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::TimeDelta recovered_installation_age; 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (client_info_backup->installation_date != 0) { 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) recovered_installation_age = 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) now - base::Time::FromTimeT(client_info_backup->installation_date); 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UMA_HISTOGRAM_COUNTS_10000("UMA.ClientIdBackupRecoveredWithAge", 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) recovered_installation_age.InHours()); 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Flush the backup back to persistent storage in case we re-generated 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // missing data above. 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BackUpCurrentClientInfo(); 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Failing attempts at getting an existing client ID, generate a new one. 123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) client_id_ = base::GenerateGUID(); 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state_->SetString(prefs::kMetricsClientID, client_id_); 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (local_state_->GetString(prefs::kMetricsOldClientID).empty()) { 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Record the timestamp of when the user opted in to UMA. 12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state_->SetInt64(prefs::kMetricsReportingEnabledTimestamp, 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Time::Now().ToTimeT()); 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } else { 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("UMA.ClientIdMigrated", true); 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state_->ClearPref(prefs::kMetricsOldClientID); 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BackUpCurrentClientInfo(); 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void MetricsStateManager::CheckForClonedInstall( 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> task_runner) { 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!cloned_install_detector_); 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MachineIdProvider* provider = MachineIdProvider::CreateInstance(); 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!provider) 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) cloned_install_detector_.reset(new ClonedInstallDetector(provider)); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cloned_install_detector_->CheckForClonedInstall(local_state_, task_runner); 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_ptr<const base::FieldTrial::EntropyProvider> 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)MetricsStateManager::CreateEntropyProvider() { 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // For metrics reporting-enabled users, we combine the client ID and low 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // entropy source to get the final entropy source. Otherwise, only use the low 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // entropy source. 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // This has two useful properties: 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // 1) It makes the entropy source less identifiable for parties that do not 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // know the low entropy source. 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // 2) It makes the final entropy source resettable. 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int low_entropy_source_value = GetLowEntropySource(); 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("UMA.LowEntropySourceValue", 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) low_entropy_source_value); 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (IsMetricsReportingEnabled()) { 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (entropy_source_returned_ == ENTROPY_SOURCE_NONE) 164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entropy_source_returned_ = ENTROPY_SOURCE_HIGH; 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_EQ(ENTROPY_SOURCE_HIGH, entropy_source_returned_); 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string high_entropy_source = 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) client_id_ + base::IntToString(low_entropy_source_value); 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return scoped_ptr<const base::FieldTrial::EntropyProvider>( 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new SHA1EntropyProvider(high_entropy_source)); 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (entropy_source_returned_ == ENTROPY_SOURCE_NONE) 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entropy_source_returned_ = ENTROPY_SOURCE_LOW; 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_EQ(ENTROPY_SOURCE_LOW, entropy_source_returned_); 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_ANDROID) || defined(OS_IOS) 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return scoped_ptr<const base::FieldTrial::EntropyProvider>( 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new CachingPermutedEntropyProvider(local_state_, 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) low_entropy_source_value, 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kMaxLowEntropySize)); 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#else 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return scoped_ptr<const base::FieldTrial::EntropyProvider>( 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new PermutedEntropyProvider(low_entropy_source_value, 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kMaxLowEntropySize)); 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_ptr<MetricsStateManager> MetricsStateManager::Create( 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state, 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::Callback<bool(void)>& is_reporting_enabled_callback, 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const StoreClientInfoCallback& store_client_info, 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const LoadClientInfoCallback& retrieve_client_info) { 194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<MetricsStateManager> result; 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Note: |instance_exists_| is updated in the constructor and destructor. 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!instance_exists_) { 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result.reset(new MetricsStateManager(local_state, 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_reporting_enabled_callback, 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) store_client_info, 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) retrieve_client_info)); 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return result.Pass(); 203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static 206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MetricsStateManager::RegisterPrefs(PrefRegistrySimple* registry) { 207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) registry->RegisterBooleanPref(prefs::kMetricsResetIds, false); 20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) registry->RegisterStringPref(prefs::kMetricsClientID, std::string()); 20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) registry->RegisterInt64Pref(prefs::kMetricsReportingEnabledTimestamp, 0); 21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource, 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kLowEntropySourceNotSet); 212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ClonedInstallDetector::RegisterPrefs(registry); 214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CachingPermutedEntropyProvider::RegisterPrefs(registry); 215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // TODO(asvitkine): Remove these once a couple of releases have passed. 217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // http://crbug.com/357704 21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) registry->RegisterStringPref(prefs::kMetricsOldClientID, std::string()); 21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) registry->RegisterIntegerPref(prefs::kMetricsOldLowEntropySource, 0); 220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void MetricsStateManager::BackUpCurrentClientInfo() { 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ClientInfo client_info; 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_info.client_id = client_id_; 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_info.installation_date = local_state_->GetInt64(prefs::kInstallDate); 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_info.reporting_enabled_date = 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) local_state_->GetInt64(prefs::kMetricsReportingEnabledTimestamp); 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) store_client_info_.Run(client_info); 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<ClientInfo> MetricsStateManager::LoadClientInfoAndMaybeMigrate() { 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<metrics::ClientInfo> client_info = load_client_info_.Run(); 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Prior to 2014-07, the client ID was stripped of its dashes before being 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // saved. Migrate back to a proper GUID if this is the case. This migration 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // code can be removed in M41+. 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const size_t kGUIDLengthWithoutDashes = 32U; 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (client_info && 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_info->client_id.length() == kGUIDLengthWithoutDashes) { 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(client_info->client_id.find('-') == std::string::npos); 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string client_id_with_dashes; 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_id_with_dashes.reserve(kGUIDLengthWithoutDashes + 4U); 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string::const_iterator client_id_it = client_info->client_id.begin(); 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < kGUIDLengthWithoutDashes + 4U; ++i) { 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (i == 8U || i == 13U || i == 18U || i == 23U) { 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_id_with_dashes.push_back('-'); 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_id_with_dashes.push_back(*client_id_it); 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++client_id_it; 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(client_id_it == client_info->client_id.end()); 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_info->client_id.assign(client_id_with_dashes); 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The GUID retrieved (and possibly fixed above) should be valid unless 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // retrieval failed. 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(!client_info || base::IsValidGUID(client_info->client_id)); 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return client_info.Pass(); 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int MetricsStateManager::GetLowEntropySource() { 265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Note that the default value for the low entropy source and the default pref 266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // value are both kLowEntropySourceNotSet, which is used to identify if the 267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // value has been set or not. 268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (low_entropy_source_ != kLowEntropySourceNotSet) 269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return low_entropy_source_; 270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const CommandLine* command_line(CommandLine::ForCurrentProcess()); 27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Only try to load the value from prefs if the user did not request a 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // reset. 274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Otherwise, skip to generating a new value. 275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!command_line->HasSwitch(switches::kResetVariationState)) { 27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int value = local_state_->GetInteger(prefs::kMetricsLowEntropySource); 277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // If the value is outside the [0, kMaxLowEntropySize) range, re-generate 278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // it below. 279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (value >= 0 && value < kMaxLowEntropySize) { 280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) low_entropy_source_ = value; 281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("UMA.GeneratedLowEntropySource", false); 282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return low_entropy_source_; 283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("UMA.GeneratedLowEntropySource", true); 287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) low_entropy_source_ = GenerateLowEntropySource(); 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state_->SetInteger(prefs::kMetricsLowEntropySource, 289010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) low_entropy_source_); 29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state_->ClearPref(prefs::kMetricsOldLowEntropySource); 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CachingPermutedEntropyProvider::ClearCache(local_state_); 292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 293010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return low_entropy_source_; 294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MetricsStateManager::ResetMetricsIDsIfNecessary() { 297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!local_state_->GetBoolean(prefs::kMetricsResetIds)) 298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("UMA.MetricsIDsReset", true); 301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(client_id_.empty()); 303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_EQ(kLowEntropySourceNotSet, low_entropy_source_); 304010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state_->ClearPref(prefs::kMetricsClientID); 30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state_->ClearPref(prefs::kMetricsLowEntropySource); 307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) local_state_->ClearPref(prefs::kMetricsResetIds); 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Also clear the backed up client info. 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) store_client_info_.Run(ClientInfo()); 311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace metrics 314