Chromium Code Reviews| Index: chrome/browser/about_flags.cc |
| diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc |
| index c08171cf1579d0883f188aa8bce0662500a99952..eb7ae85e7310ef5bb4b1bd54ee49a3b161e5e1da 100644 |
| --- a/chrome/browser/about_flags.cc |
| +++ b/chrome/browser/about_flags.cc |
| @@ -48,6 +48,10 @@ |
| #include "third_party/cros_system_api/switches/chrome_switches.h" |
| #endif |
| +#if defined(OS_WIN) |
| +#include "base/win/registry.h" |
| +#endif |
| + |
| #if defined(ENABLE_APP_LIST) |
| #include "ui/app_list/app_list_switches.h" |
| #endif |
| @@ -72,6 +76,64 @@ namespace about_flags { |
| Experiment::MULTI_VALUE, NULL, NULL, NULL, NULL, choices, arraysize(choices) |
| namespace { |
| +#if defined(OS_WIN) |
| +const wchar_t kRegistryBasePath[] = L"SOFTWARE\\Google\\Chrome"; |
| +const wchar_t kRegistryProfilePath[] = L"SOFTWARE\\Google\\Chrome\\Profile"; |
| +const wchar_t kRegistryProfileSubkey[] = L"Profile"; |
| + |
| +std::wstring ConvertToWString(const std::string& s) { |
|
sky
2014/02/11 14:57:00
There is a bunch of code for reading/writing to th
girard
2014/02/11 18:51:48
I'm using those functions below. Those functions (
|
| + std::wstring result; |
| + result.assign(s.begin(),s.end()); |
| + return result; |
| +} |
| + |
| +bool FlagIsStoredInRegistry(const std::string& flagname) { |
| + return strncmp(flagname.c_str(),switches::kHighDPISupport, |
| + strlen(switches::kHighDPISupport))==0; |
| +} |
| + |
| +DWORD ReadRegistryValue(HKEY root, |
| + const wchar_t* base_key, const wchar_t* sub_key, |
| + const std::string& value_name, DWORD default_value) { |
| + base::win::RegKey regKey(HKEY_CURRENT_USER, |
| + base_key, |
| + KEY_CREATE_SUB_KEY); |
| + if (regKey.Valid() && |
| + regKey.OpenKey(sub_key, KEY_QUERY_VALUE) == ERROR_SUCCESS) { |
| + DWORD value; |
| + if (regKey.Valid() && |
| + regKey.ReadValueDW(ConvertToWString(value_name).c_str(),&value) == |
| + ERROR_SUCCESS) { |
| + return value; |
| + } |
| + } |
| + return default_value; |
| +} |
| + |
| +// WriteRegistryValue |
| +bool WriteRegistryValue(HKEY root, |
| + const wchar_t* base_key, const wchar_t* sub_key, |
| + const std::string& value_name, const char* value_string) { |
| + DWORD value = atoi(value_string); |
| + base::win::RegKey regKey(root, |
| + base_key, |
| + KEY_CREATE_SUB_KEY); |
| + return regKey.Valid() && |
| + (regKey.CreateKey(sub_key, KEY_SET_VALUE) == ERROR_SUCCESS) && |
| + (regKey.WriteValue(ConvertToWString(value_name).c_str(),value) == |
| + ERROR_SUCCESS); |
| +} |
| + |
| +bool DeleteRegistryValue( |
| + HKEY root, const wchar_t* subkey_name, const std::string& value_name) { |
| + base::win::RegKey regKey(HKEY_CURRENT_USER, |
| + subkey_name, |
| + KEY_ALL_ACCESS); |
| + return regKey.Valid() && |
| + regKey.DeleteValue(ConvertToWString(value_name).c_str()) == ERROR_SUCCESS; |
| +} |
| + |
| +#endif |
| const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid; |
| const unsigned kOsDesktop = kOsMac | kOsWin | kOsLinux | kOsCrOS; |
| @@ -2168,6 +2230,26 @@ base::Value* CreateChoiceData( |
| return result; |
| } |
| +base::Value* CreateChoiceDataFromRegistry( |
| + const Experiment& experiment) { |
| + DCHECK(experiment.type == Experiment::MULTI_VALUE || |
| + experiment.type == Experiment::ENABLE_DISABLE_VALUE); |
| + |
| + DWORD registry_value = ReadRegistryValue( |
|
girard
2014/02/11 20:29:00
Self-review: This logic depends on other code that
|
| + HKEY_CURRENT_USER,kRegistryBasePath, |
| + kRegistryProfileSubkey,experiment.internal_name,FALSE); |
| + base::ListValue* result = new base::ListValue; |
| + for (int i = 0; i < experiment.num_choices; ++i) { |
| + base::DictionaryValue* value = new base::DictionaryValue; |
| + const std::string name = experiment.NameForChoice(i); |
| + value->SetString("internal_name", name); |
| + value->SetString("description", experiment.DescriptionForChoice(i)); |
| + value->SetBoolean("selected", i == static_cast<int>(registry_value)); |
| + result->Append(value); |
| + } |
| + return result; |
| +} |
| + |
| } // namespace |
| std::string Experiment::NameForChoice(int index) const { |
| @@ -2252,7 +2334,12 @@ void GetFlagsExperimentsData(FlagsStorage* flags_storage, |
| break; |
| case Experiment::MULTI_VALUE: |
| case Experiment::ENABLE_DISABLE_VALUE: |
| - data->Set("choices", CreateChoiceData(experiment, enabled_experiments)); |
| + if (FlagIsStoredInRegistry(experiment.internal_name)) { |
| + data->Set("choices", CreateChoiceDataFromRegistry(experiment)); |
| + } else { |
| + data->Set("choices", |
| + CreateChoiceData(experiment, enabled_experiments)); |
| + } |
| break; |
| default: |
| NOTREACHED(); |
| @@ -2429,6 +2516,13 @@ void FlagsState::SetExperimentEnabled(FlagsStorage* flags_storage, |
| GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); |
| needs_restart_ |= enabled_experiments.insert(internal_name).second; |
| flags_storage->SetFlags(enabled_experiments); |
| +#if defined(OS_WIN) |
| + if (FlagIsStoredInRegistry(experiment_name)) { |
| + WriteRegistryValue(HKEY_CURRENT_USER,kRegistryBasePath, |
| + kRegistryProfileSubkey,experiment_name.c_str(), |
| + internal_name.substr(at_index+1,1).c_str()); |
| + } |
| +#endif |
| } |
| return; |
| } |
| @@ -2469,6 +2563,12 @@ void FlagsState::SetExperimentEnabled(FlagsStorage* flags_storage, |
| } |
| } |
| +#if defined(OS_WIN) |
| + if (FlagIsStoredInRegistry(internal_name)) { |
| + DeleteRegistryValue(HKEY_CURRENT_USER,kRegistryProfilePath, |
| + internal_name); |
| + } |
| +#endif |
| flags_storage->SetFlags(enabled_experiments); |
| } |