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/memory/singleton.h" | 13 #include "base/memory/singleton.h" |
| 14 #include "base/metrics/sparse_histogram.h" |
| 15 #include "base/numerics/safe_conversions.h" |
14 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
15 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/string_util.h" |
16 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
17 #include "base/values.h" | 20 #include "base/values.h" |
18 #include "cc/base/switches.h" | 21 #include "cc/base/switches.h" |
19 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h" | 22 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h" |
20 #include "chrome/browser/flags_storage.h" | 23 #include "chrome/browser/flags_storage.h" |
21 #include "chrome/common/chrome_content_client.h" | 24 #include "chrome/common/chrome_content_client.h" |
22 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
23 #include "components/autofill/core/common/autofill_switches.h" | 26 #include "components/autofill/core/common/autofill_switches.h" |
24 #include "components/cloud_devices/common/cloud_devices_switches.h" | 27 #include "components/cloud_devices/common/cloud_devices_switches.h" |
| 28 #include "components/metrics/metrics_hashes.h" |
25 #include "components/nacl/common/nacl_switches.h" | 29 #include "components/nacl/common/nacl_switches.h" |
26 #include "components/search/search_switches.h" | 30 #include "components/search/search_switches.h" |
27 #include "content/public/browser/user_metrics.h" | 31 #include "content/public/browser/user_metrics.h" |
28 #include "extensions/common/switches.h" | 32 #include "extensions/common/switches.h" |
29 #include "grit/chromium_strings.h" | 33 #include "grit/chromium_strings.h" |
30 #include "grit/generated_resources.h" | 34 #include "grit/generated_resources.h" |
31 #include "grit/google_chrome_strings.h" | 35 #include "grit/google_chrome_strings.h" |
32 #include "media/base/media_switches.h" | 36 #include "media/base/media_switches.h" |
33 #include "ui/base/l10n/l10n_util.h" | 37 #include "ui/base/l10n/l10n_util.h" |
34 #include "ui/base/ui_base_switches.h" | 38 #include "ui/base/ui_base_switches.h" |
(...skipping 21 matching lines...) Expand all Loading... |
56 #endif | 60 #endif |
57 | 61 |
58 #if defined(ENABLE_APP_LIST) | 62 #if defined(ENABLE_APP_LIST) |
59 #include "ui/app_list/app_list_switches.h" | 63 #include "ui/app_list/app_list_switches.h" |
60 #endif | 64 #endif |
61 | 65 |
62 using base::UserMetricsAction; | 66 using base::UserMetricsAction; |
63 | 67 |
64 namespace about_flags { | 68 namespace about_flags { |
65 | 69 |
| 70 const uint32_t kBadSwitchFormatHistogramId = 0; |
| 71 |
66 // Macros to simplify specifying the type. | 72 // Macros to simplify specifying the type. |
67 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ | 73 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ |
68 Experiment::SINGLE_VALUE, \ | 74 Experiment::SINGLE_VALUE, \ |
69 command_line_switch, switch_value, NULL, NULL, NULL, 0 | 75 command_line_switch, switch_value, NULL, NULL, NULL, 0 |
70 #define SINGLE_VALUE_TYPE(command_line_switch) \ | 76 #define SINGLE_VALUE_TYPE(command_line_switch) \ |
71 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") | 77 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") |
72 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ | 78 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ |
73 disable_switch, disable_value) \ | 79 disable_switch, disable_value) \ |
74 Experiment::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ | 80 Experiment::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ |
75 disable_switch, disable_value, NULL, 3 | 81 disable_switch, disable_value, NULL, 3 |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 // To add a new experiment add to the end of kExperiments. There are two | 531 // To add a new experiment add to the end of kExperiments. There are two |
526 // distinct types of experiments: | 532 // distinct types of experiments: |
527 // . SINGLE_VALUE: experiment is either on or off. Use the SINGLE_VALUE_TYPE | 533 // . SINGLE_VALUE: experiment is either on or off. Use the SINGLE_VALUE_TYPE |
528 // macro for this type supplying the command line to the macro. | 534 // macro for this type supplying the command line to the macro. |
529 // . MULTI_VALUE: a list of choices, the first of which should correspond to a | 535 // . MULTI_VALUE: a list of choices, the first of which should correspond to a |
530 // deactivated state for this lab (i.e. no command line option). To specify | 536 // deactivated state for this lab (i.e. no command line option). To specify |
531 // this type of experiment use the macro MULTI_VALUE_TYPE supplying it the | 537 // this type of experiment use the macro MULTI_VALUE_TYPE supplying it the |
532 // array of choices. | 538 // array of choices. |
533 // See the documentation of Experiment for details on the fields. | 539 // See the documentation of Experiment for details on the fields. |
534 // | 540 // |
| 541 // Command-line switches must have entries in enum "LoginCustomFlags" in |
| 542 // histograms.xml. See note in histograms.xml and don't forget to run |
| 543 // AboutFlagsHistogramTest unit test to calculate and verify checksum. |
| 544 // |
535 // When adding a new choice, add it to the end of the list. | 545 // When adding a new choice, add it to the end of the list. |
536 const Experiment kExperiments[] = { | 546 const Experiment kExperiments[] = { |
537 { | 547 { |
538 "ignore-gpu-blacklist", | 548 "ignore-gpu-blacklist", |
539 IDS_FLAGS_IGNORE_GPU_BLACKLIST_NAME, | 549 IDS_FLAGS_IGNORE_GPU_BLACKLIST_NAME, |
540 IDS_FLAGS_IGNORE_GPU_BLACKLIST_DESCRIPTION, | 550 IDS_FLAGS_IGNORE_GPU_BLACKLIST_DESCRIPTION, |
541 kOsAll, | 551 kOsAll, |
542 SINGLE_VALUE_TYPE(switches::kIgnoreGpuBlacklist) | 552 SINGLE_VALUE_TYPE(switches::kIgnoreGpuBlacklist) |
543 }, | 553 }, |
544 { | 554 { |
(...skipping 1377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1922 kOsAll, | 1932 kOsAll, |
1923 MULTI_VALUE_TYPE(kEnableDropSyncCredentialChoices) | 1933 MULTI_VALUE_TYPE(kEnableDropSyncCredentialChoices) |
1924 }, | 1934 }, |
1925 { | 1935 { |
1926 "enable-extension-action-redesign", | 1936 "enable-extension-action-redesign", |
1927 IDS_FLAGS_ENABLE_EXTENSION_ACTION_REDESIGN_NAME, | 1937 IDS_FLAGS_ENABLE_EXTENSION_ACTION_REDESIGN_NAME, |
1928 IDS_FLAGS_ENABLE_EXTENSION_ACTION_REDESIGN_DESCRIPTION, | 1938 IDS_FLAGS_ENABLE_EXTENSION_ACTION_REDESIGN_DESCRIPTION, |
1929 kOsWin | kOsLinux | kOsCrOS, | 1939 kOsWin | kOsLinux | kOsCrOS, |
1930 SINGLE_VALUE_TYPE(extensions::switches::kEnableExtensionActionRedesign) | 1940 SINGLE_VALUE_TYPE(extensions::switches::kEnableExtensionActionRedesign) |
1931 }, | 1941 }, |
| 1942 // NOTE: Adding new command-line switches requires adding corresponding |
| 1943 // entries to enum "LoginCustomFlags" in histograms.xml. See note in |
| 1944 // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test. |
1932 }; | 1945 }; |
1933 | 1946 |
1934 const Experiment* experiments = kExperiments; | 1947 const Experiment* experiments = kExperiments; |
1935 size_t num_experiments = arraysize(kExperiments); | 1948 size_t num_experiments = arraysize(kExperiments); |
1936 | 1949 |
1937 // Stores and encapsulates the little state that about:flags has. | 1950 // Stores and encapsulates the little state that about:flags has. |
1938 class FlagsState { | 1951 class FlagsState { |
1939 public: | 1952 public: |
1940 FlagsState() : needs_restart_(false) {} | 1953 FlagsState() : needs_restart_(false) {} |
1941 void ConvertFlagsToSwitches(FlagsStorage* flags_storage, | 1954 void ConvertFlagsToSwitches(FlagsStorage* flags_storage, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2133 | 2146 |
2134 void ConvertFlagsToSwitches(FlagsStorage* flags_storage, | 2147 void ConvertFlagsToSwitches(FlagsStorage* flags_storage, |
2135 CommandLine* command_line, | 2148 CommandLine* command_line, |
2136 SentinelsMode sentinels) { | 2149 SentinelsMode sentinels) { |
2137 FlagsState::GetInstance()->ConvertFlagsToSwitches(flags_storage, | 2150 FlagsState::GetInstance()->ConvertFlagsToSwitches(flags_storage, |
2138 command_line, | 2151 command_line, |
2139 sentinels); | 2152 sentinels); |
2140 } | 2153 } |
2141 | 2154 |
2142 bool AreSwitchesIdenticalToCurrentCommandLine( | 2155 bool AreSwitchesIdenticalToCurrentCommandLine( |
2143 const CommandLine& new_cmdline, const CommandLine& active_cmdline) { | 2156 const CommandLine& new_cmdline, |
| 2157 const CommandLine& active_cmdline, |
| 2158 std::set<CommandLine::StringType>* out_difference) { |
2144 std::set<CommandLine::StringType> new_flags = | 2159 std::set<CommandLine::StringType> new_flags = |
2145 ExtractFlagsFromCommandLine(new_cmdline); | 2160 ExtractFlagsFromCommandLine(new_cmdline); |
2146 std::set<CommandLine::StringType> active_flags = | 2161 std::set<CommandLine::StringType> active_flags = |
2147 ExtractFlagsFromCommandLine(active_cmdline); | 2162 ExtractFlagsFromCommandLine(active_cmdline); |
2148 | 2163 |
| 2164 bool result = false; |
2149 // Needed because std::equal doesn't check if the 2nd set is empty. | 2165 // Needed because std::equal doesn't check if the 2nd set is empty. |
2150 if (new_flags.size() != active_flags.size()) | 2166 if (new_flags.size() == active_flags.size()) { |
2151 return false; | 2167 result = |
| 2168 std::equal(new_flags.begin(), new_flags.end(), active_flags.begin()); |
| 2169 } |
2152 | 2170 |
2153 return std::equal(new_flags.begin(), new_flags.end(), active_flags.begin()); | 2171 if (out_difference && !result) { |
| 2172 std::set_symmetric_difference( |
| 2173 new_flags.begin(), |
| 2174 new_flags.end(), |
| 2175 active_flags.begin(), |
| 2176 active_flags.end(), |
| 2177 std::inserter(*out_difference, out_difference->begin())); |
| 2178 } |
| 2179 |
| 2180 return result; |
2154 } | 2181 } |
2155 | 2182 |
2156 void GetFlagsExperimentsData(FlagsStorage* flags_storage, | 2183 void GetFlagsExperimentsData(FlagsStorage* flags_storage, |
2157 FlagAccess access, | 2184 FlagAccess access, |
2158 base::ListValue* supported_experiments, | 2185 base::ListValue* supported_experiments, |
2159 base::ListValue* unsupported_experiments) { | 2186 base::ListValue* unsupported_experiments) { |
2160 std::set<std::string> enabled_experiments; | 2187 std::set<std::string> enabled_experiments; |
2161 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); | 2188 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); |
2162 | 2189 |
2163 int current_platform = GetCurrentPlatform(); | 2190 int current_platform = GetCurrentPlatform(); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 action += *it; | 2278 action += *it; |
2252 content::RecordComputedAction(action); | 2279 content::RecordComputedAction(action); |
2253 } | 2280 } |
2254 // Since flag metrics are recorded every startup, add a tick so that the | 2281 // Since flag metrics are recorded every startup, add a tick so that the |
2255 // stats can be made meaningful. | 2282 // stats can be made meaningful. |
2256 if (flags.size()) | 2283 if (flags.size()) |
2257 content::RecordAction(UserMetricsAction("AboutFlags_StartupTick")); | 2284 content::RecordAction(UserMetricsAction("AboutFlags_StartupTick")); |
2258 content::RecordAction(UserMetricsAction("StartupTick")); | 2285 content::RecordAction(UserMetricsAction("StartupTick")); |
2259 } | 2286 } |
2260 | 2287 |
| 2288 uint32_t GetSwitchUMAId(const std::string& switch_name) { |
| 2289 return static_cast<uint32_t>(metrics::HashMetricName(switch_name)); |
| 2290 } |
| 2291 |
| 2292 void ReportCustomFlags(const std::string& uma_histogram_hame, |
| 2293 const std::set<std::string>& command_line_difference) { |
| 2294 for (std::set<std::string>::const_iterator it = |
| 2295 command_line_difference.begin(); |
| 2296 it != command_line_difference.end(); |
| 2297 ++it) { |
| 2298 int uma_id = about_flags::kBadSwitchFormatHistogramId; |
| 2299 if (StartsWithASCII(*it, "--", true /* case_sensitive */)) { |
| 2300 // Skip '--' before switch name. |
| 2301 std::string switch_name(it->substr(2)); |
| 2302 |
| 2303 // Kill value, if any. |
| 2304 const size_t value_pos = switch_name.find('='); |
| 2305 if (value_pos != std::string::npos) |
| 2306 switch_name.resize(value_pos); |
| 2307 |
| 2308 uma_id = GetSwitchUMAId(switch_name); |
| 2309 } else { |
| 2310 NOTREACHED() << "ReportCustomFlags(): flag '" << *it |
| 2311 << "' has incorrect format."; |
| 2312 } |
| 2313 DVLOG(1) << "ReportCustomFlags(): histogram='" << uma_histogram_hame |
| 2314 << "' '" << *it << "', uma_id=" << uma_id; |
| 2315 |
| 2316 // Sparse histogram macro does not cache the histogram, so it's safe |
| 2317 // to use macro with non-static histogram name here. |
| 2318 UMA_HISTOGRAM_SPARSE_SLOWLY(uma_histogram_hame, uma_id); |
| 2319 } |
| 2320 } |
| 2321 |
2261 ////////////////////////////////////////////////////////////////////////////// | 2322 ////////////////////////////////////////////////////////////////////////////// |
2262 // FlagsState implementation. | 2323 // FlagsState implementation. |
2263 | 2324 |
2264 namespace { | 2325 namespace { |
2265 | 2326 |
2266 typedef std::map<std::string, std::pair<std::string, std::string> > | 2327 typedef std::map<std::string, std::pair<std::string, std::string> > |
2267 NameToSwitchAndValueMap; | 2328 NameToSwitchAndValueMap; |
2268 | 2329 |
2269 void SetFlagToSwitchMapping(const std::string& key, | 2330 void SetFlagToSwitchMapping(const std::string& key, |
2270 const std::string& switch_name, | 2331 const std::string& switch_name, |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2450 } | 2511 } |
2451 | 2512 |
2452 const Experiment* GetExperiments(size_t* count) { | 2513 const Experiment* GetExperiments(size_t* count) { |
2453 *count = num_experiments; | 2514 *count = num_experiments; |
2454 return experiments; | 2515 return experiments; |
2455 } | 2516 } |
2456 | 2517 |
2457 } // namespace testing | 2518 } // namespace testing |
2458 | 2519 |
2459 } // namespace about_flags | 2520 } // namespace about_flags |
OLD | NEW |