blob: 42b4f4370218836ca48de7640b84f4aadddaf901 [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
danakje75c6c812024-07-26 20:37:4713#include <array>
asvitkine79ab08c2017-01-30 23:27:0514#include <map>
15#include <string>
16
17#include "base/base_export.h"
Anthony Vallee-Dubois9dbbbda32022-08-26 01:25:3118#include "base/feature_list.h"
Fergal Dalybcac47a2020-03-27 01:54:2119#include "base/logging.h"
Keishi Hattori8a7e15d2023-01-19 07:16:2920#include "base/memory/raw_ptr_exclusion.h"
Hans Wennborgafeb3902020-06-17 14:42:2921#include "base/notreached.h"
Tal Pressman3e91d6fd2020-07-02 04:38:0122#include "base/time/time.h"
asvitkine79ab08c2017-01-30 23:27:0523
24namespace base {
25
Miyoung Shinb5ad87f2019-05-13 20:12:4526// Key-value mapping type for field trial parameters.
27typedef std::map<std::string, std::string> FieldTrialParams;
28
Alexei Svitkine8724ea502019-06-14 21:51:4629// Param string decoding function for AssociateFieldTrialParamsFromString().
30typedef std::string (*FieldTrialParamsDecodeStringFunc)(const std::string& str);
31
Weilun Shi1cd8fb92020-07-17 23:31:0032// Unescapes special characters from the given string. Used in
33// AssociateFieldTrialParamsFromString() as one of the feature params decoding
34// functions.
35BASE_EXPORT std::string UnescapeValue(const std::string& value);
36
asvitkine79ab08c2017-01-30 23:27:0537// Associates the specified set of key-value |params| with the field trial
38// specified by |trial_name| and |group_name|. Fails and returns false if the
39// specified field trial already has params associated with it or the trial
40// is already active (group() has been called on it). Thread safe.
Miyoung Shinb5ad87f2019-05-13 20:12:4541BASE_EXPORT bool AssociateFieldTrialParams(const std::string& trial_name,
42 const std::string& group_name,
43 const FieldTrialParams& params);
asvitkine79ab08c2017-01-30 23:27:0544
Alexei Svitkine8724ea502019-06-14 21:51:4645// Provides a mechanism to associate multiple set of params to multiple groups
46// with a formatted string as returned by FieldTrialList::AllParamsToString().
47// |decode_data_func| allows specifying a custom decoding function.
48BASE_EXPORT bool AssociateFieldTrialParamsFromString(
49 const std::string& params_string,
50 FieldTrialParamsDecodeStringFunc decode_data_func);
51
asvitkine79ab08c2017-01-30 23:27:0552// Retrieves the set of key-value |params| for the specified field trial, based
53// on its selected group. If the field trial does not exist or its selected
54// group does not have any parameters associated with it, returns false and
55// does not modify |params|. Calling this function will result in the field
56// trial being marked as active if found (i.e. group() will be called on it),
57// if it wasn't already. Thread safe.
Miyoung Shinb5ad87f2019-05-13 20:12:4558BASE_EXPORT bool GetFieldTrialParams(const std::string& trial_name,
59 FieldTrialParams* params);
asvitkine79ab08c2017-01-30 23:27:0560
61// Retrieves the set of key-value |params| for the field trial associated with
62// the specified |feature|. A feature is associated with at most one field
63// trial and selected group. See base/feature_list.h for more information on
64// features. If the feature is not enabled, or if there's no associated params,
65// returns false and does not modify |params|. Calling this function will
66// result in the associated field trial being marked as active if found (i.e.
67// group() will be called on it), if it wasn't already. Thread safe.
Miyoung Shinb5ad87f2019-05-13 20:12:4568BASE_EXPORT bool GetFieldTrialParamsByFeature(const base::Feature& feature,
69 FieldTrialParams* params);
asvitkine79ab08c2017-01-30 23:27:0570
71// Retrieves a specific parameter value corresponding to |param_name| for the
72// specified field trial, based on its selected group. If the field trial does
73// not exist or the specified parameter does not exist, returns an empty
74// string. Calling this function will result in the field trial being marked as
75// active if found (i.e. group() will be called on it), if it wasn't already.
76// Thread safe.
77BASE_EXPORT std::string GetFieldTrialParamValue(const std::string& trial_name,
78 const std::string& param_name);
79
80// Retrieves a specific parameter value corresponding to |param_name| for the
81// field trial associated with the specified |feature|. A feature is associated
82// with at most one field trial and selected group. See base/feature_list.h for
83// more information on features. If the feature is not enabled, or the
84// specified parameter does not exist, returns an empty string. Calling this
85// function will result in the associated field trial being marked as active if
86// found (i.e. group() will be called on it), if it wasn't already. Thread safe.
87BASE_EXPORT std::string GetFieldTrialParamValueByFeature(
88 const base::Feature& feature,
89 const std::string& param_name);
90
91// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
92// string value into an int using base::StringToInt() and returns it, if
93// successful. Otherwise, it returns |default_value|. If the string value is not
94// empty and the conversion does not succeed, it produces a warning to LOG.
95BASE_EXPORT int GetFieldTrialParamByFeatureAsInt(const base::Feature& feature,
96 const std::string& param_name,
97 int default_value);
98
99// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
100// string value into a double using base::StringToDouble() and returns it, if
101// successful. Otherwise, it returns |default_value|. If the string value is not
102// empty and the conversion does not succeed, it produces a warning to LOG.
103BASE_EXPORT double GetFieldTrialParamByFeatureAsDouble(
104 const base::Feature& feature,
105 const std::string& param_name,
106 double default_value);
107
108// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
109// string value into a boolean and returns it, if successful. Otherwise, it
110// returns |default_value|. The only string representations accepted here are
111// "true" and "false". If the string value is not empty and the conversion does
112// not succeed, it produces a warning to LOG.
113BASE_EXPORT bool GetFieldTrialParamByFeatureAsBool(
114 const base::Feature& feature,
115 const std::string& param_name,
116 bool default_value);
117
Minoru Chikamunefedb8272023-09-27 02:08:24118// Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
119// string value into a base::TimeDelta and returns it, if successful. Otherwise,
120// it returns `default_value`. If the string value is not empty and the
121// conversion does not succeed, it produces a warning to LOG.
122BASE_EXPORT base::TimeDelta GetFieldTrialParamByFeatureAsTimeDelta(
123 const Feature& feature,
124 const std::string& param_name,
125 base::TimeDelta default_value);
126
sfiera01757be62017-09-20 16:36:13127// Shared declaration for various FeatureParam<T> types.
128//
129// This template is defined for the following types T:
130// bool
131// int
132// double
133// std::string
134// enum types
Tal Pressman3e91d6fd2020-07-02 04:38:01135// base::TimeDelta
sfiera01757be62017-09-20 16:36:13136//
137// See the individual definitions below for the appropriate interfaces.
138// Attempting to use it with any other type is a compile error.
Jesse Doherty031e56932020-10-21 23:23:47139//
140// Getting a param value from a FeatureParam<T> will have the same semantics as
141// GetFieldTrialParamValueByFeature(), see that function's comments for details.
Andrew Rayskiy384fa272023-10-16 17:45:59142template <typename T, bool IsEnum = std::is_enum_v<T>>
sfiera01757be62017-09-20 16:36:13143struct FeatureParam {
144 // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T
145 // in its definition so that evaluation is deferred until the template is
146 // instantiated.
Andrew Rayskiy384fa272023-10-16 17:45:59147 static_assert(!std::is_same_v<T, T>, "unsupported FeatureParam<> type");
sfiera01757be62017-09-20 16:36:13148};
149
150// Declares a string-valued parameter. Example:
151//
mlcuif190ddea2024-04-25 15:26:59152// constexpr FeatureParam<string> kAssistantName = {
sfiera01757be62017-09-20 16:36:13153// &kAssistantFeature, "assistant_name", "HAL"};
154//
Xiaohan Wang0c04ab32023-04-26 16:01:44155// If the feature is not enabled, the parameter is not set, or set to the empty
156// string, then Get() will return the default value.
sfiera01757be62017-09-20 16:36:13157template <>
158struct FeatureParam<std::string> {
159 constexpr FeatureParam(const Feature* feature,
160 const char* name,
161 const char* default_value)
162 : feature(feature), name(name), default_value(default_value) {}
163
Jesse Doherty031e56932020-10-21 23:23:47164 // Calling Get() will activate the field trial associated with |feature|. See
165 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13166 BASE_EXPORT std::string Get() const;
167
Bartek Nowierski26a2cce2024-06-23 21:34:06168 // RAW_PTR_EXCLUSION: #global-scope,
Keishi Hattori8a7e15d2023-01-19 07:16:29169 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
Bartek Nowierski26a2cce2024-06-23 21:34:06192 // RAW_PTR_EXCLUSION: #global-scope
Keishi Hattori8a7e15d2023-01-19 07:16:29193 RAW_PTR_EXCLUSION const Feature* const feature;
sfiera01757be62017-09-20 16:36:13194 const char* const name;
195 const double default_value;
196};
197
198// Declares an int-valued parameter. Example:
199//
mlcuif190ddea2024-04-25 15:26:59200// constexpr FeatureParam<int> kAssistantParallelism = {
sfiera01757be62017-09-20 16:36:13201// &kAssistantFeature, "parallelism", 4};
202//
Xiaohan Wang0c04ab32023-04-26 16:01:44203// If the feature is not enabled, the parameter is not set, or set to an invalid
204// int value, then Get() will return the default value.
sfiera01757be62017-09-20 16:36:13205template <>
206struct FeatureParam<int> {
207 constexpr FeatureParam(const Feature* feature,
208 const char* name,
209 int default_value)
210 : feature(feature), name(name), default_value(default_value) {}
211
Jesse Doherty031e56932020-10-21 23:23:47212 // Calling Get() will activate the field trial associated with |feature|. See
213 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13214 BASE_EXPORT int Get() const;
215
Bartek Nowierski26a2cce2024-06-23 21:34:06216 // RAW_PTR_EXCLUSION: #global-scope
Keishi Hattori8a7e15d2023-01-19 07:16:29217 RAW_PTR_EXCLUSION const Feature* const feature;
sfiera01757be62017-09-20 16:36:13218 const char* const name;
219 const int default_value;
220};
221
222// Declares a bool-valued parameter. Example:
223//
mlcuif190ddea2024-04-25 15:26:59224// constexpr FeatureParam<int> kAssistantIsHelpful = {
sfiera01757be62017-09-20 16:36:13225// &kAssistantFeature, "is_helpful", true};
226//
Xiaohan Wang0c04ab32023-04-26 16:01:44227// If the feature is not enabled, the parameter is not set, or set to value
228// other than "true" or "false", then Get() will return the default value.
sfiera01757be62017-09-20 16:36:13229template <>
230struct FeatureParam<bool> {
231 constexpr FeatureParam(const Feature* feature,
232 const char* name,
233 bool default_value)
234 : feature(feature), name(name), default_value(default_value) {}
235
Jesse Doherty031e56932020-10-21 23:23:47236 // Calling Get() will activate the field trial associated with |feature|. See
237 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13238 BASE_EXPORT bool Get() const;
239
Bartek Nowierski26a2cce2024-06-23 21:34:06240 // RAW_PTR_EXCLUSION: #global-scope
Keishi Hattori8a7e15d2023-01-19 07:16:29241 RAW_PTR_EXCLUSION const Feature* const feature;
sfiera01757be62017-09-20 16:36:13242 const char* const name;
243 const bool default_value;
244};
245
Tal Pressman3e91d6fd2020-07-02 04:38:01246// Declares an TimeDelta-valued parameter. Example:
247//
Evan Stade87785864f2021-10-13 21:49:11248// constexpr base::FeatureParam<base::TimeDelta> kPerAgentDelay{
249// &kPerAgentSchedulingExperiments, "delay", base::TimeDelta()};
Tal Pressman3e91d6fd2020-07-02 04:38:01250//
Xiaohan Wang0c04ab32023-04-26 16:01:44251// If the feature is not enabled, the parameter is not set, or set to an
252// invalid value (as defined by base::TimeDeltaFromString()), then Get() will
253// return the default value.
Tal Pressman3e91d6fd2020-07-02 04:38:01254template <>
255struct FeatureParam<base::TimeDelta> {
256 constexpr FeatureParam(const Feature* feature,
257 const char* name,
258 base::TimeDelta default_value)
259 : feature(feature), name(name), default_value(default_value) {}
260
Jesse Doherty031e56932020-10-21 23:23:47261 // Calling Get() will activate the field trial associated with |feature|. See
262 // GetFieldTrialParamValueByFeature() for more details.
Tal Pressman3e91d6fd2020-07-02 04:38:01263 BASE_EXPORT base::TimeDelta Get() const;
264
Bartek Nowierski26a2cce2024-06-23 21:34:06265 // RAW_PTR_EXCLUSION: #global-scope
Keishi Hattori8a7e15d2023-01-19 07:16:29266 RAW_PTR_EXCLUSION const Feature* const feature;
Tal Pressman3e91d6fd2020-07-02 04:38:01267 const char* const name;
268 const base::TimeDelta default_value;
269};
270
sfiera01757be62017-09-20 16:36:13271BASE_EXPORT void LogInvalidEnumValue(const Feature& feature,
272 const std::string& param_name,
273 const std::string& value_as_string,
274 int default_value_as_int);
275
276// Feature param declaration for an enum, with associated options. Example:
277//
Kenichi Ishibashi0a84cb5f32018-12-13 04:02:10278// constexpr FeatureParam<ShapeEnum>::Option kShapeParamOptions[] = {
sfiera01757be62017-09-20 16:36:13279// {SHAPE_CIRCLE, "circle"},
280// {SHAPE_CYLINDER, "cylinder"},
281// {SHAPE_PAPERCLIP, "paperclip"}};
mlcuif190ddea2024-04-25 15:26:59282// constexpr FeatureParam<ShapeEnum> kAssistantShapeParam = {
sfiera01757be62017-09-20 16:36:13283// &kAssistantFeature, "shape", SHAPE_CIRCLE, &kShapeParamOptions};
284//
285// With this declaration, the parameter may be set to "circle", "cylinder", or
286// "paperclip", and that will be translated to one of the three enum values. By
287// default, or if the param is set to an unknown value, the parameter will be
288// assumed to be SHAPE_CIRCLE.
289template <typename Enum>
290struct FeatureParam<Enum, true> {
291 struct Option {
292 constexpr Option(Enum value, const char* name) : value(value), name(name) {}
293
294 const Enum value;
295 const char* const name;
296 };
297
298 template <size_t option_count>
299 constexpr FeatureParam(const Feature* feature,
300 const char* name,
301 const Enum default_value,
danakje75c6c812024-07-26 20:37:47302 const std::array<Option, option_count>& options)
303 : feature(feature),
304 name(name),
305 default_value(default_value),
306 options(options.data()),
307 option_count(option_count) {
308 static_assert(option_count >= 1, "FeatureParam<enum> has no options");
309 }
310
311 template <size_t option_count>
312 constexpr FeatureParam(const Feature* feature,
313 const char* name,
314 const Enum default_value,
sfiera01757be62017-09-20 16:36:13315 const Option (*options)[option_count])
316 : feature(feature),
317 name(name),
318 default_value(default_value),
319 options(*options),
320 option_count(option_count) {
321 static_assert(option_count >= 1, "FeatureParam<enum> has no options");
322 }
323
Jesse Doherty031e56932020-10-21 23:23:47324 // Calling Get() will activate the field trial associated with |feature|. See
325 // GetFieldTrialParamValueByFeature() for more details.
sfiera01757be62017-09-20 16:36:13326 Enum Get() const {
327 std::string value = GetFieldTrialParamValueByFeature(*feature, name);
328 if (value.empty())
329 return default_value;
330 for (size_t i = 0; i < option_count; ++i) {
331 if (value == options[i].name)
332 return options[i].value;
333 }
334 LogInvalidEnumValue(*feature, name, value, static_cast<int>(default_value));
335 return default_value;
336 }
337
Fergal Dalybcac47a2020-03-27 01:54:21338 // Returns the param-string for the given enum value.
339 std::string GetName(Enum value) const {
340 for (size_t i = 0; i < option_count; ++i) {
341 if (value == options[i].value)
342 return options[i].name;
343 }
Peter Boström8c29f4a2024-05-08 01:12:11344 NOTREACHED_IN_MIGRATION();
Fergal Dalybcac47a2020-03-27 01:54:21345 return "";
346 }
347
Bartek Nowierski26a2cce2024-06-23 21:34:06348 // RAW_PTR_EXCLUSION: #global-scope
Keishi Hattori8a7e15d2023-01-19 07:16:29349 RAW_PTR_EXCLUSION const base::Feature* const feature;
sfiera01757be62017-09-20 16:36:13350 const char* const name;
351 const Enum default_value;
Bartek Nowierski26a2cce2024-06-23 21:34:06352 // RAW_PTR_EXCLUSION: #global-scope
Keishi Hattori8a7e15d2023-01-19 07:16:29353 RAW_PTR_EXCLUSION const Option* const options;
sfiera01757be62017-09-20 16:36:13354 const size_t option_count;
355};
356
asvitkine79ab08c2017-01-30 23:27:05357} // namespace base
358
359#endif // BASE_METRICS_FIELD_TRIAL_PARAMS_H_