xref: /aosp_15_r20/external/cronet/base/metrics/field_trial.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker // The FieldTrial class handles the lower level configuration of running A/B
6*6777b538SAndroid Build Coastguard Worker // tests.
7*6777b538SAndroid Build Coastguard Worker //
8*6777b538SAndroid Build Coastguard Worker // Most server-side experiments should be configured using Features which
9*6777b538SAndroid Build Coastguard Worker // have a simpler interface. See base/feature_list.h for details on
10*6777b538SAndroid Build Coastguard Worker // configurating a Feature for an experiment.
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker // In certain cases you may still need to use FieldTrial directly. This is
13*6777b538SAndroid Build Coastguard Worker // generally for either:
14*6777b538SAndroid Build Coastguard Worker // - Client-configured experiments:
15*6777b538SAndroid Build Coastguard Worker //     The experiment is controlled directly in the code. For example, if the
16*6777b538SAndroid Build Coastguard Worker //     server controlled behavior is not yet available. See below documentation.
17*6777b538SAndroid Build Coastguard Worker // - Synthetic field trials:
18*6777b538SAndroid Build Coastguard Worker //     These act like field trials for reporting purposes, but the group
19*6777b538SAndroid Build Coastguard Worker //     placement is controlled directly. See RegisterSyntheticFieldTrial().
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // If you have access, see go/client-side-field-trials for additional context.
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
24*6777b538SAndroid Build Coastguard Worker // Details:
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // FieldTrial is a class for handling details of statistical experiments
27*6777b538SAndroid Build Coastguard Worker // performed by actual users in the field (i.e., in a shipped or beta product).
28*6777b538SAndroid Build Coastguard Worker // All code is called exclusively on the UI thread currently. It only handles
29*6777b538SAndroid Build Coastguard Worker // the lower level details, server-side experiments should use
30*6777b538SAndroid Build Coastguard Worker // generally use Features (see above).
31*6777b538SAndroid Build Coastguard Worker //
32*6777b538SAndroid Build Coastguard Worker // The simplest example is an experiment to see whether one of two options
33*6777b538SAndroid Build Coastguard Worker // produces "better" results across our user population.  In that scenario, UMA
34*6777b538SAndroid Build Coastguard Worker // data is uploaded to aggregate the test results, and this FieldTrial class
35*6777b538SAndroid Build Coastguard Worker // manages the state of each such experiment (state == which option was
36*6777b538SAndroid Build Coastguard Worker // pseudo-randomly selected).
37*6777b538SAndroid Build Coastguard Worker //
38*6777b538SAndroid Build Coastguard Worker // States are typically generated randomly, either based on a one time
39*6777b538SAndroid Build Coastguard Worker // randomization (which will yield the same results, in terms of selecting
40*6777b538SAndroid Build Coastguard Worker // the client for a field trial or not, for every run of the program on a
41*6777b538SAndroid Build Coastguard Worker // given machine), or by a session randomization (generated each time the
42*6777b538SAndroid Build Coastguard Worker // application starts up, but held constant during the duration of the
43*6777b538SAndroid Build Coastguard Worker // process).
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
46*6777b538SAndroid Build Coastguard Worker // Example:  Suppose we have an experiment involving memory, such as determining
47*6777b538SAndroid Build Coastguard Worker // the impact of some pruning algorithm. Note that using this API directly is
48*6777b538SAndroid Build Coastguard Worker // not recommended, see above.
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker // // FieldTrials are reference counted, and persist automagically until
51*6777b538SAndroid Build Coastguard Worker // // process teardown, courtesy of their automatic registration in
52*6777b538SAndroid Build Coastguard Worker // // FieldTrialList.
53*6777b538SAndroid Build Coastguard Worker // scoped_refptr<base::FieldTrial> trial(
54*6777b538SAndroid Build Coastguard Worker //     base::FieldTrialList::FactoryGetFieldTrial(
55*6777b538SAndroid Build Coastguard Worker //         "MemoryExperiment", 1000, "StandardMem", entropy_provider);
56*6777b538SAndroid Build Coastguard Worker //
57*6777b538SAndroid Build Coastguard Worker // trial->AppendGroup("HighMem", 20);  // 2% in HighMem group.
58*6777b538SAndroid Build Coastguard Worker // trial->AppendGroup("LowMem", 20);   // 2% in LowMem group.
59*6777b538SAndroid Build Coastguard Worker // // Take action depending of which group we randomly land in.
60*6777b538SAndroid Build Coastguard Worker // if (trial->group_name() == "HighMem")
61*6777b538SAndroid Build Coastguard Worker //   SetPruningAlgorithm(kType1);
62*6777b538SAndroid Build Coastguard Worker // else if (trial->group_name() == "LowMem")
63*6777b538SAndroid Build Coastguard Worker //   SetPruningAlgorithm(kType2);
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker #ifndef BASE_METRICS_FIELD_TRIAL_H_
68*6777b538SAndroid Build Coastguard Worker #define BASE_METRICS_FIELD_TRIAL_H_
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
71*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker #include <atomic>
74*6777b538SAndroid Build Coastguard Worker #include <functional>
75*6777b538SAndroid Build Coastguard Worker #include <map>
76*6777b538SAndroid Build Coastguard Worker #include <memory>
77*6777b538SAndroid Build Coastguard Worker #include <set>
78*6777b538SAndroid Build Coastguard Worker #include <string>
79*6777b538SAndroid Build Coastguard Worker #include <string_view>
80*6777b538SAndroid Build Coastguard Worker #include <vector>
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker #include "base/atomicops.h"
83*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
84*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
85*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
86*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h"
87*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
88*6777b538SAndroid Build Coastguard Worker #include "base/memory/read_only_shared_memory_region.h"
89*6777b538SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
90*6777b538SAndroid Build Coastguard Worker #include "base/memory/shared_memory_mapping.h"
91*6777b538SAndroid Build Coastguard Worker #include "base/metrics/persistent_memory_allocator.h"
92*6777b538SAndroid Build Coastguard Worker #include "base/pickle.h"
93*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
94*6777b538SAndroid Build Coastguard Worker #include "base/types/expected.h"
95*6777b538SAndroid Build Coastguard Worker #include "base/types/pass_key.h"
96*6777b538SAndroid Build Coastguard Worker #include "build/blink_buildflags.h"
97*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
100*6777b538SAndroid Build Coastguard Worker #include "base/files/platform_file.h"
101*6777b538SAndroid Build Coastguard Worker #include "base/posix/global_descriptors.h"
102*6777b538SAndroid Build Coastguard Worker #endif
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker namespace base {
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker namespace test {
107*6777b538SAndroid Build Coastguard Worker class ScopedFeatureList;
108*6777b538SAndroid Build Coastguard Worker }  // namespace test
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker class CompareActiveGroupToFieldTrialMatcher;
111*6777b538SAndroid Build Coastguard Worker class FieldTrialList;
112*6777b538SAndroid Build Coastguard Worker struct LaunchOptions;
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_BLINK)
115*6777b538SAndroid Build Coastguard Worker namespace shared_memory {
116*6777b538SAndroid Build Coastguard Worker enum class SharedMemoryError;
117*6777b538SAndroid Build Coastguard Worker }  // namespace shared_memory
118*6777b538SAndroid Build Coastguard Worker #endif
119*6777b538SAndroid Build Coastguard Worker 
120*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
121*6777b538SAndroid Build Coastguard Worker  public:
122*6777b538SAndroid Build Coastguard Worker   typedef int Probability;  // Probability type for being selected in a trial.
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker   // EntropyProvider is an interface for providing entropy for one-time
125*6777b538SAndroid Build Coastguard Worker   // randomized (persistent) field trials.
126*6777b538SAndroid Build Coastguard Worker   class BASE_EXPORT EntropyProvider {
127*6777b538SAndroid Build Coastguard Worker    public:
128*6777b538SAndroid Build Coastguard Worker     virtual ~EntropyProvider();
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker     // Returns a double in the range of [0, 1) to be used for the dice roll for
131*6777b538SAndroid Build Coastguard Worker     // the specified field trial. If |randomization_seed| is not 0, it will be
132*6777b538SAndroid Build Coastguard Worker     // used in preference to |trial_name| for generating the entropy by entropy
133*6777b538SAndroid Build Coastguard Worker     // providers that support it. A given instance should always return the same
134*6777b538SAndroid Build Coastguard Worker     // value given the same input |trial_name| and |randomization_seed| values.
135*6777b538SAndroid Build Coastguard Worker     virtual double GetEntropyForTrial(std::string_view trial_name,
136*6777b538SAndroid Build Coastguard Worker                                       uint32_t randomization_seed) const = 0;
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker     // Returns a pseudorandom integer in [0, output_range).
139*6777b538SAndroid Build Coastguard Worker     // |salt| is a data parameter for the pseudorandom function.
140*6777b538SAndroid Build Coastguard Worker     uint32_t GetPseudorandomValue(uint32_t salt, uint32_t output_range) const;
141*6777b538SAndroid Build Coastguard Worker   };
142*6777b538SAndroid Build Coastguard Worker 
143*6777b538SAndroid Build Coastguard Worker   // Separate type from FieldTrial::PickleState so that it can use StringPieces.
144*6777b538SAndroid Build Coastguard Worker   struct State {
145*6777b538SAndroid Build Coastguard Worker     std::string_view trial_name;
146*6777b538SAndroid Build Coastguard Worker     std::string_view group_name;
147*6777b538SAndroid Build Coastguard Worker     bool activated = false;
148*6777b538SAndroid Build Coastguard Worker     // Whether the trial was overridden, see `FieldTrial::SetOverridden()`.
149*6777b538SAndroid Build Coastguard Worker     bool is_overridden = false;
150*6777b538SAndroid Build Coastguard Worker   };
151*6777b538SAndroid Build Coastguard Worker 
152*6777b538SAndroid Build Coastguard Worker   // Represents a Field Trial, its selected group, and override state.
153*6777b538SAndroid Build Coastguard Worker   struct ActiveGroup {
154*6777b538SAndroid Build Coastguard Worker     std::string trial_name;
155*6777b538SAndroid Build Coastguard Worker     std::string group_name;
156*6777b538SAndroid Build Coastguard Worker     // Whether the trial was overridden, see `FieldTrial::SetOverridden()`.
157*6777b538SAndroid Build Coastguard Worker     bool is_overridden = false;
158*6777b538SAndroid Build Coastguard Worker   };
159*6777b538SAndroid Build Coastguard Worker 
160*6777b538SAndroid Build Coastguard Worker   // Represents a FieldTrial, its selected group, whether it's active, and
161*6777b538SAndroid Build Coastguard Worker   // whether it's overridden. String members are pointers to the underlying
162*6777b538SAndroid Build Coastguard Worker   // strings owned by the FieldTrial object. Does not use std::string_view to
163*6777b538SAndroid Build Coastguard Worker   // avoid conversions back to std::string.
164*6777b538SAndroid Build Coastguard Worker   struct BASE_EXPORT PickleState {
165*6777b538SAndroid Build Coastguard Worker     raw_ptr<const std::string> trial_name = nullptr;
166*6777b538SAndroid Build Coastguard Worker     raw_ptr<const std::string> group_name = nullptr;
167*6777b538SAndroid Build Coastguard Worker     bool activated = false;
168*6777b538SAndroid Build Coastguard Worker     bool is_overridden = false;
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker     PickleState();
171*6777b538SAndroid Build Coastguard Worker     PickleState(const PickleState& other);
172*6777b538SAndroid Build Coastguard Worker     ~PickleState();
173*6777b538SAndroid Build Coastguard Worker   };
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   // We create one FieldTrialEntry per field trial in shared memory, via
176*6777b538SAndroid Build Coastguard Worker   // AddToAllocatorWhileLocked. The FieldTrialEntry is followed by a
177*6777b538SAndroid Build Coastguard Worker   // base::Pickle object that we unpickle and read from.
178*6777b538SAndroid Build Coastguard Worker   struct BASE_EXPORT FieldTrialEntry {
179*6777b538SAndroid Build Coastguard Worker     // SHA1(FieldTrialEntry): Increment this if structure changes!
180*6777b538SAndroid Build Coastguard Worker     static constexpr uint32_t kPersistentTypeId = 0xABA17E13 + 3;
181*6777b538SAndroid Build Coastguard Worker 
182*6777b538SAndroid Build Coastguard Worker     // Expected size for 32/64-bit check.
183*6777b538SAndroid Build Coastguard Worker     static constexpr size_t kExpectedInstanceSize = 16;
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker     // Return a pointer to the data area immediately following the entry.
GetPickledDataPtrFieldTrialEntry186*6777b538SAndroid Build Coastguard Worker     uint8_t* GetPickledDataPtr() {
187*6777b538SAndroid Build Coastguard Worker       return reinterpret_cast<uint8_t*>(this + 1);
188*6777b538SAndroid Build Coastguard Worker     }
GetPickledDataPtrFieldTrialEntry189*6777b538SAndroid Build Coastguard Worker     const uint8_t* GetPickledDataPtr() const {
190*6777b538SAndroid Build Coastguard Worker       return reinterpret_cast<const uint8_t*>(this + 1);
191*6777b538SAndroid Build Coastguard Worker     }
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker     // Whether or not this field trial is activated. This is really just a
194*6777b538SAndroid Build Coastguard Worker     // boolean but using a 32 bit value for portability reasons. It should be
195*6777b538SAndroid Build Coastguard Worker     // accessed via NoBarrier_Load()/NoBarrier_Store() to prevent the compiler
196*6777b538SAndroid Build Coastguard Worker     // from doing unexpected optimizations because it thinks that only one
197*6777b538SAndroid Build Coastguard Worker     // thread is accessing the memory location.
198*6777b538SAndroid Build Coastguard Worker     subtle::Atomic32 activated;
199*6777b538SAndroid Build Coastguard Worker 
200*6777b538SAndroid Build Coastguard Worker     // On e.g. x86, alignof(uint64_t) is 4.  Ensure consistent size and
201*6777b538SAndroid Build Coastguard Worker     // alignment of `pickle_size` across platforms. This can be considered
202*6777b538SAndroid Build Coastguard Worker     // to be padding for the final 32 bit value (activated). If this struct
203*6777b538SAndroid Build Coastguard Worker     // gains or loses fields, consider if this padding is still needed.
204*6777b538SAndroid Build Coastguard Worker     uint32_t padding;
205*6777b538SAndroid Build Coastguard Worker 
206*6777b538SAndroid Build Coastguard Worker     // Size of the pickled structure, NOT the total size of this entry.
207*6777b538SAndroid Build Coastguard Worker     uint64_t pickle_size;
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker     // Calling this is only valid when the entry is initialized. That is, it
210*6777b538SAndroid Build Coastguard Worker     // resides in shared memory and has a pickle containing the trial name,
211*6777b538SAndroid Build Coastguard Worker     // group name, and is_overridden.
212*6777b538SAndroid Build Coastguard Worker     bool GetState(std::string_view& trial_name,
213*6777b538SAndroid Build Coastguard Worker                   std::string_view& group_name,
214*6777b538SAndroid Build Coastguard Worker                   bool& is_overridden) const;
215*6777b538SAndroid Build Coastguard Worker 
216*6777b538SAndroid Build Coastguard Worker     // Calling this is only valid when the entry is initialized as well. Reads
217*6777b538SAndroid Build Coastguard Worker     // the parameters following the trial and group name and stores them as
218*6777b538SAndroid Build Coastguard Worker     // key-value mappings in |params|.
219*6777b538SAndroid Build Coastguard Worker     bool GetParams(std::map<std::string, std::string>* params) const;
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker    private:
222*6777b538SAndroid Build Coastguard Worker     // Returns an iterator over the data containing names and params.
223*6777b538SAndroid Build Coastguard Worker     PickleIterator GetPickleIterator() const;
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker     // Takes the iterator and writes out the first two items into |trial_name|
226*6777b538SAndroid Build Coastguard Worker     // and |group_name|.
227*6777b538SAndroid Build Coastguard Worker     bool ReadStringPair(PickleIterator* iter,
228*6777b538SAndroid Build Coastguard Worker                         std::string_view* trial_name,
229*6777b538SAndroid Build Coastguard Worker                         std::string_view* group_name) const;
230*6777b538SAndroid Build Coastguard Worker 
231*6777b538SAndroid Build Coastguard Worker     // Reads the field trial header, which includes the name of the trial and
232*6777b538SAndroid Build Coastguard Worker     // group, and the is_overridden bool.
233*6777b538SAndroid Build Coastguard Worker     bool ReadHeader(PickleIterator& iter,
234*6777b538SAndroid Build Coastguard Worker                     std::string_view& trial_name,
235*6777b538SAndroid Build Coastguard Worker                     std::string_view& group_name,
236*6777b538SAndroid Build Coastguard Worker                     bool& is_overridden) const;
237*6777b538SAndroid Build Coastguard Worker   };
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker   typedef std::vector<ActiveGroup> ActiveGroups;
240*6777b538SAndroid Build Coastguard Worker 
241*6777b538SAndroid Build Coastguard Worker   // A return value to indicate that a given instance has not yet had a group
242*6777b538SAndroid Build Coastguard Worker   // assignment (and hence is not yet participating in the trial).
243*6777b538SAndroid Build Coastguard Worker   static const int kNotFinalized;
244*6777b538SAndroid Build Coastguard Worker 
245*6777b538SAndroid Build Coastguard Worker   FieldTrial(const FieldTrial&) = delete;
246*6777b538SAndroid Build Coastguard Worker   FieldTrial& operator=(const FieldTrial&) = delete;
247*6777b538SAndroid Build Coastguard Worker 
248*6777b538SAndroid Build Coastguard Worker   // Establishes the name and probability of the next group in this trial.
249*6777b538SAndroid Build Coastguard Worker   // Sometimes, based on construction randomization, this call may cause the
250*6777b538SAndroid Build Coastguard Worker   // provided group to be *THE* group selected for use in this instance.
251*6777b538SAndroid Build Coastguard Worker   // AppendGroup can be called after calls to group() but it should be avoided
252*6777b538SAndroid Build Coastguard Worker   // if possible. Doing so may be confusing since it won't change the group
253*6777b538SAndroid Build Coastguard Worker   // selection.
254*6777b538SAndroid Build Coastguard Worker   void AppendGroup(const std::string& name, Probability group_probability);
255*6777b538SAndroid Build Coastguard Worker 
256*6777b538SAndroid Build Coastguard Worker   // Return the name of the FieldTrial (excluding the group name).
trial_name()257*6777b538SAndroid Build Coastguard Worker   const std::string& trial_name() const { return trial_name_; }
258*6777b538SAndroid Build Coastguard Worker 
259*6777b538SAndroid Build Coastguard Worker   // Finalizes the group assignment and notifies any/all observers. This is a
260*6777b538SAndroid Build Coastguard Worker   // no-op if the trial is already active. Note this will force an instance to
261*6777b538SAndroid Build Coastguard Worker   // participate, and make it illegal to attempt to probabilistically add any
262*6777b538SAndroid Build Coastguard Worker   // other groups to the trial.
263*6777b538SAndroid Build Coastguard Worker   void Activate();
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker   // If the group's name is empty, a string version containing the group number
266*6777b538SAndroid Build Coastguard Worker   // is used as the group name. This causes a winner to be chosen if none was.
267*6777b538SAndroid Build Coastguard Worker   const std::string& group_name();
268*6777b538SAndroid Build Coastguard Worker 
269*6777b538SAndroid Build Coastguard Worker   // Finalizes the group choice and returns the chosen group, but does not mark
270*6777b538SAndroid Build Coastguard Worker   // the trial as active - so its state will not be reported until group_name()
271*6777b538SAndroid Build Coastguard Worker   // or similar is called.
272*6777b538SAndroid Build Coastguard Worker   const std::string& GetGroupNameWithoutActivation();
273*6777b538SAndroid Build Coastguard Worker 
274*6777b538SAndroid Build Coastguard Worker   // Set the field trial as forced, meaning that it was setup earlier than
275*6777b538SAndroid Build Coastguard Worker   // the hard coded registration of the field trial to override it.
276*6777b538SAndroid Build Coastguard Worker   // This allows the code that was hard coded to register the field trial to
277*6777b538SAndroid Build Coastguard Worker   // still succeed even though the field trial has already been registered.
278*6777b538SAndroid Build Coastguard Worker   // This must be called after appending all the groups, since we will make
279*6777b538SAndroid Build Coastguard Worker   // the group choice here. Note that this is a NOOP for already forced trials.
280*6777b538SAndroid Build Coastguard Worker   // And, as the rest of the FieldTrial code, this is not thread safe and must
281*6777b538SAndroid Build Coastguard Worker   // be done from the UI thread.
282*6777b538SAndroid Build Coastguard Worker   void SetForced();
283*6777b538SAndroid Build Coastguard Worker 
284*6777b538SAndroid Build Coastguard Worker   // Returns whether the trial was overridden.
285*6777b538SAndroid Build Coastguard Worker   bool IsOverridden() const;
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   // Supports benchmarking by causing field trials' default groups to be chosen.
288*6777b538SAndroid Build Coastguard Worker   static void EnableBenchmarking();
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker   // Creates a FieldTrial object with the specified parameters, to be used for
291*6777b538SAndroid Build Coastguard Worker   // simulation of group assignment without actually affecting global field
292*6777b538SAndroid Build Coastguard Worker   // trial state in the running process. Group assignment will be done based on
293*6777b538SAndroid Build Coastguard Worker   // |entropy_value|, which must have a range of [0, 1).
294*6777b538SAndroid Build Coastguard Worker   //
295*6777b538SAndroid Build Coastguard Worker   // Note: Using this function will not register the field trial globally in the
296*6777b538SAndroid Build Coastguard Worker   // running process - for that, use FieldTrialList::FactoryGetFieldTrial().
297*6777b538SAndroid Build Coastguard Worker   //
298*6777b538SAndroid Build Coastguard Worker   // The ownership of the returned FieldTrial is transfered to the caller which
299*6777b538SAndroid Build Coastguard Worker   // is responsible for deref'ing it (e.g. by using scoped_refptr<FieldTrial>).
300*6777b538SAndroid Build Coastguard Worker   static FieldTrial* CreateSimulatedFieldTrial(
301*6777b538SAndroid Build Coastguard Worker       std::string_view trial_name,
302*6777b538SAndroid Build Coastguard Worker       Probability total_probability,
303*6777b538SAndroid Build Coastguard Worker       std::string_view default_group_name,
304*6777b538SAndroid Build Coastguard Worker       double entropy_value);
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   // Parses a '--force-fieldtrials' formatted string into entries.
307*6777b538SAndroid Build Coastguard Worker   // Returns true if the string was parsed correctly. On failure, the |entries|
308*6777b538SAndroid Build Coastguard Worker   // array may end up being partially filled.
309*6777b538SAndroid Build Coastguard Worker   //
310*6777b538SAndroid Build Coastguard Worker   // Note that currently, States returned here have is_overridden=false, but we
311*6777b538SAndroid Build Coastguard Worker   // are in the process of migrating to marking field trials set manually by
312*6777b538SAndroid Build Coastguard Worker   // command line as overridden. See b/284986126.
313*6777b538SAndroid Build Coastguard Worker   static bool ParseFieldTrialsString(std::string_view field_trials_string,
314*6777b538SAndroid Build Coastguard Worker                                      bool override_trials,
315*6777b538SAndroid Build Coastguard Worker                                      std::vector<State>& entries);
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker   // Returns a '--force-fieldtrials' formatted string representing the list of
318*6777b538SAndroid Build Coastguard Worker   // provided trial states.
319*6777b538SAndroid Build Coastguard Worker   static std::string BuildFieldTrialStateString(
320*6777b538SAndroid Build Coastguard Worker       const std::vector<State>& states);
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker   // Whether this field trial is low anonymity or not (see
323*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity|).
324*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/1431156): remove this once all call sites have been properly
325*6777b538SAndroid Build Coastguard Worker   // migrated to use an appropriate observer.
is_low_anonymity()326*6777b538SAndroid Build Coastguard Worker   bool is_low_anonymity() const { return is_low_anonymity_; }
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker  private:
329*6777b538SAndroid Build Coastguard Worker   // Allow tests to access our innards for testing purposes.
330*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, Registration);
331*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, AbsoluteProbabilities);
332*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, RemainingProbability);
333*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, FiftyFiftyProbability);
334*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, MiddleProbabilities);
335*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, OneWinner);
336*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, DisableProbability);
337*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, ActiveGroups);
338*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, AllGroups);
339*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, ActiveGroupsNotFinalized);
340*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, Save);
341*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, SaveAll);
342*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, DuplicateRestore);
343*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, SetForcedTurnFeatureOff);
344*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, SetForcedTurnFeatureOn);
345*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, SetForcedChangeDefault_Default);
346*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, SetForcedChangeDefault_NonDefault);
347*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, ObserveReentrancy);
348*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, FloatBoundariesGiveEqualGroupSizes);
349*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, DoesNotSurpassTotalProbability);
350*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest,
351*6777b538SAndroid Build Coastguard Worker                            DoNotAddSimulatedFieldTrialsToAllocator);
352*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, ClearParamsFromSharedMemory);
353*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest,
354*6777b538SAndroid Build Coastguard Worker                            TestGetRandomizedFieldTrialCount);
355*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialTest, SetLowAnonymity);
356*6777b538SAndroid Build Coastguard Worker 
357*6777b538SAndroid Build Coastguard Worker   // MATCHER(CompareActiveGroupToFieldTrialMatcher, "")
358*6777b538SAndroid Build Coastguard Worker   friend class base::CompareActiveGroupToFieldTrialMatcher;
359*6777b538SAndroid Build Coastguard Worker 
360*6777b538SAndroid Build Coastguard Worker   friend class base::FieldTrialList;
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker   friend class RefCounted<FieldTrial>;
363*6777b538SAndroid Build Coastguard Worker 
364*6777b538SAndroid Build Coastguard Worker   using FieldTrialRef = PersistentMemoryAllocator::Reference;
365*6777b538SAndroid Build Coastguard Worker 
366*6777b538SAndroid Build Coastguard Worker   // This is the group number of the 'default' group when a choice wasn't forced
367*6777b538SAndroid Build Coastguard Worker   // by a call to FieldTrialList::CreateFieldTrial. It is kept private so that
368*6777b538SAndroid Build Coastguard Worker   // consumers don't use it by mistake in cases where the group was forced.
369*6777b538SAndroid Build Coastguard Worker   static const int kDefaultGroupNumber;
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker   // Creates a field trial with the specified parameters. Group assignment will
372*6777b538SAndroid Build Coastguard Worker   // be done based on |entropy_value|, which must have a range of [0, 1).
373*6777b538SAndroid Build Coastguard Worker   FieldTrial(std::string_view trial_name,
374*6777b538SAndroid Build Coastguard Worker              Probability total_probability,
375*6777b538SAndroid Build Coastguard Worker              std::string_view default_group_name,
376*6777b538SAndroid Build Coastguard Worker              double entropy_value,
377*6777b538SAndroid Build Coastguard Worker              bool is_low_anonymity,
378*6777b538SAndroid Build Coastguard Worker              bool is_overridden);
379*6777b538SAndroid Build Coastguard Worker 
380*6777b538SAndroid Build Coastguard Worker   virtual ~FieldTrial();
381*6777b538SAndroid Build Coastguard Worker 
382*6777b538SAndroid Build Coastguard Worker   // Marks this trial as having been registered with the FieldTrialList. Must be
383*6777b538SAndroid Build Coastguard Worker   // called no more than once and before any |group()| calls have occurred.
384*6777b538SAndroid Build Coastguard Worker   void SetTrialRegistered();
385*6777b538SAndroid Build Coastguard Worker 
386*6777b538SAndroid Build Coastguard Worker   // Sets the chosen group name and number.
387*6777b538SAndroid Build Coastguard Worker   void SetGroupChoice(const std::string& group_name, int number);
388*6777b538SAndroid Build Coastguard Worker 
389*6777b538SAndroid Build Coastguard Worker   // Ensures that a group is chosen, if it hasn't yet been. The field trial
390*6777b538SAndroid Build Coastguard Worker   // might yet be disabled, so this call will *not* notify observers of the
391*6777b538SAndroid Build Coastguard Worker   // status.
392*6777b538SAndroid Build Coastguard Worker   void FinalizeGroupChoice();
393*6777b538SAndroid Build Coastguard Worker 
394*6777b538SAndroid Build Coastguard Worker   // Returns the trial name and selected group name for this field trial via
395*6777b538SAndroid Build Coastguard Worker   // the output parameter |active_group|, but only if the group has already
396*6777b538SAndroid Build Coastguard Worker   // been chosen and has been externally observed via |group()| and the trial
397*6777b538SAndroid Build Coastguard Worker   // has not been disabled. In that case, true is returned and |active_group|
398*6777b538SAndroid Build Coastguard Worker   // is filled in; otherwise, the result is false and |active_group| is left
399*6777b538SAndroid Build Coastguard Worker   // untouched.
400*6777b538SAndroid Build Coastguard Worker   bool GetActiveGroup(ActiveGroup* active_group) const;
401*6777b538SAndroid Build Coastguard Worker 
402*6777b538SAndroid Build Coastguard Worker   // Returns the trial name and selected group name for this field trial via
403*6777b538SAndroid Build Coastguard Worker   // the output parameter |field_trial_state| for all the studies.
404*6777b538SAndroid Build Coastguard Worker   void GetStateWhileLocked(PickleState* field_trial_state);
405*6777b538SAndroid Build Coastguard Worker 
406*6777b538SAndroid Build Coastguard Worker   // Returns the group_name. A winner need not have been chosen.
group_name_internal()407*6777b538SAndroid Build Coastguard Worker   const std::string& group_name_internal() const { return group_name_; }
408*6777b538SAndroid Build Coastguard Worker 
409*6777b538SAndroid Build Coastguard Worker   // The name of the field trial, as can be found via the FieldTrialList.
410*6777b538SAndroid Build Coastguard Worker   const std::string trial_name_;
411*6777b538SAndroid Build Coastguard Worker 
412*6777b538SAndroid Build Coastguard Worker   // The maximum sum of all probabilities supplied, which corresponds to 100%.
413*6777b538SAndroid Build Coastguard Worker   // This is the scaling factor used to adjust supplied probabilities.
414*6777b538SAndroid Build Coastguard Worker   const Probability divisor_;
415*6777b538SAndroid Build Coastguard Worker 
416*6777b538SAndroid Build Coastguard Worker   // The name of the default group.
417*6777b538SAndroid Build Coastguard Worker   const std::string default_group_name_;
418*6777b538SAndroid Build Coastguard Worker 
419*6777b538SAndroid Build Coastguard Worker   // The randomly selected probability that is used to select a group (or have
420*6777b538SAndroid Build Coastguard Worker   // the instance not participate).  It is the product of divisor_ and a random
421*6777b538SAndroid Build Coastguard Worker   // number between [0, 1).
422*6777b538SAndroid Build Coastguard Worker   Probability random_;
423*6777b538SAndroid Build Coastguard Worker 
424*6777b538SAndroid Build Coastguard Worker   // Sum of the probabilities of all appended groups.
425*6777b538SAndroid Build Coastguard Worker   Probability accumulated_group_probability_;
426*6777b538SAndroid Build Coastguard Worker 
427*6777b538SAndroid Build Coastguard Worker   // The number that will be returned by the next AppendGroup() call.
428*6777b538SAndroid Build Coastguard Worker   int next_group_number_;
429*6777b538SAndroid Build Coastguard Worker 
430*6777b538SAndroid Build Coastguard Worker   // The pseudo-randomly assigned group number.
431*6777b538SAndroid Build Coastguard Worker   // This is kNotFinalized if no group has been assigned.
432*6777b538SAndroid Build Coastguard Worker   int group_;
433*6777b538SAndroid Build Coastguard Worker 
434*6777b538SAndroid Build Coastguard Worker   // A textual name for the randomly selected group. Valid after |group()|
435*6777b538SAndroid Build Coastguard Worker   // has been called.
436*6777b538SAndroid Build Coastguard Worker   std::string group_name_;
437*6777b538SAndroid Build Coastguard Worker 
438*6777b538SAndroid Build Coastguard Worker   // When forced_ is true, we return the chosen group from AppendGroup when
439*6777b538SAndroid Build Coastguard Worker   // appropriate.
440*6777b538SAndroid Build Coastguard Worker   bool forced_;
441*6777b538SAndroid Build Coastguard Worker 
442*6777b538SAndroid Build Coastguard Worker   // Whether the field trial was manually overridden using a command-line flag
443*6777b538SAndroid Build Coastguard Worker   // or internals page.
444*6777b538SAndroid Build Coastguard Worker   const bool is_overridden_;
445*6777b538SAndroid Build Coastguard Worker 
446*6777b538SAndroid Build Coastguard Worker   // Specifies whether the group choice has been reported to observers.
447*6777b538SAndroid Build Coastguard Worker   bool group_reported_;
448*6777b538SAndroid Build Coastguard Worker 
449*6777b538SAndroid Build Coastguard Worker   // Whether this trial is registered with the global FieldTrialList and thus
450*6777b538SAndroid Build Coastguard Worker   // should notify it when its group is queried.
451*6777b538SAndroid Build Coastguard Worker   bool trial_registered_;
452*6777b538SAndroid Build Coastguard Worker 
453*6777b538SAndroid Build Coastguard Worker   // Reference to related field trial struct and data in shared memory.
454*6777b538SAndroid Build Coastguard Worker   FieldTrialRef ref_;
455*6777b538SAndroid Build Coastguard Worker 
456*6777b538SAndroid Build Coastguard Worker   // Denotes whether benchmarking is enabled. In this case, field trials all
457*6777b538SAndroid Build Coastguard Worker   // revert to the default group.
458*6777b538SAndroid Build Coastguard Worker   static bool enable_benchmarking_;
459*6777b538SAndroid Build Coastguard Worker 
460*6777b538SAndroid Build Coastguard Worker   // Whether this field trial is potentially low anonymity (eg. only a small
461*6777b538SAndroid Build Coastguard Worker   // set of users are included).
462*6777b538SAndroid Build Coastguard Worker   const bool is_low_anonymity_ = false;
463*6777b538SAndroid Build Coastguard Worker };
464*6777b538SAndroid Build Coastguard Worker 
465*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
466*6777b538SAndroid Build Coastguard Worker // Class with a list of all active field trials.  A trial is active if it has
467*6777b538SAndroid Build Coastguard Worker // been registered, which includes evaluating its state based on its
468*6777b538SAndroid Build Coastguard Worker // probability. Only one instance of this class exists and outside of testing,
469*6777b538SAndroid Build Coastguard Worker // will live for the entire life time of the process.
470*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT FieldTrialList {
471*6777b538SAndroid Build Coastguard Worker  public:
472*6777b538SAndroid Build Coastguard Worker   using FieldTrialAllocator = PersistentMemoryAllocator;
473*6777b538SAndroid Build Coastguard Worker 
474*6777b538SAndroid Build Coastguard Worker   // Type for function pointer passed to |AllParamsToString| used to escape
475*6777b538SAndroid Build Coastguard Worker   // special characters from |input|.
476*6777b538SAndroid Build Coastguard Worker   typedef std::string (*EscapeDataFunc)(const std::string& input);
477*6777b538SAndroid Build Coastguard Worker 
478*6777b538SAndroid Build Coastguard Worker   // Observer is notified when a FieldTrial's group is selected.
479*6777b538SAndroid Build Coastguard Worker   class BASE_EXPORT Observer {
480*6777b538SAndroid Build Coastguard Worker    public:
481*6777b538SAndroid Build Coastguard Worker     // Notify observers when FieldTrials's group is selected.
482*6777b538SAndroid Build Coastguard Worker     // Note that it should be safe to eliminate the `group_name` parameter, in
483*6777b538SAndroid Build Coastguard Worker     // favor of callers using `trial.group_name()`. This wasn't done yet because
484*6777b538SAndroid Build Coastguard Worker     // `FieldTrial::group_name()` has a non-trivial implementation.
485*6777b538SAndroid Build Coastguard Worker     virtual void OnFieldTrialGroupFinalized(const FieldTrial& trial,
486*6777b538SAndroid Build Coastguard Worker                                             const std::string& group_name) = 0;
487*6777b538SAndroid Build Coastguard Worker 
488*6777b538SAndroid Build Coastguard Worker    protected:
489*6777b538SAndroid Build Coastguard Worker     virtual ~Observer();
490*6777b538SAndroid Build Coastguard Worker   };
491*6777b538SAndroid Build Coastguard Worker 
492*6777b538SAndroid Build Coastguard Worker   // This singleton holds the global list of registered FieldTrials.
493*6777b538SAndroid Build Coastguard Worker   FieldTrialList();
494*6777b538SAndroid Build Coastguard Worker   FieldTrialList(const FieldTrialList&) = delete;
495*6777b538SAndroid Build Coastguard Worker   FieldTrialList& operator=(const FieldTrialList&) = delete;
496*6777b538SAndroid Build Coastguard Worker 
497*6777b538SAndroid Build Coastguard Worker   // Destructor Release()'s references to all registered FieldTrial instances.
498*6777b538SAndroid Build Coastguard Worker   ~FieldTrialList();
499*6777b538SAndroid Build Coastguard Worker 
500*6777b538SAndroid Build Coastguard Worker   // Gets a FieldTrial instance from the factory.
501*6777b538SAndroid Build Coastguard Worker   //
502*6777b538SAndroid Build Coastguard Worker   // |trial_name| (a) is used to register the instance with the FieldTrialList
503*6777b538SAndroid Build Coastguard Worker   // class and (b) can be used to find the trial (only one trial can be present
504*6777b538SAndroid Build Coastguard Worker   // for each name). |default_group_name| is the name of the group that is
505*6777b538SAndroid Build Coastguard Worker   // chosen if none of the subsequent appended groups are chosen. Note that the
506*6777b538SAndroid Build Coastguard Worker   // default group is also chosen whenever |enable_benchmarking_| is true.
507*6777b538SAndroid Build Coastguard Worker   //
508*6777b538SAndroid Build Coastguard Worker   // Group probabilities that are later supplied must sum to less than or equal
509*6777b538SAndroid Build Coastguard Worker   // to the |total_probability|.
510*6777b538SAndroid Build Coastguard Worker   //
511*6777b538SAndroid Build Coastguard Worker   // The |entropy_provider| is used for randomizing group selection. The
512*6777b538SAndroid Build Coastguard Worker   // |randomization_seed| will be passed to the EntropyProvider in addition
513*6777b538SAndroid Build Coastguard Worker   // to the trial name, and it's handling is defined by the EntropyProvider.
514*6777b538SAndroid Build Coastguard Worker   // * SessionEntropyProvider requires it to be 0 by DCHECK.
515*6777b538SAndroid Build Coastguard Worker   // * SHA1 and NormalizedMurmurHash providers will use a non-zero value as a
516*6777b538SAndroid Build Coastguard Worker   //   salt _instead_ of using the trial name.
517*6777b538SAndroid Build Coastguard Worker   //
518*6777b538SAndroid Build Coastguard Worker   // Some field trials may be targeted in such way that a relatively small
519*6777b538SAndroid Build Coastguard Worker   // number of users are in a particular experiment group. Such trials should
520*6777b538SAndroid Build Coastguard Worker   // have |is_low_anonymity| set to true, and their visitbility is restricted
521*6777b538SAndroid Build Coastguard Worker   // to specific callers only, via |FieldTrialListIncludingLowAnonymity|.
522*6777b538SAndroid Build Coastguard Worker   //
523*6777b538SAndroid Build Coastguard Worker   // This static method can be used to get a startup-randomized FieldTrial or a
524*6777b538SAndroid Build Coastguard Worker   // previously created forced FieldTrial.
525*6777b538SAndroid Build Coastguard Worker   static FieldTrial* FactoryGetFieldTrial(
526*6777b538SAndroid Build Coastguard Worker       std::string_view trial_name,
527*6777b538SAndroid Build Coastguard Worker       FieldTrial::Probability total_probability,
528*6777b538SAndroid Build Coastguard Worker       std::string_view default_group_name,
529*6777b538SAndroid Build Coastguard Worker       const FieldTrial::EntropyProvider& entropy_provider,
530*6777b538SAndroid Build Coastguard Worker       uint32_t randomization_seed = 0,
531*6777b538SAndroid Build Coastguard Worker       bool is_low_anonymity = false,
532*6777b538SAndroid Build Coastguard Worker       bool is_overridden = false);
533*6777b538SAndroid Build Coastguard Worker 
534*6777b538SAndroid Build Coastguard Worker   // The Find() method can be used to test to see if a named trial was already
535*6777b538SAndroid Build Coastguard Worker   // registered, or to retrieve a pointer to it from the global map.
536*6777b538SAndroid Build Coastguard Worker   static FieldTrial* Find(std::string_view trial_name);
537*6777b538SAndroid Build Coastguard Worker 
538*6777b538SAndroid Build Coastguard Worker   // Returns the group name chosen for the named trial, or the empty string if
539*6777b538SAndroid Build Coastguard Worker   // the trial does not exist. The first call of this function on a given field
540*6777b538SAndroid Build Coastguard Worker   // trial will mark it as active, so that its state will be reported with usage
541*6777b538SAndroid Build Coastguard Worker   // metrics, crashes, etc.
542*6777b538SAndroid Build Coastguard Worker   // Note: Direct use of this function and related FieldTrial functions is
543*6777b538SAndroid Build Coastguard Worker   // generally discouraged - instead please use base::Feature when possible.
544*6777b538SAndroid Build Coastguard Worker   static std::string FindFullName(std::string_view trial_name);
545*6777b538SAndroid Build Coastguard Worker 
546*6777b538SAndroid Build Coastguard Worker   // Returns true if the named trial has been registered.
547*6777b538SAndroid Build Coastguard Worker   static bool TrialExists(std::string_view trial_name);
548*6777b538SAndroid Build Coastguard Worker 
549*6777b538SAndroid Build Coastguard Worker   // Returns true if the named trial exists and has been activated.
550*6777b538SAndroid Build Coastguard Worker   static bool IsTrialActive(std::string_view trial_name);
551*6777b538SAndroid Build Coastguard Worker 
552*6777b538SAndroid Build Coastguard Worker   // Creates a persistent representation of all FieldTrial instances for
553*6777b538SAndroid Build Coastguard Worker   // resurrection in another process. This allows randomization to be done in
554*6777b538SAndroid Build Coastguard Worker   // one process, and secondary processes can be synchronized on the result.
555*6777b538SAndroid Build Coastguard Worker   // The resulting string contains the name and group name pairs of all
556*6777b538SAndroid Build Coastguard Worker   // registered FieldTrials,
557*6777b538SAndroid Build Coastguard Worker   // with "/" used to separate all names and to terminate the string. All
558*6777b538SAndroid Build Coastguard Worker   // activated trials have their name prefixed with "*". This string is parsed
559*6777b538SAndroid Build Coastguard Worker   // by |CreateTrialsFromString()|.
560*6777b538SAndroid Build Coastguard Worker   static void AllStatesToString(std::string* output);
561*6777b538SAndroid Build Coastguard Worker 
562*6777b538SAndroid Build Coastguard Worker   // Creates a persistent representation of all FieldTrial params for
563*6777b538SAndroid Build Coastguard Worker   // resurrection in another process. The returned string contains the trial
564*6777b538SAndroid Build Coastguard Worker   // name and group name pairs of all registered FieldTrials. The pair is
565*6777b538SAndroid Build Coastguard Worker   // followed by ':' separator and list of param name and values separated by
566*6777b538SAndroid Build Coastguard Worker   // '/'. It also takes |encode_data_func| function pointer for encodeing
567*6777b538SAndroid Build Coastguard Worker   // special characters. This string is parsed by
568*6777b538SAndroid Build Coastguard Worker   // |AssociateParamsFromString()|.
569*6777b538SAndroid Build Coastguard Worker   static std::string AllParamsToString(EscapeDataFunc encode_data_func);
570*6777b538SAndroid Build Coastguard Worker 
571*6777b538SAndroid Build Coastguard Worker   // Fills in the supplied vector |active_groups| (which must be empty when
572*6777b538SAndroid Build Coastguard Worker   // called) with a snapshot of all registered FieldTrials for which the group
573*6777b538SAndroid Build Coastguard Worker   // has been chosen and externally observed (via |group()|) and which have
574*6777b538SAndroid Build Coastguard Worker   // not been disabled.
575*6777b538SAndroid Build Coastguard Worker   //
576*6777b538SAndroid Build Coastguard Worker   // This does not return low anonymity field trials. Callers who need access to
577*6777b538SAndroid Build Coastguard Worker   // low anonymity field trials should use
578*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity.GetActiveFieldTrialGroups()|.
579*6777b538SAndroid Build Coastguard Worker   static void GetActiveFieldTrialGroups(
580*6777b538SAndroid Build Coastguard Worker       FieldTrial::ActiveGroups* active_groups);
581*6777b538SAndroid Build Coastguard Worker 
582*6777b538SAndroid Build Coastguard Worker   // Returns the names of field trials that are active in the parent process.
583*6777b538SAndroid Build Coastguard Worker   // If this process is not a child process with inherited field trials passed
584*6777b538SAndroid Build Coastguard Worker   // to it through PopulateLaunchOptionsWithFieldTrialState(), an empty set will
585*6777b538SAndroid Build Coastguard Worker   // be returned.
586*6777b538SAndroid Build Coastguard Worker   // Must be called only after a call to CreateTrialsInChildProcess().
587*6777b538SAndroid Build Coastguard Worker   static std::set<std::string> GetActiveTrialsOfParentProcess();
588*6777b538SAndroid Build Coastguard Worker 
589*6777b538SAndroid Build Coastguard Worker   // Use a state string (re: AllStatesToString()) to augment the current list of
590*6777b538SAndroid Build Coastguard Worker   // field trials to include the supplied trials, and using a 100% probability
591*6777b538SAndroid Build Coastguard Worker   // for each trial, force them to have the same group string. This is commonly
592*6777b538SAndroid Build Coastguard Worker   // used in a non-browser process, to carry randomly selected state in a
593*6777b538SAndroid Build Coastguard Worker   // browser process into this non-browser process, but could also be invoked
594*6777b538SAndroid Build Coastguard Worker   // through a command line argument to the browser process. Created field
595*6777b538SAndroid Build Coastguard Worker   // trials will be marked "used" for the purposes of active trial reporting
596*6777b538SAndroid Build Coastguard Worker   // if they are prefixed with |kActivationMarker|.
597*6777b538SAndroid Build Coastguard Worker   // If `override_trials` is true, `FieldTrial::SetOverridden()` is called for
598*6777b538SAndroid Build Coastguard Worker   // created trials.
599*6777b538SAndroid Build Coastguard Worker   static bool CreateTrialsFromString(const std::string& trials_string,
600*6777b538SAndroid Build Coastguard Worker                                      bool override_trials = false);
601*6777b538SAndroid Build Coastguard Worker 
602*6777b538SAndroid Build Coastguard Worker   // Creates trials in a child process from a command line that was produced
603*6777b538SAndroid Build Coastguard Worker   // via PopulateLaunchOptionsWithFieldTrialState() in the parent process.
604*6777b538SAndroid Build Coastguard Worker   // Trials are retrieved from a shared memory segment that has been shared with
605*6777b538SAndroid Build Coastguard Worker   // the child process.
606*6777b538SAndroid Build Coastguard Worker   static void CreateTrialsInChildProcess(const CommandLine& cmd_line);
607*6777b538SAndroid Build Coastguard Worker 
608*6777b538SAndroid Build Coastguard Worker   // Creates base::Feature overrides in a child process using shared memory.
609*6777b538SAndroid Build Coastguard Worker   // Requires CreateTrialsInChildProcess() to have been called first which
610*6777b538SAndroid Build Coastguard Worker   // initializes access to the shared memory segment.
611*6777b538SAndroid Build Coastguard Worker   static void ApplyFeatureOverridesInChildProcess(FeatureList* feature_list);
612*6777b538SAndroid Build Coastguard Worker 
613*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_BLINK)
614*6777b538SAndroid Build Coastguard Worker   // Populates |command_line| and |launch_options| with the handles and command
615*6777b538SAndroid Build Coastguard Worker   // line arguments necessary for a child process to inherit the shared-memory
616*6777b538SAndroid Build Coastguard Worker   // object containing the FieldTrial configuration.
617*6777b538SAndroid Build Coastguard Worker   static void PopulateLaunchOptionsWithFieldTrialState(
618*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
619*6777b538SAndroid Build Coastguard Worker       GlobalDescriptors::Key descriptor_key,
620*6777b538SAndroid Build Coastguard Worker       ScopedFD& descriptor_to_share,
621*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
622*6777b538SAndroid Build Coastguard Worker       CommandLine* command_line,
623*6777b538SAndroid Build Coastguard Worker       LaunchOptions* launch_options);
624*6777b538SAndroid Build Coastguard Worker #endif  // !BUILDFLAG(USE_BLINK)
625*6777b538SAndroid Build Coastguard Worker 
626*6777b538SAndroid Build Coastguard Worker   static ReadOnlySharedMemoryRegion DuplicateFieldTrialSharedMemoryForTesting();
627*6777b538SAndroid Build Coastguard Worker 
628*6777b538SAndroid Build Coastguard Worker   // Create a FieldTrial with the given |name| and using 100% probability for
629*6777b538SAndroid Build Coastguard Worker   // the FieldTrial, force FieldTrial to have the same group string as
630*6777b538SAndroid Build Coastguard Worker   // |group_name|. This is commonly used in a non-browser process, to carry
631*6777b538SAndroid Build Coastguard Worker   // randomly selected state in a browser process into this non-browser process.
632*6777b538SAndroid Build Coastguard Worker   // It returns NULL if there is a FieldTrial that is already registered with
633*6777b538SAndroid Build Coastguard Worker   // the same |name| but has different finalized group string (|group_name|).
634*6777b538SAndroid Build Coastguard Worker   //
635*6777b538SAndroid Build Coastguard Worker   // Visibility of field trials with |is_low_anonymity| set to true is
636*6777b538SAndroid Build Coastguard Worker   // restricted to specific callers only, see
637*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity|.
638*6777b538SAndroid Build Coastguard Worker   static FieldTrial* CreateFieldTrial(std::string_view name,
639*6777b538SAndroid Build Coastguard Worker                                       std::string_view group_name,
640*6777b538SAndroid Build Coastguard Worker                                       bool is_low_anonymity = false,
641*6777b538SAndroid Build Coastguard Worker                                       bool is_overridden = false);
642*6777b538SAndroid Build Coastguard Worker 
643*6777b538SAndroid Build Coastguard Worker   // Add an observer to be notified when a field trial is irrevocably committed
644*6777b538SAndroid Build Coastguard Worker   // to being part of some specific field_group (and hence the group_name is
645*6777b538SAndroid Build Coastguard Worker   // also finalized for that field_trial). Returns false and does nothing if
646*6777b538SAndroid Build Coastguard Worker   // there is no FieldTrialList singleton. The observer can be notified on any
647*6777b538SAndroid Build Coastguard Worker   // sequence; it must be thread-safe.
648*6777b538SAndroid Build Coastguard Worker   //
649*6777b538SAndroid Build Coastguard Worker   // Low anonymity field trials are not notified to this observer. Callers
650*6777b538SAndroid Build Coastguard Worker   // who need to be notified of low anonymity field trials should use
651*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity.AddObserver()|.
652*6777b538SAndroid Build Coastguard Worker   static bool AddObserver(Observer* observer);
653*6777b538SAndroid Build Coastguard Worker 
654*6777b538SAndroid Build Coastguard Worker   // Remove an observer. This cannot be invoked concurrently with
655*6777b538SAndroid Build Coastguard Worker   // FieldTrial::group() (typically, this means that no other thread should be
656*6777b538SAndroid Build Coastguard Worker   // running when this is invoked).
657*6777b538SAndroid Build Coastguard Worker   //
658*6777b538SAndroid Build Coastguard Worker   // Removes observers added via the |AddObserver()| method of this class.
659*6777b538SAndroid Build Coastguard Worker   static void RemoveObserver(Observer* observer);
660*6777b538SAndroid Build Coastguard Worker 
661*6777b538SAndroid Build Coastguard Worker   // Notify all observers that a group has been finalized for |field_trial|.
662*6777b538SAndroid Build Coastguard Worker   static void NotifyFieldTrialGroupSelection(FieldTrial* field_trial);
663*6777b538SAndroid Build Coastguard Worker 
664*6777b538SAndroid Build Coastguard Worker   // Return the number of active field trials.
665*6777b538SAndroid Build Coastguard Worker   static size_t GetFieldTrialCount();
666*6777b538SAndroid Build Coastguard Worker 
667*6777b538SAndroid Build Coastguard Worker   // Return the number of active field trials registered as randomized trials.
668*6777b538SAndroid Build Coastguard Worker   // Trials created using the CreateFieldTrial() do not count towards this
669*6777b538SAndroid Build Coastguard Worker   // total.
670*6777b538SAndroid Build Coastguard Worker   static size_t GetRandomizedFieldTrialCount();
671*6777b538SAndroid Build Coastguard Worker 
672*6777b538SAndroid Build Coastguard Worker   // Gets the parameters for |field_trial| from shared memory and stores them in
673*6777b538SAndroid Build Coastguard Worker   // |params|. This is only exposed for use by FieldTrialParamAssociator and
674*6777b538SAndroid Build Coastguard Worker   // shouldn't be used by anything else.
675*6777b538SAndroid Build Coastguard Worker   static bool GetParamsFromSharedMemory(
676*6777b538SAndroid Build Coastguard Worker       FieldTrial* field_trial,
677*6777b538SAndroid Build Coastguard Worker       std::map<std::string, std::string>* params);
678*6777b538SAndroid Build Coastguard Worker 
679*6777b538SAndroid Build Coastguard Worker   // Clears all the params in the allocator.
680*6777b538SAndroid Build Coastguard Worker   static void ClearParamsFromSharedMemoryForTesting();
681*6777b538SAndroid Build Coastguard Worker 
682*6777b538SAndroid Build Coastguard Worker   // Dumps field trial state to an allocator so that it can be analyzed after a
683*6777b538SAndroid Build Coastguard Worker   // crash.
684*6777b538SAndroid Build Coastguard Worker   static void DumpAllFieldTrialsToPersistentAllocator(
685*6777b538SAndroid Build Coastguard Worker       PersistentMemoryAllocator* allocator);
686*6777b538SAndroid Build Coastguard Worker 
687*6777b538SAndroid Build Coastguard Worker   // Retrieves field trial state from an allocator so that it can be analyzed
688*6777b538SAndroid Build Coastguard Worker   // after a crash. The pointers in the returned vector are into the persistent
689*6777b538SAndroid Build Coastguard Worker   // memory segment and so are only valid as long as the allocator is valid.
690*6777b538SAndroid Build Coastguard Worker   static std::vector<const FieldTrial::FieldTrialEntry*>
691*6777b538SAndroid Build Coastguard Worker   GetAllFieldTrialsFromPersistentAllocator(
692*6777b538SAndroid Build Coastguard Worker       PersistentMemoryAllocator const& allocator);
693*6777b538SAndroid Build Coastguard Worker 
694*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the global instance. This is exposed so that it can
695*6777b538SAndroid Build Coastguard Worker   // be used in a DCHECK in FeatureList and ScopedFeatureList test-only logic
696*6777b538SAndroid Build Coastguard Worker   // and is not intended to be used widely beyond those cases.
697*6777b538SAndroid Build Coastguard Worker   static FieldTrialList* GetInstance();
698*6777b538SAndroid Build Coastguard Worker 
699*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the global instance, and resets the global instance
700*6777b538SAndroid Build Coastguard Worker   // to null. The returned instance can be destroyed if it is no longer needed.
701*6777b538SAndroid Build Coastguard Worker   static FieldTrialList* ResetInstance();
702*6777b538SAndroid Build Coastguard Worker 
703*6777b538SAndroid Build Coastguard Worker   // For testing, sets the global instance to null and returns the previous one.
704*6777b538SAndroid Build Coastguard Worker   static FieldTrialList* BackupInstanceForTesting();
705*6777b538SAndroid Build Coastguard Worker 
706*6777b538SAndroid Build Coastguard Worker   // For testing, sets the global instance to |instance|.
707*6777b538SAndroid Build Coastguard Worker   static void RestoreInstanceForTesting(FieldTrialList* instance);
708*6777b538SAndroid Build Coastguard Worker 
709*6777b538SAndroid Build Coastguard Worker   // Creates a list of FieldTrial::State for all FieldTrial instances.
710*6777b538SAndroid Build Coastguard Worker   // std::string_view members are bound to the lifetime of the corresponding
711*6777b538SAndroid Build Coastguard Worker   // FieldTrial.
712*6777b538SAndroid Build Coastguard Worker   static std::vector<FieldTrial::State> GetAllFieldTrialStates(
713*6777b538SAndroid Build Coastguard Worker       PassKey<test::ScopedFeatureList>);
714*6777b538SAndroid Build Coastguard Worker 
715*6777b538SAndroid Build Coastguard Worker   // Create FieldTrials from a list of FieldTrial::State. This method is only
716*6777b538SAndroid Build Coastguard Worker   // available to ScopedFeatureList for testing. The most typical usescase is:
717*6777b538SAndroid Build Coastguard Worker   // (1) AllStatesToFieldTrialStates(&field_trials);
718*6777b538SAndroid Build Coastguard Worker   // (2) backup_ = BackupInstanceForTesting();
719*6777b538SAndroid Build Coastguard Worker   //     // field_trials depends on backup_'s lifetype.
720*6777b538SAndroid Build Coastguard Worker   // (3) field_trial_list_ = new FieldTrialList();
721*6777b538SAndroid Build Coastguard Worker   // (4) CreateTrialsFromFieldTrialStates(field_trials);
722*6777b538SAndroid Build Coastguard Worker   //     // Copy backup_'s fieldtrials to the new field_trial_list_ while
723*6777b538SAndroid Build Coastguard Worker   //     // backup_ is alive.
724*6777b538SAndroid Build Coastguard Worker   // For resurrestion in another process, need to use AllStatesToString and
725*6777b538SAndroid Build Coastguard Worker   // CreateFieldTrialsFromString.
726*6777b538SAndroid Build Coastguard Worker   static bool CreateTrialsFromFieldTrialStates(
727*6777b538SAndroid Build Coastguard Worker       PassKey<test::ScopedFeatureList>,
728*6777b538SAndroid Build Coastguard Worker       const std::vector<FieldTrial::State>& entries);
729*6777b538SAndroid Build Coastguard Worker 
730*6777b538SAndroid Build Coastguard Worker  private:
731*6777b538SAndroid Build Coastguard Worker   // Allow tests to access our innards for testing purposes.
732*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, InstantiateAllocator);
733*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, AddTrialsToAllocator);
734*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest,
735*6777b538SAndroid Build Coastguard Worker                            DoNotAddSimulatedFieldTrialsToAllocator);
736*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, AssociateFieldTrialParams);
737*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, ClearParamsFromSharedMemory);
738*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest,
739*6777b538SAndroid Build Coastguard Worker                            SerializeSharedMemoryRegionMetadata);
740*6777b538SAndroid Build Coastguard Worker   friend int SerializeSharedMemoryRegionMetadata();
741*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, CheckReadOnlySharedMemoryRegion);
742*6777b538SAndroid Build Coastguard Worker 
743*6777b538SAndroid Build Coastguard Worker   // Required so that |FieldTrialListIncludingLowAnonymity| can expose APIs from
744*6777b538SAndroid Build Coastguard Worker   // this class to its friends.
745*6777b538SAndroid Build Coastguard Worker   friend class FieldTrialListIncludingLowAnonymity;
746*6777b538SAndroid Build Coastguard Worker 
747*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_BLINK)
748*6777b538SAndroid Build Coastguard Worker   // Serialization is used to pass information about the shared memory handle
749*6777b538SAndroid Build Coastguard Worker   // to child processes. This is achieved by passing a stringified reference to
750*6777b538SAndroid Build Coastguard Worker   // the relevant OS resources to the child process.
751*6777b538SAndroid Build Coastguard Worker   //
752*6777b538SAndroid Build Coastguard Worker   // Serialization populates |launch_options| with the relevant OS handles to
753*6777b538SAndroid Build Coastguard Worker   // transfer or copy to the child process and returns serialized information
754*6777b538SAndroid Build Coastguard Worker   // to be passed to the kFieldTrialHandle command-line switch.
755*6777b538SAndroid Build Coastguard Worker   // Note: On non-Mac POSIX platforms, it is necessary to pass down the file
756*6777b538SAndroid Build Coastguard Worker   // descriptor for the shared memory separately. It can be accessed via the
757*6777b538SAndroid Build Coastguard Worker   // GetFieldTrialDescriptor() API.
758*6777b538SAndroid Build Coastguard Worker   static std::string SerializeSharedMemoryRegionMetadata(
759*6777b538SAndroid Build Coastguard Worker       const ReadOnlySharedMemoryRegion& shm,
760*6777b538SAndroid Build Coastguard Worker       LaunchOptions* launch_options);
761*6777b538SAndroid Build Coastguard Worker 
762*6777b538SAndroid Build Coastguard Worker   // Takes in |handle_switch| from the command line which represents the shared
763*6777b538SAndroid Build Coastguard Worker   // memory handle for field trials, parses it, and creates the field trials.
764*6777b538SAndroid Build Coastguard Worker   // Returns true on success, false on failure.
765*6777b538SAndroid Build Coastguard Worker   // |switch_value| also contains the serialized GUID.
766*6777b538SAndroid Build Coastguard Worker   static base::shared_memory::SharedMemoryError CreateTrialsFromSwitchValue(
767*6777b538SAndroid Build Coastguard Worker       const std::string& switch_value);
768*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(USE_BLINK)
769*6777b538SAndroid Build Coastguard Worker 
770*6777b538SAndroid Build Coastguard Worker   // Takes an unmapped ReadOnlySharedMemoryRegion, maps it with the correct size
771*6777b538SAndroid Build Coastguard Worker   // and creates field trials via CreateTrialsFromSharedMemoryMapping(). Returns
772*6777b538SAndroid Build Coastguard Worker   // true if successful and false otherwise.
773*6777b538SAndroid Build Coastguard Worker   static bool CreateTrialsFromSharedMemoryRegion(
774*6777b538SAndroid Build Coastguard Worker       const ReadOnlySharedMemoryRegion& shm_region);
775*6777b538SAndroid Build Coastguard Worker 
776*6777b538SAndroid Build Coastguard Worker   // Expects a mapped piece of shared memory |shm_mapping| that was created from
777*6777b538SAndroid Build Coastguard Worker   // the browser process's field_trial_allocator and shared via the command
778*6777b538SAndroid Build Coastguard Worker   // line. This function recreates the allocator, iterates through all the field
779*6777b538SAndroid Build Coastguard Worker   // trials in it, and creates them via CreateFieldTrial(). Returns true if
780*6777b538SAndroid Build Coastguard Worker   // successful and false otherwise.
781*6777b538SAndroid Build Coastguard Worker   static bool CreateTrialsFromSharedMemoryMapping(
782*6777b538SAndroid Build Coastguard Worker       ReadOnlySharedMemoryMapping shm_mapping);
783*6777b538SAndroid Build Coastguard Worker 
784*6777b538SAndroid Build Coastguard Worker   // Instantiate the field trial allocator, add all existing field trials to it,
785*6777b538SAndroid Build Coastguard Worker   // and duplicates its handle to a read-only handle, which gets stored in
786*6777b538SAndroid Build Coastguard Worker   // |readonly_allocator_handle|.
787*6777b538SAndroid Build Coastguard Worker   static void InstantiateFieldTrialAllocatorIfNeeded();
788*6777b538SAndroid Build Coastguard Worker 
789*6777b538SAndroid Build Coastguard Worker   // Adds the field trial to the allocator. Caller must hold a lock before
790*6777b538SAndroid Build Coastguard Worker   // calling this.
791*6777b538SAndroid Build Coastguard Worker   static void AddToAllocatorWhileLocked(PersistentMemoryAllocator* allocator,
792*6777b538SAndroid Build Coastguard Worker                                         FieldTrial* field_trial);
793*6777b538SAndroid Build Coastguard Worker 
794*6777b538SAndroid Build Coastguard Worker   // Activate the corresponding field trial entry struct in shared memory.
795*6777b538SAndroid Build Coastguard Worker   static void ActivateFieldTrialEntryWhileLocked(FieldTrial* field_trial);
796*6777b538SAndroid Build Coastguard Worker 
797*6777b538SAndroid Build Coastguard Worker   // A map from FieldTrial names to the actual instances.
798*6777b538SAndroid Build Coastguard Worker   typedef std::map<std::string, FieldTrial*, std::less<>> RegistrationMap;
799*6777b538SAndroid Build Coastguard Worker 
800*6777b538SAndroid Build Coastguard Worker   // Helper function should be called only while holding lock_.
801*6777b538SAndroid Build Coastguard Worker   FieldTrial* PreLockedFind(std::string_view name)
802*6777b538SAndroid Build Coastguard Worker       EXCLUSIVE_LOCKS_REQUIRED(lock_);
803*6777b538SAndroid Build Coastguard Worker 
804*6777b538SAndroid Build Coastguard Worker   // Register() stores a pointer to the given trial in a global map.
805*6777b538SAndroid Build Coastguard Worker   // This method also AddRef's the indicated trial.
806*6777b538SAndroid Build Coastguard Worker   // This should always be called after creating a new FieldTrial instance.
807*6777b538SAndroid Build Coastguard Worker   // If the caller wants to select the instance's group randomly,
808*6777b538SAndroid Build Coastguard Worker   // |is_randomized_trial| should be true to count the number of randomized
809*6777b538SAndroid Build Coastguard Worker   // trials correctly. Otherwise, false.
810*6777b538SAndroid Build Coastguard Worker   static void Register(FieldTrial* trial, bool is_randomized_trial);
811*6777b538SAndroid Build Coastguard Worker 
812*6777b538SAndroid Build Coastguard Worker   // Returns all the registered trials.
813*6777b538SAndroid Build Coastguard Worker   static RegistrationMap GetRegisteredTrials();
814*6777b538SAndroid Build Coastguard Worker 
815*6777b538SAndroid Build Coastguard Worker   // Create field trials from a list of FieldTrial::State.
816*6777b538SAndroid Build Coastguard Worker   // CreateTrialsFromString() and CreateTrialsFromFieldTrialStates() use this
817*6777b538SAndroid Build Coastguard Worker   // method internally.
818*6777b538SAndroid Build Coastguard Worker   static bool CreateTrialsFromFieldTrialStatesInternal(
819*6777b538SAndroid Build Coastguard Worker       const std::vector<FieldTrial::State>& entries);
820*6777b538SAndroid Build Coastguard Worker 
821*6777b538SAndroid Build Coastguard Worker   // The same as |GetActiveFieldTrialGroups| but also gives access to low
822*6777b538SAndroid Build Coastguard Worker   // anonymity field trials.
823*6777b538SAndroid Build Coastguard Worker   // Restricted to specifically allowed friends - access via
824*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity::GetActiveFieldTrialGroups|.
825*6777b538SAndroid Build Coastguard Worker   static void GetActiveFieldTrialGroupsInternal(
826*6777b538SAndroid Build Coastguard Worker       FieldTrial::ActiveGroups* active_groups,
827*6777b538SAndroid Build Coastguard Worker       bool include_low_anonymity);
828*6777b538SAndroid Build Coastguard Worker 
829*6777b538SAndroid Build Coastguard Worker   // The same as |AddObserver| but is notified for low anonymity field trials
830*6777b538SAndroid Build Coastguard Worker   // too.
831*6777b538SAndroid Build Coastguard Worker   // Restricted to specifically allowed friends - access via
832*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity::AddObserver|.
833*6777b538SAndroid Build Coastguard Worker   static bool AddObserverInternal(Observer* observer,
834*6777b538SAndroid Build Coastguard Worker                                   bool include_low_anonymity);
835*6777b538SAndroid Build Coastguard Worker 
836*6777b538SAndroid Build Coastguard Worker   // The same as |RemoveObserver| but is notified for low anonymity field trials
837*6777b538SAndroid Build Coastguard Worker   // too.
838*6777b538SAndroid Build Coastguard Worker   // Restricted to specifically allowed friends - access via
839*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity::RemoveObserver|.
840*6777b538SAndroid Build Coastguard Worker   static void RemoveObserverInternal(Observer* observer,
841*6777b538SAndroid Build Coastguard Worker                                      bool include_low_anonymity);
842*6777b538SAndroid Build Coastguard Worker 
843*6777b538SAndroid Build Coastguard Worker   static FieldTrialList* global_;  // The singleton of this class.
844*6777b538SAndroid Build Coastguard Worker 
845*6777b538SAndroid Build Coastguard Worker   // Lock for access to |registered_|, |observers_|,
846*6777b538SAndroid Build Coastguard Worker   // |observers_including_low_anonymity_|,
847*6777b538SAndroid Build Coastguard Worker   // |count_of_manually_created_field_trials_|.
848*6777b538SAndroid Build Coastguard Worker   Lock lock_;
849*6777b538SAndroid Build Coastguard Worker   RegistrationMap registered_ GUARDED_BY(lock_);
850*6777b538SAndroid Build Coastguard Worker 
851*6777b538SAndroid Build Coastguard Worker   // Counts the number of field trials whose groups are selected randomly.
852*6777b538SAndroid Build Coastguard Worker   size_t num_registered_randomized_trials_ GUARDED_BY(lock_) = 0;
853*6777b538SAndroid Build Coastguard Worker 
854*6777b538SAndroid Build Coastguard Worker   // List of observers to be notified when a group is selected for a FieldTrial.
855*6777b538SAndroid Build Coastguard Worker   // Excludes low anonymity field trials.
856*6777b538SAndroid Build Coastguard Worker   std::vector<raw_ptr<Observer, VectorExperimental>> observers_
857*6777b538SAndroid Build Coastguard Worker       GUARDED_BY(lock_);
858*6777b538SAndroid Build Coastguard Worker 
859*6777b538SAndroid Build Coastguard Worker   // List of observers to be notified when a group is selected for a FieldTrial.
860*6777b538SAndroid Build Coastguard Worker   // Includes low anonymity field trials.
861*6777b538SAndroid Build Coastguard Worker   std::vector<raw_ptr<Observer, VectorExperimental>>
862*6777b538SAndroid Build Coastguard Worker       observers_including_low_anonymity_ GUARDED_BY(lock_);
863*6777b538SAndroid Build Coastguard Worker 
864*6777b538SAndroid Build Coastguard Worker   // Counts the ongoing calls to
865*6777b538SAndroid Build Coastguard Worker   // FieldTrialList::NotifyFieldTrialGroupSelection(). Used to ensure that
866*6777b538SAndroid Build Coastguard Worker   // RemoveObserver() isn't called while notifying observers.
867*6777b538SAndroid Build Coastguard Worker   std::atomic_int num_ongoing_notify_field_trial_group_selection_calls_{0};
868*6777b538SAndroid Build Coastguard Worker 
869*6777b538SAndroid Build Coastguard Worker   // Allocator in shared memory containing field trial data. Used in both
870*6777b538SAndroid Build Coastguard Worker   // browser and child processes, but readonly in the child.
871*6777b538SAndroid Build Coastguard Worker   // In the future, we may want to move this to a more generic place if we want
872*6777b538SAndroid Build Coastguard Worker   // to start passing more data other than field trials.
873*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<FieldTrialAllocator> field_trial_allocator_;
874*6777b538SAndroid Build Coastguard Worker 
875*6777b538SAndroid Build Coastguard Worker   // Readonly copy of the region to the allocator. Needs to be a member variable
876*6777b538SAndroid Build Coastguard Worker   // because it's needed from multiple methods.
877*6777b538SAndroid Build Coastguard Worker   ReadOnlySharedMemoryRegion readonly_allocator_region_;
878*6777b538SAndroid Build Coastguard Worker 
879*6777b538SAndroid Build Coastguard Worker   // Tracks whether CreateTrialsInChildProcess() has been called.
880*6777b538SAndroid Build Coastguard Worker   bool create_trials_in_child_process_called_ = false;
881*6777b538SAndroid Build Coastguard Worker 
882*6777b538SAndroid Build Coastguard Worker   // Tracks if ResetInstance was called for this instance, to avoid resetting
883*6777b538SAndroid Build Coastguard Worker   // `global_` in the destructor.
884*6777b538SAndroid Build Coastguard Worker   bool was_reset_ = false;
885*6777b538SAndroid Build Coastguard Worker };
886*6777b538SAndroid Build Coastguard Worker 
887*6777b538SAndroid Build Coastguard Worker }  // namespace base
888*6777b538SAndroid Build Coastguard Worker 
889*6777b538SAndroid Build Coastguard Worker #endif  // BASE_METRICS_FIELD_TRIAL_H_
890