blob: 217390e057aac943e0e6b19e0c62635db223c985 [file] [log] [blame]
sdefresne0e566342015-11-24 08:55:461// 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 COMPONENTS_FLAGS_UI_FLAGS_STATE_H_
6#define COMPONENTS_FLAGS_UI_FLAGS_STATE_H_
7
avibc5337b2015-12-25 23:16:338#include <stddef.h>
9
sdefresne0e566342015-11-24 08:55:4610#include <map>
11#include <set>
12#include <string>
jkrcalbf073372016-07-29 07:21:3113#include <vector>
sdefresne0e566342015-11-24 08:55:4614
Elly Fong-Jonesc3e9aea2019-10-24 19:44:1915#include "base/callback.h"
sdefresne0e566342015-11-24 08:55:4616#include "base/command_line.h"
Elly Fong-Jones3cd75282019-11-12 20:26:5017#include "base/containers/span.h"
Elly Fong-Jonesd488661c2019-07-31 21:53:2618#include "base/feature_list.h"
Keishi Hattori0e45c022021-11-27 09:25:5219#include "base/memory/raw_ptr.h"
Morten Stenshorne7afa5802021-07-15 10:04:4320#include "base/values.h"
sdefresne0e566342015-11-24 08:55:4621
22namespace flags_ui {
23
jkrcal1383d1d2016-06-17 12:40:5624// Internal functionality exposed for tests.
25namespace internal {
26// The trial group selected when feature variation parameters are registered via
27// FlagsState::RegisterFeatureVariationParameters().
28extern const char kTrialGroupAboutFlags[];
29} // namespace internal
30
sdefresne0e566342015-11-24 08:55:4631struct FeatureEntry;
32class FlagsStorage;
33struct SwitchEntry;
34
Michael Baifee012d2021-08-11 17:13:2435// Enumeration of flag filters. These values don't persist and can be
36// renumbered.
sdefresne0e566342015-11-24 08:55:4637enum {
38 kOsMac = 1 << 0,
39 kOsWin = 1 << 1,
40 kOsLinux = 1 << 2,
41 kOsCrOS = 1 << 3,
42 kOsAndroid = 1 << 4,
sdefresneabf860062015-11-26 09:45:2243 kOsCrOSOwnerOnly = 1 << 5,
44 kOsIos = 1 << 6,
Michael Baifee012d2021-08-11 17:13:2445 kOsFuchsia = 1 << 7,
46 kOsWebView = 1 << 8,
47
48 kDeprecated = 1 << 9,
Elly Fong-Jones4054f142020-04-17 17:12:3349
50 // Flags marked with this are internal to the flags system. Never set this on
51 // a manually-added flag.
Michael Baifee012d2021-08-11 17:13:2452 kFlagInfrastructure = 1 << 10,
sdefresne0e566342015-11-24 08:55:4653};
54
55// A flag controlling the behavior of the |ConvertFlagsToSwitches| function -
56// whether it should add the sentinel switches around flags.
57enum SentinelsMode { kNoSentinels, kAddSentinels };
58
59// Differentiate between generic flags available on a per session base and flags
60// that influence the whole machine and can be said by the admin only. This flag
61// is relevant for ChromeOS for now only and dictates whether entries marked
62// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not.
noyauc8da0d22017-07-19 14:39:5263enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags };
sdefresne0e566342015-11-24 08:55:4664
65// Stores and encapsulates the little state that about:flags has.
66class FlagsState {
67 public:
Elly Fong-Jones3cd75282019-11-12 20:26:5068 // This delegate is used for embedders to configure the behavior of
69 // FlagsState. The delegate is optional.
70 class Delegate {
71 public:
72 // Returns whether |entry| should be excluded from the sets of
73 // switches/features generated by ConvertFlagsToSwitches().
Elly Fong-Jonesf8a4aa42020-08-04 15:53:3074 virtual bool ShouldExcludeFlag(const FlagsStorage* state,
75 const FeatureEntry& entry);
Elly Fong-Jones3cd75282019-11-12 20:26:5076
77 protected:
78 Delegate();
79 virtual ~Delegate();
80
81 Delegate(const Delegate&) = delete;
82 Delegate& operator=(const Delegate&) = delete;
83 };
84
85 // The delegate may be nullptr.
86 FlagsState(base::span<const FeatureEntry> feature_entries,
87 Delegate* delegate);
Peter Boström9f667c382021-10-01 20:09:3188
89 FlagsState(const FlagsState&) = delete;
90 FlagsState& operator=(const FlagsState&) = delete;
91
sdefresne0e566342015-11-24 08:55:4692 ~FlagsState();
93
jkrcal1383d1d2016-06-17 12:40:5694 // Reads the state from |flags_storage| and adds the command line flags
95 // belonging to the active feature entries to |command_line|. Features are
96 // appended via |enable_features_flag_name| and |disable_features_flag_name|.
sdefresne0e566342015-11-24 08:55:4697 void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
98 base::CommandLine* command_line,
99 SentinelsMode sentinels,
100 const char* enable_features_flag_name,
101 const char* disable_features_flag_name);
asvitkinec1a0c4f2016-08-31 20:37:39102
Elaine Chien29fce992020-12-01 17:44:34103 // Returns the FeatureEntry named |internal_name|. Returns null if no entry is
104 // matched.
105 const FeatureEntry* FindFeatureEntryByName(
106 const std::string& internal_name) const;
107
108 // Gets sanitized entries from |flags_storage|, filtering out any entries that
109 // don't exist in |feature_entries_|, and updates |flags_storage|.
110 void GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
111 std::set<std::string>* result) const;
112
Alexei Svitkine103faf82018-11-14 16:43:15113 // Reads the state from |flags_storage| and fills |switches| with the set of
114 // switches corresponding to enabled entries and |features| with the set of
115 // strings corresponding to enabled/disabled base::Feature states. Feature
116 // names are suffixed with ":enabled" or ":disabled" depending on their state.
117 void GetSwitchesAndFeaturesFromFlags(FlagsStorage* flags_storage,
118 std::set<std::string>* switches,
119 std::set<std::string>* features) const;
lawrencewu95059d1e2016-09-19 18:07:02120
sdefresne0e566342015-11-24 08:55:46121 bool IsRestartNeededToCommitChanges();
122 void SetFeatureEntryEnabled(FlagsStorage* flags_storage,
123 const std::string& internal_name,
124 bool enable);
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05125
126 // Sets |value| as the command line switch for feature given by
127 // |internal_name|. |value| contains a list of origins (serialized form of
128 // url::Origin()) separated by whitespace and/or comma. Invalid values in this
129 // list are ignored.
130 void SetOriginListFlag(const std::string& internal_name,
131 const std::string& value,
132 FlagsStorage* flags_storage);
133
Jeremy Roman863386d2017-10-31 19:25:38134 void RemoveFlagsSwitches(base::CommandLine::SwitchMap* switch_list);
sdefresne0e566342015-11-24 08:55:46135 void ResetAllFlags(FlagsStorage* flags_storage);
136 void Reset();
137
jkrcald1d20082016-07-14 15:04:24138 // Registers variations parameter values selected for features in about:flags.
139 // The selected flags are retrieved from |flags_storage|, the registered
140 // variation parameters are connected to their corresponding features in
jkrcalbf073372016-07-29 07:21:31141 // |feature_list|. Returns the (possibly empty) comma separated list of
142 // additional variation ids to register in the MetricsService that come from
143 // variations selected using chrome://flags.
144 std::vector<std::string> RegisterAllFeatureVariationParameters(
145 FlagsStorage* flags_storage,
146 base::FeatureList* feature_list);
jkrcal1383d1d2016-06-17 12:40:56147
Michael Baifee012d2021-08-11 17:13:24148 // A static version of above RegisterAllFeatureVariationParameters(), which
149 // finds the enabled feature entries from |enabled_entries| from
150 // |feature_entries|.
151 // |enabled_entries| is a set of string whose format is
152 // feature_entry_internal_name@index_of_enabled_variation, refer to
153 // FeatureEntry::NameForOption.
154 static std::vector<std::string> RegisterEnabledFeatureVariationParameters(
155 const base::span<const FeatureEntry>& feature_entries,
156 const std::set<std::string>& enabled_entries,
157 const std::string& trial_group,
158 base::FeatureList* feature_list);
159
sdefresne0e566342015-11-24 08:55:46160 // Gets the list of feature entries. Entries that are available for the
161 // current platform are appended to |supported_entries|; all other entries are
162 // appended to |unsupported_entries|.
Ken Rockot6fc4e282019-12-20 21:07:16163 //
164 // |skip_feature_entry| is called once for each feature in |feature_entries_|,
165 // and entry data for a feature is only included in the output data if the
166 // callback returns |false| for the entry.
sdefresne0e566342015-11-24 08:55:46167 void GetFlagFeatureEntries(
168 FlagsStorage* flags_storage,
169 FlagAccess access,
Morten Stenshorne7afa5802021-07-15 10:04:43170 base::Value::ListStorage& supported_entries,
171 base::Value::ListStorage& unsupported_entries,
Ken Rockot6fc4e282019-12-20 21:07:16172 base::RepeatingCallback<bool(const FeatureEntry&)> skip_feature_entry);
sdefresne0e566342015-11-24 08:55:46173
174 // Returns the value for the current platform. This is one of the values
175 // defined by the OS enum above.
176 // This is exposed only for testing.
Peter Kasting2bd21a152021-06-15 17:20:03177 static unsigned short GetCurrentPlatform();
sdefresne0e566342015-11-24 08:55:46178
sdefresne0e566342015-11-24 08:55:46179 private:
asvitkinec1a0c4f2016-08-31 20:37:39180 // Keeps track of affected switches for each FeatureEntry, based on which
181 // choice is selected for it.
182 struct SwitchEntry;
183
sdefresne0e566342015-11-24 08:55:46184 // Adds mapping to |name_to_switch_map| to set the given switch name/value.
Alexei Svitkine103faf82018-11-14 16:43:15185 void AddSwitchMapping(
186 const std::string& key,
187 const std::string& switch_name,
188 const std::string& switch_value,
189 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46190
191 // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name|
192 // to state |feature_state|.
193 void AddFeatureMapping(
194 const std::string& key,
195 const std::string& feature_name,
196 bool feature_state,
Alexei Svitkine103faf82018-11-14 16:43:15197 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46198
199 // Updates the switches in |command_line| by applying the modifications
200 // specified in |name_to_switch_map| for each entry in |enabled_entries|.
201 // |enable_features_flag_name| and |disable_features_flag_name| are switches
202 // used by the embedder to enable/disable features respectively if supported.
203 void AddSwitchesToCommandLine(
204 const std::set<std::string>& enabled_entries,
205 const std::map<std::string, SwitchEntry>& name_to_switch_map,
206 SentinelsMode sentinels,
207 base::CommandLine* command_line,
208 const char* enable_features_flag_name,
209 const char* disable_features_flag_name);
210
211 // Updates |command_line| by merging the value of the --enable-features= or
212 // --disable-features= list (per the |switch_name| param) with corresponding
213 // entries in |feature_switches| that have value |feature_state|. Keeps track
214 // of the changes by updating |appended_switches|.
215 void MergeFeatureCommandLineSwitch(
216 const std::map<std::string, bool>& feature_switches,
217 const char* switch_name,
218 bool feature_state,
219 base::CommandLine* command_line);
220
Alexei Svitkineea9e39612018-11-14 21:28:03221 // Sanitizes |enabled_entries| to only contain entries that are defined in the
222 // |feature_entries_| and whose |supported_platforms| matches |platform_mask|.
223 // Pass -1 to |platform_mask| to not do platform filtering.
224 std::set<std::string> SanitizeList(
Elly Fong-Jonesf8a4aa42020-08-04 15:53:30225 const FlagsStorage* storage,
Alexei Svitkineea9e39612018-11-14 21:28:03226 const std::set<std::string>& enabled_entries,
227 int platform_mask) const;
sdefresne0e566342015-11-24 08:55:46228
sdefresne0e566342015-11-24 08:55:46229
230 // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
231 // enabled on the current platform.
232 void GetSanitizedEnabledFlagsForCurrentPlatform(
233 FlagsStorage* flags_storage,
Alexei Svitkine103faf82018-11-14 16:43:15234 std::set<std::string>* result) const;
sdefresne0e566342015-11-24 08:55:46235
asvitkinec1a0c4f2016-08-31 20:37:39236 // Generates a flags to switches mapping based on the set of enabled flags
237 // from |flags_storage|. On output, |enabled_entries| will contain the
238 // internal names of enabled flags and |name_to_switch_map| will contain
239 // information on how they map to command-line flags or features.
Oleg Maximenko2fda7992021-08-10 09:31:41240 // When |enabled_entries| is empty |name_to_switch_map| won't be filled.
asvitkinec1a0c4f2016-08-31 20:37:39241 void GenerateFlagsToSwitchesMapping(
242 FlagsStorage* flags_storage,
cfredricfaee9972021-10-08 19:24:11243 const base::CommandLine& command_line,
asvitkinec1a0c4f2016-08-31 20:37:39244 std::set<std::string>* enabled_entries,
Alexei Svitkine103faf82018-11-14 16:43:15245 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
asvitkinec1a0c4f2016-08-31 20:37:39246
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19247 // Returns whether there is a FeatureEntry named by |name| in
248 // |feature_entries_| that:
249 // a) Is supported on this |platform_mask|, and
250 // b) Is not excluded by |exclude_predicate_|, if it is set (i.e. for which
251 // |exclude_predicate_| returns false).
Elly Fong-Jonesf8a4aa42020-08-04 15:53:30252 bool IsSupportedFeature(const FlagsStorage* storage,
253 const std::string& name,
254 int platform_mask) const;
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19255
Elly Fong-Jones3cd75282019-11-12 20:26:50256 const base::span<const FeatureEntry> feature_entries_;
sdefresne0e566342015-11-24 08:55:46257
258 bool needs_restart_;
259 std::map<std::string, std::string> flags_switches_;
260
261 // Map from switch name to a set of string, that keeps track which strings
262 // were appended to existing (list value) switches.
263 std::map<std::string, std::set<std::string>> appended_switches_;
264
Elly Fong-Jones3cd75282019-11-12 20:26:50265 // Delegate used for embedders to control display and application of flags.
266 // May be null.
Keishi Hattori0e45c022021-11-27 09:25:52267 raw_ptr<Delegate> delegate_;
sdefresne0e566342015-11-24 08:55:46268};
269
270} // namespace flags_ui
271
272#endif // COMPONENTS_FLAGS_UI_FLAGS_STATE_H_