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

Unified Diff: chrome/browser/labs.cc

Issue 3152055: Implement about:labs (Closed)
Patch Set: chromeos fix Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/labs.h ('k') | chrome/browser/prefs/browser_prefs.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/labs.cc
diff --git a/chrome/browser/labs.cc b/chrome/browser/labs.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6bd1c27773dbdd5973627a65f3a52a631c04033d
--- /dev/null
+++ b/chrome/browser/labs.cc
@@ -0,0 +1,231 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/labs.h"
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <set>
+
+#include "app/l10n_util.h"
+#include "base/command_line.h"
+#include "base/values.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+
+namespace about_labs {
+
+enum { kOsMac = 1 << 0, kOsWin = 1 << 1, kOsLinux = 1 << 2 };
+
+struct Experiment {
+ // The internal name of the experiment. This is never shown to the user.
+ // It _is_ however stored in the prefs file, so you shouldn't change the
+ // name of existing labs.
+ const char* internal_name;
+
+ // String id of the message containing the experiment's name.
+ int visible_name_id;
+
+ // String id of the message containing the experiment's description.
+ int visible_description_id;
+
+ // The platforms the experiment is available on
+ // Needs to be more than a compile-time #ifdef because of profile sync.
+ unsigned supported_platforms; // bitmask
+
+ // The commandline parameter that's added when this lab is active. This is
+ // different from |internal_name| so that the commandline flag can be
+ // renamed without breaking the prefs file.
+ const char* command_line;
+};
+
+const Experiment kExperiments[] = {
+ {
+ "expose-for-tabs",
+ IDS_LABS_TABPOSE_NAME,
+ IDS_LABS_TABPOSE_DESCRIPTION,
+ kOsMac,
+#if defined(OS_MACOSX)
+ // The switch exists only on OS X.
+ switches::kEnableExposeForTabs
+#else
+ ""
+#endif
+ },
+ {
+ "vertical-tabs",
+ IDS_LABS_LEFTTABS_NAME,
+ IDS_LABS_LEFTTABS_DESCRIPTION,
+ kOsWin,
+ switches::kEnableVerticalTabs
+ }
+};
+
+// Extracts the list of enabled lab experiments from a profile and stores them
+// in a set.
+void GetEnabledLabs(const PrefService* prefs, std::set<std::string>* result) {
+ const ListValue* enabled_experiments = prefs->GetList(
+ prefs::kEnabledLabsExperiments);
+ if (!enabled_experiments)
+ return;
+
+ for (ListValue::const_iterator it = enabled_experiments->begin();
+ it != enabled_experiments->end();
+ ++it) {
+ std::string experiment_name;
+ if (!(*it)->GetAsString(&experiment_name)) {
+ LOG(WARNING) << "Invalid entry in " << prefs::kEnabledLabsExperiments;
+ continue;
+ }
+ result->insert(experiment_name);
+ }
+}
+
+// Takes a set of enabled lab experiments
+void SetEnabledLabs(
+ PrefService* prefs, const std::set<std::string>& enabled_experiments) {
+ ListValue* experiments_list = prefs->GetMutableList(
+ prefs::kEnabledLabsExperiments);
+ if (!experiments_list)
+ return;
+
+ experiments_list->Clear();
+ for (std::set<std::string>::const_iterator it = enabled_experiments.begin();
+ it != enabled_experiments.end();
+ ++it) {
+ experiments_list->Append(new StringValue(*it));
+ }
+}
+
+// Removes all experiments from prefs::kEnabledLabsExperiments that are
+// unknown, to prevent this list to become very long as experiments are added
+// and removed.
+void SanitizeList(PrefService* prefs) {
+ std::set<std::string> known_experiments;
+ for (size_t i = 0; i < arraysize(kExperiments); ++i)
+ known_experiments.insert(kExperiments[i].internal_name);
+
+ std::set<std::string> enabled_experiments;
+ GetEnabledLabs(prefs, &enabled_experiments);
+
+ std::set<std::string> new_enabled_experiments;
+ std::set_intersection(
+ known_experiments.begin(), known_experiments.end(),
+ enabled_experiments.begin(), enabled_experiments.end(),
+ std::inserter(new_enabled_experiments, new_enabled_experiments.begin()));
+
+ SetEnabledLabs(prefs, new_enabled_experiments);
+}
+
+void GetSanitizedEnabledLabs(
+ PrefService* prefs, std::set<std::string>* result) {
+ SanitizeList(prefs);
+ GetEnabledLabs(prefs, result);
+}
+
+int GetCurrentPlatform() {
+#if defined(OS_MACOSX)
+ return kOsMac;
+#elif defined(OS_WIN)
+ return kOsWin;
+#elif defined(OS_LINUX)
+ return kOsLinux;
+#else
+#error Unknown platform
+#endif
+}
+
+bool IsEnabled() {
+#if defined(OS_CHROMEOS)
+ // ChromeOS uses a different mechanism for about:labs; integrated with their
+ // dom ui options.
+ return false;
+#elif defined(GOOGLE_CHROME_BUILD)
+ // Don't enable this on the stable channel.
+ return platform_util::GetVersionStringModifier() != string16();
+#else
+ return true;
+#endif
+}
+
+void ConvertLabsToSwitches(Profile* profile, CommandLine* command_line) {
+ // Do not activate labs features on the stable channel.
+ if (!IsEnabled())
+ return;
+
+ std::set<std::string> enabled_experiments;
+ GetSanitizedEnabledLabs(profile->GetPrefs(), &enabled_experiments);
+
+ std::map<std::string, const Experiment*> experiments;
+ for (size_t i = 0; i < arraysize(kExperiments); ++i)
+ experiments[kExperiments[i].internal_name] = &kExperiments[i];
+
+ for (std::set<std::string>::iterator it = enabled_experiments.begin();
+ it != enabled_experiments.end();
+ ++it) {
+ const std::string& experiment_name = *it;
+ std::map<std::string, const Experiment*>::iterator experiment =
+ experiments.find(experiment_name);
+ DCHECK(experiment != experiments.end());
+ if (experiment == experiments.end())
+ continue;
+
+ command_line->AppendSwitch(experiment->second->command_line);
+ }
+}
+
+ListValue* GetLabsExperimentsData(Profile* profile) {
+ std::set<std::string> enabled_experiments;
+ GetSanitizedEnabledLabs(profile->GetPrefs(), &enabled_experiments);
+
+ int current_platform = GetCurrentPlatform();
+
+ ListValue* experiments_data = new ListValue();
+ for (size_t i = 0; i < arraysize(kExperiments); ++i) {
+ const Experiment& experiment = kExperiments[i];
+ if (!(experiment.supported_platforms & current_platform))
+ continue;
+
+ DictionaryValue* data = new DictionaryValue();
+ data->SetString("internal_name", experiment.internal_name);
+ data->SetString("name",
+ l10n_util::GetStringUTF16(experiment.visible_name_id));
+ data->SetString("description",
+ l10n_util::GetStringUTF16(
+ experiment.visible_description_id));
+ data->SetBoolean("enabled",
+ enabled_experiments.count(experiment.internal_name) > 0);
+
+ experiments_data->Append(data);
+ }
+ return experiments_data;
+}
+
+static bool needs_restart_ = false;
+
+bool IsRestartNeededToCommitChanges() {
+ return needs_restart_;
+}
+
+void SetExperimentEnabled(
+ Profile* profile, const std::string& internal_name, bool enable) {
+ needs_restart_ = true;
+
+ std::set<std::string> enabled_experiments;
+ GetSanitizedEnabledLabs(profile->GetPrefs(), &enabled_experiments);
+
+ if (enable)
+ enabled_experiments.insert(internal_name);
+ else
+ enabled_experiments.erase(internal_name);
+
+ SetEnabledLabs(profile->GetPrefs(), enabled_experiments);
+}
+
+} // namespace Labs
« 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