blob: 366e173ce396597b250610bfe640e6b5d5799012 [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]ad2a3ded2010-08-27 13:19:0516#include "chrome/browser/prefs/pref_service.h"
[email protected]ad2a3ded2010-08-27 13:19:0517#include "chrome/common/chrome_switches.h"
18#include "chrome/common/pref_names.h"
19#include "grit/generated_resources.h"
20
[email protected]1a47d7e2010-10-15 00:37:2421namespace about_flags {
[email protected]ad2a3ded2010-08-27 13:19:0522
[email protected]e2ddbc92010-10-15 20:02:0723namespace {
24
[email protected]a314ee5a2010-10-26 21:23:2825const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS;
[email protected]ad2a3ded2010-08-27 13:19:0526
27const Experiment kExperiments[] = {
28 {
[email protected]232448fb2010-08-27 18:48:2429 "expose-for-tabs", // Do not change; see above.
[email protected]9486c1f2010-10-14 19:52:1230 IDS_FLAGS_TABPOSE_NAME,
31 IDS_FLAGS_TABPOSE_DESCRIPTION,
[email protected]ad2a3ded2010-08-27 13:19:0532 kOsMac,
33#if defined(OS_MACOSX)
34 // The switch exists only on OS X.
35 switches::kEnableExposeForTabs
36#else
37 ""
38#endif
39 },
40 {
[email protected]232448fb2010-08-27 18:48:2441 "vertical-tabs", // Do not change; see above.
[email protected]9486c1f2010-10-14 19:52:1242 IDS_FLAGS_SIDE_TABS_NAME,
43 IDS_FLAGS_SIDE_TABS_DESCRIPTION,
[email protected]1af1dfe2010-10-19 23:49:1444 // TODO(thakis): Move sidetabs to about:flags on ChromeOS
45 // http://crbug.com/57634
[email protected]ad2a3ded2010-08-27 13:19:0546 kOsWin,
47 switches::kEnableVerticalTabs
[email protected]654151872010-09-13 22:43:0548 },
49 {
50 "tabbed-options", // Do not change; see above.
[email protected]9486c1f2010-10-14 19:52:1251 IDS_FLAGS_TABBED_OPTIONS_NAME,
52 IDS_FLAGS_TABBED_OPTIONS_DESCRIPTION,
[email protected]1af1dfe2010-10-19 23:49:1453 kOsWin | kOsLinux | kOsMac, // Enabled by default on CrOS.
[email protected]654151872010-09-13 22:43:0554 switches::kEnableTabbedOptions
55 },
[email protected]bcf91672010-09-16 15:40:2156 {
[email protected]52fa2d52010-09-25 14:08:5657 "remoting", // Do not change; see above.
[email protected]9486c1f2010-10-14 19:52:1258 IDS_FLAGS_REMOTING_NAME,
[email protected]4fb2f1192010-09-25 14:56:3159#if defined(OS_WIN)
[email protected]52fa2d52010-09-25 14:08:5660 // Windows only supports host functionality at the moment.
[email protected]9486c1f2010-10-14 19:52:1261 IDS_FLAGS_REMOTING_HOST_DESCRIPTION,
[email protected]1af1dfe2010-10-19 23:49:1462#elif defined(OS_LINUX) // Also true for CrOS.
[email protected]52fa2d52010-09-25 14:08:5663 // Linux only supports client functionality at the moment.
[email protected]9486c1f2010-10-14 19:52:1264 IDS_FLAGS_REMOTING_CLIENT_DESCRIPTION,
[email protected]52fa2d52010-09-25 14:08:5665#else
[email protected]a6940852010-09-25 14:25:3266 // On other platforms, this lab isn't available at all.
67 0,
[email protected]52fa2d52010-09-25 14:08:5668#endif
[email protected]1af1dfe2010-10-19 23:49:1469 kOsWin | kOsLinux | kOsCrOS,
[email protected]52fa2d52010-09-25 14:08:5670 switches::kEnableRemoting
71 },
[email protected]a6f03652010-09-28 15:59:0772 {
[email protected]57b66d02010-09-30 11:24:5173 "disable-outdated-plugins", // Do not change; see above.
[email protected]9486c1f2010-10-14 19:52:1274 IDS_FLAGS_DISABLE_OUTDATED_PLUGINS_NAME,
75 IDS_FLAGS_DISABLE_OUTDATED_PLUGINS_DESCRIPTION,
[email protected]57b66d02010-09-30 11:24:5176 kOsAll,
77 switches::kDisableOutdatedPlugins
78 },
[email protected]b3ce30ea2010-10-01 09:33:5379 {
80 "xss-auditor", // Do not change; see above.
[email protected]9486c1f2010-10-14 19:52:1281 IDS_FLAGS_XSS_AUDITOR_NAME,
82 IDS_FLAGS_XSS_AUDITOR_DESCRIPTION,
[email protected]b3ce30ea2010-10-01 09:33:5383 kOsAll,
84 switches::kEnableXSSAuditor
85 },
[email protected]aea2ff42010-10-04 18:04:1986 {
87 "background-webapps", // Do not change; see above
[email protected]9486c1f2010-10-14 19:52:1288 IDS_FLAGS_BACKGROUND_WEBAPPS_NAME,
89 IDS_FLAGS_BACKGROUND_WEBAPPS_DESCRIPTION,
[email protected]aea2ff42010-10-04 18:04:1990 kOsAll,
91 switches::kEnableBackgroundMode
[email protected]7bee0b22010-10-05 17:00:4792 },
93 {
[email protected]c1bbaa82010-11-08 11:17:0594 "conflicting-modules-check", // Do not change; see above.
95 IDS_FLAGS_CONFLICTS_CHECK_NAME,
96 IDS_FLAGS_CONFLICTS_CHECK_DESCRIPTION,
97 kOsWin,
98 switches::kConflictingModulesCheck
99 },
100 {
[email protected]7bee0b22010-10-05 17:00:47101 "cloud-print-proxy", // Do not change; see above.
[email protected]9486c1f2010-10-14 19:52:12102 IDS_FLAGS_CLOUD_PRINT_PROXY_NAME,
103 IDS_FLAGS_CLOUD_PRINT_PROXY_DESCRIPTION,
[email protected]7bee0b22010-10-05 17:00:47104 kOsWin,
105 switches::kEnableCloudPrintProxy
[email protected]8b6588a2010-10-12 02:39:42106 },
[email protected]580939a2010-10-12 18:54:37107 {
108 "match-preview", // Do not change; see above.
[email protected]fdf773c52010-11-01 20:58:19109 IDS_FLAGS_PREDICTIVE_INSTANT_NAME,
110 IDS_FLAGS_PREDICTIVE_INSTANT_DESCRIPTION,
[email protected]cab030772010-11-03 21:37:36111 kOsMac,
[email protected]fdf773c52010-11-01 20:58:19112 switches::kEnablePredictiveInstant
113 },
114 {
115 "verbatim-instant", // Do not change; see above.
116 IDS_FLAGS_VERBATIM_INSTANT_NAME,
117 IDS_FLAGS_VERBATIM_INSTANT_DESCRIPTION,
118 kOsMac | kOsLinux | kOsWin,
119 switches::kEnableVerbatimInstant
[email protected]580939a2010-10-12 18:54:37120 },
[email protected]11c4c812010-10-22 19:50:12121 // FIXME(scheib): Add Flags entry for accelerated Compositing,
122 // or pull it and the strings in generated_resources.grd by Dec 2010
123 // {
124 // "gpu-compositing", // Do not change; see above
125 // IDS_FLAGS_ACCELERATED_COMPOSITING_NAME,
126 // IDS_FLAGS_ACCELERATED_COMPOSITING_DESCRIPTION,
127 // kOsAll,
128 // switches::kDisableAcceleratedCompositing
129 // },
[email protected]8b6588a2010-10-12 02:39:42130 {
131 "gpu-canvas-2d", // Do not change; see above
[email protected]9486c1f2010-10-14 19:52:12132 IDS_FLAGS_ACCELERATED_CANVAS_2D_NAME,
133 IDS_FLAGS_ACCELERATED_CANVAS_2D_DESCRIPTION,
[email protected]1af1dfe2010-10-19 23:49:14134 kOsWin | kOsLinux | kOsCrOS,
[email protected]8b6588a2010-10-12 02:39:42135 switches::kEnableAccelerated2dCanvas
[email protected]8d260e52010-10-13 01:03:05136 },
[email protected]11c4c812010-10-22 19:50:12137 // FIXME(scheib): Add Flags entry for WebGL,
138 // or pull it and the strings in generated_resources.grd by Dec 2010
139 // {
140 // "webgl", // Do not change; see above
141 // IDS_FLAGS_WEBGL_NAME,
142 // IDS_FLAGS_WEBGL_DESCRIPTION,
143 // kOsAll,
144 // switches::kDisableExperimentalWebGL
145 // }
[email protected]8d260e52010-10-13 01:03:05146 {
147 "print-preview", // Do not change; see above
[email protected]9486c1f2010-10-14 19:52:12148 IDS_FLAGS_PRINT_PREVIEW_NAME,
149 IDS_FLAGS_PRINT_PREVIEW_DESCRIPTION,
[email protected]8d260e52010-10-13 01:03:05150 kOsAll,
151 switches::kEnablePrintPreview
[email protected]2fe15fcb2010-10-21 20:39:53152 },
153 {
[email protected]4ff87d202010-11-06 01:28:40154 "enable-nacl", // Do not change; see above.
155 IDS_FLAGS_ENABLE_NACL_NAME,
156 IDS_FLAGS_ENABLE_NACL_DESCRIPTION,
157 kOsAll,
158 switches::kEnableNaCl
159 },
160 {
[email protected]2fe15fcb2010-10-21 20:39:53161 "dns-server",
162 IDS_FLAGS_DNS_SERVER_NAME,
163 IDS_FLAGS_DNS_SERVER_DESCRIPTION,
164 kOsLinux,
165 switches::kDnsServer
166 },
[email protected]177aceb2010-11-03 16:17:41167 {
[email protected]83d00d92010-11-04 19:20:21168 "page-prerender",
169 IDS_FLAGS_PAGE_PRERENDER_NAME,
170 IDS_FLAGS_PAGE_PRERENDER_DESCRIPTION,
171 kOsAll,
172 switches::kEnablePagePrerender
173 },
174 {
[email protected]177aceb2010-11-03 16:17:41175 "confirm-to-quit", // Do not change; see above.
176 IDS_FLAGS_CONFIRM_TO_QUIT_NAME,
177 IDS_FLAGS_CONFIRM_TO_QUIT_DESCRIPTION,
178 kOsMac,
179 switches::kEnableConfirmToQuit
180 },
[email protected]9a40ebef2010-11-10 17:49:13181 {
182 "snap-start", // Do not change; see above.
183 IDS_FLAGS_SNAP_START_NAME,
184 IDS_FLAGS_SNAP_START_DESCRIPTION,
185 kOsAll,
186 switches::kEnableSnapStart
187 },
[email protected]11dd68cd52010-11-12 01:15:32188 {
189 "extension-apis", // Do not change; see above.
190 IDS_FLAGS_EXPERIMENTAL_EXTENSION_APIS_NAME,
191 IDS_FLAGS_EXPERIMENTAL_EXTENSION_APIS_DESCRIPTION,
192 kOsAll,
193 switches::kEnableExperimentalExtensionApis
194 },
[email protected]3627b06d2010-11-12 16:36:16195 {
196 "click-to-play", // Do not change; see above.
197 IDS_FLAGS_CLICK_TO_PLAY_NAME,
198 IDS_FLAGS_CLICK_TO_PLAY_DESCRIPTION,
199 kOsAll,
200 switches::kEnableClickToPlay
201 },
[email protected]ad2a3ded2010-08-27 13:19:05202};
203
[email protected]a314ee5a2010-10-26 21:23:28204const Experiment* experiments = kExperiments;
205size_t num_experiments = arraysize(kExperiments);
206
[email protected]e2ddbc92010-10-15 20:02:07207// Stores and encapsulates the little state that about:flags has.
208class FlagsState {
209 public:
210 FlagsState() : needs_restart_(false) {}
211 void ConvertFlagsToSwitches(PrefService* prefs, CommandLine* command_line);
212 bool IsRestartNeededToCommitChanges();
213 void SetExperimentEnabled(
[email protected]a314ee5a2010-10-26 21:23:28214 PrefService* prefs, const std::string& internal_name, bool enable);
[email protected]e2ddbc92010-10-15 20:02:07215 void RemoveFlagsSwitches(
216 std::map<std::string, CommandLine::StringType>* switch_list);
217 void reset();
218
219 // Returns the singleton instance of this class
220 static FlagsState* instance() {
221 return Singleton<FlagsState>::get();
222 }
223
224 private:
225 bool needs_restart_;
226 std::set<std::string> flags_switches_;
227
228 DISALLOW_COPY_AND_ASSIGN(FlagsState);
229};
230
[email protected]c7b7800a2010-10-07 18:51:35231// Extracts the list of enabled lab experiments from preferences and stores them
[email protected]ad2a3ded2010-08-27 13:19:05232// in a set.
[email protected]1a47d7e2010-10-15 00:37:24233void GetEnabledFlags(const PrefService* prefs, std::set<std::string>* result) {
[email protected]ad2a3ded2010-08-27 13:19:05234 const ListValue* enabled_experiments = prefs->GetList(
235 prefs::kEnabledLabsExperiments);
236 if (!enabled_experiments)
237 return;
238
239 for (ListValue::const_iterator it = enabled_experiments->begin();
240 it != enabled_experiments->end();
241 ++it) {
242 std::string experiment_name;
243 if (!(*it)->GetAsString(&experiment_name)) {
244 LOG(WARNING) << "Invalid entry in " << prefs::kEnabledLabsExperiments;
245 continue;
246 }
247 result->insert(experiment_name);
248 }
249}
250
251// Takes a set of enabled lab experiments
[email protected]1a47d7e2010-10-15 00:37:24252void SetEnabledFlags(
[email protected]ad2a3ded2010-08-27 13:19:05253 PrefService* prefs, const std::set<std::string>& enabled_experiments) {
254 ListValue* experiments_list = prefs->GetMutableList(
255 prefs::kEnabledLabsExperiments);
256 if (!experiments_list)
257 return;
258
259 experiments_list->Clear();
260 for (std::set<std::string>::const_iterator it = enabled_experiments.begin();
261 it != enabled_experiments.end();
262 ++it) {
263 experiments_list->Append(new StringValue(*it));
264 }
265}
266
267// Removes all experiments from prefs::kEnabledLabsExperiments that are
268// unknown, to prevent this list to become very long as experiments are added
269// and removed.
270void SanitizeList(PrefService* prefs) {
271 std::set<std::string> known_experiments;
[email protected]a314ee5a2010-10-26 21:23:28272 for (size_t i = 0; i < num_experiments; ++i)
273 known_experiments.insert(experiments[i].internal_name);
[email protected]ad2a3ded2010-08-27 13:19:05274
275 std::set<std::string> enabled_experiments;
[email protected]1a47d7e2010-10-15 00:37:24276 GetEnabledFlags(prefs, &enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05277
278 std::set<std::string> new_enabled_experiments;
279 std::set_intersection(
280 known_experiments.begin(), known_experiments.end(),
281 enabled_experiments.begin(), enabled_experiments.end(),
282 std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
283
[email protected]1a47d7e2010-10-15 00:37:24284 SetEnabledFlags(prefs, new_enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05285}
286
[email protected]1a47d7e2010-10-15 00:37:24287void GetSanitizedEnabledFlags(
[email protected]ad2a3ded2010-08-27 13:19:05288 PrefService* prefs, std::set<std::string>* result) {
289 SanitizeList(prefs);
[email protected]1a47d7e2010-10-15 00:37:24290 GetEnabledFlags(prefs, result);
[email protected]ad2a3ded2010-08-27 13:19:05291}
292
[email protected]a314ee5a2010-10-26 21:23:28293// Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
294// enabled on the current platform.
295void GetSanitizedEnabledFlagsForCurrentPlatform(
296 PrefService* prefs, std::set<std::string>* result) {
297 GetSanitizedEnabledFlags(prefs, result);
298
299 // Filter out any experiments that aren't enabled on the current platform. We
300 // don't remove these from prefs else syncing to a platform with a different
301 // set of experiments would be lossy.
302 std::set<std::string> platform_experiments;
303 int current_platform = GetCurrentPlatform();
304 for (size_t i = 0; i < num_experiments; ++i) {
305 if (experiments[i].supported_platforms & current_platform)
306 platform_experiments.insert(experiments[i].internal_name);
307 }
308
309 std::set<std::string> new_enabled_experiments;
310 std::set_intersection(
311 platform_experiments.begin(), platform_experiments.end(),
312 result->begin(), result->end(),
313 std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
314
315 result->swap(new_enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05316}
317
[email protected]e2ddbc92010-10-15 20:02:07318} // namespace
319
[email protected]1a47d7e2010-10-15 00:37:24320void ConvertFlagsToSwitches(PrefService* prefs, CommandLine* command_line) {
[email protected]e2ddbc92010-10-15 20:02:07321 FlagsState::instance()->ConvertFlagsToSwitches(prefs, command_line);
[email protected]ad2a3ded2010-08-27 13:19:05322}
323
[email protected]1a47d7e2010-10-15 00:37:24324ListValue* GetFlagsExperimentsData(PrefService* prefs) {
[email protected]ad2a3ded2010-08-27 13:19:05325 std::set<std::string> enabled_experiments;
[email protected]1a47d7e2010-10-15 00:37:24326 GetSanitizedEnabledFlags(prefs, &enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05327
328 int current_platform = GetCurrentPlatform();
329
330 ListValue* experiments_data = new ListValue();
[email protected]a314ee5a2010-10-26 21:23:28331 for (size_t i = 0; i < num_experiments; ++i) {
332 const Experiment& experiment = experiments[i];
[email protected]ad2a3ded2010-08-27 13:19:05333 if (!(experiment.supported_platforms & current_platform))
334 continue;
335
336 DictionaryValue* data = new DictionaryValue();
337 data->SetString("internal_name", experiment.internal_name);
338 data->SetString("name",
339 l10n_util::GetStringUTF16(experiment.visible_name_id));
340 data->SetString("description",
341 l10n_util::GetStringUTF16(
342 experiment.visible_description_id));
343 data->SetBoolean("enabled",
344 enabled_experiments.count(experiment.internal_name) > 0);
345
346 experiments_data->Append(data);
347 }
348 return experiments_data;
349}
350
[email protected]ad2a3ded2010-08-27 13:19:05351bool IsRestartNeededToCommitChanges() {
[email protected]e2ddbc92010-10-15 20:02:07352 return FlagsState::instance()->IsRestartNeededToCommitChanges();
[email protected]ad2a3ded2010-08-27 13:19:05353}
354
355void SetExperimentEnabled(
[email protected]c7b7800a2010-10-07 18:51:35356 PrefService* prefs, const std::string& internal_name, bool enable) {
[email protected]e2ddbc92010-10-15 20:02:07357 FlagsState::instance()->SetExperimentEnabled(prefs, internal_name, enable);
358}
359
360void RemoveFlagsSwitches(
361 std::map<std::string, CommandLine::StringType>* switch_list) {
362 FlagsState::instance()->RemoveFlagsSwitches(switch_list);
363}
364
[email protected]a314ee5a2010-10-26 21:23:28365int GetCurrentPlatform() {
366#if defined(OS_MACOSX)
367 return kOsMac;
368#elif defined(OS_WIN)
369 return kOsWin;
370#elif defined(OS_CHROMEOS) // Needs to be before the OS_LINUX check.
371 return kOsCrOS;
372#elif defined(OS_LINUX)
373 return kOsLinux;
374#else
375#error Unknown platform
376#endif
377}
378
[email protected]e2ddbc92010-10-15 20:02:07379//////////////////////////////////////////////////////////////////////////////
380// FlagsState implementation.
381
382namespace {
383
384void FlagsState::ConvertFlagsToSwitches(
385 PrefService* prefs, CommandLine* command_line) {
[email protected]e2ddbc92010-10-15 20:02:07386 if (command_line->HasSwitch(switches::kNoExperiments))
387 return;
388
389 std::set<std::string> enabled_experiments;
[email protected]a314ee5a2010-10-26 21:23:28390 GetSanitizedEnabledFlagsForCurrentPlatform(prefs, &enabled_experiments);
[email protected]e2ddbc92010-10-15 20:02:07391
[email protected]a314ee5a2010-10-26 21:23:28392 std::map<std::string, const Experiment*> experiment_map;
393 for (size_t i = 0; i < num_experiments; ++i)
394 experiment_map[experiments[i].internal_name] = &experiments[i];
[email protected]e2ddbc92010-10-15 20:02:07395
396 command_line->AppendSwitch(switches::kFlagSwitchesBegin);
397 flags_switches_.insert(switches::kFlagSwitchesBegin);
398 for (std::set<std::string>::iterator it = enabled_experiments.begin();
399 it != enabled_experiments.end();
400 ++it) {
401 const std::string& experiment_name = *it;
402 std::map<std::string, const Experiment*>::iterator experiment =
[email protected]a314ee5a2010-10-26 21:23:28403 experiment_map.find(experiment_name);
404 DCHECK(experiment != experiment_map.end());
405 if (experiment == experiment_map.end())
[email protected]e2ddbc92010-10-15 20:02:07406 continue;
407
408 command_line->AppendSwitch(experiment->second->command_line);
409 flags_switches_.insert(experiment->second->command_line);
410 }
411 command_line->AppendSwitch(switches::kFlagSwitchesEnd);
412 flags_switches_.insert(switches::kFlagSwitchesEnd);
413}
414
415bool FlagsState::IsRestartNeededToCommitChanges() {
416 return needs_restart_;
417}
418
419void FlagsState::SetExperimentEnabled(
420 PrefService* prefs, const std::string& internal_name, bool enable) {
[email protected]ad2a3ded2010-08-27 13:19:05421 needs_restart_ = true;
422
423 std::set<std::string> enabled_experiments;
[email protected]1a47d7e2010-10-15 00:37:24424 GetSanitizedEnabledFlags(prefs, &enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05425
426 if (enable)
427 enabled_experiments.insert(internal_name);
428 else
429 enabled_experiments.erase(internal_name);
430
[email protected]1a47d7e2010-10-15 00:37:24431 SetEnabledFlags(prefs, enabled_experiments);
[email protected]ad2a3ded2010-08-27 13:19:05432}
433
[email protected]e2ddbc92010-10-15 20:02:07434void FlagsState::RemoveFlagsSwitches(
435 std::map<std::string, CommandLine::StringType>* switch_list) {
436 for (std::set<std::string>::const_iterator it = flags_switches_.begin();
437 it != flags_switches_.end();
438 ++it) {
439 switch_list->erase(*it);
440 }
441}
442
443void FlagsState::reset() {
444 needs_restart_ = false;
445 flags_switches_.clear();
446}
447
448} // namespace
449
450namespace testing {
451void ClearState() {
452 FlagsState::instance()->reset();
453}
[email protected]a314ee5a2010-10-26 21:23:28454
455void SetExperiments(const Experiment* e, size_t count) {
456 if (!e) {
457 experiments = kExperiments;
458 num_experiments = arraysize(kExperiments);
459 } else {
460 experiments = e;
461 num_experiments = count;
462 }
463}
464
[email protected]e2ddbc92010-10-15 20:02:07465} // namespace testing
466
[email protected]1a47d7e2010-10-15 00:37:24467} // namespace about_flags