| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/metrics/field_trial.h" | 5 #include "base/metrics/field_trial.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/base_switches.h" | 10 #include "base/base_switches.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 if (!pickle->WriteString(string2)) | 76 if (!pickle->WriteString(string2)) |
| 77 return false; | 77 return false; |
| 78 return true; | 78 return true; |
| 79 } | 79 } |
| 80 | 80 |
| 81 // Writes out the field trial's contents (via trial_state) to the pickle. The | 81 // Writes out the field trial's contents (via trial_state) to the pickle. The |
| 82 // format of the pickle looks like: | 82 // format of the pickle looks like: |
| 83 // TrialName, GroupName, ParamKey1, ParamValue1, ParamKey2, ParamValue2, ... | 83 // TrialName, GroupName, ParamKey1, ParamValue1, ParamKey2, ParamValue2, ... |
| 84 // If there are no parameters, then it just ends at GroupName. | 84 // If there are no parameters, then it just ends at GroupName. |
| 85 bool PickleFieldTrial(const FieldTrial::State& trial_state, Pickle* pickle) { | 85 bool PickleFieldTrial(const FieldTrial::State& trial_state, Pickle* pickle) { |
| 86 if (!WriteStringPair(pickle, trial_state.trial_name, trial_state.group_name)) | 86 if (!WriteStringPair(pickle, *trial_state.trial_name, |
| 87 *trial_state.group_name)) { |
| 87 return false; | 88 return false; |
| 89 } |
| 88 | 90 |
| 89 // Get field trial params. | 91 // Get field trial params. |
| 90 std::map<std::string, std::string> params; | 92 std::map<std::string, std::string> params; |
| 91 FieldTrialParamAssociator::GetInstance()->GetFieldTrialParamsWithoutFallback( | 93 FieldTrialParamAssociator::GetInstance()->GetFieldTrialParamsWithoutFallback( |
| 92 trial_state.trial_name.as_string(), trial_state.group_name.as_string(), | 94 *trial_state.trial_name, *trial_state.group_name, ¶ms); |
| 93 ¶ms); | |
| 94 | 95 |
| 95 // Write params to pickle. | 96 // Write params to pickle. |
| 96 for (const auto& param : params) { | 97 for (const auto& param : params) { |
| 97 if (!WriteStringPair(pickle, param.first, param.second)) | 98 if (!WriteStringPair(pickle, param.first, param.second)) |
| 98 return false; | 99 return false; |
| 99 } | 100 } |
| 100 return true; | 101 return true; |
| 101 } | 102 } |
| 102 | 103 |
| 103 // Created a time value based on |year|, |month| and |day_of_month| parameters. | 104 // Created a time value based on |year|, |month| and |day_of_month| parameters. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 // static_cast<FieldTrial::Probability>(100 * 0.57) == 56 | 140 // static_cast<FieldTrial::Probability>(100 * 0.57) == 56 |
| 140 // static_cast<FieldTrial::Probability>(100 * 0.58) == 57 | 141 // static_cast<FieldTrial::Probability>(100 * 0.58) == 57 |
| 141 // static_cast<FieldTrial::Probability>(100 * 0.59) == 59 | 142 // static_cast<FieldTrial::Probability>(100 * 0.59) == 59 |
| 142 const double kEpsilon = 1e-8; | 143 const double kEpsilon = 1e-8; |
| 143 const FieldTrial::Probability result = | 144 const FieldTrial::Probability result = |
| 144 static_cast<FieldTrial::Probability>(divisor * entropy_value + kEpsilon); | 145 static_cast<FieldTrial::Probability>(divisor * entropy_value + kEpsilon); |
| 145 // Ensure that adding the epsilon still results in a value < |divisor|. | 146 // Ensure that adding the epsilon still results in a value < |divisor|. |
| 146 return std::min(result, divisor - 1); | 147 return std::min(result, divisor - 1); |
| 147 } | 148 } |
| 148 | 149 |
| 150 // Separate type from FieldTrial::State so that it can use StringPieces. |
| 151 struct FieldTrialStringEntry { |
| 152 StringPiece trial_name; |
| 153 StringPiece group_name; |
| 154 bool activated = false; |
| 155 }; |
| 156 |
| 149 // Parses the --force-fieldtrials string |trials_string| into |entries|. | 157 // Parses the --force-fieldtrials string |trials_string| into |entries|. |
| 150 // Returns true if the string was parsed correctly. On failure, the |entries| | 158 // Returns true if the string was parsed correctly. On failure, the |entries| |
| 151 // array may end up being partially filled. | 159 // array may end up being partially filled. |
| 152 bool ParseFieldTrialsString(const std::string& trials_string, | 160 bool ParseFieldTrialsString(const std::string& trials_string, |
| 153 std::vector<FieldTrial::State>* entries) { | 161 std::vector<FieldTrialStringEntry>* entries) { |
| 154 const StringPiece trials_string_piece(trials_string); | 162 const StringPiece trials_string_piece(trials_string); |
| 155 | 163 |
| 156 size_t next_item = 0; | 164 size_t next_item = 0; |
| 157 while (next_item < trials_string.length()) { | 165 while (next_item < trials_string.length()) { |
| 158 size_t name_end = trials_string.find(kPersistentStringSeparator, next_item); | 166 size_t name_end = trials_string.find(kPersistentStringSeparator, next_item); |
| 159 if (name_end == trials_string.npos || next_item == name_end) | 167 if (name_end == trials_string.npos || next_item == name_end) |
| 160 return false; | 168 return false; |
| 161 size_t group_name_end = | 169 size_t group_name_end = |
| 162 trials_string.find(kPersistentStringSeparator, name_end + 1); | 170 trials_string.find(kPersistentStringSeparator, name_end + 1); |
| 163 if (name_end + 1 == group_name_end) | 171 if (name_end + 1 == group_name_end) |
| 164 return false; | 172 return false; |
| 165 if (group_name_end == trials_string.npos) | 173 if (group_name_end == trials_string.npos) |
| 166 group_name_end = trials_string.length(); | 174 group_name_end = trials_string.length(); |
| 167 | 175 |
| 168 FieldTrial::State entry; | 176 FieldTrialStringEntry entry; |
| 169 // Verify if the trial should be activated or not. | 177 // Verify if the trial should be activated or not. |
| 170 if (trials_string[next_item] == kActivationMarker) { | 178 if (trials_string[next_item] == kActivationMarker) { |
| 171 // Name cannot be only the indicator. | 179 // Name cannot be only the indicator. |
| 172 if (name_end - next_item == 1) | 180 if (name_end - next_item == 1) |
| 173 return false; | 181 return false; |
| 174 next_item++; | 182 next_item++; |
| 175 entry.activated = true; | 183 entry.activated = true; |
| 176 } | 184 } |
| 177 entry.trial_name = | 185 entry.trial_name = |
| 178 trials_string_piece.substr(next_item, name_end - next_item); | 186 trials_string_piece.substr(next_item, name_end - next_item); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 bool FieldTrial::enable_benchmarking_ = false; | 243 bool FieldTrial::enable_benchmarking_ = false; |
| 236 | 244 |
| 237 int FieldTrialList::kNoExpirationYear = 0; | 245 int FieldTrialList::kNoExpirationYear = 0; |
| 238 | 246 |
| 239 //------------------------------------------------------------------------------ | 247 //------------------------------------------------------------------------------ |
| 240 // FieldTrial methods and members. | 248 // FieldTrial methods and members. |
| 241 | 249 |
| 242 FieldTrial::EntropyProvider::~EntropyProvider() { | 250 FieldTrial::EntropyProvider::~EntropyProvider() { |
| 243 } | 251 } |
| 244 | 252 |
| 245 FieldTrial::State::State() : activated(false) {} | 253 FieldTrial::State::State() {} |
| 246 | 254 |
| 247 FieldTrial::State::State(const State& other) = default; | 255 FieldTrial::State::State(const State& other) = default; |
| 248 | 256 |
| 249 FieldTrial::State::~State() {} | 257 FieldTrial::State::~State() {} |
| 250 | 258 |
| 251 bool FieldTrial::FieldTrialEntry::GetTrialAndGroupName( | 259 bool FieldTrial::FieldTrialEntry::GetTrialAndGroupName( |
| 252 StringPiece* trial_name, | 260 StringPiece* trial_name, |
| 253 StringPiece* group_name) const { | 261 StringPiece* group_name) const { |
| 254 PickleIterator iter = GetPickleIterator(); | 262 PickleIterator iter = GetPickleIterator(); |
| 255 return ReadStringPair(&iter, trial_name, group_name); | 263 return ReadStringPair(&iter, trial_name, group_name); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 DCHECK_NE(group_, kNotFinalized); | 457 DCHECK_NE(group_, kNotFinalized); |
| 450 active_group->trial_name = trial_name_; | 458 active_group->trial_name = trial_name_; |
| 451 active_group->group_name = group_name_; | 459 active_group->group_name = group_name_; |
| 452 return true; | 460 return true; |
| 453 } | 461 } |
| 454 | 462 |
| 455 bool FieldTrial::GetState(State* field_trial_state) { | 463 bool FieldTrial::GetState(State* field_trial_state) { |
| 456 if (!enable_field_trial_) | 464 if (!enable_field_trial_) |
| 457 return false; | 465 return false; |
| 458 FinalizeGroupChoice(); | 466 FinalizeGroupChoice(); |
| 459 field_trial_state->trial_name = trial_name_; | 467 field_trial_state->trial_name = &trial_name_; |
| 460 field_trial_state->group_name = group_name_; | 468 field_trial_state->group_name = &group_name_; |
| 461 field_trial_state->activated = group_reported_; | 469 field_trial_state->activated = group_reported_; |
| 462 return true; | 470 return true; |
| 463 } | 471 } |
| 464 | 472 |
| 465 bool FieldTrial::GetStateWhileLocked(State* field_trial_state) { | 473 bool FieldTrial::GetStateWhileLocked(State* field_trial_state) { |
| 466 if (!enable_field_trial_) | 474 if (!enable_field_trial_) |
| 467 return false; | 475 return false; |
| 468 FinalizeGroupChoiceImpl(true); | 476 FinalizeGroupChoiceImpl(true); |
| 469 field_trial_state->trial_name = trial_name_; | 477 field_trial_state->trial_name = &trial_name_; |
| 470 field_trial_state->group_name = group_name_; | 478 field_trial_state->group_name = &group_name_; |
| 471 field_trial_state->activated = group_reported_; | 479 field_trial_state->activated = group_reported_; |
| 472 return true; | 480 return true; |
| 473 } | 481 } |
| 474 | 482 |
| 475 //------------------------------------------------------------------------------ | 483 //------------------------------------------------------------------------------ |
| 476 // FieldTrialList methods and members. | 484 // FieldTrialList methods and members. |
| 477 | 485 |
| 478 // static | 486 // static |
| 479 FieldTrialList* FieldTrialList::global_ = NULL; | 487 FieldTrialList* FieldTrialList::global_ = NULL; |
| 480 | 488 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 void FieldTrialList::AllStatesToString(std::string* output) { | 656 void FieldTrialList::AllStatesToString(std::string* output) { |
| 649 if (!global_) | 657 if (!global_) |
| 650 return; | 658 return; |
| 651 AutoLock auto_lock(global_->lock_); | 659 AutoLock auto_lock(global_->lock_); |
| 652 | 660 |
| 653 for (const auto& registered : global_->registered_) { | 661 for (const auto& registered : global_->registered_) { |
| 654 FieldTrial::State trial; | 662 FieldTrial::State trial; |
| 655 if (!registered.second->GetStateWhileLocked(&trial)) | 663 if (!registered.second->GetStateWhileLocked(&trial)) |
| 656 continue; | 664 continue; |
| 657 DCHECK_EQ(std::string::npos, | 665 DCHECK_EQ(std::string::npos, |
| 658 trial.trial_name.find(kPersistentStringSeparator)); | 666 trial.trial_name->find(kPersistentStringSeparator)); |
| 659 DCHECK_EQ(std::string::npos, | 667 DCHECK_EQ(std::string::npos, |
| 660 trial.group_name.find(kPersistentStringSeparator)); | 668 trial.group_name->find(kPersistentStringSeparator)); |
| 661 if (trial.activated) | 669 if (trial.activated) |
| 662 output->append(1, kActivationMarker); | 670 output->append(1, kActivationMarker); |
| 663 trial.trial_name.AppendToString(output); | 671 output->append(*trial.trial_name); |
| 664 output->append(1, kPersistentStringSeparator); | 672 output->append(1, kPersistentStringSeparator); |
| 665 trial.group_name.AppendToString(output); | 673 output->append(*trial.group_name); |
| 666 output->append(1, kPersistentStringSeparator); | 674 output->append(1, kPersistentStringSeparator); |
| 667 } | 675 } |
| 668 } | 676 } |
| 669 | 677 |
| 670 // static | 678 // static |
| 671 void FieldTrialList::GetActiveFieldTrialGroups( | 679 void FieldTrialList::GetActiveFieldTrialGroups( |
| 672 FieldTrial::ActiveGroups* active_groups) { | 680 FieldTrial::ActiveGroups* active_groups) { |
| 673 DCHECK(active_groups->empty()); | 681 DCHECK(active_groups->empty()); |
| 674 if (!global_) | 682 if (!global_) |
| 675 return; | 683 return; |
| 676 AutoLock auto_lock(global_->lock_); | 684 AutoLock auto_lock(global_->lock_); |
| 677 | 685 |
| 678 for (RegistrationMap::iterator it = global_->registered_.begin(); | 686 for (RegistrationMap::iterator it = global_->registered_.begin(); |
| 679 it != global_->registered_.end(); ++it) { | 687 it != global_->registered_.end(); ++it) { |
| 680 FieldTrial::ActiveGroup active_group; | 688 FieldTrial::ActiveGroup active_group; |
| 681 if (it->second->GetActiveGroup(&active_group)) | 689 if (it->second->GetActiveGroup(&active_group)) |
| 682 active_groups->push_back(active_group); | 690 active_groups->push_back(active_group); |
| 683 } | 691 } |
| 684 } | 692 } |
| 685 | 693 |
| 686 // static | 694 // static |
| 687 void FieldTrialList::GetActiveFieldTrialGroupsFromString( | 695 void FieldTrialList::GetActiveFieldTrialGroupsFromString( |
| 688 const std::string& trials_string, | 696 const std::string& trials_string, |
| 689 FieldTrial::ActiveGroups* active_groups) { | 697 FieldTrial::ActiveGroups* active_groups) { |
| 690 std::vector<FieldTrial::State> entries; | 698 std::vector<FieldTrialStringEntry> entries; |
| 691 if (!ParseFieldTrialsString(trials_string, &entries)) | 699 if (!ParseFieldTrialsString(trials_string, &entries)) |
| 692 return; | 700 return; |
| 693 | 701 |
| 694 for (const auto& entry : entries) { | 702 for (const auto& entry : entries) { |
| 695 if (entry.activated) { | 703 if (entry.activated) { |
| 696 FieldTrial::ActiveGroup group; | 704 FieldTrial::ActiveGroup group; |
| 697 group.trial_name = entry.trial_name.as_string(); | 705 group.trial_name = entry.trial_name.as_string(); |
| 698 group.group_name = entry.group_name.as_string(); | 706 group.group_name = entry.group_name.as_string(); |
| 699 active_groups->push_back(group); | 707 active_groups->push_back(group); |
| 700 } | 708 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 } | 740 } |
| 733 | 741 |
| 734 // static | 742 // static |
| 735 bool FieldTrialList::CreateTrialsFromString( | 743 bool FieldTrialList::CreateTrialsFromString( |
| 736 const std::string& trials_string, | 744 const std::string& trials_string, |
| 737 const std::set<std::string>& ignored_trial_names) { | 745 const std::set<std::string>& ignored_trial_names) { |
| 738 DCHECK(global_); | 746 DCHECK(global_); |
| 739 if (trials_string.empty() || !global_) | 747 if (trials_string.empty() || !global_) |
| 740 return true; | 748 return true; |
| 741 | 749 |
| 742 std::vector<FieldTrial::State> entries; | 750 std::vector<FieldTrialStringEntry> entries; |
| 743 if (!ParseFieldTrialsString(trials_string, &entries)) | 751 if (!ParseFieldTrialsString(trials_string, &entries)) |
| 744 return false; | 752 return false; |
| 745 | 753 |
| 746 for (const auto& entry : entries) { | 754 for (const auto& entry : entries) { |
| 747 const std::string trial_name = entry.trial_name.as_string(); | 755 const std::string trial_name = entry.trial_name.as_string(); |
| 748 const std::string group_name = entry.group_name.as_string(); | 756 const std::string group_name = entry.group_name.as_string(); |
| 749 | 757 |
| 750 if (ContainsKey(ignored_trial_names, trial_name)) | 758 if (ContainsKey(ignored_trial_names, trial_name)) |
| 751 continue; | 759 continue; |
| 752 | 760 |
| (...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 return; | 1351 return; |
| 1344 } | 1352 } |
| 1345 AutoLock auto_lock(global_->lock_); | 1353 AutoLock auto_lock(global_->lock_); |
| 1346 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 1354 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 1347 trial->AddRef(); | 1355 trial->AddRef(); |
| 1348 trial->SetTrialRegistered(); | 1356 trial->SetTrialRegistered(); |
| 1349 global_->registered_[trial->trial_name()] = trial; | 1357 global_->registered_[trial->trial_name()] = trial; |
| 1350 } | 1358 } |
| 1351 | 1359 |
| 1352 } // namespace base | 1360 } // namespace base |
| OLD | NEW |