xref: /aosp_15_r20/external/cronet/base/metrics/field_trial_params.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 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_METRICS_FIELD_TRIAL_PARAMS_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_METRICS_FIELD_TRIAL_PARAMS_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <map>
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker // Key-value mapping type for field trial parameters.
21*6777b538SAndroid Build Coastguard Worker typedef std::map<std::string, std::string> FieldTrialParams;
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker // Param string decoding function for AssociateFieldTrialParamsFromString().
24*6777b538SAndroid Build Coastguard Worker typedef std::string (*FieldTrialParamsDecodeStringFunc)(const std::string& str);
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // Unescapes special characters from the given string. Used in
27*6777b538SAndroid Build Coastguard Worker // AssociateFieldTrialParamsFromString() as one of the feature params decoding
28*6777b538SAndroid Build Coastguard Worker // functions.
29*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::string UnescapeValue(const std::string& value);
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker // Associates the specified set of key-value |params| with the field trial
32*6777b538SAndroid Build Coastguard Worker // specified by |trial_name| and |group_name|. Fails and returns false if the
33*6777b538SAndroid Build Coastguard Worker // specified field trial already has params associated with it or the trial
34*6777b538SAndroid Build Coastguard Worker // is already active (group() has been called on it). Thread safe.
35*6777b538SAndroid Build Coastguard Worker BASE_EXPORT bool AssociateFieldTrialParams(const std::string& trial_name,
36*6777b538SAndroid Build Coastguard Worker                                            const std::string& group_name,
37*6777b538SAndroid Build Coastguard Worker                                            const FieldTrialParams& params);
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker // Provides a mechanism to associate multiple set of params to multiple groups
40*6777b538SAndroid Build Coastguard Worker // with a formatted string as returned by FieldTrialList::AllParamsToString().
41*6777b538SAndroid Build Coastguard Worker // |decode_data_func| allows specifying a custom decoding function.
42*6777b538SAndroid Build Coastguard Worker BASE_EXPORT bool AssociateFieldTrialParamsFromString(
43*6777b538SAndroid Build Coastguard Worker     const std::string& params_string,
44*6777b538SAndroid Build Coastguard Worker     FieldTrialParamsDecodeStringFunc decode_data_func);
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker // Retrieves the set of key-value |params| for the specified field trial, based
47*6777b538SAndroid Build Coastguard Worker // on its selected group. If the field trial does not exist or its selected
48*6777b538SAndroid Build Coastguard Worker // group does not have any parameters associated with it, returns false and
49*6777b538SAndroid Build Coastguard Worker // does not modify |params|. Calling this function will result in the field
50*6777b538SAndroid Build Coastguard Worker // trial being marked as active if found (i.e. group() will be called on it),
51*6777b538SAndroid Build Coastguard Worker // if it wasn't already. Thread safe.
52*6777b538SAndroid Build Coastguard Worker BASE_EXPORT bool GetFieldTrialParams(const std::string& trial_name,
53*6777b538SAndroid Build Coastguard Worker                                      FieldTrialParams* params);
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker // Retrieves the set of key-value |params| for the field trial associated with
56*6777b538SAndroid Build Coastguard Worker // the specified |feature|. A feature is associated with at most one field
57*6777b538SAndroid Build Coastguard Worker // trial and selected group. See  base/feature_list.h for more information on
58*6777b538SAndroid Build Coastguard Worker // features. If the feature is not enabled, or if there's no associated params,
59*6777b538SAndroid Build Coastguard Worker // returns false and does not modify |params|. Calling this function will
60*6777b538SAndroid Build Coastguard Worker // result in the associated field trial being marked as active if found (i.e.
61*6777b538SAndroid Build Coastguard Worker // group() will be called on it), if it wasn't already. Thread safe.
62*6777b538SAndroid Build Coastguard Worker BASE_EXPORT bool GetFieldTrialParamsByFeature(const base::Feature& feature,
63*6777b538SAndroid Build Coastguard Worker                                               FieldTrialParams* params);
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker // Retrieves a specific parameter value corresponding to |param_name| for the
66*6777b538SAndroid Build Coastguard Worker // specified field trial, based on its selected group. If the field trial does
67*6777b538SAndroid Build Coastguard Worker // not exist or the specified parameter does not exist, returns an empty
68*6777b538SAndroid Build Coastguard Worker // string. Calling this function will result in the field trial being marked as
69*6777b538SAndroid Build Coastguard Worker // active if found (i.e. group() will be called on it), if it wasn't already.
70*6777b538SAndroid Build Coastguard Worker // Thread safe.
71*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::string GetFieldTrialParamValue(const std::string& trial_name,
72*6777b538SAndroid Build Coastguard Worker                                                 const std::string& param_name);
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker // Retrieves a specific parameter value corresponding to |param_name| for the
75*6777b538SAndroid Build Coastguard Worker // field trial associated with the specified |feature|. A feature is associated
76*6777b538SAndroid Build Coastguard Worker // with at most one field trial and selected group. See base/feature_list.h for
77*6777b538SAndroid Build Coastguard Worker // more information on features. If the feature is not enabled, or the
78*6777b538SAndroid Build Coastguard Worker // specified parameter does not exist, returns an empty string. Calling this
79*6777b538SAndroid Build Coastguard Worker // function will result in the associated field trial being marked as active if
80*6777b538SAndroid Build Coastguard Worker // found (i.e. group() will be called on it), if it wasn't already. Thread safe.
81*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::string GetFieldTrialParamValueByFeature(
82*6777b538SAndroid Build Coastguard Worker     const base::Feature& feature,
83*6777b538SAndroid Build Coastguard Worker     const std::string& param_name);
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
86*6777b538SAndroid Build Coastguard Worker // string value into an int using base::StringToInt() and returns it, if
87*6777b538SAndroid Build Coastguard Worker // successful. Otherwise, it returns |default_value|. If the string value is not
88*6777b538SAndroid Build Coastguard Worker // empty and the conversion does not succeed, it produces a warning to LOG.
89*6777b538SAndroid Build Coastguard Worker BASE_EXPORT int GetFieldTrialParamByFeatureAsInt(const base::Feature& feature,
90*6777b538SAndroid Build Coastguard Worker                                                  const std::string& param_name,
91*6777b538SAndroid Build Coastguard Worker                                                  int default_value);
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
94*6777b538SAndroid Build Coastguard Worker // string value into a double using base::StringToDouble() and returns it, if
95*6777b538SAndroid Build Coastguard Worker // successful. Otherwise, it returns |default_value|. If the string value is not
96*6777b538SAndroid Build Coastguard Worker // empty and the conversion does not succeed, it produces a warning to LOG.
97*6777b538SAndroid Build Coastguard Worker BASE_EXPORT double GetFieldTrialParamByFeatureAsDouble(
98*6777b538SAndroid Build Coastguard Worker     const base::Feature& feature,
99*6777b538SAndroid Build Coastguard Worker     const std::string& param_name,
100*6777b538SAndroid Build Coastguard Worker     double default_value);
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
103*6777b538SAndroid Build Coastguard Worker // string value into a boolean and returns it, if successful. Otherwise, it
104*6777b538SAndroid Build Coastguard Worker // returns |default_value|. The only string representations accepted here are
105*6777b538SAndroid Build Coastguard Worker // "true" and "false". If the string value is not empty and the conversion does
106*6777b538SAndroid Build Coastguard Worker // not succeed, it produces a warning to LOG.
107*6777b538SAndroid Build Coastguard Worker BASE_EXPORT bool GetFieldTrialParamByFeatureAsBool(
108*6777b538SAndroid Build Coastguard Worker     const base::Feature& feature,
109*6777b538SAndroid Build Coastguard Worker     const std::string& param_name,
110*6777b538SAndroid Build Coastguard Worker     bool default_value);
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
113*6777b538SAndroid Build Coastguard Worker // string value into a base::TimeDelta and returns it, if successful. Otherwise,
114*6777b538SAndroid Build Coastguard Worker // it returns `default_value`. If the string value is not empty and the
115*6777b538SAndroid Build Coastguard Worker // conversion does not succeed, it produces a warning to LOG.
116*6777b538SAndroid Build Coastguard Worker BASE_EXPORT base::TimeDelta GetFieldTrialParamByFeatureAsTimeDelta(
117*6777b538SAndroid Build Coastguard Worker     const Feature& feature,
118*6777b538SAndroid Build Coastguard Worker     const std::string& param_name,
119*6777b538SAndroid Build Coastguard Worker     base::TimeDelta default_value);
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker // Shared declaration for various FeatureParam<T> types.
122*6777b538SAndroid Build Coastguard Worker //
123*6777b538SAndroid Build Coastguard Worker // This template is defined for the following types T:
124*6777b538SAndroid Build Coastguard Worker //   bool
125*6777b538SAndroid Build Coastguard Worker //   int
126*6777b538SAndroid Build Coastguard Worker //   double
127*6777b538SAndroid Build Coastguard Worker //   std::string
128*6777b538SAndroid Build Coastguard Worker //   enum types
129*6777b538SAndroid Build Coastguard Worker //   base::TimeDelta
130*6777b538SAndroid Build Coastguard Worker //
131*6777b538SAndroid Build Coastguard Worker // See the individual definitions below for the appropriate interfaces.
132*6777b538SAndroid Build Coastguard Worker // Attempting to use it with any other type is a compile error.
133*6777b538SAndroid Build Coastguard Worker //
134*6777b538SAndroid Build Coastguard Worker // Getting a param value from a FeatureParam<T> will have the same semantics as
135*6777b538SAndroid Build Coastguard Worker // GetFieldTrialParamValueByFeature(), see that function's comments for details.
136*6777b538SAndroid Build Coastguard Worker template <typename T, bool IsEnum = std::is_enum_v<T>>
137*6777b538SAndroid Build Coastguard Worker struct FeatureParam {
138*6777b538SAndroid Build Coastguard Worker   // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T
139*6777b538SAndroid Build Coastguard Worker   // in its definition so that evaluation is deferred until the template is
140*6777b538SAndroid Build Coastguard Worker   // instantiated.
141*6777b538SAndroid Build Coastguard Worker   static_assert(!std::is_same_v<T, T>, "unsupported FeatureParam<> type");
142*6777b538SAndroid Build Coastguard Worker };
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker // Declares a string-valued parameter. Example:
145*6777b538SAndroid Build Coastguard Worker //
146*6777b538SAndroid Build Coastguard Worker //     constexpr FeatureParam<string> kAssistantName{
147*6777b538SAndroid Build Coastguard Worker //         &kAssistantFeature, "assistant_name", "HAL"};
148*6777b538SAndroid Build Coastguard Worker //
149*6777b538SAndroid Build Coastguard Worker // If the feature is not enabled, the parameter is not set, or set to the empty
150*6777b538SAndroid Build Coastguard Worker // string, then Get() will return the default value.
151*6777b538SAndroid Build Coastguard Worker template <>
152*6777b538SAndroid Build Coastguard Worker struct FeatureParam<std::string> {
153*6777b538SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
154*6777b538SAndroid Build Coastguard Worker                          const char* name,
155*6777b538SAndroid Build Coastguard Worker                          const char* default_value)
156*6777b538SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker   // Calling Get() will activate the field trial associated with |feature|. See
159*6777b538SAndroid Build Coastguard Worker   // GetFieldTrialParamValueByFeature() for more details.
160*6777b538SAndroid Build Coastguard Worker   BASE_EXPORT std::string Get() const;
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
163*6777b538SAndroid Build Coastguard Worker   // #global-scope, #constexpr-ctor-field-initializer
164*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const Feature* const feature;
165*6777b538SAndroid Build Coastguard Worker   const char* const name;
166*6777b538SAndroid Build Coastguard Worker   const char* const default_value;
167*6777b538SAndroid Build Coastguard Worker };
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker // Declares a double-valued parameter. Example:
170*6777b538SAndroid Build Coastguard Worker //
171*6777b538SAndroid Build Coastguard Worker //     constexpr FeatureParam<double> kAssistantTriggerThreshold{
172*6777b538SAndroid Build Coastguard Worker //         &kAssistantFeature, "trigger_threshold", 0.10};
173*6777b538SAndroid Build Coastguard Worker //
174*6777b538SAndroid Build Coastguard Worker // If the feature is not enabled, the parameter is not set, or set to an invalid
175*6777b538SAndroid Build Coastguard Worker // double value, then Get() will return the default value.
176*6777b538SAndroid Build Coastguard Worker template <>
177*6777b538SAndroid Build Coastguard Worker struct FeatureParam<double> {
178*6777b538SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
179*6777b538SAndroid Build Coastguard Worker                          const char* name,
180*6777b538SAndroid Build Coastguard Worker                          double default_value)
181*6777b538SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
182*6777b538SAndroid Build Coastguard Worker 
183*6777b538SAndroid Build Coastguard Worker   // Calling Get() will activate the field trial associated with |feature|. See
184*6777b538SAndroid Build Coastguard Worker   // GetFieldTrialParamValueByFeature() for more details.
185*6777b538SAndroid Build Coastguard Worker   BASE_EXPORT double Get() const;
186*6777b538SAndroid Build Coastguard Worker 
187*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
188*6777b538SAndroid Build Coastguard Worker   // #global-scope, #constexpr-ctor-field-initializer
189*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const Feature* const feature;
190*6777b538SAndroid Build Coastguard Worker   const char* const name;
191*6777b538SAndroid Build Coastguard Worker   const double default_value;
192*6777b538SAndroid Build Coastguard Worker };
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker // Declares an int-valued parameter. Example:
195*6777b538SAndroid Build Coastguard Worker //
196*6777b538SAndroid Build Coastguard Worker //     constexpr FeatureParam<int> kAssistantParallelism{
197*6777b538SAndroid Build Coastguard Worker //         &kAssistantFeature, "parallelism", 4};
198*6777b538SAndroid Build Coastguard Worker //
199*6777b538SAndroid Build Coastguard Worker // If the feature is not enabled, the parameter is not set, or set to an invalid
200*6777b538SAndroid Build Coastguard Worker // int value, then Get() will return the default value.
201*6777b538SAndroid Build Coastguard Worker template <>
202*6777b538SAndroid Build Coastguard Worker struct FeatureParam<int> {
203*6777b538SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
204*6777b538SAndroid Build Coastguard Worker                          const char* name,
205*6777b538SAndroid Build Coastguard Worker                          int default_value)
206*6777b538SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
207*6777b538SAndroid Build Coastguard Worker 
208*6777b538SAndroid Build Coastguard Worker   // Calling Get() will activate the field trial associated with |feature|. See
209*6777b538SAndroid Build Coastguard Worker   // GetFieldTrialParamValueByFeature() for more details.
210*6777b538SAndroid Build Coastguard Worker   BASE_EXPORT int Get() const;
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
213*6777b538SAndroid Build Coastguard Worker   // #global-scope, #constexpr-ctor-field-initializer
214*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const Feature* const feature;
215*6777b538SAndroid Build Coastguard Worker   const char* const name;
216*6777b538SAndroid Build Coastguard Worker   const int default_value;
217*6777b538SAndroid Build Coastguard Worker };
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker // Declares a bool-valued parameter. Example:
220*6777b538SAndroid Build Coastguard Worker //
221*6777b538SAndroid Build Coastguard Worker //     constexpr FeatureParam<int> kAssistantIsHelpful{
222*6777b538SAndroid Build Coastguard Worker //         &kAssistantFeature, "is_helpful", true};
223*6777b538SAndroid Build Coastguard Worker //
224*6777b538SAndroid Build Coastguard Worker // If the feature is not enabled, the parameter is not set, or set to value
225*6777b538SAndroid Build Coastguard Worker // other than "true" or "false", then Get() will return the default value.
226*6777b538SAndroid Build Coastguard Worker template <>
227*6777b538SAndroid Build Coastguard Worker struct FeatureParam<bool> {
228*6777b538SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
229*6777b538SAndroid Build Coastguard Worker                          const char* name,
230*6777b538SAndroid Build Coastguard Worker                          bool default_value)
231*6777b538SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
232*6777b538SAndroid Build Coastguard Worker 
233*6777b538SAndroid Build Coastguard Worker   // Calling Get() will activate the field trial associated with |feature|. See
234*6777b538SAndroid Build Coastguard Worker   // GetFieldTrialParamValueByFeature() for more details.
235*6777b538SAndroid Build Coastguard Worker   BASE_EXPORT bool Get() const;
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
238*6777b538SAndroid Build Coastguard Worker   // #global-scope, #constexpr-ctor-field-initializer
239*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const Feature* const feature;
240*6777b538SAndroid Build Coastguard Worker   const char* const name;
241*6777b538SAndroid Build Coastguard Worker   const bool default_value;
242*6777b538SAndroid Build Coastguard Worker };
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker // Declares an TimeDelta-valued parameter. Example:
245*6777b538SAndroid Build Coastguard Worker //
246*6777b538SAndroid Build Coastguard Worker //     constexpr base::FeatureParam<base::TimeDelta> kPerAgentDelay{
247*6777b538SAndroid Build Coastguard Worker //         &kPerAgentSchedulingExperiments, "delay", base::TimeDelta()};
248*6777b538SAndroid Build Coastguard Worker //
249*6777b538SAndroid Build Coastguard Worker // If the feature is not enabled, the parameter is not set, or set to an
250*6777b538SAndroid Build Coastguard Worker // invalid value (as defined by base::TimeDeltaFromString()), then Get() will
251*6777b538SAndroid Build Coastguard Worker // return the default value.
252*6777b538SAndroid Build Coastguard Worker template <>
253*6777b538SAndroid Build Coastguard Worker struct FeatureParam<base::TimeDelta> {
254*6777b538SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
255*6777b538SAndroid Build Coastguard Worker                          const char* name,
256*6777b538SAndroid Build Coastguard Worker                          base::TimeDelta default_value)
257*6777b538SAndroid Build Coastguard Worker       : feature(feature), name(name), default_value(default_value) {}
258*6777b538SAndroid Build Coastguard Worker 
259*6777b538SAndroid Build Coastguard Worker   // Calling Get() will activate the field trial associated with |feature|. See
260*6777b538SAndroid Build Coastguard Worker   // GetFieldTrialParamValueByFeature() for more details.
261*6777b538SAndroid Build Coastguard Worker   BASE_EXPORT base::TimeDelta Get() const;
262*6777b538SAndroid Build Coastguard Worker 
263*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
264*6777b538SAndroid Build Coastguard Worker   // #global-scope, #constexpr-ctor-field-initializer
265*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const Feature* const feature;
266*6777b538SAndroid Build Coastguard Worker   const char* const name;
267*6777b538SAndroid Build Coastguard Worker   const base::TimeDelta default_value;
268*6777b538SAndroid Build Coastguard Worker };
269*6777b538SAndroid Build Coastguard Worker 
270*6777b538SAndroid Build Coastguard Worker BASE_EXPORT void LogInvalidEnumValue(const Feature& feature,
271*6777b538SAndroid Build Coastguard Worker                                      const std::string& param_name,
272*6777b538SAndroid Build Coastguard Worker                                      const std::string& value_as_string,
273*6777b538SAndroid Build Coastguard Worker                                      int default_value_as_int);
274*6777b538SAndroid Build Coastguard Worker 
275*6777b538SAndroid Build Coastguard Worker // Feature param declaration for an enum, with associated options. Example:
276*6777b538SAndroid Build Coastguard Worker //
277*6777b538SAndroid Build Coastguard Worker //     constexpr FeatureParam<ShapeEnum>::Option kShapeParamOptions[] = {
278*6777b538SAndroid Build Coastguard Worker //         {SHAPE_CIRCLE, "circle"},
279*6777b538SAndroid Build Coastguard Worker //         {SHAPE_CYLINDER, "cylinder"},
280*6777b538SAndroid Build Coastguard Worker //         {SHAPE_PAPERCLIP, "paperclip"}};
281*6777b538SAndroid Build Coastguard Worker //     constexpr FeatureParam<ShapeEnum> kAssistantShapeParam{
282*6777b538SAndroid Build Coastguard Worker //         &kAssistantFeature, "shape", SHAPE_CIRCLE, &kShapeParamOptions};
283*6777b538SAndroid Build Coastguard Worker //
284*6777b538SAndroid Build Coastguard Worker // With this declaration, the parameter may be set to "circle", "cylinder", or
285*6777b538SAndroid Build Coastguard Worker // "paperclip", and that will be translated to one of the three enum values. By
286*6777b538SAndroid Build Coastguard Worker // default, or if the param is set to an unknown value, the parameter will be
287*6777b538SAndroid Build Coastguard Worker // assumed to be SHAPE_CIRCLE.
288*6777b538SAndroid Build Coastguard Worker template <typename Enum>
289*6777b538SAndroid Build Coastguard Worker struct FeatureParam<Enum, true> {
290*6777b538SAndroid Build Coastguard Worker   struct Option {
291*6777b538SAndroid Build Coastguard Worker     constexpr Option(Enum value, const char* name) : value(value), name(name) {}
292*6777b538SAndroid Build Coastguard Worker 
293*6777b538SAndroid Build Coastguard Worker     const Enum value;
294*6777b538SAndroid Build Coastguard Worker     const char* const name;
295*6777b538SAndroid Build Coastguard Worker   };
296*6777b538SAndroid Build Coastguard Worker 
297*6777b538SAndroid Build Coastguard Worker   template <size_t option_count>
298*6777b538SAndroid Build Coastguard Worker   constexpr FeatureParam(const Feature* feature,
299*6777b538SAndroid Build Coastguard Worker                          const char* name,
300*6777b538SAndroid Build Coastguard Worker                          const Enum default_value,
301*6777b538SAndroid Build Coastguard Worker                          const Option (*options)[option_count])
302*6777b538SAndroid Build Coastguard Worker       : feature(feature),
303*6777b538SAndroid Build Coastguard Worker         name(name),
304*6777b538SAndroid Build Coastguard Worker         default_value(default_value),
305*6777b538SAndroid Build Coastguard Worker         options(*options),
306*6777b538SAndroid Build Coastguard Worker         option_count(option_count) {
307*6777b538SAndroid Build Coastguard Worker     static_assert(option_count >= 1, "FeatureParam<enum> has no options");
308*6777b538SAndroid Build Coastguard Worker   }
309*6777b538SAndroid Build Coastguard Worker 
310*6777b538SAndroid Build Coastguard Worker   // Calling Get() will activate the field trial associated with |feature|. See
311*6777b538SAndroid Build Coastguard Worker   // GetFieldTrialParamValueByFeature() for more details.
312*6777b538SAndroid Build Coastguard Worker   Enum Get() const {
313*6777b538SAndroid Build Coastguard Worker     std::string value = GetFieldTrialParamValueByFeature(*feature, name);
314*6777b538SAndroid Build Coastguard Worker     if (value.empty())
315*6777b538SAndroid Build Coastguard Worker       return default_value;
316*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < option_count; ++i) {
317*6777b538SAndroid Build Coastguard Worker       if (value == options[i].name)
318*6777b538SAndroid Build Coastguard Worker         return options[i].value;
319*6777b538SAndroid Build Coastguard Worker     }
320*6777b538SAndroid Build Coastguard Worker     LogInvalidEnumValue(*feature, name, value, static_cast<int>(default_value));
321*6777b538SAndroid Build Coastguard Worker     return default_value;
322*6777b538SAndroid Build Coastguard Worker   }
323*6777b538SAndroid Build Coastguard Worker 
324*6777b538SAndroid Build Coastguard Worker   // Returns the param-string for the given enum value.
325*6777b538SAndroid Build Coastguard Worker   std::string GetName(Enum value) const {
326*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < option_count; ++i) {
327*6777b538SAndroid Build Coastguard Worker       if (value == options[i].value)
328*6777b538SAndroid Build Coastguard Worker         return options[i].name;
329*6777b538SAndroid Build Coastguard Worker     }
330*6777b538SAndroid Build Coastguard Worker     NOTREACHED();
331*6777b538SAndroid Build Coastguard Worker     return "";
332*6777b538SAndroid Build Coastguard Worker   }
333*6777b538SAndroid Build Coastguard Worker 
334*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
335*6777b538SAndroid Build Coastguard Worker   // #global-scope, #constexpr-ctor-field-initializer
336*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const base::Feature* const feature;
337*6777b538SAndroid Build Coastguard Worker   const char* const name;
338*6777b538SAndroid Build Coastguard Worker   const Enum default_value;
339*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
340*6777b538SAndroid Build Coastguard Worker   // #global-scope, #constexpr-ctor-field-initializer
341*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const Option* const options;
342*6777b538SAndroid Build Coastguard Worker   const size_t option_count;
343*6777b538SAndroid Build Coastguard Worker };
344*6777b538SAndroid Build Coastguard Worker 
345*6777b538SAndroid Build Coastguard Worker }  // namespace base
346*6777b538SAndroid Build Coastguard Worker 
347*6777b538SAndroid Build Coastguard Worker #endif  // BASE_METRICS_FIELD_TRIAL_PARAMS_H_
348