blob: 38ea7f7e3b0689e2a5be30a9de3f8264d97c6925 [file] [log] [blame]
[email protected]ad2a3ded2010-08-27 13:19:051// Copyright (c) 2010 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
[email protected]1a47d7e2010-10-15 00:37:245#include "chrome/browser/about_flags.h"
[email protected]ad2a3ded2010-08-27 13:19:056
7#include <algorithm>
8#include <iterator>
9#include <map>
10#include <set>
11
12#include "app/l10n_util.h"
13#include "base/command_line.h"
[email protected]e2ddbc92010-10-15 20:02:0714#include "base/singleton.h"
[email protected]ad2a3ded2010-08-27 13:19:0515#include "base/values.h"
[email protected]4bc5050c2010-11-18 17:55:5416#include "chrome/browser/metrics/user_metrics.h"
[email protected]ad2a3ded2010-08-27 13:19:0517#include "chrome/browser/prefs/pref_service.h"
[email protected]ad2a3ded2010-08-27 13:19:0518#include "chrome/common/chrome_switches.h"
19#include "chrome/common/pref_names.h"
20#include "grit/generated_resources.h"
21
[email protected]1a47d7e2010-10-15 00:37:2422namespace about_flags {
[email protected]ad2a3ded2010-08-27 13:19:0523
[email protected]e2ddbc92010-10-15 20:02:0724namespace {
25
[email protected]a314ee5a2010-10-26 21:23:2826const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS;
[email protected]ad2a3ded2010-08-27 13:19:0527
[email protected]ba8164242010-11-16 21:31:0028// Names for former Chrome OS Labs experiments, shared with prefs migration
29// code.
30const char kMediaPlayerExperimentName[] = "media-player";
31const char kAdvancedFileSystemExperimentName[] = "advanced-file-system";
32const char kVerticalTabsExperimentName[] = "vertical-tabs";
33
[email protected]4bc5050c2010-11-18 17:55:5434// RECORDING USER METRICS FOR FLAGS:
35// -----------------------------------------------------------------------------
36// The first line of the experiment is the internal name. If you'd like to
37// gather statistics about the usage of your flag, you should append a marker
38// comment to the end of the feature name, like so:
39// "my-special-feature", // FLAGS:RECORD_UMA
40//
41// After doing that, run //chrome/tools/extract_actions.py (see instructions at
42// the top of that file for details) to update the chromeactions.txt file, which
43// will enable UMA to record your feature flag.
44//
45// After your feature has shipped under a flag, you can locate the metrics
46// under the action name AboutFlags_internal-action-name. Actions are recorded
47// once per startup, so you should divide this number by AboutFlags_StartupTick
48// to get a sense of usage. Note that this will not be the same as number of
49// users with a given feature enabled because users can quit and relaunch
50// the application multiple times over a given time interval.
51// TODO(rsesek): See if there's a way to count per-user, rather than
52// per-startup.
53
[email protected]ad2a3ded2010-08-27 13:19:0554const Experiment kExperiments[] = {
55 {
[email protected]4bc5050c2010-11-18 17:55:5456 "expose-for-tabs", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:1257 IDS_FLAGS_TABPOSE_NAME,
58 IDS_FLAGS_TABPOSE_DESCRIPTION,
[email protected]ad2a3ded2010-08-27 13:19:0559 kOsMac,
60#if defined(OS_MACOSX)
61 // The switch exists only on OS X.
62 switches::kEnableExposeForTabs
63#else
64 ""
65#endif
66 },
67 {
[email protected]ba8164242010-11-16 21:31:0068 kMediaPlayerExperimentName,
69 IDS_FLAGS_MEDIA_PLAYER_NAME,
70 IDS_FLAGS_MEDIA_PLAYER_DESCRIPTION,
71 kOsCrOS,
72#if defined(OS_CHROMEOS)
73 // The switch exists only on Chrome OS.
74 switches::kEnableMediaPlayer
75#else
76 ""
77#endif
78 },
79 {
80 kAdvancedFileSystemExperimentName,
81 IDS_FLAGS_ADVANCED_FS_NAME,
82 IDS_FLAGS_ADVANCED_FS_DESCRIPTION,
83 kOsCrOS,
84#if defined(OS_CHROMEOS)
85 // The switch exists only on Chrome OS.
86 switches::kEnableAdvancedFileSystem
87#else
88 ""
89#endif
90 },
91 {
[email protected]4bc5050c2010-11-18 17:55:5492 "vertical-tabs", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:1293 IDS_FLAGS_SIDE_TABS_NAME,
94 IDS_FLAGS_SIDE_TABS_DESCRIPTION,
[email protected]ba8164242010-11-16 21:31:0095 kOsWin | kOsCrOS,
[email protected]ad2a3ded2010-08-27 13:19:0596 switches::kEnableVerticalTabs
[email protected]654151872010-09-13 22:43:0597 },
98 {
[email protected]4bc5050c2010-11-18 17:55:5499 "tabbed-options", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12100 IDS_FLAGS_TABBED_OPTIONS_NAME,
101 IDS_FLAGS_TABBED_OPTIONS_DESCRIPTION,
[email protected]1af1dfe2010-10-19 23:49:14102 kOsWin | kOsLinux | kOsMac, // Enabled by default on CrOS.
[email protected]654151872010-09-13 22:43:05103 switches::kEnableTabbedOptions
104 },
[email protected]bcf91672010-09-16 15:40:21105 {
[email protected]4bc5050c2010-11-18 17:55:54106 "remoting", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12107 IDS_FLAGS_REMOTING_NAME,
[email protected]4fb2f1192010-09-25 14:56:31108#if defined(OS_WIN)
[email protected]52fa2d52010-09-25 14:08:56109 // Windows only supports host functionality at the moment.
[email protected]9486c1f2010-10-14 19:52:12110 IDS_FLAGS_REMOTING_HOST_DESCRIPTION,
[email protected]1af1dfe2010-10-19 23:49:14111#elif defined(OS_LINUX) // Also true for CrOS.
[email protected]52fa2d52010-09-25 14:08:56112 // Linux only supports client functionality at the moment.
[email protected]9486c1f2010-10-14 19:52:12113 IDS_FLAGS_REMOTING_CLIENT_DESCRIPTION,
[email protected]52fa2d52010-09-25 14:08:56114#else
[email protected]a6940852010-09-25 14:25:32115 // On other platforms, this lab isn't available at all.
116 0,
[email protected]52fa2d52010-09-25 14:08:56117#endif
[email protected]1af1dfe2010-10-19 23:49:14118 kOsWin | kOsLinux | kOsCrOS,
[email protected]52fa2d52010-09-25 14:08:56119 switches::kEnableRemoting
120 },
[email protected]a6f03652010-09-28 15:59:07121 {
[email protected]4bc5050c2010-11-18 17:55:54122 "disable-outdated-plugins", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12123 IDS_FLAGS_DISABLE_OUTDATED_PLUGINS_NAME,
124 IDS_FLAGS_DISABLE_OUTDATED_PLUGINS_DESCRIPTION,
[email protected]57b66d02010-09-30 11:24:51125 kOsAll,
126 switches::kDisableOutdatedPlugins
127 },
[email protected]b3ce30ea2010-10-01 09:33:53128 {
[email protected]4bc5050c2010-11-18 17:55:54129 "xss-auditor", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12130 IDS_FLAGS_XSS_AUDITOR_NAME,
131 IDS_FLAGS_XSS_AUDITOR_DESCRIPTION,
[email protected]b3ce30ea2010-10-01 09:33:53132 kOsAll,
133 switches::kEnableXSSAuditor
134 },
[email protected]aea2ff42010-10-04 18:04:19135 {
[email protected]4bc5050c2010-11-18 17:55:54136 "background-webapps", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12137 IDS_FLAGS_BACKGROUND_WEBAPPS_NAME,
138 IDS_FLAGS_BACKGROUND_WEBAPPS_DESCRIPTION,
[email protected]186c8af2010-11-24 07:01:10139 kOsMac | kOsLinux | kOsCrOS, // Enabled by default on windows
[email protected]aea2ff42010-10-04 18:04:19140 switches::kEnableBackgroundMode
[email protected]7bee0b22010-10-05 17:00:47141 },
142 {
[email protected]4bc5050c2010-11-18 17:55:54143 "conflicting-modules-check", // FLAGS:RECORD_UMA
[email protected]c1bbaa82010-11-08 11:17:05144 IDS_FLAGS_CONFLICTS_CHECK_NAME,
145 IDS_FLAGS_CONFLICTS_CHECK_DESCRIPTION,
146 kOsWin,
147 switches::kConflictingModulesCheck
148 },
149 {
[email protected]4bc5050c2010-11-18 17:55:54150 "cloud-print-proxy", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12151 IDS_FLAGS_CLOUD_PRINT_PROXY_NAME,
152 IDS_FLAGS_CLOUD_PRINT_PROXY_DESCRIPTION,
[email protected]fa6d2a2f2010-11-30 21:47:19153#if defined(GOOGLE_CHROME_BUILD)
154 // For a Chrome build, we know we have a PDF plug-in, and so we'll
155 // enable by platform as we get things working.
156 0,
157#else
158 // Otherwise, where we know it could be working if a viable PDF
159 // plug-in could be supplied, we'll keep the lab enabled.
[email protected]7bee0b22010-10-05 17:00:47160 kOsWin,
[email protected]fa6d2a2f2010-11-30 21:47:19161#endif
[email protected]7bee0b22010-10-05 17:00:47162 switches::kEnableCloudPrintProxy
[email protected]8b6588a2010-10-12 02:39:42163 },
[email protected]580939a2010-10-12 18:54:37164 {
[email protected]bb461532010-11-26 21:50:23165 "crxless-web-apps",
166 IDS_FLAGS_CRXLESS_WEB_APPS_NAME,
167 IDS_FLAGS_CRXLESS_WEB_APPS_DESCRIPTION,
168 kOsAll,
169 switches::kEnableCrxlessWebApps
170 },
171 {
[email protected]4bc5050c2010-11-18 17:55:54172 "match-preview", // FLAGS:RECORD_UMA
[email protected]fdf773c52010-11-01 20:58:19173 IDS_FLAGS_PREDICTIVE_INSTANT_NAME,
174 IDS_FLAGS_PREDICTIVE_INSTANT_DESCRIPTION,
[email protected]cab030772010-11-03 21:37:36175 kOsMac,
[email protected]fdf773c52010-11-01 20:58:19176 switches::kEnablePredictiveInstant
177 },
[email protected]11c4c812010-10-22 19:50:12178 // FIXME(scheib): Add Flags entry for accelerated Compositing,
179 // or pull it and the strings in generated_resources.grd by Dec 2010
180 // {
[email protected]4bc5050c2010-11-18 17:55:54181 // "gpu-compositing",
[email protected]11c4c812010-10-22 19:50:12182 // IDS_FLAGS_ACCELERATED_COMPOSITING_NAME,
183 // IDS_FLAGS_ACCELERATED_COMPOSITING_DESCRIPTION,
184 // kOsAll,
185 // switches::kDisableAcceleratedCompositing
186 // },
[email protected]8b6588a2010-10-12 02:39:42187 {
[email protected]4bc5050c2010-11-18 17:55:54188 "gpu-canvas-2d", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12189 IDS_FLAGS_ACCELERATED_CANVAS_2D_NAME,
190 IDS_FLAGS_ACCELERATED_CANVAS_2D_DESCRIPTION,
[email protected]1af1dfe2010-10-19 23:49:14191 kOsWin | kOsLinux | kOsCrOS,
[email protected]8b6588a2010-10-12 02:39:42192 switches::kEnableAccelerated2dCanvas
[email protected]8d260e52010-10-13 01:03:05193 },
[email protected]11c4c812010-10-22 19:50:12194 // FIXME(scheib): Add Flags entry for WebGL,
195 // or pull it and the strings in generated_resources.grd by Dec 2010
196 // {
[email protected]4bc5050c2010-11-18 17:55:54197 // "webgl",
[email protected]11c4c812010-10-22 19:50:12198 // IDS_FLAGS_WEBGL_NAME,
199 // IDS_FLAGS_WEBGL_DESCRIPTION,
200 // kOsAll,
201 // switches::kDisableExperimentalWebGL
202 // }
[email protected]8d260e52010-10-13 01:03:05203 {
[email protected]4bc5050c2010-11-18 17:55:54204 "print-preview", // FLAGS:RECORD_UMA
[email protected]9486c1f2010-10-14 19:52:12205 IDS_FLAGS_PRINT_PREVIEW_NAME,
206 IDS_FLAGS_PRINT_PREVIEW_DESCRIPTION,
[email protected]8d260e52010-10-13 01:03:05207 kOsAll,
208 switches::kEnablePrintPreview
[email protected]2fe15fcb2010-10-21 20:39:53209 },
210 {
[email protected]4bc5050c2010-11-18 17:55:54211 "enable-nacl", // FLAGS:RECORD_UMA
[email protected]4ff87d202010-11-06 01:28:40212 IDS_FLAGS_ENABLE_NACL_NAME,
213 IDS_FLAGS_ENABLE_NACL_DESCRIPTION,
214 kOsAll,
215 switches::kEnableNaCl
216 },
217 {
[email protected]4bc5050c2010-11-18 17:55:54218 "dns-server", // FLAGS:RECORD_UMA
[email protected]2fe15fcb2010-10-21 20:39:53219 IDS_FLAGS_DNS_SERVER_NAME,
220 IDS_FLAGS_DNS_SERVER_DESCRIPTION,
221 kOsLinux,
222 switches::kDnsServer
223 },
[email protected]177aceb2010-11-03 16:17:41224 {
[email protected]4bc5050c2010-11-18 17:55:54225 "page-prerender", // FLAGS:RECORD_UMA
[email protected]83d00d92010-11-04 19:20:21226 IDS_FLAGS_PAGE_PRERENDER_NAME,
227 IDS_FLAGS_PAGE_PRERENDER_DESCRIPTION,
228 kOsAll,
229 switches::kEnablePagePrerender
230 },
231 {
[email protected]4bc5050c2010-11-18 17:55:54232 "confirm-to-quit", // FLAGS:RECORD_UMA
[email protected]177aceb2010-11-03 16:17:41233 IDS_FLAGS_CONFIRM_TO_QUIT_NAME,
234 IDS_FLAGS_CONFIRM_TO_QUIT_DESCRIPTION,
235 kOsMac,
236 switches::kEnableConfirmToQuit
237 },
[email protected]9a40ebef2010-11-10 17:49:13238 {
[email protected]4bc5050c2010-11-18 17:55:54239 "extension-apis", // FLAGS:RECORD_UMA
[email protected]11dd68cd52010-11-12 01:15:32240 IDS_FLAGS_EXPERIMENTAL_EXTENSION_APIS_NAME,
241 IDS_FLAGS_EXPERIMENTAL_EXTENSION_APIS_DESCRIPTION,
242 kOsAll,
243 switches::kEnableExperimentalExtensionApis
244 },
[email protected]3627b06d2010-11-12 16:36:16245 {
[email protected]4bc5050c2010-11-18 17:55:54246 "click-to-play", // FLAGS:RECORD_UMA
[email protected]3627b06d2010-11-12 16:36:16247 IDS_FLAGS_CLICK_TO_PLAY_NAME,
248 IDS_FLAGS_CLICK_TO_PLAY_DESCRIPTION,
249 kOsAll,
250 switches::kEnableClickToPlay
251 },
[email protected]80bd24e2010-11-30 09:34:38252 {
253 "disable-hyperlink-auditing",
254 IDS_FLAGS_DISABLE_HYPERLINK_AUDITING_NAME,
255 IDS_FLAGS_DISABLE_HYPERLINK_AUDITING_DESCRIPTION,
256 kOsAll,
257 switches::kNoPings
[email protected]feb28fef2010-12-01 10:52:51258 },
259 {
260 "experimental-location-features", // FLAGS:RECORD_UMA
261 IDS_FLAGS_EXPERIMENTAL_LOCATION_FEATURES_NAME,
262 IDS_FLAGS_EXPERIMENTAL_LOCATION_FEATURES_DESCRIPTION,
263 kOsMac | kOsWin | kOsLinux, // Currently does nothing on CrOS.
264 switches::kExperimentalLocationFeatures
[email protected]80bd24e2010-11-30 09:34:38265 }
[email protected]ad2a3ded2010-08-27 13:19:05266};
267
[email protected]a314ee5a2010-10-26 21:23:28268const Experiment* experiments = kExperiments;
269size_t num_experiments = arraysize(kExperiments);
270
[email protected]e2ddbc92010-10-15 20:02:07271// Stores and encapsulates the little state that about:flags has.
272class FlagsState {
273 public:
274 FlagsState() : needs_restart_(false) {}
275 void ConvertFlagsToSwitches(PrefService* prefs, CommandLine* command_line);
276 bool IsRestartNeededToCommitChanges();
277 void SetExperimentEnabled(
[email protected]a314ee5a2010-10-26 21:23:28278 PrefService* prefs, const std::string& internal_name, bool enable);
[email protected]e2ddbc92010-10-15 20:02:07279 void RemoveFlagsSwitches(
280 std::map<std::string, CommandLine::StringType>* switch_list);
281 void reset();
282
283 // Returns the singleton instance of this class
284 static FlagsState* instance() {
285 return Singleton<FlagsState>::get();
286 }
287
288 private:
289 bool needs_restart_;
290 std::set<std::string> flags_switches_;
291
292 DISALLOW_COPY_AND_ASSIGN(FlagsState);
293};
294
[email protected]ba8164242010-11-16 21:31:00295#if defined(OS_CHROMEOS)
296// Migrates Chrome OS Labs settings to experiments adding flags to enabled
297// experiment list if the corresponding pref is on.
298void MigrateChromeOSLabsPrefs(PrefService* prefs,
299 std::set<std::string>* result) {
300 DCHECK(prefs);
301 DCHECK(result);
302 if (prefs->GetBoolean(prefs::kLabsMediaplayerEnabled))
303 result->insert(kMediaPlayerExperimentName);
304 if (prefs->GetBoolean(prefs::kLabsAdvancedFilesystemEnabled))
305 result->insert(kAdvancedFileSystemExperimentName);
306 if (prefs->GetBoolean(prefs::kUseVerticalTabs))
307 result->insert(kVerticalTabsExperimentName);
308 prefs->SetBoolean(prefs::kLabsMediaplayerEnabled, false);
309 prefs->SetBoolean(prefs::kLabsAdvancedFilesystemEnabled, false);
310 prefs->SetBoolean(prefs::kUseVerticalTabs, false);
311}
312#endif
313
[email protected]c7b7800a2010-10-07 18:51:35314// Extracts the list of enabled lab experiments from preferences and stores them
[email protected]ad2a3ded2010-08-27 13:19:05315// in a set.
[email protected]1a47d7e2010-10-15 00:37:24316void GetEnabledFlags(const PrefService* prefs, std::set<std::string>* result) {
[email protected]ad2a3ded2010-08-27 13:19:05317 const ListValue* enabled_experiments = prefs->GetList(
318 prefs::kEnabledLabsExperiments);
319 if (!enabled_experiments)
320 return;
321
322 for (ListValue::const_iterator it = enabled_experiments->begin();
323 it != enabled_experiments->end();
324 ++it) {
325 std::string experiment_name;
326 if (!(*it)->GetAsString(&experiment_name)) {
327 LOG(WARNING) << "Invalid entry in " << prefs::kEnabledLabsExperiments;
328 continue;
329 }
330 result->insert(experiment_name);
331 }
332}
333
334// Takes a set of enabled lab experiments
[email protected]1a47d7e2010-10-15 00:37:24335void SetEnabledFlags(
[email protected]ad2a3ded2010-08-27 13:19:05336 PrefService* prefs, const std::set<std::string>& enabled_experiments) {
337 ListValue* experiments_list = prefs->GetMutableList(
338 prefs::kEnabledLabsExperiments);
339 if (!experiments_list)
340 return;
341
342 experiments_list->Clear();
343 for (std::set<std::string>::const_iterator it = enabled_experiments.begin();
344 it != enabled_experiments.end();
345 ++it) {
346 experiments_list->Append(new StringValue(*it));
347 }
348}
349
350// Removes all experiments from prefs::kEnabledLabsExperiments that are
351// unknown, to prevent this list to become very long as experiments are added
352// and removed.
353void SanitizeList(PrefService* prefs) {
354 std::set<std::string> known_experiments;
[email protected]a314ee5a2010-10-26 21:23:28355 for (size_t i = 0; i < num_experiments; ++i)
356 known_experiments.insert(experiments[i].internal_name);
[email protected]ad2a3ded2010-08-27 13:19:05357
358 std::set<std::string> enabled_experiments;
[email protected]1a47d7e2010-10-15 00:37:24359 GetEnabledFlags(prefs, &enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05360
361 std::set<std::string> new_enabled_experiments;
362 std::set_intersection(
363 known_experiments.begin(), known_experiments.end(),
364 enabled_experiments.begin(), enabled_experiments.end(),
365 std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
366
[email protected]1a47d7e2010-10-15 00:37:24367 SetEnabledFlags(prefs, new_enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05368}
369
[email protected]1a47d7e2010-10-15 00:37:24370void GetSanitizedEnabledFlags(
[email protected]ad2a3ded2010-08-27 13:19:05371 PrefService* prefs, std::set<std::string>* result) {
372 SanitizeList(prefs);
[email protected]1a47d7e2010-10-15 00:37:24373 GetEnabledFlags(prefs, result);
[email protected]ad2a3ded2010-08-27 13:19:05374}
375
[email protected]a314ee5a2010-10-26 21:23:28376// Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
377// enabled on the current platform.
378void GetSanitizedEnabledFlagsForCurrentPlatform(
379 PrefService* prefs, std::set<std::string>* result) {
380 GetSanitizedEnabledFlags(prefs, result);
381
382 // Filter out any experiments that aren't enabled on the current platform. We
383 // don't remove these from prefs else syncing to a platform with a different
384 // set of experiments would be lossy.
385 std::set<std::string> platform_experiments;
386 int current_platform = GetCurrentPlatform();
387 for (size_t i = 0; i < num_experiments; ++i) {
388 if (experiments[i].supported_platforms & current_platform)
389 platform_experiments.insert(experiments[i].internal_name);
390 }
391
392 std::set<std::string> new_enabled_experiments;
393 std::set_intersection(
394 platform_experiments.begin(), platform_experiments.end(),
395 result->begin(), result->end(),
396 std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
397
398 result->swap(new_enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05399}
400
[email protected]e2ddbc92010-10-15 20:02:07401} // namespace
402
[email protected]1a47d7e2010-10-15 00:37:24403void ConvertFlagsToSwitches(PrefService* prefs, CommandLine* command_line) {
[email protected]e2ddbc92010-10-15 20:02:07404 FlagsState::instance()->ConvertFlagsToSwitches(prefs, command_line);
[email protected]ad2a3ded2010-08-27 13:19:05405}
406
[email protected]1a47d7e2010-10-15 00:37:24407ListValue* GetFlagsExperimentsData(PrefService* prefs) {
[email protected]ad2a3ded2010-08-27 13:19:05408 std::set<std::string> enabled_experiments;
[email protected]1a47d7e2010-10-15 00:37:24409 GetSanitizedEnabledFlags(prefs, &enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05410
411 int current_platform = GetCurrentPlatform();
412
413 ListValue* experiments_data = new ListValue();
[email protected]a314ee5a2010-10-26 21:23:28414 for (size_t i = 0; i < num_experiments; ++i) {
415 const Experiment& experiment = experiments[i];
[email protected]ad2a3ded2010-08-27 13:19:05416 if (!(experiment.supported_platforms & current_platform))
417 continue;
418
419 DictionaryValue* data = new DictionaryValue();
420 data->SetString("internal_name", experiment.internal_name);
421 data->SetString("name",
422 l10n_util::GetStringUTF16(experiment.visible_name_id));
423 data->SetString("description",
424 l10n_util::GetStringUTF16(
425 experiment.visible_description_id));
426 data->SetBoolean("enabled",
427 enabled_experiments.count(experiment.internal_name) > 0);
428
429 experiments_data->Append(data);
430 }
431 return experiments_data;
432}
433
[email protected]ad2a3ded2010-08-27 13:19:05434bool IsRestartNeededToCommitChanges() {
[email protected]e2ddbc92010-10-15 20:02:07435 return FlagsState::instance()->IsRestartNeededToCommitChanges();
[email protected]ad2a3ded2010-08-27 13:19:05436}
437
438void SetExperimentEnabled(
[email protected]c7b7800a2010-10-07 18:51:35439 PrefService* prefs, const std::string& internal_name, bool enable) {
[email protected]e2ddbc92010-10-15 20:02:07440 FlagsState::instance()->SetExperimentEnabled(prefs, internal_name, enable);
441}
442
443void RemoveFlagsSwitches(
444 std::map<std::string, CommandLine::StringType>* switch_list) {
445 FlagsState::instance()->RemoveFlagsSwitches(switch_list);
446}
447
[email protected]a314ee5a2010-10-26 21:23:28448int GetCurrentPlatform() {
449#if defined(OS_MACOSX)
450 return kOsMac;
451#elif defined(OS_WIN)
452 return kOsWin;
453#elif defined(OS_CHROMEOS) // Needs to be before the OS_LINUX check.
454 return kOsCrOS;
455#elif defined(OS_LINUX)
456 return kOsLinux;
457#else
458#error Unknown platform
459#endif
460}
461
[email protected]4bc5050c2010-11-18 17:55:54462void RecordUMAStatistics(const PrefService* prefs) {
463 std::set<std::string> flags;
464 GetEnabledFlags(prefs, &flags);
465 for (std::set<std::string>::iterator it = flags.begin(); it != flags.end();
466 ++it) {
467 std::string action("AboutFlags_");
468 action += *it;
469 UserMetrics::RecordComputedAction(action);
470 }
471 // Since flag metrics are recorded every startup, add a tick so that the
472 // stats can be made meaningful.
473 if (flags.size())
474 UserMetrics::RecordAction(UserMetricsAction("AboutFlags_StartupTick"));
475}
476
[email protected]e2ddbc92010-10-15 20:02:07477//////////////////////////////////////////////////////////////////////////////
478// FlagsState implementation.
479
480namespace {
481
482void FlagsState::ConvertFlagsToSwitches(
483 PrefService* prefs, CommandLine* command_line) {
[email protected]e2ddbc92010-10-15 20:02:07484 if (command_line->HasSwitch(switches::kNoExperiments))
485 return;
486
487 std::set<std::string> enabled_experiments;
[email protected]ba8164242010-11-16 21:31:00488
489#if defined(OS_CHROMEOS)
490 // Some experiments were implemented via prefs on Chrome OS and we want to
491 // seamlessly migrate these prefs to about:flags for updated users.
492 MigrateChromeOSLabsPrefs(prefs, &enabled_experiments);
493#endif
494
[email protected]a314ee5a2010-10-26 21:23:28495 GetSanitizedEnabledFlagsForCurrentPlatform(prefs, &enabled_experiments);
[email protected]e2ddbc92010-10-15 20:02:07496
[email protected]a314ee5a2010-10-26 21:23:28497 std::map<std::string, const Experiment*> experiment_map;
498 for (size_t i = 0; i < num_experiments; ++i)
499 experiment_map[experiments[i].internal_name] = &experiments[i];
[email protected]e2ddbc92010-10-15 20:02:07500
501 command_line->AppendSwitch(switches::kFlagSwitchesBegin);
502 flags_switches_.insert(switches::kFlagSwitchesBegin);
503 for (std::set<std::string>::iterator it = enabled_experiments.begin();
504 it != enabled_experiments.end();
505 ++it) {
506 const std::string& experiment_name = *it;
507 std::map<std::string, const Experiment*>::iterator experiment =
[email protected]a314ee5a2010-10-26 21:23:28508 experiment_map.find(experiment_name);
509 DCHECK(experiment != experiment_map.end());
510 if (experiment == experiment_map.end())
[email protected]e2ddbc92010-10-15 20:02:07511 continue;
512
513 command_line->AppendSwitch(experiment->second->command_line);
514 flags_switches_.insert(experiment->second->command_line);
515 }
516 command_line->AppendSwitch(switches::kFlagSwitchesEnd);
517 flags_switches_.insert(switches::kFlagSwitchesEnd);
518}
519
520bool FlagsState::IsRestartNeededToCommitChanges() {
521 return needs_restart_;
522}
523
524void FlagsState::SetExperimentEnabled(
525 PrefService* prefs, const std::string& internal_name, bool enable) {
[email protected]ad2a3ded2010-08-27 13:19:05526 needs_restart_ = true;
527
528 std::set<std::string> enabled_experiments;
[email protected]1a47d7e2010-10-15 00:37:24529 GetSanitizedEnabledFlags(prefs, &enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05530
531 if (enable)
532 enabled_experiments.insert(internal_name);
533 else
534 enabled_experiments.erase(internal_name);
535
[email protected]1a47d7e2010-10-15 00:37:24536 SetEnabledFlags(prefs, enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05537}
538
[email protected]e2ddbc92010-10-15 20:02:07539void FlagsState::RemoveFlagsSwitches(
540 std::map<std::string, CommandLine::StringType>* switch_list) {
541 for (std::set<std::string>::const_iterator it = flags_switches_.begin();
542 it != flags_switches_.end();
543 ++it) {
544 switch_list->erase(*it);
545 }
546}
547
548void FlagsState::reset() {
549 needs_restart_ = false;
550 flags_switches_.clear();
551}
552
553} // namespace
554
555namespace testing {
556void ClearState() {
557 FlagsState::instance()->reset();
558}
[email protected]a314ee5a2010-10-26 21:23:28559
560void SetExperiments(const Experiment* e, size_t count) {
561 if (!e) {
562 experiments = kExperiments;
563 num_experiments = arraysize(kExperiments);
564 } else {
565 experiments = e;
566 num_experiments = count;
567 }
568}
569
[email protected]e2ddbc92010-10-15 20:02:07570} // namespace testing
571
[email protected]1a47d7e2010-10-15 00:37:24572} // namespace about_flags