blob: 06fef2a2ba40ab4095475ee3d5825f0889188d1e [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,
Fred Shih87e6a562022-04-13 19:51:5147 kOsLacros = 1 << 9,
Michael Baifee012d2021-08-11 17:13:2448
Fred Shih87e6a562022-04-13 19:51:5149 kDeprecated = 1 << 10,
Elly Fong-Jones4054f142020-04-17 17:12:3350
51 // Flags marked with this are internal to the flags system. Never set this on
52 // a manually-added flag.
Fred Shih87e6a562022-04-13 19:51:5153 kFlagInfrastructure = 1 << 11,
sdefresne0e566342015-11-24 08:55:4654};
55
56// A flag controlling the behavior of the |ConvertFlagsToSwitches| function -
57// whether it should add the sentinel switches around flags.
58enum SentinelsMode { kNoSentinels, kAddSentinels };
59
60// Differentiate between generic flags available on a per session base and flags
61// that influence the whole machine and can be said by the admin only. This flag
62// is relevant for ChromeOS for now only and dictates whether entries marked
63// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not.
noyauc8da0d22017-07-19 14:39:5264enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags };
sdefresne0e566342015-11-24 08:55:4665
66// Stores and encapsulates the little state that about:flags has.
67class FlagsState {
68 public:
Elly Fong-Jones3cd75282019-11-12 20:26:5069 // This delegate is used for embedders to configure the behavior of
70 // FlagsState. The delegate is optional.
71 class Delegate {
72 public:
73 // Returns whether |entry| should be excluded from the sets of
74 // switches/features generated by ConvertFlagsToSwitches().
Elly Fong-Jonesf8a4aa42020-08-04 15:53:3075 virtual bool ShouldExcludeFlag(const FlagsStorage* state,
76 const FeatureEntry& entry);
Elly Fong-Jones3cd75282019-11-12 20:26:5077
78 protected:
79 Delegate();
80 virtual ~Delegate();
81
82 Delegate(const Delegate&) = delete;
83 Delegate& operator=(const Delegate&) = delete;
84 };
85
86 // The delegate may be nullptr.
87 FlagsState(base::span<const FeatureEntry> feature_entries,
88 Delegate* delegate);
Peter Boström9f667c382021-10-01 20:09:3189
90 FlagsState(const FlagsState&) = delete;
91 FlagsState& operator=(const FlagsState&) = delete;
92
sdefresne0e566342015-11-24 08:55:4693 ~FlagsState();
94
jkrcal1383d1d2016-06-17 12:40:5695 // Reads the state from |flags_storage| and adds the command line flags
96 // belonging to the active feature entries to |command_line|. Features are
97 // appended via |enable_features_flag_name| and |disable_features_flag_name|.
sdefresne0e566342015-11-24 08:55:4698 void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
99 base::CommandLine* command_line,
100 SentinelsMode sentinels,
101 const char* enable_features_flag_name,
102 const char* disable_features_flag_name);
asvitkinec1a0c4f2016-08-31 20:37:39103
Elaine Chien29fce992020-12-01 17:44:34104 // Returns the FeatureEntry named |internal_name|. Returns null if no entry is
105 // matched.
106 const FeatureEntry* FindFeatureEntryByName(
107 const std::string& internal_name) const;
108
109 // Gets sanitized entries from |flags_storage|, filtering out any entries that
110 // don't exist in |feature_entries_|, and updates |flags_storage|.
111 void GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
112 std::set<std::string>* result) const;
113
Alexei Svitkine103faf82018-11-14 16:43:15114 // Reads the state from |flags_storage| and fills |switches| with the set of
115 // switches corresponding to enabled entries and |features| with the set of
116 // strings corresponding to enabled/disabled base::Feature states. Feature
117 // names are suffixed with ":enabled" or ":disabled" depending on their state.
Miriam Zimmermanef405f66e2022-06-03 17:22:16118 // Also fills |variation_ids| with variation IDs to force based on
119 // flags_storage, in the format of VariationsIdsProvider::ForceVariationIds().
120 void GetSwitchesAndFeaturesFromFlags(
121 FlagsStorage* flags_storage,
122 std::set<std::string>* switches,
123 std::set<std::string>* features,
124 std::set<std::string>* variation_ids) const;
lawrencewu95059d1e2016-09-19 18:07:02125
sdefresne0e566342015-11-24 08:55:46126 bool IsRestartNeededToCommitChanges();
127 void SetFeatureEntryEnabled(FlagsStorage* flags_storage,
128 const std::string& internal_name,
129 bool enable);
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05130
131 // Sets |value| as the command line switch for feature given by
132 // |internal_name|. |value| contains a list of origins (serialized form of
133 // url::Origin()) separated by whitespace and/or comma. Invalid values in this
134 // list are ignored.
135 void SetOriginListFlag(const std::string& internal_name,
136 const std::string& value,
137 FlagsStorage* flags_storage);
138
Jeremy Roman863386d2017-10-31 19:25:38139 void RemoveFlagsSwitches(base::CommandLine::SwitchMap* switch_list);
sdefresne0e566342015-11-24 08:55:46140 void ResetAllFlags(FlagsStorage* flags_storage);
141 void Reset();
142
jkrcald1d20082016-07-14 15:04:24143 // Registers variations parameter values selected for features in about:flags.
144 // The selected flags are retrieved from |flags_storage|, the registered
145 // variation parameters are connected to their corresponding features in
jkrcalbf073372016-07-29 07:21:31146 // |feature_list|. Returns the (possibly empty) comma separated list of
147 // additional variation ids to register in the MetricsService that come from
148 // variations selected using chrome://flags.
149 std::vector<std::string> RegisterAllFeatureVariationParameters(
150 FlagsStorage* flags_storage,
151 base::FeatureList* feature_list);
jkrcal1383d1d2016-06-17 12:40:56152
Michael Baifee012d2021-08-11 17:13:24153 // A static version of above RegisterAllFeatureVariationParameters(), which
154 // finds the enabled feature entries from |enabled_entries| from
155 // |feature_entries|.
156 // |enabled_entries| is a set of string whose format is
157 // feature_entry_internal_name@index_of_enabled_variation, refer to
158 // FeatureEntry::NameForOption.
159 static std::vector<std::string> RegisterEnabledFeatureVariationParameters(
160 const base::span<const FeatureEntry>& feature_entries,
161 const std::set<std::string>& enabled_entries,
162 const std::string& trial_group,
163 base::FeatureList* feature_list);
164
sdefresne0e566342015-11-24 08:55:46165 // Gets the list of feature entries. Entries that are available for the
166 // current platform are appended to |supported_entries|; all other entries are
167 // appended to |unsupported_entries|.
Ken Rockot6fc4e282019-12-20 21:07:16168 //
169 // |skip_feature_entry| is called once for each feature in |feature_entries_|,
170 // and entry data for a feature is only included in the output data if the
171 // callback returns |false| for the entry.
sdefresne0e566342015-11-24 08:55:46172 void GetFlagFeatureEntries(
173 FlagsStorage* flags_storage,
174 FlagAccess access,
Matt Menke4d777572022-06-15 15:55:50175 base::Value::List& supported_entries,
176 base::Value::List& unsupported_entries,
Ken Rockot6fc4e282019-12-20 21:07:16177 base::RepeatingCallback<bool(const FeatureEntry&)> skip_feature_entry);
sdefresne0e566342015-11-24 08:55:46178
179 // Returns the value for the current platform. This is one of the values
180 // defined by the OS enum above.
181 // This is exposed only for testing.
Peter Kasting2bd21a152021-06-15 17:20:03182 static unsigned short GetCurrentPlatform();
sdefresne0e566342015-11-24 08:55:46183
sdefresne0e566342015-11-24 08:55:46184 private:
asvitkinec1a0c4f2016-08-31 20:37:39185 // Keeps track of affected switches for each FeatureEntry, based on which
186 // choice is selected for it.
187 struct SwitchEntry;
188
sdefresne0e566342015-11-24 08:55:46189 // Adds mapping to |name_to_switch_map| to set the given switch name/value.
Alexei Svitkine103faf82018-11-14 16:43:15190 void AddSwitchMapping(
191 const std::string& key,
192 const std::string& switch_name,
193 const std::string& switch_value,
194 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46195
196 // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name|
Miriam Zimmermanef405f66e2022-06-03 17:22:16197 // to state |feature_state|, along with the given |variation_id|, in the
198 // format of VariationsIdsProvider::ForceVariationIds().
sdefresne0e566342015-11-24 08:55:46199 void AddFeatureMapping(
200 const std::string& key,
201 const std::string& feature_name,
202 bool feature_state,
Miriam Zimmermanef405f66e2022-06-03 17:22:16203 const std::string& variation_id,
Alexei Svitkine103faf82018-11-14 16:43:15204 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46205
206 // Updates the switches in |command_line| by applying the modifications
207 // specified in |name_to_switch_map| for each entry in |enabled_entries|.
208 // |enable_features_flag_name| and |disable_features_flag_name| are switches
209 // used by the embedder to enable/disable features respectively if supported.
210 void AddSwitchesToCommandLine(
211 const std::set<std::string>& enabled_entries,
212 const std::map<std::string, SwitchEntry>& name_to_switch_map,
213 SentinelsMode sentinels,
214 base::CommandLine* command_line,
215 const char* enable_features_flag_name,
216 const char* disable_features_flag_name);
217
218 // Updates |command_line| by merging the value of the --enable-features= or
219 // --disable-features= list (per the |switch_name| param) with corresponding
220 // entries in |feature_switches| that have value |feature_state|. Keeps track
221 // of the changes by updating |appended_switches|.
222 void MergeFeatureCommandLineSwitch(
223 const std::map<std::string, bool>& feature_switches,
224 const char* switch_name,
225 bool feature_state,
226 base::CommandLine* command_line);
227
Alexei Svitkineea9e39612018-11-14 21:28:03228 // Sanitizes |enabled_entries| to only contain entries that are defined in the
229 // |feature_entries_| and whose |supported_platforms| matches |platform_mask|.
230 // Pass -1 to |platform_mask| to not do platform filtering.
231 std::set<std::string> SanitizeList(
Elly Fong-Jonesf8a4aa42020-08-04 15:53:30232 const FlagsStorage* storage,
Alexei Svitkineea9e39612018-11-14 21:28:03233 const std::set<std::string>& enabled_entries,
234 int platform_mask) const;
sdefresne0e566342015-11-24 08:55:46235
sdefresne0e566342015-11-24 08:55:46236
237 // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
238 // enabled on the current platform.
239 void GetSanitizedEnabledFlagsForCurrentPlatform(
240 FlagsStorage* flags_storage,
Alexei Svitkine103faf82018-11-14 16:43:15241 std::set<std::string>* result) const;
sdefresne0e566342015-11-24 08:55:46242
asvitkinec1a0c4f2016-08-31 20:37:39243 // Generates a flags to switches mapping based on the set of enabled flags
244 // from |flags_storage|. On output, |enabled_entries| will contain the
245 // internal names of enabled flags and |name_to_switch_map| will contain
246 // information on how they map to command-line flags or features.
Oleg Maximenko2fda7992021-08-10 09:31:41247 // When |enabled_entries| is empty |name_to_switch_map| won't be filled.
asvitkinec1a0c4f2016-08-31 20:37:39248 void GenerateFlagsToSwitchesMapping(
249 FlagsStorage* flags_storage,
cfredricfaee9972021-10-08 19:24:11250 const base::CommandLine& command_line,
asvitkinec1a0c4f2016-08-31 20:37:39251 std::set<std::string>* enabled_entries,
Alexei Svitkine103faf82018-11-14 16:43:15252 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
asvitkinec1a0c4f2016-08-31 20:37:39253
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19254 // Returns whether there is a FeatureEntry named by |name| in
255 // |feature_entries_| that:
256 // a) Is supported on this |platform_mask|, and
257 // b) Is not excluded by |exclude_predicate_|, if it is set (i.e. for which
258 // |exclude_predicate_| returns false).
Elly Fong-Jonesf8a4aa42020-08-04 15:53:30259 bool IsSupportedFeature(const FlagsStorage* storage,
260 const std::string& name,
261 int platform_mask) const;
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19262
Elly Fong-Jones3cd75282019-11-12 20:26:50263 const base::span<const FeatureEntry> feature_entries_;
sdefresne0e566342015-11-24 08:55:46264
265 bool needs_restart_;
266 std::map<std::string, std::string> flags_switches_;
267
268 // Map from switch name to a set of string, that keeps track which strings
269 // were appended to existing (list value) switches.
270 std::map<std::string, std::set<std::string>> appended_switches_;
271
Elly Fong-Jones3cd75282019-11-12 20:26:50272 // Delegate used for embedders to control display and application of flags.
273 // May be null.
Keishi Hattori0e45c022021-11-27 09:25:52274 raw_ptr<Delegate> delegate_;
sdefresne0e566342015-11-24 08:55:46275};
276
277} // namespace flags_ui
278
279#endif // COMPONENTS_FLAGS_UI_FLAGS_STATE_H_