xref: /aosp_15_r20/external/cronet/components/metrics/entropy_state.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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