Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: base/metrics/feature_list.h

Issue 1278403003: Initial implementation of FeatureList in base/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/metrics/BUILD.gn ('k') | base/metrics/feature_list.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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_FEATURE_LIST_H_
brettw 2015/08/31 21:26:00 I think this would actually be better in base/feat
Alexei Svitkine (slow) 2015/08/31 21:59:09 Fair enough. I guess one reason I wanted it here i
6 #define BASE_METRICS_FEATURE_LIST_H_
7
8 #include <map>
9 #include <string>
10
11 #include "base/base_export.h"
12 #include "base/basictypes.h"
13 #include "base/containers/scoped_ptr_map.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/synchronization/lock.h"
16
17 namespace base {
18
19 // The Feature struct is used to define the default state for a feature. See
20 // comment below for more details. There must only ever be one struct instance
21 // for a given feature name - generally defined as a global variable.
brettw 2015/08/31 21:26:00 maybe append "or file static" after global? I don'
Alexei Svitkine (slow) 2015/08/31 21:59:09 Done.
22 struct BASE_EXPORT Feature {
23 // The name of the feature.
brettw 2015/08/31 21:26:00 It would be nice to mention here what this is used
Alexei Svitkine (slow) 2015/08/31 21:59:09 Done.
24 const char* const name;
25
26 // The default state (i.e. enabled or disabled) for this feature.
27 const bool default_state;
28 };
29
30 // The FeatureList class is used to determine whether a given feature is on or
31 // off. It provides an authoritative answer, taking into account command-line
32 // overrides and experimental control.
33 //
34 // The basic use case is for any feature that can be toggled (e.g. through
35 // command-line or an experiment) to have a defined Feature struct, e.g.:
36 //
37 // struct base::Feature kMyGreatFeature {
38 // "MyGreatFeature", true
39 // };
40 //
41 // Then, client code that wishes to query the state of the feature would check:
42 //
43 // if (base::FeatureList::IsEnabled(kMyGreatFeature)) {
44 // // Feature code goes here.
45 // }
46 //
47 // Behind the scenes, the above call would take into account any command-line
48 // flags to enable or disable the feature, any experiments that may control it
49 // and finally its default state (in that order of priority), to determine
50 // whether the feature is on.
51 //
52 // After initial initialization (which should be done single-threaded), the
53 // FeatureList API is thread safe.
brettw 2015/08/31 21:26:00 It would be nice to give an example here of how to
Alexei Svitkine (slow) 2015/08/31 21:59:09 Added command-line examples. I think the experime
54 //
55 // Note: This class is a singleton, but does not use base/memory/singleton.h in
56 // order to have control over its initialization sequence. Specifically, the
57 // intended use is to create an instance of this class and fully initialize it,
58 // before setting it as the singleton for a process, via SetInstance().
59 class BASE_EXPORT FeatureList {
60 public:
61 FeatureList();
62 ~FeatureList();
63
64 // Initializes feature overrides via command-line flags |enable_features| and
65 // |disable_features|, each of which is a comma-separated list of features to
66 // enable or disable, respectively. If a feature appears on both lists, then
67 // it will be disabled. Must only be invoked during initialization phase
68 // (before FinalizeInitialization() has been called).
69 void InitializeFromCommandLine(const std::string& enable_features,
70 const std::string& disable_features);
71
72 // Finalizes the initialization state of the FeatureList instance, so that no
73 // further overrides can be registered. For the singleton feature list, this
74 // gets called when it is registered via SetInstance().
75 void FinalizeInitialization();
76
77 // Returns whether the given |feature| is enabled. This is member function is
78 // normally called through the static IsEnabled() function, which corresponds
79 // to GeInstance()->IsFeatureEnabled(). Must only be called on a FeatureList
80 // that has been fully initialized (FinalizeInitialization() called).
81 bool IsFeatureEnabled(const Feature& feature);
82
83 // Returns whether the given |feature| is enabled. Must only be called after
84 // the singleton instance has been registered via SetInstance(). Additionally,
85 // a feature with a given name must only have a single corresponding Feature
86 // struct, which is checked for in debug builds.
87 static bool IsEnabled(const Feature& feature);
88
89 // Returns the singleton instance of FeatureList. Will return null until an
90 // instance is registered via SetInstance().
91 static FeatureList* GetInstance();
92
93 // Registers the given |instance| to be the singleton feature list for this
94 // process. This should only be called once and |instance| must not be null.
95 static void SetInstance(scoped_ptr<FeatureList> instance);
96
97 // Clears the previously-registered singleton instance for tests.
98 static void ClearInstanceForTesting();
99
100 private:
101 FRIEND_TEST_ALL_PREFIXES(FeatureListTest, CheckFeatureIdentity);
102
103 // Registers an override for feature |feature_name|. The override specifies
104 // whether the feature should be on or off (via |overridden_state|), which
105 // will take precedence over the feature's default state.
106 void RegisterOverride(const std::string& feature_name, bool overriden_state);
107
108 // Checks whether |feature| has the same address as any previously seen
109 // Feature structs with the same name. Used only from DCHECKs and tests.
110 bool CheckFeatureIdentity(const Feature& feature);
111
112 struct OverrideEntry {
113 // The overridden enable (on/off) state of the feature.
114 bool overriden_state;
115
116 // TODO(asvitkine): Expand this as more support is added.
brettw 2015/08/31 21:26:00 I'm curious, what extra stuff are you thinking of
Alexei Svitkine (slow) 2015/08/31 21:59:09 It will come in future CLs, but mainly extra bookk
117
118 explicit OverrideEntry(bool overriden_state);
119 };
120 // Map from feature name to an OverrideEntry struct for the feature, if it
121 // exists. A ScopedPtrMap<> is used because OverrideEntry will later expand
122 // to hold additional non-copyable fields.
123 ScopedPtrMap<std::string, scoped_ptr<OverrideEntry>> overrides_;
124
125 // Locked map that keeps track of seen features, to ensure a single feature is
126 // only defined once. This verification is only done in builds with DCHECKs
127 // enabled.
128 Lock feature_identity_tracker_lock_;
129 std::map<std::string, const Feature*> feature_identity_tracker_;
130
131 // Whether this object has been fully initialized. This gets set to true as a
132 // result of FinalizeInitialization().
133 bool initialized_;
134
135 DISALLOW_COPY_AND_ASSIGN(FeatureList);
136 };
137
138 } // namespace base
139
140 #endif // BASE_METRICS_FEATURE_LIST_H_
OLDNEW
« no previous file with comments | « base/metrics/BUILD.gn ('k') | base/metrics/feature_list.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698