blob: 14a2ca9d0b236ce5397d4e6c2af308da3f09a1a6 [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"
sdefresne0e566342015-11-24 08:55:4619#include "base/macros.h"
20
21namespace base {
22class ListValue;
23}
24
25namespace flags_ui {
26
jkrcal1383d1d2016-06-17 12:40:5627// Internal functionality exposed for tests.
28namespace internal {
29// The trial group selected when feature variation parameters are registered via
30// FlagsState::RegisterFeatureVariationParameters().
31extern const char kTrialGroupAboutFlags[];
32} // namespace internal
33
sdefresne0e566342015-11-24 08:55:4634struct FeatureEntry;
35class FlagsStorage;
36struct SwitchEntry;
37
Yann Dagobaa08aa2019-07-29 20:52:3738// Enumeration of flag filters.
sdefresne0e566342015-11-24 08:55:4639enum {
40 kOsMac = 1 << 0,
41 kOsWin = 1 << 1,
42 kOsLinux = 1 << 2,
43 kOsCrOS = 1 << 3,
44 kOsAndroid = 1 << 4,
sdefresneabf860062015-11-26 09:45:2245 kOsCrOSOwnerOnly = 1 << 5,
46 kOsIos = 1 << 6,
Yann Dago78028712019-09-04 15:23:5447 kDeprecated = 1 << 7,
Wez04eb259f2019-09-16 19:41:5948 kOsFuchsia = 1 << 8,
sdefresne0e566342015-11-24 08:55:4649};
50
51// A flag controlling the behavior of the |ConvertFlagsToSwitches| function -
52// whether it should add the sentinel switches around flags.
53enum SentinelsMode { kNoSentinels, kAddSentinels };
54
55// Differentiate between generic flags available on a per session base and flags
56// that influence the whole machine and can be said by the admin only. This flag
57// is relevant for ChromeOS for now only and dictates whether entries marked
58// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not.
noyauc8da0d22017-07-19 14:39:5259enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags };
sdefresne0e566342015-11-24 08:55:4660
61// Stores and encapsulates the little state that about:flags has.
62class FlagsState {
63 public:
Elly Fong-Jones3cd75282019-11-12 20:26:5064 // This delegate is used for embedders to configure the behavior of
65 // FlagsState. The delegate is optional.
66 class Delegate {
67 public:
68 // Returns whether |entry| should be excluded from the sets of
69 // switches/features generated by ConvertFlagsToSwitches().
70 virtual bool ShouldExcludeFlag(const FeatureEntry& entry);
71
72 protected:
73 Delegate();
74 virtual ~Delegate();
75
76 Delegate(const Delegate&) = delete;
77 Delegate& operator=(const Delegate&) = delete;
78 };
79
80 // The delegate may be nullptr.
81 FlagsState(base::span<const FeatureEntry> feature_entries,
82 Delegate* delegate);
sdefresne0e566342015-11-24 08:55:4683 ~FlagsState();
84
jkrcal1383d1d2016-06-17 12:40:5685 // Reads the state from |flags_storage| and adds the command line flags
86 // belonging to the active feature entries to |command_line|. Features are
87 // appended via |enable_features_flag_name| and |disable_features_flag_name|.
sdefresne0e566342015-11-24 08:55:4688 void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
89 base::CommandLine* command_line,
90 SentinelsMode sentinels,
91 const char* enable_features_flag_name,
92 const char* disable_features_flag_name);
asvitkinec1a0c4f2016-08-31 20:37:3993
Alexei Svitkine103faf82018-11-14 16:43:1594 // Reads the state from |flags_storage| and fills |switches| with the set of
95 // switches corresponding to enabled entries and |features| with the set of
96 // strings corresponding to enabled/disabled base::Feature states. Feature
97 // names are suffixed with ":enabled" or ":disabled" depending on their state.
98 void GetSwitchesAndFeaturesFromFlags(FlagsStorage* flags_storage,
99 std::set<std::string>* switches,
100 std::set<std::string>* features) const;
lawrencewu95059d1e2016-09-19 18:07:02101
sdefresne0e566342015-11-24 08:55:46102 bool IsRestartNeededToCommitChanges();
103 void SetFeatureEntryEnabled(FlagsStorage* flags_storage,
104 const std::string& internal_name,
105 bool enable);
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05106
107 // Sets |value| as the command line switch for feature given by
108 // |internal_name|. |value| contains a list of origins (serialized form of
109 // url::Origin()) separated by whitespace and/or comma. Invalid values in this
110 // list are ignored.
111 void SetOriginListFlag(const std::string& internal_name,
112 const std::string& value,
113 FlagsStorage* flags_storage);
114
Jeremy Roman863386d2017-10-31 19:25:38115 void RemoveFlagsSwitches(base::CommandLine::SwitchMap* switch_list);
sdefresne0e566342015-11-24 08:55:46116 void ResetAllFlags(FlagsStorage* flags_storage);
117 void Reset();
118
jkrcald1d20082016-07-14 15:04:24119 // Registers variations parameter values selected for features in about:flags.
120 // The selected flags are retrieved from |flags_storage|, the registered
121 // variation parameters are connected to their corresponding features in
jkrcalbf073372016-07-29 07:21:31122 // |feature_list|. Returns the (possibly empty) comma separated list of
123 // additional variation ids to register in the MetricsService that come from
124 // variations selected using chrome://flags.
125 std::vector<std::string> RegisterAllFeatureVariationParameters(
126 FlagsStorage* flags_storage,
127 base::FeatureList* feature_list);
jkrcal1383d1d2016-06-17 12:40:56128
sdefresne0e566342015-11-24 08:55:46129 // Gets the list of feature entries. Entries that are available for the
130 // current platform are appended to |supported_entries|; all other entries are
131 // appended to |unsupported_entries|.
132 void GetFlagFeatureEntries(
133 FlagsStorage* flags_storage,
134 FlagAccess access,
135 base::ListValue* supported_entries,
136 base::ListValue* unsupported_entries,
137 base::Callback<bool(const FeatureEntry&)> skip_feature_entry);
138
139 // Returns the value for the current platform. This is one of the values
140 // defined by the OS enum above.
141 // This is exposed only for testing.
142 static int GetCurrentPlatform();
143
144 // Compares a set of switches of the two provided command line objects and
145 // returns true if they are the same and false otherwise.
146 // If |out_difference| is not NULL, it's filled with set_symmetric_difference
147 // between sets.
148 // Only switches between --flag-switches-begin and --flag-switches-end are
149 // compared. The embedder may use |extra_flag_sentinel_begin_flag_name| and
150 // |extra_sentinel_end_flag_name| to specify other delimiters, if supported.
151 static bool AreSwitchesIdenticalToCurrentCommandLine(
152 const base::CommandLine& new_cmdline,
153 const base::CommandLine& active_cmdline,
154 std::set<base::CommandLine::StringType>* out_difference,
155 const char* extra_flag_sentinel_begin_flag_name,
156 const char* extra_flag_sentinel_end_flag_name);
157
158 private:
asvitkinec1a0c4f2016-08-31 20:37:39159 // Keeps track of affected switches for each FeatureEntry, based on which
160 // choice is selected for it.
161 struct SwitchEntry;
162
sdefresne0e566342015-11-24 08:55:46163 // Adds mapping to |name_to_switch_map| to set the given switch name/value.
Alexei Svitkine103faf82018-11-14 16:43:15164 void AddSwitchMapping(
165 const std::string& key,
166 const std::string& switch_name,
167 const std::string& switch_value,
168 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46169
170 // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name|
171 // to state |feature_state|.
172 void AddFeatureMapping(
173 const std::string& key,
174 const std::string& feature_name,
175 bool feature_state,
Alexei Svitkine103faf82018-11-14 16:43:15176 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
sdefresne0e566342015-11-24 08:55:46177
178 // Updates the switches in |command_line| by applying the modifications
179 // specified in |name_to_switch_map| for each entry in |enabled_entries|.
180 // |enable_features_flag_name| and |disable_features_flag_name| are switches
181 // used by the embedder to enable/disable features respectively if supported.
182 void AddSwitchesToCommandLine(
183 const std::set<std::string>& enabled_entries,
184 const std::map<std::string, SwitchEntry>& name_to_switch_map,
185 SentinelsMode sentinels,
186 base::CommandLine* command_line,
187 const char* enable_features_flag_name,
188 const char* disable_features_flag_name);
189
190 // Updates |command_line| by merging the value of the --enable-features= or
191 // --disable-features= list (per the |switch_name| param) with corresponding
192 // entries in |feature_switches| that have value |feature_state|. Keeps track
193 // of the changes by updating |appended_switches|.
194 void MergeFeatureCommandLineSwitch(
195 const std::map<std::string, bool>& feature_switches,
196 const char* switch_name,
197 bool feature_state,
198 base::CommandLine* command_line);
199
Alexei Svitkineea9e39612018-11-14 21:28:03200 // Sanitizes |enabled_entries| to only contain entries that are defined in the
201 // |feature_entries_| and whose |supported_platforms| matches |platform_mask|.
202 // Pass -1 to |platform_mask| to not do platform filtering.
203 std::set<std::string> SanitizeList(
204 const std::set<std::string>& enabled_entries,
205 int platform_mask) const;
sdefresne0e566342015-11-24 08:55:46206
Alexei Svitkineea9e39612018-11-14 21:28:03207 // Gets sanitized entries from |flags_storage|, filtering out any entries that
208 // don't exist in |feature_entries_|, and updates |flags_storage|.
sdefresne0e566342015-11-24 08:55:46209 void GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
Alexei Svitkine103faf82018-11-14 16:43:15210 std::set<std::string>* result) const;
sdefresne0e566342015-11-24 08:55:46211
212 // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
213 // enabled on the current platform.
214 void GetSanitizedEnabledFlagsForCurrentPlatform(
215 FlagsStorage* flags_storage,
Alexei Svitkine103faf82018-11-14 16:43:15216 std::set<std::string>* result) const;
sdefresne0e566342015-11-24 08:55:46217
asvitkinec1a0c4f2016-08-31 20:37:39218 // Generates a flags to switches mapping based on the set of enabled flags
219 // from |flags_storage|. On output, |enabled_entries| will contain the
220 // internal names of enabled flags and |name_to_switch_map| will contain
221 // information on how they map to command-line flags or features.
222 void GenerateFlagsToSwitchesMapping(
223 FlagsStorage* flags_storage,
224 std::set<std::string>* enabled_entries,
Alexei Svitkine103faf82018-11-14 16:43:15225 std::map<std::string, SwitchEntry>* name_to_switch_map) const;
asvitkinec1a0c4f2016-08-31 20:37:39226
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05227 // Returns the FeatureEntry named |internal_name|. Returns null if no entry is
228 // matched.
229 const FeatureEntry* FindFeatureEntryByName(
230 const std::string& internal_name) const;
231
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19232 // Returns whether there is a FeatureEntry named by |name| in
233 // |feature_entries_| that:
234 // a) Is supported on this |platform_mask|, and
235 // b) Is not excluded by |exclude_predicate_|, if it is set (i.e. for which
236 // |exclude_predicate_| returns false).
237 bool IsSupportedFeature(const std::string& name, int platform_mask) const;
238
Elly Fong-Jones3cd75282019-11-12 20:26:50239 const base::span<const FeatureEntry> feature_entries_;
sdefresne0e566342015-11-24 08:55:46240
241 bool needs_restart_;
242 std::map<std::string, std::string> flags_switches_;
243
244 // Map from switch name to a set of string, that keeps track which strings
245 // were appended to existing (list value) switches.
246 std::map<std::string, std::set<std::string>> appended_switches_;
247
Elly Fong-Jones3cd75282019-11-12 20:26:50248 // Delegate used for embedders to control display and application of flags.
249 // May be null.
250 Delegate* delegate_;
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19251
sdefresne0e566342015-11-24 08:55:46252 DISALLOW_COPY_AND_ASSIGN(FlagsState);
253};
254
255} // namespace flags_ui
256
257#endif // COMPONENTS_FLAGS_UI_FLAGS_STATE_H_