xref: /aosp_15_r20/external/cronet/base/feature_list.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 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 #ifndef BASE_FEATURE_LIST_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_FEATURE_LIST_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <atomic>
9*6777b538SAndroid Build Coastguard Worker #include <functional>
10*6777b538SAndroid Build Coastguard Worker #include <map>
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker #include <optional>
13*6777b538SAndroid Build Coastguard Worker #include <string>
14*6777b538SAndroid Build Coastguard Worker #include <string_view>
15*6777b538SAndroid Build Coastguard Worker #include <utility>
16*6777b538SAndroid Build Coastguard Worker #include <vector>
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/containers/flat_map.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/containers/flat_set.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/feature_list_buildflags.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
28*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
29*6777b538SAndroid Build Coastguard Worker #include "build/chromeos_buildflags.h"
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker namespace base {
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker class FieldTrial;
34*6777b538SAndroid Build Coastguard Worker class FieldTrialList;
35*6777b538SAndroid Build Coastguard Worker class PersistentMemoryAllocator;
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS_ASH)
38*6777b538SAndroid Build Coastguard Worker class FeatureVisitor;
39*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker // Specifies whether a given feature is enabled or disabled by default.
42*6777b538SAndroid Build Coastguard Worker // NOTE: The actual runtime state may be different, due to a field trial or a
43*6777b538SAndroid Build Coastguard Worker // command line switch.
44*6777b538SAndroid Build Coastguard Worker enum FeatureState {
45*6777b538SAndroid Build Coastguard Worker   FEATURE_DISABLED_BY_DEFAULT,
46*6777b538SAndroid Build Coastguard Worker   FEATURE_ENABLED_BY_DEFAULT,
47*6777b538SAndroid Build Coastguard Worker };
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker // Recommended macros for declaring and defining features:
50*6777b538SAndroid Build Coastguard Worker //
51*6777b538SAndroid Build Coastguard Worker // - `kFeature` is the C++ identifier that will be used for the `base::Feature`.
52*6777b538SAndroid Build Coastguard Worker // - `name` is the feature name, which must be globally unique. This name is
53*6777b538SAndroid Build Coastguard Worker //   used to enable/disable features via experiments and command-line flags.
54*6777b538SAndroid Build Coastguard Worker //   Names should use CamelCase-style naming, e.g. "MyGreatFeature".
55*6777b538SAndroid Build Coastguard Worker // - `default_state` is the default state to use for the feature, i.e.
56*6777b538SAndroid Build Coastguard Worker //   `base::FEATURE_DISABLED_BY_DEFAULT` or `base::FEATURE_ENABLED_BY_DEFAULT`.
57*6777b538SAndroid Build Coastguard Worker //   As noted above, the actual runtime state may differ from the default state,
58*6777b538SAndroid Build Coastguard Worker //   due to field trials or command-line switches.
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker // Provides a forward declaration for `kFeature` in a header file, e.g.
61*6777b538SAndroid Build Coastguard Worker //
62*6777b538SAndroid Build Coastguard Worker //   BASE_DECLARE_FEATURE(kMyFeature);
63*6777b538SAndroid Build Coastguard Worker //
64*6777b538SAndroid Build Coastguard Worker // If the feature needs to be marked as exported, i.e. it is referenced by
65*6777b538SAndroid Build Coastguard Worker // multiple components, then write:
66*6777b538SAndroid Build Coastguard Worker //
67*6777b538SAndroid Build Coastguard Worker //   COMPONENT_EXPORT(MY_COMPONENT) BASE_DECLARE_FEATURE(kMyFeature);
68*6777b538SAndroid Build Coastguard Worker #define BASE_DECLARE_FEATURE(kFeature) \
69*6777b538SAndroid Build Coastguard Worker   extern constinit const base::Feature kFeature
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker // Provides a definition for `kFeature` with `name` and `default_state`, e.g.
72*6777b538SAndroid Build Coastguard Worker //
73*6777b538SAndroid Build Coastguard Worker //   BASE_FEATURE(kMyFeature, "MyFeature", base::FEATURE_DISABLED_BY_DEFAULT);
74*6777b538SAndroid Build Coastguard Worker //
75*6777b538SAndroid Build Coastguard Worker // Features should *not* be defined in header files; do not use this macro in
76*6777b538SAndroid Build Coastguard Worker // header files.
77*6777b538SAndroid Build Coastguard Worker #define BASE_FEATURE(feature, name, default_state) \
78*6777b538SAndroid Build Coastguard Worker   constinit const base::Feature feature(name, default_state)
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker // The Feature struct is used to define the default state for a feature. There
81*6777b538SAndroid Build Coastguard Worker // must only ever be one struct instance for a given feature name—generally
82*6777b538SAndroid Build Coastguard Worker // defined as a constant global variable or file static. Declare and define
83*6777b538SAndroid Build Coastguard Worker // features using the `BASE_DECLARE_FEATURE()` and `BASE_FEATURE()` macros
84*6777b538SAndroid Build Coastguard Worker // above, as there are some subtleties involved.
85*6777b538SAndroid Build Coastguard Worker //
86*6777b538SAndroid Build Coastguard Worker // Feature constants are internally mutable, as this allows them to contain a
87*6777b538SAndroid Build Coastguard Worker // mutable member to cache their override state, while still remaining declared
88*6777b538SAndroid Build Coastguard Worker // as const. This cache member allows for significantly faster IsEnabled()
89*6777b538SAndroid Build Coastguard Worker // checks.
90*6777b538SAndroid Build Coastguard Worker //
91*6777b538SAndroid Build Coastguard Worker // However, the "Mutable Constants" check [1] detects this as a regression,
92*6777b538SAndroid Build Coastguard Worker // because this usually means that a readonly symbol is put in writable memory
93*6777b538SAndroid Build Coastguard Worker // when readonly memory would be more efficient.
94*6777b538SAndroid Build Coastguard Worker //
95*6777b538SAndroid Build Coastguard Worker // The performance gains of the cache are large enough to offset the downsides
96*6777b538SAndroid Build Coastguard Worker // to having the symbols in bssdata rather than rodata. Use LOGICALLY_CONST to
97*6777b538SAndroid Build Coastguard Worker // suppress the "Mutable Constants" check.
98*6777b538SAndroid Build Coastguard Worker //
99*6777b538SAndroid Build Coastguard Worker // [1]:
100*6777b538SAndroid Build Coastguard Worker // https://crsrc.org/c/docs/speed/binary_size/android_binary_size_trybot.md#Mutable-Constants
101*6777b538SAndroid Build Coastguard Worker struct BASE_EXPORT LOGICALLY_CONST Feature {
FeatureFeature102*6777b538SAndroid Build Coastguard Worker   constexpr Feature(const char* name, FeatureState default_state)
103*6777b538SAndroid Build Coastguard Worker       : name(name), default_state(default_state) {
104*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_BANNED_BASE_FEATURE_PREFIX)
105*6777b538SAndroid Build Coastguard Worker     if (std::string_view(name).find(BUILDFLAG(BANNED_BASE_FEATURE_PREFIX)) ==
106*6777b538SAndroid Build Coastguard Worker         0) {
107*6777b538SAndroid Build Coastguard Worker       LOG(FATAL) << "Invalid feature name " << name << " starts with "
108*6777b538SAndroid Build Coastguard Worker                  << BUILDFLAG(BANNED_BASE_FEATURE_PREFIX);
109*6777b538SAndroid Build Coastguard Worker     }
110*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(ENABLE_BANNED_BASE_FEATURE_PREFIX)
111*6777b538SAndroid Build Coastguard Worker   }
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker   // Non-copyable since:
114*6777b538SAndroid Build Coastguard Worker   // - there should be only one `Feature` instance per unique name.
115*6777b538SAndroid Build Coastguard Worker   // - a `Feature` contains internal cached state about the override state.
116*6777b538SAndroid Build Coastguard Worker   Feature(const Feature&) = delete;
117*6777b538SAndroid Build Coastguard Worker   Feature& operator=(const Feature&) = delete;
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker   // The name of the feature. This should be unique to each feature and is used
120*6777b538SAndroid Build Coastguard Worker   // for enabling/disabling features via command line flags and experiments.
121*6777b538SAndroid Build Coastguard Worker   // It is strongly recommended to use CamelCase style for feature names, e.g.
122*6777b538SAndroid Build Coastguard Worker   // "MyGreatFeature".
123*6777b538SAndroid Build Coastguard Worker   const char* const name;
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // The default state (i.e. enabled or disabled) for this feature.
126*6777b538SAndroid Build Coastguard Worker   // NOTE: The actual runtime state may be different, due to a field trial or a
127*6777b538SAndroid Build Coastguard Worker   // command line switch.
128*6777b538SAndroid Build Coastguard Worker   const FeatureState default_state;
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker  private:
131*6777b538SAndroid Build Coastguard Worker   friend class FeatureList;
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker   // A packed value where the first 8 bits represent the `OverrideState` of this
134*6777b538SAndroid Build Coastguard Worker   // feature, and the last 16 bits are a caching context ID used to allow
135*6777b538SAndroid Build Coastguard Worker   // ScopedFeatureLists to invalidate these cached values in testing. A value of
136*6777b538SAndroid Build Coastguard Worker   // 0 in the caching context ID field indicates that this value has never been
137*6777b538SAndroid Build Coastguard Worker   // looked up and cached, a value of 1 indicates this value contains the cached
138*6777b538SAndroid Build Coastguard Worker   // `OverrideState` that was looked up via `base::FeatureList`, and any other
139*6777b538SAndroid Build Coastguard Worker   // value indicate that this cached value is only valid for a particular
140*6777b538SAndroid Build Coastguard Worker   // ScopedFeatureList instance.
141*6777b538SAndroid Build Coastguard Worker   //
142*6777b538SAndroid Build Coastguard Worker   // Packing these values into a uint32_t makes it so that atomic operations
143*6777b538SAndroid Build Coastguard Worker   // performed on this fields can be lock free.
144*6777b538SAndroid Build Coastguard Worker   //
145*6777b538SAndroid Build Coastguard Worker   // The override state stored in this field is only used if the current
146*6777b538SAndroid Build Coastguard Worker   // `FeatureList::caching_context_` field is equal to the lower 16 bits of the
147*6777b538SAndroid Build Coastguard Worker   // packed cached value. Otherwise, the override state is looked up in the
148*6777b538SAndroid Build Coastguard Worker   // feature list and the cache is updated.
149*6777b538SAndroid Build Coastguard Worker   mutable std::atomic<uint32_t> cached_value = 0;
150*6777b538SAndroid Build Coastguard Worker };
151*6777b538SAndroid Build Coastguard Worker 
152*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
153*6777b538SAndroid Build Coastguard Worker // DCHECKs have been built-in, and are configurable at run-time to be fatal, or
154*6777b538SAndroid Build Coastguard Worker // not, via a DcheckIsFatal feature. We define the Feature here since it is
155*6777b538SAndroid Build Coastguard Worker // checked in FeatureList::SetInstance(). See https://crbug.com/596231.
156*6777b538SAndroid Build Coastguard Worker BASE_EXPORT BASE_DECLARE_FEATURE(kDCheckIsFatalFeature);
157*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(DCHECK_IS_CONFIGURABLE)
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker // The FeatureList class is used to determine whether a given feature is on or
160*6777b538SAndroid Build Coastguard Worker // off. It provides an authoritative answer, taking into account command-line
161*6777b538SAndroid Build Coastguard Worker // overrides and experimental control.
162*6777b538SAndroid Build Coastguard Worker //
163*6777b538SAndroid Build Coastguard Worker // The basic use case is for any feature that can be toggled (e.g. through
164*6777b538SAndroid Build Coastguard Worker // command-line or an experiment) to have a defined Feature struct, e.g.:
165*6777b538SAndroid Build Coastguard Worker //
166*6777b538SAndroid Build Coastguard Worker //   const base::Feature kMyGreatFeature {
167*6777b538SAndroid Build Coastguard Worker //     "MyGreatFeature", base::FEATURE_ENABLED_BY_DEFAULT
168*6777b538SAndroid Build Coastguard Worker //   };
169*6777b538SAndroid Build Coastguard Worker //
170*6777b538SAndroid Build Coastguard Worker // Then, client code that wishes to query the state of the feature would check:
171*6777b538SAndroid Build Coastguard Worker //
172*6777b538SAndroid Build Coastguard Worker //   if (base::FeatureList::IsEnabled(kMyGreatFeature)) {
173*6777b538SAndroid Build Coastguard Worker //     // Feature code goes here.
174*6777b538SAndroid Build Coastguard Worker //   }
175*6777b538SAndroid Build Coastguard Worker //
176*6777b538SAndroid Build Coastguard Worker // Behind the scenes, the above call would take into account any command-line
177*6777b538SAndroid Build Coastguard Worker // flags to enable or disable the feature, any experiments that may control it
178*6777b538SAndroid Build Coastguard Worker // and finally its default state (in that order of priority), to determine
179*6777b538SAndroid Build Coastguard Worker // whether the feature is on.
180*6777b538SAndroid Build Coastguard Worker //
181*6777b538SAndroid Build Coastguard Worker // Features can be explicitly forced on or off by specifying a list of comma-
182*6777b538SAndroid Build Coastguard Worker // separated feature names via the following command-line flags:
183*6777b538SAndroid Build Coastguard Worker //
184*6777b538SAndroid Build Coastguard Worker //   --enable-features=Feature5,Feature7
185*6777b538SAndroid Build Coastguard Worker //   --disable-features=Feature1,Feature2,Feature3
186*6777b538SAndroid Build Coastguard Worker //
187*6777b538SAndroid Build Coastguard Worker // To enable/disable features in a test, do NOT append --enable-features or
188*6777b538SAndroid Build Coastguard Worker // --disable-features to the command-line directly. Instead, use
189*6777b538SAndroid Build Coastguard Worker // ScopedFeatureList. See base/test/scoped_feature_list.h for details.
190*6777b538SAndroid Build Coastguard Worker //
191*6777b538SAndroid Build Coastguard Worker // After initialization (which should be done single-threaded), the FeatureList
192*6777b538SAndroid Build Coastguard Worker // API is thread safe.
193*6777b538SAndroid Build Coastguard Worker //
194*6777b538SAndroid Build Coastguard Worker // Note: This class is a singleton, but does not use base/memory/singleton.h in
195*6777b538SAndroid Build Coastguard Worker // order to have control over its initialization sequence. Specifically, the
196*6777b538SAndroid Build Coastguard Worker // intended use is to create an instance of this class and fully initialize it,
197*6777b538SAndroid Build Coastguard Worker // before setting it as the singleton for a process, via SetInstance().
198*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT FeatureList {
199*6777b538SAndroid Build Coastguard Worker  public:
200*6777b538SAndroid Build Coastguard Worker   FeatureList();
201*6777b538SAndroid Build Coastguard Worker   FeatureList(const FeatureList&) = delete;
202*6777b538SAndroid Build Coastguard Worker   FeatureList& operator=(const FeatureList&) = delete;
203*6777b538SAndroid Build Coastguard Worker   ~FeatureList();
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker   // Used by common test fixture classes to prevent abuse of ScopedFeatureList
206*6777b538SAndroid Build Coastguard Worker   // after multiple threads have started.
207*6777b538SAndroid Build Coastguard Worker   class BASE_EXPORT ScopedDisallowOverrides {
208*6777b538SAndroid Build Coastguard Worker    public:
209*6777b538SAndroid Build Coastguard Worker     explicit ScopedDisallowOverrides(const char* reason);
210*6777b538SAndroid Build Coastguard Worker     ScopedDisallowOverrides(const ScopedDisallowOverrides&) = delete;
211*6777b538SAndroid Build Coastguard Worker     ScopedDisallowOverrides& operator=(const ScopedDisallowOverrides&) = delete;
212*6777b538SAndroid Build Coastguard Worker     ~ScopedDisallowOverrides();
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker    private:
215*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
216*6777b538SAndroid Build Coastguard Worker     const char* const previous_reason_;
217*6777b538SAndroid Build Coastguard Worker #endif
218*6777b538SAndroid Build Coastguard Worker   };
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker   // Specifies whether a feature override enables or disables the feature.
221*6777b538SAndroid Build Coastguard Worker   enum OverrideState {
222*6777b538SAndroid Build Coastguard Worker     OVERRIDE_USE_DEFAULT,
223*6777b538SAndroid Build Coastguard Worker     OVERRIDE_DISABLE_FEATURE,
224*6777b538SAndroid Build Coastguard Worker     OVERRIDE_ENABLE_FEATURE,
225*6777b538SAndroid Build Coastguard Worker   };
226*6777b538SAndroid Build Coastguard Worker 
227*6777b538SAndroid Build Coastguard Worker   // Accessor class, used to look up features by _name_ rather than by Feature
228*6777b538SAndroid Build Coastguard Worker   // object.
229*6777b538SAndroid Build Coastguard Worker   // Should only be used in limited cases. See ConstructAccessor() for details.
230*6777b538SAndroid Build Coastguard Worker   class BASE_EXPORT Accessor {
231*6777b538SAndroid Build Coastguard Worker    public:
232*6777b538SAndroid Build Coastguard Worker     Accessor(const Accessor&) = delete;
233*6777b538SAndroid Build Coastguard Worker     Accessor& operator=(const Accessor&) = delete;
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker     // Looks up the feature, returning only its override state, rather than
236*6777b538SAndroid Build Coastguard Worker     // falling back on a default value (since there is no default value given).
237*6777b538SAndroid Build Coastguard Worker     // Callers of this MUST ensure that there is a consistent, compile-time
238*6777b538SAndroid Build Coastguard Worker     // default value associated.
239*6777b538SAndroid Build Coastguard Worker     FeatureList::OverrideState GetOverrideStateByFeatureName(
240*6777b538SAndroid Build Coastguard Worker         std::string_view feature_name);
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker     // Look up the feature, and, if present, populate |params|.
243*6777b538SAndroid Build Coastguard Worker     // See GetFieldTrialParams in field_trial_params.h for more documentation.
244*6777b538SAndroid Build Coastguard Worker     bool GetParamsByFeatureName(std::string_view feature_name,
245*6777b538SAndroid Build Coastguard Worker                                 std::map<std::string, std::string>* params);
246*6777b538SAndroid Build Coastguard Worker 
247*6777b538SAndroid Build Coastguard Worker    private:
248*6777b538SAndroid Build Coastguard Worker     // Allow FeatureList to construct this class.
249*6777b538SAndroid Build Coastguard Worker     friend class FeatureList;
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker     explicit Accessor(FeatureList* feature_list);
252*6777b538SAndroid Build Coastguard Worker 
253*6777b538SAndroid Build Coastguard Worker     // Unowned pointer to the FeatureList object we use to look up feature
254*6777b538SAndroid Build Coastguard Worker     // enablement.
255*6777b538SAndroid Build Coastguard Worker     raw_ptr<FeatureList, DanglingUntriaged> feature_list_;
256*6777b538SAndroid Build Coastguard Worker   };
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker   // Describes a feature override. The first member is a Feature that will be
259*6777b538SAndroid Build Coastguard Worker   // overridden with the state given by the second member.
260*6777b538SAndroid Build Coastguard Worker   using FeatureOverrideInfo =
261*6777b538SAndroid Build Coastguard Worker       std::pair<const std::reference_wrapper<const Feature>, OverrideState>;
262*6777b538SAndroid Build Coastguard Worker 
263*6777b538SAndroid Build Coastguard Worker   // Initializes feature overrides via command-line flags `--enable-features=`
264*6777b538SAndroid Build Coastguard Worker   // and `--disable-features=`, each of which is a comma-separated list of
265*6777b538SAndroid Build Coastguard Worker   // features to enable or disable, respectively. This function also allows
266*6777b538SAndroid Build Coastguard Worker   // users to set a feature's field trial params via `--enable-features=`. Must
267*6777b538SAndroid Build Coastguard Worker   // only be invoked during the initialization phase (before
268*6777b538SAndroid Build Coastguard Worker   // FinalizeInitialization() has been called).
269*6777b538SAndroid Build Coastguard Worker   //
270*6777b538SAndroid Build Coastguard Worker   // If a feature appears on both lists, then it will be disabled. If
271*6777b538SAndroid Build Coastguard Worker   // a list entry has the format "FeatureName<TrialName" then this
272*6777b538SAndroid Build Coastguard Worker   // initialization will also associate the feature state override with the
273*6777b538SAndroid Build Coastguard Worker   // named field trial, if it exists. If a list entry has the format
274*6777b538SAndroid Build Coastguard Worker   // "FeatureName:k1/v1/k2/v2", "FeatureName<TrialName:k1/v1/k2/v2" or
275*6777b538SAndroid Build Coastguard Worker   // "FeatureName<TrialName.GroupName:k1/v1/k2/v2" then this initialization will
276*6777b538SAndroid Build Coastguard Worker   // also associate the feature state override with the named field trial and
277*6777b538SAndroid Build Coastguard Worker   // its params. If the feature params part is provided but trial and/or group
278*6777b538SAndroid Build Coastguard Worker   // isn't, this initialization will also create a synthetic trial, named
279*6777b538SAndroid Build Coastguard Worker   // "Study" followed by the feature name, i.e. "StudyFeature", and group, named
280*6777b538SAndroid Build Coastguard Worker   // "Group" followed by the feature name, i.e. "GroupFeature", for the params.
281*6777b538SAndroid Build Coastguard Worker   // If a feature name is prefixed with the '*' character, it will be created
282*6777b538SAndroid Build Coastguard Worker   // with OVERRIDE_USE_DEFAULT - which is useful for associating with a trial
283*6777b538SAndroid Build Coastguard Worker   // while using the default state.
284*6777b538SAndroid Build Coastguard Worker   void InitFromCommandLine(const std::string& enable_features,
285*6777b538SAndroid Build Coastguard Worker                            const std::string& disable_features);
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   // Initializes feature overrides through the field trial allocator, which
288*6777b538SAndroid Build Coastguard Worker   // we're using to store the feature names, their override state, and the name
289*6777b538SAndroid Build Coastguard Worker   // of the associated field trial.
290*6777b538SAndroid Build Coastguard Worker   void InitFromSharedMemory(PersistentMemoryAllocator* allocator);
291*6777b538SAndroid Build Coastguard Worker 
292*6777b538SAndroid Build Coastguard Worker   // Returns true if the state of |feature_name| has been overridden (regardless
293*6777b538SAndroid Build Coastguard Worker   // of whether the overridden value is the same as the default value) for any
294*6777b538SAndroid Build Coastguard Worker   // reason (e.g. command line or field trial).
295*6777b538SAndroid Build Coastguard Worker   bool IsFeatureOverridden(const std::string& feature_name) const;
296*6777b538SAndroid Build Coastguard Worker 
297*6777b538SAndroid Build Coastguard Worker   // Returns true if the state of |feature_name| has been overridden via
298*6777b538SAndroid Build Coastguard Worker   // |InitFromCommandLine()|. This includes features explicitly
299*6777b538SAndroid Build Coastguard Worker   // disabled/enabled with --disable-features and --enable-features, as well as
300*6777b538SAndroid Build Coastguard Worker   // any extra feature overrides that depend on command line switches.
301*6777b538SAndroid Build Coastguard Worker   bool IsFeatureOverriddenFromCommandLine(
302*6777b538SAndroid Build Coastguard Worker       const std::string& feature_name) const;
303*6777b538SAndroid Build Coastguard Worker 
304*6777b538SAndroid Build Coastguard Worker   // Returns true if the state |feature_name| has been overridden by
305*6777b538SAndroid Build Coastguard Worker   // |InitFromCommandLine()| and the state matches |state|.
306*6777b538SAndroid Build Coastguard Worker   bool IsFeatureOverriddenFromCommandLine(const std::string& feature_name,
307*6777b538SAndroid Build Coastguard Worker                                           OverrideState state) const;
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker   // Associates a field trial for reporting purposes corresponding to the
310*6777b538SAndroid Build Coastguard Worker   // command-line setting the feature state to |for_overridden_state|. The trial
311*6777b538SAndroid Build Coastguard Worker   // will be activated when the state of the feature is first queried. This
312*6777b538SAndroid Build Coastguard Worker   // should be called during registration, after InitFromCommandLine() has
313*6777b538SAndroid Build Coastguard Worker   // been called but before the instance is registered via SetInstance().
314*6777b538SAndroid Build Coastguard Worker   void AssociateReportingFieldTrial(const std::string& feature_name,
315*6777b538SAndroid Build Coastguard Worker                                     OverrideState for_overridden_state,
316*6777b538SAndroid Build Coastguard Worker                                     FieldTrial* field_trial);
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker   // Registers a field trial to override the enabled state of the specified
319*6777b538SAndroid Build Coastguard Worker   // feature to |override_state|. Command-line overrides still take precedence
320*6777b538SAndroid Build Coastguard Worker   // over field trials, so this will have no effect if the feature is being
321*6777b538SAndroid Build Coastguard Worker   // overridden from the command-line. The associated field trial will be
322*6777b538SAndroid Build Coastguard Worker   // activated when the feature state for this feature is queried. This should
323*6777b538SAndroid Build Coastguard Worker   // be called during registration, after InitFromCommandLine() has been
324*6777b538SAndroid Build Coastguard Worker   // called but before the instance is registered via SetInstance().
325*6777b538SAndroid Build Coastguard Worker   void RegisterFieldTrialOverride(const std::string& feature_name,
326*6777b538SAndroid Build Coastguard Worker                                   OverrideState override_state,
327*6777b538SAndroid Build Coastguard Worker                                   FieldTrial* field_trial);
328*6777b538SAndroid Build Coastguard Worker 
329*6777b538SAndroid Build Coastguard Worker   // Adds extra overrides (not associated with a field trial). Should be called
330*6777b538SAndroid Build Coastguard Worker   // before SetInstance().
331*6777b538SAndroid Build Coastguard Worker   // The ordering of calls with respect to InitFromCommandLine(),
332*6777b538SAndroid Build Coastguard Worker   // RegisterFieldTrialOverride(), etc. matters. The first call wins out,
333*6777b538SAndroid Build Coastguard Worker   // because the |overrides_| map uses insert(), which retains the first
334*6777b538SAndroid Build Coastguard Worker   // inserted entry and does not overwrite it on subsequent calls to insert().
335*6777b538SAndroid Build Coastguard Worker   void RegisterExtraFeatureOverrides(
336*6777b538SAndroid Build Coastguard Worker       const std::vector<FeatureOverrideInfo>& extra_overrides);
337*6777b538SAndroid Build Coastguard Worker 
338*6777b538SAndroid Build Coastguard Worker   // Loops through feature overrides and serializes them all into |allocator|.
339*6777b538SAndroid Build Coastguard Worker   void AddFeaturesToAllocator(PersistentMemoryAllocator* allocator);
340*6777b538SAndroid Build Coastguard Worker 
341*6777b538SAndroid Build Coastguard Worker   // Returns comma-separated lists of feature names (in the same format that is
342*6777b538SAndroid Build Coastguard Worker   // accepted by InitFromCommandLine()) corresponding to features that
343*6777b538SAndroid Build Coastguard Worker   // have been overridden - either through command-line or via FieldTrials. For
344*6777b538SAndroid Build Coastguard Worker   // those features that have an associated FieldTrial, the output entry will be
345*6777b538SAndroid Build Coastguard Worker   // of the format "FeatureName<TrialName" (|include_group_name|=false) or
346*6777b538SAndroid Build Coastguard Worker   // "FeatureName<TrialName.GroupName" (if |include_group_name|=true), where
347*6777b538SAndroid Build Coastguard Worker   // "TrialName" is the name of the FieldTrial and "GroupName" is the group
348*6777b538SAndroid Build Coastguard Worker   // name of the FieldTrial. Features that have overrides with
349*6777b538SAndroid Build Coastguard Worker   // OVERRIDE_USE_DEFAULT will be added to |enable_overrides| with a '*'
350*6777b538SAndroid Build Coastguard Worker   // character prefix. Must be called only after the instance has been
351*6777b538SAndroid Build Coastguard Worker   // initialized and registered.
352*6777b538SAndroid Build Coastguard Worker   void GetFeatureOverrides(std::string* enable_overrides,
353*6777b538SAndroid Build Coastguard Worker                            std::string* disable_overrides,
354*6777b538SAndroid Build Coastguard Worker                            bool include_group_names = false) const;
355*6777b538SAndroid Build Coastguard Worker 
356*6777b538SAndroid Build Coastguard Worker   // Like GetFeatureOverrides(), but only returns overrides that were specified
357*6777b538SAndroid Build Coastguard Worker   // explicitly on the command-line, omitting the ones from field trials.
358*6777b538SAndroid Build Coastguard Worker   void GetCommandLineFeatureOverrides(std::string* enable_overrides,
359*6777b538SAndroid Build Coastguard Worker                                       std::string* disable_overrides) const;
360*6777b538SAndroid Build Coastguard Worker 
361*6777b538SAndroid Build Coastguard Worker   // Returns the field trial associated with the given feature |name|. Used for
362*6777b538SAndroid Build Coastguard Worker   // getting the FieldTrial without requiring a struct Feature.
363*6777b538SAndroid Build Coastguard Worker   base::FieldTrial* GetAssociatedFieldTrialByFeatureName(
364*6777b538SAndroid Build Coastguard Worker       std::string_view name) const;
365*6777b538SAndroid Build Coastguard Worker 
366*6777b538SAndroid Build Coastguard Worker   // DO NOT USE outside of internal field trial implementation code. Instead use
367*6777b538SAndroid Build Coastguard Worker   // GetAssociatedFieldTrialByFeatureName(), which performs some additional
368*6777b538SAndroid Build Coastguard Worker   // validation.
369*6777b538SAndroid Build Coastguard Worker   //
370*6777b538SAndroid Build Coastguard Worker   // Returns whether the given feature |name| is associated with a field trial.
371*6777b538SAndroid Build Coastguard Worker   // If the given feature |name| does not exist, return false. Unlike
372*6777b538SAndroid Build Coastguard Worker   // GetAssociatedFieldTrialByFeatureName(), this function must be called during
373*6777b538SAndroid Build Coastguard Worker   // |FeatureList| initialization; the returned value will report whether the
374*6777b538SAndroid Build Coastguard Worker   // provided |name| has been used so far.
375*6777b538SAndroid Build Coastguard Worker   bool HasAssociatedFieldTrialByFeatureName(std::string_view name) const;
376*6777b538SAndroid Build Coastguard Worker 
377*6777b538SAndroid Build Coastguard Worker   // Get associated field trial for the given feature |name| only if override
378*6777b538SAndroid Build Coastguard Worker   // enables it.
379*6777b538SAndroid Build Coastguard Worker   FieldTrial* GetEnabledFieldTrialByFeatureName(std::string_view name) const;
380*6777b538SAndroid Build Coastguard Worker 
381*6777b538SAndroid Build Coastguard Worker   // Construct an accessor allowing access to GetOverrideStateByFeatureName().
382*6777b538SAndroid Build Coastguard Worker   // This can only be called before the FeatureList is initialized, and is
383*6777b538SAndroid Build Coastguard Worker   // intended for very narrow use.
384*6777b538SAndroid Build Coastguard Worker   // If you're tempted to use it, do so only in consultation with feature_list
385*6777b538SAndroid Build Coastguard Worker   // OWNERS.
386*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<Accessor> ConstructAccessor();
387*6777b538SAndroid Build Coastguard Worker 
388*6777b538SAndroid Build Coastguard Worker   // Returns whether the given `feature` is enabled.
389*6777b538SAndroid Build Coastguard Worker   //
390*6777b538SAndroid Build Coastguard Worker   // If no `FeatureList` instance is registered, this will:
391*6777b538SAndroid Build Coastguard Worker   // - DCHECK(), if FailOnFeatureAccessWithoutFeatureList() was called.
392*6777b538SAndroid Build Coastguard Worker   //     TODO(crbug.com/1358639): Change the DCHECK to a CHECK when we're
393*6777b538SAndroid Build Coastguard Worker   //     confident that all early accesses have been fixed. We don't want to
394*6777b538SAndroid Build Coastguard Worker   //     get many crash reports from the field in the meantime.
395*6777b538SAndroid Build Coastguard Worker   // - Return the default state, otherwise. Registering a `FeatureList` later
396*6777b538SAndroid Build Coastguard Worker   //   will fail.
397*6777b538SAndroid Build Coastguard Worker   //
398*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/1358639): Make early FeatureList access fail on iOS, Android
399*6777b538SAndroid Build Coastguard Worker   // and ChromeOS. This currently only works on Windows, Mac and Linux.
400*6777b538SAndroid Build Coastguard Worker   //
401*6777b538SAndroid Build Coastguard Worker   // A feature with a given name must only have a single corresponding Feature
402*6777b538SAndroid Build Coastguard Worker   // instance, which is checked in builds with DCHECKs enabled.
403*6777b538SAndroid Build Coastguard Worker   static bool IsEnabled(const Feature& feature);
404*6777b538SAndroid Build Coastguard Worker 
405*6777b538SAndroid Build Coastguard Worker   // Some characters are not allowed to appear in feature names or the
406*6777b538SAndroid Build Coastguard Worker   // associated field trial names, as they are used as special characters for
407*6777b538SAndroid Build Coastguard Worker   // command-line serialization. This function checks that the strings are ASCII
408*6777b538SAndroid Build Coastguard Worker   // (since they are used in command-line API functions that require ASCII) and
409*6777b538SAndroid Build Coastguard Worker   // whether there are any reserved characters present, returning true if the
410*6777b538SAndroid Build Coastguard Worker   // string is valid.
411*6777b538SAndroid Build Coastguard Worker   static bool IsValidFeatureOrFieldTrialName(std::string_view name);
412*6777b538SAndroid Build Coastguard Worker 
413*6777b538SAndroid Build Coastguard Worker   // If the given |feature| is overridden, returns its enabled state; otherwise,
414*6777b538SAndroid Build Coastguard Worker   // returns an empty optional. Must only be called after the singleton instance
415*6777b538SAndroid Build Coastguard Worker   // has been registered via SetInstance(). Additionally, a feature with a given
416*6777b538SAndroid Build Coastguard Worker   // name must only have a single corresponding Feature struct, which is checked
417*6777b538SAndroid Build Coastguard Worker   // in builds with DCHECKs enabled.
418*6777b538SAndroid Build Coastguard Worker   static std::optional<bool> GetStateIfOverridden(const Feature& feature);
419*6777b538SAndroid Build Coastguard Worker 
420*6777b538SAndroid Build Coastguard Worker   // Returns the field trial associated with the given |feature|. Must only be
421*6777b538SAndroid Build Coastguard Worker   // called after the singleton instance has been registered via SetInstance().
422*6777b538SAndroid Build Coastguard Worker   static FieldTrial* GetFieldTrial(const Feature& feature);
423*6777b538SAndroid Build Coastguard Worker 
424*6777b538SAndroid Build Coastguard Worker   // Splits a comma-separated string containing feature names into a vector. The
425*6777b538SAndroid Build Coastguard Worker   // resulting pieces point to parts of |input|.
426*6777b538SAndroid Build Coastguard Worker   static std::vector<std::string_view> SplitFeatureListString(
427*6777b538SAndroid Build Coastguard Worker       std::string_view input);
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker   // Checks and parses the |enable_feature| (e.g.
430*6777b538SAndroid Build Coastguard Worker   // FeatureName<Study.Group:Param1/value1/) obtained by applying
431*6777b538SAndroid Build Coastguard Worker   // SplitFeatureListString() to the |enable_features| flag, and sets
432*6777b538SAndroid Build Coastguard Worker   // |feature_name| to be the feature's name, |study_name| and |group_name| to
433*6777b538SAndroid Build Coastguard Worker   // be the field trial name and its group name if the field trial is specified
434*6777b538SAndroid Build Coastguard Worker   // or field trial parameters are given, |params| to be the field trial
435*6777b538SAndroid Build Coastguard Worker   // parameters if exists.
436*6777b538SAndroid Build Coastguard Worker   static bool ParseEnableFeatureString(std::string_view enable_feature,
437*6777b538SAndroid Build Coastguard Worker                                        std::string* feature_name,
438*6777b538SAndroid Build Coastguard Worker                                        std::string* study_name,
439*6777b538SAndroid Build Coastguard Worker                                        std::string* group_name,
440*6777b538SAndroid Build Coastguard Worker                                        std::string* params);
441*6777b538SAndroid Build Coastguard Worker 
442*6777b538SAndroid Build Coastguard Worker   // Initializes and sets an instance of FeatureList with feature overrides via
443*6777b538SAndroid Build Coastguard Worker   // command-line flags |enable_features| and |disable_features| if one has not
444*6777b538SAndroid Build Coastguard Worker   // already been set from command-line flags. Returns true if an instance did
445*6777b538SAndroid Build Coastguard Worker   // not previously exist. See InitFromCommandLine() for more details
446*6777b538SAndroid Build Coastguard Worker   // about |enable_features| and |disable_features| parameters.
447*6777b538SAndroid Build Coastguard Worker   static bool InitInstance(const std::string& enable_features,
448*6777b538SAndroid Build Coastguard Worker                            const std::string& disable_features);
449*6777b538SAndroid Build Coastguard Worker 
450*6777b538SAndroid Build Coastguard Worker   // Like the above, but also adds extra overrides. If a feature appears in
451*6777b538SAndroid Build Coastguard Worker   // |extra_overrides| and also |enable_features| or |disable_features|, the
452*6777b538SAndroid Build Coastguard Worker   // disable/enable will supersede the extra overrides.
453*6777b538SAndroid Build Coastguard Worker   static bool InitInstance(
454*6777b538SAndroid Build Coastguard Worker       const std::string& enable_features,
455*6777b538SAndroid Build Coastguard Worker       const std::string& disable_features,
456*6777b538SAndroid Build Coastguard Worker       const std::vector<FeatureOverrideInfo>& extra_overrides);
457*6777b538SAndroid Build Coastguard Worker 
458*6777b538SAndroid Build Coastguard Worker   // Returns the singleton instance of FeatureList. Will return null until an
459*6777b538SAndroid Build Coastguard Worker   // instance is registered via SetInstance().
460*6777b538SAndroid Build Coastguard Worker   static FeatureList* GetInstance();
461*6777b538SAndroid Build Coastguard Worker 
462*6777b538SAndroid Build Coastguard Worker   // Registers the given |instance| to be the singleton feature list for this
463*6777b538SAndroid Build Coastguard Worker   // process. This should only be called once and |instance| must not be null.
464*6777b538SAndroid Build Coastguard Worker   // Note: If you are considering using this for the purposes of testing, take
465*6777b538SAndroid Build Coastguard Worker   // a look at using base/test/scoped_feature_list.h instead.
466*6777b538SAndroid Build Coastguard Worker   static void SetInstance(std::unique_ptr<FeatureList> instance);
467*6777b538SAndroid Build Coastguard Worker 
468*6777b538SAndroid Build Coastguard Worker   // Registers the given `instance` to be the temporary singleton feature list
469*6777b538SAndroid Build Coastguard Worker   // for this process. While the given `instance` is the singleton feature list,
470*6777b538SAndroid Build Coastguard Worker   // only the state of features matching `allowed_feature_names` can be checked.
471*6777b538SAndroid Build Coastguard Worker   // Attempting to query other feature will behave as if no feature list was set
472*6777b538SAndroid Build Coastguard Worker   // at all. It is expected that this instance is replaced using `SetInstance`
473*6777b538SAndroid Build Coastguard Worker   // with an instance without limitations as soon as practical.
474*6777b538SAndroid Build Coastguard Worker   static void SetEarlyAccessInstance(
475*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<FeatureList> instance,
476*6777b538SAndroid Build Coastguard Worker       base::flat_set<std::string> allowed_feature_names);
477*6777b538SAndroid Build Coastguard Worker 
478*6777b538SAndroid Build Coastguard Worker   // Clears the previously-registered singleton instance for tests and returns
479*6777b538SAndroid Build Coastguard Worker   // the old instance.
480*6777b538SAndroid Build Coastguard Worker   // Note: Most tests should never call this directly. Instead consider using
481*6777b538SAndroid Build Coastguard Worker   // base::test::ScopedFeatureList.
482*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<FeatureList> ClearInstanceForTesting();
483*6777b538SAndroid Build Coastguard Worker 
484*6777b538SAndroid Build Coastguard Worker   // Sets a given (initialized) |instance| to be the singleton feature list,
485*6777b538SAndroid Build Coastguard Worker   // for testing. Existing instance must be null. This is primarily intended
486*6777b538SAndroid Build Coastguard Worker   // to support base::test::ScopedFeatureList helper class.
487*6777b538SAndroid Build Coastguard Worker   static void RestoreInstanceForTesting(std::unique_ptr<FeatureList> instance);
488*6777b538SAndroid Build Coastguard Worker 
489*6777b538SAndroid Build Coastguard Worker   // After calling this, an attempt to access feature state when no FeatureList
490*6777b538SAndroid Build Coastguard Worker   // is registered will DCHECK.
491*6777b538SAndroid Build Coastguard Worker   //
492*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/1358639): Change the DCHECK to a CHECK when we're confident
493*6777b538SAndroid Build Coastguard Worker   // that all early accesses have been fixed. We don't want to get many crash
494*6777b538SAndroid Build Coastguard Worker   // reports from the field in the meantime.
495*6777b538SAndroid Build Coastguard Worker   //
496*6777b538SAndroid Build Coastguard Worker   // Note: This isn't the default behavior because accesses are tolerated in
497*6777b538SAndroid Build Coastguard Worker   // processes that never register a FeatureList.
498*6777b538SAndroid Build Coastguard Worker   static void FailOnFeatureAccessWithoutFeatureList();
499*6777b538SAndroid Build Coastguard Worker 
500*6777b538SAndroid Build Coastguard Worker   // Returns the first feature that was accessed before a FeatureList was
501*6777b538SAndroid Build Coastguard Worker   // registered that allows accessing the feature.
502*6777b538SAndroid Build Coastguard Worker   static const Feature* GetEarlyAccessedFeatureForTesting();
503*6777b538SAndroid Build Coastguard Worker 
504*6777b538SAndroid Build Coastguard Worker   // Resets the state of the early feature access tracker.
505*6777b538SAndroid Build Coastguard Worker   static void ResetEarlyFeatureAccessTrackerForTesting();
506*6777b538SAndroid Build Coastguard Worker 
507*6777b538SAndroid Build Coastguard Worker   // Adds a feature to the early allowed feature access list for tests. Should
508*6777b538SAndroid Build Coastguard Worker   // only be called on a FeatureList that was set with SetEarlyAccessInstance().
509*6777b538SAndroid Build Coastguard Worker   void AddEarlyAllowedFeatureForTesting(std::string feature_name);
510*6777b538SAndroid Build Coastguard Worker 
511*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS_ASH)
512*6777b538SAndroid Build Coastguard Worker   // Allows a visitor to record override state, parameters, and field trial
513*6777b538SAndroid Build Coastguard Worker   // associated with each feature.
514*6777b538SAndroid Build Coastguard Worker   //
515*6777b538SAndroid Build Coastguard Worker   // NOTE: This is intended only for the special case of needing to get all
516*6777b538SAndroid Build Coastguard Worker   // overrides. This use case is specific to CrOS-Ash. Most users should call
517*6777b538SAndroid Build Coastguard Worker   // IsEnabled() to query a feature's state.
518*6777b538SAndroid Build Coastguard Worker   static void VisitFeaturesAndParams(FeatureVisitor& visitor);
519*6777b538SAndroid Build Coastguard Worker #endif  // BULDFLAG(IS_CHROMEOS_ASH)
520*6777b538SAndroid Build Coastguard Worker 
521*6777b538SAndroid Build Coastguard Worker  private:
522*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FeatureListTest, CheckFeatureIdentity);
523*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FeatureListTest,
524*6777b538SAndroid Build Coastguard Worker                            StoreAndRetrieveFeaturesFromSharedMemory);
525*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(FeatureListTest,
526*6777b538SAndroid Build Coastguard Worker                            StoreAndRetrieveAssociatedFeaturesFromSharedMemory);
527*6777b538SAndroid Build Coastguard Worker   // Allow Accessor to access GetOverrideStateByFeatureName().
528*6777b538SAndroid Build Coastguard Worker   friend class Accessor;
529*6777b538SAndroid Build Coastguard Worker 
530*6777b538SAndroid Build Coastguard Worker   struct OverrideEntry {
531*6777b538SAndroid Build Coastguard Worker     // The overridden enable (on/off) state of the feature.
532*6777b538SAndroid Build Coastguard Worker     OverrideState overridden_state;
533*6777b538SAndroid Build Coastguard Worker 
534*6777b538SAndroid Build Coastguard Worker     // An optional associated field trial, which will be activated when the
535*6777b538SAndroid Build Coastguard Worker     // state of the feature is queried for the first time. Weak pointer to the
536*6777b538SAndroid Build Coastguard Worker     // FieldTrial object that is owned by the FieldTrialList singleton.
537*6777b538SAndroid Build Coastguard Worker     raw_ptr<base::FieldTrial> field_trial;
538*6777b538SAndroid Build Coastguard Worker 
539*6777b538SAndroid Build Coastguard Worker     // Specifies whether the feature's state is overridden by |field_trial|.
540*6777b538SAndroid Build Coastguard Worker     // If it's not, and |field_trial| is not null, it means it is simply an
541*6777b538SAndroid Build Coastguard Worker     // associated field trial for reporting purposes (and |overridden_state|
542*6777b538SAndroid Build Coastguard Worker     // came from the command-line).
543*6777b538SAndroid Build Coastguard Worker     bool overridden_by_field_trial;
544*6777b538SAndroid Build Coastguard Worker 
545*6777b538SAndroid Build Coastguard Worker     // TODO(asvitkine): Expand this as more support is added.
546*6777b538SAndroid Build Coastguard Worker 
547*6777b538SAndroid Build Coastguard Worker     // Constructs an OverrideEntry for the given |overridden_state|. If
548*6777b538SAndroid Build Coastguard Worker     // |field_trial| is not null, it implies that |overridden_state| comes from
549*6777b538SAndroid Build Coastguard Worker     // the trial, so |overridden_by_field_trial| will be set to true.
550*6777b538SAndroid Build Coastguard Worker     OverrideEntry(OverrideState overridden_state, FieldTrial* field_trial);
551*6777b538SAndroid Build Coastguard Worker   };
552*6777b538SAndroid Build Coastguard Worker 
553*6777b538SAndroid Build Coastguard Worker   // Returns the override for the field trial associated with the given feature
554*6777b538SAndroid Build Coastguard Worker   // |name| or null if the feature is not found.
555*6777b538SAndroid Build Coastguard Worker   const base::FeatureList::OverrideEntry* GetOverrideEntryByFeatureName(
556*6777b538SAndroid Build Coastguard Worker       std::string_view name) const;
557*6777b538SAndroid Build Coastguard Worker 
558*6777b538SAndroid Build Coastguard Worker   // Finalizes the initialization state of the FeatureList, so that no further
559*6777b538SAndroid Build Coastguard Worker   // overrides can be registered. This is called by SetInstance() on the
560*6777b538SAndroid Build Coastguard Worker   // singleton feature list that is being registered.
561*6777b538SAndroid Build Coastguard Worker   void FinalizeInitialization();
562*6777b538SAndroid Build Coastguard Worker 
563*6777b538SAndroid Build Coastguard Worker   // Returns whether the given |feature| is enabled. This is invoked by the
564*6777b538SAndroid Build Coastguard Worker   // public FeatureList::IsEnabled() static function on the global singleton.
565*6777b538SAndroid Build Coastguard Worker   // Requires the FeatureList to have already been fully initialized.
566*6777b538SAndroid Build Coastguard Worker   bool IsFeatureEnabled(const Feature& feature) const;
567*6777b538SAndroid Build Coastguard Worker 
568*6777b538SAndroid Build Coastguard Worker   // Returns whether the given |feature| is enabled. This is invoked by the
569*6777b538SAndroid Build Coastguard Worker   // public FeatureList::GetStateIfOverridden() static function on the global
570*6777b538SAndroid Build Coastguard Worker   // singleton. Requires the FeatureList to have already been fully initialized.
571*6777b538SAndroid Build Coastguard Worker   std::optional<bool> IsFeatureEnabledIfOverridden(
572*6777b538SAndroid Build Coastguard Worker       const Feature& feature) const;
573*6777b538SAndroid Build Coastguard Worker 
574*6777b538SAndroid Build Coastguard Worker   // Returns the override state of a given |feature|. If the feature was not
575*6777b538SAndroid Build Coastguard Worker   // overridden, returns OVERRIDE_USE_DEFAULT. Performs any necessary callbacks
576*6777b538SAndroid Build Coastguard Worker   // for when the feature state has been observed, e.g. activating field trials.
577*6777b538SAndroid Build Coastguard Worker   OverrideState GetOverrideState(const Feature& feature) const;
578*6777b538SAndroid Build Coastguard Worker 
579*6777b538SAndroid Build Coastguard Worker   // Same as GetOverrideState(), but without a default value.
580*6777b538SAndroid Build Coastguard Worker   OverrideState GetOverrideStateByFeatureName(
581*6777b538SAndroid Build Coastguard Worker       std::string_view feature_name) const;
582*6777b538SAndroid Build Coastguard Worker 
583*6777b538SAndroid Build Coastguard Worker   // Returns the field trial associated with the given |feature|. This is
584*6777b538SAndroid Build Coastguard Worker   // invoked by the public FeatureList::GetFieldTrial() static function on the
585*6777b538SAndroid Build Coastguard Worker   // global singleton. Requires the FeatureList to have already been fully
586*6777b538SAndroid Build Coastguard Worker   // initialized.
587*6777b538SAndroid Build Coastguard Worker   base::FieldTrial* GetAssociatedFieldTrial(const Feature& feature) const;
588*6777b538SAndroid Build Coastguard Worker 
589*6777b538SAndroid Build Coastguard Worker   // For each feature name in comma-separated list of strings |feature_list|,
590*6777b538SAndroid Build Coastguard Worker   // registers an override with the specified |overridden_state|. Also, will
591*6777b538SAndroid Build Coastguard Worker   // associate an optional named field trial if the entry is of the format
592*6777b538SAndroid Build Coastguard Worker   // "FeatureName<TrialName".
593*6777b538SAndroid Build Coastguard Worker   void RegisterOverridesFromCommandLine(const std::string& feature_list,
594*6777b538SAndroid Build Coastguard Worker                                         OverrideState overridden_state);
595*6777b538SAndroid Build Coastguard Worker 
596*6777b538SAndroid Build Coastguard Worker   // Registers an override for feature |feature_name|. The override specifies
597*6777b538SAndroid Build Coastguard Worker   // whether the feature should be on or off (via |overridden_state|), which
598*6777b538SAndroid Build Coastguard Worker   // will take precedence over the feature's default state. If |field_trial| is
599*6777b538SAndroid Build Coastguard Worker   // not null, registers the specified field trial object to be associated with
600*6777b538SAndroid Build Coastguard Worker   // the feature, which will activate the field trial when the feature state is
601*6777b538SAndroid Build Coastguard Worker   // queried. If an override is already registered for the given feature, it
602*6777b538SAndroid Build Coastguard Worker   // will not be changed.
603*6777b538SAndroid Build Coastguard Worker   void RegisterOverride(std::string_view feature_name,
604*6777b538SAndroid Build Coastguard Worker                         OverrideState overridden_state,
605*6777b538SAndroid Build Coastguard Worker                         FieldTrial* field_trial);
606*6777b538SAndroid Build Coastguard Worker 
607*6777b538SAndroid Build Coastguard Worker   // Implementation of GetFeatureOverrides() with a parameter that specifies
608*6777b538SAndroid Build Coastguard Worker   // whether only command-line enabled overrides should be emitted. See that
609*6777b538SAndroid Build Coastguard Worker   // function's comments for more details.
610*6777b538SAndroid Build Coastguard Worker   void GetFeatureOverridesImpl(std::string* enable_overrides,
611*6777b538SAndroid Build Coastguard Worker                                std::string* disable_overrides,
612*6777b538SAndroid Build Coastguard Worker                                bool command_line_only,
613*6777b538SAndroid Build Coastguard Worker                                bool include_group_name = false) const;
614*6777b538SAndroid Build Coastguard Worker 
615*6777b538SAndroid Build Coastguard Worker   // Verifies that there's only a single definition of a Feature struct for a
616*6777b538SAndroid Build Coastguard Worker   // given feature name. Keeps track of the first seen Feature struct for each
617*6777b538SAndroid Build Coastguard Worker   // feature. Returns false when called on a Feature struct with a different
618*6777b538SAndroid Build Coastguard Worker   // address than the first one it saw for that feature name. Used only from
619*6777b538SAndroid Build Coastguard Worker   // DCHECKs and tests. This is const because it's called from const getters and
620*6777b538SAndroid Build Coastguard Worker   // doesn't modify externally visible state.
621*6777b538SAndroid Build Coastguard Worker   bool CheckFeatureIdentity(const Feature& feature) const;
622*6777b538SAndroid Build Coastguard Worker 
623*6777b538SAndroid Build Coastguard Worker   // Returns true if this feature list was set with SetEarlyAccessInstance().
624*6777b538SAndroid Build Coastguard Worker   bool IsEarlyAccessInstance() const;
625*6777b538SAndroid Build Coastguard Worker 
626*6777b538SAndroid Build Coastguard Worker   // Returns if this feature list instance allows access to the given feature.
627*6777b538SAndroid Build Coastguard Worker   // If a this feature list was set with SetEarlyAccessInstance(), only the
628*6777b538SAndroid Build Coastguard Worker   // features in `allowed_feature_names_` can be checked.
629*6777b538SAndroid Build Coastguard Worker   bool AllowFeatureAccess(const Feature& feature) const;
630*6777b538SAndroid Build Coastguard Worker 
631*6777b538SAndroid Build Coastguard Worker   // Map from feature name to an OverrideEntry struct for the feature, if it
632*6777b538SAndroid Build Coastguard Worker   // exists.
633*6777b538SAndroid Build Coastguard Worker   base::flat_map<std::string, OverrideEntry> overrides_;
634*6777b538SAndroid Build Coastguard Worker 
635*6777b538SAndroid Build Coastguard Worker   // Locked map that keeps track of seen features, to ensure a single feature is
636*6777b538SAndroid Build Coastguard Worker   // only defined once. This verification is only done in builds with DCHECKs
637*6777b538SAndroid Build Coastguard Worker   // enabled. This is mutable as it's not externally visible and needs to be
638*6777b538SAndroid Build Coastguard Worker   // usable from const getters.
639*6777b538SAndroid Build Coastguard Worker   mutable Lock feature_identity_tracker_lock_;
640*6777b538SAndroid Build Coastguard Worker   mutable std::map<std::string, const Feature*> feature_identity_tracker_
641*6777b538SAndroid Build Coastguard Worker       GUARDED_BY(feature_identity_tracker_lock_);
642*6777b538SAndroid Build Coastguard Worker 
643*6777b538SAndroid Build Coastguard Worker   // Tracks the associated FieldTrialList for DCHECKs. This is used to catch
644*6777b538SAndroid Build Coastguard Worker   // the scenario where multiple FieldTrialList are used with the same
645*6777b538SAndroid Build Coastguard Worker   // FeatureList - which can lead to overrides pointing to invalid FieldTrial
646*6777b538SAndroid Build Coastguard Worker   // objects.
647*6777b538SAndroid Build Coastguard Worker   raw_ptr<base::FieldTrialList> field_trial_list_ = nullptr;
648*6777b538SAndroid Build Coastguard Worker 
649*6777b538SAndroid Build Coastguard Worker   // Whether this object has been fully initialized. This gets set to true as a
650*6777b538SAndroid Build Coastguard Worker   // result of FinalizeInitialization().
651*6777b538SAndroid Build Coastguard Worker   bool initialized_ = false;
652*6777b538SAndroid Build Coastguard Worker 
653*6777b538SAndroid Build Coastguard Worker   // Whether this object has been initialized from command line.
654*6777b538SAndroid Build Coastguard Worker   bool initialized_from_command_line_ = false;
655*6777b538SAndroid Build Coastguard Worker 
656*6777b538SAndroid Build Coastguard Worker   // Used when querying `base::Feature` state to determine if the cached value
657*6777b538SAndroid Build Coastguard Worker   // in the `Feature` object is populated and valid. See the comment on
658*6777b538SAndroid Build Coastguard Worker   // `base::Feature::cached_value` for more details.
659*6777b538SAndroid Build Coastguard Worker   const uint16_t caching_context_;
660*6777b538SAndroid Build Coastguard Worker 
661*6777b538SAndroid Build Coastguard Worker   // If this instance was set with SetEarlyAccessInstance(), this set contains
662*6777b538SAndroid Build Coastguard Worker   // the names of the features whose state is allowed to be checked. Attempting
663*6777b538SAndroid Build Coastguard Worker   // to check the state of a feature not on this list will behave as if no
664*6777b538SAndroid Build Coastguard Worker   // feature list was initialized at all.
665*6777b538SAndroid Build Coastguard Worker   base::flat_set<std::string> allowed_feature_names_;
666*6777b538SAndroid Build Coastguard Worker };
667*6777b538SAndroid Build Coastguard Worker 
668*6777b538SAndroid Build Coastguard Worker }  // namespace base
669*6777b538SAndroid Build Coastguard Worker 
670*6777b538SAndroid Build Coastguard Worker #endif  // BASE_FEATURE_LIST_H_
671