feature_list.h (7802B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 // This is a cut down version of base/feature_list.h. 8 // This just returns the default state for a feature. 9 10 #ifndef BASE_FEATURE_LIST_H_ 11 #define BASE_FEATURE_LIST_H_ 12 13 namespace base { 14 15 16 // Specifies whether a given feature is enabled or disabled by default. 17 // NOTE: The actual runtime state may be different, due to a field trial or a 18 // command line switch. 19 enum FeatureState { 20 FEATURE_DISABLED_BY_DEFAULT, 21 FEATURE_ENABLED_BY_DEFAULT, 22 }; 23 24 // Recommended macros for declaring and defining features and parameters: 25 // 26 // - `kFeature` is the C++ identifier that will be used for the `base::Feature`. 27 // - `name` is the feature name, which must be globally unique. This name is 28 // used to enable/disable features via experiments and command-line flags. 29 // Names should use CamelCase-style naming, e.g. "MyGreatFeature". 30 // - `default_state` is the default state to use for the feature, i.e. 31 // `base::FEATURE_DISABLED_BY_DEFAULT` or `base::FEATURE_ENABLED_BY_DEFAULT`. 32 // As noted above, the actual runtime state may differ from the default state, 33 // due to field trials or command-line switches. 34 35 // Provides a forward declaration for `kFeature` in a header file, e.g. 36 // 37 // BASE_DECLARE_FEATURE(kMyFeature); 38 // 39 // If the feature needs to be marked as exported, i.e. it is referenced by 40 // multiple components, then write: 41 // 42 // COMPONENT_EXPORT(MY_COMPONENT) BASE_DECLARE_FEATURE(kMyFeature); 43 #define BASE_DECLARE_FEATURE(kFeature) \ 44 extern CONSTINIT const base::Feature kFeature 45 46 // Provides a definition for `kFeature` with `name` and `default_state`, e.g. 47 // 48 // BASE_FEATURE(kMyFeature, "MyFeature", base::FEATURE_DISABLED_BY_DEFAULT); 49 // 50 // Features should *not* be defined in header files; do not use this macro in 51 // header files. 52 #define BASE_FEATURE(feature, name, default_state) \ 53 CONSTINIT const base::Feature feature( \ 54 name, default_state, base::internal::FeatureMacroHandshake::kSecret) 55 56 // Provides a forward declaration for `feature_object_name` in a header file, 57 // e.g. 58 // 59 // BASE_DECLARE_FEATURE_PARAM(kMyFeatureParam); 60 // 61 // If the feature needs to be marked as exported, i.e. it is referenced by 62 // multiple components, then write: 63 // 64 // COMPONENT_EXPORT(MY_COMPONENT) BASE_DECLARE_FEATURE_PARAM(kMyFeatureParam); 65 // 66 // This macro enables optimizations to make the second and later calls faster, 67 // but requires additional memory uses. If you obtain the parameter only once, 68 // you can instantiate base::FeatureParam directly, or can call 69 // base::GetFieldTrialParamByFeatureAsInt or equivalent functions for other 70 // types directly. 71 #define BASE_DECLARE_FEATURE_PARAM(T, feature_object_name) \ 72 extern CONSTINIT const base::FeatureParam<T> feature_object_name 73 74 // Provides a definition for `feature_object_name` with `T`, `feature`, `name` 75 // and `default_value`, with an internal parsed value cache, e.g. 76 // 77 // BASE_FEATURE_PARAM(int, kMyFeatureParam, kMyFeature, "MyFeatureParam", 0); 78 // 79 // `T` is a parameter type, one of bool, int, size_t, double, std::string, and 80 // base::TimeDelta. Enum types are not supported for now. 81 // 82 // For now, ScopedFeatureList doesn't work to change the value dynamically when 83 // the cache is used with this macro. 84 // 85 // It should *not* be defined in header files; do not use this macro in header 86 // files. 87 #define BASE_FEATURE_PARAM(T, feature_object_name, feature, name, \ 88 default_value) \ 89 namespace field_trial_params_internal { \ 90 T GetFeatureParamWithCacheFor##feature_object_name( \ 91 const base::FeatureParam<T>* feature_param) { \ 92 static const typename base::internal::FeatureParamTraits< \ 93 T>::CacheStorageType storage = \ 94 base::internal::FeatureParamTraits<T>::ToCacheStorageType( \ 95 feature_param->GetWithoutCache()); \ 96 return base::internal::FeatureParamTraits<T>::FromCacheStorageType( \ 97 storage); \ 98 } \ 99 } /* field_trial_params_internal */ \ 100 CONSTINIT const base::FeatureParam<T> feature_object_name( \ 101 feature, name, default_value, \ 102 &field_trial_params_internal:: \ 103 GetFeatureParamWithCacheFor##feature_object_name) 104 105 // Same as BASE_FEATURE_PARAM() but used for enum type parameters with on extra 106 // argument, `options`. See base::FeatureParam<Enum> template declaration in 107 // //base/metrics/field_trial_params.h for `options`' details. 108 #define BASE_FEATURE_ENUM_PARAM(T, feature_object_name, feature, name, \ 109 default_value, options) \ 110 namespace field_trial_params_internal { \ 111 T GetFeatureParamWithCacheFor##feature_object_name( \ 112 const base::FeatureParam<T>* feature_param) { \ 113 static const T param = feature_param->GetWithoutCache(); \ 114 return param; \ 115 } \ 116 } /* field_trial_params_internal */ \ 117 CONSTINIT const base::FeatureParam<T> feature_object_name( \ 118 feature, name, default_value, options, \ 119 &field_trial_params_internal:: \ 120 GetFeatureParamWithCacheFor##feature_object_name) 121 122 // Secret handshake to (try to) ensure all places that construct a base::Feature 123 // go through the helper `BASE_FEATURE()` macro above. 124 namespace internal { 125 enum class FeatureMacroHandshake { kSecret }; 126 } 127 128 // The Feature struct is used to define the default state for a feature. See 129 // comment below for more details. There must only ever be one struct instance 130 // for a given feature name - generally defined as a constant global variable or 131 // file static. It should never be used as a constexpr as it breaks 132 // pointer-based identity lookup. 133 struct BASE_EXPORT Feature { 134 constexpr Feature(const char* name, FeatureState default_state, 135 internal::FeatureMacroHandshake) 136 : name(name), default_state(default_state) { 137 } 138 139 // Non-copyable since: 140 // - there should be only one `Feature` instance per unique name. 141 // - a `Feature` contains internal cached state about the override state. 142 Feature(const Feature&) = delete; 143 Feature& operator=(const Feature&) = delete; 144 145 // The name of the feature. This should be unique to each feature and is used 146 // for enabling/disabling features via command line flags and experiments. 147 // It is strongly recommended to use CamelCase style for feature names, e.g. 148 // "MyGreatFeature". 149 const char* const name; 150 151 // The default state (i.e. enabled or disabled) for this feature. 152 const FeatureState default_state; 153 }; 154 155 class BASE_EXPORT FeatureList { 156 public: 157 static bool IsEnabled(const Feature& feature) { 158 return feature.default_state == FEATURE_ENABLED_BY_DEFAULT; 159 } 160 161 static FeatureList* GetInstance() { return nullptr; } 162 163 FeatureList(const FeatureList&) = delete; 164 FeatureList& operator=(const FeatureList&) = delete; 165 }; 166 167 } // namespace base 168 169 #endif // BASE_FEATURE_LIST_H_