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 |