| 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 |