Home | History | Annotate | Download | only in browser
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/about_flags.h"
      6 
      7 #include <algorithm>
      8 #include <iterator>
      9 #include <map>
     10 #include <set>
     11 #include <utility>
     12 
     13 #include "ash/ash_switches.h"
     14 #include "base/command_line.h"
     15 #include "base/memory/singleton.h"
     16 #include "base/strings/string_number_conversions.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "base/values.h"
     19 #include "cc/base/switches.h"
     20 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h"
     21 #include "chrome/browser/flags_storage.h"
     22 #include "chrome/common/chrome_content_client.h"
     23 #include "chrome/common/chrome_switches.h"
     24 #include "components/autofill/core/common/autofill_switches.h"
     25 #include "components/nacl/common/nacl_switches.h"
     26 #include "content/public/browser/user_metrics.h"
     27 #include "extensions/common/switches.h"
     28 #include "grit/chromium_strings.h"
     29 #include "grit/generated_resources.h"
     30 #include "grit/google_chrome_strings.h"
     31 #include "media/base/media_switches.h"
     32 #include "ui/base/l10n/l10n_util.h"
     33 #include "ui/base/ui_base_switches.h"
     34 #include "ui/compositor/compositor_switches.h"
     35 #include "ui/events/event_switches.h"
     36 #include "ui/gfx/switches.h"
     37 #include "ui/gl/gl_switches.h"
     38 #include "ui/keyboard/keyboard_switches.h"
     39 #include "ui/message_center/message_center_switches.h"
     40 #include "ui/surface/surface_switches.h"
     41 #include "ui/views/views_switches.h"
     42 
     43 #if defined(USE_ASH)
     44 #include "ash/ash_switches.h"
     45 #endif
     46 
     47 #if defined(OS_CHROMEOS)
     48 #include "chromeos/chromeos_switches.h"
     49 #include "third_party/cros_system_api/switches/chrome_switches.h"
     50 #endif
     51 
     52 #if defined(ENABLE_APP_LIST)
     53 #include "ui/app_list/app_list_switches.h"
     54 #endif
     55 
     56 using content::UserMetricsAction;
     57 
     58 namespace about_flags {
     59 
     60 // Macros to simplify specifying the type.
     61 #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \
     62     Experiment::SINGLE_VALUE, \
     63     command_line_switch, switch_value, NULL, NULL, NULL, 0
     64 #define SINGLE_VALUE_TYPE(command_line_switch) \
     65     SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "")
     66 #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \
     67                                             disable_switch, disable_value) \
     68     Experiment::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \
     69     disable_switch, disable_value, NULL, 3
     70 #define ENABLE_DISABLE_VALUE_TYPE(enable_switch, disable_switch) \
     71     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, "", disable_switch, "")
     72 #define MULTI_VALUE_TYPE(choices) \
     73     Experiment::MULTI_VALUE, NULL, NULL, NULL, NULL, choices, arraysize(choices)
     74 
     75 namespace {
     76 
     77 const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid;
     78 const unsigned kOsDesktop = kOsMac | kOsWin | kOsLinux | kOsCrOS;
     79 
     80 // Adds a |StringValue| to |list| for each platform where |bitmask| indicates
     81 // whether the experiment is available on that platform.
     82 void AddOsStrings(unsigned bitmask, ListValue* list) {
     83   struct {
     84     unsigned bit;
     85     const char* const name;
     86   } kBitsToOs[] = {
     87     {kOsMac, "Mac"},
     88     {kOsWin, "Windows"},
     89     {kOsLinux, "Linux"},
     90     {kOsCrOS, "Chrome OS"},
     91     {kOsAndroid, "Android"},
     92     {kOsCrOSOwnerOnly, "Chrome OS (owner only)"},
     93   };
     94   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kBitsToOs); ++i)
     95     if (bitmask & kBitsToOs[i].bit)
     96       list->Append(new StringValue(kBitsToOs[i].name));
     97 }
     98 
     99 // Convert switch constants to proper CommandLine::StringType strings.
    100 CommandLine::StringType GetSwitchString(const std::string& flag) {
    101   CommandLine cmd_line(CommandLine::NO_PROGRAM);
    102   cmd_line.AppendSwitch(flag);
    103   DCHECK(cmd_line.argv().size() == 2);
    104   return cmd_line.argv()[1];
    105 }
    106 
    107 // Scoops flags from a command line.
    108 std::set<CommandLine::StringType> ExtractFlagsFromCommandLine(
    109     const CommandLine& cmdline) {
    110   std::set<CommandLine::StringType> flags;
    111   // First do the ones between --flag-switches-begin and --flag-switches-end.
    112   CommandLine::StringVector::const_iterator first =
    113       std::find(cmdline.argv().begin(), cmdline.argv().end(),
    114                 GetSwitchString(switches::kFlagSwitchesBegin));
    115   CommandLine::StringVector::const_iterator last =
    116       std::find(cmdline.argv().begin(), cmdline.argv().end(),
    117                 GetSwitchString(switches::kFlagSwitchesEnd));
    118   if (first != cmdline.argv().end() && last != cmdline.argv().end())
    119     flags.insert(first + 1, last);
    120 #if defined(OS_CHROMEOS)
    121   // Then add those between --policy-switches-begin and --policy-switches-end.
    122   first = std::find(cmdline.argv().begin(), cmdline.argv().end(),
    123                     GetSwitchString(chromeos::switches::kPolicySwitchesBegin));
    124   last = std::find(cmdline.argv().begin(), cmdline.argv().end(),
    125                    GetSwitchString(chromeos::switches::kPolicySwitchesEnd));
    126   if (first != cmdline.argv().end() && last != cmdline.argv().end())
    127     flags.insert(first + 1, last);
    128 #endif
    129   return flags;
    130 }
    131 
    132 const Experiment::Choice kEnableCompositingForFixedPositionChoices[] = {
    133   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    134   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    135     switches::kEnableCompositingForFixedPosition, ""},
    136   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    137     switches::kDisableCompositingForFixedPosition, ""},
    138   { IDS_FLAGS_COMPOSITING_FOR_FIXED_POSITION_HIGH_DPI,
    139     switches::kEnableHighDpiCompositingForFixedPosition, ""}
    140 };
    141 
    142 const Experiment::Choice kEnableCompositingForTransitionChoices[] = {
    143   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    144   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    145     switches::kEnableCompositingForTransition, ""},
    146   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    147     switches::kDisableCompositingForTransition, ""},
    148 };
    149 
    150 const Experiment::Choice kEnableAcceleratedFixedRootBackgroundChoices[] = {
    151   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    152   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    153     switches::kEnableAcceleratedFixedRootBackground, ""},
    154   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    155     switches::kDisableAcceleratedFixedRootBackground, ""},
    156 };
    157 
    158 const Experiment::Choice kTouchEventsChoices[] = {
    159   { IDS_GENERIC_EXPERIMENT_CHOICE_AUTOMATIC, "", "" },
    160   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    161     switches::kTouchEvents,
    162     switches::kTouchEventsEnabled },
    163   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    164     switches::kTouchEvents,
    165     switches::kTouchEventsDisabled }
    166 };
    167 
    168 const Experiment::Choice kTouchOptimizedUIChoices[] = {
    169   { IDS_GENERIC_EXPERIMENT_CHOICE_AUTOMATIC, "", "" },
    170   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    171     switches::kTouchOptimizedUI,
    172     switches::kTouchOptimizedUIEnabled },
    173   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    174     switches::kTouchOptimizedUI,
    175     switches::kTouchOptimizedUIDisabled }
    176 };
    177 
    178 const Experiment::Choice kNaClDebugMaskChoices[] = {
    179   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    180   // Secure shell can be used on ChromeOS for forwarding the TCP port opened by
    181   // debug stub to a remote machine. Since secure shell uses NaCl, we provide
    182   // an option to switch off its debugging.
    183   { IDS_NACL_DEBUG_MASK_CHOICE_EXCLUDE_UTILS,
    184       switches::kNaClDebugMask, "!*://*/*ssh_client.nmf" },
    185   { IDS_NACL_DEBUG_MASK_CHOICE_INCLUDE_DEBUG,
    186       switches::kNaClDebugMask, "*://*/*debug.nmf" }
    187 };
    188 
    189 const Experiment::Choice kImplSidePaintingChoices[] = {
    190   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    191   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    192     cc::switches::kEnableImplSidePainting, ""},
    193   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    194     cc::switches::kDisableImplSidePainting, ""}
    195 };
    196 
    197 const Experiment::Choice kDeadlineSchedulingChoices[] = {
    198   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    199   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    200     switches::kEnableDeadlineScheduling, ""},
    201   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    202     switches::kDisableDeadlineScheduling, ""}
    203 };
    204 
    205 const Experiment::Choice kUIDeadlineSchedulingChoices[] = {
    206   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    207   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    208     switches::kUIEnableDeadlineScheduling, ""},
    209   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    210     switches::kUIDisableDeadlineScheduling, ""}
    211 };
    212 
    213 const Experiment::Choice kLCDTextChoices[] = {
    214   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    215   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED, cc::switches::kEnableLCDText, ""},
    216   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED, cc::switches::kDisableLCDText, ""}
    217 };
    218 
    219 const Experiment::Choice kDelegatedRendererChoices[] = {
    220   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    221   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    222     switches::kEnableDelegatedRenderer, ""},
    223   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    224     switches::kDisableDelegatedRenderer, ""}
    225 };
    226 
    227 const Experiment::Choice kMaxTilesForInterestAreaChoices[] = {
    228   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    229   { IDS_FLAGS_MAX_TILES_FOR_INTEREST_AREA_SHORT,
    230     cc::switches::kMaxTilesForInterestArea, "64"},
    231   { IDS_FLAGS_MAX_TILES_FOR_INTEREST_AREA_TALL,
    232     cc::switches::kMaxTilesForInterestArea, "128"},
    233   { IDS_FLAGS_MAX_TILES_FOR_INTEREST_AREA_GRANDE,
    234     cc::switches::kMaxTilesForInterestArea, "256"},
    235   { IDS_FLAGS_MAX_TILES_FOR_INTEREST_AREA_VENTI,
    236     cc::switches::kMaxTilesForInterestArea, "512"}
    237 };
    238 
    239 const Experiment::Choice kDefaultTileWidthChoices[] = {
    240   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    241   { IDS_FLAGS_DEFAULT_TILE_WIDTH_SHORT,
    242     switches::kDefaultTileWidth, "128"},
    243   { IDS_FLAGS_DEFAULT_TILE_WIDTH_TALL,
    244     switches::kDefaultTileWidth, "256"},
    245   { IDS_FLAGS_DEFAULT_TILE_WIDTH_GRANDE,
    246     switches::kDefaultTileWidth, "512"},
    247   { IDS_FLAGS_DEFAULT_TILE_WIDTH_VENTI,
    248     switches::kDefaultTileWidth, "1024"}
    249 };
    250 
    251 #if defined(USE_ASH)
    252 const Experiment::Choice kAshOverviewDelayChoices[] = {
    253   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    254   { IDS_FLAGS_OVERVIEW_DELAY_INSTANT,
    255     ash::switches::kAshOverviewDelayOnAltTab, "0" },
    256   { IDS_FLAGS_OVERVIEW_DELAY_SHORT,
    257     ash::switches::kAshOverviewDelayOnAltTab, "100" },
    258   { IDS_FLAGS_OVERVIEW_DELAY_LONG,
    259     ash::switches::kAshOverviewDelayOnAltTab, "500" },
    260   { IDS_FLAGS_OVERVIEW_DELAY_NEVER,
    261     ash::switches::kAshOverviewDelayOnAltTab, "10000" },
    262 };
    263 #endif
    264 
    265 const Experiment::Choice kDefaultTileHeightChoices[] = {
    266   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    267   { IDS_FLAGS_DEFAULT_TILE_HEIGHT_SHORT,
    268     switches::kDefaultTileHeight, "128"},
    269   { IDS_FLAGS_DEFAULT_TILE_HEIGHT_TALL,
    270     switches::kDefaultTileHeight, "256"},
    271   { IDS_FLAGS_DEFAULT_TILE_HEIGHT_GRANDE,
    272     switches::kDefaultTileHeight, "512"},
    273   { IDS_FLAGS_DEFAULT_TILE_HEIGHT_VENTI,
    274     switches::kDefaultTileHeight, "1024"}
    275 };
    276 
    277 const Experiment::Choice kSimpleCacheBackendChoices[] = {
    278   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    279   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    280     switches::kUseSimpleCacheBackend, "off" },
    281   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    282     switches::kUseSimpleCacheBackend, "on"}
    283 };
    284 
    285 #if defined(USE_AURA)
    286 const Experiment::Choice kTabCaptureUpscaleQualityChoices[] = {
    287   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    288   { IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_FAST,
    289     switches::kTabCaptureUpscaleQuality, "fast" },
    290   { IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_GOOD,
    291     switches::kTabCaptureUpscaleQuality, "good" },
    292   { IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_BEST,
    293     switches::kTabCaptureUpscaleQuality, "best" },
    294 };
    295 
    296 const Experiment::Choice kTabCaptureDownscaleQualityChoices[] = {
    297   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    298   { IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_FAST,
    299     switches::kTabCaptureDownscaleQuality, "fast" },
    300   { IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_GOOD,
    301     switches::kTabCaptureDownscaleQuality, "good" },
    302   { IDS_FLAGS_TAB_CAPTURE_SCALE_QUALITY_BEST,
    303     switches::kTabCaptureDownscaleQuality, "best" },
    304 };
    305 #endif
    306 
    307 const Experiment::Choice kMapImageChoices[] = {
    308   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    309   { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
    310     cc::switches::kEnableMapImage, ""},
    311   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    312     cc::switches::kDisableMapImage, ""}
    313 };
    314 
    315 #if defined(OS_ANDROID)
    316 const Experiment::Choice kZeroSuggestExperimentsChoices[] = {
    317   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    318   { IDS_FLAGS_ZERO_SUGGEST_MOST_VISITED,
    319     switches::kEnableZeroSuggestMostVisited, ""},
    320   { IDS_FLAGS_ZERO_SUGGEST_ETHER_SERP,
    321     switches::kEnableZeroSuggestEtherSerp, ""},
    322   { IDS_FLAGS_ZERO_SUGGEST_ETHER_NO_SERP,
    323     switches::kEnableZeroSuggestEtherNoSerp, ""},
    324   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    325     switches::kDisableZeroSuggest, ""}
    326 };
    327 #endif
    328 
    329 const Experiment::Choice kNumRasterThreadsChoices[] = {
    330   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    331   { IDS_FLAGS_NUM_RASTER_THREADS_ONE, cc::switches::kNumRasterThreads, "1" },
    332   { IDS_FLAGS_NUM_RASTER_THREADS_TWO, cc::switches::kNumRasterThreads, "2" },
    333   { IDS_FLAGS_NUM_RASTER_THREADS_THREE, cc::switches::kNumRasterThreads, "3" },
    334   { IDS_FLAGS_NUM_RASTER_THREADS_FOUR, cc::switches::kNumRasterThreads, "4" }
    335 };
    336 
    337 // We're using independent flags here (as opposed to a common flag with
    338 // different values) to be able to enable/disable the entire experience
    339 // associated with this feature server-side from the FieldTrial (the complete
    340 // experience includes other flag changes as well). It is not currently possible
    341 // to do that with "flag=value" flags.
    342 const Experiment::Choice kSearchButtonInOmniboxChoices[] = {
    343   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
    344   { IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
    345     switches::kDisableSearchButtonInOmnibox, ""},
    346   { IDS_FLAGS_SEARCH_BUTTON_IN_OMNIBOX_ENABLE_FOR_STR,
    347     switches::kEnableSearchButtonInOmniboxForStr, ""},
    348   { IDS_FLAGS_SEARCH_BUTTON_IN_OMNIBOX_ENABLE_FOR_STR_OR_IIP,
    349     switches::kEnableSearchButtonInOmniboxForStrOrIip, ""},
    350   { IDS_FLAGS_SEARCH_BUTTON_IN_OMNIBOX_ENABLED,
    351     switches::kEnableSearchButtonInOmniboxAlways, ""}
    352 };
    353 
    354 // RECORDING USER METRICS FOR FLAGS:
    355 // -----------------------------------------------------------------------------
    356 // The first line of the experiment is the internal name. If you'd like to
    357 // gather statistics about the usage of your flag, you should append a marker
    358 // comment to the end of the feature name, like so:
    359 //   "my-special-feature",  // FLAGS:RECORD_UMA
    360 //
    361 // After doing that, run //tools/metrics/actions/extract_actions.py (see
    362 // instructions at the top of that file for details) to update the
    363 // chromeactions.txt file, which will enable UMA to record your feature flag.
    364 //
    365 // After your feature has shipped under a flag, you can locate the metrics under
    366 // the action name AboutFlags_internal-action-name. Actions are recorded once
    367 // per startup, so you should divide this number by AboutFlags_StartupTick to
    368 // get a sense of usage. Note that this will not be the same as number of users
    369 // with a given feature enabled because users can quit and relaunch the
    370 // application multiple times over a given time interval. The dashboard also
    371 // shows you how many (metrics reporting) users have enabled the flag over the
    372 // last seven days. However, note that this is not the same as the number of
    373 // users who have the flag enabled, since enabling the flag happens once,
    374 // whereas running with the flag enabled happens until the user flips the flag
    375 // again.
    376 
    377 // To add a new experiment add to the end of kExperiments. There are two
    378 // distinct types of experiments:
    379 // . SINGLE_VALUE: experiment is either on or off. Use the SINGLE_VALUE_TYPE
    380 //   macro for this type supplying the command line to the macro.
    381 // . MULTI_VALUE: a list of choices, the first of which should correspond to a
    382 //   deactivated state for this lab (i.e. no command line option).  To specify
    383 //   this type of experiment use the macro MULTI_VALUE_TYPE supplying it the
    384 //   array of choices.
    385 // See the documentation of Experiment for details on the fields.
    386 //
    387 // When adding a new choice, add it to the end of the list.
    388 const Experiment kExperiments[] = {
    389   {
    390     "expose-for-tabs",  // FLAGS:RECORD_UMA
    391     IDS_FLAGS_TABPOSE_NAME,
    392     IDS_FLAGS_TABPOSE_DESCRIPTION,
    393     kOsMac,
    394 #if defined(OS_MACOSX)
    395     // The switch exists only on OS X.
    396     SINGLE_VALUE_TYPE(switches::kEnableExposeForTabs)
    397 #else
    398     SINGLE_VALUE_TYPE("")
    399 #endif
    400   },
    401   {
    402     "conflicting-modules-check",  // FLAGS:RECORD_UMA
    403     IDS_FLAGS_CONFLICTS_CHECK_NAME,
    404     IDS_FLAGS_CONFLICTS_CHECK_DESCRIPTION,
    405     kOsWin,
    406     SINGLE_VALUE_TYPE(switches::kConflictingModulesCheck)
    407   },
    408   {
    409     "ignore-gpu-blacklist",
    410     IDS_FLAGS_IGNORE_GPU_BLACKLIST_NAME,
    411     IDS_FLAGS_IGNORE_GPU_BLACKLIST_DESCRIPTION,
    412     kOsAll,
    413     SINGLE_VALUE_TYPE(switches::kIgnoreGpuBlacklist)
    414   },
    415   {
    416     "force-compositing-mode-2",
    417     IDS_FLAGS_FORCE_COMPOSITING_MODE_NAME,
    418     IDS_FLAGS_FORCE_COMPOSITING_MODE_DESCRIPTION,
    419     kOsMac | kOsLinux,
    420     ENABLE_DISABLE_VALUE_TYPE(switches::kForceCompositingMode,
    421                               switches::kDisableForceCompositingMode)
    422   },
    423   {
    424     "threaded-compositing-mode",
    425     IDS_FLAGS_THREADED_COMPOSITING_MODE_NAME,
    426     IDS_FLAGS_THREADED_COMPOSITING_MODE_DESCRIPTION,
    427     kOsMac | kOsLinux,
    428     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableThreadedCompositing,
    429                               switches::kDisableThreadedCompositing)
    430   },
    431   {
    432     "force-accelerated-composited-scrolling",
    433      IDS_FLAGS_FORCE_ACCELERATED_OVERFLOW_SCROLL_MODE_NAME,
    434      IDS_FLAGS_FORCE_ACCELERATED_OVERFLOW_SCROLL_MODE_DESCRIPTION,
    435      kOsAll,
    436      ENABLE_DISABLE_VALUE_TYPE(switches::kEnableAcceleratedOverflowScroll,
    437                                switches::kDisableAcceleratedOverflowScroll)
    438   },
    439   {
    440     "force-universal-accelerated-composited-scrolling",
    441      IDS_FLAGS_FORCE_UNIVERSAL_ACCELERATED_OVERFLOW_SCROLL_MODE_NAME,
    442      IDS_FLAGS_FORCE_UNIVERSAL_ACCELERATED_OVERFLOW_SCROLL_MODE_DESCRIPTION,
    443      kOsAll,
    444      ENABLE_DISABLE_VALUE_TYPE(
    445          switches::kEnableUniversalAcceleratedOverflowScroll,
    446          switches::kDisableUniversalAcceleratedOverflowScroll)
    447   },
    448 #if defined(OS_WIN)
    449   {
    450     "enable-direct-write",
    451     IDS_FLAGS_ENABLE_DIRECT_WRITE_NAME,
    452     IDS_FLAGS_ENABLE_DIRECT_WRITE_DESCRIPTION,
    453     kOsWin,
    454     SINGLE_VALUE_TYPE(switches::kEnableDirectWrite)
    455   },
    456 #endif
    457   {
    458     "enable-experimental-canvas-features",
    459     IDS_FLAGS_ENABLE_EXPERIMENTAL_CANVAS_FEATURES_NAME,
    460     IDS_FLAGS_ENABLE_EXPERIMENTAL_CANVAS_FEATURES_DESCRIPTION,
    461     kOsAll,
    462     SINGLE_VALUE_TYPE(switches::kEnableExperimentalCanvasFeatures)
    463   },
    464   {
    465     "disable-accelerated-2d-canvas",
    466     IDS_FLAGS_DISABLE_ACCELERATED_2D_CANVAS_NAME,
    467     IDS_FLAGS_DISABLE_ACCELERATED_2D_CANVAS_DESCRIPTION,
    468     kOsAll,
    469     SINGLE_VALUE_TYPE(switches::kDisableAccelerated2dCanvas)
    470   },
    471   {
    472     "composited-layer-borders",
    473     IDS_FLAGS_COMPOSITED_LAYER_BORDERS,
    474     IDS_FLAGS_COMPOSITED_LAYER_BORDERS_DESCRIPTION,
    475     kOsAll,
    476     SINGLE_VALUE_TYPE(cc::switches::kShowCompositedLayerBorders)
    477   },
    478   {
    479     "show-fps-counter",
    480     IDS_FLAGS_SHOW_FPS_COUNTER,
    481     IDS_FLAGS_SHOW_FPS_COUNTER_DESCRIPTION,
    482     kOsAll,
    483     SINGLE_VALUE_TYPE(cc::switches::kShowFPSCounter)
    484   },
    485   {
    486     "accelerated-filters",
    487     IDS_FLAGS_ACCELERATED_FILTERS,
    488     IDS_FLAGS_ACCELERATED_FILTERS_DESCRIPTION,
    489     kOsAll,
    490     SINGLE_VALUE_TYPE(switches::kEnableAcceleratedFilters)
    491   },
    492   {
    493     "disable-webgl",
    494     IDS_FLAGS_DISABLE_WEBGL_NAME,
    495     IDS_FLAGS_DISABLE_WEBGL_DESCRIPTION,
    496     kOsAll,
    497     SINGLE_VALUE_TYPE(switches::kDisableExperimentalWebGL)
    498   },
    499   {
    500     "enable-d3d11",
    501     IDS_FLAGS_ENABLE_D3D11_NAME,
    502     IDS_FLAGS_ENABLE_D3D11_DESCRIPTION,
    503     kOsWin,
    504     SINGLE_VALUE_TYPE(switches::kEnableD3D11)
    505   },
    506   {
    507     "disable-webrtc",
    508     IDS_FLAGS_DISABLE_WEBRTC_NAME,
    509     IDS_FLAGS_DISABLE_WEBRTC_DESCRIPTION,
    510     kOsAndroid,
    511 #if defined(OS_ANDROID)
    512     SINGLE_VALUE_TYPE(switches::kDisableWebRTC)
    513 #else
    514     SINGLE_VALUE_TYPE("")
    515 #endif
    516   },
    517 #if defined(ENABLE_WEBRTC)
    518   {
    519     "disable-device-enumeration",
    520     IDS_FLAGS_DISABLE_DEVICE_ENUMERATION_NAME,
    521     IDS_FLAGS_DISABLE_DEVICE_ENUMERATION_DESCRIPTION,
    522     kOsAll,
    523     SINGLE_VALUE_TYPE(switches::kDisableDeviceEnumeration)
    524   },
    525   {
    526     "disable-sctp-data-channels",
    527     IDS_FLAGS_DISABLE_SCTP_DATA_CHANNELS_NAME,
    528     IDS_FLAGS_DISABLE_SCTP_DATA_CHANNELS_DESCRIPTION,
    529     kOsAll,
    530     SINGLE_VALUE_TYPE(switches::kDisableSCTPDataChannels)
    531   },
    532   {
    533     "disable-webrtc-hw-decoding",
    534     IDS_FLAGS_DISABLE_WEBRTC_HW_DECODING_NAME,
    535     IDS_FLAGS_DISABLE_WEBRTC_HW_DECODING_DESCRIPTION,
    536     kOsAndroid | kOsCrOS,
    537     SINGLE_VALUE_TYPE(switches::kDisableWebRtcHWDecoding)
    538   },
    539   {
    540     "disable-webrtc-hw-encoding",
    541     IDS_FLAGS_DISABLE_WEBRTC_HW_ENCODING_NAME,
    542     IDS_FLAGS_DISABLE_WEBRTC_HW_ENCODING_DESCRIPTION,
    543     kOsAndroid | kOsCrOS,
    544     SINGLE_VALUE_TYPE(switches::kDisableWebRtcHWEncoding)
    545   },
    546 #endif
    547 #if defined(OS_ANDROID)
    548 #if defined(ARCH_CPU_X86)
    549   {
    550       "enable-webaudio",
    551       IDS_FLAGS_ENABLE_WEBAUDIO_NAME,
    552       IDS_FLAGS_ENABLE_WEBAUDIO_DESCRIPTION,
    553       kOsAndroid,
    554       SINGLE_VALUE_TYPE(switches::kEnableWebAudio)
    555   },
    556 #else
    557   {
    558     "disable-webaudio",
    559     IDS_FLAGS_DISABLE_WEBAUDIO_NAME,
    560     IDS_FLAGS_DISABLE_WEBAUDIO_DESCRIPTION,
    561     kOsAndroid,
    562     SINGLE_VALUE_TYPE(switches::kDisableWebAudio)
    563   },
    564 #endif
    565 #endif
    566   {
    567     "fixed-position-creates-stacking-context",
    568     IDS_FLAGS_FIXED_POSITION_CREATES_STACKING_CONTEXT_NAME,
    569     IDS_FLAGS_FIXED_POSITION_CREATES_STACKING_CONTEXT_DESCRIPTION,
    570     kOsAll,
    571     ENABLE_DISABLE_VALUE_TYPE(
    572         switches::kEnableFixedPositionCreatesStackingContext,
    573         switches::kDisableFixedPositionCreatesStackingContext)
    574   },
    575   {
    576     "enable-compositing-for-fixed-position",
    577     IDS_FLAGS_COMPOSITING_FOR_FIXED_POSITION_NAME,
    578     IDS_FLAGS_COMPOSITING_FOR_FIXED_POSITION_DESCRIPTION,
    579     kOsAll,
    580     MULTI_VALUE_TYPE(kEnableCompositingForFixedPositionChoices)
    581   },
    582   {
    583     "enable-compositing-for-transition",
    584     IDS_FLAGS_COMPOSITING_FOR_TRANSITION_NAME,
    585     IDS_FLAGS_COMPOSITING_FOR_TRANSITION_DESCRIPTION,
    586     kOsAll,
    587     MULTI_VALUE_TYPE(kEnableCompositingForTransitionChoices)
    588   },
    589   {
    590     "enable-accelerated-fixed-root-background",
    591     IDS_FLAGS_ACCELERATED_FIXED_ROOT_BACKGROUND_NAME,
    592     IDS_FLAGS_ACCELERATED_FIXED_ROOT_BACKGROUND_DESCRIPTION,
    593     kOsAll,
    594     MULTI_VALUE_TYPE(kEnableAcceleratedFixedRootBackgroundChoices)
    595   },
    596   // TODO(bbudge): When NaCl is on by default, remove this flag entry.
    597   {
    598     "enable-nacl",  // FLAGS:RECORD_UMA
    599     IDS_FLAGS_ENABLE_NACL_NAME,
    600     IDS_FLAGS_ENABLE_NACL_DESCRIPTION,
    601     kOsDesktop,
    602     SINGLE_VALUE_TYPE(switches::kEnableNaCl)
    603   },
    604   {
    605     "enable-nacl-debug",  // FLAGS:RECORD_UMA
    606     IDS_FLAGS_ENABLE_NACL_DEBUG_NAME,
    607     IDS_FLAGS_ENABLE_NACL_DEBUG_DESCRIPTION,
    608     kOsDesktop,
    609     SINGLE_VALUE_TYPE(switches::kEnableNaClDebug)
    610   },
    611   {
    612     "disable-pnacl",  // FLAGS:RECORD_UMA
    613     IDS_FLAGS_DISABLE_PNACL_NAME,
    614     IDS_FLAGS_DISABLE_PNACL_DESCRIPTION,
    615     kOsDesktop,
    616     SINGLE_VALUE_TYPE(switches::kDisablePnacl)
    617   },
    618   {
    619     "nacl-debug-mask",  // FLAGS:RECORD_UMA
    620     IDS_FLAGS_NACL_DEBUG_MASK_NAME,
    621     IDS_FLAGS_NACL_DEBUG_MASK_DESCRIPTION,
    622     kOsDesktop,
    623     MULTI_VALUE_TYPE(kNaClDebugMaskChoices)
    624   },
    625   {
    626     "extension-apis",  // FLAGS:RECORD_UMA
    627     IDS_FLAGS_EXPERIMENTAL_EXTENSION_APIS_NAME,
    628     IDS_FLAGS_EXPERIMENTAL_EXTENSION_APIS_DESCRIPTION,
    629     kOsDesktop,
    630     SINGLE_VALUE_TYPE(extensions::switches::kEnableExperimentalExtensionApis)
    631   },
    632   {
    633     "extensions-on-chrome-urls",
    634     IDS_FLAGS_EXTENSIONS_ON_CHROME_URLS_NAME,
    635     IDS_FLAGS_EXTENSIONS_ON_CHROME_URLS_DESCRIPTION,
    636     kOsAll,
    637     SINGLE_VALUE_TYPE(extensions::switches::kExtensionsOnChromeURLs)
    638   },
    639   {
    640     "enable-fast-unload",
    641     IDS_FLAGS_ENABLE_FAST_UNLOAD_NAME,
    642     IDS_FLAGS_ENABLE_FAST_UNLOAD_DESCRIPTION,
    643     kOsAll,
    644     SINGLE_VALUE_TYPE(switches::kEnableFastUnload)
    645   },
    646   {
    647     "enable-adview",
    648     IDS_FLAGS_ENABLE_ADVIEW_NAME,
    649     IDS_FLAGS_ENABLE_ADVIEW_DESCRIPTION,
    650     kOsDesktop,
    651     SINGLE_VALUE_TYPE(switches::kEnableAdview)
    652   },
    653   {
    654     "enable-adview-src-attribute",
    655     IDS_FLAGS_ENABLE_ADVIEW_SRC_ATTRIBUTE_NAME,
    656     IDS_FLAGS_ENABLE_ADVIEW_SRC_ATTRIBUTE_DESCRIPTION,
    657     kOsDesktop,
    658     SINGLE_VALUE_TYPE(switches::kEnableAdviewSrcAttribute)
    659   },
    660   {
    661     "enable-app-window-controls",
    662     IDS_FLAGS_ENABLE_APP_WINDOW_CONTROLS_NAME,
    663     IDS_FLAGS_ENABLE_APP_WINDOW_CONTROLS_DESCRIPTION,
    664     kOsDesktop,
    665     SINGLE_VALUE_TYPE(switches::kEnableAppWindowControls)
    666   },
    667   {
    668     "script-badges",
    669     IDS_FLAGS_SCRIPT_BADGES_NAME,
    670     IDS_FLAGS_SCRIPT_BADGES_DESCRIPTION,
    671     kOsDesktop,
    672     SINGLE_VALUE_TYPE(extensions::switches::kScriptBadges)
    673   },
    674   {
    675     "script-bubble",
    676     IDS_FLAGS_SCRIPT_BUBBLE_NAME,
    677     IDS_FLAGS_SCRIPT_BUBBLE_DESCRIPTION,
    678     kOsDesktop,
    679     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(
    680         extensions::switches::kScriptBubble, "1",
    681         extensions::switches::kScriptBubble, "0")
    682   },
    683   {
    684     "apps-new-install-bubble",
    685     IDS_FLAGS_APPS_NEW_INSTALL_BUBBLE_NAME,
    686     IDS_FLAGS_APPS_NEW_INSTALL_BUBBLE_DESCRIPTION,
    687     kOsDesktop,
    688     SINGLE_VALUE_TYPE(switches::kAppsNewInstallBubble)
    689   },
    690   {
    691     "disable-hyperlink-auditing",
    692     IDS_FLAGS_DISABLE_HYPERLINK_AUDITING_NAME,
    693     IDS_FLAGS_DISABLE_HYPERLINK_AUDITING_DESCRIPTION,
    694     kOsAll,
    695     SINGLE_VALUE_TYPE(switches::kNoPings)
    696   },
    697   {
    698     "tab-groups-context-menu",
    699     IDS_FLAGS_TAB_GROUPS_CONTEXT_MENU_NAME,
    700     IDS_FLAGS_TAB_GROUPS_CONTEXT_MENU_DESCRIPTION,
    701     kOsWin,
    702     SINGLE_VALUE_TYPE(switches::kEnableTabGroupsContextMenu)
    703   },
    704 #if defined(OS_ANDROID)
    705   {
    706     "enable-new-ntp",
    707     IDS_FLAGS_ENABLE_NEW_NTP,
    708     IDS_FLAGS_ENABLE_NEW_NTP_DESCRIPTION,
    709     kOsAndroid,
    710     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableNewNTP,
    711                               switches::kDisableNewNTP)
    712   },
    713 #endif
    714   {
    715     "show-autofill-type-predictions",
    716     IDS_FLAGS_SHOW_AUTOFILL_TYPE_PREDICTIONS_NAME,
    717     IDS_FLAGS_SHOW_AUTOFILL_TYPE_PREDICTIONS_DESCRIPTION,
    718     kOsAll,
    719     SINGLE_VALUE_TYPE(autofill::switches::kShowAutofillTypePredictions)
    720   },
    721   {
    722     "enable-gesture-tap-highlight",
    723     IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_NAME,
    724     IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_DESCRIPTION,
    725     kOsLinux | kOsCrOS,
    726     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableGestureTapHighlight,
    727                               switches::kDisableGestureTapHighlight)
    728   },
    729   {
    730     "enable-smooth-scrolling",  // FLAGS:RECORD_UMA
    731     IDS_FLAGS_ENABLE_SMOOTH_SCROLLING_NAME,
    732     IDS_FLAGS_ENABLE_SMOOTH_SCROLLING_DESCRIPTION,
    733     // Can't expose the switch unless the code is compiled in.
    734     // On by default for the Mac (different implementation in WebKit).
    735     kOsWin | kOsLinux,
    736     SINGLE_VALUE_TYPE(switches::kEnableSmoothScrolling)
    737   },
    738   {
    739     "enable-overlay-scrollbars",
    740     IDS_FLAGS_ENABLE_OVERLAY_SCROLLBARS_NAME,
    741     IDS_FLAGS_ENABLE_OVERLAY_SCROLLBARS_DESCRIPTION,
    742     // Uses the system preference on Mac (a different implementation).
    743     // On Android, this is always enabled.
    744     kOsCrOS,
    745     SINGLE_VALUE_TYPE(switches::kEnableOverlayScrollbars)
    746   },
    747   {
    748     "enable-panels",
    749     IDS_FLAGS_ENABLE_PANELS_NAME,
    750     IDS_FLAGS_ENABLE_PANELS_DESCRIPTION,
    751     kOsDesktop,
    752     SINGLE_VALUE_TYPE(switches::kEnablePanels)
    753   },
    754   {
    755     // See http://crbug.com/120416 for how to remove this flag.
    756     "save-page-as-mhtml",  // FLAGS:RECORD_UMA
    757     IDS_FLAGS_SAVE_PAGE_AS_MHTML_NAME,
    758     IDS_FLAGS_SAVE_PAGE_AS_MHTML_DESCRIPTION,
    759     kOsMac | kOsWin | kOsLinux,
    760     SINGLE_VALUE_TYPE(switches::kSavePageAsMHTML)
    761   },
    762   {
    763     "enable-autologin",
    764     IDS_FLAGS_ENABLE_AUTOLOGIN_NAME,
    765     IDS_FLAGS_ENABLE_AUTOLOGIN_DESCRIPTION,
    766     kOsMac | kOsWin | kOsLinux,
    767     SINGLE_VALUE_TYPE(switches::kEnableAutologin)
    768   },
    769   {
    770     "enable-quic",
    771     IDS_FLAGS_ENABLE_QUIC_NAME,
    772     IDS_FLAGS_ENABLE_QUIC_DESCRIPTION,
    773     kOsAll,
    774     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableQuic,
    775                               switches::kDisableQuic)
    776   },
    777   {
    778     "enable-quic-https",
    779     IDS_FLAGS_ENABLE_QUIC_HTTPS_NAME,
    780     IDS_FLAGS_ENABLE_QUIC_HTTPS_DESCRIPTION,
    781     kOsAll,
    782     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableQuicHttps,
    783                               switches::kDisableQuicHttps)
    784   },
    785   {
    786     "enable-spdy4a2",
    787     IDS_FLAGS_ENABLE_SPDY4A2_NAME,
    788     IDS_FLAGS_ENABLE_SPDY4A2_DESCRIPTION,
    789     kOsAll,
    790     SINGLE_VALUE_TYPE(switches::kEnableSpdy4a2)
    791   },
    792   {
    793     "enable-http2-draft-04",
    794     IDS_FLAGS_ENABLE_HTTP2_DRAFT_04_NAME,
    795     IDS_FLAGS_ENABLE_HTTP2_DRAFT_04_DESCRIPTION,
    796     kOsAll,
    797     SINGLE_VALUE_TYPE(switches::kEnableHttp2Draft04)
    798   },
    799   {
    800     "enable-async-dns",
    801     IDS_FLAGS_ENABLE_ASYNC_DNS_NAME,
    802     IDS_FLAGS_ENABLE_ASYNC_DNS_DESCRIPTION,
    803     kOsWin | kOsMac | kOsLinux | kOsCrOS,
    804     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableAsyncDns,
    805                               switches::kDisableAsyncDns)
    806   },
    807   {
    808     "disable-webkit-media-source",
    809     IDS_FLAGS_DISABLE_WEBKIT_MEDIA_SOURCE_NAME,
    810     IDS_FLAGS_DISABLE_WEBKIT_MEDIA_SOURCE_DESCRIPTION,
    811     kOsAll,
    812     SINGLE_VALUE_TYPE(switches::kDisableWebKitMediaSource)
    813   },
    814   {
    815     "disable-unprefixed-media-source",
    816     IDS_FLAGS_DISABLE_UNPREFIXED_MEDIA_SOURCE_NAME,
    817     IDS_FLAGS_DISABLE_UNPREFIXED_MEDIA_SOURCE_DESCRIPTION,
    818     kOsAll,
    819     SINGLE_VALUE_TYPE(switches::kDisableUnprefixedMediaSource)
    820   },
    821   {
    822     "enable-encrypted-media",
    823     IDS_FLAGS_ENABLE_ENCRYPTED_MEDIA_NAME,
    824     IDS_FLAGS_ENABLE_ENCRYPTED_MEDIA_DESCRIPTION,
    825     kOsAll,
    826     SINGLE_VALUE_TYPE(switches::kEnableEncryptedMedia)
    827   },
    828   {
    829     "disable-prefixed-encrypted-media",
    830     IDS_FLAGS_DISABLE_PREFIXED_ENCRYPTED_MEDIA_NAME,
    831     IDS_FLAGS_DISABLE_PREFIXED_ENCRYPTED_MEDIA_DESCRIPTION,
    832     kOsAll,
    833     SINGLE_VALUE_TYPE(switches::kDisablePrefixedEncryptedMedia)
    834   },
    835 #if defined(OS_ANDROID)
    836   {
    837     "disable-infobar-for-protected-media-identifier",
    838     IDS_FLAGS_DISABLE_INFOBAR_FOR_PROTECTED_MEDIA_IDENTIFIER_NAME,
    839     IDS_FLAGS_DISABLE_INFOBAR_FOR_PROTECTED_MEDIA_IDENTIFIER_DESCRIPTION,
    840     kOsAndroid,
    841     SINGLE_VALUE_TYPE(switches::kDisableInfobarForProtectedMediaIdentifier)
    842   },
    843   {
    844     "mediadrm-enable-non-compositing",
    845     IDS_FLAGS_MEDIADRM_ENABLE_NON_COMPOSITING_NAME,
    846     IDS_FLAGS_MEDIADRM_ENABLE_NON_COMPOSITING_DESCRIPTION,
    847     kOsAndroid,
    848     SINGLE_VALUE_TYPE(switches::kMediaDrmEnableNonCompositing)
    849   },
    850 #endif  // defined(OS_ANDROID)
    851   {
    852     "disable-opus-playback",
    853     IDS_FLAGS_DISABLE_OPUS_PLAYBACK_NAME,
    854     IDS_FLAGS_DISABLE_OPUS_PLAYBACK_DESCRIPTION,
    855     kOsDesktop,
    856     SINGLE_VALUE_TYPE(switches::kDisableOpusPlayback)
    857   },
    858  {
    859     "disable-vp8-alpha-playback",
    860     IDS_FLAGS_DISABLE_VP8_ALPHA_PLAYBACK_NAME,
    861     IDS_FLAGS_DISABLE_VP8_ALPHA_PLAYBACK_DESCRIPTION,
    862     kOsDesktop,
    863     SINGLE_VALUE_TYPE(switches::kDisableVp8AlphaPlayback)
    864   },
    865   {
    866     "per-tile-painting",
    867     IDS_FLAGS_PER_TILE_PAINTING_NAME,
    868     IDS_FLAGS_PER_TILE_PAINTING_DESCRIPTION,
    869     kOsMac | kOsLinux | kOsCrOS,
    870     SINGLE_VALUE_TYPE(cc::switches::kEnablePerTilePainting)
    871   },
    872   {
    873     "enable-javascript-harmony",
    874     IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_NAME,
    875     IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_DESCRIPTION,
    876     kOsAll,
    877     SINGLE_VALUE_TYPE_AND_VALUE(switches::kJavaScriptFlags, "--harmony")
    878   },
    879   {
    880     "enable-tab-browser-dragging",
    881     IDS_FLAGS_ENABLE_TAB_BROWSER_DRAGGING_NAME,
    882     IDS_FLAGS_ENABLE_TAB_BROWSER_DRAGGING_DESCRIPTION,
    883     kOsWin,
    884     SINGLE_VALUE_TYPE(switches::kTabBrowserDragging)
    885   },
    886   {
    887     "disable-restore-session-state",
    888     IDS_FLAGS_DISABLE_RESTORE_SESSION_STATE_NAME,
    889     IDS_FLAGS_DISABLE_RESTORE_SESSION_STATE_DESCRIPTION,
    890     kOsAll,
    891     SINGLE_VALUE_TYPE(switches::kDisableRestoreSessionState)
    892   },
    893   {
    894     "disable-software-rasterizer",
    895     IDS_FLAGS_DISABLE_SOFTWARE_RASTERIZER_NAME,
    896     IDS_FLAGS_DISABLE_SOFTWARE_RASTERIZER_DESCRIPTION,
    897 #if defined(ENABLE_SWIFTSHADER)
    898     kOsAll,
    899 #else
    900     0,
    901 #endif
    902     SINGLE_VALUE_TYPE(switches::kDisableSoftwareRasterizer)
    903   },
    904   {
    905     "enable-experimental-web-platform-features",
    906     IDS_FLAGS_EXPERIMENTAL_WEB_PLATFORM_FEATURES_NAME,
    907     IDS_FLAGS_EXPERIMENTAL_WEB_PLATFORM_FEATURES_DESCRIPTION,
    908     kOsAll,
    909     SINGLE_VALUE_TYPE(switches::kEnableExperimentalWebPlatformFeatures)
    910   },
    911   {
    912     "disable-ntp-other-sessions-menu",
    913     IDS_FLAGS_NTP_OTHER_SESSIONS_MENU_NAME,
    914     IDS_FLAGS_NTP_OTHER_SESSIONS_MENU_DESCRIPTION,
    915     kOsDesktop,
    916     SINGLE_VALUE_TYPE(switches::kDisableNTPOtherSessionsMenu)
    917   },
    918 #if defined(USE_ASH)
    919   {
    920     "enable-ash-oak",
    921     IDS_FLAGS_ENABLE_ASH_OAK_NAME,
    922     IDS_FLAGS_ENABLE_ASH_OAK_DESCRIPTION,
    923     kOsAll,
    924     SINGLE_VALUE_TYPE(ash::switches::kAshEnableOak),
    925   },
    926 #endif
    927   {
    928     "enable-devtools-experiments",
    929     IDS_FLAGS_ENABLE_DEVTOOLS_EXPERIMENTS_NAME,
    930     IDS_FLAGS_ENABLE_DEVTOOLS_EXPERIMENTS_DESCRIPTION,
    931     kOsDesktop,
    932     SINGLE_VALUE_TYPE(switches::kEnableDevToolsExperiments)
    933   },
    934   {
    935     "silent-debugger-extension-api",
    936     IDS_FLAGS_SILENT_DEBUGGER_EXTENSION_API_NAME,
    937     IDS_FLAGS_SILENT_DEBUGGER_EXTENSION_API_DESCRIPTION,
    938     kOsDesktop,
    939     SINGLE_VALUE_TYPE(switches::kSilentDebuggerExtensionAPI)
    940   },
    941   {
    942     "enable-suggestions-ntp",
    943     IDS_FLAGS_NTP_SUGGESTIONS_PAGE_NAME,
    944     IDS_FLAGS_NTP_SUGGESTIONS_PAGE_DESCRIPTION,
    945     kOsDesktop,
    946     SINGLE_VALUE_TYPE(switches::kEnableSuggestionsTabPage)
    947   },
    948   {
    949     "spellcheck-autocorrect",
    950     IDS_FLAGS_SPELLCHECK_AUTOCORRECT,
    951     IDS_FLAGS_SPELLCHECK_AUTOCORRECT_DESCRIPTION,
    952     kOsWin | kOsLinux | kOsCrOS,
    953     SINGLE_VALUE_TYPE(switches::kEnableSpellingAutoCorrect)
    954   },
    955   {
    956     "enable-scroll-prediction",
    957     IDS_FLAGS_ENABLE_SCROLL_PREDICTION_NAME,
    958     IDS_FLAGS_ENABLE_SCROLL_PREDICTION_DESCRIPTION,
    959     kOsDesktop,
    960     SINGLE_VALUE_TYPE(switches::kEnableScrollPrediction)
    961   },
    962   {
    963     "touch-events",
    964     IDS_TOUCH_EVENTS_NAME,
    965     IDS_TOUCH_EVENTS_DESCRIPTION,
    966     kOsDesktop,
    967     MULTI_VALUE_TYPE(kTouchEventsChoices)
    968   },
    969   {
    970     "touch-optimized-ui",
    971     IDS_FLAGS_TOUCH_OPTIMIZED_UI_NAME,
    972     IDS_FLAGS_TOUCH_OPTIMIZED_UI_DESCRIPTION,
    973     kOsWin,
    974     MULTI_VALUE_TYPE(kTouchOptimizedUIChoices)
    975   },
    976   {
    977     "disable-touch-adjustment",
    978     IDS_DISABLE_TOUCH_ADJUSTMENT_NAME,
    979     IDS_DISABLE_TOUCH_ADJUSTMENT_DESCRIPTION,
    980     kOsWin | kOsLinux | kOsCrOS,
    981     SINGLE_VALUE_TYPE(switches::kDisableTouchAdjustment)
    982   },
    983 #if defined(OS_CHROMEOS)
    984   {
    985       "ash-use-alternate-shelf",
    986       IDS_FLAGS_ALTERNATE_SHELF_LAYOUT_NAME,
    987       IDS_FLAGS_ALTERNATE_SHELF_LAYOUT_DESCRIPTION,
    988       kOsCrOS,
    989       ENABLE_DISABLE_VALUE_TYPE(ash::switches::kAshUseAlternateShelfLayout,
    990                                 ash::switches::kAshDisableAlternateShelfLayout)
    991   },
    992   {
    993       "ash-disable-drag-off-shelf",
    994       IDS_FLAGS_DRAG_OFF_SHELF_NAME,
    995       IDS_FLAGS_DRAG_OFF_SHELF_DESCRIPTION,
    996       kOsCrOS,
    997       SINGLE_VALUE_TYPE(ash::switches::kAshDisableDragOffShelf)
    998   },
    999   {
   1000     "enable-background-loader",
   1001     IDS_ENABLE_BACKLOADER_NAME,
   1002     IDS_ENABLE_BACKLOADER_DESCRIPTION,
   1003     kOsCrOS,
   1004     SINGLE_VALUE_TYPE(chromeos::switches::kEnableBackgroundLoader)
   1005   },
   1006   {
   1007     "ash-enable-docked-windows",
   1008     IDS_FLAGS_DOCKED_WINDOWS_NAME,
   1009     IDS_FLAGS_DOCKED_WINDOWS_DESCRIPTION,
   1010     kOsCrOS,
   1011     SINGLE_VALUE_TYPE(ash::switches::kAshEnableDockedWindows)
   1012   },
   1013   {
   1014     "ash-enable-immersive-fullscreen-all-windows",
   1015     IDS_FLAGS_IMMERSIVE_FULLSCREEN_FOR_ALL_WINDOWS_NAME,
   1016     IDS_FLAGS_IMMERSIVE_FULLSCREEN_FOR_ALL_WINDOWS_DESCRIPTION,
   1017     kOsCrOS,
   1018     SINGLE_VALUE_TYPE(ash::switches::kAshEnableImmersiveFullscreenForAllWindows)
   1019   },
   1020 #endif
   1021   {
   1022     "enable-download-resumption",
   1023     IDS_FLAGS_ENABLE_DOWNLOAD_RESUMPTION_NAME,
   1024     IDS_FLAGS_ENABLE_DOWNLOAD_RESUMPTION_DESCRIPTION,
   1025     kOsDesktop,
   1026     SINGLE_VALUE_TYPE(switches::kEnableDownloadResumption)
   1027   },
   1028   {
   1029     "allow-nacl-socket-api",
   1030     IDS_FLAGS_ALLOW_NACL_SOCKET_API_NAME,
   1031     IDS_FLAGS_ALLOW_NACL_SOCKET_API_DESCRIPTION,
   1032     kOsDesktop,
   1033     SINGLE_VALUE_TYPE_AND_VALUE(switches::kAllowNaClSocketAPI, "*")
   1034   },
   1035   {
   1036     "stacked-tab-strip",
   1037     IDS_FLAGS_STACKED_TAB_STRIP_NAME,
   1038     IDS_FLAGS_STACKED_TAB_STRIP_DESCRIPTION,
   1039     kOsWin,
   1040     SINGLE_VALUE_TYPE(switches::kEnableStackedTabStrip)
   1041   },
   1042   {
   1043     "force-device-scale-factor",
   1044     IDS_FLAGS_FORCE_HIGH_DPI_NAME,
   1045     IDS_FLAGS_FORCE_HIGH_DPI_DESCRIPTION,
   1046     kOsCrOS,
   1047     SINGLE_VALUE_TYPE_AND_VALUE(switches::kForceDeviceScaleFactor, "2")
   1048   },
   1049 #if defined(OS_CHROMEOS)
   1050   {
   1051     "allow-touchpad-three-finger-click",
   1052     IDS_FLAGS_ALLOW_TOUCHPAD_THREE_FINGER_CLICK_NAME,
   1053     IDS_FLAGS_ALLOW_TOUCHPAD_THREE_FINGER_CLICK_DESCRIPTION,
   1054     kOsCrOS,
   1055     SINGLE_VALUE_TYPE(chromeos::switches::kEnableTouchpadThreeFingerClick)
   1056   },
   1057 #endif
   1058 #if defined(USE_ASH)
   1059   {
   1060     "show-launcher-alignment-menu",
   1061     IDS_FLAGS_SHOW_SHELF_ALIGNMENT_MENU_NAME,
   1062     IDS_FLAGS_SHOW_SHELF_ALIGNMENT_MENU_DESCRIPTION,
   1063     kOsAll,
   1064     ENABLE_DISABLE_VALUE_TYPE(
   1065         ash::switches::kShowShelfAlignmentMenu,
   1066         ash::switches::kHideShelfAlignmentMenu)
   1067   },
   1068   {
   1069     "disable-minimize-on-second-launcher-item-click",
   1070     IDS_FLAGS_DISABLE_MINIMIZE_ON_SECOND_LAUNCHER_ITEM_CLICK_NAME,
   1071     IDS_FLAGS_DISABLE_MINIMIZE_ON_SECOND_LAUNCHER_ITEM_CLICK_DESCRIPTION,
   1072     kOsAll,
   1073     SINGLE_VALUE_TYPE(switches::kDisableMinimizeOnSecondLauncherItemClick)
   1074   },
   1075   {
   1076     "multiple-snap-window-widths",
   1077     IDS_MULTIPLE_SNAP_WINDOW_WIDTHS_NAME,
   1078     IDS_MULTIPLE_SNAP_WINDOW_WIDTHS_DESCRIPTION,
   1079     kOsAll,
   1080     SINGLE_VALUE_TYPE(ash::switches::kAshMultipleSnapWindowWidths)
   1081   },
   1082   {
   1083     "disable-overview-mode",
   1084     IDS_FLAGS_DISABLE_OVERVIEW_MODE_NAME,
   1085     IDS_FLAGS_DISABLE_OVERVIEW_MODE_DESCRIPTION,
   1086     kOsCrOS,
   1087     SINGLE_VALUE_TYPE(ash::switches::kAshDisableOverviewMode)
   1088   },
   1089   {
   1090     "overview-delay-on-alt-tab",
   1091     IDS_FLAGS_OVERVIEW_DELAY_NAME,
   1092     IDS_FLAGS_OVERVIEW_DELAY_DESCRIPTION,
   1093     kOsCrOS,
   1094     MULTI_VALUE_TYPE(kAshOverviewDelayChoices)
   1095   },
   1096   {
   1097     "show-touch-hud",
   1098     IDS_FLAGS_SHOW_TOUCH_HUD_NAME,
   1099     IDS_FLAGS_SHOW_TOUCH_HUD_DESCRIPTION,
   1100     kOsAll,
   1101     SINGLE_VALUE_TYPE(ash::switches::kAshTouchHud)
   1102   },
   1103   {
   1104     "enable-pinch",
   1105     IDS_FLAGS_ENABLE_PINCH_SCALE_NAME,
   1106     IDS_FLAGS_ENABLE_PINCH_SCALE_DESCRIPTION,
   1107     kOsLinux | kOsWin | kOsCrOS,
   1108     ENABLE_DISABLE_VALUE_TYPE(switches::kEnablePinch, switches::kDisablePinch),
   1109   },
   1110   {
   1111     "enable-pinch-virtual-viewport",
   1112     IDS_FLAGS_ENABLE_PINCH_VIRTUAL_VIEWPORT_NAME,
   1113     IDS_FLAGS_ENABLE_PINCH_VIRTUAL_VIEWPORT_DESCRIPTION,
   1114     kOsLinux | kOsWin | kOsCrOS,
   1115     SINGLE_VALUE_TYPE(cc::switches::kEnablePinchVirtualViewport),
   1116   },
   1117 #endif  // defined(USE_ASH)
   1118 #if defined(OS_CHROMEOS)
   1119   {
   1120     "disable-boot-animation",
   1121     IDS_FLAGS_DISABLE_BOOT_ANIMATION,
   1122     IDS_FLAGS_DISABLE_BOOT_ANIMATION_DESCRIPTION,
   1123     kOsCrOSOwnerOnly,
   1124     SINGLE_VALUE_TYPE(chromeos::switches::kDisableBootAnimation),
   1125   },
   1126   {
   1127     "file-manager-show-checkboxes",
   1128     IDS_FLAGS_FILE_MANAGER_SHOW_CHECKBOXES_NAME,
   1129     IDS_FLAGS_FILE_MANAGER_SHOW_CHECKBOXES_DESCRIPTION,
   1130     kOsCrOS,
   1131     SINGLE_VALUE_TYPE(chromeos::switches::kFileManagerShowCheckboxes)
   1132   },
   1133   {
   1134     "file-manager-enable-webstore-integration",
   1135     IDS_FLAGS_FILE_MANAGER_ENABLE_WEBSTORE_INTEGRATION,
   1136     IDS_FLAGS_FILE_MANAGER_ENABLE_WEBSTORE_INTEGRATION_DESCRIPTION,
   1137     kOsCrOS,
   1138     SINGLE_VALUE_TYPE(chromeos::switches::kFileManagerEnableWebstoreIntegration)
   1139   },
   1140   {
   1141     "disable-quickoffice-component-app",
   1142     IDS_FLAGS_DISABLE_QUICKOFFICE_COMPONENT_APP_NAME,
   1143     IDS_FLAGS_DISABLE_QUICKOFFICE_COMPONENT_APP_DESCRIPTION,
   1144     kOsCrOS,
   1145     SINGLE_VALUE_TYPE(chromeos::switches::kDisableQuickofficeComponentApp),
   1146   },
   1147   {
   1148     "enable-saml-signin",
   1149     IDS_FLAGS_ENABLE_SAML_SIGNIN_NAME,
   1150     IDS_FLAGS_ENABLE_SAML_SIGNIN_DESCRIPTION,
   1151     kOsCrOS,
   1152     SINGLE_VALUE_TYPE(chromeos::switches::kEnableSamlSignin),
   1153   },
   1154   {
   1155     "enable-multi-profiles",
   1156     IDS_FLAGS_ENABLE_MULTI_PROFILES_NAME,
   1157     IDS_FLAGS_ENABLE_MULTI_PROFILES_DESCRIPTION,
   1158     kOsCrOS,
   1159     SINGLE_VALUE_TYPE(switches::kMultiProfiles),
   1160   },
   1161 #endif  // defined(OS_CHROMEOS)
   1162   { "disable-accelerated-video-decode",
   1163     IDS_FLAGS_DISABLE_ACCELERATED_VIDEO_DECODE_NAME,
   1164     IDS_FLAGS_DISABLE_ACCELERATED_VIDEO_DECODE_DESCRIPTION,
   1165     kOsWin | kOsCrOS,
   1166     SINGLE_VALUE_TYPE(switches::kDisableAcceleratedVideoDecode),
   1167   },
   1168   {
   1169     "enable-contacts",
   1170     IDS_FLAGS_ENABLE_CONTACTS_NAME,
   1171     IDS_FLAGS_ENABLE_CONTACTS_DESCRIPTION,
   1172     kOsCrOS,
   1173     SINGLE_VALUE_TYPE(switches::kEnableContacts)
   1174   },
   1175 #if defined(USE_ASH)
   1176   {
   1177     "ash-debug-shortcuts",
   1178     IDS_FLAGS_DEBUG_SHORTCUTS_NAME,
   1179     IDS_FLAGS_DEBUG_SHORTCUTS_DESCRIPTION,
   1180     kOsAll,
   1181     SINGLE_VALUE_TYPE(ash::switches::kAshDebugShortcuts),
   1182   },
   1183   { "ash-enable-advanced-gestures",
   1184     IDS_FLAGS_ENABLE_ADVANCED_GESTURES_NAME,
   1185     IDS_FLAGS_ENABLE_ADVANCED_GESTURES_DESCRIPTION,
   1186     kOsCrOS,
   1187     SINGLE_VALUE_TYPE(ash::switches::kAshEnableAdvancedGestures),
   1188   },
   1189   { "ash-alternate-caption-button",
   1190     IDS_FLAGS_ASH_FRAME_CAPTION_BUTTON_STYLE_NAME,
   1191     IDS_FLAGS_ASH_FRAME_CAPTION_BUTTON_STYLE_DESCRIPTION,
   1192     kOsCrOS,
   1193     ENABLE_DISABLE_VALUE_TYPE(
   1194         ash::switches::kAshEnableAlternateFrameCaptionButtonStyle,
   1195         ash::switches::kAshDisableAlternateFrameCaptionButtonStyle),
   1196   },
   1197   {
   1198     "ash-disable-auto-maximizing",
   1199     IDS_FLAGS_ASH_AUTO_MAXIMIZING_NAME,
   1200     IDS_FLAGS_ASH_AUTO_MAXIMIZING_DESCRIPTION,
   1201     kOsWin | kOsLinux | kOsCrOS,
   1202     SINGLE_VALUE_TYPE(ash::switches::kAshDisableAutoMaximizing)
   1203   },
   1204   { "ash-disable-drag-and-drop-applist-to-launcher",
   1205     IDS_FLAGS_DND_APPLIST_TO_LAUNCHER_NAME,
   1206     IDS_FLAGS_DND_APPLIST_TO_LAUNCHER_DESCRIPTION,
   1207     kOsCrOS,
   1208     SINGLE_VALUE_TYPE(ash::switches::kAshDisableDragAndDropAppListToLauncher),
   1209   },
   1210 #if defined(OS_LINUX)
   1211   { "ash-enable-memory-monitor",
   1212       IDS_FLAGS_ENABLE_MEMORY_MONITOR_NAME,
   1213       IDS_FLAGS_ENABLE_MEMORY_MONITOR_DESCRIPTION,
   1214       kOsCrOS,
   1215       SINGLE_VALUE_TYPE(ash::switches::kAshEnableMemoryMonitor),
   1216   },
   1217 #endif
   1218 #if defined(OS_CHROMEOS)
   1219   { "ash-enable-full-multi-profile-mode",
   1220       IDS_FLAGS_ENABLE_FULL_MULTI_PROFILE_MODE,
   1221       IDS_FLAGS_ENABLE_FULL_MULTI_PROFILE_MODE_DESCRIPTION,
   1222       kOsCrOS,
   1223       SINGLE_VALUE_TYPE(ash::switches::kAshEnableFullMultiProfileMode),
   1224   },
   1225   { "ash-enable-multi-user-tray",
   1226       IDS_FLAGS_ENABLE_MULTI_USER_TRAY,
   1227       IDS_FLAGS_ENABLE_MULTI_USER_TRAY_DESCRIPTION,
   1228       kOsCrOS,
   1229       SINGLE_VALUE_TYPE(ash::switches::kAshEnableMultiUserTray),
   1230   },
   1231 #endif
   1232 #endif
   1233 #if defined(OS_CHROMEOS)
   1234   {
   1235     "ash-audio-device-menu",
   1236     IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_NAME,
   1237     IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_DESCRIPTION,
   1238     kOsCrOS,
   1239     ENABLE_DISABLE_VALUE_TYPE(ash::switches::kAshEnableAudioDeviceMenu,
   1240                               ash::switches::kAshDisableAudioDeviceMenu)
   1241   },
   1242   {
   1243     "enable-carrier-switching",
   1244     IDS_FLAGS_ENABLE_CARRIER_SWITCHING,
   1245     IDS_FLAGS_ENABLE_CARRIER_SWITCHING_DESCRIPTION,
   1246     kOsCrOS,
   1247     SINGLE_VALUE_TYPE(chromeos::switches::kEnableCarrierSwitching)
   1248   },
   1249   {
   1250     "enable-request-tablet-site",
   1251     IDS_FLAGS_ENABLE_REQUEST_TABLET_SITE_NAME,
   1252     IDS_FLAGS_ENABLE_REQUEST_TABLET_SITE_DESCRIPTION,
   1253     kOsCrOS,
   1254     SINGLE_VALUE_TYPE(chromeos::switches::kEnableRequestTabletSite)
   1255   },
   1256 #endif
   1257   {
   1258     "debug-packed-apps",
   1259     IDS_FLAGS_DEBUG_PACKED_APP_NAME,
   1260     IDS_FLAGS_DEBUG_PACKED_APP_DESCRIPTION,
   1261     kOsDesktop,
   1262     SINGLE_VALUE_TYPE(switches::kDebugPackedApps)
   1263   },
   1264   {
   1265     "enable-password-generation",
   1266     IDS_FLAGS_ENABLE_PASSWORD_GENERATION_NAME,
   1267     IDS_FLAGS_ENABLE_PASSWORD_GENERATION_DESCRIPTION,
   1268     kOsDesktop,
   1269     ENABLE_DISABLE_VALUE_TYPE(autofill::switches::kEnablePasswordGeneration,
   1270                               autofill::switches::kDisablePasswordGeneration)
   1271   },
   1272   {
   1273     "password-manager-reauthentication",
   1274     IDS_FLAGS_PASSWORD_MANAGER_REAUTHENTICATION_NAME,
   1275     IDS_FLAGS_PASSWORD_MANAGER_REAUTHENTICATION_DESCRIPTION,
   1276     kOsMac | kOsWin,
   1277     SINGLE_VALUE_TYPE(switches::kDisablePasswordManagerReauthentication)
   1278   },
   1279   {
   1280     "password-autofill-public-suffix-domain-matching",
   1281     IDS_FLAGS_PASSWORD_AUTOFILL_PUBLIC_SUFFIX_DOMAIN_MATCHING_NAME,
   1282     IDS_FLAGS_PASSWORD_AUTOFILL_PUBLIC_SUFFIX_DOMAIN_MATCHING_DESCRIPTION,
   1283     kOsAndroid,
   1284     ENABLE_DISABLE_VALUE_TYPE(
   1285         switches::kEnablePasswordAutofillPublicSuffixDomainMatching,
   1286         switches::kDisablePasswordAutofillPublicSuffixDomainMatching)
   1287   },
   1288   {
   1289     "enable-deferred-image-decoding",
   1290     IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_NAME,
   1291     IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_DESCRIPTION,
   1292     kOsMac | kOsLinux | kOsCrOS,
   1293     SINGLE_VALUE_TYPE(switches::kEnableDeferredImageDecoding)
   1294   },
   1295   {
   1296     "performance-monitor-gathering",
   1297     IDS_FLAGS_PERFORMANCE_MONITOR_GATHERING_NAME,
   1298     IDS_FLAGS_PERFORMANCE_MONITOR_GATHERING_DESCRIPTION,
   1299     kOsAll,
   1300     SINGLE_VALUE_TYPE(switches::kPerformanceMonitorGathering)
   1301   },
   1302   {
   1303     "wallet-service-use-sandbox",
   1304     IDS_FLAGS_WALLET_SERVICE_USE_SANDBOX_NAME,
   1305     IDS_FLAGS_WALLET_SERVICE_USE_SANDBOX_DESCRIPTION,
   1306     kOsCrOS | kOsWin | kOsMac,
   1307     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(
   1308         autofill::switches::kWalletServiceUseSandbox, "1",
   1309         autofill::switches::kWalletServiceUseSandbox, "0")
   1310   },
   1311   {
   1312     "enable-interactive-autocomplete",
   1313     IDS_FLAGS_ENABLE_INTERACTIVE_AUTOCOMPLETE_NAME,
   1314     IDS_FLAGS_ENABLE_INTERACTIVE_AUTOCOMPLETE_DESCRIPTION,
   1315     kOsWin | kOsCrOS | kOsAndroid | kOsMac,
   1316     ENABLE_DISABLE_VALUE_TYPE(
   1317         autofill::switches::kEnableInteractiveAutocomplete,
   1318         autofill::switches::kDisableInteractiveAutocomplete)
   1319   },
   1320 #if defined(USE_AURA)
   1321   {
   1322     "overscroll-history-navigation",
   1323     IDS_FLAGS_OVERSCROLL_HISTORY_NAVIGATION_NAME,
   1324     IDS_FLAGS_OVERSCROLL_HISTORY_NAVIGATION_DESCRIPTION,
   1325     kOsAll,
   1326     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(
   1327         switches::kOverscrollHistoryNavigation, "1",
   1328         switches::kOverscrollHistoryNavigation, "0")
   1329   },
   1330 #endif
   1331   {
   1332     "scroll-end-effect",
   1333     IDS_FLAGS_SCROLL_END_EFFECT_NAME,
   1334     IDS_FLAGS_SCROLL_END_EFFECT_DESCRIPTION,
   1335     kOsCrOS,
   1336     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(
   1337         switches::kScrollEndEffect, "1",
   1338         switches::kScrollEndEffect, "0")
   1339   },
   1340   {
   1341     "enable-touch-side-bezels",
   1342     IDS_FLAGS_ENABLE_TOUCH_SIDE_BEZELS_NAME,
   1343     IDS_FLAGS_ENABLE_TOUCH_SIDE_BEZELS_DESCRIPTION,
   1344     kOsCrOS,
   1345     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(
   1346         switches::kTouchSideBezels, "1",
   1347         switches::kTouchSideBezels, "0")
   1348   },
   1349   {
   1350     "enable-touch-drag-drop",
   1351     IDS_FLAGS_ENABLE_TOUCH_DRAG_DROP_NAME,
   1352     IDS_FLAGS_ENABLE_TOUCH_DRAG_DROP_DESCRIPTION,
   1353     kOsWin | kOsCrOS,
   1354     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableTouchDragDrop,
   1355                               switches::kDisableTouchDragDrop)
   1356   },
   1357   {
   1358     "enable-touch-editing",
   1359     IDS_FLAGS_ENABLE_TOUCH_EDITING_NAME,
   1360     IDS_FLAGS_ENABLE_TOUCH_EDITING_DESCRIPTION,
   1361     kOsCrOS,
   1362     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableTouchEditing,
   1363                               switches::kDisableTouchEditing)
   1364   },
   1365   {
   1366     "enable-rich-notifications",
   1367     IDS_FLAGS_ENABLE_RICH_NOTIFICATIONS_NAME,
   1368     IDS_FLAGS_ENABLE_RICH_NOTIFICATIONS_DESCRIPTION,
   1369     kOsWin | kOsMac,
   1370     ENABLE_DISABLE_VALUE_TYPE(
   1371         message_center::switches::kEnableRichNotifications,
   1372         message_center::switches::kDisableRichNotifications)
   1373   },
   1374   {
   1375     "enable-experimental-notification-ui",
   1376     IDS_FLAGS_ENABLE_EXPERIMENTAL_NOTIFICATION_UI_NAME,
   1377     IDS_FLAGS_ENABLE_EXPERIMENTAL_NOTIFICATION_UI_DESCRIPTION,
   1378     kOsDesktop,
   1379     SINGLE_VALUE_TYPE(
   1380         message_center::switches::kEnableExperimentalNotificationUI)
   1381   },
   1382   {
   1383     "enable-sync-synced-notifications",
   1384     IDS_FLAGS_ENABLE_SYNCED_NOTIFICATIONS_NAME,
   1385     IDS_FLAGS_ENABLE_SYNCED_NOTIFICATIONS_DESCRIPTION,
   1386     kOsDesktop,
   1387     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableSyncSyncedNotifications,
   1388                               switches::kDisableSyncSyncedNotifications)
   1389   },
   1390   {
   1391     "disable-full-history-sync",
   1392     IDS_FLAGS_FULL_HISTORY_SYNC_NAME,
   1393     IDS_FLAGS_FULL_HISTORY_SYNC_DESCRIPTION,
   1394     kOsAll,
   1395     SINGLE_VALUE_TYPE(switches::kHistoryDisableFullHistorySync)
   1396   },
   1397   {
   1398     "enable-usermedia-screen-capture",
   1399     IDS_FLAGS_ENABLE_SCREEN_CAPTURE_NAME,
   1400     IDS_FLAGS_ENABLE_SCREEN_CAPTURE_DESCRIPTION,
   1401     kOsDesktop,
   1402     SINGLE_VALUE_TYPE(switches::kEnableUserMediaScreenCapturing)
   1403   },
   1404   {
   1405     "enable-apps-devtool-app",
   1406     IDS_FLAGS_ENABLE_APPS_DEVTOOL_APP_NAME,
   1407     IDS_FLAGS_ENABLE_APPS_DEVTOOL_APP_DESCRIPTION,
   1408     kOsDesktop,
   1409     SINGLE_VALUE_TYPE(switches::kAppsDevtool)
   1410   },
   1411   {
   1412     "impl-side-painting",
   1413     IDS_FLAGS_IMPL_SIDE_PAINTING_NAME,
   1414     IDS_FLAGS_IMPL_SIDE_PAINTING_DESCRIPTION,
   1415     kOsAll,
   1416     MULTI_VALUE_TYPE(kImplSidePaintingChoices)
   1417   },
   1418   {
   1419     "deadline-scheduling",
   1420     IDS_FLAGS_DEADLINE_SCHEDULING_NAME,
   1421     IDS_FLAGS_DEADLINE_SCHEDULING_DESCRIPTION,
   1422     kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid,
   1423     MULTI_VALUE_TYPE(kDeadlineSchedulingChoices)
   1424   },
   1425   {
   1426     "ui-deadline-scheduling",
   1427     IDS_FLAGS_UI_DEADLINE_SCHEDULING_NAME,
   1428     IDS_FLAGS_UI_DEADLINE_SCHEDULING_DESCRIPTION,
   1429 #ifdef USE_AURA
   1430     kOsWin | kOsLinux |
   1431 #endif
   1432     kOsCrOS,
   1433     MULTI_VALUE_TYPE(kUIDeadlineSchedulingChoices)
   1434   },
   1435   {
   1436     "lcd-text-aa",
   1437     IDS_FLAGS_LCD_TEXT_NAME,
   1438     IDS_FLAGS_LCD_TEXT_DESCRIPTION,
   1439     kOsDesktop,
   1440     MULTI_VALUE_TYPE(kLCDTextChoices)
   1441   },
   1442   {
   1443     "delegated-renderer",
   1444     IDS_FLAGS_DELEGATED_RENDERER_NAME,
   1445     IDS_FLAGS_DELEGATED_RENDERER_DESCRIPTION,
   1446 #ifdef USE_AURA
   1447     kOsWin | kOsLinux |
   1448 #endif
   1449     kOsAndroid | kOsCrOS,
   1450     MULTI_VALUE_TYPE(kDelegatedRendererChoices)
   1451   },
   1452   {
   1453     "enable-websocket-experimental-implementation",
   1454     IDS_FLAGS_ENABLE_EXPERIMENTAL_WEBSOCKET_NAME,
   1455     IDS_FLAGS_ENABLE_EXPERIMENTAL_WEBSOCKET_DESCRIPTION,
   1456     kOsAll,
   1457     SINGLE_VALUE_TYPE(switches::kEnableExperimentalWebSocket)
   1458   },
   1459   {
   1460     "max-tiles-for-interest-area",
   1461     IDS_FLAGS_MAX_TILES_FOR_INTEREST_AREA_NAME,
   1462     IDS_FLAGS_MAX_TILES_FOR_INTEREST_AREA_DESCRIPTION,
   1463     kOsAll,
   1464     MULTI_VALUE_TYPE(kMaxTilesForInterestAreaChoices)
   1465   },
   1466   {
   1467     "enable-offline-mode",
   1468     IDS_FLAGS_ENABLE_OFFLINE_MODE_NAME,
   1469     IDS_FLAGS_ENABLE_OFFLINE_MODE_DESCRIPTION,
   1470     kOsAll,
   1471     SINGLE_VALUE_TYPE(switches::kEnableOfflineCacheAccess)
   1472   },
   1473   {
   1474     "default-tile-width",
   1475     IDS_FLAGS_DEFAULT_TILE_WIDTH_NAME,
   1476     IDS_FLAGS_DEFAULT_TILE_WIDTH_DESCRIPTION,
   1477     kOsAll,
   1478     MULTI_VALUE_TYPE(kDefaultTileWidthChoices)
   1479   },
   1480   {
   1481     "default-tile-height",
   1482     IDS_FLAGS_DEFAULT_TILE_HEIGHT_NAME,
   1483     IDS_FLAGS_DEFAULT_TILE_HEIGHT_DESCRIPTION,
   1484     kOsAll,
   1485     MULTI_VALUE_TYPE(kDefaultTileHeightChoices)
   1486   },
   1487   // TODO(sky): ifdef needed until focus sorted out in DesktopNativeWidgetAura.
   1488 #if !defined(USE_AURA)
   1489   {
   1490     "track-active-visit-time",
   1491     IDS_FLAGS_TRACK_ACTIVE_VISIT_TIME_NAME,
   1492     IDS_FLAGS_TRACK_ACTIVE_VISIT_TIME_DESCRIPTION,
   1493     kOsWin,
   1494     SINGLE_VALUE_TYPE(switches::kTrackActiveVisitTime)
   1495   },
   1496 #endif
   1497 #if defined(OS_ANDROID)
   1498   {
   1499     "disable-gesture-requirement-for-media-playback",
   1500     IDS_FLAGS_DISABLE_GESTURE_REQUIREMENT_FOR_MEDIA_PLAYBACK_NAME,
   1501     IDS_FLAGS_DISABLE_GESTURE_REQUIREMENT_FOR_MEDIA_PLAYBACK_DESCRIPTION,
   1502     kOsAndroid,
   1503     SINGLE_VALUE_TYPE(switches::kDisableGestureRequirementForMediaPlayback)
   1504   },
   1505 #endif
   1506 #if defined(ENABLE_GOOGLE_NOW)
   1507   {
   1508     "enable-google-now",
   1509     IDS_FLAGS_ENABLE_GOOGLE_NOW_INTEGRATION_NAME,
   1510     IDS_FLAGS_ENABLE_GOOGLE_NOW_INTEGRATION_DESCRIPTION,
   1511     kOsWin | kOsCrOS | kOsMac,
   1512     ENABLE_DISABLE_VALUE_TYPE(
   1513         switches::kEnableGoogleNowIntegration,
   1514         switches::kDisableGoogleNowIntegration)
   1515   },
   1516 #endif
   1517 #if defined(OS_CHROMEOS)
   1518   {
   1519     "enable-virtual-keyboard",
   1520     IDS_FLAGS_ENABLE_VIRTUAL_KEYBOARD_NAME,
   1521     IDS_FLAGS_ENABLE_VIRTUAL_KEYBOARD_DESCRIPTION,
   1522     kOsCrOS,
   1523     SINGLE_VALUE_TYPE(keyboard::switches::kEnableVirtualKeyboard)
   1524   },
   1525   {
   1526     "enable-swipe-selection",
   1527     IDS_FLAGS_ENABLE_SWIPE_SELECTION_NAME,
   1528     IDS_FLAGS_ENABLE_SWIPE_SELECTION_DESCRIPTION,
   1529     kOsCrOS,
   1530     SINGLE_VALUE_TYPE(keyboard::switches::kEnableSwipeSelection)
   1531   },
   1532 #endif
   1533   {
   1534     "enable-simple-cache-backend",
   1535     IDS_FLAGS_ENABLE_SIMPLE_CACHE_BACKEND_NAME,
   1536     IDS_FLAGS_ENABLE_SIMPLE_CACHE_BACKEND_DESCRIPTION,
   1537     kOsAll,
   1538     MULTI_VALUE_TYPE(kSimpleCacheBackendChoices)
   1539   },
   1540   {
   1541     "enable-tcp-fast-open",
   1542     IDS_FLAGS_ENABLE_TCP_FAST_OPEN_NAME,
   1543     IDS_FLAGS_ENABLE_TCP_FAST_OPEN_DESCRIPTION,
   1544     kOsLinux | kOsCrOS | kOsAndroid,
   1545     SINGLE_VALUE_TYPE(switches::kEnableTcpFastOpen)
   1546   },
   1547   {
   1548     "apps-use-native-frame",
   1549     IDS_FLAGS_ENABLE_NATIVE_FRAMES_FOR_APPS_NAME,
   1550     IDS_FLAGS_ENABLE_NATIVE_FRAMES_FOR_APPS_DESCRIPTION,
   1551     kOsMac | kOsWin | kOsLinux,
   1552     SINGLE_VALUE_TYPE(switches::kAppsUseNativeFrame)
   1553   },
   1554   {
   1555     "enable-syncfs-directory-operation",
   1556     IDS_FLAGS_ENABLE_SYNC_DIRECTORY_OPERATION_NAME,
   1557     IDS_FLAGS_ENABLE_SYNC_DIRECTORY_OPERATION_DESCRIPTION,
   1558     kOsAll,
   1559     SINGLE_VALUE_TYPE(switches::kSyncfsEnableDirectoryOperation),
   1560   },
   1561 #if defined(ENABLE_MDNS)
   1562   {
   1563     "disable-device-discovery",
   1564     IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_NAME,
   1565     IDS_FLAGS_DISABLE_DEVICE_DISCOVERY_DESCRIPTION,
   1566     kOsWin | kOsLinux | kOsCrOS,
   1567     SINGLE_VALUE_TYPE(switches::kDisableDeviceDiscovery)
   1568   },
   1569   {
   1570     "device-discovery-notifications",
   1571     IDS_FLAGS_DEVICE_DISCOVERY_NOTIFICATIONS_NAME,
   1572     IDS_FLAGS_DEVICE_DISCOVERY_NOTIFICATIONS_DESCRIPTION,
   1573     kOsWin | kOsLinux | kOsCrOS,
   1574     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableDeviceDiscoveryNotifications,
   1575                               switches::kDisableDeviceDiscoveryNotifications)
   1576   },
   1577   {
   1578     "disable-privet-local-printing",
   1579     IDS_FLAGS_DISABLE_PRIVET_LOCAL_PRINTING_NAME,
   1580     IDS_FLAGS_DISABLE_PRIVET_LOCAL_PRINTING_DESCRIPTION,
   1581     kOsWin | kOsLinux | kOsCrOS,
   1582     SINGLE_VALUE_TYPE(switches::kDisablePrivetLocalPrinting)
   1583   },
   1584   {
   1585     "enable-print-preview-register-promos",
   1586     IDS_FLAGS_ENABLE_PRINT_PREVIEW_REGISTER_PROMOS_NAME,
   1587     IDS_FLAGS_ENABLE_PRINT_PREVIEW_REGISTER_PROMOS_DESCRIPTION,
   1588     kOsWin | kOsLinux | kOsCrOS,
   1589     SINGLE_VALUE_TYPE(switches::kEnablePrintPreviewRegisterPromos)
   1590   },
   1591 #endif  // ENABLE_MDNS
   1592 #if defined(OS_MACOSX)
   1593   {
   1594     "enable-app-shims",
   1595     IDS_FLAGS_ENABLE_APP_SHIMS_NAME,
   1596     IDS_FLAGS_ENABLE_APP_SHIMS_DESCRIPTION,
   1597     kOsMac,
   1598     SINGLE_VALUE_TYPE(switches::kEnableAppShims)
   1599   },
   1600   {
   1601     "enable-simplified-fullscreen",
   1602     IDS_FLAGS_ENABLE_SIMPLIFIED_FULLSCREEN_NAME,
   1603     IDS_FLAGS_ENABLE_SIMPLIFIED_FULLSCREEN_DESCRIPTION,
   1604     kOsMac,
   1605     SINGLE_VALUE_TYPE(switches::kEnableSimplifiedFullscreen)
   1606   },
   1607 #endif
   1608 #if defined(TOOLKIT_VIEWS)
   1609   {
   1610     "omnibox-auto-completion-for-ime",
   1611     IDS_FLAGS_ENABLE_OMNIBOX_AUTO_COMPLETION_FOR_IME_NAME,
   1612     IDS_FLAGS_ENABLE_OMNIBOX_AUTO_COMPLETION_FOR_IME_DESCRIPTION,
   1613     kOsCrOS | kOsWin | kOsLinux,
   1614     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableOmniboxAutoCompletionForIme,
   1615                               switches::kDisableOmniboxAutoCompletionForIme)
   1616   },
   1617 #endif
   1618 #if defined(USE_AURA)
   1619   {
   1620     "tab-capture-upscale-quality",
   1621     IDS_FLAGS_TAB_CAPTURE_UPSCALE_QUALITY_NAME,
   1622     IDS_FLAGS_TAB_CAPTURE_UPSCALE_QUALITY_DESCRIPTION,
   1623     kOsAll,
   1624     MULTI_VALUE_TYPE(kTabCaptureUpscaleQualityChoices)
   1625   },
   1626   {
   1627     "tab-capture-downscale-quality",
   1628     IDS_FLAGS_TAB_CAPTURE_DOWNSCALE_QUALITY_NAME,
   1629     IDS_FLAGS_TAB_CAPTURE_DOWNSCALE_QUALITY_DESCRIPTION,
   1630     kOsAll,
   1631     MULTI_VALUE_TYPE(kTabCaptureDownscaleQualityChoices)
   1632   },
   1633 #endif
   1634   {
   1635     "enable-spelling-feedback-field-trial",
   1636     IDS_FLAGS_ENABLE_SPELLING_FEEDBACK_FIELD_TRIAL_NAME,
   1637     IDS_FLAGS_ENABLE_SPELLING_FEEDBACK_FIELD_TRIAL_DESCRIPTION,
   1638     kOsAll,
   1639     SINGLE_VALUE_TYPE(switches::kEnableSpellingFeedbackFieldTrial)
   1640   },
   1641   {
   1642     "enable-webgl-draft-extensions",
   1643     IDS_FLAGS_ENABLE_WEBGL_DRAFT_EXTENSIONS_NAME,
   1644     IDS_FLAGS_ENABLE_WEBGL_DRAFT_EXTENSIONS_DESCRIPTION,
   1645     kOsAll,
   1646     SINGLE_VALUE_TYPE(switches::kEnableWebGLDraftExtensions)
   1647   },
   1648   {
   1649     "enable-html-imports",
   1650     IDS_FLAGS_ENABLE_HTML_IMPORTS_NAME,
   1651     IDS_FLAGS_ENABLE_HTML_IMPORTS_DESCRIPTION,
   1652     kOsAll,
   1653     SINGLE_VALUE_TYPE(switches::kEnableHTMLImports)
   1654   },
   1655   {
   1656     "high-dpi-support",
   1657     IDS_FLAGS_HIDPI_NAME,
   1658     IDS_FLAGS_HIDPI_DESCRIPTION,
   1659     kOsWin,
   1660     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(switches::kHighDPISupport, "1",
   1661                                         switches::kHighDPISupport, "0")
   1662   },
   1663 #if defined(OS_CHROMEOS)
   1664   {
   1665     "enable-quickoffice-viewing",
   1666     IDS_FLAGS_ENABLE_QUICKOFFICE_DESKTOP_VIEWING_NAME,
   1667     IDS_FLAGS_ENABLE_QUICKOFFICE_DESKTOP_VIEWING_DESCRIPTION,
   1668     kOsCrOS,
   1669     SINGLE_VALUE_TYPE(switches::kEnableQuickofficeViewing),
   1670   },
   1671   {
   1672     "enable-sticky-keys",
   1673     IDS_FLAGS_ENABLE_STICKY_KEYS_NAME,
   1674     IDS_FLAGS_ENABLE_STICKY_KEYS_DESCRIPTION,
   1675     kOsCrOS,
   1676     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableStickyKeys,
   1677                               switches::kDisableStickyKeys)
   1678   },
   1679 #endif
   1680   {
   1681     "enable-web-midi",
   1682     IDS_FLAGS_ENABLE_WEB_MIDI_NAME,
   1683     IDS_FLAGS_ENABLE_WEB_MIDI_DESCRIPTION,
   1684     kOsMac | kOsWin,
   1685     SINGLE_VALUE_TYPE(switches::kEnableWebMIDI)
   1686   },
   1687   {
   1688     "enable-new-profile-management",
   1689     IDS_FLAGS_ENABLE_NEW_PROFILE_MANAGEMENT_NAME,
   1690     IDS_FLAGS_ENABLE_NEW_PROFILE_MANAGEMENT_DESCRIPTION,
   1691     kOsMac | kOsWin | kOsLinux,
   1692     SINGLE_VALUE_TYPE(switches::kNewProfileManagement)
   1693   },
   1694   {
   1695     "enable-inline-signin",
   1696     IDS_FLAGS_ENABLE_INLINE_SIGNIN_NAME,
   1697     IDS_FLAGS_ENABLE_INLINE_SIGNIN_DESCRIPTION,
   1698     kOsMac | kOsWin | kOsLinux,
   1699     SINGLE_VALUE_TYPE(switches::kEnableInlineSignin)
   1700   },
   1701   {
   1702     "enable-google-profile-info",
   1703     IDS_FLAGS_ENABLE_GOOGLE_PROFILE_INFO_NAME,
   1704     IDS_FLAGS_ENABLE_GOOGLE_PROFILE_INFO_DESCRIPTION,
   1705     kOsMac | kOsWin | kOsLinux,
   1706     SINGLE_VALUE_TYPE(switches::kGoogleProfileInfo)
   1707   },
   1708   {
   1709     "disable-app-launcher",
   1710     IDS_FLAGS_RESET_APP_LIST_INSTALL_STATE_NAME,
   1711     IDS_FLAGS_RESET_APP_LIST_INSTALL_STATE_DESCRIPTION,
   1712     kOsMac | kOsWin,
   1713     SINGLE_VALUE_TYPE(switches::kResetAppListInstallState)
   1714   },
   1715 #if defined(ENABLE_APP_LIST)
   1716   {
   1717     "enable-app-launcher-start-page",
   1718     IDS_FLAGS_ENABLE_APP_LIST_START_PAGE_NAME,
   1719     IDS_FLAGS_ENABLE_APP_LIST_START_PAGE_DESCRIPTION,
   1720     kOsWin | kOsCrOS,
   1721     SINGLE_VALUE_TYPE(switches::kShowAppListStartPage)
   1722   },
   1723   {
   1724     "enable-app-list-folder",
   1725     IDS_FLAGS_ENABLE_APP_LIST_FOLDER,
   1726     IDS_FLAGS_ENABLE_APP_LIST_FOLDER_DESCRIPTION,
   1727     kOsWin | kOsCrOS,
   1728     SINGLE_VALUE_TYPE(app_list::switches::kEnableFolderUI)
   1729   },
   1730 #endif
   1731 #if defined(OS_CHROMEOS)
   1732   {
   1733     "disable-user-image-sync",
   1734     IDS_FLAGS_DISABLE_USER_IMAGE_SYNC_NAME,
   1735     IDS_FLAGS_DISABLE_USER_IMAGE_SYNC_DESCRIPTION,
   1736     kOsCrOS,
   1737     SINGLE_VALUE_TYPE(chromeos::switches::kDisableUserImageSync)
   1738   },
   1739 #endif
   1740 #if defined(OS_ANDROID)
   1741   {
   1742     "enable-accessibility-tab-switcher",
   1743     IDS_FLAGS_ENABLE_ACCESSIBILITY_TAB_SWITCHER_NAME,
   1744     IDS_FLAGS_ENABLE_ACCESSIBILITY_TAB_SWITCHER_DESCRIPTION,
   1745     kOsAndroid,
   1746     SINGLE_VALUE_TYPE(switches::kEnableAccessibilityTabSwitcher)
   1747   },
   1748   {
   1749     "disable-accessibility-script-injection",
   1750     IDS_FLAGS_DISABLE_ACCESSIBILITY_SCRIPT_INJECTION_NAME,
   1751     IDS_FLAGS_DISABLE_ACCESSIBILITY_SCRIPT_INJECTION_DESCRIPTION,
   1752     kOsAndroid,
   1753     // Java-only switch: ContentSwitches.DISABLE_ACCESSIBILITY_SCRIPT_INJECTION.
   1754     SINGLE_VALUE_TYPE("disable-accessibility-script-injection")
   1755   },
   1756 #endif
   1757   {
   1758     "map-image",
   1759     IDS_FLAGS_MAP_IMAGE_NAME,
   1760     IDS_FLAGS_MAP_IMAGE_DESCRIPTION,
   1761     kOsAll,
   1762     MULTI_VALUE_TYPE(kMapImageChoices)
   1763   },
   1764   {
   1765     "enable-add-to-homescreen",
   1766     IDS_FLAGS_ENABLE_ADD_TO_HOMESCREEN_NAME,
   1767     IDS_FLAGS_ENABLE_ADD_TO_HOMESCREEN_DESCRIPTION,
   1768     kOsAndroid,
   1769 #if defined(OS_ANDROID)
   1770     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableAddToHomescreen,
   1771                               switches::kDisableAddToHomescreen),
   1772 #else
   1773     SINGLE_VALUE_TYPE("")
   1774 #endif
   1775   },
   1776 #if defined(OS_CHROMEOS)
   1777   {
   1778     "disable-first-run-ui",
   1779     IDS_FLAGS_DISABLE_FIRST_RUN_UI_NAME,
   1780     IDS_FLAGS_DISABLE_FIRST_RUN_UI_DESCRIPTION,
   1781     kOsCrOS,
   1782     SINGLE_VALUE_TYPE(chromeos::switches::kDisableFirstRunUI)
   1783   },
   1784   {
   1785     "enable-first-run-ui-transitions",
   1786     IDS_FLAGS_ENABLE_FIRST_RUN_UI_TRANSITIONS_NAME,
   1787     IDS_FLAGS_ENABLE_FIRST_RUN_UI_TRANSITIONS_DESCRIPTION,
   1788     kOsCrOS,
   1789     SINGLE_VALUE_TYPE(chromeos::switches::kEnableFirstRunUITransitions)
   1790   },
   1791 #endif
   1792   {
   1793     "disable-compositor-touch-hit-testing",
   1794     IDS_FLAGS_DISABLE_COMPOSITOR_TOUCH_HIT_TESTING_NAME,
   1795     IDS_FLAGS_DISABLE_COMPOSITOR_TOUCH_HIT_TESTING_DESCRIPTION,
   1796     kOsAll,
   1797     SINGLE_VALUE_TYPE(cc::switches::kDisableCompositorTouchHitTesting),
   1798   },
   1799   {
   1800     "enable-accelerated-scrollable-frames",
   1801      IDS_FLAGS_ENABLE_ACCELERATED_SCROLLABLE_FRAMES_NAME,
   1802      IDS_FLAGS_ENABLE_ACCELERATED_SCROLLABLE_FRAMES_DESCRIPTION,
   1803      kOsAll,
   1804      ENABLE_DISABLE_VALUE_TYPE(switches::kEnableAcceleratedScrollableFrames,
   1805                                switches::kDisableAcceleratedScrollableFrames)
   1806   },
   1807   {
   1808     "enable-composited-scrolling-for-frames",
   1809      IDS_FLAGS_ENABLE_COMPOSITED_SCROLLING_FOR_FRAMES_NAME,
   1810      IDS_FLAGS_ENABLE_COMPOSITED_SCROLLING_FOR_FRAMES_DESCRIPTION,
   1811      kOsAll,
   1812      ENABLE_DISABLE_VALUE_TYPE(switches::kEnableCompositedScrollingForFrames,
   1813                                switches::kDisableCompositedScrollingForFrames)
   1814   },
   1815   {
   1816     "enable-streamlined-hosted-apps",
   1817     IDS_FLAGS_ENABLE_STREAMLINED_HOSTED_APPS_NAME,
   1818     IDS_FLAGS_ENABLE_STREAMLINED_HOSTED_APPS_DESCRIPTION,
   1819     kOsWin | kOsCrOS | kOsLinux,
   1820     SINGLE_VALUE_TYPE(switches::kEnableStreamlinedHostedApps)
   1821   },
   1822   {
   1823     "enable-ephemeral-apps",
   1824     IDS_FLAGS_ENABLE_EPHEMERAL_APPS_NAME,
   1825     IDS_FLAGS_ENABLE_EPHEMERAL_APPS_DESCRIPTION,
   1826     kOsWin | kOsLinux | kOsCrOS,
   1827     SINGLE_VALUE_TYPE(switches::kEnableEphemeralApps)
   1828   },
   1829   {
   1830     "enable-service-worker",
   1831     IDS_FLAGS_ENABLE_SERVICE_WORKER_NAME,
   1832     IDS_FLAGS_ENABLE_SERVICE_WORKER_DESCRIPTION,
   1833     kOsAll,
   1834     SINGLE_VALUE_TYPE(switches::kEnableServiceWorker)
   1835   },
   1836 #if defined(OS_ANDROID)
   1837   {
   1838     "disable-click-delay",
   1839     IDS_FLAGS_DISABLE_CLICK_DELAY_NAME,
   1840     IDS_FLAGS_DISABLE_CLICK_DELAY_DESCRIPTION,
   1841     kOsAndroid,
   1842     // Java-only switch: CommandLine.DISABLE_CLICK_DELAY
   1843     SINGLE_VALUE_TYPE("disable-click-delay")
   1844   },
   1845 #endif
   1846 #if defined(OS_CHROMEOS)
   1847   {
   1848     "disable-ime-mode-indicator",
   1849     IDS_FLAGS_DISABLE_IME_MODE_INDICATOR,
   1850     IDS_FLAGS_DISABLE_IME_MODE_INDICATOR_DESCRIPTION,
   1851     kOsCrOS,
   1852     SINGLE_VALUE_TYPE(chromeos::switches::kDisableIMEModeIndicator)
   1853   },
   1854 #endif
   1855   {
   1856     "enable-translate-new-ux",
   1857     IDS_FLAGS_ENABLE_TRANSLATE_NEW_UX_NAME,
   1858     IDS_FLAGS_ENABLE_TRANSLATE_NEW_UX_DESCRIPTION,
   1859     kOsDesktop,
   1860     SINGLE_VALUE_TYPE(switches::kEnableTranslateNewUX)
   1861   },
   1862 #if defined(TOOLKIT_VIEWS)
   1863   {
   1864     "disable-views-rect-based-targeting",  // FLAGS:RECORD_UMA
   1865     IDS_FLAGS_DISABLE_VIEWS_RECT_BASED_TARGETING_NAME,
   1866     IDS_FLAGS_DISABLE_VIEWS_RECT_BASED_TARGETING_DESCRIPTION,
   1867     kOsCrOS | kOsWin,
   1868     SINGLE_VALUE_TYPE(views::switches::kDisableViewsRectBasedTargeting)
   1869   },
   1870 #endif
   1871   {
   1872     "enable-apps-show-on-first-paint",
   1873     IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_NAME,
   1874     IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_DESCRIPTION,
   1875     kOsDesktop,
   1876     SINGLE_VALUE_TYPE(switches::kEnableAppsShowOnFirstPaint)
   1877   },
   1878   {
   1879     "enable-enhanced-bookmarks",
   1880     IDS_FLAGS_ENABLE_ENHANCED_BOOKMARKS_NAME,
   1881     IDS_FLAGS_ENABLE_ENHANCED_BOOKMARKS_DESCRIPTION,
   1882     kOsDesktop,
   1883     ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(switches::kEnableEnhancedBookmarks, "1",
   1884                                         switches::kEnableEnhancedBookmarks, "0")
   1885   },
   1886 #if defined(OS_ANDROID)
   1887   {
   1888     "enable-zero-suggest-experiment",
   1889     IDS_FLAGS_ZERO_SUGGEST_EXPERIMENT_NAME,
   1890     IDS_FLAGS_ZERO_SUGGEST_EXPERIMENT_DESCRIPTION,
   1891     kOsAndroid,
   1892     MULTI_VALUE_TYPE(kZeroSuggestExperimentsChoices)
   1893   },
   1894 #endif
   1895   {
   1896     "num-raster-threads",
   1897     IDS_FLAGS_NUM_RASTER_THREADS_NAME,
   1898     IDS_FLAGS_NUM_RASTER_THREADS_DESCRIPTION,
   1899     kOsAll,
   1900     MULTI_VALUE_TYPE(kNumRasterThreadsChoices)
   1901   },
   1902   {
   1903     "origin-chip",
   1904     IDS_FLAGS_ORIGIN_CHIP_NAME,
   1905     IDS_FLAGS_ORIGIN_CHIP_DESCRIPTION,
   1906     kOsCrOS | kOsWin,
   1907     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableOriginChip,
   1908                               switches::kDisableOriginChip)
   1909   },
   1910   {
   1911     "search-button-in-omnibox",
   1912     IDS_FLAGS_SEARCH_BUTTON_IN_OMNIBOX_NAME,
   1913     IDS_FLAGS_SEARCH_BUTTON_IN_OMNIBOX_DESCRIPTION,
   1914     kOsCrOS | kOsMac | kOsWin,
   1915     MULTI_VALUE_TYPE(kSearchButtonInOmniboxChoices)
   1916   },
   1917   {
   1918     "enable-ignore-autocomplete-off",
   1919     IDS_FLAGS_ENABLE_IGNORE_AUTOCOMPLETE_OFF_NAME,
   1920     IDS_FLAGS_ENABLE_IGNORE_AUTOCOMPLETE_OFF_DESCRIPTION,
   1921     kOsAll,
   1922     SINGLE_VALUE_TYPE(autofill::switches::kEnableIgnoreAutocompleteOff)
   1923   }
   1924 };
   1925 
   1926 const Experiment* experiments = kExperiments;
   1927 size_t num_experiments = arraysize(kExperiments);
   1928 
   1929 // Stores and encapsulates the little state that about:flags has.
   1930 class FlagsState {
   1931  public:
   1932   FlagsState() : needs_restart_(false) {}
   1933   void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
   1934                               CommandLine* command_line,
   1935                               SentinelsMode sentinels);
   1936   bool IsRestartNeededToCommitChanges();
   1937   void SetExperimentEnabled(
   1938       FlagsStorage* flags_storage,
   1939       const std::string& internal_name,
   1940       bool enable);
   1941   void RemoveFlagsSwitches(
   1942       std::map<std::string, CommandLine::StringType>* switch_list);
   1943   void ResetAllFlags(FlagsStorage* flags_storage);
   1944   void reset();
   1945 
   1946   // Returns the singleton instance of this class
   1947   static FlagsState* GetInstance() {
   1948     return Singleton<FlagsState>::get();
   1949   }
   1950 
   1951  private:
   1952   bool needs_restart_;
   1953   std::map<std::string, std::string> flags_switches_;
   1954 
   1955   DISALLOW_COPY_AND_ASSIGN(FlagsState);
   1956 };
   1957 
   1958 // Adds the internal names for the specified experiment to |names|.
   1959 void AddInternalName(const Experiment& e, std::set<std::string>* names) {
   1960   if (e.type == Experiment::SINGLE_VALUE) {
   1961     names->insert(e.internal_name);
   1962   } else {
   1963     DCHECK(e.type == Experiment::MULTI_VALUE ||
   1964            e.type == Experiment::ENABLE_DISABLE_VALUE);
   1965     for (int i = 0; i < e.num_choices; ++i)
   1966       names->insert(e.NameForChoice(i));
   1967   }
   1968 }
   1969 
   1970 // Confirms that an experiment is valid, used in a DCHECK in
   1971 // SanitizeList below.
   1972 bool ValidateExperiment(const Experiment& e) {
   1973   switch (e.type) {
   1974     case Experiment::SINGLE_VALUE:
   1975       DCHECK_EQ(0, e.num_choices);
   1976       DCHECK(!e.choices);
   1977       break;
   1978     case Experiment::MULTI_VALUE:
   1979       DCHECK_GT(e.num_choices, 0);
   1980       DCHECK(e.choices);
   1981       DCHECK(e.choices[0].command_line_switch);
   1982       DCHECK_EQ('\0', e.choices[0].command_line_switch[0]);
   1983       break;
   1984     case Experiment::ENABLE_DISABLE_VALUE:
   1985       DCHECK_EQ(3, e.num_choices);
   1986       DCHECK(!e.choices);
   1987       DCHECK(e.command_line_switch);
   1988       DCHECK(e.command_line_value);
   1989       DCHECK(e.disable_command_line_switch);
   1990       DCHECK(e.disable_command_line_value);
   1991       break;
   1992     default:
   1993       NOTREACHED();
   1994   }
   1995   return true;
   1996 }
   1997 
   1998 // Removes all experiments from prefs::kEnabledLabsExperiments that are
   1999 // unknown, to prevent this list to become very long as experiments are added
   2000 // and removed.
   2001 void SanitizeList(FlagsStorage* flags_storage) {
   2002   std::set<std::string> known_experiments;
   2003   for (size_t i = 0; i < num_experiments; ++i) {
   2004     DCHECK(ValidateExperiment(experiments[i]));
   2005     AddInternalName(experiments[i], &known_experiments);
   2006   }
   2007 
   2008   std::set<std::string> enabled_experiments = flags_storage->GetFlags();
   2009 
   2010   std::set<std::string> new_enabled_experiments;
   2011   std::set_intersection(
   2012       known_experiments.begin(), known_experiments.end(),
   2013       enabled_experiments.begin(), enabled_experiments.end(),
   2014       std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
   2015 
   2016   if (new_enabled_experiments != enabled_experiments)
   2017     flags_storage->SetFlags(new_enabled_experiments);
   2018 }
   2019 
   2020 void GetSanitizedEnabledFlags(
   2021     FlagsStorage* flags_storage, std::set<std::string>* result) {
   2022   SanitizeList(flags_storage);
   2023   *result = flags_storage->GetFlags();
   2024 }
   2025 
   2026 bool SkipConditionalExperiment(const Experiment& experiment) {
   2027   if (experiment.internal_name == std::string("enable-enhanced-bookmarks")) {
   2028     return !IsEnhancedBookmarksExperimentEnabled();
   2029   }
   2030   return false;
   2031 }
   2032 
   2033 
   2034 // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
   2035 // enabled on the current platform.
   2036 void GetSanitizedEnabledFlagsForCurrentPlatform(
   2037     FlagsStorage* flags_storage, std::set<std::string>* result) {
   2038   GetSanitizedEnabledFlags(flags_storage, result);
   2039 
   2040   // Filter out any experiments that aren't enabled on the current platform.  We
   2041   // don't remove these from prefs else syncing to a platform with a different
   2042   // set of experiments would be lossy.
   2043   std::set<std::string> platform_experiments;
   2044   int current_platform = GetCurrentPlatform();
   2045   for (size_t i = 0; i < num_experiments; ++i) {
   2046     if (experiments[i].supported_platforms & current_platform)
   2047       AddInternalName(experiments[i], &platform_experiments);
   2048 #if defined(OS_CHROMEOS)
   2049     if (experiments[i].supported_platforms & kOsCrOSOwnerOnly)
   2050       AddInternalName(experiments[i], &platform_experiments);
   2051 #endif
   2052   }
   2053 
   2054   std::set<std::string> new_enabled_experiments;
   2055   std::set_intersection(
   2056       platform_experiments.begin(), platform_experiments.end(),
   2057       result->begin(), result->end(),
   2058       std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
   2059 
   2060   result->swap(new_enabled_experiments);
   2061 }
   2062 
   2063 // Returns the Value representing the choice data in the specified experiment.
   2064 Value* CreateChoiceData(const Experiment& experiment,
   2065                         const std::set<std::string>& enabled_experiments) {
   2066   DCHECK(experiment.type == Experiment::MULTI_VALUE ||
   2067          experiment.type == Experiment::ENABLE_DISABLE_VALUE);
   2068   ListValue* result = new ListValue;
   2069   for (int i = 0; i < experiment.num_choices; ++i) {
   2070     DictionaryValue* value = new DictionaryValue;
   2071     const std::string name = experiment.NameForChoice(i);
   2072     value->SetString("internal_name", name);
   2073     value->SetString("description", experiment.DescriptionForChoice(i));
   2074     value->SetBoolean("selected", enabled_experiments.count(name) > 0);
   2075     result->Append(value);
   2076   }
   2077   return result;
   2078 }
   2079 
   2080 }  // namespace
   2081 
   2082 std::string Experiment::NameForChoice(int index) const {
   2083   DCHECK(type == Experiment::MULTI_VALUE ||
   2084          type == Experiment::ENABLE_DISABLE_VALUE);
   2085   DCHECK_LT(index, num_choices);
   2086   return std::string(internal_name) + testing::kMultiSeparator +
   2087          base::IntToString(index);
   2088 }
   2089 
   2090 base::string16 Experiment::DescriptionForChoice(int index) const {
   2091   DCHECK(type == Experiment::MULTI_VALUE ||
   2092          type == Experiment::ENABLE_DISABLE_VALUE);
   2093   DCHECK_LT(index, num_choices);
   2094   int description_id;
   2095   if (type == Experiment::ENABLE_DISABLE_VALUE) {
   2096     const int kEnableDisableDescriptionIds[] = {
   2097       IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT,
   2098       IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
   2099       IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
   2100     };
   2101     description_id = kEnableDisableDescriptionIds[index];
   2102   } else {
   2103     description_id = choices[index].description_id;
   2104   }
   2105   return l10n_util::GetStringUTF16(description_id);
   2106 }
   2107 
   2108 void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
   2109                             CommandLine* command_line,
   2110                             SentinelsMode sentinels) {
   2111   FlagsState::GetInstance()->ConvertFlagsToSwitches(flags_storage,
   2112                                                     command_line,
   2113                                                     sentinels);
   2114 }
   2115 
   2116 bool AreSwitchesIdenticalToCurrentCommandLine(
   2117     const CommandLine& new_cmdline, const CommandLine& active_cmdline) {
   2118   std::set<CommandLine::StringType> new_flags =
   2119       ExtractFlagsFromCommandLine(new_cmdline);
   2120   std::set<CommandLine::StringType> active_flags =
   2121       ExtractFlagsFromCommandLine(active_cmdline);
   2122 
   2123   // Needed because std::equal doesn't check if the 2nd set is empty.
   2124   if (new_flags.size() != active_flags.size())
   2125     return false;
   2126 
   2127   return std::equal(new_flags.begin(), new_flags.end(), active_flags.begin());
   2128 }
   2129 
   2130 void GetFlagsExperimentsData(FlagsStorage* flags_storage,
   2131                              FlagAccess access,
   2132                              base::ListValue* supported_experiments,
   2133                              base::ListValue* unsupported_experiments) {
   2134   std::set<std::string> enabled_experiments;
   2135   GetSanitizedEnabledFlags(flags_storage, &enabled_experiments);
   2136 
   2137   int current_platform = GetCurrentPlatform();
   2138 
   2139   for (size_t i = 0; i < num_experiments; ++i) {
   2140     const Experiment& experiment = experiments[i];
   2141     if (SkipConditionalExperiment(experiment))
   2142       continue;
   2143 
   2144     DictionaryValue* data = new DictionaryValue();
   2145     data->SetString("internal_name", experiment.internal_name);
   2146     data->SetString("name",
   2147                     l10n_util::GetStringUTF16(experiment.visible_name_id));
   2148     data->SetString("description",
   2149                     l10n_util::GetStringUTF16(
   2150                         experiment.visible_description_id));
   2151 
   2152     ListValue* supported_platforms = new ListValue();
   2153     AddOsStrings(experiment.supported_platforms, supported_platforms);
   2154     data->Set("supported_platforms", supported_platforms);
   2155 
   2156     switch (experiment.type) {
   2157       case Experiment::SINGLE_VALUE:
   2158         data->SetBoolean(
   2159             "enabled",
   2160             enabled_experiments.count(experiment.internal_name) > 0);
   2161         break;
   2162       case Experiment::MULTI_VALUE:
   2163       case Experiment::ENABLE_DISABLE_VALUE:
   2164         data->Set("choices", CreateChoiceData(experiment, enabled_experiments));
   2165         break;
   2166       default:
   2167         NOTREACHED();
   2168     }
   2169 
   2170     bool supported = (experiment.supported_platforms & current_platform) != 0;
   2171 #if defined(OS_CHROMEOS)
   2172     if (access == kOwnerAccessToFlags &&
   2173         (experiment.supported_platforms & kOsCrOSOwnerOnly) != 0) {
   2174       supported = true;
   2175     }
   2176 #endif
   2177     if (supported)
   2178       supported_experiments->Append(data);
   2179     else
   2180       unsupported_experiments->Append(data);
   2181   }
   2182 }
   2183 
   2184 bool IsRestartNeededToCommitChanges() {
   2185   return FlagsState::GetInstance()->IsRestartNeededToCommitChanges();
   2186 }
   2187 
   2188 void SetExperimentEnabled(FlagsStorage* flags_storage,
   2189                           const std::string& internal_name,
   2190                           bool enable) {
   2191   FlagsState::GetInstance()->SetExperimentEnabled(flags_storage,
   2192                                                   internal_name, enable);
   2193 }
   2194 
   2195 void RemoveFlagsSwitches(
   2196     std::map<std::string, CommandLine::StringType>* switch_list) {
   2197   FlagsState::GetInstance()->RemoveFlagsSwitches(switch_list);
   2198 }
   2199 
   2200 void ResetAllFlags(FlagsStorage* flags_storage) {
   2201   FlagsState::GetInstance()->ResetAllFlags(flags_storage);
   2202 }
   2203 
   2204 int GetCurrentPlatform() {
   2205 #if defined(OS_MACOSX)
   2206   return kOsMac;
   2207 #elif defined(OS_WIN)
   2208   return kOsWin;
   2209 #elif defined(OS_CHROMEOS)  // Needs to be before the OS_LINUX check.
   2210   return kOsCrOS;
   2211 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
   2212   return kOsLinux;
   2213 #elif defined(OS_ANDROID)
   2214   return kOsAndroid;
   2215 #else
   2216 #error Unknown platform
   2217 #endif
   2218 }
   2219 
   2220 void RecordUMAStatistics(FlagsStorage* flags_storage) {
   2221   std::set<std::string> flags = flags_storage->GetFlags();
   2222   for (std::set<std::string>::iterator it = flags.begin(); it != flags.end();
   2223        ++it) {
   2224     std::string action("AboutFlags_");
   2225     action += *it;
   2226     content::RecordComputedAction(action);
   2227   }
   2228   // Since flag metrics are recorded every startup, add a tick so that the
   2229   // stats can be made meaningful.
   2230   if (flags.size())
   2231     content::RecordAction(UserMetricsAction("AboutFlags_StartupTick"));
   2232   content::RecordAction(UserMetricsAction("StartupTick"));
   2233 }
   2234 
   2235 //////////////////////////////////////////////////////////////////////////////
   2236 // FlagsState implementation.
   2237 
   2238 namespace {
   2239 
   2240 typedef std::map<std::string, std::pair<std::string, std::string> >
   2241     NameToSwitchAndValueMap;
   2242 
   2243 void SetFlagToSwitchMapping(const std::string& key,
   2244                             const std::string& switch_name,
   2245                             const std::string& switch_value,
   2246                             NameToSwitchAndValueMap* name_to_switch_map) {
   2247   DCHECK(name_to_switch_map->end() == name_to_switch_map->find(key));
   2248   (*name_to_switch_map)[key] = std::make_pair(switch_name, switch_value);
   2249 }
   2250 
   2251 void FlagsState::ConvertFlagsToSwitches(FlagsStorage* flags_storage,
   2252                                         CommandLine* command_line,
   2253                                         SentinelsMode sentinels) {
   2254   if (command_line->HasSwitch(switches::kNoExperiments))
   2255     return;
   2256 
   2257   std::set<std::string> enabled_experiments;
   2258 
   2259   GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage,
   2260                                              &enabled_experiments);
   2261 
   2262   NameToSwitchAndValueMap name_to_switch_map;
   2263   for (size_t i = 0; i < num_experiments; ++i) {
   2264     const Experiment& e = experiments[i];
   2265     if (e.type == Experiment::SINGLE_VALUE) {
   2266       SetFlagToSwitchMapping(e.internal_name, e.command_line_switch,
   2267                              e.command_line_value, &name_to_switch_map);
   2268     } else if (e.type == Experiment::MULTI_VALUE) {
   2269       for (int j = 0; j < e.num_choices; ++j) {
   2270         SetFlagToSwitchMapping(e.NameForChoice(j),
   2271                                e.choices[j].command_line_switch,
   2272                                e.choices[j].command_line_value,
   2273                                &name_to_switch_map);
   2274       }
   2275     } else {
   2276       DCHECK_EQ(e.type, Experiment::ENABLE_DISABLE_VALUE);
   2277       SetFlagToSwitchMapping(e.NameForChoice(0), std::string(), std::string(),
   2278                              &name_to_switch_map);
   2279       SetFlagToSwitchMapping(e.NameForChoice(1), e.command_line_switch,
   2280                              e.command_line_value, &name_to_switch_map);
   2281       SetFlagToSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch,
   2282                              e.disable_command_line_value, &name_to_switch_map);
   2283     }
   2284   }
   2285 
   2286   if (sentinels == kAddSentinels) {
   2287     command_line->AppendSwitch(switches::kFlagSwitchesBegin);
   2288     flags_switches_.insert(
   2289         std::pair<std::string, std::string>(switches::kFlagSwitchesBegin,
   2290                                             std::string()));
   2291   }
   2292   for (std::set<std::string>::iterator it = enabled_experiments.begin();
   2293        it != enabled_experiments.end();
   2294        ++it) {
   2295     const std::string& experiment_name = *it;
   2296     NameToSwitchAndValueMap::const_iterator name_to_switch_it =
   2297         name_to_switch_map.find(experiment_name);
   2298     if (name_to_switch_it == name_to_switch_map.end()) {
   2299       NOTREACHED();
   2300       continue;
   2301     }
   2302 
   2303     const std::pair<std::string, std::string>&
   2304         switch_and_value_pair = name_to_switch_it->second;
   2305 
   2306     CHECK(!switch_and_value_pair.first.empty());
   2307     command_line->AppendSwitchASCII(switch_and_value_pair.first,
   2308                                     switch_and_value_pair.second);
   2309     flags_switches_[switch_and_value_pair.first] = switch_and_value_pair.second;
   2310   }
   2311   if (sentinels == kAddSentinels) {
   2312     command_line->AppendSwitch(switches::kFlagSwitchesEnd);
   2313     flags_switches_.insert(
   2314         std::pair<std::string, std::string>(switches::kFlagSwitchesEnd,
   2315                                             std::string()));
   2316   }
   2317 }
   2318 
   2319 bool FlagsState::IsRestartNeededToCommitChanges() {
   2320   return needs_restart_;
   2321 }
   2322 
   2323 void FlagsState::SetExperimentEnabled(FlagsStorage* flags_storage,
   2324                                       const std::string& internal_name,
   2325                                       bool enable) {
   2326   size_t at_index = internal_name.find(testing::kMultiSeparator);
   2327   if (at_index != std::string::npos) {
   2328     DCHECK(enable);
   2329     // We're being asked to enable a multi-choice experiment. Disable the
   2330     // currently selected choice.
   2331     DCHECK_NE(at_index, 0u);
   2332     const std::string experiment_name = internal_name.substr(0, at_index);
   2333     SetExperimentEnabled(flags_storage, experiment_name, false);
   2334 
   2335     // And enable the new choice, if it is not the default first choice.
   2336     if (internal_name != experiment_name + "@0") {
   2337       std::set<std::string> enabled_experiments;
   2338       GetSanitizedEnabledFlags(flags_storage, &enabled_experiments);
   2339       needs_restart_ |= enabled_experiments.insert(internal_name).second;
   2340       flags_storage->SetFlags(enabled_experiments);
   2341     }
   2342     return;
   2343   }
   2344 
   2345   std::set<std::string> enabled_experiments;
   2346   GetSanitizedEnabledFlags(flags_storage, &enabled_experiments);
   2347 
   2348   const Experiment* e = NULL;
   2349   for (size_t i = 0; i < num_experiments; ++i) {
   2350     if (experiments[i].internal_name == internal_name) {
   2351       e = experiments + i;
   2352       break;
   2353     }
   2354   }
   2355   DCHECK(e);
   2356 
   2357   if (e->type == Experiment::SINGLE_VALUE) {
   2358     if (enable)
   2359       needs_restart_ |= enabled_experiments.insert(internal_name).second;
   2360     else
   2361       needs_restart_ |= (enabled_experiments.erase(internal_name) > 0);
   2362   } else {
   2363     if (enable) {
   2364       // Enable the first choice.
   2365       needs_restart_ |= enabled_experiments.insert(e->NameForChoice(0)).second;
   2366     } else {
   2367       // Find the currently enabled choice and disable it.
   2368       for (int i = 0; i < e->num_choices; ++i) {
   2369         std::string choice_name = e->NameForChoice(i);
   2370         if (enabled_experiments.find(choice_name) !=
   2371             enabled_experiments.end()) {
   2372           needs_restart_ = true;
   2373           enabled_experiments.erase(choice_name);
   2374           // Continue on just in case there's a bug and more than one
   2375           // experiment for this choice was enabled.
   2376         }
   2377       }
   2378     }
   2379   }
   2380 
   2381   flags_storage->SetFlags(enabled_experiments);
   2382 }
   2383 
   2384 void FlagsState::RemoveFlagsSwitches(
   2385     std::map<std::string, CommandLine::StringType>* switch_list) {
   2386   for (std::map<std::string, std::string>::const_iterator
   2387            it = flags_switches_.begin(); it != flags_switches_.end(); ++it) {
   2388     switch_list->erase(it->first);
   2389   }
   2390 }
   2391 
   2392 void FlagsState::ResetAllFlags(FlagsStorage* flags_storage) {
   2393   needs_restart_ = true;
   2394 
   2395   std::set<std::string> no_experiments;
   2396   flags_storage->SetFlags(no_experiments);
   2397 }
   2398 
   2399 void FlagsState::reset() {
   2400   needs_restart_ = false;
   2401   flags_switches_.clear();
   2402 }
   2403 
   2404 }  // namespace
   2405 
   2406 namespace testing {
   2407 
   2408 // WARNING: '@' is also used in the html file. If you update this constant you
   2409 // also need to update the html file.
   2410 const char kMultiSeparator[] = "@";
   2411 
   2412 void ClearState() {
   2413   FlagsState::GetInstance()->reset();
   2414 }
   2415 
   2416 void SetExperiments(const Experiment* e, size_t count) {
   2417   if (!e) {
   2418     experiments = kExperiments;
   2419     num_experiments = arraysize(kExperiments);
   2420   } else {
   2421     experiments = e;
   2422     num_experiments = count;
   2423   }
   2424 }
   2425 
   2426 const Experiment* GetExperiments(size_t* count) {
   2427   *count = num_experiments;
   2428   return experiments;
   2429 }
   2430 
   2431 }  // namespace testing
   2432 
   2433 }  // namespace about_flags
   2434