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 10 matching lines...) Expand all Loading... |
21 namespace { | 21 namespace { |
22 | 22 |
23 // Pointer to the FeatureList instance singleton that was set via | 23 // Pointer to the FeatureList instance singleton that was set via |
24 // FeatureList::SetInstance(). Does not use base/memory/singleton.h in order to | 24 // FeatureList::SetInstance(). Does not use base/memory/singleton.h in order to |
25 // have more control over initialization timing. Leaky. | 25 // have more control over initialization timing. Leaky. |
26 FeatureList* g_instance = nullptr; | 26 FeatureList* g_instance = nullptr; |
27 | 27 |
28 // Tracks whether the FeatureList instance was initialized via an accessor. | 28 // Tracks whether the FeatureList instance was initialized via an accessor. |
29 bool g_initialized_from_accessor = false; | 29 bool g_initialized_from_accessor = false; |
30 | 30 |
31 const uint32_t kFeatureType = 0x06567CA6 + 1; // SHA1(FeatureEntry) v1 | |
32 | |
33 // An allocator entry for a feature in shared memory. The FeatureEntry is | 31 // An allocator entry for a feature in shared memory. The FeatureEntry is |
34 // followed by a base::Pickle object that contains the feature and trial name. | 32 // followed by a base::Pickle object that contains the feature and trial name. |
35 // Any changes to this structure requires a bump in kFeatureType defined above. | |
36 struct FeatureEntry { | 33 struct FeatureEntry { |
| 34 // SHA1(FeatureEntry): Increment this if structure changes! |
| 35 static constexpr uint32_t kPersistentTypeId = 0x06567CA6 + 1; |
| 36 |
37 // Expected size for 32/64-bit check. | 37 // Expected size for 32/64-bit check. |
38 static constexpr size_t kExpectedInstanceSize = 8; | 38 static constexpr size_t kExpectedInstanceSize = 8; |
39 | 39 |
40 // Specifies whether a feature override enables or disables the feature. Same | 40 // Specifies whether a feature override enables or disables the feature. Same |
41 // values as the OverrideState enum in feature_list.h | 41 // values as the OverrideState enum in feature_list.h |
42 uint32_t override_state; | 42 uint32_t override_state; |
43 | 43 |
44 // Size of the pickled structure, NOT the total size of this entry. | 44 // Size of the pickled structure, NOT the total size of this entry. |
45 uint32_t pickle_size; | 45 uint32_t pickle_size; |
46 | 46 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 RegisterOverridesFromCommandLine(enable_features, OVERRIDE_ENABLE_FEATURE); | 91 RegisterOverridesFromCommandLine(enable_features, OVERRIDE_ENABLE_FEATURE); |
92 | 92 |
93 initialized_from_command_line_ = true; | 93 initialized_from_command_line_ = true; |
94 } | 94 } |
95 | 95 |
96 void FeatureList::InitializeFromSharedMemory( | 96 void FeatureList::InitializeFromSharedMemory( |
97 PersistentMemoryAllocator* allocator) { | 97 PersistentMemoryAllocator* allocator) { |
98 DCHECK(!initialized_); | 98 DCHECK(!initialized_); |
99 | 99 |
100 PersistentMemoryAllocator::Iterator iter(allocator); | 100 PersistentMemoryAllocator::Iterator iter(allocator); |
101 | 101 const FeatureEntry* entry; |
102 PersistentMemoryAllocator::Reference ref; | 102 while ((entry = iter.GetNextOfObject<FeatureEntry>()) != nullptr) { |
103 while ((ref = iter.GetNextOfType(kFeatureType)) != | |
104 PersistentMemoryAllocator::kReferenceNull) { | |
105 const FeatureEntry* entry = | |
106 allocator->GetAsObject<const FeatureEntry>(ref, kFeatureType); | |
107 | |
108 OverrideState override_state = | 103 OverrideState override_state = |
109 static_cast<OverrideState>(entry->override_state); | 104 static_cast<OverrideState>(entry->override_state); |
110 | 105 |
111 StringPiece feature_name; | 106 StringPiece feature_name; |
112 StringPiece trial_name; | 107 StringPiece trial_name; |
113 if (!entry->GetFeatureAndTrialName(&feature_name, &trial_name)) | 108 if (!entry->GetFeatureAndTrialName(&feature_name, &trial_name)) |
114 continue; | 109 continue; |
115 | 110 |
116 FieldTrial* trial = FieldTrialList::Find(trial_name.as_string()); | 111 FieldTrial* trial = FieldTrialList::Find(trial_name.as_string()); |
117 RegisterOverride(feature_name, override_state, trial); | 112 RegisterOverride(feature_name, override_state, trial); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 void FeatureList::AddFeaturesToAllocator(PersistentMemoryAllocator* allocator) { | 158 void FeatureList::AddFeaturesToAllocator(PersistentMemoryAllocator* allocator) { |
164 DCHECK(initialized_); | 159 DCHECK(initialized_); |
165 | 160 |
166 for (const auto& override : overrides_) { | 161 for (const auto& override : overrides_) { |
167 Pickle pickle; | 162 Pickle pickle; |
168 pickle.WriteString(override.first); | 163 pickle.WriteString(override.first); |
169 if (override.second.field_trial) | 164 if (override.second.field_trial) |
170 pickle.WriteString(override.second.field_trial->trial_name()); | 165 pickle.WriteString(override.second.field_trial->trial_name()); |
171 | 166 |
172 size_t total_size = sizeof(FeatureEntry) + pickle.size(); | 167 size_t total_size = sizeof(FeatureEntry) + pickle.size(); |
173 PersistentMemoryAllocator::Reference ref = | 168 FeatureEntry* entry = allocator->AllocateObject<FeatureEntry>(total_size); |
174 allocator->Allocate(total_size, kFeatureType); | 169 if (!entry) |
175 if (!ref) | |
176 return; | 170 return; |
177 | 171 |
178 FeatureEntry* entry = | |
179 allocator->GetAsObject<FeatureEntry>(ref, kFeatureType); | |
180 entry->override_state = override.second.overridden_state; | 172 entry->override_state = override.second.overridden_state; |
181 entry->pickle_size = pickle.size(); | 173 entry->pickle_size = pickle.size(); |
182 | 174 |
183 char* dst = reinterpret_cast<char*>(entry) + sizeof(FeatureEntry); | 175 char* dst = reinterpret_cast<char*>(entry) + sizeof(FeatureEntry); |
184 memcpy(dst, pickle.data(), pickle.size()); | 176 memcpy(dst, pickle.data(), pickle.size()); |
185 | 177 |
186 allocator->MakeIterable(ref); | 178 allocator->MakeIterable(entry); |
187 } | 179 } |
188 } | 180 } |
189 | 181 |
190 void FeatureList::GetFeatureOverrides(std::string* enable_overrides, | 182 void FeatureList::GetFeatureOverrides(std::string* enable_overrides, |
191 std::string* disable_overrides) { | 183 std::string* disable_overrides) { |
192 DCHECK(initialized_); | 184 DCHECK(initialized_); |
193 | 185 |
194 enable_overrides->clear(); | 186 enable_overrides->clear(); |
195 disable_overrides->clear(); | 187 disable_overrides->clear(); |
196 | 188 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 return it->second == &feature; | 388 return it->second == &feature; |
397 } | 389 } |
398 | 390 |
399 FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state, | 391 FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state, |
400 FieldTrial* field_trial) | 392 FieldTrial* field_trial) |
401 : overridden_state(overridden_state), | 393 : overridden_state(overridden_state), |
402 field_trial(field_trial), | 394 field_trial(field_trial), |
403 overridden_by_field_trial(field_trial != nullptr) {} | 395 overridden_by_field_trial(field_trial != nullptr) {} |
404 | 396 |
405 } // namespace base | 397 } // namespace base |
OLD | NEW |