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 |