Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/about_flags.h" | 5 #include "chrome/browser/about_flags.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 | 41 |
| 42 #if defined(USE_ASH) | 42 #if defined(USE_ASH) |
| 43 #include "ash/ash_switches.h" | 43 #include "ash/ash_switches.h" |
| 44 #endif | 44 #endif |
| 45 | 45 |
| 46 #if defined(OS_CHROMEOS) | 46 #if defined(OS_CHROMEOS) |
| 47 #include "chromeos/chromeos_switches.h" | 47 #include "chromeos/chromeos_switches.h" |
| 48 #include "third_party/cros_system_api/switches/chrome_switches.h" | 48 #include "third_party/cros_system_api/switches/chrome_switches.h" |
| 49 #endif | 49 #endif |
| 50 | 50 |
| 51 #if defined(OS_WIN) | |
| 52 #include "base/win/registry.h" | |
| 53 #endif | |
| 54 | |
| 51 #if defined(ENABLE_APP_LIST) | 55 #if defined(ENABLE_APP_LIST) |
| 52 #include "ui/app_list/app_list_switches.h" | 56 #include "ui/app_list/app_list_switches.h" |
| 53 #endif | 57 #endif |
| 54 | 58 |
| 55 using base::UserMetricsAction; | 59 using base::UserMetricsAction; |
| 56 | 60 |
| 57 namespace about_flags { | 61 namespace about_flags { |
| 58 | 62 |
| 59 // Macros to simplify specifying the type. | 63 // Macros to simplify specifying the type. |
| 60 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ | 64 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ |
| 61 Experiment::SINGLE_VALUE, \ | 65 Experiment::SINGLE_VALUE, \ |
| 62 command_line_switch, switch_value, NULL, NULL, NULL, 0 | 66 command_line_switch, switch_value, NULL, NULL, NULL, 0 |
| 63 #define SINGLE_VALUE_TYPE(command_line_switch) \ | 67 #define SINGLE_VALUE_TYPE(command_line_switch) \ |
| 64 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") | 68 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") |
| 65 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ | 69 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ |
| 66 disable_switch, disable_value) \ | 70 disable_switch, disable_value) \ |
| 67 Experiment::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ | 71 Experiment::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ |
| 68 disable_switch, disable_value, NULL, 3 | 72 disable_switch, disable_value, NULL, 3 |
| 69 #define ENABLE_DISABLE_VALUE_TYPE(enable_switch, disable_switch) \ | 73 #define ENABLE_DISABLE_VALUE_TYPE(enable_switch, disable_switch) \ |
| 70 ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, "", disable_switch, "") | 74 ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, "", disable_switch, "") |
| 71 #define MULTI_VALUE_TYPE(choices) \ | 75 #define MULTI_VALUE_TYPE(choices) \ |
| 72 Experiment::MULTI_VALUE, NULL, NULL, NULL, NULL, choices, arraysize(choices) | 76 Experiment::MULTI_VALUE, NULL, NULL, NULL, NULL, choices, arraysize(choices) |
| 73 | 77 |
| 74 namespace { | 78 namespace { |
| 79 #if defined(OS_WIN) | |
| 80 const wchar_t kRegistryBasePath[] = L"SOFTWARE\\Google\\Chrome"; | |
| 81 const wchar_t kRegistryProfilePath[] = L"SOFTWARE\\Google\\Chrome\\Profile"; | |
| 82 const wchar_t kRegistryProfileSubkey[] = L"Profile"; | |
| 83 | |
| 84 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 (
| |
| 85 std::wstring result; | |
| 86 result.assign(s.begin(),s.end()); | |
| 87 return result; | |
| 88 } | |
| 89 | |
| 90 bool FlagIsStoredInRegistry(const std::string& flagname) { | |
| 91 return strncmp(flagname.c_str(),switches::kHighDPISupport, | |
| 92 strlen(switches::kHighDPISupport))==0; | |
| 93 } | |
| 94 | |
| 95 DWORD ReadRegistryValue(HKEY root, | |
| 96 const wchar_t* base_key, const wchar_t* sub_key, | |
| 97 const std::string& value_name, DWORD default_value) { | |
| 98 base::win::RegKey regKey(HKEY_CURRENT_USER, | |
| 99 base_key, | |
| 100 KEY_CREATE_SUB_KEY); | |
| 101 if (regKey.Valid() && | |
| 102 regKey.OpenKey(sub_key, KEY_QUERY_VALUE) == ERROR_SUCCESS) { | |
| 103 DWORD value; | |
| 104 if (regKey.Valid() && | |
| 105 regKey.ReadValueDW(ConvertToWString(value_name).c_str(),&value) == | |
| 106 ERROR_SUCCESS) { | |
| 107 return value; | |
| 108 } | |
| 109 } | |
| 110 return default_value; | |
| 111 } | |
| 112 | |
| 113 // WriteRegistryValue | |
| 114 bool WriteRegistryValue(HKEY root, | |
| 115 const wchar_t* base_key, const wchar_t* sub_key, | |
| 116 const std::string& value_name, const char* value_string) { | |
| 117 DWORD value = atoi(value_string); | |
| 118 base::win::RegKey regKey(root, | |
| 119 base_key, | |
| 120 KEY_CREATE_SUB_KEY); | |
| 121 return regKey.Valid() && | |
| 122 (regKey.CreateKey(sub_key, KEY_SET_VALUE) == ERROR_SUCCESS) && | |
| 123 (regKey.WriteValue(ConvertToWString(value_name).c_str(),value) == | |
| 124 ERROR_SUCCESS); | |
| 125 } | |
| 126 | |
| 127 bool DeleteRegistryValue( | |
| 128 HKEY root, const wchar_t* subkey_name, const std::string& value_name) { | |
| 129 base::win::RegKey regKey(HKEY_CURRENT_USER, | |
| 130 subkey_name, | |
| 131 KEY_ALL_ACCESS); | |
| 132 return regKey.Valid() && | |
| 133 regKey.DeleteValue(ConvertToWString(value_name).c_str()) == ERROR_SUCCESS; | |
| 134 } | |
| 135 | |
| 136 #endif | |
| 75 | 137 |
| 76 const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid; | 138 const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid; |
| 77 const unsigned kOsDesktop = kOsMac | kOsWin | kOsLinux | kOsCrOS; | 139 const unsigned kOsDesktop = kOsMac | kOsWin | kOsLinux | kOsCrOS; |
| 78 | 140 |
| 79 // Adds a |StringValue| to |list| for each platform where |bitmask| indicates | 141 // Adds a |StringValue| to |list| for each platform where |bitmask| indicates |
| 80 // whether the experiment is available on that platform. | 142 // whether the experiment is available on that platform. |
| 81 void AddOsStrings(unsigned bitmask, base::ListValue* list) { | 143 void AddOsStrings(unsigned bitmask, base::ListValue* list) { |
| 82 struct { | 144 struct { |
| 83 unsigned bit; | 145 unsigned bit; |
| 84 const char* const name; | 146 const char* const name; |
| (...skipping 2076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2161 base::DictionaryValue* value = new base::DictionaryValue; | 2223 base::DictionaryValue* value = new base::DictionaryValue; |
| 2162 const std::string name = experiment.NameForChoice(i); | 2224 const std::string name = experiment.NameForChoice(i); |
| 2163 value->SetString("internal_name", name); | 2225 value->SetString("internal_name", name); |
| 2164 value->SetString("description", experiment.DescriptionForChoice(i)); | 2226 value->SetString("description", experiment.DescriptionForChoice(i)); |
| 2165 value->SetBoolean("selected", enabled_experiments.count(name) > 0); | 2227 value->SetBoolean("selected", enabled_experiments.count(name) > 0); |
| 2166 result->Append(value); | 2228 result->Append(value); |
| 2167 } | 2229 } |
| 2168 return result; | 2230 return result; |
| 2169 } | 2231 } |
| 2170 | 2232 |
| 2233 base::Value* CreateChoiceDataFromRegistry( | |
| 2234 const Experiment& experiment) { | |
| 2235 DCHECK(experiment.type == Experiment::MULTI_VALUE || | |
| 2236 experiment.type == Experiment::ENABLE_DISABLE_VALUE); | |
| 2237 | |
| 2238 DWORD registry_value = ReadRegistryValue( | |
|
girard
2014/02/11 20:29:00
Self-review: This logic depends on other code that
| |
| 2239 HKEY_CURRENT_USER,kRegistryBasePath, | |
| 2240 kRegistryProfileSubkey,experiment.internal_name,FALSE); | |
| 2241 base::ListValue* result = new base::ListValue; | |
| 2242 for (int i = 0; i < experiment.num_choices; ++i) { | |
| 2243 base::DictionaryValue* value = new base::DictionaryValue; | |
| 2244 const std::string name = experiment.NameForChoice(i); | |
| 2245 value->SetString("internal_name", name); | |
| 2246 value->SetString("description", experiment.DescriptionForChoice(i)); | |
| 2247 value->SetBoolean("selected", i == static_cast<int>(registry_value)); | |
| 2248 result->Append(value); | |
| 2249 } | |
| 2250 return result; | |
| 2251 } | |
| 2252 | |
| 2171 } // namespace | 2253 } // namespace |
| 2172 | 2254 |
| 2173 std::string Experiment::NameForChoice(int index) const { | 2255 std::string Experiment::NameForChoice(int index) const { |
| 2174 DCHECK(type == Experiment::MULTI_VALUE || | 2256 DCHECK(type == Experiment::MULTI_VALUE || |
| 2175 type == Experiment::ENABLE_DISABLE_VALUE); | 2257 type == Experiment::ENABLE_DISABLE_VALUE); |
| 2176 DCHECK_LT(index, num_choices); | 2258 DCHECK_LT(index, num_choices); |
| 2177 return std::string(internal_name) + testing::kMultiSeparator + | 2259 return std::string(internal_name) + testing::kMultiSeparator + |
| 2178 base::IntToString(index); | 2260 base::IntToString(index); |
| 2179 } | 2261 } |
| 2180 | 2262 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2245 data->Set("supported_platforms", supported_platforms); | 2327 data->Set("supported_platforms", supported_platforms); |
| 2246 | 2328 |
| 2247 switch (experiment.type) { | 2329 switch (experiment.type) { |
| 2248 case Experiment::SINGLE_VALUE: | 2330 case Experiment::SINGLE_VALUE: |
| 2249 data->SetBoolean( | 2331 data->SetBoolean( |
| 2250 "enabled", | 2332 "enabled", |
| 2251 enabled_experiments.count(experiment.internal_name) > 0); | 2333 enabled_experiments.count(experiment.internal_name) > 0); |
| 2252 break; | 2334 break; |
| 2253 case Experiment::MULTI_VALUE: | 2335 case Experiment::MULTI_VALUE: |
| 2254 case Experiment::ENABLE_DISABLE_VALUE: | 2336 case Experiment::ENABLE_DISABLE_VALUE: |
| 2255 data->Set("choices", CreateChoiceData(experiment, enabled_experiments)); | 2337 if (FlagIsStoredInRegistry(experiment.internal_name)) { |
| 2338 data->Set("choices", CreateChoiceDataFromRegistry(experiment)); | |
| 2339 } else { | |
| 2340 data->Set("choices", | |
| 2341 CreateChoiceData(experiment, enabled_experiments)); | |
| 2342 } | |
| 2256 break; | 2343 break; |
| 2257 default: | 2344 default: |
| 2258 NOTREACHED(); | 2345 NOTREACHED(); |
| 2259 } | 2346 } |
| 2260 | 2347 |
| 2261 bool supported = (experiment.supported_platforms & current_platform) != 0; | 2348 bool supported = (experiment.supported_platforms & current_platform) != 0; |
| 2262 #if defined(OS_CHROMEOS) | 2349 #if defined(OS_CHROMEOS) |
| 2263 if (access == kOwnerAccessToFlags && | 2350 if (access == kOwnerAccessToFlags && |
| 2264 (experiment.supported_platforms & kOsCrOSOwnerOnly) != 0) { | 2351 (experiment.supported_platforms & kOsCrOSOwnerOnly) != 0) { |
| 2265 supported = true; | 2352 supported = true; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2422 DCHECK_NE(at_index, 0u); | 2509 DCHECK_NE(at_index, 0u); |
| 2423 const std::string experiment_name = internal_name.substr(0, at_index); | 2510 const std::string experiment_name = internal_name.substr(0, at_index); |
| 2424 SetExperimentEnabled(flags_storage, experiment_name, false); | 2511 SetExperimentEnabled(flags_storage, experiment_name, false); |
| 2425 | 2512 |
| 2426 // And enable the new choice, if it is not the default first choice. | 2513 // And enable the new choice, if it is not the default first choice. |
| 2427 if (internal_name != experiment_name + "@0") { | 2514 if (internal_name != experiment_name + "@0") { |
| 2428 std::set<std::string> enabled_experiments; | 2515 std::set<std::string> enabled_experiments; |
| 2429 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); | 2516 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); |
| 2430 needs_restart_ |= enabled_experiments.insert(internal_name).second; | 2517 needs_restart_ |= enabled_experiments.insert(internal_name).second; |
| 2431 flags_storage->SetFlags(enabled_experiments); | 2518 flags_storage->SetFlags(enabled_experiments); |
| 2519 #if defined(OS_WIN) | |
| 2520 if (FlagIsStoredInRegistry(experiment_name)) { | |
| 2521 WriteRegistryValue(HKEY_CURRENT_USER,kRegistryBasePath, | |
| 2522 kRegistryProfileSubkey,experiment_name.c_str(), | |
| 2523 internal_name.substr(at_index+1,1).c_str()); | |
| 2524 } | |
| 2525 #endif | |
| 2432 } | 2526 } |
| 2433 return; | 2527 return; |
| 2434 } | 2528 } |
| 2435 | 2529 |
| 2436 std::set<std::string> enabled_experiments; | 2530 std::set<std::string> enabled_experiments; |
| 2437 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); | 2531 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); |
| 2438 | 2532 |
| 2439 const Experiment* e = NULL; | 2533 const Experiment* e = NULL; |
| 2440 for (size_t i = 0; i < num_experiments; ++i) { | 2534 for (size_t i = 0; i < num_experiments; ++i) { |
| 2441 if (experiments[i].internal_name == internal_name) { | 2535 if (experiments[i].internal_name == internal_name) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2462 enabled_experiments.end()) { | 2556 enabled_experiments.end()) { |
| 2463 needs_restart_ = true; | 2557 needs_restart_ = true; |
| 2464 enabled_experiments.erase(choice_name); | 2558 enabled_experiments.erase(choice_name); |
| 2465 // Continue on just in case there's a bug and more than one | 2559 // Continue on just in case there's a bug and more than one |
| 2466 // experiment for this choice was enabled. | 2560 // experiment for this choice was enabled. |
| 2467 } | 2561 } |
| 2468 } | 2562 } |
| 2469 } | 2563 } |
| 2470 } | 2564 } |
| 2471 | 2565 |
| 2566 #if defined(OS_WIN) | |
| 2567 if (FlagIsStoredInRegistry(internal_name)) { | |
| 2568 DeleteRegistryValue(HKEY_CURRENT_USER,kRegistryProfilePath, | |
| 2569 internal_name); | |
| 2570 } | |
| 2571 #endif | |
| 2472 flags_storage->SetFlags(enabled_experiments); | 2572 flags_storage->SetFlags(enabled_experiments); |
| 2473 } | 2573 } |
| 2474 | 2574 |
| 2475 void FlagsState::RemoveFlagsSwitches( | 2575 void FlagsState::RemoveFlagsSwitches( |
| 2476 std::map<std::string, CommandLine::StringType>* switch_list) { | 2576 std::map<std::string, CommandLine::StringType>* switch_list) { |
| 2477 for (std::map<std::string, std::string>::const_iterator | 2577 for (std::map<std::string, std::string>::const_iterator |
| 2478 it = flags_switches_.begin(); it != flags_switches_.end(); ++it) { | 2578 it = flags_switches_.begin(); it != flags_switches_.end(); ++it) { |
| 2479 switch_list->erase(it->first); | 2579 switch_list->erase(it->first); |
| 2480 } | 2580 } |
| 2481 } | 2581 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2515 } | 2615 } |
| 2516 | 2616 |
| 2517 const Experiment* GetExperiments(size_t* count) { | 2617 const Experiment* GetExperiments(size_t* count) { |
| 2518 *count = num_experiments; | 2618 *count = num_experiments; |
| 2519 return experiments; | 2619 return experiments; |
| 2520 } | 2620 } |
| 2521 | 2621 |
| 2522 } // namespace testing | 2622 } // namespace testing |
| 2523 | 2623 |
| 2524 } // namespace about_flags | 2624 } // namespace about_flags |
| OLD | NEW |