[M120 Migration][VD] Enable direct rendering for TVPlus
[platform/framework/web/chromium-efl.git] / components / metrics / entropy_state.cc
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 #include "components/metrics/entropy_state.h"
6
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram_functions.h"
10 #include "base/rand_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "components/metrics/metrics_pref_names.h"
13 #include "components/metrics/metrics_switches.h"
14 #include "components/prefs/pref_service.h"
15
16 #if BUILDFLAG(IS_ANDROID)
17 #include "base/android/jni_android.h"
18 #include "components/metrics/jni_headers/LowEntropySource_jni.h"
19 #endif  // BUILDFLAG(IS_ANDROID)
20
21 namespace metrics {
22
23 namespace {
24
25 #if BUILDFLAG(IS_CHROMEOS_LACROS)
26 // Needed for a check to see if we retrieved entropy values before we have
27 // transferred them from Ash.
28 bool g_entropy_source_has_been_retrieved = false;
29 bool g_entropy_source_has_been_set = false;
30 #endif
31
32 // Generates a new non-identifying entropy source used to seed persistent
33 // activities. Make it static so that the new low entropy source value will
34 // only be generated on first access. And thus, even though we may write the
35 // new low entropy source value to prefs multiple times, it stays the same
36 // value.
37 int GenerateLowEntropySource() {
38 #if BUILDFLAG(IS_ANDROID)
39   // Note: As in the non-Android case below, the Java implementation also uses
40   // a static cache, so subsequent invocations will return the same value.
41   JNIEnv* env = base::android::AttachCurrentThread();
42   return Java_LowEntropySource_generateLowEntropySource(env);
43 #else
44   static const int low_entropy_source =
45       base::RandInt(0, EntropyState::kMaxLowEntropySize - 1);
46   return low_entropy_source;
47 #endif  // BUILDFLAG(IS_ANDROID)
48 }
49
50 // Generates a new non-identifying low entropy source using the same method
51 // that's used for the actual low entropy source. This one, however, is only
52 // used for statistical validation, and *not* for randomization or experiment
53 // assignment.
54 int GeneratePseudoLowEntropySource() {
55 #if BUILDFLAG(IS_ANDROID)
56   // Note: As in the non-Android case below, the Java implementation also uses
57   // a static cache, so subsequent invocations will return the same value.
58   JNIEnv* env = base::android::AttachCurrentThread();
59   return Java_LowEntropySource_generatePseudoLowEntropySource(env);
60 #else
61   static const int pseudo_low_entropy_source =
62       base::RandInt(0, EntropyState::kMaxLowEntropySize - 1);
63   return pseudo_low_entropy_source;
64 #endif  // BUILDFLAG(IS_ANDROID)
65 }
66
67 }  // namespace
68
69 EntropyState::EntropyState(PrefService* local_state)
70     : local_state_(local_state) {}
71
72 // static
73 constexpr int EntropyState::kLowEntropySourceNotSet;
74
75 // static
76 void EntropyState::ClearPrefs(PrefService* local_state) {
77 #if BUILDFLAG(IS_CHROMEOS_LACROS)
78   // There are currently multiple EntropyState objects (crbug/1495576) and as
79   // Lacros does not own the entropy values anyways, it shouldn't clear them
80   // either.
81   LOG(WARNING) << "EntropyState::ClearPrefs ignored as set remotely.";
82 #else
83   local_state->ClearPref(prefs::kMetricsLowEntropySource);
84   local_state->ClearPref(prefs::kMetricsOldLowEntropySource);
85   local_state->ClearPref(prefs::kMetricsPseudoLowEntropySource);
86 #endif
87 }
88
89 // static
90 void EntropyState::RegisterPrefs(PrefRegistrySimple* registry) {
91   registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource,
92                                 kLowEntropySourceNotSet);
93   registry->RegisterIntegerPref(prefs::kMetricsOldLowEntropySource,
94                                 kLowEntropySourceNotSet);
95   registry->RegisterIntegerPref(prefs::kMetricsPseudoLowEntropySource,
96                                 kLowEntropySourceNotSet);
97 }
98
99 #if BUILDFLAG(IS_CHROMEOS_LACROS)
100 // static
101 void EntropyState::SetExternalPrefs(PrefService* local_state,
102                                     int low_entropy_source,
103                                     int old_low_entropy_source,
104                                     int pseudo_low_entropy_source) {
105   if (!g_entropy_source_has_been_set) {
106     g_entropy_source_has_been_set = true;
107     // As an |EntropyState| object has an internal state, we need to make sure
108     // that none gets read before the Ash values have been transferred.
109     // This is usually taken care of by
110     // `ChromeMetricsServicesManagerClient::GetMetricsStateManager` which first
111     // sets the Ash values and then creates the `MetricsStateManager`.
112     if (g_entropy_source_has_been_retrieved) {
113       LOG(ERROR) << "Entropy value was retrieved before they were updated";
114     }
115     DCHECK(!g_entropy_source_has_been_retrieved);
116   }
117   local_state->SetInteger(prefs::kMetricsLowEntropySource, low_entropy_source);
118   local_state->SetInteger(prefs::kMetricsOldLowEntropySource,
119                           old_low_entropy_source);
120   local_state->SetInteger(prefs::kMetricsPseudoLowEntropySource,
121                           pseudo_low_entropy_source);
122 }
123 #endif
124
125 std::string EntropyState::GetHighEntropySource(
126     const std::string& initial_client_id) {
127   DCHECK(!initial_client_id.empty());
128   // For metrics reporting-enabled users, we combine the client ID and low
129   // entropy source to get the final entropy source.
130   // This has two useful properties:
131   //  1) It makes the entropy source less identifiable for parties that do not
132   //     know the low entropy source.
133   //  2) It makes the final entropy source resettable.
134
135   // If this install has an old low entropy source, continue using it, to avoid
136   // changing the group assignments of studies using high entropy. New installs
137   // only have the new low entropy source. If the number of installs with old
138   // sources ever becomes small enough (see UMA.LowEntropySourceValue), we could
139   // remove it, and just use the new source here.
140   int low_entropy_source = GetOldLowEntropySource();
141   if (low_entropy_source == kLowEntropySourceNotSet)
142     low_entropy_source = GetLowEntropySource();
143
144   return initial_client_id + base::NumberToString(low_entropy_source);
145 }
146
147 int EntropyState::GetLowEntropySource() {
148   UpdateLowEntropySources();
149   return low_entropy_source_;
150 }
151
152 int EntropyState::GetPseudoLowEntropySource() {
153   UpdateLowEntropySources();
154   return pseudo_low_entropy_source_;
155 }
156
157 int EntropyState::GetOldLowEntropySource() {
158   UpdateLowEntropySources();
159   return old_low_entropy_source_;
160 }
161
162 void EntropyState::UpdateLowEntropySources() {
163 #if BUILDFLAG(IS_CHROMEOS_LACROS)
164   // Coming here, someone was reading an entropy value.
165   g_entropy_source_has_been_retrieved = true;
166 #endif
167   // The default value for |low_entropy_source_| and the default pref value are
168   // both |kLowEntropySourceNotSet|, which indicates the value has not been set.
169   if (low_entropy_source_ != kLowEntropySourceNotSet &&
170       pseudo_low_entropy_source_ != kLowEntropySourceNotSet)
171     return;
172
173   const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
174   // Only try to load the value from prefs if the user did not request a reset.
175   // Otherwise, skip to generating a new value. We would have already returned
176   // if both |low_entropy_source_| and |pseudo_low_entropy_source_| were set,
177   // ensuring we only do this reset on the first call to
178   // UpdateLowEntropySources().
179   if (!command_line->HasSwitch(switches::kResetVariationState)) {
180     int new_pref = local_state_->GetInteger(prefs::kMetricsLowEntropySource);
181     if (IsValidLowEntropySource(new_pref))
182       low_entropy_source_ = new_pref;
183     int old_pref = local_state_->GetInteger(prefs::kMetricsOldLowEntropySource);
184     if (IsValidLowEntropySource(old_pref))
185       old_low_entropy_source_ = old_pref;
186     int pseudo_pref =
187         local_state_->GetInteger(prefs::kMetricsPseudoLowEntropySource);
188     if (IsValidLowEntropySource(pseudo_pref))
189       pseudo_low_entropy_source_ = pseudo_pref;
190   }
191
192   // If the new source is missing or corrupt (or requested to be reset), then
193   // (re)create it. Don't bother recreating the old source if it's corrupt,
194   // because we only keep the old source around for consistency, and we can't
195   // maintain a consistent value if we recreate it.
196   if (low_entropy_source_ == kLowEntropySourceNotSet) {
197     low_entropy_source_ = GenerateLowEntropySource();
198     DCHECK(IsValidLowEntropySource(low_entropy_source_));
199     local_state_->SetInteger(prefs::kMetricsLowEntropySource,
200                              low_entropy_source_);
201   }
202
203   // If the pseudo source is missing or corrupt (or requested to be reset), then
204   // (re)create it. Don't bother recreating the old source if it's corrupt,
205   // because we only keep the old source around for consistency, and we can't
206   // maintain a consistent value if we recreate it.
207   if (pseudo_low_entropy_source_ == kLowEntropySourceNotSet) {
208     pseudo_low_entropy_source_ = GeneratePseudoLowEntropySource();
209     DCHECK(IsValidLowEntropySource(pseudo_low_entropy_source_));
210     local_state_->SetInteger(prefs::kMetricsPseudoLowEntropySource,
211                              pseudo_low_entropy_source_);
212   }
213
214   // If the old source was present but corrupt (or requested to be reset), then
215   // we'll never use it again, so delete it.
216   if (old_low_entropy_source_ == kLowEntropySourceNotSet &&
217       local_state_->HasPrefPath(prefs::kMetricsOldLowEntropySource)) {
218     local_state_->ClearPref(prefs::kMetricsOldLowEntropySource);
219   }
220
221   DCHECK_NE(low_entropy_source_, kLowEntropySourceNotSet);
222 }
223
224 // static
225 bool EntropyState::IsValidLowEntropySource(int value) {
226   return value >= 0 && value < kMaxLowEntropySize;
227 }
228
229 }  // namespace metrics