| 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 |