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 |
| 238 } // namespace | 220 } // namespace |
| 239 | 221 |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 // processes are properly reported in crash reports. | 750 // processes are properly reported in crash reports. |
| 769 trial->group(); | 751 trial->group(); |
| 770 } | 752 } |
| 771 } | 753 } |
| 772 return true; | 754 return true; |
| 773 } | 755 } |
| 774 | 756 |
| 775 // static | 757 // static |
| 776 void FieldTrialList::CreateTrialsFromCommandLine( | 758 void FieldTrialList::CreateTrialsFromCommandLine( |
| 777 const CommandLine& cmd_line, | 759 const CommandLine& cmd_line, |
| 778 const char* field_trial_handle_switch, | 760 const char* field_trial_switch_value, |
|
Alexei Svitkine (slow)
2017/05/05 22:37:50
Nit: You still have a sed error here :P
erikchen
2017/05/08 23:37:49
Done.
| |
| 779 int fd_key) { | 761 int fd_key) { |
| 780 global_->create_trials_from_command_line_called_ = true; | 762 global_->create_trials_from_command_line_called_ = true; |
| 781 | 763 |
| 782 #if defined(OS_WIN) | 764 #if defined(OS_WIN) |
| 783 if (cmd_line.HasSwitch(field_trial_handle_switch)) { | 765 if (cmd_line.HasSwitch(field_trial_switch_value)) { |
| 784 std::string handle_switch = | 766 std::string switch_value = |
| 785 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); | 767 cmd_line.GetSwitchValueASCII(field_trial_switch_value); |
| 786 bool result = CreateTrialsFromHandleSwitch(handle_switch); | 768 bool result = CreateTrialsFromSwitchValue(switch_value); |
| 787 DCHECK(result); | 769 DCHECK(result); |
| 788 } | 770 } |
| 789 #endif | 771 #endif |
| 790 | 772 |
| 791 #if defined(OS_POSIX) && !defined(OS_NACL) | 773 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 792 // On POSIX, we check if the handle is valid by seeing if the browser process | 774 // 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 | 775 // 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. | 776 // occur in some browser tests which don't initialize the allocator. |
| 795 if (cmd_line.HasSwitch(field_trial_handle_switch)) { | 777 if (cmd_line.HasSwitch(field_trial_switch_value)) { |
| 796 bool result = CreateTrialsFromDescriptor(fd_key); | 778 std::string switch_value = |
| 779 cmd_line.GetSwitchValueASCII(field_trial_switch_value); | |
| 780 bool result = CreateTrialsFromDescriptor(fd_key, switch_value); | |
| 797 DCHECK(result); | 781 DCHECK(result); |
| 798 } | 782 } |
| 799 #endif | 783 #endif |
| 800 | 784 |
| 801 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { | 785 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { |
| 802 bool result = FieldTrialList::CreateTrialsFromString( | 786 bool result = FieldTrialList::CreateTrialsFromString( |
| 803 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), | 787 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), |
| 804 std::set<std::string>()); | 788 std::set<std::string>()); |
| 805 DCHECK(result); | 789 DCHECK(result); |
| 806 } | 790 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 825 } | 809 } |
| 826 | 810 |
| 827 #if defined(OS_WIN) | 811 #if defined(OS_WIN) |
| 828 // static | 812 // static |
| 829 void FieldTrialList::AppendFieldTrialHandleIfNeeded( | 813 void FieldTrialList::AppendFieldTrialHandleIfNeeded( |
| 830 HandlesToInheritVector* handles) { | 814 HandlesToInheritVector* handles) { |
| 831 if (!global_) | 815 if (!global_) |
| 832 return; | 816 return; |
| 833 if (kUseSharedMemoryForFieldTrials) { | 817 if (kUseSharedMemoryForFieldTrials) { |
| 834 InstantiateFieldTrialAllocatorIfNeeded(); | 818 InstantiateFieldTrialAllocatorIfNeeded(); |
| 835 if (global_->readonly_allocator_handle_) | 819 if (global_->readonly_allocator_handle_.IsValid()) |
| 836 handles->push_back(global_->readonly_allocator_handle_); | 820 handles->push_back(global_->readonly_allocator_handle_.GetHandle()); |
| 837 } | 821 } |
| 838 } | 822 } |
| 839 #endif | 823 #endif |
| 840 | 824 |
| 841 #if defined(OS_POSIX) && !defined(OS_NACL) | 825 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 842 // static | 826 // static |
| 843 int FieldTrialList::GetFieldTrialHandle() { | 827 SharedMemoryHandle FieldTrialList::GetFieldTrialHandle() { |
| 844 if (global_ && kUseSharedMemoryForFieldTrials) { | 828 if (global_ && kUseSharedMemoryForFieldTrials) { |
| 845 InstantiateFieldTrialAllocatorIfNeeded(); | 829 InstantiateFieldTrialAllocatorIfNeeded(); |
| 846 // We check for an invalid handle where this gets called. | 830 // We check for an invalid handle where this gets called. |
| 847 return global_->readonly_allocator_handle_; | 831 return global_->readonly_allocator_handle_; |
| 848 } | 832 } |
| 849 return kInvalidPlatformFile; | 833 return SharedMemoryHandle(); |
| 850 } | 834 } |
| 851 #endif | 835 #endif |
| 852 | 836 |
| 853 // static | 837 // static |
| 854 void FieldTrialList::CopyFieldTrialStateToFlags( | 838 void FieldTrialList::CopyFieldTrialStateToFlags( |
| 855 const char* field_trial_handle_switch, | 839 const char* field_trial_handle_switch, |
| 856 const char* enable_features_switch, | 840 const char* enable_features_switch, |
| 857 const char* disable_features_switch, | 841 const char* disable_features_switch, |
| 858 CommandLine* cmd_line) { | 842 CommandLine* cmd_line) { |
| 859 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, | 843 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, |
| 860 // content browser tests currently don't create a FieldTrialList because they | 844 // content browser tests currently don't create a FieldTrialList because they |
| 861 // don't run ChromeBrowserMainParts code where it's done for Chrome. | 845 // don't run ChromeBrowserMainParts code where it's done for Chrome. |
| 862 // Some tests depend on the enable and disable features flag switch, though, | 846 // 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. | 847 // so we can still add those even though AllStatesToString() will be a no-op. |
| 864 if (!global_) { | 848 if (!global_) { |
| 865 AddFeatureAndFieldTrialFlags(enable_features_switch, | 849 AddFeatureAndFieldTrialFlags(enable_features_switch, |
| 866 disable_features_switch, cmd_line); | 850 disable_features_switch, cmd_line); |
| 867 return; | 851 return; |
| 868 } | 852 } |
| 869 | 853 |
| 870 // Use shared memory to pass the state if the feature is enabled, otherwise | 854 // 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. | 855 // fallback to passing it via the command line as a string. |
| 872 if (kUseSharedMemoryForFieldTrials) { | 856 if (kUseSharedMemoryForFieldTrials) { |
| 873 InstantiateFieldTrialAllocatorIfNeeded(); | 857 InstantiateFieldTrialAllocatorIfNeeded(); |
| 874 // If the readonly handle didn't get duplicated properly, then fallback to | 858 // If the readonly handle didn't get duplicated properly, then fallback to |
| 875 // original behavior. | 859 // original behavior. |
| 876 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { | 860 if (!global_->readonly_allocator_handle_.IsValid()) { |
| 877 AddFeatureAndFieldTrialFlags(enable_features_switch, | 861 AddFeatureAndFieldTrialFlags(enable_features_switch, |
| 878 disable_features_switch, cmd_line); | 862 disable_features_switch, cmd_line); |
| 879 return; | 863 return; |
| 880 } | 864 } |
| 881 | 865 |
| 882 global_->field_trial_allocator_->UpdateTrackingHistograms(); | 866 global_->field_trial_allocator_->UpdateTrackingHistograms(); |
| 883 | 867 std::string switch_value = SerializeSharedMemoryHandleMetadata( |
| 884 #if defined(OS_WIN) | 868 global_->readonly_allocator_handle_); |
| 885 // We need to pass a named anonymous handle to shared memory over the | 869 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; | 870 return; |
| 908 } | 871 } |
| 909 | 872 |
| 910 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch, | 873 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch, |
| 911 cmd_line); | 874 cmd_line); |
| 912 } | 875 } |
| 913 | 876 |
| 914 // static | 877 // static |
| 915 FieldTrial* FieldTrialList::CreateFieldTrial( | 878 FieldTrial* FieldTrialList::CreateFieldTrial( |
| 916 const std::string& name, | 879 const std::string& name, |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1125 std::vector<const FieldTrial::FieldTrialEntry*> entries; | 1088 std::vector<const FieldTrial::FieldTrialEntry*> entries; |
| 1126 FieldTrialAllocator::Iterator iter(&allocator); | 1089 FieldTrialAllocator::Iterator iter(&allocator); |
| 1127 const FieldTrial::FieldTrialEntry* entry; | 1090 const FieldTrial::FieldTrialEntry* entry; |
| 1128 while ((entry = iter.GetNextOfObject<FieldTrial::FieldTrialEntry>()) != | 1091 while ((entry = iter.GetNextOfObject<FieldTrial::FieldTrialEntry>()) != |
| 1129 nullptr) { | 1092 nullptr) { |
| 1130 entries.push_back(entry); | 1093 entries.push_back(entry); |
| 1131 } | 1094 } |
| 1132 return entries; | 1095 return entries; |
| 1133 } | 1096 } |
| 1134 | 1097 |
| 1098 // static | |
| 1099 std::string FieldTrialList::SerializeSharedMemoryHandleMetadata( | |
| 1100 const SharedMemoryHandle& shm) { | |
| 1101 std::stringstream ss; | |
| 1102 #if defined(OS_WIN) | |
| 1103 // Tell the child process the name of the inherited HANDLE. | |
| 1104 uintptr_t uintptr_handle = reinterpret_cast<uintptr_t>(shm.GetHandle()); | |
| 1105 ss << uintptr_handle << ","; | |
| 1106 #elif !defined(OS_POSIX) | |
| 1107 #error Unsupported OS | |
| 1108 #endif | |
| 1109 | |
| 1110 base::UnguessableToken guid = shm.GetGUID(); | |
| 1111 ss << guid.GetHighForSerialization() << "," << guid.GetLowForSerialization(); | |
| 1112 return ss.str(); | |
| 1113 } | |
| 1114 | |
| 1135 #if defined(OS_WIN) | 1115 #if defined(OS_WIN) |
| 1136 // static | 1116 // static |
| 1137 bool FieldTrialList::CreateTrialsFromHandleSwitch( | 1117 SharedMemoryHandle FieldTrialList::DeserializeSharedMemoryHandleMetadata( |
| 1138 const std::string& handle_switch) { | 1118 const std::string& switch_value) { |
| 1139 int field_trial_handle = std::stoi(handle_switch); | 1119 std::vector<std::string> tokens = base::SplitString( |
|
Alexei Svitkine (slow)
2017/05/05 22:37:50
Nit: Use StringSplitPiece() version
erikchen
2017/05/08 23:37:49
Done.
| |
| 1120 switch_value, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 1121 | |
| 1122 if (tokens.size() != 3) | |
| 1123 return SharedMemoryHandle(); | |
| 1124 | |
| 1125 int field_trial_handle = 0; | |
| 1126 if (!base::StringToInt(tokens[0], &field_trial_handle)) | |
| 1127 return SharedMemoryHandle(); | |
| 1140 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); | 1128 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); |
| 1141 // TODO(erikchen): Plumb a GUID for this SharedMemoryHandle. | 1129 |
| 1142 // https://crbug.com/713763. | 1130 uint64_t high = 0; |
| 1143 SharedMemoryHandle shm_handle(handle, base::UnguessableToken::Create()); | 1131 if (!base::StringToUint64(tokens[1], &high)) |
| 1144 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); | 1132 return SharedMemoryHandle(); |
| 1133 uint64_t low = 0; | |
| 1134 if (!base::StringToUint64(tokens[2], &low)) | |
| 1135 return SharedMemoryHandle(); | |
| 1136 | |
| 1137 base::UnguessableToken guid = base::UnguessableToken::Deserialize(high, low); | |
| 1138 return SharedMemoryHandle(handle, guid); | |
| 1139 } | |
| 1140 | |
| 1141 // static | |
| 1142 bool FieldTrialList::CreateTrialsFromSwitchValue( | |
| 1143 const std::string& switch_value) { | |
|
Alexei Svitkine (slow)
2017/05/05 22:37:50
Please match the same order in .cc as in .h file -
erikchen
2017/05/08 23:37:49
Done.
| |
| 1144 SharedMemoryHandle shm = DeserializeSharedMemoryHandleMetadata(switch_value); | |
| 1145 if (!shm.IsValid()) | |
| 1146 return false; | |
| 1147 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm); | |
| 1145 } | 1148 } |
| 1146 #endif | 1149 #endif |
| 1147 | 1150 |
| 1148 #if defined(OS_POSIX) && !defined(OS_NACL) | 1151 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 1149 // static | 1152 // static |
| 1150 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { | 1153 SharedMemoryHandle FieldTrialList::DeserializeSharedMemoryHandleMetadata( |
| 1154 int fd, | |
| 1155 const std::string& switch_value) { | |
| 1156 std::vector<std::string> tokens = base::SplitString( | |
| 1157 switch_value, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 1158 | |
| 1159 if (tokens.size() != 2) | |
| 1160 return SharedMemoryHandle(); | |
| 1161 uint64_t high = 0; | |
| 1162 if (!base::StringToUint64(tokens[0], &high)) | |
| 1163 return SharedMemoryHandle(); | |
| 1164 uint64_t low = 0; | |
| 1165 if (!base::StringToUint64(tokens[1], &low)) | |
| 1166 return SharedMemoryHandle(); | |
|
Alexei Svitkine (slow)
2017/05/05 22:37:50
Nit: I find the following a bit cleaner:
uint64_t
erikchen
2017/05/08 23:37:49
Done.
| |
| 1167 | |
| 1168 base::UnguessableToken guid = base::UnguessableToken::Deserialize(high, low); | |
|
Alexei Svitkine (slow)
2017/05/05 22:37:51
Suggest making a helper anon function to share thi
erikchen
2017/05/08 23:37:49
Done.
| |
| 1169 return SharedMemoryHandle(FileDescriptor(fd, true), guid); | |
| 1170 } | |
| 1171 | |
| 1172 // static | |
| 1173 bool FieldTrialList::CreateTrialsFromDescriptor( | |
| 1174 int fd_key, | |
| 1175 const std::string& switch_value) { | |
| 1151 if (!kUseSharedMemoryForFieldTrials) | 1176 if (!kUseSharedMemoryForFieldTrials) |
| 1152 return false; | 1177 return false; |
| 1153 | 1178 |
| 1154 if (fd_key == -1) | 1179 if (fd_key == -1) |
| 1155 return false; | 1180 return false; |
| 1156 | 1181 |
| 1157 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); | 1182 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); |
| 1158 if (fd == -1) | 1183 if (fd == -1) |
| 1159 return false; | 1184 return false; |
| 1160 | 1185 |
| 1161 // TODO(erikchen): Plumb a GUID for this SharedMemoryHandle. | 1186 SharedMemoryHandle shm = |
| 1162 // https://crbug.com/713763. | 1187 DeserializeSharedMemoryHandleMetadata(fd, switch_value); |
| 1163 SharedMemoryHandle shm_handle(FileDescriptor(fd, true), | 1188 if (!shm.IsValid()) |
| 1164 base::UnguessableToken::Create()); | 1189 return false; |
| 1165 | 1190 |
| 1166 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); | 1191 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm); |
| 1167 DCHECK(result); | 1192 DCHECK(result); |
| 1168 return true; | 1193 return true; |
| 1169 } | 1194 } |
| 1170 #endif | 1195 #endif |
| 1171 | 1196 |
| 1172 // static | 1197 // static |
| 1173 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle( | 1198 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle( |
| 1174 SharedMemoryHandle shm_handle) { | 1199 SharedMemoryHandle shm_handle) { |
| 1175 // shm gets deleted when it gets out of scope, but that's OK because we need | 1200 // 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. | 1201 // it only for the duration of this method. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1247 } | 1272 } |
| 1248 | 1273 |
| 1249 // Add all existing features. | 1274 // Add all existing features. |
| 1250 FeatureList::GetInstance()->AddFeaturesToAllocator( | 1275 FeatureList::GetInstance()->AddFeaturesToAllocator( |
| 1251 global_->field_trial_allocator_.get()); | 1276 global_->field_trial_allocator_.get()); |
| 1252 | 1277 |
| 1253 #if !defined(OS_NACL) | 1278 #if !defined(OS_NACL) |
| 1254 // Set |readonly_allocator_handle_| so we can pass it to be inherited and | 1279 // Set |readonly_allocator_handle_| so we can pass it to be inherited and |
| 1255 // via the command line. | 1280 // via the command line. |
| 1256 global_->readonly_allocator_handle_ = | 1281 global_->readonly_allocator_handle_ = |
| 1257 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); | 1282 global_->field_trial_allocator_->shared_memory()->GetReadOnlyHandle(); |
| 1258 #endif | 1283 #endif |
| 1259 } | 1284 } |
| 1260 | 1285 |
| 1261 // static | 1286 // static |
| 1262 void FieldTrialList::AddToAllocatorWhileLocked( | 1287 void FieldTrialList::AddToAllocatorWhileLocked( |
| 1263 PersistentMemoryAllocator* allocator, | 1288 PersistentMemoryAllocator* allocator, |
| 1264 FieldTrial* field_trial) { | 1289 FieldTrial* field_trial) { |
| 1265 // Don't do anything if the allocator hasn't been instantiated yet. | 1290 // Don't do anything if the allocator hasn't been instantiated yet. |
| 1266 if (allocator == nullptr) | 1291 if (allocator == nullptr) |
| 1267 return; | 1292 return; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1359 return; | 1384 return; |
| 1360 } | 1385 } |
| 1361 AutoLock auto_lock(global_->lock_); | 1386 AutoLock auto_lock(global_->lock_); |
| 1362 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 1387 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 1363 trial->AddRef(); | 1388 trial->AddRef(); |
| 1364 trial->SetTrialRegistered(); | 1389 trial->SetTrialRegistered(); |
| 1365 global_->registered_[trial->trial_name()] = trial; | 1390 global_->registered_[trial->trial_name()] = trial; |
| 1366 } | 1391 } |
| 1367 | 1392 |
| 1368 } // namespace base | 1393 } // namespace base |
| OLD | NEW |