Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Unified Diff: chrome/browser/about_flags.cc

Issue 1411453004: Componentize internal class FlagsState in flags_ui component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@feature_entry
Patch Set: Rebase Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/about_flags.h ('k') | chrome/browser/about_flags_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/about_flags.cc
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 96aa9d340dd8ff37185f7f12be4b03ba44ba1304..7d362519616f5c65c12655888ce6f4736b6f110c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -9,6 +9,8 @@
#include <set>
#include <utility>
+#include "base/bind.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/memory/singleton.h"
@@ -33,6 +35,7 @@
#include "components/enhanced_bookmarks/enhanced_bookmark_switches.h"
#include "components/flags_ui/feature_entry_macros.h"
#include "components/flags_ui/flags_storage.h"
+#include "components/flags_ui/flags_ui_switches.h"
#include "components/metrics/metrics_hashes.h"
#include "components/nacl/common/nacl_switches.h"
#include "components/offline_pages/offline_page_switches.h"
@@ -89,77 +92,20 @@
#endif
using flags_ui::FeatureEntry;
+using flags_ui::kOsMac;
+using flags_ui::kOsWin;
+using flags_ui::kOsLinux;
+using flags_ui::kOsCrOS;
+using flags_ui::kOsAndroid;
+using flags_ui::kOsCrOSOwnerOnly;
namespace about_flags {
namespace {
-// Enumeration of OSs.
-enum {
- kOsMac = 1 << 0,
- kOsWin = 1 << 1,
- kOsLinux = 1 << 2,
- kOsCrOS = 1 << 3,
- kOsAndroid = 1 << 4,
- kOsCrOSOwnerOnly = 1 << 5
-};
-
const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid;
const unsigned kOsDesktop = kOsMac | kOsWin | kOsLinux | kOsCrOS;
-// Adds a |StringValue| to |list| for each platform where |bitmask| indicates
-// whether the entry is available on that platform.
-void AddOsStrings(unsigned bitmask, base::ListValue* list) {
- struct {
- unsigned bit;
- const char* const name;
- } kBitsToOs[] = {
- {kOsMac, "Mac"},
- {kOsWin, "Windows"},
- {kOsLinux, "Linux"},
- {kOsCrOS, "Chrome OS"},
- {kOsAndroid, "Android"},
- {kOsCrOSOwnerOnly, "Chrome OS (owner only)"},
- };
- for (size_t i = 0; i < arraysize(kBitsToOs); ++i) {
- if (bitmask & kBitsToOs[i].bit)
- list->Append(new base::StringValue(kBitsToOs[i].name));
- }
-}
-
-// Convert switch constants to proper CommandLine::StringType strings.
-base::CommandLine::StringType GetSwitchString(const std::string& flag) {
- base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM);
- cmd_line.AppendSwitch(flag);
- DCHECK_EQ(2U, cmd_line.argv().size());
- return cmd_line.argv()[1];
-}
-
-// Scoops flags from a command line.
-std::set<base::CommandLine::StringType> ExtractFlagsFromCommandLine(
- const base::CommandLine& cmdline) {
- std::set<base::CommandLine::StringType> flags;
- // First do the ones between --flag-switches-begin and --flag-switches-end.
- base::CommandLine::StringVector::const_iterator first =
- std::find(cmdline.argv().begin(), cmdline.argv().end(),
- GetSwitchString(switches::kFlagSwitchesBegin));
- base::CommandLine::StringVector::const_iterator last =
- std::find(cmdline.argv().begin(), cmdline.argv().end(),
- GetSwitchString(switches::kFlagSwitchesEnd));
- if (first != cmdline.argv().end() && last != cmdline.argv().end())
- flags.insert(first + 1, last);
-#if defined(OS_CHROMEOS)
- // Then add those between --policy-switches-begin and --policy-switches-end.
- first = std::find(cmdline.argv().begin(), cmdline.argv().end(),
- GetSwitchString(chromeos::switches::kPolicySwitchesBegin));
- last = std::find(cmdline.argv().begin(), cmdline.argv().end(),
- GetSwitchString(chromeos::switches::kPolicySwitchesEnd));
- if (first != cmdline.argv().end() && last != cmdline.argv().end())
- flags.insert(first + 1, last);
-#endif
- return flags;
-}
-
const FeatureEntry::Choice kTouchEventsChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_AUTOMATIC, "", "" },
{ IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
@@ -2111,193 +2057,28 @@ const FeatureEntry kFeatureEntries[] = {
// histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
};
-// Stores and encapsulates the little state that about:flags has.
-class FlagsState {
+class FlagsStateSingleton {
public:
- FlagsState()
- : feature_entries(kFeatureEntries),
- num_feature_entries(arraysize(kFeatureEntries)),
- needs_restart_(false) {}
- void ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage,
- base::CommandLine* command_line,
- SentinelsMode sentinels);
- bool IsRestartNeededToCommitChanges();
- void SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage,
- const std::string& internal_name,
- bool enable);
- void RemoveFlagsSwitches(
- std::map<std::string, base::CommandLine::StringType>* switch_list);
- void ResetAllFlags(flags_ui::FlagsStorage* flags_storage);
- void Reset();
-
- // 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|.
- void GetFlagFeatureEntries(flags_ui::FlagsStorage* flags_storage,
- FlagAccess access,
- base::ListValue* supported_entries,
- base::ListValue* unsupported_entries);
-
- void SetFeatureEntries(const FeatureEntry* entries, size_t count);
- const FeatureEntry* GetFeatureEntries(size_t* count);
-
- // Returns the singleton instance of this class
- static FlagsState* GetInstance() {
- return base::Singleton<FlagsState>::get();
- }
+ FlagsStateSingleton()
+ : flags_state_(kFeatureEntries, arraysize(kFeatureEntries)) {}
+ ~FlagsStateSingleton() {}
- private:
- // Keeps track of affected switches for each FeatureEntry, based on which
- // choice is selected for it.
- struct SwitchEntry {
- // Corresponding base::Feature to toggle.
- std::string feature_name;
-
- // If |feature_name| is not empty, the state (enable/disabled) to set.
- bool feature_state;
-
- // The name of the switch to add.
- std::string switch_name;
-
- // If |switch_name| is not empty, the value of the switch to set.
- std::string switch_value;
-
- SwitchEntry() : feature_state(false) {}
- };
-
- // 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);
-
- // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name|
- // to state |feature_state|.
- void AddFeatureMapping(
- const std::string& key,
- const std::string& feature_name,
- bool feature_state,
- std::map<std::string, SwitchEntry>* name_to_switch_map);
-
- // Updates the switches in |command_line| by applying the modifications
- // specified in |name_to_switch_map| for each entry in |enabled_entries|.
- 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);
-
- // 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);
-
- // Removes all entries from prefs::kEnabledLabsExperiments that are unknown,
- // to prevent this list to become very long as entries are added and removed.
- void SanitizeList(flags_ui::FlagsStorage* flags_storage);
-
- void GetSanitizedEnabledFlags(flags_ui::FlagsStorage* flags_storage,
- std::set<std::string>* result);
-
- // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
- // enabled on the current platform.
- void GetSanitizedEnabledFlagsForCurrentPlatform(
- flags_ui::FlagsStorage* flags_storage,
- std::set<std::string>* result);
-
- const FeatureEntry* feature_entries;
- size_t num_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_;
-
- DISALLOW_COPY_AND_ASSIGN(FlagsState);
-};
-
-// Adds the internal names for the specified entry to |names|.
-void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) {
- switch (e.type) {
- case FeatureEntry::SINGLE_VALUE:
- case FeatureEntry::SINGLE_DISABLE_VALUE:
- names->insert(e.internal_name);
- break;
- case FeatureEntry::MULTI_VALUE:
- case FeatureEntry::ENABLE_DISABLE_VALUE:
- case FeatureEntry::FEATURE_VALUE:
- for (int i = 0; i < e.num_choices; ++i)
- names->insert(e.NameForChoice(i));
- break;
+ static FlagsStateSingleton* GetInstance() {
+ return base::Singleton<FlagsStateSingleton>::get();
}
-}
-// Confirms that an entry is valid, used in a DCHECK in
-// SanitizeList below.
-bool ValidateFeatureEntry(const FeatureEntry& e) {
- switch (e.type) {
- case FeatureEntry::SINGLE_VALUE:
- case FeatureEntry::SINGLE_DISABLE_VALUE:
- DCHECK_EQ(0, e.num_choices);
- DCHECK(!e.choices);
- return true;
- case FeatureEntry::MULTI_VALUE:
- DCHECK_GT(e.num_choices, 0);
- DCHECK(e.choices);
- DCHECK(e.choices[0].command_line_switch);
- DCHECK_EQ('\0', e.choices[0].command_line_switch[0]);
- return true;
- case FeatureEntry::ENABLE_DISABLE_VALUE:
- DCHECK_EQ(3, e.num_choices);
- DCHECK(!e.choices);
- DCHECK(e.command_line_switch);
- DCHECK(e.command_line_value);
- DCHECK(e.disable_command_line_switch);
- DCHECK(e.disable_command_line_value);
- return true;
- case FeatureEntry::FEATURE_VALUE:
- DCHECK_EQ(3, e.num_choices);
- DCHECK(!e.choices);
- DCHECK(e.feature);
- return true;
+ static flags_ui::FlagsState* GetFlagsState() {
+ return &GetInstance()->flags_state_;
}
- NOTREACHED();
- return false;
-}
-void FlagsState::SanitizeList(flags_ui::FlagsStorage* flags_storage) {
- std::set<std::string> known_entries;
- for (size_t i = 0; i < num_feature_entries; ++i) {
- DCHECK(ValidateFeatureEntry(feature_entries[i]));
- AddInternalName(feature_entries[i], &known_entries);
- }
-
- std::set<std::string> enabled_entries = flags_storage->GetFlags();
-
- std::set<std::string> new_enabled_entries =
- base::STLSetIntersection<std::set<std::string> >(
- known_entries, enabled_entries);
-
- if (new_enabled_entries != enabled_entries)
- flags_storage->SetFlags(new_enabled_entries);
-}
+ private:
+ flags_ui::FlagsState flags_state_;
-void FlagsState::GetSanitizedEnabledFlags(flags_ui::FlagsStorage* flags_storage,
- std::set<std::string>* result) {
- SanitizeList(flags_storage);
- *result = flags_storage->GetFlags();
-}
+ DISALLOW_COPY_AND_ASSIGN(FlagsStateSingleton);
+};
bool SkipConditionalFeatureEntry(const FeatureEntry& entry) {
version_info::Channel channel = chrome::GetChannel();
-
#if defined(OS_ANDROID)
// enable-data-reduction-proxy-dev is only available for the Dev/Beta channel.
if (!strcmp("enable-data-reduction-proxy-dev", entry.internal_name) &&
@@ -2356,214 +2137,64 @@ bool SkipConditionalFeatureEntry(const FeatureEntry& entry) {
return false;
}
-void FlagsState::GetSanitizedEnabledFlagsForCurrentPlatform(
- flags_ui::FlagsStorage* flags_storage,
- std::set<std::string>* result) {
- GetSanitizedEnabledFlags(flags_storage, result);
-
- // Filter out any entries that aren't enabled on the current platform. We
- // don't remove these from prefs else syncing to a platform with a different
- // set of entries would be lossy.
- std::set<std::string> platform_entries;
- int current_platform = GetCurrentPlatform();
- for (size_t i = 0; i < num_feature_entries; ++i) {
- const FeatureEntry& entry = feature_entries[i];
- if (entry.supported_platforms & current_platform)
- AddInternalName(entry, &platform_entries);
-#if defined(OS_CHROMEOS)
- if (feature_entries[i].supported_platforms & kOsCrOSOwnerOnly)
- AddInternalName(entry, &platform_entries);
-#endif
- }
-
- std::set<std::string> new_enabled_entries =
- base::STLSetIntersection<std::set<std::string> >(
- platform_entries, *result);
-
- result->swap(new_enabled_entries);
-}
-
-// Returns true if none of this entry's options have been enabled.
-bool IsDefaultValue(
- const FeatureEntry& entry,
- const std::set<std::string>& enabled_entries) {
- switch (entry.type) {
- case FeatureEntry::SINGLE_VALUE:
- case FeatureEntry::SINGLE_DISABLE_VALUE:
- return enabled_entries.count(entry.internal_name) == 0;
- case FeatureEntry::MULTI_VALUE:
- case FeatureEntry::ENABLE_DISABLE_VALUE:
- case FeatureEntry::FEATURE_VALUE:
- for (int i = 0; i < entry.num_choices; ++i) {
- if (enabled_entries.count(entry.NameForChoice(i)) > 0)
- return false;
- }
- return true;
- }
- NOTREACHED();
- return true;
-}
-
-// Returns the Value representing the choice data in the specified entry.
-base::Value* CreateChoiceData(
- const FeatureEntry& entry,
- const std::set<std::string>& enabled_entries) {
- DCHECK(entry.type == FeatureEntry::MULTI_VALUE ||
- entry.type == FeatureEntry::ENABLE_DISABLE_VALUE ||
- entry.type == FeatureEntry::FEATURE_VALUE);
- base::ListValue* result = new base::ListValue;
- for (int i = 0; i < entry.num_choices; ++i) {
- base::DictionaryValue* value = new base::DictionaryValue;
- const std::string name = entry.NameForChoice(i);
- value->SetString("internal_name", name);
- value->SetString("description", entry.DescriptionForChoice(i));
- value->SetBoolean("selected", enabled_entries.count(name) > 0);
- result->Append(value);
- }
- return result;
-}
-
} // namespace
void ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage,
base::CommandLine* command_line,
- SentinelsMode sentinels) {
- FlagsState::GetInstance()->ConvertFlagsToSwitches(flags_storage,
- command_line,
- sentinels);
+ flags_ui::SentinelsMode sentinels) {
+ if (command_line->HasSwitch(switches::kNoExperiments))
+ return;
+
+ FlagsStateSingleton::GetFlagsState()->ConvertFlagsToSwitches(
+ flags_storage, command_line, sentinels, switches::kEnableFeatures,
+ switches::kDisableFeatures);
}
bool AreSwitchesIdenticalToCurrentCommandLine(
const base::CommandLine& new_cmdline,
const base::CommandLine& active_cmdline,
std::set<base::CommandLine::StringType>* out_difference) {
- std::set<base::CommandLine::StringType> new_flags =
- ExtractFlagsFromCommandLine(new_cmdline);
- std::set<base::CommandLine::StringType> active_flags =
- ExtractFlagsFromCommandLine(active_cmdline);
-
- bool result = false;
- // Needed because std::equal doesn't check if the 2nd set is empty.
- if (new_flags.size() == active_flags.size()) {
- result =
- std::equal(new_flags.begin(), new_flags.end(), active_flags.begin());
- }
-
- if (out_difference && !result) {
- std::set_symmetric_difference(
- new_flags.begin(),
- new_flags.end(),
- active_flags.begin(),
- active_flags.end(),
- std::inserter(*out_difference, out_difference->begin()));
- }
-
- return result;
-}
-
-void FlagsState::GetFlagFeatureEntries(flags_ui::FlagsStorage* flags_storage,
- FlagAccess access,
- base::ListValue* supported_entries,
- base::ListValue* unsupported_entries) {
- std::set<std::string> enabled_entries;
- GetSanitizedEnabledFlags(flags_storage, &enabled_entries);
-
- int current_platform = GetCurrentPlatform();
-
- for (size_t i = 0; i < num_feature_entries; ++i) {
- const FeatureEntry& entry = feature_entries[i];
- if (SkipConditionalFeatureEntry(entry))
- continue;
-
- base::DictionaryValue* data = new base::DictionaryValue();
- data->SetString("internal_name", entry.internal_name);
- data->SetString("name",
- l10n_util::GetStringUTF16(entry.visible_name_id));
- data->SetString("description",
- l10n_util::GetStringUTF16(
- entry.visible_description_id));
-
- base::ListValue* supported_platforms = new base::ListValue();
- AddOsStrings(entry.supported_platforms, supported_platforms);
- data->Set("supported_platforms", supported_platforms);
- // True if the switch is not currently passed.
- bool is_default_value = IsDefaultValue(entry, enabled_entries);
- data->SetBoolean("is_default", is_default_value);
-
- switch (entry.type) {
- case FeatureEntry::SINGLE_VALUE:
- case FeatureEntry::SINGLE_DISABLE_VALUE:
- data->SetBoolean(
- "enabled",
- (!is_default_value &&
- entry.type == FeatureEntry::SINGLE_VALUE) ||
- (is_default_value &&
- entry.type == FeatureEntry::SINGLE_DISABLE_VALUE));
- break;
- case FeatureEntry::MULTI_VALUE:
- case FeatureEntry::ENABLE_DISABLE_VALUE:
- case FeatureEntry::FEATURE_VALUE:
- data->Set("choices", CreateChoiceData(entry, enabled_entries));
- break;
- }
-
- bool supported = (entry.supported_platforms & current_platform) != 0;
+ const char* extra_flag_sentinel_begin_flag_name = nullptr;
+ const char* extra_flag_sentinel_end_flag_name = nullptr;
#if defined(OS_CHROMEOS)
- if (access == kOwnerAccessToFlags &&
- (entry.supported_platforms & kOsCrOSOwnerOnly) != 0) {
- supported = true;
- }
-#endif
- if (supported)
- supported_entries->Append(data);
- else
- unsupported_entries->Append(data);
- }
+ // Put the flags between --policy-switches--begin and --policy-switches-end on
+ // ChromeOS.
+ extra_flag_sentinel_begin_flag_name =
+ chromeos::switches::kPolicySwitchesBegin;
+ extra_flag_sentinel_end_flag_name = chromeos::switches::kPolicySwitchesEnd;
+#endif
+ return flags_ui::FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
+ new_cmdline, active_cmdline, out_difference,
+ extra_flag_sentinel_begin_flag_name, extra_flag_sentinel_end_flag_name);
}
void GetFlagFeatureEntries(flags_ui::FlagsStorage* flags_storage,
- FlagAccess access,
+ flags_ui::FlagAccess access,
base::ListValue* supported_entries,
base::ListValue* unsupported_entries) {
- FlagsState::GetInstance()->GetFlagFeatureEntries(flags_storage, access,
- supported_entries,
- unsupported_entries);
+ FlagsStateSingleton::GetFlagsState()->GetFlagFeatureEntries(
+ flags_storage, access, supported_entries, unsupported_entries,
+ base::Bind(&SkipConditionalFeatureEntry));
}
bool IsRestartNeededToCommitChanges() {
- return FlagsState::GetInstance()->IsRestartNeededToCommitChanges();
+ return FlagsStateSingleton::GetFlagsState()->IsRestartNeededToCommitChanges();
}
void SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage,
const std::string& internal_name,
bool enable) {
- FlagsState::GetInstance()->SetFeatureEntryEnabled(flags_storage,
- internal_name, enable);
+ FlagsStateSingleton::GetFlagsState()->SetFeatureEntryEnabled(
+ flags_storage, internal_name, enable);
}
void RemoveFlagsSwitches(
std::map<std::string, base::CommandLine::StringType>* switch_list) {
- FlagsState::GetInstance()->RemoveFlagsSwitches(switch_list);
+ FlagsStateSingleton::GetFlagsState()->RemoveFlagsSwitches(switch_list);
}
void ResetAllFlags(flags_ui::FlagsStorage* flags_storage) {
- FlagsState::GetInstance()->ResetAllFlags(flags_storage);
-}
-
-int GetCurrentPlatform() {
-#if defined(OS_MACOSX)
- return kOsMac;
-#elif defined(OS_WIN)
- return kOsWin;
-#elif defined(OS_CHROMEOS) // Needs to be before the OS_LINUX check.
- return kOsCrOS;
-#elif defined(OS_LINUX) || defined(OS_OPENBSD)
- return kOsLinux;
-#elif defined(OS_ANDROID)
- return kOsAndroid;
-#else
-#error Unknown platform
-#endif
+ FlagsStateSingleton::GetFlagsState()->ResetAllFlags(flags_storage);
}
void RecordUMAStatistics(flags_ui::FlagsStorage* flags_storage) {
@@ -2612,310 +2243,13 @@ void ReportCustomFlags(const std::string& uma_histogram_hame,
}
}
-//////////////////////////////////////////////////////////////////////////////
-// FlagsState implementation.
-
-namespace {
-
-void FlagsState::ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage,
- base::CommandLine* command_line,
- SentinelsMode sentinels) {
- if (command_line->HasSwitch(switches::kNoExperiments))
- return;
-
- std::set<std::string> enabled_entries;
-
- GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries);
-
- std::map<std::string, SwitchEntry> name_to_switch_map;
- for (size_t i = 0; i < num_feature_entries; ++i) {
- const FeatureEntry& e = feature_entries[i];
- switch (e.type) {
- case FeatureEntry::SINGLE_VALUE:
- case FeatureEntry::SINGLE_DISABLE_VALUE:
- AddSwitchMapping(e.internal_name, e.command_line_switch,
- e.command_line_value, &name_to_switch_map);
- break;
- case FeatureEntry::MULTI_VALUE:
- for (int j = 0; j < e.num_choices; ++j) {
- AddSwitchMapping(e.NameForChoice(j), e.choices[j].command_line_switch,
- e.choices[j].command_line_value,
- &name_to_switch_map);
- }
- break;
- case FeatureEntry::ENABLE_DISABLE_VALUE:
- AddSwitchMapping(e.NameForChoice(0), std::string(), std::string(),
- &name_to_switch_map);
- AddSwitchMapping(e.NameForChoice(1), e.command_line_switch,
- e.command_line_value, &name_to_switch_map);
- AddSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch,
- e.disable_command_line_value, &name_to_switch_map);
- break;
- case FeatureEntry::FEATURE_VALUE:
- AddFeatureMapping(e.NameForChoice(0), std::string(), false,
- &name_to_switch_map);
- AddFeatureMapping(e.NameForChoice(1), e.feature->name, true,
- &name_to_switch_map);
- AddFeatureMapping(e.NameForChoice(2), e.feature->name, false,
- &name_to_switch_map);
- break;
- }
- }
-
- AddSwitchesToCommandLine(enabled_entries, name_to_switch_map, sentinels,
- command_line);
-}
-
-bool FlagsState::IsRestartNeededToCommitChanges() {
- return needs_restart_;
-}
-
-void FlagsState::SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage,
- const std::string& internal_name,
- bool enable) {
- size_t at_index = internal_name.find(flags_ui::testing::kMultiSeparator);
- if (at_index != std::string::npos) {
- DCHECK(enable);
- // We're being asked to enable a multi-choice entry. Disable the
- // currently selected choice.
- DCHECK_NE(at_index, 0u);
- const std::string entry_name = internal_name.substr(0, at_index);
- SetFeatureEntryEnabled(flags_storage, entry_name, false);
-
- // And enable the new choice, if it is not the default first choice.
- if (internal_name != entry_name + "@0") {
- std::set<std::string> enabled_entries;
- GetSanitizedEnabledFlags(flags_storage, &enabled_entries);
- needs_restart_ |= enabled_entries.insert(internal_name).second;
- flags_storage->SetFlags(enabled_entries);
- }
- return;
- }
-
- std::set<std::string> enabled_entries;
- GetSanitizedEnabledFlags(flags_storage, &enabled_entries);
-
- const FeatureEntry* e = nullptr;
- for (size_t i = 0; i < num_feature_entries; ++i) {
- if (feature_entries[i].internal_name == internal_name) {
- e = feature_entries + i;
- break;
- }
- }
- DCHECK(e);
-
- if (e->type == FeatureEntry::SINGLE_VALUE) {
- if (enable)
- needs_restart_ |= enabled_entries.insert(internal_name).second;
- else
- needs_restart_ |= (enabled_entries.erase(internal_name) > 0);
- } else if (e->type == FeatureEntry::SINGLE_DISABLE_VALUE) {
- if (!enable)
- needs_restart_ |= enabled_entries.insert(internal_name).second;
- else
- needs_restart_ |= (enabled_entries.erase(internal_name) > 0);
- } else {
- if (enable) {
- // Enable the first choice.
- needs_restart_ |= enabled_entries.insert(e->NameForChoice(0)).second;
- } else {
- // Find the currently enabled choice and disable it.
- for (int i = 0; i < e->num_choices; ++i) {
- std::string choice_name = e->NameForChoice(i);
- if (enabled_entries.find(choice_name) !=
- enabled_entries.end()) {
- needs_restart_ = true;
- enabled_entries.erase(choice_name);
- // Continue on just in case there's a bug and more than one
- // entry for this choice was enabled.
- }
- }
- }
- }
-
- flags_storage->SetFlags(enabled_entries);
-}
-
-void FlagsState::RemoveFlagsSwitches(
- std::map<std::string, base::CommandLine::StringType>* switch_list) {
- for (const auto& entry : flags_switches_)
- switch_list->erase(entry.first);
-
- // If feature entries were added to --enable-features= or --disable-features=
- // lists, remove them here while preserving existing values.
- for (const auto& entry : appended_switches_) {
- const auto& switch_name = entry.first;
- const auto& switch_added_values = entry.second;
-
- // The below is either a std::string or a base::string16 based on platform.
- const auto& existing_value = (*switch_list)[switch_name];
-#if defined(OS_WIN)
- const std::string existing_value_utf8 = base::UTF16ToUTF8(existing_value);
-#else
- const std::string& existing_value_utf8 = existing_value;
-#endif
-
- std::vector<std::string> features =
- base::FeatureList::SplitFeatureListString(existing_value_utf8);
- std::vector<std::string> remaining_features;
- // For any featrue name in |features| that is not in |switch_added_values| -
- // i.e. it wasn't added by about_flags code, add it to |remaining_features|.
- for (const std::string& feature : features) {
- if (!ContainsKey(switch_added_values, feature))
- remaining_features.push_back(feature);
- }
-
- // Either remove the flag entirely if |remaining_features| is empty, or set
- // the new list.
- if (remaining_features.empty()) {
- switch_list->erase(switch_name);
- } else {
- std::string switch_value = base::JoinString(remaining_features, ",");
-#if defined(OS_WIN)
- (*switch_list)[switch_name] = base::UTF8ToUTF16(switch_value);
-#else
- (*switch_list)[switch_name] = switch_value;
-#endif
- }
- }
-}
-
-void FlagsState::ResetAllFlags(flags_ui::FlagsStorage* flags_storage) {
- needs_restart_ = true;
-
- std::set<std::string> no_entries;
- flags_storage->SetFlags(no_entries);
-}
-
-void FlagsState::Reset() {
- needs_restart_ = false;
- flags_switches_.clear();
- appended_switches_.clear();
-}
-
-void FlagsState::SetFeatureEntries(const FeatureEntry* entries, size_t count) {
- feature_entries = entries;
- num_feature_entries = count;
-}
-
-const FeatureEntry* FlagsState::GetFeatureEntries(size_t* count) {
- *count = num_feature_entries;
- return feature_entries;
-}
-
-void FlagsState::AddSwitchMapping(
- const std::string& key,
- const std::string& switch_name,
- const std::string& switch_value,
- std::map<std::string, SwitchEntry>* name_to_switch_map) {
- DCHECK(!ContainsKey(*name_to_switch_map, key));
-
- SwitchEntry* entry = &(*name_to_switch_map)[key];
- entry->switch_name = switch_name;
- entry->switch_value = switch_value;
-}
-
-void FlagsState::AddFeatureMapping(
- const std::string& key,
- const std::string& feature_name,
- bool feature_state,
- std::map<std::string, SwitchEntry>* name_to_switch_map) {
- DCHECK(!ContainsKey(*name_to_switch_map, key));
-
- SwitchEntry* entry = &(*name_to_switch_map)[key];
- entry->feature_name = feature_name;
- entry->feature_state = feature_state;
-}
-
-void FlagsState::AddSwitchesToCommandLine(
- const std::set<std::string>& enabled_entries,
- const std::map<std::string, SwitchEntry>& name_to_switch_map,
- SentinelsMode sentinels,
- base::CommandLine* command_line) {
- std::map<std::string, bool> feature_switches;
- if (sentinels == kAddSentinels) {
- command_line->AppendSwitch(switches::kFlagSwitchesBegin);
- flags_switches_[switches::kFlagSwitchesBegin] = std::string();
- }
-
- for (const std::string& entry_name : enabled_entries) {
- const auto& entry_it = name_to_switch_map.find(entry_name);
- if (entry_it == name_to_switch_map.end()) {
- NOTREACHED();
- continue;
- }
-
- const SwitchEntry& entry = entry_it->second;
- if (!entry.feature_name.empty()) {
- feature_switches[entry.feature_name] = entry.feature_state;
- } else if (!entry.switch_name.empty()) {
- command_line->AppendSwitchASCII(entry.switch_name, entry.switch_value);
- flags_switches_[entry.switch_name] = entry.switch_value;
- }
- // If an entry doesn't match either of the above, then it is likely the
- // default entry for a FEATURE_VALUE entry. Safe to ignore.
- }
-
- if (!feature_switches.empty()) {
- MergeFeatureCommandLineSwitch(feature_switches, switches::kEnableFeatures,
- true, command_line);
- MergeFeatureCommandLineSwitch(feature_switches, switches::kDisableFeatures,
- false, command_line);
- }
-
- if (sentinels == kAddSentinels) {
- command_line->AppendSwitch(switches::kFlagSwitchesEnd);
- flags_switches_[switches::kFlagSwitchesEnd] = std::string();
- }
-}
-
-void FlagsState::MergeFeatureCommandLineSwitch(
- const std::map<std::string, bool>& feature_switches,
- const char* switch_name,
- bool feature_state,
- base::CommandLine* command_line) {
- std::string original_switch_value =
- command_line->GetSwitchValueASCII(switch_name);
- std::vector<std::string> features =
- base::FeatureList::SplitFeatureListString(original_switch_value);
- // Only add features that don't already exist in the lists.
- // Note: The ContainsValue() call results in O(n^2) performance, but in
- // practice n should be very small.
- for (const auto& entry : feature_switches) {
- if (entry.second == feature_state &&
- !ContainsValue(features, entry.first)) {
- features.push_back(entry.first);
- appended_switches_[switch_name].insert(entry.first);
- }
- }
- // Update the switch value only if it didn't change. This avoids setting an
- // empty list or duplicating the same list (since AppendSwitch() adds the
- // switch to the end but doesn't remove previous ones).
- std::string switch_value = base::JoinString(features, ",");
- if (switch_value != original_switch_value)
- command_line->AppendSwitchASCII(switch_name, switch_value);
-}
-
-} // namespace
-
namespace testing {
const base::HistogramBase::Sample kBadSwitchFormatHistogramId = 0;
-void ClearState() {
- FlagsState::GetInstance()->Reset();
-}
-
-void SetFeatureEntries(const FeatureEntry* entries, size_t count) {
- if (!entries) {
- entries = kFeatureEntries;
- count = arraysize(kFeatureEntries);
- }
- FlagsState::GetInstance()->SetFeatureEntries(entries, count);
-}
-
const FeatureEntry* GetFeatureEntries(size_t* count) {
- return FlagsState::GetInstance()->GetFeatureEntries(count);
+ *count = arraysize(kFeatureEntries);
+ return kFeatureEntries;
}
} // namespace testing
« no previous file with comments | « chrome/browser/about_flags.h ('k') | chrome/browser/about_flags_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698