Chromium Code Reviews| Index: base/metrics/field_trial.cc |
| diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc |
| index c1416dbce2e80a61bc188104c49780c82b9b57c2..44c56b2ec2dfc480577dd9939a1878f3d01619bf 100644 |
| --- a/base/metrics/field_trial.cc |
| +++ b/base/metrics/field_trial.cc |
| @@ -1,11 +1,14 @@ |
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| #include "base/metrics/field_trial.h" |
| +#include "base/file_util.h" |
| #include "base/logging.h" |
| +#include "base/pickle.h" |
| #include "base/rand_util.h" |
| +#include "base/sha1.h" |
| #include "base/stringprintf.h" |
| #include "base/utf_string_conversions.h" |
| @@ -37,10 +40,11 @@ FieldTrial::FieldTrial(const std::string& name, |
| : name_(name), |
| divisor_(total_probability), |
| default_group_name_(default_group_name), |
| - random_(static_cast<Probability>(divisor_ * base::RandDouble())), |
| + random_(static_cast<Probability>(divisor_ * RandDouble())), |
| accumulated_group_probability_(0), |
| next_group_number_(kDefaultGroupNumber+1), |
| - group_(kNotFinalized) { |
| + group_(kNotFinalized), |
| + disable_field_trial_(false) { |
| DCHECK_GT(total_probability, 0); |
| DCHECK(!default_group_name_.empty()); |
| FieldTrialList::Register(this); |
| @@ -51,7 +55,7 @@ FieldTrial::FieldTrial(const std::string& name, |
| DCHECK_GT(day_of_month, 0); |
| DCHECK_LT(day_of_month, 32); |
| - base::Time::Exploded exploded; |
| + Time::Exploded exploded; |
| exploded.year = year; |
| exploded.month = month; |
| exploded.day_of_week = 0; // Should be unused. |
| @@ -61,8 +65,26 @@ FieldTrial::FieldTrial(const std::string& name, |
| exploded.second = 0; |
| exploded.millisecond = 0; |
| - base::Time expiration_time = Time::FromLocalExploded(exploded); |
| - disable_field_trial_ = (GetBuildTime() > expiration_time) ? true : false; |
| + Time expiration_time = Time::FromLocalExploded(exploded); |
| + if (GetBuildTime() > expiration_time) { |
| + Disable(); |
| + } |
|
jar (doing other things)
2011/04/21 01:03:50
style nit: Don't bother with braces on one line if
Jói
2011/04/21 19:50:33
Done.
|
| +} |
| + |
| +void FieldTrial::UseOneTimeRandomization(const std::string& machine_id) { |
| + DCHECK_EQ(group_, kNotFinalized); |
| + if (machine_id.empty()) { |
| + NOTREACHED(); |
| + disable_field_trial_ = true; |
| + return; |
| + } |
| + |
| + random_ = static_cast<Probability>( |
| + divisor_ * MachineIdToUniformDouble(machine_id)); |
|
jar (doing other things)
2011/04/21 01:03:50
Is your hope to make these repeatable on a given m
Jói
2011/04/21 19:50:33
I'm now using the UMA ID and salting with the tria
|
| +} |
| + |
| +void FieldTrial::Disable() { |
| + disable_field_trial_ = true; |
| } |
| int FieldTrial::AppendGroup(const std::string& name, |
| @@ -80,7 +102,7 @@ int FieldTrial::AppendGroup(const std::string& name, |
| // This is the group that crossed the random line, so we do the assignment. |
| group_ = next_group_number_; |
| if (name.empty()) |
| - base::StringAppendF(&group_name_, "%d", group_); |
| + StringAppendF(&group_name_, "%d", group_); |
| else |
| group_name_ = name; |
| } |
| @@ -127,6 +149,28 @@ Time FieldTrial::GetBuildTime() { |
| return integral_build_time; |
| } |
| +// static |
| +double FieldTrial::MachineIdToUniformDouble(const std::string& machine_id) { |
| + // We use SHA-1 over the unique ID we have for machine/user (we add |
| + // the user part by adding the user's home directory). SHA-1 is designed |
| + // to produce a uniformly random spread in its output space, even for |
| + // nearly-identical inputs, so it helps make this data look like a uniform |
| + // random distribution. |
| + Pickle pickle; |
| + pickle.WriteString(machine_id); |
| + file_util::GetHomeDir().WriteToPickle(&pickle); |
|
jar (doing other things)
2011/04/21 01:03:50
Pickling is a waste. It doesn't add to the entrop
Jói
2011/04/21 19:50:33
Done.
|
| + |
| + unsigned char sha1_hash[SHA1_LENGTH]; |
| + SHA1HashBytes(reinterpret_cast<const unsigned char*>(pickle.data()), |
| + pickle.size(), |
| + sha1_hash); |
| + |
| + COMPILE_ASSERT(sizeof(uint64) < sizeof(sha1_hash), need_more_data); |
| + uint64* bits = reinterpret_cast<uint64*>(&sha1_hash[0]); |
| + |
| + return BitsToRandDouble(*bits); |
| +} |
| + |
| //------------------------------------------------------------------------------ |
| // FieldTrialList methods and members. |