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" |
| 11 #include "base/build_time.h" | 11 #include "base/build_time.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/debug/activity_tracker.h" | 13 #include "base/debug/activity_tracker.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/field_trial_param_associator.h" | 15 #include "base/metrics/field_trial_param_associator.h" |
| 16 #include "base/process/memory.h" | 16 #include "base/process/memory.h" |
| 17 #include "base/rand_util.h" | 17 #include "base/rand_util.h" |
| 18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/strings/string_split.h" | |
| 19 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
| 20 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
| 21 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 22 #include "base/unguessable_token.h" | 23 #include "base/unguessable_token.h" |
| 23 | 24 |
| 24 // On POSIX, the fd is shared using the mapping in GlobalDescriptors. | 25 // On POSIX, the fd is shared using the mapping in GlobalDescriptors. |
| 25 #if defined(OS_POSIX) && !defined(OS_NACL) | 26 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 26 #include "base/posix/global_descriptors.h" | 27 #include "base/posix/global_descriptors.h" |
| 27 #endif | 28 #endif |
| 28 | 29 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 cmd_line->AppendSwitchASCII(disable_features_switch, disabled_features); | 202 cmd_line->AppendSwitchASCII(disable_features_switch, disabled_features); |
| 202 | 203 |
| 203 std::string field_trial_states; | 204 std::string field_trial_states; |
| 204 FieldTrialList::AllStatesToString(&field_trial_states); | 205 FieldTrialList::AllStatesToString(&field_trial_states); |
| 205 if (!field_trial_states.empty()) { | 206 if (!field_trial_states.empty()) { |
| 206 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials, | 207 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials, |
| 207 field_trial_states); | 208 field_trial_states); |
| 208 } | 209 } |
| 209 } | 210 } |
| 210 | 211 |
| 211 #if defined(OS_WIN) | |
| 212 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { | |
| 213 HANDLE src = allocator->shared_memory()->handle().GetHandle(); | |
| 214 ProcessHandle process = GetCurrentProcess(); | |
| 215 DWORD access = SECTION_MAP_READ | SECTION_QUERY; | |
| 216 HANDLE dst; | |
| 217 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) | |
| 218 return kInvalidPlatformFile; | |
| 219 return dst; | |
| 220 } | |
| 221 #endif | |
| 222 | |
| 223 #if defined(OS_POSIX) && !defined(OS_NACL) | |
| 224 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { | |
| 225 SharedMemoryHandle handle = allocator->shared_memory()->GetReadOnlyHandle(); | |
| 226 return SharedMemory::GetFdFromSharedMemoryHandle(handle); | |
| 227 } | |
| 228 #endif | |
| 229 | |
| 230 void OnOutOfMemory(size_t size) { | 212 void OnOutOfMemory(size_t size) { |
| 231 #if defined(OS_NACL) | 213 #if defined(OS_NACL) |
| 232 NOTREACHED(); | 214 NOTREACHED(); |
| 233 #else | 215 #else |
| 234 TerminateBecauseOutOfMemory(size); | 216 TerminateBecauseOutOfMemory(size); |
| 235 #endif | 217 #endif |
| 236 } | 218 } |
| 237 | 219 |
| 220 #if !defined(OS_NACL) | |
| 221 // Returns whether the operation succeeded. | |
| 222 bool DeserializeGUIDFromStringPieces(const base::StringPiece& first, | |
|
Alexei Svitkine (slow)
2017/05/09 14:47:40
Nit: StringPiece is meant to be passed by value -
erikchen
2017/05/09 16:53:52
Done.
| |
| 223 const base::StringPiece& second, | |
| 224 base::UnguessableToken* guid) { | |
| 225 uint64_t high = 0; | |
| 226 uint64_t low = 0; | |
| 227 if (!base::StringToUint64(first, &high) || | |
| 228 !base::StringToUint64(second, &low)) { | |
| 229 return false; | |
| 230 } | |
| 231 | |
| 232 *guid = base::UnguessableToken::Deserialize(high, low); | |
| 233 return true; | |
| 234 } | |
| 235 #endif | |
| 236 | |
| 238 } // namespace | 237 } // namespace |
| 239 | 238 |
| 240 // statics | 239 // statics |
| 241 const int FieldTrial::kNotFinalized = -1; | 240 const int FieldTrial::kNotFinalized = -1; |
| 242 const int FieldTrial::kDefaultGroupNumber = 0; | 241 const int FieldTrial::kDefaultGroupNumber = 0; |
| 243 bool FieldTrial::enable_benchmarking_ = false; | 242 bool FieldTrial::enable_benchmarking_ = false; |
| 244 | 243 |
| 245 int FieldTrialList::kNoExpirationYear = 0; | 244 int FieldTrialList::kNoExpirationYear = 0; |
| 246 | 245 |
| 247 //------------------------------------------------------------------------------ | 246 //------------------------------------------------------------------------------ |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 774 | 773 |
| 775 // static | 774 // static |
| 776 void FieldTrialList::CreateTrialsFromCommandLine( | 775 void FieldTrialList::CreateTrialsFromCommandLine( |
| 777 const CommandLine& cmd_line, | 776 const CommandLine& cmd_line, |
| 778 const char* field_trial_handle_switch, | 777 const char* field_trial_handle_switch, |
| 779 int fd_key) { | 778 int fd_key) { |
| 780 global_->create_trials_from_command_line_called_ = true; | 779 global_->create_trials_from_command_line_called_ = true; |
| 781 | 780 |
| 782 #if defined(OS_WIN) | 781 #if defined(OS_WIN) |
| 783 if (cmd_line.HasSwitch(field_trial_handle_switch)) { | 782 if (cmd_line.HasSwitch(field_trial_handle_switch)) { |
| 784 std::string handle_switch = | 783 std::string switch_value = |
| 785 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); | 784 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); |
| 786 bool result = CreateTrialsFromHandleSwitch(handle_switch); | 785 bool result = CreateTrialsFromSwitchValue(switch_value); |
| 787 DCHECK(result); | 786 DCHECK(result); |
| 788 } | 787 } |
| 789 #endif | 788 #endif |
| 790 | 789 |
| 791 #if defined(OS_POSIX) && !defined(OS_NACL) | 790 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 792 // On POSIX, we check if the handle is valid by seeing if the browser process | 791 // On POSIX, we check if the handle is valid by seeing if the browser process |
| 793 // sent over the switch (we don't care about the value). Invalid handles | 792 // sent over the switch (we don't care about the value). Invalid handles |
| 794 // occur in some browser tests which don't initialize the allocator. | 793 // occur in some browser tests which don't initialize the allocator. |
| 795 if (cmd_line.HasSwitch(field_trial_handle_switch)) { | 794 if (cmd_line.HasSwitch(field_trial_handle_switch)) { |
| 796 bool result = CreateTrialsFromDescriptor(fd_key); | 795 std::string switch_value = |
| 796 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); | |
| 797 bool result = CreateTrialsFromDescriptor(fd_key, switch_value); | |
| 797 DCHECK(result); | 798 DCHECK(result); |
| 798 } | 799 } |
| 799 #endif | 800 #endif |
| 800 | 801 |
| 801 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { | 802 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { |
| 802 bool result = FieldTrialList::CreateTrialsFromString( | 803 bool result = FieldTrialList::CreateTrialsFromString( |
| 803 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), | 804 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), |
| 804 std::set<std::string>()); | 805 std::set<std::string>()); |
| 805 DCHECK(result); | 806 DCHECK(result); |
| 806 } | 807 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 825 } | 826 } |
| 826 | 827 |
| 827 #if defined(OS_WIN) | 828 #if defined(OS_WIN) |
| 828 // static | 829 // static |
| 829 void FieldTrialList::AppendFieldTrialHandleIfNeeded( | 830 void FieldTrialList::AppendFieldTrialHandleIfNeeded( |
| 830 HandlesToInheritVector* handles) { | 831 HandlesToInheritVector* handles) { |
| 831 if (!global_) | 832 if (!global_) |
| 832 return; | 833 return; |
| 833 if (kUseSharedMemoryForFieldTrials) { | 834 if (kUseSharedMemoryForFieldTrials) { |
| 834 InstantiateFieldTrialAllocatorIfNeeded(); | 835 InstantiateFieldTrialAllocatorIfNeeded(); |
| 835 if (global_->readonly_allocator_handle_) | 836 if (global_->readonly_allocator_handle_.IsValid()) |
| 836 handles->push_back(global_->readonly_allocator_handle_); | 837 handles->push_back(global_->readonly_allocator_handle_.GetHandle()); |
| 837 } | 838 } |
| 838 } | 839 } |
| 839 #endif | 840 #endif |
| 840 | 841 |
| 841 #if defined(OS_POSIX) && !defined(OS_NACL) | 842 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 842 // static | 843 // static |
| 843 int FieldTrialList::GetFieldTrialHandle() { | 844 SharedMemoryHandle FieldTrialList::GetFieldTrialHandle() { |
| 844 if (global_ && kUseSharedMemoryForFieldTrials) { | 845 if (global_ && kUseSharedMemoryForFieldTrials) { |
| 845 InstantiateFieldTrialAllocatorIfNeeded(); | 846 InstantiateFieldTrialAllocatorIfNeeded(); |
| 846 // We check for an invalid handle where this gets called. | 847 // We check for an invalid handle where this gets called. |
| 847 return global_->readonly_allocator_handle_; | 848 return global_->readonly_allocator_handle_; |
| 848 } | 849 } |
| 849 return kInvalidPlatformFile; | 850 return SharedMemoryHandle(); |
| 850 } | 851 } |
| 851 #endif | 852 #endif |
| 852 | 853 |
| 853 // static | 854 // static |
| 854 void FieldTrialList::CopyFieldTrialStateToFlags( | 855 void FieldTrialList::CopyFieldTrialStateToFlags( |
| 855 const char* field_trial_handle_switch, | 856 const char* field_trial_handle_switch, |
| 856 const char* enable_features_switch, | 857 const char* enable_features_switch, |
| 857 const char* disable_features_switch, | 858 const char* disable_features_switch, |
| 858 CommandLine* cmd_line) { | 859 CommandLine* cmd_line) { |
| 859 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, | 860 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, |
| 860 // content browser tests currently don't create a FieldTrialList because they | 861 // content browser tests currently don't create a FieldTrialList because they |
| 861 // don't run ChromeBrowserMainParts code where it's done for Chrome. | 862 // don't run ChromeBrowserMainParts code where it's done for Chrome. |
| 862 // Some tests depend on the enable and disable features flag switch, though, | 863 // Some tests depend on the enable and disable features flag switch, though, |
| 863 // so we can still add those even though AllStatesToString() will be a no-op. | 864 // so we can still add those even though AllStatesToString() will be a no-op. |
| 864 if (!global_) { | 865 if (!global_) { |
| 865 AddFeatureAndFieldTrialFlags(enable_features_switch, | 866 AddFeatureAndFieldTrialFlags(enable_features_switch, |
| 866 disable_features_switch, cmd_line); | 867 disable_features_switch, cmd_line); |
| 867 return; | 868 return; |
| 868 } | 869 } |
| 869 | 870 |
| 870 // Use shared memory to pass the state if the feature is enabled, otherwise | 871 // Use shared memory to pass the state if the feature is enabled, otherwise |
| 871 // fallback to passing it via the command line as a string. | 872 // fallback to passing it via the command line as a string. |
| 872 if (kUseSharedMemoryForFieldTrials) { | 873 if (kUseSharedMemoryForFieldTrials) { |
| 873 InstantiateFieldTrialAllocatorIfNeeded(); | 874 InstantiateFieldTrialAllocatorIfNeeded(); |
| 874 // If the readonly handle didn't get duplicated properly, then fallback to | 875 // If the readonly handle didn't get duplicated properly, then fallback to |
| 875 // original behavior. | 876 // original behavior. |
| 876 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { | 877 if (!global_->readonly_allocator_handle_.IsValid()) { |
| 877 AddFeatureAndFieldTrialFlags(enable_features_switch, | 878 AddFeatureAndFieldTrialFlags(enable_features_switch, |
| 878 disable_features_switch, cmd_line); | 879 disable_features_switch, cmd_line); |
| 879 return; | 880 return; |
| 880 } | 881 } |
| 881 | 882 |
| 882 global_->field_trial_allocator_->UpdateTrackingHistograms(); | 883 global_->field_trial_allocator_->UpdateTrackingHistograms(); |
| 883 | 884 std::string switch_value = SerializeSharedMemoryHandleMetadata( |
| 884 #if defined(OS_WIN) | 885 global_->readonly_allocator_handle_); |
| 885 // We need to pass a named anonymous handle to shared memory over the | 886 cmd_line->AppendSwitchASCII(field_trial_handle_switch, switch_value); |
| 886 // command line on Windows, since the child doesn't know which of the | |
| 887 // handles it inherited it should open. | |
| 888 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We | |
| 889 // basically cast the handle into an int (uintptr_t, to be exact), stringify | |
| 890 // the int, and pass it as a command-line flag. The child process will do | |
| 891 // the reverse conversions to retrieve the handle. See | |
| 892 // http://stackoverflow.com/a/153077 | |
| 893 auto uintptr_handle = | |
| 894 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); | |
| 895 std::string field_trial_handle = std::to_string(uintptr_handle); | |
| 896 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); | |
| 897 #elif defined(OS_POSIX) | |
| 898 // On POSIX, we dup the fd into a fixed fd kFieldTrialDescriptor, so we | |
| 899 // don't have to pass over the handle (it's not even the right handle | |
| 900 // anyways). But some browser tests don't create the allocator, so we need | |
| 901 // to be able to distinguish valid and invalid handles. We do that by just | |
| 902 // checking that the flag is set with a dummy value. | |
| 903 cmd_line->AppendSwitchASCII(field_trial_handle_switch, "1"); | |
| 904 #else | |
| 905 #error Unsupported OS | |
| 906 #endif | |
| 907 return; | 887 return; |
| 908 } | 888 } |
| 909 | 889 |
| 910 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch, | 890 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch, |
| 911 cmd_line); | 891 cmd_line); |
| 912 } | 892 } |
| 913 | 893 |
| 914 // static | 894 // static |
| 915 FieldTrial* FieldTrialList::CreateFieldTrial( | 895 FieldTrial* FieldTrialList::CreateFieldTrial( |
| 916 const std::string& name, | 896 const std::string& name, |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1125 std::vector<const FieldTrial::FieldTrialEntry*> entries; | 1105 std::vector<const FieldTrial::FieldTrialEntry*> entries; |
| 1126 FieldTrialAllocator::Iterator iter(&allocator); | 1106 FieldTrialAllocator::Iterator iter(&allocator); |
| 1127 const FieldTrial::FieldTrialEntry* entry; | 1107 const FieldTrial::FieldTrialEntry* entry; |
| 1128 while ((entry = iter.GetNextOfObject<FieldTrial::FieldTrialEntry>()) != | 1108 while ((entry = iter.GetNextOfObject<FieldTrial::FieldTrialEntry>()) != |
| 1129 nullptr) { | 1109 nullptr) { |
| 1130 entries.push_back(entry); | 1110 entries.push_back(entry); |
| 1131 } | 1111 } |
| 1132 return entries; | 1112 return entries; |
| 1133 } | 1113 } |
| 1134 | 1114 |
| 1115 // static | |
| 1116 std::string FieldTrialList::SerializeSharedMemoryHandleMetadata( | |
| 1117 const SharedMemoryHandle& shm) { | |
| 1118 std::stringstream ss; | |
| 1119 #if defined(OS_WIN) | |
| 1120 // Tell the child process the name of the inherited HANDLE. | |
| 1121 uintptr_t uintptr_handle = reinterpret_cast<uintptr_t>(shm.GetHandle()); | |
| 1122 ss << uintptr_handle << ","; | |
| 1123 #elif !defined(OS_POSIX) | |
| 1124 #error Unsupported OS | |
| 1125 #endif | |
| 1126 | |
| 1127 base::UnguessableToken guid = shm.GetGUID(); | |
| 1128 ss << guid.GetHighForSerialization() << "," << guid.GetLowForSerialization(); | |
| 1129 return ss.str(); | |
| 1130 } | |
| 1131 | |
| 1135 #if defined(OS_WIN) | 1132 #if defined(OS_WIN) |
| 1136 // static | 1133 // static |
| 1137 bool FieldTrialList::CreateTrialsFromHandleSwitch( | 1134 SharedMemoryHandle FieldTrialList::DeserializeSharedMemoryHandleMetadata( |
| 1138 const std::string& handle_switch) { | 1135 const std::string& switch_value) { |
| 1139 int field_trial_handle = std::stoi(handle_switch); | 1136 std::vector<base::StringPiece> tokens = base::SplitStringPiece( |
| 1137 switch_value, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 1138 | |
| 1139 if (tokens.size() != 3) | |
| 1140 return SharedMemoryHandle(); | |
| 1141 | |
| 1142 int field_trial_handle = 0; | |
| 1143 if (!base::StringToInt(tokens[0], &field_trial_handle)) | |
| 1144 return SharedMemoryHandle(); | |
| 1140 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); | 1145 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); |
| 1141 // TODO(erikchen): Plumb a GUID for this SharedMemoryHandle. | 1146 |
| 1142 // https://crbug.com/713763. | 1147 base::UnguessableToken guid; |
| 1143 SharedMemoryHandle shm_handle(handle, base::UnguessableToken::Create()); | 1148 if (!DeserializeGUIDFromStringPieces(tokens[1], tokens[2], &guid)) |
| 1144 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); | 1149 return SharedMemoryHandle(); |
| 1150 | |
| 1151 return SharedMemoryHandle(handle, guid); | |
| 1145 } | 1152 } |
| 1146 #endif | 1153 #endif // defined(OS_WIN) |
| 1147 | 1154 |
| 1148 #if defined(OS_POSIX) && !defined(OS_NACL) | 1155 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 1149 // static | 1156 // static |
| 1150 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { | 1157 SharedMemoryHandle FieldTrialList::DeserializeSharedMemoryHandleMetadata( |
| 1158 int fd, | |
| 1159 const std::string& switch_value) { | |
| 1160 std::vector<base::StringPiece> tokens = base::SplitStringPiece( | |
| 1161 switch_value, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 1162 | |
| 1163 if (tokens.size() != 2) | |
| 1164 return SharedMemoryHandle(); | |
| 1165 | |
| 1166 base::UnguessableToken guid; | |
| 1167 if (!DeserializeGUIDFromStringPieces(tokens[0], tokens[1], &guid)) | |
| 1168 return SharedMemoryHandle(); | |
| 1169 | |
| 1170 return SharedMemoryHandle(FileDescriptor(fd, true), guid); | |
| 1171 } | |
| 1172 #endif // defined(OS_POSIX) && !defined(OS_NACL) | |
| 1173 | |
| 1174 #if defined(OS_WIN) | |
| 1175 // static | |
| 1176 bool FieldTrialList::CreateTrialsFromSwitchValue( | |
| 1177 const std::string& switch_value) { | |
| 1178 SharedMemoryHandle shm = DeserializeSharedMemoryHandleMetadata(switch_value); | |
| 1179 if (!shm.IsValid()) | |
| 1180 return false; | |
| 1181 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm); | |
| 1182 } | |
| 1183 #endif // defined(OS_WIN) | |
| 1184 | |
| 1185 #if defined(OS_POSIX) && !defined(OS_NACL) | |
| 1186 // static | |
| 1187 bool FieldTrialList::CreateTrialsFromDescriptor( | |
| 1188 int fd_key, | |
| 1189 const std::string& switch_value) { | |
| 1151 if (!kUseSharedMemoryForFieldTrials) | 1190 if (!kUseSharedMemoryForFieldTrials) |
| 1152 return false; | 1191 return false; |
| 1153 | 1192 |
| 1154 if (fd_key == -1) | 1193 if (fd_key == -1) |
| 1155 return false; | 1194 return false; |
| 1156 | 1195 |
| 1157 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); | 1196 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); |
| 1158 if (fd == -1) | 1197 if (fd == -1) |
| 1159 return false; | 1198 return false; |
| 1160 | 1199 |
| 1161 // TODO(erikchen): Plumb a GUID for this SharedMemoryHandle. | 1200 SharedMemoryHandle shm = |
| 1162 // https://crbug.com/713763. | 1201 DeserializeSharedMemoryHandleMetadata(fd, switch_value); |
| 1163 SharedMemoryHandle shm_handle(FileDescriptor(fd, true), | 1202 if (!shm.IsValid()) |
| 1164 base::UnguessableToken::Create()); | 1203 return false; |
| 1165 | 1204 |
| 1166 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); | 1205 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm); |
| 1167 DCHECK(result); | 1206 DCHECK(result); |
| 1168 return true; | 1207 return true; |
| 1169 } | 1208 } |
| 1170 #endif | 1209 #endif // defined(OS_POSIX) && !defined(OS_NACL) |
| 1171 | 1210 |
| 1172 // static | 1211 // static |
| 1173 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle( | 1212 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle( |
| 1174 SharedMemoryHandle shm_handle) { | 1213 SharedMemoryHandle shm_handle) { |
| 1175 // shm gets deleted when it gets out of scope, but that's OK because we need | 1214 // shm gets deleted when it gets out of scope, but that's OK because we need |
| 1176 // it only for the duration of this method. | 1215 // it only for the duration of this method. |
| 1177 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true)); | 1216 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true)); |
| 1178 if (!shm.get()->Map(kFieldTrialAllocationSize)) | 1217 if (!shm.get()->Map(kFieldTrialAllocationSize)) |
| 1179 OnOutOfMemory(kFieldTrialAllocationSize); | 1218 OnOutOfMemory(kFieldTrialAllocationSize); |
| 1180 | 1219 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1247 } | 1286 } |
| 1248 | 1287 |
| 1249 // Add all existing features. | 1288 // Add all existing features. |
| 1250 FeatureList::GetInstance()->AddFeaturesToAllocator( | 1289 FeatureList::GetInstance()->AddFeaturesToAllocator( |
| 1251 global_->field_trial_allocator_.get()); | 1290 global_->field_trial_allocator_.get()); |
| 1252 | 1291 |
| 1253 #if !defined(OS_NACL) | 1292 #if !defined(OS_NACL) |
| 1254 // Set |readonly_allocator_handle_| so we can pass it to be inherited and | 1293 // Set |readonly_allocator_handle_| so we can pass it to be inherited and |
| 1255 // via the command line. | 1294 // via the command line. |
| 1256 global_->readonly_allocator_handle_ = | 1295 global_->readonly_allocator_handle_ = |
| 1257 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); | 1296 global_->field_trial_allocator_->shared_memory()->GetReadOnlyHandle(); |
| 1258 #endif | 1297 #endif |
| 1259 } | 1298 } |
| 1260 | 1299 |
| 1261 // static | 1300 // static |
| 1262 void FieldTrialList::AddToAllocatorWhileLocked( | 1301 void FieldTrialList::AddToAllocatorWhileLocked( |
| 1263 PersistentMemoryAllocator* allocator, | 1302 PersistentMemoryAllocator* allocator, |
| 1264 FieldTrial* field_trial) { | 1303 FieldTrial* field_trial) { |
| 1265 // Don't do anything if the allocator hasn't been instantiated yet. | 1304 // Don't do anything if the allocator hasn't been instantiated yet. |
| 1266 if (allocator == nullptr) | 1305 if (allocator == nullptr) |
| 1267 return; | 1306 return; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1359 return; | 1398 return; |
| 1360 } | 1399 } |
| 1361 AutoLock auto_lock(global_->lock_); | 1400 AutoLock auto_lock(global_->lock_); |
| 1362 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 1401 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 1363 trial->AddRef(); | 1402 trial->AddRef(); |
| 1364 trial->SetTrialRegistered(); | 1403 trial->SetTrialRegistered(); |
| 1365 global_->registered_[trial->trial_name()] = trial; | 1404 global_->registered_[trial->trial_name()] = trial; |
| 1366 } | 1405 } |
| 1367 | 1406 |
| 1368 } // namespace base | 1407 } // namespace base |
| OLD | NEW |