blob: bc1e3c6a09d2fb25b9f7286feab8f73579bbd2ed [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2015 The Chromium Authors
sdefresne0e566342015-11-24 08:55:462// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
rbpotter422d5eb2025-02-05 16:42:485#ifndef COMPONENTS_WEBUI_FLAGS_FLAGS_STATE_H_
6#define COMPONENTS_WEBUI_FLAGS_FLAGS_STATE_H_
sdefresne0e566342015-11-24 08:55:467
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
sdefresne0e566342015-11-24 08:55:4615#include "base/command_line.h"
Elly Fong-Jones3cd75282019-11-12 20:26:5016#include "base/containers/span.h"
Elly Fong-Jonesd488661c2019-07-31 21:53:2617#include "base/feature_list.h"
Avi Drissman12be0312023-01-11 09:16:0918#include "base/functional/callback.h"
Keishi Hattori0e45c022021-11-27 09:25:5219#include "base/memory/raw_ptr.h"
Ali Hijaziad8f16952024-06-17 16:27:1320#include "base/memory/raw_span.h"
Morten Stenshorne7afa5802021-07-15 10:04:4321#include "base/values.h"
sdefresne0e566342015-11-24 08:55:4622
Martin Kongcb37cf72025-01-28 18:43:4723#if BUILDFLAG(IS_ANDROID)
24#include "components/cached_flags/android/jni_delegate.h"
25#endif
26
sdefresne0e566342015-11-24 08:55:4627namespace flags_ui {
28
jkrcal1383d1d2016-06-17 12:40:5629// Internal functionality exposed for tests.
30namespace internal {
31// The trial group selected when feature variation parameters are registered via
32// FlagsState::RegisterFeatureVariationParameters().
33extern const char kTrialGroupAboutFlags[];
34} // namespace internal
35
sdefresne0e566342015-11-24 08:55:4636struct FeatureEntry;
37class FlagsStorage;
sdefresne0e566342015-11-24 08:55:4638
Michael Baifee012d2021-08-11 17:13:2439// Enumeration of flag filters. These values don't persist and can be
40// renumbered.
sdefresne0e566342015-11-24 08:55:4641enum {
42 kOsMac = 1 << 0,
43 kOsWin = 1 << 1,
44 kOsLinux = 1 << 2,
45 kOsCrOS = 1 << 3,
46 kOsAndroid = 1 << 4,
sdefresneabf860062015-11-26 09:45:2247 kOsCrOSOwnerOnly = 1 << 5,
48 kOsIos = 1 << 6,
Michael Baifee012d2021-08-11 17:13:2449 kOsFuchsia = 1 << 7,
50 kOsWebView = 1 << 8,
51
Maksim Sisov224ed982024-12-05 09:19:2452 kDeprecated = 1 << 9,
Elly Fong-Jones4054f142020-04-17 17:12:3353
54 // Flags marked with this are internal to the flags system. Never set this on
55 // a manually-added flag.
Maksim Sisov224ed982024-12-05 09:19:2456 kFlagInfrastructure = 1 << 10,
sdefresne0e566342015-11-24 08:55:4657};
58
59// A flag controlling the behavior of the |ConvertFlagsToSwitches| function -
60// whether it should add the sentinel switches around flags.
61enum SentinelsMode { kNoSentinels, kAddSentinels };
62
63// Differentiate between generic flags available on a per session base and flags
64// that influence the whole machine and can be said by the admin only. This flag
65// is relevant for ChromeOS for now only and dictates whether entries marked
66// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not.
noyauc8da0d22017-07-19 14:39:5267enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags };
sdefresne0e566342015-11-24 08:55:4668
69// Stores and encapsulates the little state that about:flags has.
70class FlagsState {
71 public:
Elly Fong-Jones3cd75282019-11-12 20:26:5072 // This delegate is used for embedders to configure the behavior of
73 // FlagsState. The delegate is optional.
74 class Delegate {
75 public:
76 // Returns whether |entry| should be excluded from the sets of
77 // switches/features generated by ConvertFlagsToSwitches().
Elly Fong-Jonesf8a4aa42020-08-04 15:53:3078 virtual bool ShouldExcludeFlag(const FlagsStorage* state,
79 const FeatureEntry& entry);
Elly Fong-Jones3cd75282019-11-12 20:26:5080
81 protected:
82 Delegate();
83 virtual ~Delegate();
84
85 Delegate(const Delegate&) = delete;
86 Delegate& operator=(const Delegate&) = delete;
87 };
88
89 // The delegate may be nullptr.
90 FlagsState(base::span<const FeatureEntry> feature_entries,
91 Delegate* delegate);
Peter Boström9f667c382021-10-01 20:09:3192
93 FlagsState(const FlagsState&) = delete;
94 FlagsState& operator=(const FlagsState&) = delete;
95
sdefresne0e566342015-11-24 08:55:4696 ~FlagsState();
97
jkrcal1383d1d2016-06-17 12:40:5698 // Reads the state from |flags_storage| and adds the command line flags
99 // belonging to the active feature entries to |command_line|. Features are
100 // appended via |enable_features_flag_name| and |disable_features_flag_name|.
sdefresne0e566342015-11-24 08:55:46101 void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
102 base::CommandLine* command_line,
103 SentinelsMode sentinels,
104 const char* enable_features_flag_name,
105 const char* disable_features_flag_name);
asvitkinec1a0c4f2016-08-31 20:37:39106
Elaine Chien29fce992020-12-01 17:44:34107 // Returns the FeatureEntry named |internal_name|. Returns null if no entry is
108 // matched.
109 const FeatureEntry* FindFeatureEntryByName(
110 const std::string& internal_name) const;
111
112 // Gets sanitized entries from |flags_storage|, filtering out any entries that
113 // don't exist in |feature_entries_|, and updates |flags_storage|.
114 void GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
115 std::set<std::string>* result) const;
116
Alexei Svitkine103faf82018-11-14 16:43:15117 // Reads the state from |flags_storage| and fills |switches| with the set of
118 // switches corresponding to enabled entries and |features| with the set of
119 // strings corresponding to enabled/disabled base::Feature states. Feature
120 // names are suffixed with ":enabled" or ":disabled" depending on their state.
Miriam Zimmermanef405f66e2022-06-03 17:22:16121 // Also fills |variation_ids| with variation IDs to force based on
122 // flags_storage, in the format of VariationsIdsProvider::ForceVariationIds().
123 void GetSwitchesAndFeaturesFromFlags(
124 FlagsStorage* flags_storage,
125 std::set<std::string>* switches,
126 std::set<std::string>* features,
127 std::set<std::string>* variation_ids) const;
lawrencewu95059d1e2016-09-19 18:07:02128
sdefresne0e566342015-11-24 08:55:46129 bool IsRestartNeededToCommitChanges();
130 void SetFeatureEntryEnabled(FlagsStorage* flags_storage,
131 const std::string& internal_name,
132 bool enable);
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05133
134 // Sets |value| as the command line switch for feature given by
135 // |internal_name|. |value| contains a list of origins (serialized form of
136 // url::Origin()) separated by whitespace and/or comma. Invalid values in this
137 // list are ignored.
138 void SetOriginListFlag(const std::string& internal_name,
139 const std::string& value,
140 FlagsStorage* flags_storage);
141
Russ Hamiltonff7639e2023-08-02 01:40:27142 // Sets |value| as the parameter for the feature given by |internal_name|.
143 // |value| contains an arbitrary string.
144 void SetStringFlag(const std::string& internal_name,
145 const std::string& value,
146 FlagsStorage* flags_storage);
147
Erik Chen92f2f0d2023-03-13 00:09:48148 // This method removes command line switches that were set by flags state.
149 // |switch_list| is an input and an output.
Jeremy Roman863386d2017-10-31 19:25:38150 void RemoveFlagsSwitches(base::CommandLine::SwitchMap* switch_list);
Erik Chen92f2f0d2023-03-13 00:09:48151
sdefresne0e566342015-11-24 08:55:46152 void ResetAllFlags(FlagsStorage* flags_storage);
153 void Reset();
154
jkrcald1d20082016-07-14 15:04:24155 // Registers variations parameter values selected for features in about:flags.
156 // The selected flags are retrieved from |flags_storage|, the registered
157 // variation parameters are connected to their corresponding features in
jkrcalbf073372016-07-29 07:21:31158 // |feature_list|. Returns the (possibly empty) comma separated list of
159 // additional variation ids to register in the MetricsService that come from
160 // variations selected using chrome://flags.
161 std::vector<std::string> RegisterAllFeatureVariationParameters(
162 FlagsStorage* flags_storage,
163 base::FeatureList* feature_list);
jkrcal1383d1d2016-06-17 12:40:56164
Michael Baifee012d2021-08-11 17:13:24165 // A static version of above RegisterAllFeatureVariationParameters(), which
166 // finds the enabled feature entries from |enabled_entries| from
167 // |feature_entries|.
168 // |enabled_entries| is a set of string whose format is
169 // feature_entry_internal_name@index_of_enabled_variation, refer to
170 // FeatureEntry::NameForOption.
171 static std::vector<std::string> RegisterEnabledFeatureVariationParameters(
172 const base::span<const FeatureEntry>& feature_entries,
173 const std::set<std::string>& enabled_entries,
174 const std::string& trial_group,
175 base::FeatureList* feature_list);
176
sdefresne0e566342015-11-24 08:55:46177 // Gets the list of feature entries. Entries that are available for the
178 // current platform are appended to |supported_entries|; all other entries are
179 // appended to |unsupported_entries|.
Ken Rockot6fc4e282019-12-20 21:07:16180 //
181 // |skip_feature_entry| is called once for each feature in |feature_entries_|,
182 // and entry data for a feature is only included in the output data if the
183 // callback returns |false| for the entry.
sdefresne0e566342015-11-24 08:55:46184 void GetFlagFeatureEntries(
185 FlagsStorage* flags_storage,
186 FlagAccess access,
Matt Menke4d777572022-06-15 15:55:50187 base::Value::List& supported_entries,
188 base::Value::List& unsupported_entries,
Ken Rockot6fc4e282019-12-20 21:07:16189 base::RepeatingCallback<bool(const FeatureEntry&)> skip_feature_entry);
sdefresne0e566342015-11-24 08:55:46190
191 // Returns the value for the current platform. This is one of the values
192 // defined by the OS enum above.
193 // This is exposed only for testing.
Peter Kasting2bd21a152021-06-15 17:20:03194 static unsigned short GetCurrentPlatform();
sdefresne0e566342015-11-24 08:55:46195
sdefresne0e566342015-11-24 08:55:46196 private:
asvitkinec1a0c4f2016-08-31 20:37:39197 // Keeps track of affected switches for each FeatureEntry, based on which
198 // choice is selected for it.
199 struct SwitchEntry;
200
sdefresne0e566342015-11-24 08:55:46201 // Adds mapping to |name_to_switch_map| to set the given switch name/value.
Alexei Svitkine103faf82018-11-14 16:43:15202 void AddSwitchMapping(
203 const std::string& key,
204 const std::string& switch_name,
205 const std::string& switch_value,
206 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46207
208 // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name|
Miriam Zimmermanef405f66e2022-06-03 17:22:16209 // to state |feature_state|, along with the given |variation_id|, in the
210 // format of VariationsIdsProvider::ForceVariationIds().
sdefresne0e566342015-11-24 08:55:46211 void AddFeatureMapping(
212 const std::string& key,
213 const std::string& feature_name,
214 bool feature_state,
Miriam Zimmermanef405f66e2022-06-03 17:22:16215 const std::string& variation_id,
Alexei Svitkine103faf82018-11-14 16:43:15216 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46217
218 // Updates the switches in |command_line| by applying the modifications
219 // specified in |name_to_switch_map| for each entry in |enabled_entries|.
220 // |enable_features_flag_name| and |disable_features_flag_name| are switches
221 // used by the embedder to enable/disable features respectively if supported.
222 void AddSwitchesToCommandLine(
223 const std::set<std::string>& enabled_entries,
224 const std::map<std::string, SwitchEntry>& name_to_switch_map,
225 SentinelsMode sentinels,
226 base::CommandLine* command_line,
227 const char* enable_features_flag_name,
228 const char* disable_features_flag_name);
229
230 // Updates |command_line| by merging the value of the --enable-features= or
231 // --disable-features= list (per the |switch_name| param) with corresponding
232 // entries in |feature_switches| that have value |feature_state|. Keeps track
233 // of the changes by updating |appended_switches|.
234 void MergeFeatureCommandLineSwitch(
235 const std::map<std::string, bool>& feature_switches,
236 const char* switch_name,
237 bool feature_state,
238 base::CommandLine* command_line);
239
Luc Nguyen95892de2022-06-27 18:32:01240 // Updates |command_line| by merging the value of the --force-variation-ids
241 // list with corresponding entries in |variation_ids|.
242 void MergeVariationIdsCommandLineSwitch(
243 const std::vector<std::string>& variation_ids,
244 base::CommandLine* command_line);
245
Alexei Svitkineea9e39612018-11-14 21:28:03246 // Sanitizes |enabled_entries| to only contain entries that are defined in the
247 // |feature_entries_| and whose |supported_platforms| matches |platform_mask|.
248 // Pass -1 to |platform_mask| to not do platform filtering.
249 std::set<std::string> SanitizeList(
Elly Fong-Jonesf8a4aa42020-08-04 15:53:30250 const FlagsStorage* storage,
Alexei Svitkineea9e39612018-11-14 21:28:03251 const std::set<std::string>& enabled_entries,
252 int platform_mask) const;
sdefresne0e566342015-11-24 08:55:46253
sdefresne0e566342015-11-24 08:55:46254 // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
255 // enabled on the current platform.
256 void GetSanitizedEnabledFlagsForCurrentPlatform(
257 FlagsStorage* flags_storage,
Alexei Svitkine103faf82018-11-14 16:43:15258 std::set<std::string>* result) const;
sdefresne0e566342015-11-24 08:55:46259
asvitkinec1a0c4f2016-08-31 20:37:39260 // Generates a flags to switches mapping based on the set of enabled flags
261 // from |flags_storage|. On output, |enabled_entries| will contain the
262 // internal names of enabled flags and |name_to_switch_map| will contain
263 // information on how they map to command-line flags or features.
Oleg Maximenko2fda7992021-08-10 09:31:41264 // When |enabled_entries| is empty |name_to_switch_map| won't be filled.
asvitkinec1a0c4f2016-08-31 20:37:39265 void GenerateFlagsToSwitchesMapping(
266 FlagsStorage* flags_storage,
cfredricfaee9972021-10-08 19:24:11267 const base::CommandLine& command_line,
asvitkinec1a0c4f2016-08-31 20:37:39268 std::set<std::string>* enabled_entries,
Alexei Svitkine103faf82018-11-14 16:43:15269 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
asvitkinec1a0c4f2016-08-31 20:37:39270
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19271 // Returns whether there is a FeatureEntry named by |name| in
272 // |feature_entries_| that:
273 // a) Is supported on this |platform_mask|, and
274 // b) Is not excluded by |exclude_predicate_|, if it is set (i.e. for which
275 // |exclude_predicate_| returns false).
Elly Fong-Jonesf8a4aa42020-08-04 15:53:30276 bool IsSupportedFeature(const FlagsStorage* storage,
277 const std::string& name,
278 int platform_mask) const;
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19279
Martin Kongcb37cf72025-01-28 18:43:47280 // Stores the flags in both FlagsStorage and SharedPreferences.
281 // Call FlagsStorage.SetFlags() to store the flags in FlagsStorage.
282 // Make the appropriate JNI calls to store the flags in SharedPreferences.
283 void SetFlags(FlagsStorage* flags_storage,
Martin Kongc97b78a2025-03-06 18:58:47284 const std::set<std::string>& enabled_flags,
285 const std::set<std::string>& prev_enabled_flags) const;
Martin Kongcb37cf72025-01-28 18:43:47286
Ali Hijaziad8f16952024-06-17 16:27:13287 const base::raw_span<const FeatureEntry> feature_entries_;
sdefresne0e566342015-11-24 08:55:46288
289 bool needs_restart_;
290 std::map<std::string, std::string> flags_switches_;
291
292 // Map from switch name to a set of string, that keeps track which strings
293 // were appended to existing (list value) switches.
294 std::map<std::string, std::set<std::string>> appended_switches_;
295
Elly Fong-Jones3cd75282019-11-12 20:26:50296 // Delegate used for embedders to control display and application of flags.
297 // May be null.
Keishi Hattori0e45c022021-11-27 09:25:52298 raw_ptr<Delegate> delegate_;
Martin Kongcb37cf72025-01-28 18:43:47299
300#if BUILDFLAG(IS_ANDROID)
301 // Delegate used by internal code to make JNI calls.
302 std::unique_ptr<cached_flags::JniDelegate> jni_delegate_;
303
304 public:
305 void SetJniDelegateForTesting(
306 std::unique_ptr<cached_flags::JniDelegate> delegate) {
307 jni_delegate_ = std::move(delegate);
308 }
309#endif
sdefresne0e566342015-11-24 08:55:46310};
311
312} // namespace flags_ui
313
rbpotter422d5eb2025-02-05 16:42:48314#endif // COMPONENTS_WEBUI_FLAGS_FLAGS_STATE_H_