1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_WEBUI_FLAGS_FLAGS_STATE_H_
#define COMPONENTS_WEBUI_FLAGS_FLAGS_STATE_H_
#include <stddef.h>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_span.h"
#include "base/values.h"
#if BUILDFLAG(IS_ANDROID)
#include "components/cached_flags/android/jni_delegate.h"
#endif
namespace flags_ui {
// Internal functionality exposed for tests.
namespace internal {
// The trial group selected when feature variation parameters are registered via
// FlagsState::RegisterFeatureVariationParameters().
extern const char kTrialGroupAboutFlags[];
} // namespace internal
struct FeatureEntry;
class FlagsStorage;
// Enumeration of flag filters. These values don't persist and can be
// renumbered.
enum {
kOsMac = 1 << 0,
kOsWin = 1 << 1,
kOsLinux = 1 << 2,
kOsCrOS = 1 << 3,
kOsAndroid = 1 << 4,
kOsCrOSOwnerOnly = 1 << 5,
kOsIos = 1 << 6,
kOsFuchsia = 1 << 7,
kOsWebView = 1 << 8,
kDeprecated = 1 << 9,
// Flags marked with this are internal to the flags system. Never set this on
// a manually-added flag.
kFlagInfrastructure = 1 << 10,
};
// A flag controlling the behavior of the |ConvertFlagsToSwitches| function -
// whether it should add the sentinel switches around flags.
enum SentinelsMode { kNoSentinels, kAddSentinels };
// Differentiate between generic flags available on a per session base and flags
// that influence the whole machine and can be said by the admin only. This flag
// is relevant for ChromeOS for now only and dictates whether entries marked
// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not.
enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags };
// Stores and encapsulates the little state that about:flags has.
class FlagsState {
public:
// This delegate is used for embedders to configure the behavior of
// FlagsState. The delegate is optional.
class Delegate {
public:
// Returns whether |entry| should be excluded from the sets of
// switches/features generated by ConvertFlagsToSwitches().
virtual bool ShouldExcludeFlag(const FlagsStorage* state,
const FeatureEntry& entry);
protected:
Delegate();
virtual ~Delegate();
Delegate(const Delegate&) = delete;
Delegate& operator=(const Delegate&) = delete;
};
// The delegate may be nullptr.
FlagsState(base::span<const FeatureEntry> feature_entries,
Delegate* delegate);
FlagsState(const FlagsState&) = delete;
FlagsState& operator=(const FlagsState&) = delete;
~FlagsState();
// Reads the state from |flags_storage| and adds the command line flags
// belonging to the active feature entries to |command_line|. Features are
// appended via |enable_features_flag_name| and |disable_features_flag_name|.
void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
base::CommandLine* command_line,
SentinelsMode sentinels,
const char* enable_features_flag_name,
const char* disable_features_flag_name);
// Returns the FeatureEntry named |internal_name|. Returns null if no entry is
// matched.
const FeatureEntry* FindFeatureEntryByName(
const std::string& internal_name) const;
// Gets sanitized entries from |flags_storage|, filtering out any entries that
// don't exist in |feature_entries_|, and updates |flags_storage|.
void GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
std::set<std::string>* result) const;
// Reads the state from |flags_storage| and fills |switches| with the set of
// switches corresponding to enabled entries and |features| with the set of
// strings corresponding to enabled/disabled base::Feature states. Feature
// names are suffixed with ":enabled" or ":disabled" depending on their state.
// Also fills |variation_ids| with variation IDs to force based on
// flags_storage, in the format of VariationsIdsProvider::ForceVariationIds().
void GetSwitchesAndFeaturesFromFlags(
FlagsStorage* flags_storage,
std::set<std::string>* switches,
std::set<std::string>* features,
std::set<std::string>* variation_ids) const;
bool IsRestartNeededToCommitChanges();
void SetFeatureEntryEnabled(FlagsStorage* flags_storage,
const std::string& internal_name,
bool enable);
// Sets |value| as the command line switch for feature given by
// |internal_name|. |value| contains a list of origins (serialized form of
// url::Origin()) separated by whitespace and/or comma. Invalid values in this
// list are ignored.
void SetOriginListFlag(const std::string& internal_name,
const std::string& value,
FlagsStorage* flags_storage);
// Sets |value| as the parameter for the feature given by |internal_name|.
// |value| contains an arbitrary string.
void SetStringFlag(const std::string& internal_name,
const std::string& value,
FlagsStorage* flags_storage);
// This method removes command line switches that were set by flags state.
// |switch_list| is an input and an output.
void RemoveFlagsSwitches(base::CommandLine::SwitchMap* switch_list);
void ResetAllFlags(FlagsStorage* flags_storage);
void Reset();
// Registers variations parameter values selected for features in about:flags.
// The selected flags are retrieved from |flags_storage|, the registered
// variation parameters are connected to their corresponding features in
// |feature_list|. Returns the (possibly empty) comma separated list of
// additional variation ids to register in the MetricsService that come from
// variations selected using chrome://flags.
std::vector<std::string> RegisterAllFeatureVariationParameters(
FlagsStorage* flags_storage,
base::FeatureList* feature_list);
// A static version of above RegisterAllFeatureVariationParameters(), which
// finds the enabled feature entries from |enabled_entries| from
// |feature_entries|.
// |enabled_entries| is a set of string whose format is
// feature_entry_internal_name@index_of_enabled_variation, refer to
// FeatureEntry::NameForOption.
static std::vector<std::string> RegisterEnabledFeatureVariationParameters(
const base::span<const FeatureEntry>& feature_entries,
const std::set<std::string>& enabled_entries,
const std::string& trial_group,
base::FeatureList* feature_list);
// Gets the list of feature entries. Entries that are available for the
// current platform are appended to |supported_entries|; all other entries are
// appended to |unsupported_entries|.
//
// |skip_feature_entry| is called once for each feature in |feature_entries_|,
// and entry data for a feature is only included in the output data if the
// callback returns |false| for the entry.
void GetFlagFeatureEntries(
FlagsStorage* flags_storage,
FlagAccess access,
base::Value::List& supported_entries,
base::Value::List& unsupported_entries,
base::RepeatingCallback<bool(const FeatureEntry&)> skip_feature_entry);
// Returns the value for the current platform. This is one of the values
// defined by the OS enum above.
// This is exposed only for testing.
static unsigned short GetCurrentPlatform();
private:
// Keeps track of affected switches for each FeatureEntry, based on which
// choice is selected for it.
struct SwitchEntry;
// Adds mapping to |name_to_switch_map| to set the given switch name/value.
void AddSwitchMapping(
const std::string& key,
const std::string& switch_name,
const std::string& switch_value,
std::map<std::string, SwitchEntry>* name_to_switch_map) const;
// Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name|
// to state |feature_state|, along with the given |variation_id|, in the
// format of VariationsIdsProvider::ForceVariationIds().
void AddFeatureMapping(
const std::string& key,
const std::string& feature_name,
bool feature_state,
const std::string& variation_id,
std::map<std::string, SwitchEntry>* name_to_switch_map) const;
// Updates the switches in |command_line| by applying the modifications
// specified in |name_to_switch_map| for each entry in |enabled_entries|.
// |enable_features_flag_name| and |disable_features_flag_name| are switches
// used by the embedder to enable/disable features respectively if supported.
void AddSwitchesToCommandLine(
const std::set<std::string>& enabled_entries,
const std::map<std::string, SwitchEntry>& name_to_switch_map,
SentinelsMode sentinels,
base::CommandLine* command_line,
const char* enable_features_flag_name,
const char* disable_features_flag_name);
// Updates |command_line| by merging the value of the --enable-features= or
// --disable-features= list (per the |switch_name| param) with corresponding
// entries in |feature_switches| that have value |feature_state|. Keeps track
// of the changes by updating |appended_switches|.
void MergeFeatureCommandLineSwitch(
const std::map<std::string, bool>& feature_switches,
const char* switch_name,
bool feature_state,
base::CommandLine* command_line);
// Updates |command_line| by merging the value of the --force-variation-ids
// list with corresponding entries in |variation_ids|.
void MergeVariationIdsCommandLineSwitch(
const std::vector<std::string>& variation_ids,
base::CommandLine* command_line);
// Sanitizes |enabled_entries| to only contain entries that are defined in the
// |feature_entries_| and whose |supported_platforms| matches |platform_mask|.
// Pass -1 to |platform_mask| to not do platform filtering.
std::set<std::string> SanitizeList(
const FlagsStorage* storage,
const std::set<std::string>& enabled_entries,
int platform_mask) const;
// Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
// enabled on the current platform.
void GetSanitizedEnabledFlagsForCurrentPlatform(
FlagsStorage* flags_storage,
std::set<std::string>* result) const;
// Generates a flags to switches mapping based on the set of enabled flags
// from |flags_storage|. On output, |enabled_entries| will contain the
// internal names of enabled flags and |name_to_switch_map| will contain
// information on how they map to command-line flags or features.
// When |enabled_entries| is empty |name_to_switch_map| won't be filled.
void GenerateFlagsToSwitchesMapping(
FlagsStorage* flags_storage,
const base::CommandLine& command_line,
std::set<std::string>* enabled_entries,
std::map<std::string, SwitchEntry>* name_to_switch_map) const;
// Returns whether there is a FeatureEntry named by |name| in
// |feature_entries_| that:
// a) Is supported on this |platform_mask|, and
// b) Is not excluded by |exclude_predicate_|, if it is set (i.e. for which
// |exclude_predicate_| returns false).
bool IsSupportedFeature(const FlagsStorage* storage,
const std::string& name,
int platform_mask) const;
// Stores the flags in both FlagsStorage and SharedPreferences.
// Call FlagsStorage.SetFlags() to store the flags in FlagsStorage.
// Make the appropriate JNI calls to store the flags in SharedPreferences.
void SetFlags(FlagsStorage* flags_storage,
const std::set<std::string>& enabled_flags,
const std::set<std::string>& prev_enabled_flags) const;
const base::raw_span<const FeatureEntry> feature_entries_;
bool needs_restart_;
std::map<std::string, std::string> flags_switches_;
// Map from switch name to a set of string, that keeps track which strings
// were appended to existing (list value) switches.
std::map<std::string, std::set<std::string>> appended_switches_;
// Delegate used for embedders to control display and application of flags.
// May be null.
raw_ptr<Delegate> delegate_;
#if BUILDFLAG(IS_ANDROID)
// Delegate used by internal code to make JNI calls.
std::unique_ptr<cached_flags::JniDelegate> jni_delegate_;
public:
void SetJniDelegateForTesting(
std::unique_ptr<cached_flags::JniDelegate> delegate) {
jni_delegate_ = std::move(delegate);
}
#endif
};
} // namespace flags_ui
#endif // COMPONENTS_WEBUI_FLAGS_FLAGS_STATE_H_
|