blob: 47916fd09384d4742a5ab7da1246542545d0f412 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2017 The Chromium Authors
asvitkine79ab08c2017-01-30 23:27:052// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakj51d26a42024-04-25 14:23:565#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7#pragma allow_unsafe_buffers
8#endif
9
asvitkine79ab08c2017-01-30 23:27:0510#ifndef BASE_METRICS_FIELD_TRIAL_PARAMS_H_
11#define BASE_METRICS_FIELD_TRIAL_PARAMS_H_
12
13#include <map>
14#include <string>
15
16#include "base/base_export.h"
Anthony Vallee-Dubois9dbbbda32022-08-26 01:25:3117#include "base/feature_list.h"
Fergal Dalybcac47a2020-03-27 01:54:2118#include "base/logging.h"
Keishi Hattori8a7e15d2023-01-19 07:16:2919#include "base/memory/raw_ptr_exclusion.h"
Hans Wennborgafeb3902020-06-17 14:42:2920#include "base/notreached.h"
Tal Pressman3e91d6fd2020-07-02 04:38:0121#include "base/time/time.h"
asvitkine79ab08c2017-01-30 23:27:0522
23namespace base {
24
Miyoung Shinb5ad87f2019-05-13 20:12:4525// Key-value mapping type for field trial parameters.
26typedef std::map<std::string, std::string> FieldTrialParams;
27
Alexei Svitkine8724ea502019-06-14 21:51:4628// Param string decoding function for AssociateFieldTrialParamsFromString().
29typedef std::string (*FieldTrialParamsDecodeStringFunc)(const std::string& str);
30
Weilun Shi1cd8fb92020-07-17 23:31:0031// Unescapes special characters from the given string. Used in
32// AssociateFieldTrialParamsFromString() as one of the feature params decoding
33// functions.
34BASE_EXPORT std::string UnescapeValue(const std::string& value);
35
asvitkine79ab08c2017-01-30 23:27:0536// Associates the specified set of key-value |params| with the field trial
37// specified by |trial_name| and |group_name|. Fails and returns false if the
38// specified field trial already has params associated with it or the trial
39// is already active (group() has been called on it). Thread safe.
Miyoung Shinb5ad87f2019-05-13 20:12:4540BASE_EXPORT bool AssociateFieldTrialParams(const std::string& trial_name,
41 const std::string& group_name,
42 const FieldTrialParams& params);
asvitkine79ab08c2017-01-30 23:27:0543
Alexei Svitkine8724ea502019-06-14 21:51:4644// Provides a mechanism to associate multiple set of params to multiple groups
45// with a formatted string as returned by FieldTrialList::AllParamsToString().
46// |decode_data_func| allows specifying a custom decoding function.
47BASE_EXPORT bool AssociateFieldTrialParamsFromString(
48 const std::string& params_string,
49 FieldTrialParamsDecodeStringFunc decode_data_func);
50
asvitkine79ab08c2017-01-30 23:27:0551// Retrieves the set of key-value |params| for the specified field trial, based
52// on its selected group. If the field trial does not exist or its selected
53// group does not have any parameters associated with it, returns false and
54// does not modify |params|. Calling this function will result in the field
55// trial being marked as active if found (i.e. group() will be called on it),
56// if it wasn't already. Thread safe.
Miyoung Shinb5ad87f2019-05-13 20:12:4557BASE_EXPORT bool GetFieldTrialParams(const std::string& trial_name,
58 FieldTrialParams* params);
asvitkine79ab08c2017-01-30 23:27:0559
60// Retrieves the set of key-value |params| for the field trial associated with
61// the specified |feature|. A feature is associated with at most one field
62// trial and selected group. See base/feature_list.h for more information on
63// features. If the feature is not enabled, or if there's no associated params,
64// returns false and does not modify |params|. Calling this function will
65// result in the associated field trial being marked as active if found (i.e.
66// group() will be called on it), if it wasn't already. Thread safe.
Miyoung Shinb5ad87f2019-05-13 20:12:4567BASE_EXPORT bool GetFieldTrialParamsByFeature(const base::Feature& feature,
68 FieldTrialParams* params);
asvitkine79ab08c2017-01-30 23:27:0569
70// Retrieves a specific parameter value corresponding to |param_name| for the
71// specified field trial, based on its selected group. If the field trial does
72// not exist or the specified parameter does not exist, returns an empty
73// string. Calling this function will result in the field trial being marked as
74// active if found (i.e. group() will be called on it), if it wasn't already.
75// Thread safe.
76BASE_EXPORT std::string GetFieldTrialParamValue(const std::string& trial_name,
77 const std::string& param_name);
78
79// Retrieves a specific parameter value corresponding to |param_name| for the
80// field trial associated with the specified |feature|. A feature is associated
81// with at most one field trial and selected group. See base/feature_list.h for
82// more information on features. If the feature is not enabled, or the
83// specified parameter does not exist, returns an empty string. Calling this
84// function will result in the associated field trial being marked as active if
85// found (i.e. group() will be called on it), if it wasn't already. Thread safe.
86BASE_EXPORT std::string GetFieldTrialParamValueByFeature(
87 const base::Feature& feature,
88 const std::string& param_name);
89
90// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
91// string value into an int using base::StringToInt() and returns it, if
92// successful. Otherwise, it returns |default_value|. If the string value is not
93// empty and the conversion does not succeed, it produces a warning to LOG.
94BASE_EXPORT int GetFieldTrialParamByFeatureAsInt(const base::Feature& feature,
95 const std::string& param_name,
96 int default_value);
97
98// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
99// string value into a double using base::StringToDouble() and returns it, if
100// successful. Otherwise, it returns |default_value|. If the string value is not
101// empty and the conversion does not succeed, it produces a warning to LOG.
102BASE_EXPORT double GetFieldTrialParamByFeatureAsDouble(
103 const base::Feature& feature,
104 const std::string& param_name,
105 double default_value);
106
107// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
108// string value into a boolean and returns it, if successful. Otherwise, it
109// returns |default_value|. The only string representations accepted here are
110// "true" and "false". If the string value is not empty and the conversion does
111// not succeed, it produces a warning to LOG.
112BASE_EXPORT bool GetFieldTrialParamByFeatureAsBool(
113 const base::Feature& feature,
114 const std::string& param_name,
115 bool default_value);
116
Minoru Chikamunefedb8272023-09-27 02:08:24117// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
118// string value into a base::TimeDelta and returns it, if successful. Otherwise,
119// it returns `default_value`. If the string value is not empty and the
120// conversion does not succeed, it produces a warning to LOG.
121BASE_EXPORT base::TimeDelta GetFieldTrialParamByFeatureAsTimeDelta(
122 const Feature& feature,
123 const std::string& param_name,
124 base::TimeDelta default_value);
125
sfiera01757be62017-09-20 16:36:13126// Shared declaration for various FeatureParam<T> types.
127//
128// This template is defined for the following types T:
129// bool
130// int
131// double
132// std::string
133// enum types
Tal Pressman3e91d6fd2020-07-02 04:38:01134// base::TimeDelta
sfiera01757be62017-09-20 16:36:13135//
136// See the individual definitions below for the appropriate interfaces.
137// Attempting to use it with any other type is a compile error.
Jesse Doherty031e56932020-10-21 23:23:47138//
139// Getting a param value from a FeatureParam<T> will have the same semantics as
140// GetFieldTrialParamValueByFeature(), see that function's comments for details.
Andrew Rayskiy384fa272023-10-16 17:45:59141template <typename T, bool IsEnum = std::is_enum_v<T>>
sfiera01757be62017-09-20 16:36:13142struct FeatureParam {
143 // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T
144 // in its definition so that evaluation is deferred until the template is
145 // instantiated.
Andrew Rayskiy384fa272023-10-16 17:45:59146 static_assert(!std::is_same_v<T, T>, "unsupported FeatureParam<> type");
sfiera01757be62017-09-20 16:36:13147};
148
149// Declares a string-valued parameter. Example:
150//
mlcuif190ddea2024-04-25 15:26:59151// constexpr FeatureParam<string> kAssistantName = {
sfiera01757be62017-09-20 16:36:13152// &kAssistantFeature, "assistant_name", "HAL"};
153//
Xiaohan Wang0c04ab32023-04-26 16:01:44154// If the feature is not enabled, the parameter is not set, or set to the empty
155// string, then Get() will return the default value.
sfiera01757be62017-09-20 16:36:13156template <>
157struct FeatureParam<std::string> {
158 constexpr FeatureParam(const Feature* feature,
159 const char* name,
160 const char* default_value)
161 : feature(feature), name(name), default_value(default_value) {}
162
Jesse Doherty031e56932020-10-21 23:23:47163 // Calling Get() will activate the field trial associated with |feature|. See
164 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13165 BASE_EXPORT std::string Get() const;
166
Keishi Hattori8a7e15d2023-01-19 07:16:29167 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
168 // #global-scope, #constexpr-ctor-field-initializer
169 RAW_PTR_EXCLUSION const Feature* const feature;
sfiera01757be62017-09-20 16:36:13170 const char* const name;
171 const char* const default_value;
172};
173
174// Declares a double-valued parameter. Example:
175//
mlcuif190ddea2024-04-25 15:26:59176// constexpr FeatureParam<double> kAssistantTriggerThreshold = {
sfiera01757be62017-09-20 16:36:13177// &kAssistantFeature, "trigger_threshold", 0.10};
178//
Xiaohan Wang0c04ab32023-04-26 16:01:44179// If the feature is not enabled, the parameter is not set, or set to an invalid
180// double value, then Get() will return the default value.
sfiera01757be62017-09-20 16:36:13181template <>
182struct FeatureParam<double> {
183 constexpr FeatureParam(const Feature* feature,
184 const char* name,
185 double default_value)
186 : feature(feature), name(name), default_value(default_value) {}
187
Jesse Doherty031e56932020-10-21 23:23:47188 // Calling Get() will activate the field trial associated with |feature|. See
189 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13190 BASE_EXPORT double Get() const;
191
Keishi Hattori8a7e15d2023-01-19 07:16:29192 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
193 // #global-scope, #constexpr-ctor-field-initializer
194 RAW_PTR_EXCLUSION const Feature* const feature;
sfiera01757be62017-09-20 16:36:13195 const char* const name;
196 const double default_value;
197};
198
199// Declares an int-valued parameter. Example:
200//
mlcuif190ddea2024-04-25 15:26:59201// constexpr FeatureParam<int> kAssistantParallelism = {
sfiera01757be62017-09-20 16:36:13202// &kAssistantFeature, "parallelism", 4};
203//
Xiaohan Wang0c04ab32023-04-26 16:01:44204// If the feature is not enabled, the parameter is not set, or set to an invalid
205// int value, then Get() will return the default value.
sfiera01757be62017-09-20 16:36:13206template <>
207struct FeatureParam<int> {
208 constexpr FeatureParam(const Feature* feature,
209 const char* name,
210 int default_value)
211 : feature(feature), name(name), default_value(default_value) {}
212
Jesse Doherty031e56932020-10-21 23:23:47213 // Calling Get() will activate the field trial associated with |feature|. See
214 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13215 BASE_EXPORT int Get() const;
216
Keishi Hattori8a7e15d2023-01-19 07:16:29217 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
218 // #global-scope, #constexpr-ctor-field-initializer
219 RAW_PTR_EXCLUSION const Feature* const feature;
sfiera01757be62017-09-20 16:36:13220 const char* const name;
221 const int default_value;
222};
223
224// Declares a bool-valued parameter. Example:
225//
mlcuif190ddea2024-04-25 15:26:59226// constexpr FeatureParam<int> kAssistantIsHelpful = {
sfiera01757be62017-09-20 16:36:13227// &kAssistantFeature, "is_helpful", true};
228//
Xiaohan Wang0c04ab32023-04-26 16:01:44229// If the feature is not enabled, the parameter is not set, or set to value
230// other than "true" or "false", then Get() will return the default value.
sfiera01757be62017-09-20 16:36:13231template <>
232struct FeatureParam<bool> {
233 constexpr FeatureParam(const Feature* feature,
234 const char* name,
235 bool default_value)
236 : feature(feature), name(name), default_value(default_value) {}
237
Jesse Doherty031e56932020-10-21 23:23:47238 // Calling Get() will activate the field trial associated with |feature|. See
239 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13240 BASE_EXPORT bool Get() const;
241
Keishi Hattori8a7e15d2023-01-19 07:16:29242 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
243 // #global-scope, #constexpr-ctor-field-initializer
244 RAW_PTR_EXCLUSION const Feature* const feature;
sfiera01757be62017-09-20 16:36:13245 const char* const name;
246 const bool default_value;
247};
248
Tal Pressman3e91d6fd2020-07-02 04:38:01249// Declares an TimeDelta-valued parameter. Example:
250//
Evan Stade87785864f2021-10-13 21:49:11251// constexpr base::FeatureParam<base::TimeDelta> kPerAgentDelay{
252// &kPerAgentSchedulingExperiments, "delay", base::TimeDelta()};
Tal Pressman3e91d6fd2020-07-02 04:38:01253//
Xiaohan Wang0c04ab32023-04-26 16:01:44254// If the feature is not enabled, the parameter is not set, or set to an
255// invalid value (as defined by base::TimeDeltaFromString()), then Get() will
256// return the default value.
Tal Pressman3e91d6fd2020-07-02 04:38:01257template <>
258struct FeatureParam<base::TimeDelta> {
259 constexpr FeatureParam(const Feature* feature,
260 const char* name,
261 base::TimeDelta default_value)
262 : feature(feature), name(name), default_value(default_value) {}
263
Jesse Doherty031e56932020-10-21 23:23:47264 // Calling Get() will activate the field trial associated with |feature|. See
265 // GetFieldTrialParamValueByFeature() for more details.
Tal Pressman3e91d6fd2020-07-02 04:38:01266 BASE_EXPORT base::TimeDelta Get() const;
267
Keishi Hattori8a7e15d2023-01-19 07:16:29268 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
269 // #global-scope, #constexpr-ctor-field-initializer
270 RAW_PTR_EXCLUSION const Feature* const feature;
Tal Pressman3e91d6fd2020-07-02 04:38:01271 const char* const name;
272 const base::TimeDelta default_value;
273};
274
sfiera01757be62017-09-20 16:36:13275BASE_EXPORT void LogInvalidEnumValue(const Feature& feature,
276 const std::string& param_name,
277 const std::string& value_as_string,
278 int default_value_as_int);
279
280// Feature param declaration for an enum, with associated options. Example:
281//
Kenichi Ishibashi0a84cb5f32018-12-13 04:02:10282// constexpr FeatureParam<ShapeEnum>::Option kShapeParamOptions[] = {
sfiera01757be62017-09-20 16:36:13283// {SHAPE_CIRCLE, "circle"},
284// {SHAPE_CYLINDER, "cylinder"},
285// {SHAPE_PAPERCLIP, "paperclip"}};
mlcuif190ddea2024-04-25 15:26:59286// constexpr FeatureParam<ShapeEnum> kAssistantShapeParam = {
sfiera01757be62017-09-20 16:36:13287// &kAssistantFeature, "shape", SHAPE_CIRCLE, &kShapeParamOptions};
288//
289// With this declaration, the parameter may be set to "circle", "cylinder", or
290// "paperclip", and that will be translated to one of the three enum values. By
291// default, or if the param is set to an unknown value, the parameter will be
292// assumed to be SHAPE_CIRCLE.
293template <typename Enum>
294struct FeatureParam<Enum, true> {
295 struct Option {
296 constexpr Option(Enum value, const char* name) : value(value), name(name) {}
297
298 const Enum value;
299 const char* const name;
300 };
301
302 template <size_t option_count>
303 constexpr FeatureParam(const Feature* feature,
304 const char* name,
305 const Enum default_value,
306 const Option (*options)[option_count])
307 : feature(feature),
308 name(name),
309 default_value(default_value),
310 options(*options),
311 option_count(option_count) {
312 static_assert(option_count >= 1, "FeatureParam<enum> has no options");
313 }
314
Jesse Doherty031e56932020-10-21 23:23:47315 // Calling Get() will activate the field trial associated with |feature|. See
316 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13317 Enum Get() const {
318 std::string value = GetFieldTrialParamValueByFeature(*feature, name);
319 if (value.empty())
320 return default_value;
321 for (size_t i = 0; i < option_count; ++i) {
322 if (value == options[i].name)
323 return options[i].value;
324 }
325 LogInvalidEnumValue(*feature, name, value, static_cast<int>(default_value));
326 return default_value;
327 }
328
Fergal Dalybcac47a2020-03-27 01:54:21329 // Returns the param-string for the given enum value.
330 std::string GetName(Enum value) const {
331 for (size_t i = 0; i < option_count; ++i) {
332 if (value == options[i].value)
333 return options[i].name;
334 }
Peter Boström8c29f4a2024-05-08 01:12:11335 NOTREACHED_IN_MIGRATION();
Fergal Dalybcac47a2020-03-27 01:54:21336 return "";
337 }
338
Keishi Hattori8a7e15d2023-01-19 07:16:29339 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
340 // #global-scope, #constexpr-ctor-field-initializer
341 RAW_PTR_EXCLUSION const base::Feature* const feature;
sfiera01757be62017-09-20 16:36:13342 const char* const name;
343 const Enum default_value;
Keishi Hattori8a7e15d2023-01-19 07:16:29344 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
345 // #global-scope, #constexpr-ctor-field-initializer
346 RAW_PTR_EXCLUSION const Option* const options;
sfiera01757be62017-09-20 16:36:13347 const size_t option_count;
348};
349
asvitkine79ab08c2017-01-30 23:27:05350} // namespace base
351
352#endif // BASE_METRICS_FIELD_TRIAL_PARAMS_H_