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" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
22 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
23 | 23 |
24 // On systems that use the zygote process to spawn child processes, we must | 24 // On systems that use the zygote process to spawn child processes, we must |
25 // retrieve the correct fd using the mapping in GlobalDescriptors. | 25 // retrieve the correct fd using the mapping in GlobalDescriptors. |
26 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MACOSX) && \ | 26 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MACOSX) && \ |
27 !defined(OS_ANDROID) | 27 !defined(OS_ANDROID) |
28 #define POSIX_WITH_ZYGOTE 1 | 28 #define POSIX_WITH_ZYGOTE 1 |
29 #endif | 29 #endif |
30 | 30 |
31 #if defined(POSIX_WITH_ZYGOTE) | 31 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) |
32 #include "base/posix/global_descriptors.h" | 32 #include "base/posix/global_descriptors.h" |
33 #endif | 33 #endif |
34 | 34 |
35 namespace base { | 35 namespace base { |
36 | 36 |
37 namespace { | 37 namespace { |
38 | 38 |
39 // Define a separator character to use when creating a persistent form of an | 39 // Define a separator character to use when creating a persistent form of an |
40 // instance. This is intended for use as a command line argument, passed to a | 40 // instance. This is intended for use as a command line argument, passed to a |
41 // second process to mimic our state (i.e., provide the same group name). | 41 // second process to mimic our state (i.e., provide the same group name). |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 HANDLE src = allocator->shared_memory()->handle().GetHandle(); | 262 HANDLE src = allocator->shared_memory()->handle().GetHandle(); |
263 ProcessHandle process = GetCurrentProcess(); | 263 ProcessHandle process = GetCurrentProcess(); |
264 DWORD access = SECTION_MAP_READ | SECTION_QUERY; | 264 DWORD access = SECTION_MAP_READ | SECTION_QUERY; |
265 HANDLE dst; | 265 HANDLE dst; |
266 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) | 266 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) |
267 return kInvalidPlatformFile; | 267 return kInvalidPlatformFile; |
268 return dst; | 268 return dst; |
269 } | 269 } |
270 #endif | 270 #endif |
271 | 271 |
272 #if defined(POSIX_WITH_ZYGOTE) | 272 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) |
273 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { | 273 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { |
274 SharedMemoryHandle new_handle; | 274 SharedMemoryHandle new_handle; |
275 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(), | 275 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(), |
276 &new_handle); | 276 &new_handle); |
277 return SharedMemory::GetFdFromSharedMemoryHandle(new_handle); | 277 return SharedMemory::GetFdFromSharedMemoryHandle(new_handle); |
278 } | 278 } |
279 #endif | 279 #endif |
280 | 280 |
281 } // namespace | 281 } // namespace |
282 | 282 |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 | 783 |
784 #if defined(OS_WIN) | 784 #if defined(OS_WIN) |
785 if (cmd_line.HasSwitch(field_trial_handle_switch)) { | 785 if (cmd_line.HasSwitch(field_trial_handle_switch)) { |
786 std::string handle_switch = | 786 std::string handle_switch = |
787 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); | 787 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); |
788 bool result = CreateTrialsFromHandleSwitch(handle_switch); | 788 bool result = CreateTrialsFromHandleSwitch(handle_switch); |
789 DCHECK(result); | 789 DCHECK(result); |
790 } | 790 } |
791 #endif | 791 #endif |
792 | 792 |
793 #if defined(POSIX_WITH_ZYGOTE) | 793 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) |
794 // If we failed to create trials from the descriptor, fallback to the command | 794 // If we failed to create trials from the descriptor, fallback to the command |
795 // line. Otherwise we're good -- return. | 795 // line. Otherwise we're good -- return. |
796 if (CreateTrialsFromDescriptor(fd_key)) | 796 if (CreateTrialsFromDescriptor(fd_key)) |
797 return; | 797 return; |
798 #endif | 798 #endif |
799 | 799 |
800 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { | 800 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { |
801 bool result = FieldTrialList::CreateTrialsFromString( | 801 bool result = FieldTrialList::CreateTrialsFromString( |
802 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), | 802 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), |
803 std::set<std::string>()); | 803 std::set<std::string>()); |
804 DCHECK(result); | 804 DCHECK(result); |
805 } | 805 } |
806 } | 806 } |
807 | 807 |
808 #if defined(POSIX_WITH_ZYGOTE) | 808 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) |
809 // static | 809 // static |
810 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { | 810 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { |
811 if (!kUseSharedMemoryForFieldTrials) | 811 if (!kUseSharedMemoryForFieldTrials) |
812 return false; | 812 return false; |
813 | 813 |
814 if (fd_key == -1) | 814 if (fd_key == -1) |
815 return false; | 815 return false; |
816 | 816 |
817 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); | 817 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); |
818 if (fd == -1) | 818 if (fd == -1) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 // static | 854 // static |
855 void FieldTrialList::CopyFieldTrialStateToFlags( | 855 void FieldTrialList::CopyFieldTrialStateToFlags( |
856 const char* field_trial_handle_switch, | 856 const char* field_trial_handle_switch, |
857 CommandLine* cmd_line) { | 857 CommandLine* cmd_line) { |
858 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, | 858 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, |
859 // content browser tests currently don't create a FieldTrialList because they | 859 // content browser tests currently don't create a FieldTrialList because they |
860 // don't run ChromeBrowserMainParts code where it's done for Chrome. | 860 // don't run ChromeBrowserMainParts code where it's done for Chrome. |
861 if (!global_) | 861 if (!global_) |
862 return; | 862 return; |
863 | 863 |
864 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) | 864 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) |
865 // Use shared memory to pass the state if the feature is enabled, otherwise | 865 // Use shared memory to pass the state if the feature is enabled, otherwise |
866 // fallback to passing it via the command line as a string. | 866 // fallback to passing it via the command line as a string. |
867 if (kUseSharedMemoryForFieldTrials) { | 867 if (kUseSharedMemoryForFieldTrials) { |
868 InstantiateFieldTrialAllocatorIfNeeded(); | 868 InstantiateFieldTrialAllocatorIfNeeded(); |
869 // If the readonly handle didn't get duplicated properly, then fallback to | 869 // If the readonly handle didn't get duplicated properly, then fallback to |
870 // original behavior. | 870 // original behavior. |
871 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { | 871 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { |
872 AddForceFieldTrialsFlag(cmd_line); | 872 AddForceFieldTrialsFlag(cmd_line); |
873 return; | 873 return; |
874 } | 874 } |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1147 if (!global_) | 1147 if (!global_) |
1148 return; | 1148 return; |
1149 AutoLock auto_lock(global_->lock_); | 1149 AutoLock auto_lock(global_->lock_); |
1150 // Create the allocator if not already created and add all existing trials. | 1150 // Create the allocator if not already created and add all existing trials. |
1151 if (global_->field_trial_allocator_ != nullptr) | 1151 if (global_->field_trial_allocator_ != nullptr) |
1152 return; | 1152 return; |
1153 | 1153 |
1154 SharedMemoryCreateOptions options; | 1154 SharedMemoryCreateOptions options; |
1155 options.size = kFieldTrialAllocationSize; | 1155 options.size = kFieldTrialAllocationSize; |
1156 options.share_read_only = true; | 1156 options.share_read_only = true; |
| 1157 #if defined(OS_MACOSX) |
| 1158 options.type = SharedMemoryHandle::POSIX; |
| 1159 #endif |
1157 | 1160 |
1158 std::unique_ptr<SharedMemory> shm(new SharedMemory()); | 1161 std::unique_ptr<SharedMemory> shm(new SharedMemory()); |
1159 if (!shm->Create(options)) | 1162 if (!shm->Create(options)) |
1160 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); | 1163 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); |
1161 | 1164 |
1162 if (!shm->Map(kFieldTrialAllocationSize)) | 1165 if (!shm->Map(kFieldTrialAllocationSize)) |
1163 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); | 1166 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); |
1164 | 1167 |
1165 global_->field_trial_allocator_.reset( | 1168 global_->field_trial_allocator_.reset( |
1166 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); | 1169 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); |
1167 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); | 1170 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); |
1168 | 1171 |
1169 // Add all existing field trials. | 1172 // Add all existing field trials. |
1170 for (const auto& registered : global_->registered_) { | 1173 for (const auto& registered : global_->registered_) { |
1171 AddToAllocatorWhileLocked(registered.second); | 1174 AddToAllocatorWhileLocked(registered.second); |
1172 } | 1175 } |
1173 | 1176 |
1174 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) | 1177 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) |
1175 // Set |readonly_allocator_handle_| so we can pass it to be inherited and | 1178 // Set |readonly_allocator_handle_| so we can pass it to be inherited and |
1176 // via the command line. | 1179 // via the command line. |
1177 global_->readonly_allocator_handle_ = | 1180 global_->readonly_allocator_handle_ = |
1178 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); | 1181 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); |
1179 #endif | 1182 #endif |
1180 } | 1183 } |
1181 #endif | 1184 #endif |
1182 | 1185 |
1183 // static | 1186 // static |
1184 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { | 1187 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 return; | 1282 return; |
1280 } | 1283 } |
1281 AutoLock auto_lock(global_->lock_); | 1284 AutoLock auto_lock(global_->lock_); |
1282 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 1285 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
1283 trial->AddRef(); | 1286 trial->AddRef(); |
1284 trial->SetTrialRegistered(); | 1287 trial->SetTrialRegistered(); |
1285 global_->registered_[trial->trial_name()] = trial; | 1288 global_->registered_[trial->trial_name()] = trial; |
1286 } | 1289 } |
1287 | 1290 |
1288 } // namespace base | 1291 } // namespace base |
OLD | NEW |