diff options
author | mad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-12 07:08:07 +0000 |
---|---|---|
committer | mad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-12 07:08:07 +0000 |
commit | 2d4729587b4377874e12be4c578333f02f0cba4b (patch) | |
tree | 457c4cb66b23eb7b7ff2eef50decd77b479d3b62 | |
parent | c263bc8d3aae4595f1351a70c80142438e017e26 (diff) | |
download | chromium_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.cc | 129 | ||||
-rw-r--r-- | base/metrics/field_trial.h | 124 | ||||
-rw-r--r-- | base/metrics/field_trial_unittest.cc | 153 | ||||
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_field_trial.cc | 18 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 97 | ||||
-rw-r--r-- | chrome/browser/component_updater/pepper_flash_field_trial.cc | 8 | ||||
-rw-r--r-- | chrome/browser/instant/instant_field_trial.cc | 7 | ||||
-rw-r--r-- | chrome/browser/net/http_pipelining_compatibility_client.cc | 4 | ||||
-rw-r--r-- | chrome/browser/net/network_stats.cc | 5 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_field_trial.cc | 55 | ||||
-rw-r--r-- | chrome/browser/ui/webui/ntp/new_tab_ui.cc | 4 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_automation.cc | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/render_process_host_impl.cc | 2 | ||||
-rw-r--r-- | content/public/common/content_switches.cc | 16 | ||||
-rw-r--r-- | content/public/common/content_switches.h | 2 | ||||
-rw-r--r-- | content/renderer/renderer_main.cc | 6 |
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); } |