| 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 <iterator> | 7 #include <iterator> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/feature_list.h" |
| 13 #include "base/memory/singleton.h" | 14 #include "base/memory/singleton.h" |
| 14 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
| 15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 19 #include "base/values.h" | 20 #include "base/values.h" |
| 20 #include "cc/base/switches.h" | 21 #include "cc/base/switches.h" |
| 21 #include "chrome/common/channel_info.h" | 22 #include "chrome/common/channel_info.h" |
| 22 #include "chrome/common/chrome_content_client.h" | 23 #include "chrome/common/chrome_content_client.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 #if defined(ENABLE_EXTENSIONS) | 77 #if defined(ENABLE_EXTENSIONS) |
| 77 #include "extensions/common/switches.h" | 78 #include "extensions/common/switches.h" |
| 78 #endif | 79 #endif |
| 79 | 80 |
| 80 #if defined(USE_OZONE) | 81 #if defined(USE_OZONE) |
| 81 #include "ui/ozone/public/ozone_switches.h" | 82 #include "ui/ozone/public/ozone_switches.h" |
| 82 #endif | 83 #endif |
| 83 | 84 |
| 84 namespace about_flags { | 85 namespace about_flags { |
| 85 | 86 |
| 86 // Macros to simplify specifying the type. | 87 // Macros to simplify specifying the type. Please refer to the comments on |
| 87 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ | 88 // FeatureEntry::Type in the header file, which explain the different entry |
| 88 FeatureEntry::SINGLE_VALUE, \ | 89 // types and when they should be used. |
| 89 command_line_switch, switch_value, NULL, NULL, NULL, 0 | 90 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ |
| 91 FeatureEntry::SINGLE_VALUE, command_line_switch, switch_value, nullptr, \ |
| 92 nullptr, nullptr, nullptr, 0 |
| 90 #define SINGLE_VALUE_TYPE(command_line_switch) \ | 93 #define SINGLE_VALUE_TYPE(command_line_switch) \ |
| 91 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") | 94 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") |
| 92 #define SINGLE_DISABLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ | 95 #define SINGLE_DISABLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ |
| 93 FeatureEntry::SINGLE_DISABLE_VALUE, \ | 96 FeatureEntry::SINGLE_DISABLE_VALUE, command_line_switch, switch_value, \ |
| 94 command_line_switch, switch_value, NULL, NULL, NULL, 0 | 97 nullptr, nullptr, nullptr, nullptr, 0 |
| 95 #define SINGLE_DISABLE_VALUE_TYPE(command_line_switch) \ | 98 #define SINGLE_DISABLE_VALUE_TYPE(command_line_switch) \ |
| 96 SINGLE_DISABLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") | 99 SINGLE_DISABLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") |
| 97 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ | 100 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ |
| 98 disable_switch, disable_value) \ | 101 disable_switch, disable_value) \ |
| 99 FeatureEntry::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ | 102 FeatureEntry::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ |
| 100 disable_switch, disable_value, NULL, 3 | 103 disable_switch, disable_value, nullptr, nullptr, 3 |
| 101 #define ENABLE_DISABLE_VALUE_TYPE(enable_switch, disable_switch) \ | 104 #define ENABLE_DISABLE_VALUE_TYPE(enable_switch, disable_switch) \ |
| 102 ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, "", disable_switch, "") | 105 ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, "", disable_switch, "") |
| 103 #define MULTI_VALUE_TYPE(choices) \ | 106 #define MULTI_VALUE_TYPE(choices) \ |
| 104 FeatureEntry::MULTI_VALUE, NULL, NULL, NULL, NULL, choices, \ | 107 FeatureEntry::MULTI_VALUE, nullptr, nullptr, nullptr, nullptr, nullptr, \ |
| 105 arraysize(choices) | 108 choices, arraysize(choices) |
| 109 #define FEATURE_VALUE_TYPE(feature) \ |
| 110 FeatureEntry::FEATURE_VALUE, nullptr, nullptr, nullptr, nullptr, \ |
| 111 feature.name, nullptr, 3 |
| 106 | 112 |
| 107 namespace { | 113 namespace { |
| 108 | 114 |
| 109 // Enumeration of OSs. | 115 // Enumeration of OSs. |
| 110 enum { | 116 enum { |
| 111 kOsMac = 1 << 0, | 117 kOsMac = 1 << 0, |
| 112 kOsWin = 1 << 1, | 118 kOsWin = 1 << 1, |
| 113 kOsLinux = 1 << 2, | 119 kOsLinux = 1 << 2, |
| 114 kOsCrOS = 1 << 3, | 120 kOsCrOS = 1 << 3, |
| 115 kOsAndroid = 1 << 4, | 121 kOsAndroid = 1 << 4, |
| (...skipping 2037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2153 | 2159 |
| 2154 void SetFeatureEntries(const FeatureEntry* entries, size_t count); | 2160 void SetFeatureEntries(const FeatureEntry* entries, size_t count); |
| 2155 const FeatureEntry* GetFeatureEntries(size_t* count); | 2161 const FeatureEntry* GetFeatureEntries(size_t* count); |
| 2156 | 2162 |
| 2157 // Returns the singleton instance of this class | 2163 // Returns the singleton instance of this class |
| 2158 static FlagsState* GetInstance() { | 2164 static FlagsState* GetInstance() { |
| 2159 return base::Singleton<FlagsState>::get(); | 2165 return base::Singleton<FlagsState>::get(); |
| 2160 } | 2166 } |
| 2161 | 2167 |
| 2162 private: | 2168 private: |
| 2169 // Keeps track of affected switches for each FeatureEntry, based on which |
| 2170 // choice is selected for it. |
| 2171 struct SwitchEntry { |
| 2172 // Corresponding base::Feature to toggle. |
| 2173 std::string feature_name; |
| 2174 |
| 2175 // If |feature_name| is not empty, the state (enable/disabled) to set. |
| 2176 bool feature_state; |
| 2177 |
| 2178 // The name of the switch to add. |
| 2179 std::string switch_name; |
| 2180 |
| 2181 // If |switch_name| is not empty, the value of the switch to set. |
| 2182 std::string switch_value; |
| 2183 |
| 2184 SwitchEntry() : feature_state(false) {} |
| 2185 }; |
| 2186 |
| 2187 // Adds mapping to |name_to_switch_map| to set the given switch name/value. |
| 2188 void AddSwitchMapping(const std::string& key, |
| 2189 const std::string& switch_name, |
| 2190 const std::string& switch_value, |
| 2191 std::map<std::string, SwitchEntry>* name_to_switch_map); |
| 2192 |
| 2193 // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name| |
| 2194 // to state |feature_state|. |
| 2195 void AddFeatureMapping( |
| 2196 const std::string& key, |
| 2197 const std::string& feature_name, |
| 2198 bool feature_state, |
| 2199 std::map<std::string, SwitchEntry>* name_to_switch_map); |
| 2200 |
| 2201 // Updates the switches in |command_line| by applying the modifications |
| 2202 // specified in |name_to_switch_map| for each entry in |enabled_entries|. |
| 2203 void AddSwitchesToCommandLine( |
| 2204 const std::set<std::string>& enabled_entries, |
| 2205 const std::map<std::string, SwitchEntry>& name_to_switch_map, |
| 2206 SentinelsMode sentinels, |
| 2207 base::CommandLine* command_line); |
| 2208 |
| 2209 // Updates |command_line| by merging the value of the --enable-features= or |
| 2210 // --disable-features= list (per the |switch_name| param) with corresponding |
| 2211 // entries in |feature_switches| that have value |feature_state|. Keeps track |
| 2212 // of the changes by updating |appended_switches|. |
| 2213 void MergeFeatureCommandLineSwitch( |
| 2214 const std::map<std::string, bool>& feature_switches, |
| 2215 const char* switch_name, |
| 2216 bool feature_state, |
| 2217 base::CommandLine* command_line); |
| 2218 |
| 2163 // Removes all entries from prefs::kEnabledLabsExperiments that are unknown, | 2219 // Removes all entries from prefs::kEnabledLabsExperiments that are unknown, |
| 2164 // to prevent this list to become very long as entries are added and removed. | 2220 // to prevent this list to become very long as entries are added and removed. |
| 2165 void SanitizeList(flags_ui::FlagsStorage* flags_storage); | 2221 void SanitizeList(flags_ui::FlagsStorage* flags_storage); |
| 2166 | 2222 |
| 2167 void GetSanitizedEnabledFlags(flags_ui::FlagsStorage* flags_storage, | 2223 void GetSanitizedEnabledFlags(flags_ui::FlagsStorage* flags_storage, |
| 2168 std::set<std::string>* result); | 2224 std::set<std::string>* result); |
| 2169 | 2225 |
| 2170 // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't | 2226 // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't |
| 2171 // enabled on the current platform. | 2227 // enabled on the current platform. |
| 2172 void GetSanitizedEnabledFlagsForCurrentPlatform( | 2228 void GetSanitizedEnabledFlagsForCurrentPlatform( |
| 2173 flags_ui::FlagsStorage* flags_storage, | 2229 flags_ui::FlagsStorage* flags_storage, |
| 2174 std::set<std::string>* result); | 2230 std::set<std::string>* result); |
| 2175 | 2231 |
| 2176 const FeatureEntry* feature_entries; | 2232 const FeatureEntry* feature_entries; |
| 2177 size_t num_feature_entries; | 2233 size_t num_feature_entries; |
| 2178 | 2234 |
| 2179 bool needs_restart_; | 2235 bool needs_restart_; |
| 2180 std::map<std::string, std::string> flags_switches_; | 2236 std::map<std::string, std::string> flags_switches_; |
| 2181 | 2237 |
| 2238 // Map from switch name to a set of string, that keeps track which strings |
| 2239 // were appended to existing (list value) switches. |
| 2240 std::map<std::string, std::set<std::string>> appended_switches_; |
| 2241 |
| 2182 DISALLOW_COPY_AND_ASSIGN(FlagsState); | 2242 DISALLOW_COPY_AND_ASSIGN(FlagsState); |
| 2183 }; | 2243 }; |
| 2184 | 2244 |
| 2185 // Adds the internal names for the specified entry to |names|. | 2245 // Adds the internal names for the specified entry to |names|. |
| 2186 void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) { | 2246 void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) { |
| 2187 if (e.type == FeatureEntry::SINGLE_VALUE || | 2247 switch (e.type) { |
| 2188 e.type == FeatureEntry::SINGLE_DISABLE_VALUE) { | 2248 case FeatureEntry::SINGLE_VALUE: |
| 2189 names->insert(e.internal_name); | 2249 case FeatureEntry::SINGLE_DISABLE_VALUE: |
| 2190 } else { | 2250 names->insert(e.internal_name); |
| 2191 DCHECK(e.type == FeatureEntry::MULTI_VALUE || | 2251 break; |
| 2192 e.type == FeatureEntry::ENABLE_DISABLE_VALUE); | 2252 case FeatureEntry::MULTI_VALUE: |
| 2193 for (int i = 0; i < e.num_choices; ++i) | 2253 case FeatureEntry::ENABLE_DISABLE_VALUE: |
| 2194 names->insert(e.NameForChoice(i)); | 2254 case FeatureEntry::FEATURE_VALUE: |
| 2255 for (int i = 0; i < e.num_choices; ++i) |
| 2256 names->insert(e.NameForChoice(i)); |
| 2257 break; |
| 2195 } | 2258 } |
| 2196 } | 2259 } |
| 2197 | 2260 |
| 2198 // Confirms that an entry is valid, used in a DCHECK in | 2261 // Confirms that an entry is valid, used in a DCHECK in |
| 2199 // SanitizeList below. | 2262 // SanitizeList below. |
| 2200 bool ValidateFeatureEntry(const FeatureEntry& e) { | 2263 bool ValidateFeatureEntry(const FeatureEntry& e) { |
| 2201 switch (e.type) { | 2264 switch (e.type) { |
| 2202 case FeatureEntry::SINGLE_VALUE: | 2265 case FeatureEntry::SINGLE_VALUE: |
| 2203 case FeatureEntry::SINGLE_DISABLE_VALUE: | 2266 case FeatureEntry::SINGLE_DISABLE_VALUE: |
| 2204 DCHECK_EQ(0, e.num_choices); | 2267 DCHECK_EQ(0, e.num_choices); |
| 2205 DCHECK(!e.choices); | 2268 DCHECK(!e.choices); |
| 2206 break; | 2269 return true; |
| 2207 case FeatureEntry::MULTI_VALUE: | 2270 case FeatureEntry::MULTI_VALUE: |
| 2208 DCHECK_GT(e.num_choices, 0); | 2271 DCHECK_GT(e.num_choices, 0); |
| 2209 DCHECK(e.choices); | 2272 DCHECK(e.choices); |
| 2210 DCHECK(e.choices[0].command_line_switch); | 2273 DCHECK(e.choices[0].command_line_switch); |
| 2211 DCHECK_EQ('\0', e.choices[0].command_line_switch[0]); | 2274 DCHECK_EQ('\0', e.choices[0].command_line_switch[0]); |
| 2212 break; | 2275 return true; |
| 2213 case FeatureEntry::ENABLE_DISABLE_VALUE: | 2276 case FeatureEntry::ENABLE_DISABLE_VALUE: |
| 2214 DCHECK_EQ(3, e.num_choices); | 2277 DCHECK_EQ(3, e.num_choices); |
| 2215 DCHECK(!e.choices); | 2278 DCHECK(!e.choices); |
| 2216 DCHECK(e.command_line_switch); | 2279 DCHECK(e.command_line_switch); |
| 2217 DCHECK(e.command_line_value); | 2280 DCHECK(e.command_line_value); |
| 2218 DCHECK(e.disable_command_line_switch); | 2281 DCHECK(e.disable_command_line_switch); |
| 2219 DCHECK(e.disable_command_line_value); | 2282 DCHECK(e.disable_command_line_value); |
| 2220 break; | 2283 return true; |
| 2221 default: | 2284 case FeatureEntry::FEATURE_VALUE: |
| 2222 NOTREACHED(); | 2285 DCHECK_EQ(3, e.num_choices); |
| 2286 DCHECK(!e.choices); |
| 2287 DCHECK(e.feature_name); |
| 2288 return true; |
| 2223 } | 2289 } |
| 2224 return true; | 2290 NOTREACHED(); |
| 2291 return false; |
| 2225 } | 2292 } |
| 2226 | 2293 |
| 2227 void FlagsState::SanitizeList(flags_ui::FlagsStorage* flags_storage) { | 2294 void FlagsState::SanitizeList(flags_ui::FlagsStorage* flags_storage) { |
| 2228 std::set<std::string> known_entries; | 2295 std::set<std::string> known_entries; |
| 2229 for (size_t i = 0; i < num_feature_entries; ++i) { | 2296 for (size_t i = 0; i < num_feature_entries; ++i) { |
| 2230 DCHECK(ValidateFeatureEntry(feature_entries[i])); | 2297 DCHECK(ValidateFeatureEntry(feature_entries[i])); |
| 2231 AddInternalName(feature_entries[i], &known_entries); | 2298 AddInternalName(feature_entries[i], &known_entries); |
| 2232 } | 2299 } |
| 2233 | 2300 |
| 2234 std::set<std::string> enabled_entries = flags_storage->GetFlags(); | 2301 std::set<std::string> enabled_entries = flags_storage->GetFlags(); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2338 // Returns true if none of this entry's options have been enabled. | 2405 // Returns true if none of this entry's options have been enabled. |
| 2339 bool IsDefaultValue( | 2406 bool IsDefaultValue( |
| 2340 const FeatureEntry& entry, | 2407 const FeatureEntry& entry, |
| 2341 const std::set<std::string>& enabled_entries) { | 2408 const std::set<std::string>& enabled_entries) { |
| 2342 switch (entry.type) { | 2409 switch (entry.type) { |
| 2343 case FeatureEntry::SINGLE_VALUE: | 2410 case FeatureEntry::SINGLE_VALUE: |
| 2344 case FeatureEntry::SINGLE_DISABLE_VALUE: | 2411 case FeatureEntry::SINGLE_DISABLE_VALUE: |
| 2345 return enabled_entries.count(entry.internal_name) == 0; | 2412 return enabled_entries.count(entry.internal_name) == 0; |
| 2346 case FeatureEntry::MULTI_VALUE: | 2413 case FeatureEntry::MULTI_VALUE: |
| 2347 case FeatureEntry::ENABLE_DISABLE_VALUE: | 2414 case FeatureEntry::ENABLE_DISABLE_VALUE: |
| 2415 case FeatureEntry::FEATURE_VALUE: |
| 2348 for (int i = 0; i < entry.num_choices; ++i) { | 2416 for (int i = 0; i < entry.num_choices; ++i) { |
| 2349 if (enabled_entries.count(entry.NameForChoice(i)) > 0) | 2417 if (enabled_entries.count(entry.NameForChoice(i)) > 0) |
| 2350 return false; | 2418 return false; |
| 2351 } | 2419 } |
| 2352 break; | 2420 return true; |
| 2353 default: | |
| 2354 NOTREACHED(); | |
| 2355 } | 2421 } |
| 2422 NOTREACHED(); |
| 2356 return true; | 2423 return true; |
| 2357 } | 2424 } |
| 2358 | 2425 |
| 2359 // Returns the Value representing the choice data in the specified entry. | 2426 // Returns the Value representing the choice data in the specified entry. |
| 2360 base::Value* CreateChoiceData( | 2427 base::Value* CreateChoiceData( |
| 2361 const FeatureEntry& entry, | 2428 const FeatureEntry& entry, |
| 2362 const std::set<std::string>& enabled_entries) { | 2429 const std::set<std::string>& enabled_entries) { |
| 2363 DCHECK(entry.type == FeatureEntry::MULTI_VALUE || | 2430 DCHECK(entry.type == FeatureEntry::MULTI_VALUE || |
| 2364 entry.type == FeatureEntry::ENABLE_DISABLE_VALUE); | 2431 entry.type == FeatureEntry::ENABLE_DISABLE_VALUE || |
| 2432 entry.type == FeatureEntry::FEATURE_VALUE); |
| 2365 base::ListValue* result = new base::ListValue; | 2433 base::ListValue* result = new base::ListValue; |
| 2366 for (int i = 0; i < entry.num_choices; ++i) { | 2434 for (int i = 0; i < entry.num_choices; ++i) { |
| 2367 base::DictionaryValue* value = new base::DictionaryValue; | 2435 base::DictionaryValue* value = new base::DictionaryValue; |
| 2368 const std::string name = entry.NameForChoice(i); | 2436 const std::string name = entry.NameForChoice(i); |
| 2369 value->SetString("internal_name", name); | 2437 value->SetString("internal_name", name); |
| 2370 value->SetString("description", entry.DescriptionForChoice(i)); | 2438 value->SetString("description", entry.DescriptionForChoice(i)); |
| 2371 value->SetBoolean("selected", enabled_entries.count(name) > 0); | 2439 value->SetBoolean("selected", enabled_entries.count(name) > 0); |
| 2372 result->Append(value); | 2440 result->Append(value); |
| 2373 } | 2441 } |
| 2374 return result; | 2442 return result; |
| 2375 } | 2443 } |
| 2376 | 2444 |
| 2377 } // namespace | 2445 } // namespace |
| 2378 | 2446 |
| 2379 std::string FeatureEntry::NameForChoice(int index) const { | 2447 std::string FeatureEntry::NameForChoice(int index) const { |
| 2380 DCHECK(type == FeatureEntry::MULTI_VALUE || | 2448 DCHECK(type == FeatureEntry::MULTI_VALUE || |
| 2381 type == FeatureEntry::ENABLE_DISABLE_VALUE); | 2449 type == FeatureEntry::ENABLE_DISABLE_VALUE || |
| 2450 type == FeatureEntry::FEATURE_VALUE); |
| 2382 DCHECK_LT(index, num_choices); | 2451 DCHECK_LT(index, num_choices); |
| 2383 return std::string(internal_name) + testing::kMultiSeparator + | 2452 return std::string(internal_name) + testing::kMultiSeparator + |
| 2384 base::IntToString(index); | 2453 base::IntToString(index); |
| 2385 } | 2454 } |
| 2386 | 2455 |
| 2387 base::string16 FeatureEntry::DescriptionForChoice(int index) const { | 2456 base::string16 FeatureEntry::DescriptionForChoice(int index) const { |
| 2388 DCHECK(type == FeatureEntry::MULTI_VALUE || | 2457 DCHECK(type == FeatureEntry::MULTI_VALUE || |
| 2389 type == FeatureEntry::ENABLE_DISABLE_VALUE); | 2458 type == FeatureEntry::ENABLE_DISABLE_VALUE || |
| 2459 type == FeatureEntry::FEATURE_VALUE); |
| 2390 DCHECK_LT(index, num_choices); | 2460 DCHECK_LT(index, num_choices); |
| 2391 int description_id; | 2461 int description_id; |
| 2392 if (type == FeatureEntry::ENABLE_DISABLE_VALUE) { | 2462 if (type == FeatureEntry::ENABLE_DISABLE_VALUE || |
| 2463 type == FeatureEntry::FEATURE_VALUE) { |
| 2393 const int kEnableDisableDescriptionIds[] = { | 2464 const int kEnableDisableDescriptionIds[] = { |
| 2394 IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, | 2465 IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, |
| 2395 IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED, | 2466 IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED, |
| 2396 IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED, | 2467 IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED, |
| 2397 }; | 2468 }; |
| 2398 description_id = kEnableDisableDescriptionIds[index]; | 2469 description_id = kEnableDisableDescriptionIds[index]; |
| 2399 } else { | 2470 } else { |
| 2400 description_id = choices[index].description_id; | 2471 description_id = choices[index].description_id; |
| 2401 } | 2472 } |
| 2402 return l10n_util::GetStringUTF16(description_id); | 2473 return l10n_util::GetStringUTF16(description_id); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2506 FlagsState::GetInstance()->GetFlagFeatureEntries(flags_storage, access, | 2577 FlagsState::GetInstance()->GetFlagFeatureEntries(flags_storage, access, |
| 2507 supported_entries, | 2578 supported_entries, |
| 2508 unsupported_entries); | 2579 unsupported_entries); |
| 2509 } | 2580 } |
| 2510 | 2581 |
| 2511 bool IsRestartNeededToCommitChanges() { | 2582 bool IsRestartNeededToCommitChanges() { |
| 2512 return FlagsState::GetInstance()->IsRestartNeededToCommitChanges(); | 2583 return FlagsState::GetInstance()->IsRestartNeededToCommitChanges(); |
| 2513 } | 2584 } |
| 2514 | 2585 |
| 2515 void SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage, | 2586 void SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage, |
| 2516 const std::string& internal_name, | 2587 const std::string& internal_name, |
| 2517 bool enable) { | 2588 bool enable) { |
| 2518 FlagsState::GetInstance()->SetFeatureEntryEnabled(flags_storage, | 2589 FlagsState::GetInstance()->SetFeatureEntryEnabled(flags_storage, |
| 2519 internal_name, enable); | 2590 internal_name, enable); |
| 2520 } | 2591 } |
| 2521 | 2592 |
| 2522 void RemoveFlagsSwitches( | 2593 void RemoveFlagsSwitches( |
| 2523 std::map<std::string, base::CommandLine::StringType>* switch_list) { | 2594 std::map<std::string, base::CommandLine::StringType>* switch_list) { |
| 2524 FlagsState::GetInstance()->RemoveFlagsSwitches(switch_list); | 2595 FlagsState::GetInstance()->RemoveFlagsSwitches(switch_list); |
| 2525 } | 2596 } |
| 2526 | 2597 |
| 2527 void ResetAllFlags(flags_ui::FlagsStorage* flags_storage) { | 2598 void ResetAllFlags(flags_ui::FlagsStorage* flags_storage) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2588 // to use macro with non-static histogram name here. | 2659 // to use macro with non-static histogram name here. |
| 2589 UMA_HISTOGRAM_SPARSE_SLOWLY(uma_histogram_hame, uma_id); | 2660 UMA_HISTOGRAM_SPARSE_SLOWLY(uma_histogram_hame, uma_id); |
| 2590 } | 2661 } |
| 2591 } | 2662 } |
| 2592 | 2663 |
| 2593 ////////////////////////////////////////////////////////////////////////////// | 2664 ////////////////////////////////////////////////////////////////////////////// |
| 2594 // FlagsState implementation. | 2665 // FlagsState implementation. |
| 2595 | 2666 |
| 2596 namespace { | 2667 namespace { |
| 2597 | 2668 |
| 2598 typedef std::map<std::string, std::pair<std::string, std::string> > | |
| 2599 NameToSwitchAndValueMap; | |
| 2600 | |
| 2601 void SetFlagToSwitchMapping(const std::string& key, | |
| 2602 const std::string& switch_name, | |
| 2603 const std::string& switch_value, | |
| 2604 NameToSwitchAndValueMap* name_to_switch_map) { | |
| 2605 DCHECK(name_to_switch_map->end() == name_to_switch_map->find(key)); | |
| 2606 (*name_to_switch_map)[key] = std::make_pair(switch_name, switch_value); | |
| 2607 } | |
| 2608 | |
| 2609 void FlagsState::ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage, | 2669 void FlagsState::ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage, |
| 2610 base::CommandLine* command_line, | 2670 base::CommandLine* command_line, |
| 2611 SentinelsMode sentinels) { | 2671 SentinelsMode sentinels) { |
| 2612 if (command_line->HasSwitch(switches::kNoExperiments)) | 2672 if (command_line->HasSwitch(switches::kNoExperiments)) |
| 2613 return; | 2673 return; |
| 2614 | 2674 |
| 2615 std::set<std::string> enabled_entries; | 2675 std::set<std::string> enabled_entries; |
| 2616 | 2676 |
| 2617 GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, | 2677 GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries); |
| 2618 &enabled_entries); | |
| 2619 | 2678 |
| 2620 NameToSwitchAndValueMap name_to_switch_map; | 2679 std::map<std::string, SwitchEntry> name_to_switch_map; |
| 2621 for (size_t i = 0; i < num_feature_entries; ++i) { | 2680 for (size_t i = 0; i < num_feature_entries; ++i) { |
| 2622 const FeatureEntry& e = feature_entries[i]; | 2681 const FeatureEntry& e = feature_entries[i]; |
| 2623 if (e.type == FeatureEntry::SINGLE_VALUE || | 2682 switch (e.type) { |
| 2624 e.type == FeatureEntry::SINGLE_DISABLE_VALUE) { | 2683 case FeatureEntry::SINGLE_VALUE: |
| 2625 SetFlagToSwitchMapping(e.internal_name, e.command_line_switch, | 2684 case FeatureEntry::SINGLE_DISABLE_VALUE: |
| 2626 e.command_line_value, &name_to_switch_map); | 2685 AddSwitchMapping(e.internal_name, e.command_line_switch, |
| 2627 } else if (e.type == FeatureEntry::MULTI_VALUE) { | 2686 e.command_line_value, &name_to_switch_map); |
| 2628 for (int j = 0; j < e.num_choices; ++j) { | 2687 break; |
| 2629 SetFlagToSwitchMapping(e.NameForChoice(j), | 2688 case FeatureEntry::MULTI_VALUE: |
| 2630 e.choices[j].command_line_switch, | 2689 for (int j = 0; j < e.num_choices; ++j) { |
| 2631 e.choices[j].command_line_value, | 2690 AddSwitchMapping(e.NameForChoice(j), e.choices[j].command_line_switch, |
| 2632 &name_to_switch_map); | 2691 e.choices[j].command_line_value, |
| 2633 } | 2692 &name_to_switch_map); |
| 2634 } else { | 2693 } |
| 2635 DCHECK_EQ(e.type, FeatureEntry::ENABLE_DISABLE_VALUE); | 2694 break; |
| 2636 SetFlagToSwitchMapping(e.NameForChoice(0), std::string(), std::string(), | 2695 case FeatureEntry::ENABLE_DISABLE_VALUE: |
| 2637 &name_to_switch_map); | 2696 AddSwitchMapping(e.NameForChoice(0), std::string(), std::string(), |
| 2638 SetFlagToSwitchMapping(e.NameForChoice(1), e.command_line_switch, | 2697 &name_to_switch_map); |
| 2639 e.command_line_value, &name_to_switch_map); | 2698 AddSwitchMapping(e.NameForChoice(1), e.command_line_switch, |
| 2640 SetFlagToSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch, | 2699 e.command_line_value, &name_to_switch_map); |
| 2641 e.disable_command_line_value, &name_to_switch_map); | 2700 AddSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch, |
| 2701 e.disable_command_line_value, &name_to_switch_map); |
| 2702 break; |
| 2703 case FeatureEntry::FEATURE_VALUE: |
| 2704 AddFeatureMapping(e.NameForChoice(0), std::string(), false, |
| 2705 &name_to_switch_map); |
| 2706 AddFeatureMapping(e.NameForChoice(1), e.feature_name, true, |
| 2707 &name_to_switch_map); |
| 2708 AddFeatureMapping(e.NameForChoice(2), e.feature_name, false, |
| 2709 &name_to_switch_map); |
| 2710 break; |
| 2642 } | 2711 } |
| 2643 } | 2712 } |
| 2644 | 2713 |
| 2645 if (sentinels == kAddSentinels) { | 2714 AddSwitchesToCommandLine(enabled_entries, name_to_switch_map, sentinels, |
| 2646 command_line->AppendSwitch(switches::kFlagSwitchesBegin); | 2715 command_line); |
| 2647 flags_switches_.insert( | |
| 2648 std::pair<std::string, std::string>(switches::kFlagSwitchesBegin, | |
| 2649 std::string())); | |
| 2650 } | |
| 2651 for (const std::string& entry_name : enabled_entries) { | |
| 2652 NameToSwitchAndValueMap::const_iterator name_to_switch_it = | |
| 2653 name_to_switch_map.find(entry_name); | |
| 2654 if (name_to_switch_it == name_to_switch_map.end()) { | |
| 2655 NOTREACHED(); | |
| 2656 continue; | |
| 2657 } | |
| 2658 | |
| 2659 const std::pair<std::string, std::string>& | |
| 2660 switch_and_value_pair = name_to_switch_it->second; | |
| 2661 | |
| 2662 CHECK(!switch_and_value_pair.first.empty()); | |
| 2663 command_line->AppendSwitchASCII(switch_and_value_pair.first, | |
| 2664 switch_and_value_pair.second); | |
| 2665 flags_switches_[switch_and_value_pair.first] = switch_and_value_pair.second; | |
| 2666 } | |
| 2667 if (sentinels == kAddSentinels) { | |
| 2668 command_line->AppendSwitch(switches::kFlagSwitchesEnd); | |
| 2669 flags_switches_.insert( | |
| 2670 std::pair<std::string, std::string>(switches::kFlagSwitchesEnd, | |
| 2671 std::string())); | |
| 2672 } | |
| 2673 } | 2716 } |
| 2674 | 2717 |
| 2675 bool FlagsState::IsRestartNeededToCommitChanges() { | 2718 bool FlagsState::IsRestartNeededToCommitChanges() { |
| 2676 return needs_restart_; | 2719 return needs_restart_; |
| 2677 } | 2720 } |
| 2678 | 2721 |
| 2679 void FlagsState::SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage, | 2722 void FlagsState::SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage, |
| 2680 const std::string& internal_name, | 2723 const std::string& internal_name, |
| 2681 bool enable) { | 2724 bool enable) { |
| 2682 size_t at_index = internal_name.find(testing::kMultiSeparator); | 2725 size_t at_index = internal_name.find(testing::kMultiSeparator); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2694 GetSanitizedEnabledFlags(flags_storage, &enabled_entries); | 2737 GetSanitizedEnabledFlags(flags_storage, &enabled_entries); |
| 2695 needs_restart_ |= enabled_entries.insert(internal_name).second; | 2738 needs_restart_ |= enabled_entries.insert(internal_name).second; |
| 2696 flags_storage->SetFlags(enabled_entries); | 2739 flags_storage->SetFlags(enabled_entries); |
| 2697 } | 2740 } |
| 2698 return; | 2741 return; |
| 2699 } | 2742 } |
| 2700 | 2743 |
| 2701 std::set<std::string> enabled_entries; | 2744 std::set<std::string> enabled_entries; |
| 2702 GetSanitizedEnabledFlags(flags_storage, &enabled_entries); | 2745 GetSanitizedEnabledFlags(flags_storage, &enabled_entries); |
| 2703 | 2746 |
| 2704 const FeatureEntry* e = NULL; | 2747 const FeatureEntry* e = nullptr; |
| 2705 for (size_t i = 0; i < num_feature_entries; ++i) { | 2748 for (size_t i = 0; i < num_feature_entries; ++i) { |
| 2706 if (feature_entries[i].internal_name == internal_name) { | 2749 if (feature_entries[i].internal_name == internal_name) { |
| 2707 e = feature_entries + i; | 2750 e = feature_entries + i; |
| 2708 break; | 2751 break; |
| 2709 } | 2752 } |
| 2710 } | 2753 } |
| 2711 DCHECK(e); | 2754 DCHECK(e); |
| 2712 | 2755 |
| 2713 if (e->type == FeatureEntry::SINGLE_VALUE) { | 2756 if (e->type == FeatureEntry::SINGLE_VALUE) { |
| 2714 if (enable) | 2757 if (enable) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2739 } | 2782 } |
| 2740 } | 2783 } |
| 2741 | 2784 |
| 2742 flags_storage->SetFlags(enabled_entries); | 2785 flags_storage->SetFlags(enabled_entries); |
| 2743 } | 2786 } |
| 2744 | 2787 |
| 2745 void FlagsState::RemoveFlagsSwitches( | 2788 void FlagsState::RemoveFlagsSwitches( |
| 2746 std::map<std::string, base::CommandLine::StringType>* switch_list) { | 2789 std::map<std::string, base::CommandLine::StringType>* switch_list) { |
| 2747 for (const auto& entry : flags_switches_) | 2790 for (const auto& entry : flags_switches_) |
| 2748 switch_list->erase(entry.first); | 2791 switch_list->erase(entry.first); |
| 2792 |
| 2793 // If feature entries were added to --enable-features= or --disable-features= |
| 2794 // lists, remove them here while preserving existing values. |
| 2795 for (const auto& entry : appended_switches_) { |
| 2796 const auto& switch_name = entry.first; |
| 2797 const auto& switch_added_values = entry.second; |
| 2798 |
| 2799 // The below is either a std::string or a base::string16 based on platform. |
| 2800 const auto& existing_value = (*switch_list)[switch_name]; |
| 2801 #if defined(OS_WIN) |
| 2802 const std::string existing_value_utf8 = base::UTF16ToUTF8(existing_value); |
| 2803 #else |
| 2804 const std::string& existing_value_utf8 = existing_value; |
| 2805 #endif |
| 2806 |
| 2807 std::vector<std::string> features = |
| 2808 base::FeatureList::SplitFeatureListString(existing_value_utf8); |
| 2809 std::vector<std::string> remaining_features; |
| 2810 // For any featrue name in |features| that is not in |switch_added_values| - |
| 2811 // i.e. it wasn't added by about_flags code, add it to |remaining_features|. |
| 2812 for (const std::string& feature : features) { |
| 2813 if (!ContainsKey(switch_added_values, feature)) |
| 2814 remaining_features.push_back(feature); |
| 2815 } |
| 2816 |
| 2817 // Either remove the flag entirely if |remaining_features| is empty, or set |
| 2818 // the new list. |
| 2819 if (remaining_features.empty()) { |
| 2820 switch_list->erase(switch_name); |
| 2821 } else { |
| 2822 std::string switch_value = base::JoinString(remaining_features, ","); |
| 2823 #if defined(OS_WIN) |
| 2824 (*switch_list)[switch_name] = base::UTF8ToUTF16(switch_value); |
| 2825 #else |
| 2826 (*switch_list)[switch_name] = switch_value; |
| 2827 #endif |
| 2828 } |
| 2829 } |
| 2749 } | 2830 } |
| 2750 | 2831 |
| 2751 void FlagsState::ResetAllFlags(flags_ui::FlagsStorage* flags_storage) { | 2832 void FlagsState::ResetAllFlags(flags_ui::FlagsStorage* flags_storage) { |
| 2752 needs_restart_ = true; | 2833 needs_restart_ = true; |
| 2753 | 2834 |
| 2754 std::set<std::string> no_entries; | 2835 std::set<std::string> no_entries; |
| 2755 flags_storage->SetFlags(no_entries); | 2836 flags_storage->SetFlags(no_entries); |
| 2756 } | 2837 } |
| 2757 | 2838 |
| 2758 void FlagsState::Reset() { | 2839 void FlagsState::Reset() { |
| 2759 needs_restart_ = false; | 2840 needs_restart_ = false; |
| 2760 flags_switches_.clear(); | 2841 flags_switches_.clear(); |
| 2842 appended_switches_.clear(); |
| 2761 } | 2843 } |
| 2762 | 2844 |
| 2763 void FlagsState::SetFeatureEntries(const FeatureEntry* entries, size_t count) { | 2845 void FlagsState::SetFeatureEntries(const FeatureEntry* entries, size_t count) { |
| 2764 feature_entries = entries; | 2846 feature_entries = entries; |
| 2765 num_feature_entries = count; | 2847 num_feature_entries = count; |
| 2766 } | 2848 } |
| 2767 | 2849 |
| 2768 const FeatureEntry* FlagsState::GetFeatureEntries(size_t* count) { | 2850 const FeatureEntry* FlagsState::GetFeatureEntries(size_t* count) { |
| 2769 *count = num_feature_entries; | 2851 *count = num_feature_entries; |
| 2770 return feature_entries; | 2852 return feature_entries; |
| 2771 } | 2853 } |
| 2772 | 2854 |
| 2855 void FlagsState::AddSwitchMapping( |
| 2856 const std::string& key, |
| 2857 const std::string& switch_name, |
| 2858 const std::string& switch_value, |
| 2859 std::map<std::string, SwitchEntry>* name_to_switch_map) { |
| 2860 DCHECK(!ContainsKey(*name_to_switch_map, key)); |
| 2861 |
| 2862 SwitchEntry* entry = &(*name_to_switch_map)[key]; |
| 2863 entry->switch_name = switch_name; |
| 2864 entry->switch_value = switch_value; |
| 2865 } |
| 2866 |
| 2867 void FlagsState::AddFeatureMapping( |
| 2868 const std::string& key, |
| 2869 const std::string& feature_name, |
| 2870 bool feature_state, |
| 2871 std::map<std::string, SwitchEntry>* name_to_switch_map) { |
| 2872 DCHECK(!ContainsKey(*name_to_switch_map, key)); |
| 2873 |
| 2874 SwitchEntry* entry = &(*name_to_switch_map)[key]; |
| 2875 entry->feature_name = feature_name; |
| 2876 entry->feature_state = feature_state; |
| 2877 } |
| 2878 |
| 2879 void FlagsState::AddSwitchesToCommandLine( |
| 2880 const std::set<std::string>& enabled_entries, |
| 2881 const std::map<std::string, SwitchEntry>& name_to_switch_map, |
| 2882 SentinelsMode sentinels, |
| 2883 base::CommandLine* command_line) { |
| 2884 std::map<std::string, bool> feature_switches; |
| 2885 if (sentinels == kAddSentinels) { |
| 2886 command_line->AppendSwitch(switches::kFlagSwitchesBegin); |
| 2887 flags_switches_[switches::kFlagSwitchesBegin] = std::string(); |
| 2888 } |
| 2889 |
| 2890 for (const std::string& entry_name : enabled_entries) { |
| 2891 const auto& entry_it = name_to_switch_map.find(entry_name); |
| 2892 if (entry_it == name_to_switch_map.end()) { |
| 2893 NOTREACHED(); |
| 2894 continue; |
| 2895 } |
| 2896 |
| 2897 const SwitchEntry& entry = entry_it->second; |
| 2898 if (!entry.feature_name.empty()) { |
| 2899 feature_switches[entry.feature_name] = entry.feature_state; |
| 2900 } else if (!entry.switch_name.empty()) { |
| 2901 command_line->AppendSwitchASCII(entry.switch_name, entry.switch_value); |
| 2902 flags_switches_[entry.switch_name] = entry.switch_value; |
| 2903 } |
| 2904 // If an entry doesn't match either of the above, then it is likely the |
| 2905 // default entry for a FEATURE_VALUE entry. Safe to ignore. |
| 2906 } |
| 2907 |
| 2908 if (!feature_switches.empty()) { |
| 2909 MergeFeatureCommandLineSwitch(feature_switches, switches::kEnableFeatures, |
| 2910 true, command_line); |
| 2911 MergeFeatureCommandLineSwitch(feature_switches, switches::kDisableFeatures, |
| 2912 false, command_line); |
| 2913 } |
| 2914 |
| 2915 if (sentinels == kAddSentinels) { |
| 2916 command_line->AppendSwitch(switches::kFlagSwitchesEnd); |
| 2917 flags_switches_[switches::kFlagSwitchesEnd] = std::string(); |
| 2918 } |
| 2919 } |
| 2920 |
| 2921 void FlagsState::MergeFeatureCommandLineSwitch( |
| 2922 const std::map<std::string, bool>& feature_switches, |
| 2923 const char* switch_name, |
| 2924 bool feature_state, |
| 2925 base::CommandLine* command_line) { |
| 2926 std::string original_switch_value = |
| 2927 command_line->GetSwitchValueASCII(switch_name); |
| 2928 std::vector<std::string> features = |
| 2929 base::FeatureList::SplitFeatureListString(original_switch_value); |
| 2930 // Only add features that don't already exist in the lists. |
| 2931 // Note: The ContainsValue() call results in O(n^2) performance, but in |
| 2932 // practice n should be very small. |
| 2933 for (const auto& entry : feature_switches) { |
| 2934 if (entry.second == feature_state && |
| 2935 !ContainsValue(features, entry.first)) { |
| 2936 features.push_back(entry.first); |
| 2937 appended_switches_[switch_name].insert(entry.first); |
| 2938 } |
| 2939 } |
| 2940 // Update the switch value only if it didn't change. This avoids setting an |
| 2941 // empty list or duplicating the same list (since AppendSwitch() adds the |
| 2942 // switch to the end but doesn't remove previous ones). |
| 2943 std::string switch_value = base::JoinString(features, ","); |
| 2944 if (switch_value != original_switch_value) |
| 2945 command_line->AppendSwitchASCII(switch_name, switch_value); |
| 2946 } |
| 2947 |
| 2773 } // namespace | 2948 } // namespace |
| 2774 | 2949 |
| 2775 namespace testing { | 2950 namespace testing { |
| 2776 | 2951 |
| 2777 // WARNING: '@' is also used in the html file. If you update this constant you | 2952 // WARNING: '@' is also used in the html file. If you update this constant you |
| 2778 // also need to update the html file. | 2953 // also need to update the html file. |
| 2779 const char kMultiSeparator[] = "@"; | 2954 const char kMultiSeparator[] = "@"; |
| 2780 | 2955 |
| 2781 const base::HistogramBase::Sample kBadSwitchFormatHistogramId = 0; | 2956 const base::HistogramBase::Sample kBadSwitchFormatHistogramId = 0; |
| 2782 | 2957 |
| 2783 void ClearState() { | 2958 void ClearState() { |
| 2784 FlagsState::GetInstance()->Reset(); | 2959 FlagsState::GetInstance()->Reset(); |
| 2785 } | 2960 } |
| 2786 | 2961 |
| 2787 void SetFeatureEntries(const FeatureEntry* entries, size_t count) { | 2962 void SetFeatureEntries(const FeatureEntry* entries, size_t count) { |
| 2788 if (!entries) { | 2963 if (!entries) { |
| 2789 entries = kFeatureEntries; | 2964 entries = kFeatureEntries; |
| 2790 count = arraysize(kFeatureEntries); | 2965 count = arraysize(kFeatureEntries); |
| 2791 } | 2966 } |
| 2792 FlagsState::GetInstance()->SetFeatureEntries(entries, count); | 2967 FlagsState::GetInstance()->SetFeatureEntries(entries, count); |
| 2793 } | 2968 } |
| 2794 | 2969 |
| 2795 const FeatureEntry* GetFeatureEntries(size_t* count) { | 2970 const FeatureEntry* GetFeatureEntries(size_t* count) { |
| 2796 return FlagsState::GetInstance()->GetFeatureEntries(count); | 2971 return FlagsState::GetInstance()->GetFeatureEntries(count); |
| 2797 } | 2972 } |
| 2798 | 2973 |
| 2799 } // namespace testing | 2974 } // namespace testing |
| 2800 | 2975 |
| 2801 } // namespace about_flags | 2976 } // namespace about_flags |
| OLD | NEW |