1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_METRICS_FIELD_TRIAL_PARAMS_H_ 6 #define BASE_METRICS_FIELD_TRIAL_PARAMS_H_ 7 8 #include <map> 9 #include <string> 10 11 #include "base/base_export.h" 12 13 namespace base { 14 15 struct Feature; 16 17 // Associates the specified set of key-value |params| with the field trial 18 // specified by |trial_name| and |group_name|. Fails and returns false if the 19 // specified field trial already has params associated with it or the trial 20 // is already active (group() has been called on it). Thread safe. 21 BASE_EXPORT bool AssociateFieldTrialParams( 22 const std::string& trial_name, 23 const std::string& group_name, 24 const std::map<std::string, std::string>& params); 25 26 // Retrieves the set of key-value |params| for the specified field trial, based 27 // on its selected group. If the field trial does not exist or its selected 28 // group does not have any parameters associated with it, returns false and 29 // does not modify |params|. Calling this function will result in the field 30 // trial being marked as active if found (i.e. group() will be called on it), 31 // if it wasn't already. Thread safe. 32 BASE_EXPORT bool GetFieldTrialParams( 33 const std::string& trial_name, 34 std::map<std::string, std::string>* params); 35 36 // Retrieves the set of key-value |params| for the field trial associated with 37 // the specified |feature|. A feature is associated with at most one field 38 // trial and selected group. See base/feature_list.h for more information on 39 // features. If the feature is not enabled, or if there's no associated params, 40 // returns false and does not modify |params|. Calling this function will 41 // result in the associated field trial being marked as active if found (i.e. 42 // group() will be called on it), if it wasn't already. Thread safe. 43 BASE_EXPORT bool GetFieldTrialParamsByFeature( 44 const base::Feature& feature, 45 std::map<std::string, std::string>* params); 46 47 // Retrieves a specific parameter value corresponding to |param_name| for the 48 // specified field trial, based on its selected group. If the field trial does 49 // not exist or the specified parameter does not exist, returns an empty 50 // string. Calling this function will result in the field trial being marked as 51 // active if found (i.e. group() will be called on it), if it wasn't already. 52 // Thread safe. 53 BASE_EXPORT std::string GetFieldTrialParamValue(const std::string& trial_name, 54 const std::string& param_name); 55 56 // Retrieves a specific parameter value corresponding to |param_name| for the 57 // field trial associated with the specified |feature|. A feature is associated 58 // with at most one field trial and selected group. See base/feature_list.h for 59 // more information on features. If the feature is not enabled, or the 60 // specified parameter does not exist, returns an empty string. Calling this 61 // function will result in the associated field trial being marked as active if 62 // found (i.e. group() will be called on it), if it wasn't already. Thread safe. 63 BASE_EXPORT std::string GetFieldTrialParamValueByFeature( 64 const base::Feature& feature, 65 const std::string& param_name); 66 67 // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the 68 // string value into an int using base::StringToInt() and returns it, if 69 // successful. Otherwise, it returns |default_value|. If the string value is not 70 // empty and the conversion does not succeed, it produces a warning to LOG. 71 BASE_EXPORT int GetFieldTrialParamByFeatureAsInt(const base::Feature& feature, 72 const std::string& param_name, 73 int default_value); 74 75 // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the 76 // string value into a double using base::StringToDouble() and returns it, if 77 // successful. Otherwise, it returns |default_value|. If the string value is not 78 // empty and the conversion does not succeed, it produces a warning to LOG. 79 BASE_EXPORT double GetFieldTrialParamByFeatureAsDouble( 80 const base::Feature& feature, 81 const std::string& param_name, 82 double default_value); 83 84 // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the 85 // string value into a boolean and returns it, if successful. Otherwise, it 86 // returns |default_value|. The only string representations accepted here are 87 // "true" and "false". If the string value is not empty and the conversion does 88 // not succeed, it produces a warning to LOG. 89 BASE_EXPORT bool GetFieldTrialParamByFeatureAsBool( 90 const base::Feature& feature, 91 const std::string& param_name, 92 bool default_value); 93 94 // Shared declaration for various FeatureParam<T> types. 95 // 96 // This template is defined for the following types T: 97 // bool 98 // int 99 // double 100 // std::string 101 // enum types 102 // 103 // See the individual definitions below for the appropriate interfaces. 104 // Attempting to use it with any other type is a compile error. 105 template <typename T, bool IsEnum = std::is_enum<T>::value> 106 struct FeatureParam { 107 // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T 108 // in its definition so that evaluation is deferred until the template is 109 // instantiated. 110 static_assert(!std::is_same<T, T>::value, "unsupported FeatureParam<> type"); 111 }; 112 113 // Declares a string-valued parameter. Example: 114 // 115 // constexpr FeatureParam<string> kAssistantName{ 116 // &kAssistantFeature, "assistant_name", "HAL"}; 117 // 118 // If the feature is not set, or set to the empty string, then Get() will return 119 // the default value. 120 template <> 121 struct FeatureParam<std::string> { 122 constexpr FeatureParam(const Feature* feature, 123 const char* name, 124 const char* default_value) 125 : feature(feature), name(name), default_value(default_value) {} 126 127 BASE_EXPORT std::string Get() const; 128 129 const Feature* const feature; 130 const char* const name; 131 const char* const default_value; 132 }; 133 134 // Declares a double-valued parameter. Example: 135 // 136 // constexpr FeatureParam<double> kAssistantTriggerThreshold{ 137 // &kAssistantFeature, "trigger_threshold", 0.10}; 138 // 139 // If the feature is not set, or set to an invalid double value, then Get() will 140 // return the default value. 141 template <> 142 struct FeatureParam<double> { 143 constexpr FeatureParam(const Feature* feature, 144 const char* name, 145 double default_value) 146 : feature(feature), name(name), default_value(default_value) {} 147 148 BASE_EXPORT double Get() const; 149 150 const Feature* const feature; 151 const char* const name; 152 const double default_value; 153 }; 154 155 // Declares an int-valued parameter. Example: 156 // 157 // constexpr FeatureParam<int> kAssistantParallelism{ 158 // &kAssistantFeature, "parallelism", 4}; 159 // 160 // If the feature is not set, or set to an invalid int value, then Get() will 161 // return the default value. 162 template <> 163 struct FeatureParam<int> { 164 constexpr FeatureParam(const Feature* feature, 165 const char* name, 166 int default_value) 167 : feature(feature), name(name), default_value(default_value) {} 168 169 BASE_EXPORT int Get() const; 170 171 const Feature* const feature; 172 const char* const name; 173 const int default_value; 174 }; 175 176 // Declares a bool-valued parameter. Example: 177 // 178 // constexpr FeatureParam<int> kAssistantIsHelpful{ 179 // &kAssistantFeature, "is_helpful", true}; 180 // 181 // If the feature is not set, or set to value other than "true" or "false", then 182 // Get() will return the default value. 183 template <> 184 struct FeatureParam<bool> { 185 constexpr FeatureParam(const Feature* feature, 186 const char* name, 187 bool default_value) 188 : feature(feature), name(name), default_value(default_value) {} 189 190 BASE_EXPORT bool Get() const; 191 192 const Feature* const feature; 193 const char* const name; 194 const bool default_value; 195 }; 196 197 BASE_EXPORT void LogInvalidEnumValue(const Feature& feature, 198 const std::string& param_name, 199 const std::string& value_as_string, 200 int default_value_as_int); 201 202 // Feature param declaration for an enum, with associated options. Example: 203 // 204 // constexpr FeatureParam<ShapeEnum>::Option[] kShapeParamOptions[] = { 205 // {SHAPE_CIRCLE, "circle"}, 206 // {SHAPE_CYLINDER, "cylinder"}, 207 // {SHAPE_PAPERCLIP, "paperclip"}}; 208 // constexpr FeatureParam<ShapeEnum> kAssistantShapeParam{ 209 // &kAssistantFeature, "shape", SHAPE_CIRCLE, &kShapeParamOptions}; 210 // 211 // With this declaration, the parameter may be set to "circle", "cylinder", or 212 // "paperclip", and that will be translated to one of the three enum values. By 213 // default, or if the param is set to an unknown value, the parameter will be 214 // assumed to be SHAPE_CIRCLE. 215 template <typename Enum> 216 struct FeatureParam<Enum, true> { 217 struct Option { 218 constexpr Option(Enum value, const char* name) : value(value), name(name) {} 219 220 const Enum value; 221 const char* const name; 222 }; 223 224 template <size_t option_count> 225 constexpr FeatureParam(const Feature* feature, 226 const char* name, 227 const Enum default_value, 228 const Option (*options)[option_count]) 229 : feature(feature), 230 name(name), 231 default_value(default_value), 232 options(*options), 233 option_count(option_count) { 234 static_assert(option_count >= 1, "FeatureParam<enum> has no options"); 235 } 236 237 Enum Get() const { 238 std::string value = GetFieldTrialParamValueByFeature(*feature, name); 239 if (value.empty()) 240 return default_value; 241 for (size_t i = 0; i < option_count; ++i) { 242 if (value == options[i].name) 243 return options[i].value; 244 } 245 LogInvalidEnumValue(*feature, name, value, static_cast<int>(default_value)); 246 return default_value; 247 } 248 249 const base::Feature* const feature; 250 const char* const name; 251 const Enum default_value; 252 const Option* const options; 253 const size_t option_count; 254 }; 255 256 } // namespace base 257 258 #endif // BASE_METRICS_FIELD_TRIAL_PARAMS_H_ 259