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

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

Issue 3152055: Implement about:labs (Closed)
Patch Set: chromeos fix Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/labs.h ('k') | chrome/browser/prefs/browser_prefs.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // 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
5 #include "chrome/browser/labs.h"
6
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"
14 #include "base/values.h"
15 #include "chrome/browser/platform_util.h"
16 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/browser/profile.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/pref_names.h"
20 #include "grit/generated_resources.h"
21
22 namespace about_labs {
23
24 enum { kOsMac = 1 << 0, kOsWin = 1 << 1, kOsLinux = 1 << 2 };
25
26 struct Experiment {
27 // The internal name of the experiment. This is never shown to the user.
28 // It _is_ however stored in the prefs file, so you shouldn't change the
29 // name of existing labs.
30 const char* internal_name;
31
32 // String id of the message containing the experiment's name.
33 int visible_name_id;
34
35 // String id of the message containing the experiment's description.
36 int visible_description_id;
37
38 // The platforms the experiment is available on
39 // Needs to be more than a compile-time #ifdef because of profile sync.
40 unsigned supported_platforms; // bitmask
41
42 // The commandline parameter that's added when this lab is active. This is
43 // different from |internal_name| so that the commandline flag can be
44 // renamed without breaking the prefs file.
45 const char* command_line;
46 };
47
48 const Experiment kExperiments[] = {
49 {
50 "expose-for-tabs",
51 IDS_LABS_TABPOSE_NAME,
52 IDS_LABS_TABPOSE_DESCRIPTION,
53 kOsMac,
54 #if defined(OS_MACOSX)
55 // The switch exists only on OS X.
56 switches::kEnableExposeForTabs
57 #else
58 ""
59 #endif
60 },
61 {
62 "vertical-tabs",
63 IDS_LABS_LEFTTABS_NAME,
64 IDS_LABS_LEFTTABS_DESCRIPTION,
65 kOsWin,
66 switches::kEnableVerticalTabs
67 }
68 };
69
70 // Extracts the list of enabled lab experiments from a profile and stores them
71 // in a set.
72 void GetEnabledLabs(const PrefService* prefs, std::set<std::string>* result) {
73 const ListValue* enabled_experiments = prefs->GetList(
74 prefs::kEnabledLabsExperiments);
75 if (!enabled_experiments)
76 return;
77
78 for (ListValue::const_iterator it = enabled_experiments->begin();
79 it != enabled_experiments->end();
80 ++it) {
81 std::string experiment_name;
82 if (!(*it)->GetAsString(&experiment_name)) {
83 LOG(WARNING) << "Invalid entry in " << prefs::kEnabledLabsExperiments;
84 continue;
85 }
86 result->insert(experiment_name);
87 }
88 }
89
90 // Takes a set of enabled lab experiments
91 void SetEnabledLabs(
92 PrefService* prefs, const std::set<std::string>& enabled_experiments) {
93 ListValue* experiments_list = prefs->GetMutableList(
94 prefs::kEnabledLabsExperiments);
95 if (!experiments_list)
96 return;
97
98 experiments_list->Clear();
99 for (std::set<std::string>::const_iterator it = enabled_experiments.begin();
100 it != enabled_experiments.end();
101 ++it) {
102 experiments_list->Append(new StringValue(*it));
103 }
104 }
105
106 // Removes all experiments from prefs::kEnabledLabsExperiments that are
107 // unknown, to prevent this list to become very long as experiments are added
108 // and removed.
109 void SanitizeList(PrefService* prefs) {
110 std::set<std::string> known_experiments;
111 for (size_t i = 0; i < arraysize(kExperiments); ++i)
112 known_experiments.insert(kExperiments[i].internal_name);
113
114 std::set<std::string> enabled_experiments;
115 GetEnabledLabs(prefs, &enabled_experiments);
116
117 std::set<std::string> new_enabled_experiments;
118 std::set_intersection(
119 known_experiments.begin(), known_experiments.end(),
120 enabled_experiments.begin(), enabled_experiments.end(),
121 std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
122
123 SetEnabledLabs(prefs, new_enabled_experiments);
124 }
125
126 void GetSanitizedEnabledLabs(
127 PrefService* prefs, std::set<std::string>* result) {
128 SanitizeList(prefs);
129 GetEnabledLabs(prefs, result);
130 }
131
132 int GetCurrentPlatform() {
133 #if defined(OS_MACOSX)
134 return kOsMac;
135 #elif defined(OS_WIN)
136 return kOsWin;
137 #elif defined(OS_LINUX)
138 return kOsLinux;
139 #else
140 #error Unknown platform
141 #endif
142 }
143
144 bool IsEnabled() {
145 #if defined(OS_CHROMEOS)
146 // ChromeOS uses a different mechanism for about:labs; integrated with their
147 // dom ui options.
148 return false;
149 #elif defined(GOOGLE_CHROME_BUILD)
150 // Don't enable this on the stable channel.
151 return platform_util::GetVersionStringModifier() != string16();
152 #else
153 return true;
154 #endif
155 }
156
157 void ConvertLabsToSwitches(Profile* profile, CommandLine* command_line) {
158 // Do not activate labs features on the stable channel.
159 if (!IsEnabled())
160 return;
161
162 std::set<std::string> enabled_experiments;
163 GetSanitizedEnabledLabs(profile->GetPrefs(), &enabled_experiments);
164
165 std::map<std::string, const Experiment*> experiments;
166 for (size_t i = 0; i < arraysize(kExperiments); ++i)
167 experiments[kExperiments[i].internal_name] = &kExperiments[i];
168
169 for (std::set<std::string>::iterator it = enabled_experiments.begin();
170 it != enabled_experiments.end();
171 ++it) {
172 const std::string& experiment_name = *it;
173 std::map<std::string, const Experiment*>::iterator experiment =
174 experiments.find(experiment_name);
175 DCHECK(experiment != experiments.end());
176 if (experiment == experiments.end())
177 continue;
178
179 command_line->AppendSwitch(experiment->second->command_line);
180 }
181 }
182
183 ListValue* GetLabsExperimentsData(Profile* profile) {
184 std::set<std::string> enabled_experiments;
185 GetSanitizedEnabledLabs(profile->GetPrefs(), &enabled_experiments);
186
187 int current_platform = GetCurrentPlatform();
188
189 ListValue* experiments_data = new ListValue();
190 for (size_t i = 0; i < arraysize(kExperiments); ++i) {
191 const Experiment& experiment = kExperiments[i];
192 if (!(experiment.supported_platforms & current_platform))
193 continue;
194
195 DictionaryValue* data = new DictionaryValue();
196 data->SetString("internal_name", experiment.internal_name);
197 data->SetString("name",
198 l10n_util::GetStringUTF16(experiment.visible_name_id));
199 data->SetString("description",
200 l10n_util::GetStringUTF16(
201 experiment.visible_description_id));
202 data->SetBoolean("enabled",
203 enabled_experiments.count(experiment.internal_name) > 0);
204
205 experiments_data->Append(data);
206 }
207 return experiments_data;
208 }
209
210 static bool needs_restart_ = false;
211
212 bool IsRestartNeededToCommitChanges() {
213 return needs_restart_;
214 }
215
216 void SetExperimentEnabled(
217 Profile* profile, const std::string& internal_name, bool enable) {
218 needs_restart_ = true;
219
220 std::set<std::string> enabled_experiments;
221 GetSanitizedEnabledLabs(profile->GetPrefs(), &enabled_experiments);
222
223 if (enable)
224 enabled_experiments.insert(internal_name);
225 else
226 enabled_experiments.erase(internal_name);
227
228 SetEnabledLabs(profile->GetPrefs(), enabled_experiments);
229 }
230
231 } // namespace Labs
OLDNEW
« no previous file with comments | « chrome/browser/labs.h ('k') | chrome/browser/prefs/browser_prefs.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698