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