// Copyright 2020 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_METRICS_ENTROPY_STATE_H_ #define COMPONENTS_METRICS_ENTROPY_STATE_H_ #include #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "components/prefs/pref_registry_simple.h" class PrefService; namespace metrics { // A class to get entropy source values from the PrefService. class EntropyState final { public: // Creates the EntropyState with the given |local_state| to get // the entropy source value from this helper class. explicit EntropyState(PrefService* local_state); EntropyState(const EntropyState&) = delete; EntropyState& operator=(const EntropyState&) = delete; // Clears low_entropy_source and old_low_entropy_source in the prefs. static void ClearPrefs(PrefService* local_state); // Registers low_entropy_source and old_low_entropy_source in the prefs. static void RegisterPrefs(PrefRegistrySimple* registry); #if BUILDFLAG(IS_CHROMEOS_LACROS) // Overriding the entropy source preferences with new values as given by // Ash upon initialization, before the MetricsService gets created. // |limited_entropy_randomization_source| will only be overridden if it's // valid. See IsValidLimitedEntropyRandomizationSource(). static void SetExternalPrefs( PrefService* local_state, int low_entropy_source, int old_low_entropy_source, int pseudo_low_entropy_source, std::string_view limited_entropy_randomization_source); #endif // Returns the high entropy source for this client, which is composed of a // client ID and the low entropy source. This is intended to be unique for // each install. |initial_client_id| is the client_id that was used to // randomize field trials and must not be empty. std::string GetHighEntropySource(const std::string& initial_client_id); // Returns the low entropy source that is used to randomize field trials on // startup for this client. Generates a new value if there is none. See the // |low_entropy_source_| comment for more info. int GetLowEntropySource(); // Returns the pseudo low entropy source for this client. Generates a new // value if there is none. See the |pseudo_low_entropy_source_| comment // for more info. int GetPseudoLowEntropySource(); // Returns the old low entropy source for this client. Does not generate a new // value, but instead returns |kLowEntropySourceNotSet|, if there is none. See // the |old_low_entropy_source_| comment for more info. int GetOldLowEntropySource(); // Returns the limited entropy randomization source that is used to randomize // field trials in a limited entropy layer. Generates a new value if there is // none. See the |limited_entropy_randomization_source_| comment for more // info. std::string_view GetLimitedEntropyRandomizationSource(); // The argument used to generate a non-identifying entropy source. We want no // more than 13 bits of entropy, so use this max to return a number in the // range [0, 7999] as the entropy source (12.97 bits of entropy). // // The value should be kept consistent with // LowEntropySource.MAX_LOW_ENTROPY_SIZE in Java. static constexpr int kMaxLowEntropySize = 8000; private: FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, LowEntropySourceNotReset); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, PseudoLowEntropySourceNotReset); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveNoLowEntropySource); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveOnlyNewLowEntropySource); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveOnlyOldLowEntropySource); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, CorruptNewLowEntropySources); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, CorruptOldLowEntropySources); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, ValidLimitedEntropyRandomizationSource); FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, InvalidLimitedEntropyRandomizationSource); // Default value for prefs::kMetricsLowEntropySource. static constexpr int kLowEntropySourceNotSet = -1; // Loads the low entropy source values from prefs. Creates the new source // value if it doesn't exist, but doesn't create the old source value. After // this function finishes, |low_entropy_source_| will be set, but // |old_low_entropy_source_| may still be |kLowEntropySourceNotSet|. void UpdateLowEntropySources(); // Returns the limited entropy randomization source value if one is already // set. Otherwise, attempts to generate a new one either when there isn't a // previously set one stored in prefs, or when the command line flag // --reset-variation-state is set. In both cases, the newly generated value // will be set and stored stored in prefs before returning. void UpdateLimitedEntropyRandomizationSource(); // Checks whether a value is on the range of allowed low entropy source // values. static bool IsValidLowEntropySource(int value); // Checks whether the given value is a valid limited entropy randomization // source. static bool IsValidLimitedEntropyRandomizationSource(std::string_view value); // Generates a new limited entropy randomization source. std::string GenerateLimitedEntropyRandomizationSource(); // The local state prefs store. const raw_ptr local_state_; // The non-identifying low entropy source values. These values seed the // pseudorandom generators which pick experimental groups. The "old" value is // thought to be biased in the wild, and is no longer used for experiments // requiring low entropy. Clients which already have an "old" value continue // incorporating it into the high entropy source, to avoid changing those // group assignments. New clients only have the new source. // // The pseudo-low entropy source is not used for experiment diversion, but // only for statistical validation. (Since it's not used for experiment // diversion, it won't be subject to drift over time as experiment effects // accumulate in actual low entropy source buckets.) // // During startup these are set to the values used for randomizing field // trials and won't be changed within the session even after calling // |ClearPrefs|. int low_entropy_source_ = kLowEntropySourceNotSet; int old_low_entropy_source_ = kLowEntropySourceNotSet; int pseudo_low_entropy_source_ = kLowEntropySourceNotSet; // This value is used to seed the randomization for field trials in the // limited entropy layer. During startup this value is set to one that's // previously set. If a previously set value is not available, it will // generate a new one. See more in the comments of // |UpdateLimitedEntropyRandomizationSource|. // // Similar to the |low_entropy_source_| above, this value won't be changed // within the session, even after calling |ClearPrefs|. std::string limited_entropy_randomization_source_; }; } // namespace metrics #endif // COMPONENTS_METRICS_ENTROPY_STATE_H_