|  | // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_METRICS_FIELD_TRIAL_PARAMS_H_ | 
|  | #define BASE_METRICS_FIELD_TRIAL_PARAMS_H_ | 
|  |  | 
|  | #include <map> | 
|  | #include <string> | 
|  |  | 
|  | #include "base/base_export.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | struct Feature; | 
|  |  | 
|  | // Associates the specified set of key-value |params| with the field trial | 
|  | // specified by |trial_name| and |group_name|. Fails and returns false if the | 
|  | // specified field trial already has params associated with it or the trial | 
|  | // is already active (group() has been called on it). Thread safe. | 
|  | BASE_EXPORT bool AssociateFieldTrialParams( | 
|  | const std::string& trial_name, | 
|  | const std::string& group_name, | 
|  | const std::map<std::string, std::string>& params); | 
|  |  | 
|  | // Retrieves the set of key-value |params| for the specified field trial, based | 
|  | // on its selected group. If the field trial does not exist or its selected | 
|  | // group does not have any parameters associated with it, returns false and | 
|  | // does not modify |params|. Calling this function will result in the field | 
|  | // trial being marked as active if found (i.e. group() will be called on it), | 
|  | // if it wasn't already. Thread safe. | 
|  | BASE_EXPORT bool GetFieldTrialParams( | 
|  | const std::string& trial_name, | 
|  | std::map<std::string, std::string>* params); | 
|  |  | 
|  | // Retrieves the set of key-value |params| for the field trial associated with | 
|  | // the specified |feature|. A feature is associated with at most one field | 
|  | // trial and selected group. See  base/feature_list.h for more information on | 
|  | // features. If the feature is not enabled, or if there's no associated params, | 
|  | // returns false and does not modify |params|. Calling this function will | 
|  | // result in the associated field trial being marked as active if found (i.e. | 
|  | // group() will be called on it), if it wasn't already. Thread safe. | 
|  | BASE_EXPORT bool GetFieldTrialParamsByFeature( | 
|  | const base::Feature& feature, | 
|  | std::map<std::string, std::string>* params); | 
|  |  | 
|  | // Retrieves a specific parameter value corresponding to |param_name| for the | 
|  | // specified field trial, based on its selected group. If the field trial does | 
|  | // not exist or the specified parameter does not exist, returns an empty | 
|  | // string. Calling this function will result in the field trial being marked as | 
|  | // active if found (i.e. group() will be called on it), if it wasn't already. | 
|  | // Thread safe. | 
|  | BASE_EXPORT std::string GetFieldTrialParamValue(const std::string& trial_name, | 
|  | const std::string& param_name); | 
|  |  | 
|  | // Retrieves a specific parameter value corresponding to |param_name| for the | 
|  | // field trial associated with the specified |feature|. A feature is associated | 
|  | // with at most one field trial and selected group. See base/feature_list.h for | 
|  | // more information on features. If the feature is not enabled, or the | 
|  | // specified parameter does not exist, returns an empty string. Calling this | 
|  | // function will result in the associated field trial being marked as active if | 
|  | // found (i.e. group() will be called on it), if it wasn't already. Thread safe. | 
|  | BASE_EXPORT std::string GetFieldTrialParamValueByFeature( | 
|  | const base::Feature& feature, | 
|  | const std::string& param_name); | 
|  |  | 
|  | // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the | 
|  | // string value into an int using base::StringToInt() and returns it, if | 
|  | // successful. Otherwise, it returns |default_value|. If the string value is not | 
|  | // empty and the conversion does not succeed, it produces a warning to LOG. | 
|  | BASE_EXPORT int GetFieldTrialParamByFeatureAsInt(const base::Feature& feature, | 
|  | const std::string& param_name, | 
|  | int default_value); | 
|  |  | 
|  | // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the | 
|  | // string value into a double using base::StringToDouble() and returns it, if | 
|  | // successful. Otherwise, it returns |default_value|. If the string value is not | 
|  | // empty and the conversion does not succeed, it produces a warning to LOG. | 
|  | BASE_EXPORT double GetFieldTrialParamByFeatureAsDouble( | 
|  | const base::Feature& feature, | 
|  | const std::string& param_name, | 
|  | double default_value); | 
|  |  | 
|  | // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the | 
|  | // string value into a boolean and returns it, if successful. Otherwise, it | 
|  | // returns |default_value|. The only string representations accepted here are | 
|  | // "true" and "false". If the string value is not empty and the conversion does | 
|  | // not succeed, it produces a warning to LOG. | 
|  | BASE_EXPORT bool GetFieldTrialParamByFeatureAsBool( | 
|  | const base::Feature& feature, | 
|  | const std::string& param_name, | 
|  | bool default_value); | 
|  |  | 
|  | // Shared declaration for various FeatureParam<T> types. | 
|  | // | 
|  | // This template is defined for the following types T: | 
|  | //   bool | 
|  | //   int | 
|  | //   double | 
|  | //   std::string | 
|  | //   enum types | 
|  | // | 
|  | // See the individual definitions below for the appropriate interfaces. | 
|  | // Attempting to use it with any other type is a compile error. | 
|  | template <typename T, bool IsEnum = std::is_enum<T>::value> | 
|  | struct FeatureParam { | 
|  | // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T | 
|  | // in its definition so that evaluation is deferred until the template is | 
|  | // instantiated. | 
|  | static_assert(!std::is_same<T, T>::value, "unsupported FeatureParam<> type"); | 
|  | }; | 
|  |  | 
|  | // Declares a string-valued parameter. Example: | 
|  | // | 
|  | //     constexpr FeatureParam<string> kAssistantName{ | 
|  | //         &kAssistantFeature, "assistant_name", "HAL"}; | 
|  | // | 
|  | // If the feature is not set, or set to the empty string, then Get() will return | 
|  | // the default value. | 
|  | template <> | 
|  | struct FeatureParam<std::string> { | 
|  | constexpr FeatureParam(const Feature* feature, | 
|  | const char* name, | 
|  | const char* default_value) | 
|  | : feature(feature), name(name), default_value(default_value) {} | 
|  |  | 
|  | BASE_EXPORT std::string Get() const; | 
|  |  | 
|  | const Feature* const feature; | 
|  | const char* const name; | 
|  | const char* const default_value; | 
|  | }; | 
|  |  | 
|  | // Declares a double-valued parameter. Example: | 
|  | // | 
|  | //     constexpr FeatureParam<double> kAssistantTriggerThreshold{ | 
|  | //         &kAssistantFeature, "trigger_threshold", 0.10}; | 
|  | // | 
|  | // If the feature is not set, or set to an invalid double value, then Get() will | 
|  | // return the default value. | 
|  | template <> | 
|  | struct FeatureParam<double> { | 
|  | constexpr FeatureParam(const Feature* feature, | 
|  | const char* name, | 
|  | double default_value) | 
|  | : feature(feature), name(name), default_value(default_value) {} | 
|  |  | 
|  | BASE_EXPORT double Get() const; | 
|  |  | 
|  | const Feature* const feature; | 
|  | const char* const name; | 
|  | const double default_value; | 
|  | }; | 
|  |  | 
|  | // Declares an int-valued parameter. Example: | 
|  | // | 
|  | //     constexpr FeatureParam<int> kAssistantParallelism{ | 
|  | //         &kAssistantFeature, "parallelism", 4}; | 
|  | // | 
|  | // If the feature is not set, or set to an invalid int value, then Get() will | 
|  | // return the default value. | 
|  | template <> | 
|  | struct FeatureParam<int> { | 
|  | constexpr FeatureParam(const Feature* feature, | 
|  | const char* name, | 
|  | int default_value) | 
|  | : feature(feature), name(name), default_value(default_value) {} | 
|  |  | 
|  | BASE_EXPORT int Get() const; | 
|  |  | 
|  | const Feature* const feature; | 
|  | const char* const name; | 
|  | const int default_value; | 
|  | }; | 
|  |  | 
|  | // Declares a bool-valued parameter. Example: | 
|  | // | 
|  | //     constexpr FeatureParam<int> kAssistantIsHelpful{ | 
|  | //         &kAssistantFeature, "is_helpful", true}; | 
|  | // | 
|  | // If the feature is not set, or set to value other than "true" or "false", then | 
|  | // Get() will return the default value. | 
|  | template <> | 
|  | struct FeatureParam<bool> { | 
|  | constexpr FeatureParam(const Feature* feature, | 
|  | const char* name, | 
|  | bool default_value) | 
|  | : feature(feature), name(name), default_value(default_value) {} | 
|  |  | 
|  | BASE_EXPORT bool Get() const; | 
|  |  | 
|  | const Feature* const feature; | 
|  | const char* const name; | 
|  | const bool default_value; | 
|  | }; | 
|  |  | 
|  | BASE_EXPORT void LogInvalidEnumValue(const Feature& feature, | 
|  | const std::string& param_name, | 
|  | const std::string& value_as_string, | 
|  | int default_value_as_int); | 
|  |  | 
|  | // Feature param declaration for an enum, with associated options. Example: | 
|  | // | 
|  | //     constexpr FeatureParam<ShapeEnum>::Option[] kShapeParamOptions[] = { | 
|  | //         {SHAPE_CIRCLE, "circle"}, | 
|  | //         {SHAPE_CYLINDER, "cylinder"}, | 
|  | //         {SHAPE_PAPERCLIP, "paperclip"}}; | 
|  | //     constexpr FeatureParam<ShapeEnum> kAssistantShapeParam{ | 
|  | //         &kAssistantFeature, "shape", SHAPE_CIRCLE, &kShapeParamOptions}; | 
|  | // | 
|  | // With this declaration, the parameter may be set to "circle", "cylinder", or | 
|  | // "paperclip", and that will be translated to one of the three enum values. By | 
|  | // default, or if the param is set to an unknown value, the parameter will be | 
|  | // assumed to be SHAPE_CIRCLE. | 
|  | template <typename Enum> | 
|  | struct FeatureParam<Enum, true> { | 
|  | struct Option { | 
|  | constexpr Option(Enum value, const char* name) : value(value), name(name) {} | 
|  |  | 
|  | const Enum value; | 
|  | const char* const name; | 
|  | }; | 
|  |  | 
|  | template <size_t option_count> | 
|  | constexpr FeatureParam(const Feature* feature, | 
|  | const char* name, | 
|  | const Enum default_value, | 
|  | const Option (*options)[option_count]) | 
|  | : feature(feature), | 
|  | name(name), | 
|  | default_value(default_value), | 
|  | options(*options), | 
|  | option_count(option_count) { | 
|  | static_assert(option_count >= 1, "FeatureParam<enum> has no options"); | 
|  | } | 
|  |  | 
|  | Enum Get() const { | 
|  | std::string value = GetFieldTrialParamValueByFeature(*feature, name); | 
|  | if (value.empty()) | 
|  | return default_value; | 
|  | for (size_t i = 0; i < option_count; ++i) { | 
|  | if (value == options[i].name) | 
|  | return options[i].value; | 
|  | } | 
|  | LogInvalidEnumValue(*feature, name, value, static_cast<int>(default_value)); | 
|  | return default_value; | 
|  | } | 
|  |  | 
|  | const base::Feature* const feature; | 
|  | const char* const name; | 
|  | const Enum default_value; | 
|  | const Option* const options; | 
|  | const size_t option_count; | 
|  | }; | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_METRICS_FIELD_TRIAL_PARAMS_H_ |