1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_METRICS_ENTROPY_STATE_H_ 6 #define COMPONENTS_METRICS_ENTROPY_STATE_H_ 7 8 #include <string> 9 10 #include "base/gtest_prod_util.h" 11 #include "base/memory/raw_ptr.h" 12 #include "components/prefs/pref_registry_simple.h" 13 14 class PrefService; 15 16 namespace metrics { 17 18 // A class to get entropy source values from the PrefService. 19 class EntropyState final { 20 public: 21 // Creates the EntropyState with the given |local_state| to get 22 // the entropy source value from this helper class. 23 explicit EntropyState(PrefService* local_state); 24 25 EntropyState(const EntropyState&) = delete; 26 EntropyState& operator=(const EntropyState&) = delete; 27 28 // Clears low_entropy_source and old_low_entropy_source in the prefs. 29 static void ClearPrefs(PrefService* local_state); 30 31 // Registers low_entropy_source and old_low_entropy_source in the prefs. 32 static void RegisterPrefs(PrefRegistrySimple* registry); 33 34 #if BUILDFLAG(IS_CHROMEOS_LACROS) 35 // Overriding the entropy source preferences with new values as given by 36 // Ash upon initialization, before the MetricsService gets created. 37 // |limited_entropy_randomization_source| will only be overridden if it's 38 // valid. See IsValidLimitedEntropyRandomizationSource(). 39 static void SetExternalPrefs( 40 PrefService* local_state, 41 int low_entropy_source, 42 int old_low_entropy_source, 43 int pseudo_low_entropy_source, 44 std::string_view limited_entropy_randomization_source); 45 #endif 46 47 // Returns the high entropy source for this client, which is composed of a 48 // client ID and the low entropy source. This is intended to be unique for 49 // each install. |initial_client_id| is the client_id that was used to 50 // randomize field trials and must not be empty. 51 std::string GetHighEntropySource(const std::string& initial_client_id); 52 53 // Returns the low entropy source that is used to randomize field trials on 54 // startup for this client. Generates a new value if there is none. See the 55 // |low_entropy_source_| comment for more info. 56 int GetLowEntropySource(); 57 58 // Returns the pseudo low entropy source for this client. Generates a new 59 // value if there is none. See the |pseudo_low_entropy_source_| comment 60 // for more info. 61 int GetPseudoLowEntropySource(); 62 63 // Returns the old low entropy source for this client. Does not generate a new 64 // value, but instead returns |kLowEntropySourceNotSet|, if there is none. See 65 // the |old_low_entropy_source_| comment for more info. 66 int GetOldLowEntropySource(); 67 68 // Returns the limited entropy randomization source that is used to randomize 69 // field trials in a limited entropy layer. Generates a new value if there is 70 // none. See the |limited_entropy_randomization_source_| comment for more 71 // info. 72 std::string_view GetLimitedEntropyRandomizationSource(); 73 74 // The argument used to generate a non-identifying entropy source. We want no 75 // more than 13 bits of entropy, so use this max to return a number in the 76 // range [0, 7999] as the entropy source (12.97 bits of entropy). 77 // 78 // The value should be kept consistent with 79 // LowEntropySource.MAX_LOW_ENTROPY_SIZE in Java. 80 static constexpr int kMaxLowEntropySize = 8000; 81 82 private: 83 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, LowEntropySourceNotReset); 84 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, PseudoLowEntropySourceNotReset); 85 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveNoLowEntropySource); 86 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveOnlyNewLowEntropySource); 87 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveOnlyOldLowEntropySource); 88 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, CorruptNewLowEntropySources); 89 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, CorruptOldLowEntropySources); 90 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, 91 ValidLimitedEntropyRandomizationSource); 92 FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, 93 InvalidLimitedEntropyRandomizationSource); 94 95 // Default value for prefs::kMetricsLowEntropySource. 96 static constexpr int kLowEntropySourceNotSet = -1; 97 98 // Loads the low entropy source values from prefs. Creates the new source 99 // value if it doesn't exist, but doesn't create the old source value. After 100 // this function finishes, |low_entropy_source_| will be set, but 101 // |old_low_entropy_source_| may still be |kLowEntropySourceNotSet|. 102 void UpdateLowEntropySources(); 103 104 // Returns the limited entropy randomization source value if one is already 105 // set. Otherwise, attempts to generate a new one either when there isn't a 106 // previously set one stored in prefs, or when the command line flag 107 // --reset-variation-state is set. In both cases, the newly generated value 108 // will be set and stored stored in prefs before returning. 109 void UpdateLimitedEntropyRandomizationSource(); 110 111 // Checks whether a value is on the range of allowed low entropy source 112 // values. 113 static bool IsValidLowEntropySource(int value); 114 115 // Checks whether the given value is a valid limited entropy randomization 116 // source. 117 static bool IsValidLimitedEntropyRandomizationSource(std::string_view value); 118 119 // Generates a new limited entropy randomization source. 120 std::string GenerateLimitedEntropyRandomizationSource(); 121 122 // The local state prefs store. 123 const raw_ptr<PrefService> local_state_; 124 125 // The non-identifying low entropy source values. These values seed the 126 // pseudorandom generators which pick experimental groups. The "old" value is 127 // thought to be biased in the wild, and is no longer used for experiments 128 // requiring low entropy. Clients which already have an "old" value continue 129 // incorporating it into the high entropy source, to avoid changing those 130 // group assignments. New clients only have the new source. 131 // 132 // The pseudo-low entropy source is not used for experiment diversion, but 133 // only for statistical validation. (Since it's not used for experiment 134 // diversion, it won't be subject to drift over time as experiment effects 135 // accumulate in actual low entropy source buckets.) 136 // 137 // During startup these are set to the values used for randomizing field 138 // trials and won't be changed within the session even after calling 139 // |ClearPrefs|. 140 int low_entropy_source_ = kLowEntropySourceNotSet; 141 int old_low_entropy_source_ = kLowEntropySourceNotSet; 142 int pseudo_low_entropy_source_ = kLowEntropySourceNotSet; 143 144 // This value is used to seed the randomization for field trials in the 145 // limited entropy layer. During startup this value is set to one that's 146 // previously set. If a previously set value is not available, it will 147 // generate a new one. See more in the comments of 148 // |UpdateLimitedEntropyRandomizationSource|. 149 // 150 // Similar to the |low_entropy_source_| above, this value won't be changed 151 // within the session, even after calling |ClearPrefs|. 152 std::string limited_entropy_randomization_source_; 153 }; 154 155 } // namespace metrics 156 157 #endif // COMPONENTS_METRICS_ENTROPY_STATE_H_ 158