Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(746)

Side by Side Diff: chrome/browser/about_flags.cc

Issue 344883002: Collect UMA statistics on which chrome://flags lead to chrome restart on ChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update after review. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
14 #include "base/stl_util.h" 15 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
17 #include "base/values.h" 18 #include "base/values.h"
18 #include "cc/base/switches.h" 19 #include "cc/base/switches.h"
19 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h" 20 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h"
20 #include "chrome/browser/flags_storage.h" 21 #include "chrome/browser/flags_storage.h"
21 #include "chrome/common/chrome_content_client.h" 22 #include "chrome/common/chrome_content_client.h"
22 #include "chrome/common/chrome_switches.h" 23 #include "chrome/common/chrome_switches.h"
23 #include "components/autofill/core/common/autofill_switches.h" 24 #include "components/autofill/core/common/autofill_switches.h"
24 #include "components/cloud_devices/common/cloud_devices_switches.h" 25 #include "components/cloud_devices/common/cloud_devices_switches.h"
25 #include "components/nacl/common/nacl_switches.h" 26 #include "components/nacl/common/nacl_switches.h"
26 #include "content/public/browser/user_metrics.h" 27 #include "content/public/browser/user_metrics.h"
27 #include "extensions/common/switches.h" 28 #include "extensions/common/switches.h"
28 #include "grit/chromium_strings.h" 29 #include "grit/chromium_strings.h"
29 #include "grit/generated_resources.h" 30 #include "grit/generated_resources.h"
30 #include "grit/google_chrome_strings.h" 31 #include "grit/google_chrome_strings.h"
31 #include "media/base/media_switches.h" 32 #include "media/base/media_switches.h"
33 #include "third_party/zlib/zlib.h"
32 #include "ui/base/l10n/l10n_util.h" 34 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/ui_base_switches.h" 35 #include "ui/base/ui_base_switches.h"
34 #include "ui/display/display_switches.h" 36 #include "ui/display/display_switches.h"
35 #include "ui/events/event_switches.h" 37 #include "ui/events/event_switches.h"
36 #include "ui/gfx/switches.h" 38 #include "ui/gfx/switches.h"
37 #include "ui/gl/gl_switches.h" 39 #include "ui/gl/gl_switches.h"
38 #include "ui/keyboard/keyboard_switches.h" 40 #include "ui/keyboard/keyboard_switches.h"
39 #include "ui/native_theme/native_theme_switches.h" 41 #include "ui/native_theme/native_theme_switches.h"
40 #include "ui/views/views_switches.h" 42 #include "ui/views/views_switches.h"
41 43
(...skipping 12 matching lines...) Expand all
54 #endif 56 #endif
55 57
56 #if defined(ENABLE_APP_LIST) 58 #if defined(ENABLE_APP_LIST)
57 #include "ui/app_list/app_list_switches.h" 59 #include "ui/app_list/app_list_switches.h"
58 #endif 60 #endif
59 61
60 using base::UserMetricsAction; 62 using base::UserMetricsAction;
61 63
62 namespace about_flags { 64 namespace about_flags {
63 65
66 const uint32_t kBadSwitchFormatHistogramId = 0;
67
64 // Macros to simplify specifying the type. 68 // Macros to simplify specifying the type.
65 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ 69 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \
66 Experiment::SINGLE_VALUE, \ 70 Experiment::SINGLE_VALUE, \
67 command_line_switch, switch_value, NULL, NULL, NULL, 0 71 command_line_switch, switch_value, NULL, NULL, NULL, 0
68 #define SINGLE_VALUE_TYPE(command_line_switch) \ 72 #define SINGLE_VALUE_TYPE(command_line_switch) \
69 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") 73 SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "")
70 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ 74 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \
71 disable_switch, disable_value) \ 75 disable_switch, disable_value) \
72 Experiment::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ 76 Experiment::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \
73 disable_switch, disable_value, NULL, 3 77 disable_switch, disable_value, NULL, 3
(...skipping 1435 matching lines...) Expand 10 before | Expand all | Expand 10 after
1509 }, 1513 },
1510 #endif 1514 #endif
1511 #if defined(OS_ANDROID) 1515 #if defined(OS_ANDROID)
1512 { 1516 {
1513 "enable-accessibility-tab-switcher", 1517 "enable-accessibility-tab-switcher",
1514 IDS_FLAGS_ENABLE_ACCESSIBILITY_TAB_SWITCHER_NAME, 1518 IDS_FLAGS_ENABLE_ACCESSIBILITY_TAB_SWITCHER_NAME,
1515 IDS_FLAGS_ENABLE_ACCESSIBILITY_TAB_SWITCHER_DESCRIPTION, 1519 IDS_FLAGS_ENABLE_ACCESSIBILITY_TAB_SWITCHER_DESCRIPTION,
1516 kOsAndroid, 1520 kOsAndroid,
1517 SINGLE_VALUE_TYPE(switches::kEnableAccessibilityTabSwitcher) 1521 SINGLE_VALUE_TYPE(switches::kEnableAccessibilityTabSwitcher)
1518 }, 1522 },
1519 {
1520 // TODO(dmazzoni): remove this flag when native android accessibility
1521 // ships in the stable channel. http://crbug.com/356775
1522 "enable-accessibility-script-injection",
1523 IDS_FLAGS_ENABLE_ACCESSIBILITY_SCRIPT_INJECTION_NAME,
1524 IDS_FLAGS_ENABLE_ACCESSIBILITY_SCRIPT_INJECTION_DESCRIPTION,
1525 kOsAndroid,
1526 // Java-only switch: ContentSwitches.ENABLE_ACCESSIBILITY_SCRIPT_INJECTION.
1527 SINGLE_VALUE_TYPE("enable-accessibility-script-injection")
1528 },
Ilya Sherman 2014/08/05 20:14:46 This diff seems unrelated to your CL.
Alexander Alekseev 2014/08/07 23:24:55 As this CL doesn't have explicit UMA IDs, this par
Ilya Sherman 2014/08/08 03:49:45 If this switch is obsolete, I'd prefer that you re
Alexander Alekseev 2014/08/09 01:30:00 Done.
1529 #endif 1523 #endif
1530 { 1524 {
1531 "enable-one-copy", 1525 "enable-one-copy",
1532 IDS_FLAGS_ONE_COPY_NAME, 1526 IDS_FLAGS_ONE_COPY_NAME,
1533 IDS_FLAGS_ONE_COPY_DESCRIPTION, 1527 IDS_FLAGS_ONE_COPY_DESCRIPTION,
1534 kOsAll, 1528 kOsAll,
1535 SINGLE_VALUE_TYPE(switches::kEnableOneCopy) 1529 SINGLE_VALUE_TYPE(switches::kEnableOneCopy)
1536 }, 1530 },
1537 { 1531 {
1538 "enable-zero-copy", 1532 "enable-zero-copy",
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
1947 SentinelsMode sentinels); 1941 SentinelsMode sentinels);
1948 bool IsRestartNeededToCommitChanges(); 1942 bool IsRestartNeededToCommitChanges();
1949 void SetExperimentEnabled( 1943 void SetExperimentEnabled(
1950 FlagsStorage* flags_storage, 1944 FlagsStorage* flags_storage,
1951 const std::string& internal_name, 1945 const std::string& internal_name,
1952 bool enable); 1946 bool enable);
1953 void RemoveFlagsSwitches( 1947 void RemoveFlagsSwitches(
1954 std::map<std::string, CommandLine::StringType>* switch_list); 1948 std::map<std::string, CommandLine::StringType>* switch_list);
1955 void ResetAllFlags(FlagsStorage* flags_storage); 1949 void ResetAllFlags(FlagsStorage* flags_storage);
1956 void reset(); 1950 void reset();
1951 std::set<std::string> GetAllSwitchesForTesting() const;
1957 1952
1958 // Returns the singleton instance of this class 1953 // Returns the singleton instance of this class
1959 static FlagsState* GetInstance() { 1954 static FlagsState* GetInstance() {
1960 return Singleton<FlagsState>::get(); 1955 return Singleton<FlagsState>::get();
1961 } 1956 }
1962 1957
1963 private: 1958 private:
1964 bool needs_restart_; 1959 bool needs_restart_;
1965 std::map<std::string, std::string> flags_switches_; 1960 std::map<std::string, std::string> flags_switches_;
1966 1961
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
2137 2132
2138 void ConvertFlagsToSwitches(FlagsStorage* flags_storage, 2133 void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
2139 CommandLine* command_line, 2134 CommandLine* command_line,
2140 SentinelsMode sentinels) { 2135 SentinelsMode sentinels) {
2141 FlagsState::GetInstance()->ConvertFlagsToSwitches(flags_storage, 2136 FlagsState::GetInstance()->ConvertFlagsToSwitches(flags_storage,
2142 command_line, 2137 command_line,
2143 sentinels); 2138 sentinels);
2144 } 2139 }
2145 2140
2146 bool AreSwitchesIdenticalToCurrentCommandLine( 2141 bool AreSwitchesIdenticalToCurrentCommandLine(
2147 const CommandLine& new_cmdline, const CommandLine& active_cmdline) { 2142 const CommandLine& new_cmdline,
2143 const CommandLine& active_cmdline,
2144 std::set<CommandLine::StringType>* out_difference) {
2148 std::set<CommandLine::StringType> new_flags = 2145 std::set<CommandLine::StringType> new_flags =
2149 ExtractFlagsFromCommandLine(new_cmdline); 2146 ExtractFlagsFromCommandLine(new_cmdline);
2150 std::set<CommandLine::StringType> active_flags = 2147 std::set<CommandLine::StringType> active_flags =
2151 ExtractFlagsFromCommandLine(active_cmdline); 2148 ExtractFlagsFromCommandLine(active_cmdline);
2152 2149
2150 bool result = false;
2153 // Needed because std::equal doesn't check if the 2nd set is empty. 2151 // Needed because std::equal doesn't check if the 2nd set is empty.
2154 if (new_flags.size() != active_flags.size()) 2152 if (new_flags.size() == active_flags.size()) {
2155 return false; 2153 result =
2154 std::equal(new_flags.begin(), new_flags.end(), active_flags.begin());
2155 }
2156 2156
2157 return std::equal(new_flags.begin(), new_flags.end(), active_flags.begin()); 2157 if (out_difference && !result) {
2158 std::set_symmetric_difference(
2159 new_flags.begin(),
2160 new_flags.end(),
2161 active_flags.begin(),
2162 active_flags.end(),
2163 std::inserter(*out_difference, out_difference->begin()));
2164 }
2165
2166 return result;
2158 } 2167 }
2159 2168
2160 void GetFlagsExperimentsData(FlagsStorage* flags_storage, 2169 void GetFlagsExperimentsData(FlagsStorage* flags_storage,
2161 FlagAccess access, 2170 FlagAccess access,
2162 base::ListValue* supported_experiments, 2171 base::ListValue* supported_experiments,
2163 base::ListValue* unsupported_experiments) { 2172 base::ListValue* unsupported_experiments) {
2164 std::set<std::string> enabled_experiments; 2173 std::set<std::string> enabled_experiments;
2165 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments); 2174 GetSanitizedEnabledFlags(flags_storage, &enabled_experiments);
2166 2175
2167 int current_platform = GetCurrentPlatform(); 2176 int current_platform = GetCurrentPlatform();
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2255 action += *it; 2264 action += *it;
2256 content::RecordComputedAction(action); 2265 content::RecordComputedAction(action);
2257 } 2266 }
2258 // Since flag metrics are recorded every startup, add a tick so that the 2267 // Since flag metrics are recorded every startup, add a tick so that the
2259 // stats can be made meaningful. 2268 // stats can be made meaningful.
2260 if (flags.size()) 2269 if (flags.size())
2261 content::RecordAction(UserMetricsAction("AboutFlags_StartupTick")); 2270 content::RecordAction(UserMetricsAction("AboutFlags_StartupTick"));
2262 content::RecordAction(UserMetricsAction("StartupTick")); 2271 content::RecordAction(UserMetricsAction("StartupTick"));
2263 } 2272 }
2264 2273
2274 uint32 GetSwitchUMAId(const std::string& switch_name) {
2275 return static_cast<unsigned>(
Ilya Sherman 2014/08/05 20:14:46 Please cast directly to the returned type, i.e. ui
Alexander Alekseev 2014/08/07 23:24:56 Done.
2276 crc32(0,
Ilya Sherman 2014/08/05 20:14:46 Optional: md5 is more commonly used for UMA code.
Alexander Alekseev 2014/08/07 23:24:56 On a server-side it looks like uint32, so it doesn
Ilya Sherman 2014/08/08 03:49:45 The only reason that special support might be usef
2277 reinterpret_cast<const Bytef*>(switch_name.c_str()),
2278 switch_name.length()));
2279 }
2280
2281 void ReportCustomFlags(const std::string& uma_histogram_hame,
2282 const std::set<std::string>& command_line_difference) {
2283 for (std::set<std::string>::const_iterator it =
2284 command_line_difference.begin();
2285 it != command_line_difference.end();
2286 ++it) {
2287 int uma_id = about_flags::kBadSwitchFormatHistogramId;
2288 if (it->size() > 2) {
Ilya Sherman 2014/08/05 20:14:46 It seems more appropriate to check the actual char
Alexander Alekseev 2014/08/07 23:24:56 Done.
2289 // Skip '--' before switch name.
2290 std::string switch_name(it->substr(2));
2291
2292 // Kill value, if any.
2293 const size_t value_pos = switch_name.find('=');
2294 if (value_pos != std::string::npos)
2295 switch_name.resize(value_pos);
2296
2297 uma_id = GetSwitchUMAId(switch_name);
2298 } else {
2299 NOTREACHED() << "ReportCustomFlags(): flag '" << *it
2300 << "' has incorrect format.";
2301 }
2302 VLOG(1) << "ReportCustomFlags(): histogram='" << uma_histogram_hame << "' '"
2303 << *it << "', uma_id=" << uma_id;
2304
2305 // Sparse histogram macro does not cache the histogram, so it's safe
2306 // to use macro with non-static histogram name here.
2307 UMA_HISTOGRAM_SPARSE_SLOWLY(uma_histogram_hame, uma_id);
2308 }
2309 }
2310
2311 std::set<std::string> GetAllSwitchesForTesting() {
2312 return FlagsState::GetInstance()->GetAllSwitchesForTesting();
2313 }
2314
2265 ////////////////////////////////////////////////////////////////////////////// 2315 //////////////////////////////////////////////////////////////////////////////
2266 // FlagsState implementation. 2316 // FlagsState implementation.
2267 2317
2268 namespace { 2318 namespace {
2269 2319
2270 typedef std::map<std::string, std::pair<std::string, std::string> > 2320 typedef std::map<std::string, std::pair<std::string, std::string> >
2271 NameToSwitchAndValueMap; 2321 NameToSwitchAndValueMap;
2272 2322
2273 void SetFlagToSwitchMapping(const std::string& key, 2323 void SetFlagToSwitchMapping(const std::string& key,
2274 const std::string& switch_name, 2324 const std::string& switch_name,
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2424 2474
2425 std::set<std::string> no_experiments; 2475 std::set<std::string> no_experiments;
2426 flags_storage->SetFlags(no_experiments); 2476 flags_storage->SetFlags(no_experiments);
2427 } 2477 }
2428 2478
2429 void FlagsState::reset() { 2479 void FlagsState::reset() {
2430 needs_restart_ = false; 2480 needs_restart_ = false;
2431 flags_switches_.clear(); 2481 flags_switches_.clear();
2432 } 2482 }
2433 2483
2484 std::set<std::string> FlagsState::GetAllSwitchesForTesting() const {
2485 std::set<std::string> result;
2486
2487 for (size_t i = 0; i < num_experiments; ++i) {
2488 const Experiment& e = experiments[i];
Ilya Sherman 2014/08/05 20:14:46 nit: Please use complete variable names rather tha
Alexander Alekseev 2014/08/07 23:24:56 Done.
2489 if (e.type == Experiment::SINGLE_VALUE) {
2490 result.insert(e.command_line_switch);
2491 } else if (e.type == Experiment::MULTI_VALUE) {
2492 for (int j = 0; j < e.num_choices; ++j) {
2493 result.insert(e.choices[j].command_line_switch);
2494 }
2495 } else {
2496 DCHECK_EQ(e.type, Experiment::ENABLE_DISABLE_VALUE);
2497 result.insert(e.command_line_switch);
2498 result.insert(e.disable_command_line_switch);
2499 }
2500 }
2501 return result;
2502 }
Ilya Sherman 2014/08/05 20:14:46 Why isn't this in the testing namespace below? In
Alexander Alekseev 2014/08/07 23:24:56 Done.
2503
2434 } // namespace 2504 } // namespace
2435 2505
2436 namespace testing { 2506 namespace testing {
2437 2507
2438 // WARNING: '@' is also used in the html file. If you update this constant you 2508 // WARNING: '@' is also used in the html file. If you update this constant you
2439 // also need to update the html file. 2509 // also need to update the html file.
2440 const char kMultiSeparator[] = "@"; 2510 const char kMultiSeparator[] = "@";
2441 2511
2442 void ClearState() { 2512 void ClearState() {
2443 FlagsState::GetInstance()->reset(); 2513 FlagsState::GetInstance()->reset();
(...skipping 10 matching lines...) Expand all
2454 } 2524 }
2455 2525
2456 const Experiment* GetExperiments(size_t* count) { 2526 const Experiment* GetExperiments(size_t* count) {
2457 *count = num_experiments; 2527 *count = num_experiments;
2458 return experiments; 2528 return experiments;
2459 } 2529 }
2460 2530
2461 } // namespace testing 2531 } // namespace testing
2462 2532
2463 } // namespace about_flags 2533 } // namespace about_flags
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698