Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/feature_list.h" | 5 #include "base/feature_list.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 // serialization. This function checks that the strings are ASCII (since they | 28 // serialization. This function checks that the strings are ASCII (since they |
| 29 // are used in command-line API functions that require ASCII) and whether there | 29 // are used in command-line API functions that require ASCII) and whether there |
| 30 // are any reserved characters present, returning true if the string is valid. | 30 // are any reserved characters present, returning true if the string is valid. |
| 31 // Only called in DCHECKs. | 31 // Only called in DCHECKs. |
| 32 bool IsValidFeatureOrFieldTrialName(const std::string& name) { | 32 bool IsValidFeatureOrFieldTrialName(const std::string& name) { |
| 33 return IsStringASCII(name) && name.find_first_of(",<*") == std::string::npos; | 33 return IsStringASCII(name) && name.find_first_of(",<*") == std::string::npos; |
| 34 } | 34 } |
| 35 | 35 |
| 36 } // namespace | 36 } // namespace |
| 37 | 37 |
| 38 FeatureList::FeatureList() | 38 FeatureList::FeatureList() {} |
| 39 : initialized_(false), | |
| 40 initialized_from_command_line_(false) { | |
| 41 } | |
| 42 | 39 |
| 43 FeatureList::~FeatureList() {} | 40 FeatureList::~FeatureList() {} |
| 44 | 41 |
| 45 void FeatureList::InitializeFromCommandLine( | 42 void FeatureList::InitializeFromCommandLine( |
| 46 const std::string& enable_features, | 43 const std::string& enable_features, |
| 47 const std::string& disable_features) { | 44 const std::string& disable_features) { |
| 48 DCHECK(!initialized_); | 45 DCHECK(!initialized_); |
| 49 | 46 |
| 50 // Process disabled features first, so that disabled ones take precedence over | 47 // Process disabled features first, so that disabled ones take precedence over |
| 51 // enabled ones (since RegisterOverride() uses insert()). | 48 // enabled ones (since RegisterOverride() uses insert()). |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 target_list->append(entry.first); | 123 target_list->append(entry.first); |
| 127 if (entry.second.field_trial) { | 124 if (entry.second.field_trial) { |
| 128 target_list->push_back('<'); | 125 target_list->push_back('<'); |
| 129 target_list->append(entry.second.field_trial->trial_name()); | 126 target_list->append(entry.second.field_trial->trial_name()); |
| 130 } | 127 } |
| 131 } | 128 } |
| 132 } | 129 } |
| 133 | 130 |
| 134 // static | 131 // static |
| 135 bool FeatureList::IsEnabled(const Feature& feature) { | 132 bool FeatureList::IsEnabled(const Feature& feature) { |
| 133 if (!GetInstance()) { | |
| 134 CHECK(InitializeInstance(std::string(), std::string())); | |
|
Sergey Ulanov
2016/07/01 21:36:10
As discussed offline I think the problem here is t
Alexei Svitkine (slow)
2016/07/04 15:50:06
I don't think we want this class to use base::Sing
Sergey Ulanov
2016/07/04 16:52:53
base::Singleton<>::get() doesn't have any locks. I
Alexei Svitkine (slow)
2016/07/04 16:55:55
Still, that's more overhead than we have currently
joedow
2016/07/05 21:05:56
My concern with the feedback above is that I don't
Alexei Svitkine (slow)
2016/07/05 21:11:34
That's a good point. Returning default state SGTM.
| |
| 135 GetInstance()->initialized_from_accessor_ = true; | |
| 136 } | |
| 136 return GetInstance()->IsFeatureEnabled(feature); | 137 return GetInstance()->IsFeatureEnabled(feature); |
| 137 } | 138 } |
| 138 | 139 |
| 139 // static | 140 // static |
| 140 FieldTrial* FeatureList::GetFieldTrial(const Feature& feature) { | 141 FieldTrial* FeatureList::GetFieldTrial(const Feature& feature) { |
| 142 if (!GetInstance()) { | |
| 143 CHECK(InitializeInstance(std::string(), std::string())); | |
| 144 GetInstance()->initialized_from_accessor_ = true; | |
| 145 } | |
| 141 return GetInstance()->GetAssociatedFieldTrial(feature); | 146 return GetInstance()->GetAssociatedFieldTrial(feature); |
| 142 } | 147 } |
| 143 | 148 |
| 144 // static | 149 // static |
| 145 std::vector<std::string> FeatureList::SplitFeatureListString( | 150 std::vector<std::string> FeatureList::SplitFeatureListString( |
| 146 const std::string& input) { | 151 const std::string& input) { |
| 147 return SplitString(input, ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); | 152 return SplitString(input, ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); |
| 148 } | 153 } |
| 149 | 154 |
| 150 // static | 155 // static |
| 151 bool FeatureList::InitializeInstance(const std::string& enable_features, | 156 bool FeatureList::InitializeInstance(const std::string& enable_features, |
| 152 const std::string& disable_features) { | 157 const std::string& disable_features) { |
| 153 // We want to initialize a new instance here to support command-line features | 158 // We want to initialize a new instance here to support command-line features |
| 154 // in testing better. For example, we initialize a dummy instance in | 159 // in testing better. For example, we initialize a dummy instance in |
| 155 // base/test/test_suite.cc, and override it in content/browser/ | 160 // base/test/test_suite.cc, and override it in content/browser/ |
| 156 // browser_main_loop.cc. | 161 // browser_main_loop.cc. |
| 157 // On the other hand, we want to avoid re-initialization from command line. | 162 // On the other hand, we want to avoid re-initialization from command line. |
| 158 // For example, we initialize an instance in chrome/browser/ | 163 // For example, we initialize an instance in chrome/browser/ |
| 159 // chrome_browser_main.cc and do not override it in content/browser/ | 164 // chrome_browser_main.cc and do not override it in content/browser/ |
| 160 // browser_main_loop.cc. | 165 // browser_main_loop.cc. |
| 166 // If the singleton was previously initialized from within an accessor, we | |
| 167 // want to prevent callers from reinitializing the singleton and masking the | |
| 168 // access call(s) which likely returned incorrect information. | |
| 161 bool instance_existed_before = false; | 169 bool instance_existed_before = false; |
| 162 if (g_instance) { | 170 if (g_instance) { |
| 171 DCHECK(!g_instance->initialized_from_accessor_); | |
| 163 if (g_instance->initialized_from_command_line_) | 172 if (g_instance->initialized_from_command_line_) |
| 164 return false; | 173 return false; |
| 165 | 174 |
| 166 delete g_instance; | 175 delete g_instance; |
| 167 g_instance = nullptr; | 176 g_instance = nullptr; |
| 168 instance_existed_before = true; | 177 instance_existed_before = true; |
| 169 } | 178 } |
| 170 | 179 |
| 171 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); | 180 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 172 feature_list->InitializeFromCommandLine(enable_features, disable_features); | 181 feature_list->InitializeFromCommandLine(enable_features, disable_features); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 return it->second == &feature; | 297 return it->second == &feature; |
| 289 } | 298 } |
| 290 | 299 |
| 291 FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state, | 300 FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state, |
| 292 FieldTrial* field_trial) | 301 FieldTrial* field_trial) |
| 293 : overridden_state(overridden_state), | 302 : overridden_state(overridden_state), |
| 294 field_trial(field_trial), | 303 field_trial(field_trial), |
| 295 overridden_by_field_trial(field_trial != nullptr) {} | 304 overridden_by_field_trial(field_trial != nullptr) {} |
| 296 | 305 |
| 297 } // namespace base | 306 } // namespace base |
| OLD | NEW |