Chromium Code Reviews| 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 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { | 327 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { |
| 328 group_ = number; | 328 group_ = number; |
| 329 if (group_name.empty()) | 329 if (group_name.empty()) |
| 330 StringAppendF(&group_name_, "%d", group_); | 330 StringAppendF(&group_name_, "%d", group_); |
| 331 else | 331 else |
| 332 group_name_ = group_name; | 332 group_name_ = group_name; |
| 333 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; | 333 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; |
| 334 } | 334 } |
| 335 | 335 |
| 336 void FieldTrial::FinalizeGroupChoice() { | 336 void FieldTrial::FinalizeGroupChoice() { |
| 337 FinalizeGroupChoiceImpl(false); | |
| 338 } | |
| 339 | |
| 340 void FieldTrial::FinalizeGroupChoiceImpl(bool is_locked) { | |
| 337 if (group_ != kNotFinalized) | 341 if (group_ != kNotFinalized) |
| 338 return; | 342 return; |
| 339 accumulated_group_probability_ = divisor_; | 343 accumulated_group_probability_ = divisor_; |
| 340 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not | 344 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not |
| 341 // finalized. | 345 // finalized. |
| 342 DCHECK(!forced_); | 346 DCHECK(!forced_); |
| 343 SetGroupChoice(default_group_name_, kDefaultGroupNumber); | 347 SetGroupChoice(default_group_name_, kDefaultGroupNumber); |
| 344 | 348 |
| 345 // Add the field trial to shared memory. | 349 // Add the field trial to shared memory. |
| 346 if (kUseSharedMemoryForFieldTrials) | 350 if (kUseSharedMemoryForFieldTrials) |
| 347 FieldTrialList::OnGroupFinalized(this); | 351 FieldTrialList::OnGroupFinalized(is_locked, this); |
| 348 } | 352 } |
| 349 | 353 |
| 350 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { | 354 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { |
| 351 if (!group_reported_ || !enable_field_trial_) | 355 if (!group_reported_ || !enable_field_trial_) |
| 352 return false; | 356 return false; |
| 353 DCHECK_NE(group_, kNotFinalized); | 357 DCHECK_NE(group_, kNotFinalized); |
| 354 active_group->trial_name = trial_name_; | 358 active_group->trial_name = trial_name_; |
| 355 active_group->group_name = group_name_; | 359 active_group->group_name = group_name_; |
| 356 return true; | 360 return true; |
| 357 } | 361 } |
| 358 | 362 |
| 359 bool FieldTrial::GetState(State* field_trial_state) { | 363 bool FieldTrial::GetState(State* field_trial_state) { |
| 360 if (!enable_field_trial_) | 364 if (!enable_field_trial_) |
| 361 return false; | 365 return false; |
| 362 FinalizeGroupChoice(); | 366 FinalizeGroupChoice(); |
| 363 field_trial_state->trial_name = trial_name_; | 367 field_trial_state->trial_name = trial_name_; |
| 364 field_trial_state->group_name = group_name_; | 368 field_trial_state->group_name = group_name_; |
| 365 field_trial_state->activated = group_reported_; | 369 field_trial_state->activated = group_reported_; |
| 366 return true; | 370 return true; |
| 367 } | 371 } |
| 368 | 372 |
| 373 bool FieldTrial::GetStateWhileLocked(State* field_trial_state) { | |
| 374 if (!enable_field_trial_) | |
| 375 return false; | |
| 376 FinalizeGroupChoiceImpl(true); | |
| 377 field_trial_state->trial_name = trial_name_; | |
| 378 field_trial_state->group_name = group_name_; | |
| 379 field_trial_state->activated = group_reported_; | |
| 380 return true; | |
| 381 } | |
| 382 | |
| 369 //------------------------------------------------------------------------------ | 383 //------------------------------------------------------------------------------ |
| 370 // FieldTrialList methods and members. | 384 // FieldTrialList methods and members. |
| 371 | 385 |
| 372 // static | 386 // static |
| 373 FieldTrialList* FieldTrialList::global_ = NULL; | 387 FieldTrialList* FieldTrialList::global_ = NULL; |
| 374 | 388 |
| 375 // static | 389 // static |
| 376 bool FieldTrialList::used_without_global_ = false; | 390 bool FieldTrialList::used_without_global_ = false; |
| 377 | 391 |
| 378 FieldTrialList::Observer::~Observer() { | 392 FieldTrialList::Observer::~Observer() { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 } | 553 } |
| 540 | 554 |
| 541 // static | 555 // static |
| 542 void FieldTrialList::AllStatesToString(std::string* output) { | 556 void FieldTrialList::AllStatesToString(std::string* output) { |
| 543 if (!global_) | 557 if (!global_) |
| 544 return; | 558 return; |
| 545 AutoLock auto_lock(global_->lock_); | 559 AutoLock auto_lock(global_->lock_); |
| 546 | 560 |
| 547 for (const auto& registered : global_->registered_) { | 561 for (const auto& registered : global_->registered_) { |
| 548 FieldTrial::State trial; | 562 FieldTrial::State trial; |
| 549 if (!registered.second->GetState(&trial)) | 563 if (!registered.second->GetStateWhileLocked(&trial)) |
| 550 continue; | 564 continue; |
| 551 DCHECK_EQ(std::string::npos, | 565 DCHECK_EQ(std::string::npos, |
| 552 trial.trial_name.find(kPersistentStringSeparator)); | 566 trial.trial_name.find(kPersistentStringSeparator)); |
| 553 DCHECK_EQ(std::string::npos, | 567 DCHECK_EQ(std::string::npos, |
| 554 trial.group_name.find(kPersistentStringSeparator)); | 568 trial.group_name.find(kPersistentStringSeparator)); |
| 555 if (trial.activated) | 569 if (trial.activated) |
| 556 output->append(1, kActivationMarker); | 570 output->append(1, kActivationMarker); |
| 557 trial.trial_name.AppendToString(output); | 571 trial.trial_name.AppendToString(output); |
| 558 output->append(1, kPersistentStringSeparator); | 572 output->append(1, kPersistentStringSeparator); |
| 559 trial.group_name.AppendToString(output); | 573 trial.group_name.AppendToString(output); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 664 } | 678 } |
| 665 | 679 |
| 666 #if defined(OS_WIN) | 680 #if defined(OS_WIN) |
| 667 // static | 681 // static |
| 668 void FieldTrialList::AppendFieldTrialHandleIfNeeded( | 682 void FieldTrialList::AppendFieldTrialHandleIfNeeded( |
| 669 HandlesToInheritVector* handles) { | 683 HandlesToInheritVector* handles) { |
| 670 if (!global_) | 684 if (!global_) |
| 671 return; | 685 return; |
| 672 if (kUseSharedMemoryForFieldTrials) { | 686 if (kUseSharedMemoryForFieldTrials) { |
| 673 InstantiateFieldTrialAllocatorIfNeeded(); | 687 InstantiateFieldTrialAllocatorIfNeeded(); |
| 674 if (global_->readonly_allocator_handle_) | 688 if (global_ && global_->readonly_allocator_handle_) |
|
Alexei Svitkine (slow)
2016/10/28 18:57:34
There's already an early return on line 684.
lawrencewu
2016/10/31 18:59:25
Fixed.
| |
| 675 handles->push_back(global_->readonly_allocator_handle_); | 689 handles->push_back(global_->readonly_allocator_handle_); |
| 676 } | 690 } |
| 677 } | 691 } |
| 678 #endif | 692 #endif |
| 679 | 693 |
| 680 // static | 694 // static |
| 681 void FieldTrialList::CopyFieldTrialStateToFlags( | 695 void FieldTrialList::CopyFieldTrialStateToFlags( |
| 682 const char* field_trial_handle_switch, | 696 const char* field_trial_handle_switch, |
| 683 CommandLine* cmd_line) { | 697 CommandLine* cmd_line) { |
| 684 #if defined(OS_WIN) | 698 #if defined(OS_WIN) |
| 685 // Use shared memory to pass the state if the feature is enabled, otherwise | 699 // Use shared memory to pass the state if the feature is enabled, otherwise |
| 686 // fallback to passing it via the command line as a string. | 700 // fallback to passing it via the command line as a string. |
| 687 if (kUseSharedMemoryForFieldTrials) { | 701 if (kUseSharedMemoryForFieldTrials) { |
| 688 InstantiateFieldTrialAllocatorIfNeeded(); | 702 InstantiateFieldTrialAllocatorIfNeeded(); |
| 689 // If the readonly handle didn't get duplicated properly, then fallback to | 703 // If the readonly handle didn't get duplicated properly, then fallback to |
| 690 // original behavior. | 704 // original behavior. |
| 691 if (!global_->readonly_allocator_handle_) { | 705 if (!global_ || !global_->readonly_allocator_handle_) { |
|
Alexei Svitkine (slow)
2016/10/28 18:57:34
Can we instead fix the browser test to have a Fiel
lawrencewu
2016/10/31 18:59:25
As we discussed, I moved the check for global to t
| |
| 692 AddForceFieldTrialsFlag(cmd_line); | 706 AddForceFieldTrialsFlag(cmd_line); |
| 693 return; | 707 return; |
| 694 } | 708 } |
| 695 | 709 |
| 696 // HANDLE is just typedef'd to void *. We basically cast the handle into an | 710 // HANDLE is just typedef'd to void *. We basically cast the handle into an |
| 697 // int (uintptr_t, to be exact), stringify the int, and pass it as a | 711 // int (uintptr_t, to be exact), stringify the int, and pass it as a |
| 698 // command-line flag. The child process will do the reverse conversions to | 712 // command-line flag. The child process will do the reverse conversions to |
| 699 // retrieve the handle. See http://stackoverflow.com/a/153077 | 713 // retrieve the handle. See http://stackoverflow.com/a/153077 |
| 700 auto uintptr_handle = | 714 auto uintptr_handle = |
| 701 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); | 715 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 } | 762 } |
| 749 | 763 |
| 750 // static | 764 // static |
| 751 void FieldTrialList::RemoveObserver(Observer* observer) { | 765 void FieldTrialList::RemoveObserver(Observer* observer) { |
| 752 if (!global_) | 766 if (!global_) |
| 753 return; | 767 return; |
| 754 global_->observer_list_->RemoveObserver(observer); | 768 global_->observer_list_->RemoveObserver(observer); |
| 755 } | 769 } |
| 756 | 770 |
| 757 // static | 771 // static |
| 758 void FieldTrialList::OnGroupFinalized(FieldTrial* field_trial) { | 772 void FieldTrialList::OnGroupFinalized(bool is_locked, FieldTrial* field_trial) { |
| 759 if (!global_) | 773 if (!global_) |
| 760 return; | 774 return; |
| 761 AutoLock auto_lock(global_->lock_); | 775 if (is_locked) { |
| 762 AddToAllocatorWhileLocked(field_trial); | 776 AddToAllocatorWhileLocked(field_trial); |
| 777 } else { | |
| 778 AutoLock auto_lock(global_->lock_); | |
| 779 AddToAllocatorWhileLocked(field_trial); | |
| 780 } | |
| 763 } | 781 } |
| 764 | 782 |
| 765 // static | 783 // static |
| 766 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { | 784 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { |
| 767 if (!global_) | 785 if (!global_) |
| 768 return; | 786 return; |
| 769 | 787 |
| 770 { | 788 { |
| 771 AutoLock auto_lock(global_->lock_); | 789 AutoLock auto_lock(global_->lock_); |
| 772 if (field_trial->group_reported_) | 790 if (field_trial->group_reported_) |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 return; | 962 return; |
| 945 } | 963 } |
| 946 AutoLock auto_lock(global_->lock_); | 964 AutoLock auto_lock(global_->lock_); |
| 947 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 965 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 948 trial->AddRef(); | 966 trial->AddRef(); |
| 949 trial->SetTrialRegistered(); | 967 trial->SetTrialRegistered(); |
| 950 global_->registered_[trial->trial_name()] = trial; | 968 global_->registered_[trial->trial_name()] = trial; |
| 951 } | 969 } |
| 952 | 970 |
| 953 } // namespace base | 971 } // namespace base |
| OLD | NEW |