Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "content/browser/child_process_launcher_helper.h" | 5 #include "content/browser/child_process_launcher_helper.h" |
| 6 | 6 |
| 7 #include "base/base_paths.h" | |
| 8 #include "base/files/file.h" | |
| 9 #include "base/lazy_instance.h" | |
| 7 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| 11 #include "base/path_service.h" | |
| 12 #include "base/posix/global_descriptors.h" | |
| 13 #include "base/strings/string_number_conversions.h" | |
| 14 #include "base/strings/string_util.h" | |
| 8 #include "content/browser/child_process_launcher.h" | 15 #include "content/browser/child_process_launcher.h" |
| 16 #include "content/public/common/content_descriptors.h" | |
| 9 #include "content/public/common/content_switches.h" | 17 #include "content/public/common/content_switches.h" |
| 10 #include "content/public/common/sandboxed_process_launcher_delegate.h" | 18 #include "content/public/common/sandboxed_process_launcher_delegate.h" |
| 11 #include "mojo/edk/embedder/platform_channel_pair.h" | 19 #include "mojo/edk/embedder/platform_channel_pair.h" |
| 12 | 20 |
| 13 namespace content { | 21 namespace content { |
| 14 namespace internal { | 22 namespace internal { |
| 15 | 23 |
| 16 namespace { | 24 namespace { |
| 17 | 25 |
| 26 base::LazyInstance< | |
| 27 std::map<std::string, std::unique_ptr<catalog::RequiredFileMap>>> | |
| 28 g_required_files_by_service = LAZY_INSTANCE_INITIALIZER; | |
| 29 | |
| 30 base::LazyInstance<std::map<std::string, std::string>> | |
| 31 g_process_name_to_service_name = LAZY_INSTANCE_INITIALIZER; | |
| 32 | |
| 33 typedef std::map<base::FilePath, | |
| 34 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>> | |
| 35 OpenedFileMap; | |
| 36 base::LazyInstance<OpenedFileMap> g_opened_files = LAZY_INSTANCE_INITIALIZER; | |
| 37 | |
| 18 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) { | 38 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) { |
| 19 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); | 39 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); |
| 20 // Log the launch time, separating out the first one (which will likely be | 40 // Log the launch time, separating out the first one (which will likely be |
| 21 // slower due to the rest of the browser initializing at the same time). | 41 // slower due to the rest of the browser initializing at the same time). |
| 22 static bool done_first_launch = false; | 42 static bool done_first_launch = false; |
| 23 if (done_first_launch) { | 43 if (done_first_launch) { |
| 24 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time); | 44 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time); |
| 25 } else { | 45 } else { |
| 26 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time); | 46 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time); |
| 27 done_first_launch = true; | 47 done_first_launch = true; |
| 28 } | 48 } |
| 29 } | 49 } |
| 30 | 50 |
| 51 base::PlatformFile OpenFileIfNecessary(const base::FilePath& path, | |
| 52 base::MemoryMappedFile::Region* region) { | |
| 53 const auto& iter = g_opened_files.Get().find(path); | |
| 54 if (iter != g_opened_files.Get().end()) { | |
| 55 *region = iter->second.second; | |
| 56 return iter->second.first; | |
| 57 } | |
| 58 base::File file = ChildProcessLauncherHelper::OpenFile(path, region); | |
| 59 if (!file.IsValid()) { | |
| 60 return base::kInvalidPlatformFile; | |
| 61 } | |
| 62 // g_opened_files becomes the owner of the file descriptor. | |
| 63 base::PlatformFile fd = file.TakePlatformFile(); | |
| 64 g_opened_files.Get()[path] = std::make_pair(fd, *region); | |
| 65 return fd; | |
| 66 } | |
| 67 | |
| 31 } // namespace | 68 } // namespace |
| 32 | 69 |
| 33 ChildProcessLauncherHelper::Process::Process(Process&& other) | 70 ChildProcessLauncherHelper::Process::Process(Process&& other) |
| 34 : process(std::move(other.process)) | 71 : process(std::move(other.process)) |
| 35 #if defined(OS_LINUX) | 72 #if defined(OS_LINUX) |
| 36 , zygote(other.zygote) | 73 , zygote(other.zygote) |
| 37 #endif | 74 #endif |
| 38 { | 75 { |
| 39 } | 76 } |
| 40 | 77 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 base::Bind(&ChildProcessLauncherHelper::LaunchOnLauncherThread, this)); | 121 base::Bind(&ChildProcessLauncherHelper::LaunchOnLauncherThread, this)); |
| 85 } | 122 } |
| 86 | 123 |
| 87 void ChildProcessLauncherHelper::LaunchOnLauncherThread() { | 124 void ChildProcessLauncherHelper::LaunchOnLauncherThread() { |
| 88 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); | 125 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); |
| 89 | 126 |
| 90 begin_launch_time_ = base::TimeTicks::Now(); | 127 begin_launch_time_ = base::TimeTicks::Now(); |
| 91 | 128 |
| 92 std::unique_ptr<FileMappedForLaunch> files_to_register = GetFilesToMap(); | 129 std::unique_ptr<FileMappedForLaunch> files_to_register = GetFilesToMap(); |
| 93 | 130 |
| 131 // Also include the files specified in the services' manifests. | |
| 132 const auto& service_name_iter = | |
| 133 g_process_name_to_service_name.Get().find(GetProcessType()); | |
| 134 CHECK(service_name_iter != g_process_name_to_service_name.Get().end()); | |
| 135 std::string service_name = service_name_iter->second; | |
| 136 const auto& files_iter = g_required_files_by_service.Get().find(service_name); | |
| 137 if (files_iter != g_required_files_by_service.Get().end()) { | |
| 138 catalog::RequiredFileMap* required_files_map = files_iter->second.get(); | |
| 139 base::GlobalDescriptors::Key key = kContentDynamicDescriptorStart; | |
| 140 std::string switch_value; | |
| 141 for (const auto& key_path_iter : *required_files_map) { | |
| 142 base::MemoryMappedFile::Region region; | |
| 143 base::PlatformFile file = | |
| 144 OpenFileIfNecessary(base::FilePath(key_path_iter.second), ®ion); | |
| 145 if (file == base::kInvalidPlatformFile) { | |
| 146 LOG(ERROR) << "Ignoring invalid file " << key_path_iter.second; | |
| 147 continue; | |
| 148 } | |
| 149 if (!switch_value.empty()) { | |
| 150 switch_value += ","; | |
| 151 } | |
| 152 switch_value += key_path_iter.first; | |
| 153 switch_value += ":"; | |
| 154 switch_value += base::IntToString(key); | |
| 155 files_to_register->ShareWithRegion(key, file, region); | |
| 156 key++; | |
| 157 DCHECK(key < kContentDynamicDescriptorMax); | |
| 158 } | |
| 159 command_line()->AppendSwitchASCII(switches::kSharedFiles, switch_value); | |
| 160 } | |
| 161 | |
| 94 bool is_synchronous_launch = true; | 162 bool is_synchronous_launch = true; |
| 95 int launch_result = LAUNCH_RESULT_FAILURE; | 163 int launch_result = LAUNCH_RESULT_FAILURE; |
| 96 base::LaunchOptions options; | 164 base::LaunchOptions options; |
| 97 BeforeLaunchOnLauncherThread(*files_to_register, &options); | 165 BeforeLaunchOnLauncherThread(*files_to_register, &options); |
| 98 | 166 |
| 99 Process process = LaunchProcessOnLauncherThread(options, | 167 Process process = LaunchProcessOnLauncherThread(options, |
| 100 std::move(files_to_register), | 168 std::move(files_to_register), |
| 101 &is_synchronous_launch, | 169 &is_synchronous_launch, |
| 102 &launch_result); | 170 &launch_result); |
| 103 | 171 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 return; | 222 return; |
| 155 } | 223 } |
| 156 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! | 224 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! |
| 157 // So don't do this on the UI/IO threads. | 225 // So don't do this on the UI/IO threads. |
| 158 BrowserThread::PostTask( | 226 BrowserThread::PostTask( |
| 159 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 227 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
| 160 base::Bind(&ChildProcessLauncherHelper::ForceNormalProcessTerminationSync, | 228 base::Bind(&ChildProcessLauncherHelper::ForceNormalProcessTerminationSync, |
| 161 base::Passed(&process))); | 229 base::Passed(&process))); |
| 162 } | 230 } |
| 163 | 231 |
| 232 // static | |
| 233 void ChildProcessLauncherHelper::SetRegisteredFilesForService( | |
| 234 const std::string& service_name, | |
| 235 std::unique_ptr<catalog::RequiredFileMap> required_files) { | |
| 236 if (required_files->empty()) | |
| 237 return; | |
| 238 | |
| 239 std::map<std::string, std::string>& service_name_resolver = | |
|
Ken Rockot(use gerrit already)
2017/02/09 17:17:28
I don't see this being used? Is the |service_name|
Jay Civelli
2017/02/09 22:08:27
It's a bit confusing, I am setting a local var tha
| |
| 240 g_process_name_to_service_name.Get(); | |
| 241 if (service_name_resolver.empty()) { | |
| 242 // Populate the process name to service name. | |
|
Ken Rockot(use gerrit already)
2017/02/09 17:17:28
nit: s/Populate/Translate/?
Also maybe add a TODO
Jay Civelli
2017/02/09 22:08:27
Changed to populate map.
| |
| 243 // The service names are defined in the JSON manifests, so we don't have a | |
| 244 // constant accessible for them. | |
| 245 service_name_resolver[switches::kRendererProcess] = "content_renderer"; | |
| 246 service_name_resolver[switches::kGpuProcess] = "content_gpu"; | |
| 247 service_name_resolver[switches::kPpapiPluginProcess] = "content_plugin"; | |
| 248 service_name_resolver[switches::kUtilityProcess] = "content_utility"; | |
| 249 } | |
| 250 | |
| 251 if (!base::StartsWith(service_name, "content", | |
| 252 base::CompareCase::INSENSITIVE_ASCII)) { | |
| 253 // Not a content child service, ignore. | |
| 254 return; | |
| 255 } | |
| 256 | |
| 257 DCHECK(g_required_files_by_service.Get().count(service_name) == 0); | |
| 258 g_required_files_by_service.Get()[service_name] = std::move(required_files); | |
| 259 } | |
| 260 | |
| 164 } // namespace internal | 261 } // namespace internal |
| 165 } // namespace content | 262 } // namespace content |
| OLD | NEW |