| 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 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { | 330 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { |
| 331 group_ = number; | 331 group_ = number; |
| 332 if (group_name.empty()) | 332 if (group_name.empty()) |
| 333 StringAppendF(&group_name_, "%d", group_); | 333 StringAppendF(&group_name_, "%d", group_); |
| 334 else | 334 else |
| 335 group_name_ = group_name; | 335 group_name_ = group_name; |
| 336 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; | 336 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; |
| 337 } | 337 } |
| 338 | 338 |
| 339 void FieldTrial::FinalizeGroupChoice() { | 339 void FieldTrial::FinalizeGroupChoice() { |
| 340 FinalizeGroupChoiceImpl(false); |
| 341 } |
| 342 |
| 343 void FieldTrial::FinalizeGroupChoiceImpl(bool is_locked) { |
| 340 if (group_ != kNotFinalized) | 344 if (group_ != kNotFinalized) |
| 341 return; | 345 return; |
| 342 accumulated_group_probability_ = divisor_; | 346 accumulated_group_probability_ = divisor_; |
| 343 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not | 347 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not |
| 344 // finalized. | 348 // finalized. |
| 345 DCHECK(!forced_); | 349 DCHECK(!forced_); |
| 346 SetGroupChoice(default_group_name_, kDefaultGroupNumber); | 350 SetGroupChoice(default_group_name_, kDefaultGroupNumber); |
| 347 | 351 |
| 348 // Add the field trial to shared memory. | 352 // Add the field trial to shared memory. |
| 349 if (kUseSharedMemoryForFieldTrials) | 353 if (kUseSharedMemoryForFieldTrials) |
| 350 FieldTrialList::OnGroupFinalized(this); | 354 FieldTrialList::OnGroupFinalized(is_locked, this); |
| 351 } | 355 } |
| 352 | 356 |
| 353 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { | 357 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { |
| 354 if (!group_reported_ || !enable_field_trial_) | 358 if (!group_reported_ || !enable_field_trial_) |
| 355 return false; | 359 return false; |
| 356 DCHECK_NE(group_, kNotFinalized); | 360 DCHECK_NE(group_, kNotFinalized); |
| 357 active_group->trial_name = trial_name_; | 361 active_group->trial_name = trial_name_; |
| 358 active_group->group_name = group_name_; | 362 active_group->group_name = group_name_; |
| 359 return true; | 363 return true; |
| 360 } | 364 } |
| 361 | 365 |
| 362 bool FieldTrial::GetState(State* field_trial_state) { | 366 bool FieldTrial::GetState(State* field_trial_state) { |
| 363 if (!enable_field_trial_) | 367 if (!enable_field_trial_) |
| 364 return false; | 368 return false; |
| 365 FinalizeGroupChoice(); | 369 FinalizeGroupChoice(); |
| 366 field_trial_state->trial_name = trial_name_; | 370 field_trial_state->trial_name = trial_name_; |
| 367 field_trial_state->group_name = group_name_; | 371 field_trial_state->group_name = group_name_; |
| 368 field_trial_state->activated = group_reported_; | 372 field_trial_state->activated = group_reported_; |
| 369 return true; | 373 return true; |
| 370 } | 374 } |
| 371 | 375 |
| 376 bool FieldTrial::GetStateWhileLocked(State* field_trial_state) { |
| 377 if (!enable_field_trial_) |
| 378 return false; |
| 379 FinalizeGroupChoiceImpl(true); |
| 380 field_trial_state->trial_name = trial_name_; |
| 381 field_trial_state->group_name = group_name_; |
| 382 field_trial_state->activated = group_reported_; |
| 383 return true; |
| 384 } |
| 385 |
| 372 //------------------------------------------------------------------------------ | 386 //------------------------------------------------------------------------------ |
| 373 // FieldTrialList methods and members. | 387 // FieldTrialList methods and members. |
| 374 | 388 |
| 375 // static | 389 // static |
| 376 FieldTrialList* FieldTrialList::global_ = NULL; | 390 FieldTrialList* FieldTrialList::global_ = NULL; |
| 377 | 391 |
| 378 // static | 392 // static |
| 379 bool FieldTrialList::used_without_global_ = false; | 393 bool FieldTrialList::used_without_global_ = false; |
| 380 | 394 |
| 381 FieldTrialList::Observer::~Observer() { | 395 FieldTrialList::Observer::~Observer() { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 } | 556 } |
| 543 | 557 |
| 544 // static | 558 // static |
| 545 void FieldTrialList::AllStatesToString(std::string* output) { | 559 void FieldTrialList::AllStatesToString(std::string* output) { |
| 546 if (!global_) | 560 if (!global_) |
| 547 return; | 561 return; |
| 548 AutoLock auto_lock(global_->lock_); | 562 AutoLock auto_lock(global_->lock_); |
| 549 | 563 |
| 550 for (const auto& registered : global_->registered_) { | 564 for (const auto& registered : global_->registered_) { |
| 551 FieldTrial::State trial; | 565 FieldTrial::State trial; |
| 552 if (!registered.second->GetState(&trial)) | 566 if (!registered.second->GetStateWhileLocked(&trial)) |
| 553 continue; | 567 continue; |
| 554 DCHECK_EQ(std::string::npos, | 568 DCHECK_EQ(std::string::npos, |
| 555 trial.trial_name.find(kPersistentStringSeparator)); | 569 trial.trial_name.find(kPersistentStringSeparator)); |
| 556 DCHECK_EQ(std::string::npos, | 570 DCHECK_EQ(std::string::npos, |
| 557 trial.group_name.find(kPersistentStringSeparator)); | 571 trial.group_name.find(kPersistentStringSeparator)); |
| 558 if (trial.activated) | 572 if (trial.activated) |
| 559 output->append(1, kActivationMarker); | 573 output->append(1, kActivationMarker); |
| 560 trial.trial_name.AppendToString(output); | 574 trial.trial_name.AppendToString(output); |
| 561 output->append(1, kPersistentStringSeparator); | 575 output->append(1, kPersistentStringSeparator); |
| 562 trial.group_name.AppendToString(output); | 576 trial.group_name.AppendToString(output); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 if (global_->readonly_allocator_handle_) | 691 if (global_->readonly_allocator_handle_) |
| 678 handles->push_back(global_->readonly_allocator_handle_); | 692 handles->push_back(global_->readonly_allocator_handle_); |
| 679 } | 693 } |
| 680 } | 694 } |
| 681 #endif | 695 #endif |
| 682 | 696 |
| 683 // static | 697 // static |
| 684 void FieldTrialList::CopyFieldTrialStateToFlags( | 698 void FieldTrialList::CopyFieldTrialStateToFlags( |
| 685 const char* field_trial_handle_switch, | 699 const char* field_trial_handle_switch, |
| 686 CommandLine* cmd_line) { | 700 CommandLine* cmd_line) { |
| 701 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, |
| 702 // content browser tests currently don't create a FieldTrialList because they |
| 703 // don't run ChromeBrowserMainParts code where it's done for Chrome. |
| 704 if (!global_) |
| 705 return; |
| 706 |
| 687 #if defined(OS_WIN) | 707 #if defined(OS_WIN) |
| 688 // Use shared memory to pass the state if the feature is enabled, otherwise | 708 // Use shared memory to pass the state if the feature is enabled, otherwise |
| 689 // fallback to passing it via the command line as a string. | 709 // fallback to passing it via the command line as a string. |
| 690 if (kUseSharedMemoryForFieldTrials) { | 710 if (kUseSharedMemoryForFieldTrials) { |
| 691 InstantiateFieldTrialAllocatorIfNeeded(); | 711 InstantiateFieldTrialAllocatorIfNeeded(); |
| 692 // If the readonly handle didn't get duplicated properly, then fallback to | 712 // If the readonly handle didn't get duplicated properly, then fallback to |
| 693 // original behavior. | 713 // original behavior. |
| 694 if (!global_->readonly_allocator_handle_) { | 714 if (!global_->readonly_allocator_handle_) { |
| 695 AddForceFieldTrialsFlag(cmd_line); | 715 AddForceFieldTrialsFlag(cmd_line); |
| 696 return; | 716 return; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 } | 771 } |
| 752 | 772 |
| 753 // static | 773 // static |
| 754 void FieldTrialList::RemoveObserver(Observer* observer) { | 774 void FieldTrialList::RemoveObserver(Observer* observer) { |
| 755 if (!global_) | 775 if (!global_) |
| 756 return; | 776 return; |
| 757 global_->observer_list_->RemoveObserver(observer); | 777 global_->observer_list_->RemoveObserver(observer); |
| 758 } | 778 } |
| 759 | 779 |
| 760 // static | 780 // static |
| 761 void FieldTrialList::OnGroupFinalized(FieldTrial* field_trial) { | 781 void FieldTrialList::OnGroupFinalized(bool is_locked, FieldTrial* field_trial) { |
| 762 if (!global_) | 782 if (!global_) |
| 763 return; | 783 return; |
| 764 AutoLock auto_lock(global_->lock_); | 784 if (is_locked) { |
| 765 AddToAllocatorWhileLocked(field_trial); | 785 AddToAllocatorWhileLocked(field_trial); |
| 786 } else { |
| 787 AutoLock auto_lock(global_->lock_); |
| 788 AddToAllocatorWhileLocked(field_trial); |
| 789 } |
| 766 } | 790 } |
| 767 | 791 |
| 768 // static | 792 // static |
| 769 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { | 793 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { |
| 770 if (!global_) | 794 if (!global_) |
| 771 return; | 795 return; |
| 772 | 796 |
| 773 { | 797 { |
| 774 AutoLock auto_lock(global_->lock_); | 798 AutoLock auto_lock(global_->lock_); |
| 775 if (field_trial->group_reported_) | 799 if (field_trial->group_reported_) |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 return; | 972 return; |
| 949 } | 973 } |
| 950 AutoLock auto_lock(global_->lock_); | 974 AutoLock auto_lock(global_->lock_); |
| 951 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 975 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 952 trial->AddRef(); | 976 trial->AddRef(); |
| 953 trial->SetTrialRegistered(); | 977 trial->SetTrialRegistered(); |
| 954 global_->registered_[trial->trial_name()] = trial; | 978 global_->registered_[trial->trial_name()] = trial; |
| 955 } | 979 } |
| 956 | 980 |
| 957 } // namespace base | 981 } // namespace base |
| OLD | NEW |