summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-12 07:08:07 +0000
committermad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-12 07:08:07 +0000
commit2d4729587b4377874e12be4c578333f02f0cba4b (patch)
tree457c4cb66b23eb7b7ff2eef50decd77b479d3b62
parentc263bc8d3aae4595f1351a70c80142438e017e26 (diff)
downloadchromium_src-2d4729587b4377874e12be4c578333f02f0cba4b.zip
chromium_src-2d4729587b4377874e12be4c578333f02f0cba4b.tar.gz
chromium_src-2d4729587b4377874e12be4c578333f02f0cba4b.tar.bz2
Field Trials choices can now be forced from a command line argument, and yet still behave as if a coin was tossed, except the coin is tricked :-).
To do this, we needed to change the usage from a regular constructor (which is not private) to a static CreateInstance method (which is why there is a bunch of TBR'd owners, those changes were trivial to existing users of FieldTrials). OWNERs of trivially changed files: TBR=sky,jamesr,cpu,joi, BUG=119726 TEST=base_unittests.exe --gtest_filter=FieldTrialTest.* You can also find an active field trial name and force it to a given group by passing the following command line argument "--force-fieldtest=<trial_name>/<default_group_name>/<group_name>/" Review URL: http://codereview.chromium.org/9705074 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131948 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/metrics/field_trial.cc129
-rw-r--r--base/metrics/field_trial.h124
-rw-r--r--base/metrics/field_trial_unittest.cc153
-rw-r--r--chrome/browser/autocomplete/autocomplete_field_trial.cc18
-rw-r--r--chrome/browser/chrome_browser_main.cc97
-rw-r--r--chrome/browser/component_updater/pepper_flash_field_trial.cc8
-rw-r--r--chrome/browser/instant/instant_field_trial.cc7
-rw-r--r--chrome/browser/net/http_pipelining_compatibility_client.cc4
-rw-r--r--chrome/browser/net/network_stats.cc5
-rw-r--r--chrome/browser/prerender/prerender_field_trial.cc55
-rw-r--r--chrome/browser/ui/webui/ntp/new_tab_ui.cc4
-rw-r--r--chrome_frame/chrome_frame_automation.cc6
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc2
-rw-r--r--content/public/common/content_switches.cc16
-rw-r--r--content/public/common/content_switches.h2
-rw-r--r--content/renderer/renderer_main.cc6
16 files changed, 400 insertions, 236 deletions
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index b211326..28886f0 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -43,11 +43,11 @@ FieldTrial::FieldTrial(const std::string& name,
next_group_number_(kDefaultGroupNumber + 1),
group_(kNotFinalized),
group_name_hash_(kReservedHashValue),
- enable_field_trial_(true) {
+ enable_field_trial_(true),
+ forced_(false) {
DCHECK_GT(total_probability, 0);
DCHECK(!name_.empty());
DCHECK(!default_group_name_.empty());
- FieldTrialList::Register(this);
DCHECK_GT(year, 1970);
DCHECK_GT(month, 0);
@@ -71,6 +71,9 @@ FieldTrial::FieldTrial(const std::string& name,
}
void FieldTrial::UseOneTimeRandomization() {
+ // No need to specify randomization when the group choice was forced.
+ if (forced_)
+ return;
DCHECK_EQ(group_, kNotFinalized);
DCHECK_EQ(kDefaultGroupNumber + 1, next_group_number_);
if (!FieldTrialList::IsOneTimeRandomizationEnabled()) {
@@ -89,14 +92,29 @@ void FieldTrial::Disable() {
// In case we are disabled after initialization, we need to switch
// the trial to the default group.
if (group_ != kNotFinalized) {
- group_ = kDefaultGroupNumber;
- group_name_ = default_group_name_;
- group_name_hash_ = HashName(group_name_);
+ // Only reset when not already the default group, because in case we were
+ // forced to the default group, the group number may not be
+ // kDefaultGroupNumber, so we should keep it as is.
+ if (group_name_ != default_group_name_)
+ SetGroupChoice(default_group_name_, kDefaultGroupNumber);
}
}
int FieldTrial::AppendGroup(const std::string& name,
Probability group_probability) {
+ // When the group choice was previously forced, we only need to return the
+ // the id of the chosen group, and anything can be returned for the others.
+ if (forced_) {
+ DCHECK(!group_name_.empty());
+ if (name == group_name_) {
+ return group_;
+ }
+ DCHECK_NE(next_group_number_, group_);
+ // We still return different numbers each time, in case some caller need
+ // them to be different.
+ return next_group_number_++;
+ }
+
DCHECK_LE(group_probability, divisor_);
DCHECK_GE(group_probability, 0);
@@ -108,12 +126,7 @@ int FieldTrial::AppendGroup(const std::string& name,
DCHECK_LE(accumulated_group_probability_, divisor_);
if (group_ == kNotFinalized && accumulated_group_probability_ > random_) {
// This is the group that crossed the random line, so we do the assignment.
- group_ = next_group_number_;
- if (name.empty())
- StringAppendF(&group_name_, "%d", group_);
- else
- group_name_ = name;
- group_name_hash_ = HashName(group_name_);
+ SetGroupChoice(name, next_group_number_);
FieldTrialList::NotifyFieldTrialGroupSelection(name_, group_name_);
}
return next_group_number_++;
@@ -122,9 +135,10 @@ int FieldTrial::AppendGroup(const std::string& name,
int FieldTrial::group() {
if (group_ == kNotFinalized) {
accumulated_group_probability_ = divisor_;
- group_ = kDefaultGroupNumber;
- group_name_ = default_group_name_;
- group_name_hash_ = HashName(group_name_);
+ // Here it's OK to use kDefaultGroupNumber
+ // since we can't be forced and not finalized.
+ DCHECK(!forced_);
+ SetGroupChoice(default_group_name_, kDefaultGroupNumber);
FieldTrialList::NotifyFieldTrialGroupSelection(name_, group_name_);
}
return group_;
@@ -160,6 +174,15 @@ void FieldTrial::EnableBenchmarking() {
FieldTrial::~FieldTrial() {}
+void FieldTrial::SetGroupChoice(const std::string& name, int number) {
+ group_ = number;
+ if (name.empty())
+ StringAppendF(&group_name_, "%d", group_);
+ else
+ group_name_ = name;
+ group_name_hash_ = HashName(group_name_);
+}
+
// static
double FieldTrial::HashClientId(const std::string& client_id,
const std::string& trial_name) {
@@ -234,15 +257,33 @@ FieldTrialList::~FieldTrialList() {
}
// static
-void FieldTrialList::Register(FieldTrial* trial) {
- if (!global_) {
- used_without_global_ = true;
- return;
+FieldTrial* FieldTrialList::FactoryGetFieldTrial(
+ const std::string& name,
+ FieldTrial::Probability total_probability,
+ const std::string& default_group_name,
+ const int year,
+ const int month,
+ const int day_of_month,
+ int* default_group_number) {
+ if (default_group_number)
+ *default_group_number = FieldTrial::kDefaultGroupNumber;
+ // Check if the field trial has already been created in some other way.
+ FieldTrial* existing_trial = Find(name);
+ if (existing_trial) {
+ CHECK(existing_trial->forced_);
+ // If the field trial has already been forced, check whether it was forced
+ // to the default group. Return the chosen group number, in that case..
+ if (default_group_number &&
+ default_group_name == existing_trial->default_group_name()) {
+ *default_group_number = existing_trial->group();
+ }
+ return existing_trial;
}
- AutoLock auto_lock(global_->lock_);
- DCHECK(!global_->PreLockedFind(trial->name()));
- trial->AddRef();
- global_->registered_[trial->name()] = trial;
+
+ FieldTrial* field_trial = new FieldTrial(
+ name, total_probability, default_group_name, year, month, day_of_month);
+ FieldTrialList::Register(field_trial);
+ return field_trial;
}
// static
@@ -283,7 +324,7 @@ void FieldTrialList::StatesToString(std::string* output) {
for (RegistrationList::iterator it = global_->registered_.begin();
it != global_->registered_.end(); ++it) {
- const std::string name = it->first;
+ const std::string& name = it->first;
std::string group_name = it->second->group_name_internal();
if (group_name.empty())
continue; // Should not include uninitialized trials.
@@ -313,23 +354,22 @@ void FieldTrialList::GetFieldTrialNameGroupIds(
}
// static
-bool FieldTrialList::CreateTrialsInChildProcess(
- const std::string& parent_trials) {
+bool FieldTrialList::CreateTrialsFromString(const std::string& trials_string) {
DCHECK(global_);
- if (parent_trials.empty() || !global_)
+ if (trials_string.empty() || !global_)
return true;
size_t next_item = 0;
- while (next_item < parent_trials.length()) {
- size_t name_end = parent_trials.find(kPersistentStringSeparator, next_item);
- if (name_end == parent_trials.npos || next_item == name_end)
+ while (next_item < trials_string.length()) {
+ size_t name_end = trials_string.find(kPersistentStringSeparator, next_item);
+ if (name_end == trials_string.npos || next_item == name_end)
return false;
- size_t group_name_end = parent_trials.find(kPersistentStringSeparator,
+ size_t group_name_end = trials_string.find(kPersistentStringSeparator,
name_end + 1);
- if (group_name_end == parent_trials.npos || name_end + 1 == group_name_end)
+ if (group_name_end == trials_string.npos || name_end + 1 == group_name_end)
return false;
- std::string name(parent_trials, next_item, name_end - next_item);
- std::string group_name(parent_trials, name_end + 1,
+ std::string name(trials_string, next_item, name_end - next_item);
+ std::string group_name(trials_string, name_end + 1,
group_name_end - name_end - 1);
next_item = group_name_end + 1;
@@ -349,9 +389,10 @@ FieldTrial* FieldTrialList::CreateFieldTrial(
if (name.empty() || group_name.empty() || !global_)
return NULL;
- FieldTrial *field_trial(FieldTrialList::Find(name));
+ FieldTrial* field_trial = FieldTrialList::Find(name);
if (field_trial) {
- // In single process mode, we may have already created the field trial.
+ // In single process mode, or when we force them from the command line,
+ // we may have already created the field trial.
if (field_trial->group_name_internal() != group_name)
return NULL;
return field_trial;
@@ -359,7 +400,11 @@ FieldTrial* FieldTrialList::CreateFieldTrial(
const int kTotalProbability = 100;
field_trial = new FieldTrial(name, kTotalProbability, group_name,
kExpirationYearInFuture, 1, 1);
+ // This is where we may assign a group number different from
+ // kDefaultGroupNumber to the default group.
field_trial->AppendGroup(group_name, kTotalProbability);
+ field_trial->forced_ = true;
+ FieldTrialList::Register(field_trial);
return field_trial;
}
@@ -425,4 +470,16 @@ FieldTrial* FieldTrialList::PreLockedFind(const std::string& name) {
return it->second;
}
+// static
+void FieldTrialList::Register(FieldTrial* trial) {
+ if (!global_) {
+ used_without_global_ = true;
+ return;
+ }
+ AutoLock auto_lock(global_->lock_);
+ DCHECK(!global_->PreLockedFind(trial->name()));
+ trial->AddRef();
+ global_->registered_[trial->name()] = trial;
+}
+
} // namespace base
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h
index 50508d2..2852393 100644
--- a/base/metrics/field_trial.h
+++ b/base/metrics/field_trial.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -103,26 +103,6 @@ class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
// assignment (and hence is not yet participating in the trial).
static const int kNotFinalized;
- // This is the group number of the 'default' group. This provides an easy way
- // to assign all the remaining probability to a group ('default').
- static const int kDefaultGroupNumber;
-
- // The name is used to register the instance with the FieldTrialList class,
- // and can be used to find the trial (only one trial can be present for each
- // name). |name| and |default_group_name| may not be empty.
- //
- // Group probabilities that are later supplied must sum to less than or equal
- // to the total_probability. Arguments year, month and day_of_month specify
- // the expiration time. If the build time is after the expiration time then
- // the field trial reverts to the 'default' group.
- //
- // Using this constructor creates a startup-randomized FieldTrial. If you
- // want a one-time randomized trial, call UseOneTimeRandomization() right
- // after construction.
- FieldTrial(const std::string& name, Probability total_probability,
- const std::string& default_group_name, const int year,
- const int month, const int day_of_month);
-
// Changes the field trial to use one-time randomization, i.e. produce the
// same result for the current trial on every run of this client. Must be
// called right after construction.
@@ -133,6 +113,8 @@ class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
// at any time after initialization (should not be interleaved with
// AppendGroup calls). Once disabled, there is no way to re-enable a
// trial.
+ // TODO(mad): http://code.google.com/p/chromium/issues/detail?id=121446
+ // This doesn't properly reset to Default when a group was forced.
void Disable();
// Establish the name and probability of the next group in this trial.
@@ -145,24 +127,20 @@ class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
std::string name() const { return name_; }
// Return the randomly selected group number that was assigned.
- // Return kDefaultGroupNumber if the instance is in the 'default' group.
// Note that this will force an instance to participate, and make it illegal
// to attempt to probabilistically add any other groups to the trial.
int group();
- // If the group's name is empty, a string version containing the group
- // number is used as the group name.
+ // If the group's name is empty, a string version containing the group number
+ // is used as the group name. This causes a winner to be chosen if none was.
std::string group_name();
// Gets the unique identifier of the Field Trial, but only if a group was
// officially chosen, otherwise name_group_id is left untouched and false
- // is returned. When true is returned, the name and group ids were successfuly
- // set in name_group_id.
+ // is returned. When true is returned, the name and group ids were
+ // successfully set in name_group_id.
bool GetNameGroupId(NameGroupId* name_group_id);
- // Return the default group name of the FieldTrial.
- std::string default_group_name() const { return default_group_name_; }
-
// Helper function for the most common use: as an argument to specify the
// name of a HISTOGRAM. Use the original histogram name as the name_prefix.
static std::string MakeName(const std::string& name_prefix,
@@ -193,8 +171,22 @@ class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
friend class RefCounted<FieldTrial>;
+ // This is the group number of the 'default' group when a choice wasn't forced
+ // by a call to FieldTrialList::CreateFieldTrial. It is kept private so that
+ // consumers don't use it by mistake in cases where the group was forced.
+ static const int kDefaultGroupNumber;
+
+ FieldTrial(const std::string& name, Probability total_probability,
+ const std::string& default_group_name, const int year,
+ const int month, const int day_of_month);
virtual ~FieldTrial();
+ // Return the default group name of the FieldTrial.
+ std::string default_group_name() const { return default_group_name_; }
+
+ // Sets the group_name as well as group_name_hash to make sure they are sync.
+ void SetGroupChoice(const std::string& name, int number);
+
// Returns the group_name. A winner need not have been chosen.
std::string group_name_internal() const { return group_name_; }
@@ -247,6 +239,10 @@ class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
// group.
bool enable_field_trial_;
+ // When forced_ is true, we return the chosen group from AppendGroup when
+ // appropriate.
+ bool forced_;
+
// When benchmarking is enabled, field trials all revert to the 'default'
// group.
static bool enable_benchmarking_;
@@ -263,7 +259,7 @@ class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
// Only one instance of this class exists.
class BASE_EXPORT FieldTrialList {
public:
- // Define a separator charactor to use when creating a persistent form of an
+ // Define a separator character to use when creating a persistent form of an
// instance. This is intended for use as a command line argument, passed to a
// second process to mimic our state (i.e., provide the same group name).
static const char kPersistentStringSeparator; // Currently a slash.
@@ -292,9 +288,33 @@ class BASE_EXPORT FieldTrialList {
// Destructor Release()'s references to all registered FieldTrial instances.
~FieldTrialList();
- // Register() stores a pointer to the given trial in a global map.
- // This method also AddRef's the indicated trial.
- static void Register(FieldTrial* trial);
+ // Get a FieldTrial instance from the factory.
+ //
+ // |name| is used to register the instance with the FieldTrialList class,
+ // and can be used to find the trial (only one trial can be present for each
+ // name). |default_group_name| is the name of the default group which will
+ // be chosen if none of the subsequent appended groups get to be chosen.
+ // |default_group_number| can receive the group number of the default group as
+ // AppendGroup returns the number of the subsequence groups. |name| and
+ // |default_group_name| may not be empty but |default_group_number| can be
+ // NULL if the value is not needed.
+ //
+ // Group probabilities that are later supplied must sum to less than or equal
+ // to the |total_probability|. Arguments |year|, |month| and |day_of_month|
+ // specify the expiration time. If the build time is after the expiration time
+ // then the field trial reverts to the 'default' group.
+ //
+ // Use this static method to get a startup-randomized FieldTrial or a
+ // previously created forced FieldTrial. If you want a one-time randomized
+ // trial, call UseOneTimeRandomization() right after creation.
+ static FieldTrial* FactoryGetFieldTrial(
+ const std::string& name,
+ FieldTrial::Probability total_probability,
+ const std::string& default_group_name,
+ const int year,
+ const int month,
+ const int day_of_month,
+ int* default_group_number);
// The Find() method can be used to test to see if a named Trial was already
// registered, or to retrieve a pointer to it from the global map.
@@ -311,11 +331,12 @@ class BASE_EXPORT FieldTrialList {
// Returns true if the named trial has been registered.
static bool TrialExists(const std::string& name);
- // Create a persistent representation of all FieldTrial instances and the
- // |client_id()| state for resurrection in another process. This allows
- // randomization to be done in one process, and secondary processes can be
- // synchronized on the result. The resulting string contains the
- // |client_id()|, the names, the trial name, and a "/" separator.
+ // Creates a persistent representation of all FieldTrial instances for
+ // resurrection in another process. This allows randomization to be done in
+ // one process, and secondary processes can be synchronized on the result.
+ // The resulting string contains the name and group name pairs for all trials,
+ // with "/" used to separate all names and to terminate the string. This
+ // string is parsed by CreateTrialsFromString().
static void StatesToString(std::string* output);
// Returns an array of Unique IDs for each Field Trial that has a chosen
@@ -324,24 +345,20 @@ class BASE_EXPORT FieldTrialList {
static void GetFieldTrialNameGroupIds(
std::vector<FieldTrial::NameGroupId>* name_group_ids);
- // Use a previously generated state string (re: StatesToString()) augment the
- // current list of field tests to include the supplied tests, and using a 100%
- // probability for each test, force them to have the same group string. This
- // is commonly used in a non-browser process, to carry randomly selected state
- // in a browser process into this non-browser process. This method calls
- // CreateFieldTrial to create the FieldTrial in the non-browser process.
- // Currently only the group_name_ and name_ are restored, as well as the
- // |client_id()| state, that could be used for one-time randomized trials
- // set up only in child processes.
- static bool CreateTrialsInChildProcess(const std::string& prior_trials);
+ // Use a state string (re: StatesToString()) to augment the current list of
+ // field tests to include the supplied tests, and using a 100% probability for
+ // each test, force them to have the same group string. This is commonly used
+ // in a non-browser process, to carry randomly selected state in a browser
+ // process into this non-browser process, but could also be invoked through a
+ // command line argument to the browser process.
+ static bool CreateTrialsFromString(const std::string& prior_trials);
// Create a FieldTrial with the given |name| and using 100% probability for
// the FieldTrial, force FieldTrial to have the same group string as
// |group_name|. This is commonly used in a non-browser process, to carry
// randomly selected state in a browser process into this non-browser process.
- // Currently only the group_name_ and name_ are set in the FieldTrial. It
- // returns NULL if there is a FieldTrial that is already registered with the
- // same |name| but has different finalized group string (|group_name|).
+ // It returns NULL if there is a FieldTrial that is already registered with
+ // the same |name| but has different finalized group string (|group_name|).
static FieldTrial* CreateFieldTrial(const std::string& name,
const std::string& group_name);
@@ -390,6 +407,11 @@ class BASE_EXPORT FieldTrialList {
// Helper function should be called only while holding lock_.
FieldTrial* PreLockedFind(const std::string& name);
+ // Register() stores a pointer to the given trial in a global map.
+ // This method also AddRef's the indicated trial.
+ // This should always be called after creating a new FieldTrial instance.
+ static void Register(FieldTrial* trial);
+
static FieldTrialList* global_; // The singleton of this class.
// This will tell us if there is an attempt to register a field
diff --git a/base/metrics/field_trial_unittest.cc b/base/metrics/field_trial_unittest.cc
index 7dc70ec3..9c50fc5 100644
--- a/base/metrics/field_trial_unittest.cc
+++ b/base/metrics/field_trial_unittest.cc
@@ -47,8 +47,8 @@ TEST_F(FieldTrialTest, Registration) {
EXPECT_FALSE(FieldTrialList::Find(name1));
EXPECT_FALSE(FieldTrialList::Find(name2));
- FieldTrial* trial1 =
- new FieldTrial(name1, 10, "default name 1 test", next_year_, 12, 31);
+ FieldTrial* trial1 = FieldTrialList::FactoryGetFieldTrial(
+ name1, 10, "default name 1 test", next_year_, 12, 31, NULL);
EXPECT_EQ(FieldTrial::kNotFinalized, trial1->group_);
EXPECT_EQ(name1, trial1->name());
EXPECT_EQ("", trial1->group_name_internal());
@@ -58,8 +58,8 @@ TEST_F(FieldTrialTest, Registration) {
EXPECT_EQ(trial1, FieldTrialList::Find(name1));
EXPECT_FALSE(FieldTrialList::Find(name2));
- FieldTrial* trial2 =
- new FieldTrial(name2, 10, "default name 2 test", next_year_, 12, 31);
+ FieldTrial* trial2 = FieldTrialList::FactoryGetFieldTrial(
+ name2, 10, "default name 2 test", next_year_, 12, 31, NULL);
EXPECT_EQ(FieldTrial::kNotFinalized, trial2->group_);
EXPECT_EQ(name2, trial2->name());
EXPECT_EQ("", trial2->group_name_internal());
@@ -83,18 +83,16 @@ TEST_F(FieldTrialTest, AbsoluteProbabilities) {
always_false[0] = i;
default_always_false[0] = i;
- FieldTrial* trial_true =
- new FieldTrial(
- always_true, 10, default_always_true, next_year_, 12, 31);
+ FieldTrial* trial_true = FieldTrialList::FactoryGetFieldTrial(
+ always_true, 10, default_always_true, next_year_, 12, 31, NULL);
const std::string winner = "TheWinner";
int winner_group = trial_true->AppendGroup(winner, 10);
EXPECT_EQ(winner_group, trial_true->group());
EXPECT_EQ(winner, trial_true->group_name());
- FieldTrial* trial_false =
- new FieldTrial(
- always_false, 10, default_always_false, next_year_, 12, 31);
+ FieldTrial* trial_false = FieldTrialList::FactoryGetFieldTrial(
+ always_false, 10, default_always_false, next_year_, 12, 31, NULL);
int loser_group = trial_false->AppendGroup("ALoser", 0);
EXPECT_NE(loser_group, trial_false->group());
@@ -107,15 +105,17 @@ TEST_F(FieldTrialTest, RemainingProbability) {
const std::string loser = "Loser";
scoped_refptr<FieldTrial> trial;
int counter = 0;
+ int default_group_number = -1;
do {
std::string name = StringPrintf("trial%d", ++counter);
- trial = new FieldTrial(name, 10, winner, next_year_, 12, 31);
+ trial = FieldTrialList::FactoryGetFieldTrial(
+ name, 10, winner, next_year_, 12, 31, &default_group_number);
trial->AppendGroup(loser, 5); // 50% chance of not being chosen.
// If a group is not assigned, group_ will be kNotFinalized.
} while (trial->group_ != FieldTrial::kNotFinalized);
// And that 'default' group (winner) should always win.
- EXPECT_EQ(FieldTrial::kDefaultGroupNumber, trial->group());
+ EXPECT_EQ(default_group_number, trial->group());
// And that winner should ALWAYS win.
EXPECT_EQ(winner, trial->group_name());
@@ -133,8 +133,8 @@ TEST_F(FieldTrialTest, FiftyFiftyProbability) {
std::string name = base::StringPrintf("FiftyFifty%d", ++counter);
std::string default_group_name = base::StringPrintf("Default FiftyFifty%d",
++counter);
- scoped_refptr<FieldTrial> trial(
- new FieldTrial(name, 2, default_group_name, next_year_, 12, 31));
+ scoped_refptr<FieldTrial> trial(FieldTrialList::FactoryGetFieldTrial(
+ name, 2, default_group_name, next_year_, 12, 31, NULL));
trial->AppendGroup("first", 1); // 50% chance of being chosen.
// If group_ is kNotFinalized, then a group assignement hasn't been done.
if (trial->group_ != FieldTrial::kNotFinalized) {
@@ -157,8 +157,8 @@ TEST_F(FieldTrialTest, MiddleProbabilities) {
for (int i = 1; i < 250; ++i) {
name[0] = i;
default_group_name[0] = i;
- FieldTrial* trial =
- new FieldTrial(name, 10, default_group_name, next_year_, 12, 31);
+ FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
+ name, 10, default_group_name, next_year_, 12, 31, NULL);
int might_win = trial->AppendGroup("MightWin", 5);
if (trial->group() == might_win) {
@@ -180,9 +180,10 @@ TEST_F(FieldTrialTest, OneWinner) {
char default_group_name[] = "Default some name";
int group_count(10);
- FieldTrial* trial =
- new FieldTrial(
- name, group_count, default_group_name, next_year_, 12, 31);
+ int default_group_number = -1;
+ FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
+ name, group_count, default_group_name, next_year_, 12, 31,
+ &default_group_number);
int winner_index(-2);
std::string winner_name;
@@ -199,6 +200,9 @@ TEST_F(FieldTrialTest, OneWinner) {
}
}
EXPECT_GE(winner_index, 0);
+ // Since all groups cover the total probability, we should not have
+ // chosen the default group.
+ EXPECT_NE(trial->group(), default_group_number);
EXPECT_EQ(trial->group(), winner_index);
EXPECT_EQ(trial->group_name(), winner_name);
}
@@ -209,13 +213,15 @@ TEST_F(FieldTrialTest, DisableProbability) {
const std::string name = "Trial";
// Create a field trail that has expired.
+ int default_group_number = -1;
scoped_refptr<FieldTrial> trial;
- trial = new FieldTrial(
- name, 1000000000, default_group_name, last_year_, 1, 1);
+ trial = FieldTrialList::FactoryGetFieldTrial(
+ name, 1000000000, default_group_name, last_year_, 1, 1,
+ &default_group_number);
trial->AppendGroup(loser, 999999999); // 99.9999999% chance of being chosen.
// Because trial has expired, we should always be in the default group.
- EXPECT_EQ(FieldTrial::kDefaultGroupNumber, trial->group());
+ EXPECT_EQ(default_group_number, trial->group());
// And that default_group_name should ALWAYS win.
EXPECT_EQ(default_group_name, trial->group_name());
@@ -245,8 +251,8 @@ TEST_F(FieldTrialTest, HashName) {
TEST_F(FieldTrialTest, NameGroupIds) {
std::string no_group("No Group");
uint32 no_group_id = FieldTrial::HashName(no_group);
- scoped_refptr<FieldTrial> trial(new FieldTrial(
- no_group, 10, "Default", next_year_, 12, 31));
+ scoped_refptr<FieldTrial> trial(FieldTrialList::FactoryGetFieldTrial(
+ no_group, 10, "Default", next_year_, 12, 31, NULL));
// There is no winner yet, so no NameGroupId should be returned.
FieldTrial::NameGroupId name_group_id;
@@ -255,7 +261,8 @@ TEST_F(FieldTrialTest, NameGroupIds) {
// Create a single winning group.
std::string one_winner("One Winner");
uint32 one_winner_id = FieldTrial::HashName(one_winner);
- trial = new FieldTrial(one_winner, 10, "Default", next_year_, 12, 31);
+ trial = FieldTrialList::FactoryGetFieldTrial(
+ one_winner, 10, "Default", next_year_, 12, 31, NULL);
std::string winner("Winner");
uint32 winner_group_id = FieldTrial::HashName(winner);
trial->AppendGroup(winner, 10);
@@ -266,7 +273,8 @@ TEST_F(FieldTrialTest, NameGroupIds) {
std::string multi_group("MultiGroup");
uint32 multi_group_id = FieldTrial::HashName(multi_group);
scoped_refptr<FieldTrial> multi_group_trial =
- new FieldTrial(multi_group, 9, "Default", next_year_, 12, 31);
+ FieldTrialList::FactoryGetFieldTrial(multi_group, 9, "Default",
+ next_year_, 12, 31, NULL);
multi_group_trial->AppendGroup("Me", 3);
multi_group_trial->AppendGroup("You", 3);
@@ -294,9 +302,8 @@ TEST_F(FieldTrialTest, NameGroupIds) {
TEST_F(FieldTrialTest, Save) {
std::string save_string;
- FieldTrial* trial =
- new FieldTrial(
- "Some name", 10, "Default some name", next_year_, 12, 31);
+ FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
+ "Some name", 10, "Default some name", next_year_, 12, 31, NULL);
// There is no winner yet, so no textual group name is associated with trial.
// In this case, the trial should not be included.
EXPECT_EQ("", trial->group_name_internal());
@@ -311,8 +318,8 @@ TEST_F(FieldTrialTest, Save) {
save_string.clear();
// Create a second trial and winning group.
- FieldTrial* trial2 =
- new FieldTrial("xxx", 10, "Default xxx", next_year_, 12, 31);
+ FieldTrial* trial2 = FieldTrialList::FactoryGetFieldTrial(
+ "xxx", 10, "Default xxx", next_year_, 12, 31, NULL);
trial2->AppendGroup("yyyy", 10);
FieldTrialList::StatesToString(&save_string);
@@ -324,7 +331,7 @@ TEST_F(FieldTrialTest, Restore) {
EXPECT_TRUE(FieldTrialList::Find("Some_name") == NULL);
EXPECT_TRUE(FieldTrialList::Find("xxx") == NULL);
- FieldTrialList::CreateTrialsInChildProcess("Some_name/Winner/xxx/yyyy/");
+ FieldTrialList::CreateTrialsFromString("Some_name/Winner/xxx/yyyy/");
FieldTrial* trial = FieldTrialList::Find("Some_name");
ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
@@ -338,29 +345,27 @@ TEST_F(FieldTrialTest, Restore) {
}
TEST_F(FieldTrialTest, BogusRestore) {
- EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess("MissingSlash"));
- EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess("MissingGroupName/"));
- EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess(
+ EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingSlash"));
+ EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingGroupName/"));
+ EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
"MissingFinalSlash/gname"));
- EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess(
+ EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
"noname, only group/"));
}
TEST_F(FieldTrialTest, DuplicateRestore) {
- FieldTrial* trial =
- new FieldTrial(
- "Some name", 10, "Default some name", next_year_, 12, 31);
+ FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
+ "Some name", 10, "Default some name", next_year_, 12, 31, NULL);
trial->AppendGroup("Winner", 10);
std::string save_string;
FieldTrialList::StatesToString(&save_string);
EXPECT_EQ("Some name/Winner/", save_string);
// It is OK if we redundantly specify a winner.
- EXPECT_TRUE(FieldTrialList::CreateTrialsInChildProcess(save_string));
+ EXPECT_TRUE(FieldTrialList::CreateTrialsFromString(save_string));
// But it is an error to try to change to a different winner.
- EXPECT_FALSE(FieldTrialList::CreateTrialsInChildProcess(
- "Some name/Loser/"));
+ EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("Some name/Loser/"));
}
TEST_F(FieldTrialTest, CreateFieldTrial) {
@@ -375,9 +380,8 @@ TEST_F(FieldTrialTest, CreateFieldTrial) {
}
TEST_F(FieldTrialTest, DuplicateFieldTrial) {
- FieldTrial* trial =
- new FieldTrial(
- "Some_name", 10, "Default some name", next_year_, 12, 31);
+ FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
+ "Some_name", 10, "Default some name", next_year_, 12, 31, NULL);
trial->AppendGroup("Winner", 10);
// It is OK if we redundantly specify a winner.
@@ -390,8 +394,8 @@ TEST_F(FieldTrialTest, DuplicateFieldTrial) {
}
TEST_F(FieldTrialTest, MakeName) {
- FieldTrial* trial =
- new FieldTrial("Field Trial", 10, "Winner", next_year_, 12, 31);
+ FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
+ "Field Trial", 10, "Winner", next_year_, 12, 31, NULL);
trial->group();
EXPECT_EQ("Histogram_Winner",
FieldTrial::MakeName("Histogram", "Field Trial"));
@@ -467,8 +471,10 @@ TEST_F(FieldTrialTest, UseOneTimeRandomization) {
// _might_ actually give the same result, but we know that given
// the particular client_id we use for unit tests they won't.
scoped_refptr<FieldTrial> trials[] = {
- new FieldTrial("one", 100, "default", next_year_, 1, 1),
- new FieldTrial("two", 100, "default", next_year_, 1, 1),
+ FieldTrialList::FactoryGetFieldTrial("one", 100, "default",
+ next_year_, 1, 1, NULL),
+ FieldTrialList::FactoryGetFieldTrial("two", 100, "default",
+ next_year_, 1, 1, NULL),
};
for (size_t i = 0; i < arraysize(trials); ++i) {
@@ -486,20 +492,61 @@ TEST_F(FieldTrialTest, UseOneTimeRandomization) {
}
TEST_F(FieldTrialTest, DisableImmediately) {
- FieldTrial* trial =
- new FieldTrial("trial", 100, "default", next_year_, 12, 31);
+ int default_group_number = -1;
+ FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
+ "trial", 100, "default", next_year_, 12, 31, &default_group_number);
trial->Disable();
ASSERT_EQ("default", trial->group_name());
- ASSERT_EQ(FieldTrial::kDefaultGroupNumber, trial->group());
+ ASSERT_EQ(default_group_number, trial->group());
}
TEST_F(FieldTrialTest, DisableAfterInitialization) {
FieldTrial* trial =
- new FieldTrial("trial", 100, "default", next_year_, 12, 31);
+ FieldTrialList::FactoryGetFieldTrial("trial", 100, "default",
+ next_year_, 12, 31, NULL);
trial->AppendGroup("non_default", 100);
ASSERT_EQ("non_default", trial->group_name());
trial->Disable();
ASSERT_EQ("default", trial->group_name());
}
+TEST_F(FieldTrialTest, ForcedFieldTrials) {
+ // Validate we keep the forced choice.
+ FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Use the",
+ "Force");
+ EXPECT_STREQ("Force", forced_trial->group_name().c_str());
+
+ int default_group_number = -1;
+ FieldTrial* factory_trial = FieldTrialList::FactoryGetFieldTrial(
+ "Use the", 1000, "default", next_year_, 12, 31, &default_group_number);
+ EXPECT_EQ(factory_trial, forced_trial);
+
+ int chosen_group = factory_trial->AppendGroup("Force", 100);
+ EXPECT_EQ(chosen_group, factory_trial->group());
+ int not_chosen_group = factory_trial->AppendGroup("Dark Side", 100);
+ EXPECT_NE(chosen_group, not_chosen_group);
+
+ // Since we didn't force the default group, we should not be returned the
+ // chosen group as the default group.
+ EXPECT_NE(default_group_number, chosen_group);
+ int new_group = factory_trial->AppendGroup("Duck Tape", 800);
+ EXPECT_NE(chosen_group, new_group);
+ // The new group should not be the default group either.
+ EXPECT_NE(default_group_number, new_group);
+
+ // Forcing the default should use the proper group ID.
+ forced_trial = FieldTrialList::CreateFieldTrial("Trial Name", "Default");
+ factory_trial = FieldTrialList::FactoryGetFieldTrial(
+ "Trial Name", 1000, "Default", next_year_, 12, 31, &default_group_number);
+ EXPECT_EQ(forced_trial, factory_trial);
+
+ int other_group = factory_trial->AppendGroup("Not Default", 100);
+ EXPECT_STREQ("Default", factory_trial->group_name().c_str());
+ EXPECT_EQ(default_group_number, factory_trial->group());
+ EXPECT_NE(other_group, factory_trial->group());
+
+ int new_other_group = factory_trial->AppendGroup("Not Default Either", 800);
+ EXPECT_NE(new_other_group, factory_trial->group());
+}
+
} // namespace base
diff --git a/chrome/browser/autocomplete/autocomplete_field_trial.cc b/chrome/browser/autocomplete/autocomplete_field_trial.cc
index 0b0876a..44ae729 100644
--- a/chrome/browser/autocomplete/autocomplete_field_trial.cc
+++ b/chrome/browser/autocomplete/autocomplete_field_trial.cc
@@ -64,18 +64,19 @@ void AutocompleteFieldTrial::Activate() {
if (base::FieldTrialList::IsOneTimeRandomizationEnabled()) { // sticky trials
// Create aggressive History URL Provider field trial.
// Make it expire on August 1, 2012.
- scoped_refptr<base::FieldTrial> trial(new base::FieldTrial(
- kAggressiveHUPFieldTrialName, kAggressiveHUPFieldTrialDivisor,
- "Standard", 2012, 8, 1));
+ scoped_refptr<base::FieldTrial> trial(
+ base::FieldTrialList::FactoryGetFieldTrial(
+ kAggressiveHUPFieldTrialName, kAggressiveHUPFieldTrialDivisor,
+ "Standard", 2012, 8, 1, NULL));
trial->UseOneTimeRandomization();
aggressive_hup_experiment_group = trial->AppendGroup("Aggressive",
kAggressiveHUPFieldTrialExperimentFraction);
// Create inline History Quick Provider field trial.
// Make it expire on November 8, 2012.
- trial = new base::FieldTrial(
+ trial = base::FieldTrialList::FactoryGetFieldTrial(
kDisallowInlineHQPFieldTrialName, kDisallowInlineHQPFieldTrialDivisor,
- "Standard", 2012, 11, 8);
+ "Standard", 2012, 11, 8, NULL);
trial->UseOneTimeRandomization();
disallow_inline_hqp_experiment_group = trial->AppendGroup("DisallowInline",
kDisallowInlineHQPFieldTrialExperimentFraction);
@@ -84,9 +85,10 @@ void AutocompleteFieldTrial::Activate() {
// Create the suggest field trial (regardless of sticky-ness status, but
// make it sticky if possible).
// Make it expire on October 1, 2012.
- scoped_refptr<base::FieldTrial> trial(new base::FieldTrial(
- kSuggestFieldTrialName, kSuggestFieldTrialNumberOfGroups,
- "0", 2012, 10, 1));
+ scoped_refptr<base::FieldTrial> trial(
+ base::FieldTrialList::FactoryGetFieldTrial(
+ kSuggestFieldTrialName, kSuggestFieldTrialNumberOfGroups,
+ "0", 2012, 10, 1, NULL));
if (base::FieldTrialList::IsOneTimeRandomizationEnabled())
trial->UseOneTimeRandomization();
// We've already created one group; now just need to create
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 185baac..5dbf897 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -588,6 +588,19 @@ void ChromeBrowserMainParts::SetupMetricsAndFieldTrials() {
metrics->ForceClientIdCreation(); // Needed below.
field_trial_list_.reset(new base::FieldTrialList(metrics->GetClientId()));
+ // Ensure any field trials specified on the command line are initialized.
+ // Also stop the metrics service so that we don't pollute UMA.
+#ifndef NDEBUG
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kForceFieldTrials)) {
+ std::string persistent = command_line->GetSwitchValueASCII(
+ switches::kForceFieldTrials);
+ bool ret = base::FieldTrialList::CreateTrialsFromString(persistent);
+ CHECK(ret) << "Invalid --" << switches::kForceFieldTrials <<
+ " list specified.";
+ }
+#endif // NDEBUG
+
SetupFieldTrials(metrics->recording_active(),
local_state_->IsManagedPreference(
prefs::kMaxConnectionsPerProxy));
@@ -609,16 +622,17 @@ void ChromeBrowserMainParts::ConnectionFieldTrial() {
const base::FieldTrial::Probability kConnectDivisor = 100;
const base::FieldTrial::Probability kConnectProbability = 1; // 1% prob.
- // After June 30, 2011 builds, it will always be in default group.
- scoped_refptr<base::FieldTrial> connect_trial(
- new base::FieldTrial(
- "ConnCountImpact", kConnectDivisor, "conn_count_6", 2011, 6, 30));
-
// This (6) is the current default value. Having this group declared here
// makes it straightforward to modify |kConnectProbability| such that the same
// probability value will be assigned to all the other groups, while
// preserving the remainder of the of probability space to the default value.
- const int connect_6 = connect_trial->kDefaultGroupNumber;
+ int connect_6 = -1;
+
+ // After June 30, 2011 builds, it will always be in default group.
+ scoped_refptr<base::FieldTrial> connect_trial(
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "ConnCountImpact", kConnectDivisor, "conn_count_6", 2011, 6, 30,
+ &connect_6));
const int connect_5 = connect_trial->AppendGroup("conn_count_5",
kConnectProbability);
@@ -663,10 +677,11 @@ void ChromeBrowserMainParts::SocketTimeoutFieldTrial() {
const base::FieldTrial::Probability kSocketTimeoutProbability = 1;
// After June 30, 2011 builds, it will always be in default group.
+ int socket_timeout_10 = -1;
scoped_refptr<base::FieldTrial> socket_timeout_trial(
- new base::FieldTrial("IdleSktToImpact", kIdleSocketTimeoutDivisor,
- "idle_timeout_10", 2011, 6, 30));
- const int socket_timeout_10 = socket_timeout_trial->kDefaultGroupNumber;
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "IdleSktToImpact", kIdleSocketTimeoutDivisor, "idle_timeout_10",
+ 2011, 6, 30, &socket_timeout_10));
const int socket_timeout_5 =
socket_timeout_trial->AppendGroup("idle_timeout_5",
@@ -696,16 +711,17 @@ void ChromeBrowserMainParts::ProxyConnectionsFieldTrial() {
// 25% probability
const base::FieldTrial::Probability kProxyConnectionProbability = 1;
- // After June 30, 2011 builds, it will always be in default group.
- scoped_refptr<base::FieldTrial> proxy_connection_trial(
- new base::FieldTrial("ProxyConnectionImpact", kProxyConnectionsDivisor,
- "proxy_connections_32", 2011, 6, 30));
-
// This (32 connections per proxy server) is the current default value.
// Declaring it here allows us to easily re-assign the probability space while
// maintaining that the default group always has the remainder of the "share",
// which allows for cleaner and quicker changes down the line if needed.
- const int proxy_connections_32 = proxy_connection_trial->kDefaultGroupNumber;
+ int proxy_connections_32 = -1;
+
+ // After June 30, 2011 builds, it will always be in default group.
+ scoped_refptr<base::FieldTrial> proxy_connection_trial(
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "ProxyConnectionImpact", kProxyConnectionsDivisor,
+ "proxy_connections_32", 2011, 6, 30, &proxy_connections_32));
// The number of max sockets per group cannot be greater than the max number
// of sockets per proxy server. We tried using 8, and it can easily
@@ -758,13 +774,14 @@ void ChromeBrowserMainParts::SpdyFieldTrial() {
base::FieldTrial::Probability npnhttp_probability = 5;
base::FieldTrial::Probability spdy3_probability = 10;
+ // NPN with spdy support is the default.
+ int npn_spdy_grp = -1;
+
// After June 30, 2013 builds, it will always be in default group.
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial(
- "SpdyImpact", kSpdyDivisor, "npn_with_spdy", 2013, 6, 30));
-
- // NPN with spdy support is the default.
- int npn_spdy_grp = trial->kDefaultGroupNumber;
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "SpdyImpact", kSpdyDivisor, "npn_with_spdy", 2013, 6, 30,
+ &npn_spdy_grp));
// NPN with only http support, no spdy.
int npn_http_grp = trial->AppendGroup("npn_with_http", npnhttp_probability);
@@ -798,8 +815,8 @@ void ChromeBrowserMainParts::SpdyFieldTrial() {
// After June 30, 2013 builds, it will always be in default group
// (cwndDynamic).
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial(
- "SpdyCwnd", kSpdyCwndDivisor, "cwndDynamic", 2013, 6, 30));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "SpdyCwnd", kSpdyCwndDivisor, "cwndDynamic", 2013, 6, 30, NULL));
trial->AppendGroup("cwnd10", kSpdyCwnd10);
trial->AppendGroup("cwnd16", kSpdyCwnd16);
@@ -835,14 +852,15 @@ void ChromeBrowserMainParts::WarmConnectionFieldTrial() {
const base::FieldTrial::Probability kWarmSocketDivisor = 100;
const base::FieldTrial::Probability kWarmSocketProbability = 33;
+ // Default value is USE_LAST_ACCESSED_SOCKET.
+ int last_accessed_socket = -1;
+
// After January 30, 2013 builds, it will always be in default group.
scoped_refptr<base::FieldTrial> warmest_socket_trial(
- new base::FieldTrial(
+ base::FieldTrialList::FactoryGetFieldTrial(
"WarmSocketImpact", kWarmSocketDivisor, "last_accessed_socket",
- 2013, 1, 30));
+ 2013, 1, 30, &last_accessed_socket));
- // Default value is USE_LAST_ACCESSED_SOCKET.
- const int last_accessed_socket = warmest_socket_trial->kDefaultGroupNumber;
const int warmest_socket = warmest_socket_trial->AppendGroup(
"warmest_socket", kWarmSocketProbability);
const int warm_socket = warmest_socket_trial->AppendGroup(
@@ -872,11 +890,11 @@ void ChromeBrowserMainParts::ConnectBackupJobsFieldTrial() {
// 1% probability.
const base::FieldTrial::Probability kConnectBackupJobsProbability = 1;
// After June 30, 2011 builds, it will always be in default group.
+ int connect_backup_jobs_enabled = -1;
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial("ConnnectBackupJobs",
- kConnectBackupJobsDivisor, "ConnectBackupJobsEnabled", 2011, 6,
- 30));
- const int connect_backup_jobs_enabled = trial->kDefaultGroupNumber;
+ base::FieldTrialList::FactoryGetFieldTrial("ConnnectBackupJobs",
+ kConnectBackupJobsDivisor, "ConnectBackupJobsEnabled",
+ 2011, 6, 30, &connect_backup_jobs_enabled));
trial->AppendGroup("ConnectBackupJobsDisabled",
kConnectBackupJobsProbability);
const int trial_group = trial->group();
@@ -894,8 +912,9 @@ void ChromeBrowserMainParts::PredictorFieldTrial() {
// After June 30, 2011 builds, it will always be in default group
// (default_enabled_prefetch).
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial("DnsImpact", kDivisor,
- "default_enabled_prefetch", 2011, 10, 30));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "DnsImpact", kDivisor, "default_enabled_prefetch", 2011, 10, 30,
+ NULL));
// First option is to disable prefetching completely.
int disabled_prefetch = trial->AppendGroup("disabled_prefetch",
@@ -1038,6 +1057,13 @@ bool ChromeBrowserMainParts::IsMetricsReportingEnabled() {
// prefs, we turn on recording. We disable metrics completely for
// non-official builds.
bool enabled = false;
+#ifndef NDEBUG
+ // The debug build doesn't sent UMA logs when FieldTrials are forced.
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kForceFieldTrials))
+ return false;
+#endif // #ifndef NDEBUG
+
#if defined(GOOGLE_CHROME_BUILD)
#if defined(OS_CHROMEOS)
chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
@@ -1608,10 +1634,11 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
base::FieldTrial::Probability kSDCH_DIVISOR = 1000;
base::FieldTrial::Probability kSDCH_DISABLE_PROBABILITY = 1; // 0.1% prob.
// After March 31, 2012 builds, it will always be in default group.
+ int sdch_enabled_group = -1;
scoped_refptr<base::FieldTrial> sdch_trial(
- new base::FieldTrial("GlobalSdch", kSDCH_DIVISOR, "global_enable_sdch",
- 2012, 3, 31));
- int sdch_enabled_group = sdch_trial->kDefaultGroupNumber;
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "GlobalSdch", kSDCH_DIVISOR, "global_enable_sdch", 2012, 3, 31,
+ &sdch_enabled_group));
sdch_trial->AppendGroup("global_disable_sdch",
kSDCH_DISABLE_PROBABILITY);
diff --git a/chrome/browser/component_updater/pepper_flash_field_trial.cc b/chrome/browser/component_updater/pepper_flash_field_trial.cc
index b624a6e..7cea088 100644
--- a/chrome/browser/component_updater/pepper_flash_field_trial.cc
+++ b/chrome/browser/component_updater/pepper_flash_field_trial.cc
@@ -14,12 +14,14 @@ namespace {
const char* const kFieldTrialName = "PepperFlash";
const char* const kDisableGroupName = "DisableByDefault";
const char* const kEnableGroupName = "EnableByDefault";
+int g_disabled_group_number = -1;
void ActivateFieldTrial() {
// The field trial will expire on Jan 1st, 2014.
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial(kFieldTrialName, 1000, kDisableGroupName,
- 2014, 1, 1));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ kFieldTrialName, 1000, kDisableGroupName, 2014, 1, 1,
+ &g_disabled_group_number));
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kPpapiFlashFieldTrial)) {
@@ -55,5 +57,5 @@ bool PepperFlashFieldTrial::InEnableByDefaultGroup() {
int group = base::FieldTrialList::FindValue(kFieldTrialName);
return group != base::FieldTrial::kNotFinalized &&
- group != base::FieldTrial::kDefaultGroupNumber;
+ group != g_disabled_group_number;
}
diff --git a/chrome/browser/instant/instant_field_trial.cc b/chrome/browser/instant/instant_field_trial.cc
index ea696dd..5cb5f1e 100644
--- a/chrome/browser/instant/instant_field_trial.cc
+++ b/chrome/browser/instant/instant_field_trial.cc
@@ -17,6 +17,7 @@ namespace {
// Field trial IDs of the control and experiment groups. Though they are not
// literally "const", they are set only once, in Activate() below. See the .h
// file for what these groups represent.
+int g_inactive = -1;
int g_instant = 0;
int g_suggest = 0;
int g_hidden = 0;
@@ -28,7 +29,8 @@ int g_control = 0;
// static
void InstantFieldTrial::Activate() {
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial("Instant", 1000, "Inactive", 2013, 7, 1));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "Instant", 1000, "Inactive", 2013, 7, 1, &g_inactive));
// Try to give the user a consistent experience, if possible.
if (base::FieldTrialList::IsOneTimeRandomizationEnabled())
@@ -76,8 +78,7 @@ InstantFieldTrial::Group InstantFieldTrial::GetGroup(Profile* profile) {
}
const int group = base::FieldTrialList::FindValue("Instant");
- if (group == base::FieldTrial::kNotFinalized ||
- group == base::FieldTrial::kDefaultGroupNumber) {
+ if (group == base::FieldTrial::kNotFinalized || group == g_inactive) {
UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 2, 10);
return INACTIVE;
}
diff --git a/chrome/browser/net/http_pipelining_compatibility_client.cc b/chrome/browser/net/http_pipelining_compatibility_client.cc
index 9afe7d5..72fc8d3 100644
--- a/chrome/browser/net/http_pipelining_compatibility_client.cc
+++ b/chrome/browser/net/http_pipelining_compatibility_client.cc
@@ -468,8 +468,8 @@ void CollectPipeliningCapabilityStatsOnIOThread(
return;
}
// After April 14, 2012, the trial will disable itself.
- trial = new base::FieldTrial(kTrialName, kDivisor,
- "disable_test", 2012, 4, 14);
+ trial = base::FieldTrialList::FactoryGetFieldTrial(
+ kTrialName, kDivisor, "disable_test", 2012, 4, 14, NULL);
chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
if (channel == chrome::VersionInfo::CHANNEL_CANARY) {
diff --git a/chrome/browser/net/network_stats.cc b/chrome/browser/net/network_stats.cc
index c092968..a22e656 100644
--- a/chrome/browser/net/network_stats.cc
+++ b/chrome/browser/net/network_stats.cc
@@ -653,8 +653,9 @@ void CollectNetworkStats(const std::string& network_stats_server,
// After October 30, 2012 builds, it will always be in default group
// (disable_network_stats).
- trial = new base::FieldTrial("NetworkConnectivity", kDivisor,
- "disable_network_stats", 2012, 10, 30);
+ trial = base::FieldTrialList::FactoryGetFieldTrial(
+ "NetworkConnectivity", kDivisor, "disable_network_stats",
+ 2012, 10, 30, NULL);
// Add option to collect_stats for NetworkConnectivity.
int collect_stats_group = trial->AppendGroup("collect_stats",
diff --git a/chrome/browser/prerender/prerender_field_trial.cc b/chrome/browser/prerender/prerender_field_trial.cc
index 51cfd93..ab43ff2 100644
--- a/chrome/browser/prerender/prerender_field_trial.cc
+++ b/chrome/browser/prerender/prerender_field_trial.cc
@@ -21,6 +21,7 @@ namespace prerender {
namespace {
const char kOmniboxTrialName[] = "PrerenderFromOmnibox";
+int g_omnibox_trial_default_group_number = -1;
void SetupPrefetchFieldTrial() {
chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
@@ -32,8 +33,9 @@ void SetupPrefetchFieldTrial() {
const base::FieldTrial::Probability divisor = 1000;
const base::FieldTrial::Probability prefetch_probability = 500;
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial("Prefetch", divisor,
- "ContentPrefetchPrefetchOff", 2012, 6, 30));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "Prefetch", divisor, "ContentPrefetchPrefetchOff",
+ 2012, 6, 30, NULL));
const int kPrefetchOnGroup = trial->AppendGroup("ContentPrefetchPrefetchOn",
prefetch_probability);
PrerenderManager::SetIsPrefetchEnabled(trial->group() == kPrefetchOnGroup);
@@ -68,47 +70,48 @@ void SetupPrerenderFieldTrial() {
control1_probability + no_use1_probability + exp2_probability +
exp2_5min_ttl_probability + control2_probability +
no_use2_probability);
+ int experiment_1_group = -1;
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial("Prerender", divisor,
- "ContentPrefetchPrerender1", 2012, 6, 30));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "Prerender", divisor, "ContentPrefetchPrerender1",
+ 2012, 6, 30, &experiment_1_group));
- const int kExperiment1Group = trial->kDefaultGroupNumber;
- const int kExperiment15minTTLGroup =
+ const int experiment_15_min_TTL_group =
trial->AppendGroup("ContentPrefetchPrerenderExp5minTTL1",
exp1_5min_ttl_probability);
- const int kControl1Group =
+ const int control_1_group =
trial->AppendGroup("ContentPrefetchPrerenderControl1",
control1_probability);
- const int kNoUse1Group =
+ const int no_use_1_group =
trial->AppendGroup("ContentPrefetchPrerenderNoUse1",
no_use1_probability);
- const int kExperiment2Group =
+ const int experiment_2_group =
trial->AppendGroup("ContentPrefetchPrerender2",
exp2_probability);
- const int kExperiment25minTTLGroup =
+ const int experiment_25_min_TTL_group =
trial->AppendGroup("ContentPrefetchPrerenderExp5minTTL2",
exp2_5min_ttl_probability);
- const int kControl2Group =
+ const int control_2_group =
trial->AppendGroup("ContentPrefetchPrerenderControl2",
control2_probability);
- const int kNoUse2Group =
+ const int no_use_2_group =
trial->AppendGroup("ContentPrefetchPrerenderNoUse2",
no_use2_probability);
const int trial_group = trial->group();
- if (trial_group == kExperiment1Group ||
- trial_group == kExperiment2Group) {
+ if (trial_group == experiment_1_group ||
+ trial_group == experiment_2_group) {
PrerenderManager::SetMode(
PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP);
- } else if (trial_group == kExperiment15minTTLGroup ||
- trial_group == kExperiment25minTTLGroup) {
+ } else if (trial_group == experiment_15_min_TTL_group ||
+ trial_group == experiment_25_min_TTL_group) {
PrerenderManager::SetMode(
PrerenderManager::PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP);
- } else if (trial_group == kControl1Group ||
- trial_group == kControl2Group) {
+ } else if (trial_group == control_1_group ||
+ trial_group == control_2_group) {
PrerenderManager::SetMode(
PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
- } else if (trial_group == kNoUse1Group ||
- trial_group == kNoUse2Group) {
+ } else if (trial_group == no_use_1_group ||
+ trial_group == no_use_2_group) {
PrerenderManager::SetMode(
PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP);
} else {
@@ -192,8 +195,9 @@ void ConfigureOmniboxPrerender() {
kDisabledProbability = 1;
}
scoped_refptr<base::FieldTrial> omnibox_prerender_trial(
- new base::FieldTrial(kOmniboxTrialName, kDivisor,
- "OmniboxPrerenderEnabled", 2012, 8, 30));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ kOmniboxTrialName, kDivisor, "OmniboxPrerenderEnabled",
+ 2012, 8, 30, &g_omnibox_trial_default_group_number));
omnibox_prerender_trial->AppendGroup("OmniboxPrerenderDisabled",
kDisabledProbability);
@@ -202,8 +206,9 @@ void ConfigureOmniboxPrerender() {
const base::FieldTrial::Probability kEightProbability = 33;
scoped_refptr<base::FieldTrial> weighting_trial(
- new base::FieldTrial("OmniboxPrerenderHitWeightingTrial", kDivisor,
- "OmniboxPrerenderWeight1.0", 2012, 8, 30));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "OmniboxPrerenderHitWeightingTrial", kDivisor,
+ "OmniboxPrerenderWeight1.0", 2012, 8, 30, NULL));
const int kOmniboxWeightFourGroup =
weighting_trial->AppendGroup("OmniboxPrerenderWeight4.0",
kFourProbability);
@@ -242,7 +247,7 @@ bool IsOmniboxEnabled(Profile* profile) {
const int group = base::FieldTrialList::FindValue(kOmniboxTrialName);
return group == base::FieldTrial::kNotFinalized ||
- group == base::FieldTrial::kDefaultGroupNumber;
+ group == g_omnibox_trial_default_group_number;
}
} // namespace prerender
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
index b4d6683..209fd3e 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui.cc
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
@@ -275,8 +275,8 @@ void NewTabUI::RegisterUserPrefs(PrefService* prefs) {
// static
void NewTabUI::SetupFieldTrials() {
scoped_refptr<base::FieldTrial> trial(
- new base::FieldTrial(kWebStoreLinkExperiment, 3, "Disabled",
- 2012, 6, 1));
+ base::FieldTrialList::FactoryGetFieldTrial(
+ kWebStoreLinkExperiment, 3, "Disabled", 2012, 6, 1, NULL));
// Try to give the user a consistent experience, if possible.
if (base::FieldTrialList::IsOneTimeRandomizationEnabled())
diff --git a/chrome_frame/chrome_frame_automation.cc b/chrome_frame/chrome_frame_automation.cc
index 88f5f9c..9a649c0 100644
--- a/chrome_frame/chrome_frame_automation.cc
+++ b/chrome_frame/chrome_frame_automation.cc
@@ -1040,8 +1040,10 @@ void ChromeFrameAutomationClient::InitializeFieldTrials() {
if (!trial) {
// Do one-time initialization of the field trial here.
// TODO(robertshield): End the field trial before March 7th 2013.
- scoped_refptr<base::FieldTrial> new_trial = new base::FieldTrial(
- "ChromeShutdownDelay", 1000, kWithDelayFieldTrialName, 2013, 3, 7);
+ scoped_refptr<base::FieldTrial> new_trial =
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "ChromeShutdownDelay", 1000, kWithDelayFieldTrialName,
+ 2013, 3, 7, NULL);
// Be consistent for this client. Note that this will only have an effect
// once the client id is persisted. See http://crbug.com/117188
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index d62cada..e38a37f 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -632,7 +632,7 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
std::string field_trial_states;
base::FieldTrialList::StatesToString(&field_trial_states);
if (!field_trial_states.empty()) {
- command_line->AppendSwitchASCII(switches::kForceFieldTestNameAndValue,
+ command_line->AppendSwitchASCII(switches::kForceFieldTrials,
field_trial_states);
}
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 2819e1d..c660c57 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -366,17 +366,15 @@ const char kExtraPluginDir[] = "extra-plugin-dir";
// the base layer even when compositing is not strictly required.
const char kForceCompositingMode[] = "force-compositing-mode";
-// Some field tests may rendomized in the browser, and the randomly selected
-// outcome needs to be propagated to the renderer. For instance, this is used
+// Some field trials may be randomized in the browser, and the randomly selected
+// outcome needs to be propagated to the renderer. For instance, this is used
// to modify histograms recorded in the renderer, or to get the renderer to
// also set of its state (initialize, or not initialize components) to match the
-// experiment(s).
-// The argument is a string-ized list of experiment names, and the associated
-// value that was randomly selected. In the recent implementetaion, the
-// persistent representation generated by field_trial.cc and later decoded, is a
-// list of name and value pairs, separated by slashes. See field trial.cc for
-// current details.
-const char kForceFieldTestNameAndValue[] = "force-fieldtest";
+// experiment(s). The option is also useful for forcing field trials when
+// testing changes locally. The argument is a list of name and value pairs,
+// separated by slashes. See FieldTrialList::CreateTrialsFromString() in
+// field_trial.h for details.
+const char kForceFieldTrials[] = "force-fieldtrials";
// Force renderer accessibility to be on instead of enabling it on demand when
// a screen reader is detected. The disable-renderer-accessibility switch
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index d63df83..fb1bff4 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -117,7 +117,7 @@ CONTENT_EXPORT extern const char kDisableWebIntents[];
CONTENT_EXPORT extern const char kExperimentalLocationFeatures[];
extern const char kExtraPluginDir[];
CONTENT_EXPORT extern const char kForceCompositingMode[];
-extern const char kForceFieldTestNameAndValue[];
+extern const char kForceFieldTrials[];
CONTENT_EXPORT extern const char kForceRendererAccessibility[];
extern const char kGpuLauncher[];
CONTENT_EXPORT extern const char kGpuProcess[];
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc
index becc623..24354fe 100644
--- a/content/renderer/renderer_main.cc
+++ b/content/renderer/renderer_main.cc
@@ -236,10 +236,10 @@ int RendererMain(const content::MainFunctionParams& parameters) {
// one-time randomized trials; they should be created in the browser process.
base::FieldTrialList field_trial(EmptyString());
// Ensure any field trials in browser are reflected into renderer.
- if (parsed_command_line.HasSwitch(switches::kForceFieldTestNameAndValue)) {
+ if (parsed_command_line.HasSwitch(switches::kForceFieldTrials)) {
std::string persistent = parsed_command_line.GetSwitchValueASCII(
- switches::kForceFieldTestNameAndValue);
- bool ret = field_trial.CreateTrialsInChildProcess(persistent);
+ switches::kForceFieldTrials);
+ bool ret = base::FieldTrialList::CreateTrialsFromString(persistent);
DCHECK(ret);
}