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 | 8 |
9 #include "base/build_time.h" | 9 #include "base/build_time.h" |
| 10 #include "base/lazy_instance.h" |
10 #include "base/logging.h" | 11 #include "base/logging.h" |
11 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
13 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
14 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
15 | 16 |
16 namespace base { | 17 namespace base { |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 void CheckTrialGroup(const std::string& trial_name, | 109 void CheckTrialGroup(const std::string& trial_name, |
109 const std::string& trial_group, | 110 const std::string& trial_group, |
110 std::map<std::string, std::string>* seen_states) { | 111 std::map<std::string, std::string>* seen_states) { |
111 if (ContainsKey(*seen_states, trial_name)) { | 112 if (ContainsKey(*seen_states, trial_name)) { |
112 CHECK_EQ((*seen_states)[trial_name], trial_group) << trial_name; | 113 CHECK_EQ((*seen_states)[trial_name], trial_group) << trial_name; |
113 } else { | 114 } else { |
114 (*seen_states)[trial_name] = trial_group; | 115 (*seen_states)[trial_name] = trial_group; |
115 } | 116 } |
116 } | 117 } |
117 | 118 |
| 119 // A second copy of FieldTrialList::seen_states_ that is meant to outlive the |
| 120 // FieldTrialList object to determine if the inconsistency happens because there |
| 121 // might be multiple FieldTrialList objects. |
| 122 // TODO(asvitkine): Remove when crbug.com/359406 is resolved. |
| 123 base::LazyInstance<std::map<std::string, std::string>>::Leaky g_seen_states = |
| 124 LAZY_INSTANCE_INITIALIZER; |
| 125 |
| 126 // Tracks whether |g_seen_states| is used. Defaults to false, because unit tests |
| 127 // will create multiple FieldTrialList instances. |
| 128 bool g_use_global_check_states = false; |
| 129 |
118 } // namespace | 130 } // namespace |
119 | 131 |
120 // statics | 132 // statics |
121 const int FieldTrial::kNotFinalized = -1; | 133 const int FieldTrial::kNotFinalized = -1; |
122 const int FieldTrial::kDefaultGroupNumber = 0; | 134 const int FieldTrial::kDefaultGroupNumber = 0; |
123 bool FieldTrial::enable_benchmarking_ = false; | 135 bool FieldTrial::enable_benchmarking_ = false; |
124 | 136 |
125 int FieldTrialList::kNoExpirationYear = 0; | 137 int FieldTrialList::kNoExpirationYear = 0; |
126 | 138 |
127 //------------------------------------------------------------------------------ | 139 //------------------------------------------------------------------------------ |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 while (!registered_.empty()) { | 343 while (!registered_.empty()) { |
332 RegistrationMap::iterator it = registered_.begin(); | 344 RegistrationMap::iterator it = registered_.begin(); |
333 it->second->Release(); | 345 it->second->Release(); |
334 registered_.erase(it->first); | 346 registered_.erase(it->first); |
335 } | 347 } |
336 DCHECK_EQ(this, global_); | 348 DCHECK_EQ(this, global_); |
337 global_ = NULL; | 349 global_ = NULL; |
338 } | 350 } |
339 | 351 |
340 // static | 352 // static |
| 353 void FieldTrialList::EnableGlobalStateChecks() { |
| 354 CHECK(!g_use_global_check_states); |
| 355 g_use_global_check_states = true; |
| 356 } |
| 357 |
| 358 // static |
341 FieldTrial* FieldTrialList::FactoryGetFieldTrial( | 359 FieldTrial* FieldTrialList::FactoryGetFieldTrial( |
342 const std::string& trial_name, | 360 const std::string& trial_name, |
343 FieldTrial::Probability total_probability, | 361 FieldTrial::Probability total_probability, |
344 const std::string& default_group_name, | 362 const std::string& default_group_name, |
345 const int year, | 363 const int year, |
346 const int month, | 364 const int month, |
347 const int day_of_month, | 365 const int day_of_month, |
348 FieldTrial::RandomizationType randomization_type, | 366 FieldTrial::RandomizationType randomization_type, |
349 int* default_group_number) { | 367 int* default_group_number) { |
350 return FactoryGetFieldTrialWithRandomizationSeed( | 368 return FactoryGetFieldTrialWithRandomizationSeed( |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 trial.trial_name.find(kPersistentStringSeparator)); | 500 trial.trial_name.find(kPersistentStringSeparator)); |
483 DCHECK_EQ(std::string::npos, | 501 DCHECK_EQ(std::string::npos, |
484 trial.group_name.find(kPersistentStringSeparator)); | 502 trial.group_name.find(kPersistentStringSeparator)); |
485 if (trial.activated) | 503 if (trial.activated) |
486 output->append(1, kActivationMarker); | 504 output->append(1, kActivationMarker); |
487 trial.trial_name.AppendToString(output); | 505 trial.trial_name.AppendToString(output); |
488 output->append(1, kPersistentStringSeparator); | 506 output->append(1, kPersistentStringSeparator); |
489 trial.group_name.AppendToString(output); | 507 trial.group_name.AppendToString(output); |
490 output->append(1, kPersistentStringSeparator); | 508 output->append(1, kPersistentStringSeparator); |
491 | 509 |
| 510 // TODO(asvitkine): Remove these when http://crbug.com/359406 is fixed. |
492 CheckTrialGroup(trial.trial_name.as_string(), trial.group_name.as_string(), | 511 CheckTrialGroup(trial.trial_name.as_string(), trial.group_name.as_string(), |
493 &global_->seen_states_); | 512 &global_->seen_states_); |
| 513 if (g_use_global_check_states) { |
| 514 CheckTrialGroup(trial.trial_name.as_string(), |
| 515 trial.group_name.as_string(), &g_seen_states.Get()); |
| 516 } |
494 } | 517 } |
495 } | 518 } |
496 | 519 |
497 // static | 520 // static |
498 void FieldTrialList::GetActiveFieldTrialGroups( | 521 void FieldTrialList::GetActiveFieldTrialGroups( |
499 FieldTrial::ActiveGroups* active_groups) { | 522 FieldTrial::ActiveGroups* active_groups) { |
500 DCHECK(active_groups->empty()); | 523 DCHECK(active_groups->empty()); |
501 if (!global_) | 524 if (!global_) |
502 return; | 525 return; |
503 AutoLock auto_lock(global_->lock_); | 526 AutoLock auto_lock(global_->lock_); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 { | 631 { |
609 AutoLock auto_lock(global_->lock_); | 632 AutoLock auto_lock(global_->lock_); |
610 if (field_trial->group_reported_) | 633 if (field_trial->group_reported_) |
611 return; | 634 return; |
612 field_trial->group_reported_ = true; | 635 field_trial->group_reported_ = true; |
613 } | 636 } |
614 | 637 |
615 if (!field_trial->enable_field_trial_) | 638 if (!field_trial->enable_field_trial_) |
616 return; | 639 return; |
617 | 640 |
| 641 // TODO(asvitkine): Remove this block when http://crbug.com/359406 is fixed. |
618 { | 642 { |
619 AutoLock auto_lock(global_->lock_); | 643 AutoLock auto_lock(global_->lock_); |
620 CheckTrialGroup(field_trial->trial_name(), | 644 CheckTrialGroup(field_trial->trial_name(), |
621 field_trial->group_name_internal(), &global_->seen_states_); | 645 field_trial->group_name_internal(), &global_->seen_states_); |
| 646 if (g_use_global_check_states) { |
| 647 CheckTrialGroup(field_trial->trial_name(), |
| 648 field_trial->group_name_internal(), &g_seen_states.Get()); |
| 649 } |
622 } | 650 } |
623 global_->observer_list_->Notify( | 651 global_->observer_list_->Notify( |
624 FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized, | 652 FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized, |
625 field_trial->trial_name(), field_trial->group_name_internal()); | 653 field_trial->trial_name(), field_trial->group_name_internal()); |
626 } | 654 } |
627 | 655 |
628 // static | 656 // static |
629 size_t FieldTrialList::GetFieldTrialCount() { | 657 size_t FieldTrialList::GetFieldTrialCount() { |
630 if (!global_) | 658 if (!global_) |
631 return 0; | 659 return 0; |
(...skipping 26 matching lines...) Expand all Loading... |
658 return; | 686 return; |
659 } | 687 } |
660 AutoLock auto_lock(global_->lock_); | 688 AutoLock auto_lock(global_->lock_); |
661 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 689 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
662 trial->AddRef(); | 690 trial->AddRef(); |
663 trial->SetTrialRegistered(); | 691 trial->SetTrialRegistered(); |
664 global_->registered_[trial->trial_name()] = trial; | 692 global_->registered_[trial->trial_name()] = trial; |
665 } | 693 } |
666 | 694 |
667 } // namespace base | 695 } // namespace base |
OLD | NEW |