OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "content/browser/child_process_launcher.h" | 5 #include "content/browser/child_process_launcher.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 done_first_launch = true; | 83 done_first_launch = true; |
84 } | 84 } |
85 } | 85 } |
86 | 86 |
87 #if defined(OS_ANDROID) | 87 #if defined(OS_ANDROID) |
88 // TODO(sievers): Remove this by defining better what happens on what | 88 // TODO(sievers): Remove this by defining better what happens on what |
89 // thread in the corresponding Java code. | 89 // thread in the corresponding Java code. |
90 void OnChildProcessStartedAndroid(const NotifyCallback& callback, | 90 void OnChildProcessStartedAndroid(const NotifyCallback& callback, |
91 BrowserThread::ID client_thread_id, | 91 BrowserThread::ID client_thread_id, |
92 const base::TimeTicks begin_launch_time, | 92 const base::TimeTicks begin_launch_time, |
93 base::ScopedFD ipcfd, | |
94 base::ScopedFD mojo_fd, | 93 base::ScopedFD mojo_fd, |
95 base::ProcessHandle handle) { | 94 base::ProcessHandle handle) { |
96 int launch_result = (handle == base::kNullProcessHandle) | 95 int launch_result = (handle == base::kNullProcessHandle) |
97 ? LAUNCH_RESULT_FAILURE | 96 ? LAUNCH_RESULT_FAILURE |
98 : LAUNCH_RESULT_SUCCESS; | 97 : LAUNCH_RESULT_SUCCESS; |
99 // This can be called on the launcher thread or UI thread. | 98 // This can be called on the launcher thread or UI thread. |
100 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; | 99 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; |
101 BrowserThread::PostTask( | 100 BrowserThread::PostTask( |
102 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 101 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
103 base::Bind(&RecordHistogramsOnLauncherThread, launch_time)); | 102 base::Bind(&RecordHistogramsOnLauncherThread, launch_time)); |
104 | 103 |
105 base::Closure callback_on_client_thread(base::Bind( | 104 base::Closure callback_on_client_thread(base::Bind( |
106 callback, nullptr, base::Passed(&ipcfd), base::Passed(&mojo_fd), | 105 callback, nullptr, base::Passed(&mojo_fd), |
107 base::Passed(base::Process(handle)), launch_result)); | 106 base::Passed(base::Process(handle)), launch_result)); |
108 if (BrowserThread::CurrentlyOn(client_thread_id)) { | 107 if (BrowserThread::CurrentlyOn(client_thread_id)) { |
109 callback_on_client_thread.Run(); | 108 callback_on_client_thread.Run(); |
110 } else { | 109 } else { |
111 BrowserThread::PostTask( | 110 BrowserThread::PostTask( |
112 client_thread_id, FROM_HERE, callback_on_client_thread); | 111 client_thread_id, FROM_HERE, callback_on_client_thread); |
113 } | 112 } |
114 } | 113 } |
115 #endif | 114 #endif |
116 | 115 |
117 void LaunchOnLauncherThread(const NotifyCallback& callback, | 116 void LaunchOnLauncherThread(const NotifyCallback& callback, |
118 BrowserThread::ID client_thread_id, | 117 BrowserThread::ID client_thread_id, |
119 int child_process_id, | 118 int child_process_id, |
120 SandboxedProcessLauncherDelegate* delegate, | 119 SandboxedProcessLauncherDelegate* delegate, |
121 #if defined(OS_ANDROID) | |
122 base::ScopedFD ipcfd, | |
123 #endif | |
124 mojo::edk::ScopedPlatformHandle client_handle, | 120 mojo::edk::ScopedPlatformHandle client_handle, |
125 base::CommandLine* cmd_line) { | 121 base::CommandLine* cmd_line) { |
126 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); | 122 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); |
127 std::unique_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); | 123 std::unique_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); |
128 #if !defined(OS_ANDROID) | 124 #if !defined(OS_ANDROID) |
129 ZygoteHandle zygote = nullptr; | 125 ZygoteHandle zygote = nullptr; |
130 int launch_result = LAUNCH_RESULT_FAILURE; | 126 int launch_result = LAUNCH_RESULT_FAILURE; |
131 #endif | 127 #endif |
132 #if defined(OS_WIN) | 128 #if defined(OS_WIN) |
133 bool launch_elevated = delegate->ShouldLaunchElevated(); | 129 bool launch_elevated = delegate->ShouldLaunchElevated(); |
134 #elif defined(OS_MACOSX) | 130 #elif defined(OS_MACOSX) |
135 base::EnvironmentMap env = delegate->GetEnvironment(); | 131 base::EnvironmentMap env = delegate->GetEnvironment(); |
136 base::ScopedFD ipcfd = delegate->TakeIpcFd(); | |
137 #elif defined(OS_POSIX) && !defined(OS_ANDROID) | 132 #elif defined(OS_POSIX) && !defined(OS_ANDROID) |
138 base::EnvironmentMap env = delegate->GetEnvironment(); | 133 base::EnvironmentMap env = delegate->GetEnvironment(); |
139 base::ScopedFD ipcfd = delegate->TakeIpcFd(); | |
140 #endif | 134 #endif |
141 std::unique_ptr<base::CommandLine> cmd_line_deleter(cmd_line); | 135 std::unique_ptr<base::CommandLine> cmd_line_deleter(cmd_line); |
142 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); | 136 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); |
143 | 137 |
144 base::Process process; | 138 base::Process process; |
145 #if defined(OS_WIN) | 139 #if defined(OS_WIN) |
146 if (launch_elevated) { | 140 if (launch_elevated) { |
147 // When establishing a Mojo connection, the pipe path has already been added | 141 // When establishing a Mojo connection, the pipe path has already been added |
148 // to the command line. | 142 // to the command line. |
149 base::LaunchOptions options; | 143 base::LaunchOptions options; |
(...skipping 11 matching lines...) Expand all Loading... |
161 #elif defined(OS_POSIX) | 155 #elif defined(OS_POSIX) |
162 std::string process_type = | 156 std::string process_type = |
163 cmd_line->GetSwitchValueASCII(switches::kProcessType); | 157 cmd_line->GetSwitchValueASCII(switches::kProcessType); |
164 std::unique_ptr<FileDescriptorInfo> files_to_register( | 158 std::unique_ptr<FileDescriptorInfo> files_to_register( |
165 FileDescriptorInfoImpl::Create()); | 159 FileDescriptorInfoImpl::Create()); |
166 | 160 |
167 base::ScopedFD mojo_fd(client_handle.release().handle); | 161 base::ScopedFD mojo_fd(client_handle.release().handle); |
168 DCHECK(mojo_fd.is_valid()); | 162 DCHECK(mojo_fd.is_valid()); |
169 | 163 |
170 #if defined(OS_ANDROID) | 164 #if defined(OS_ANDROID) |
171 if (ipcfd.get() != -1) | |
172 files_to_register->Share(kPrimaryIPCChannel, ipcfd.get()); | |
173 files_to_register->Share(kMojoIPCChannel, mojo_fd.get()); | 165 files_to_register->Share(kMojoIPCChannel, mojo_fd.get()); |
174 #else | 166 #else |
175 if (ipcfd.get() != -1) | |
176 files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd)); | |
177 files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd)); | 167 files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd)); |
178 #endif | 168 #endif |
179 #endif | 169 #endif |
180 | 170 |
181 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 171 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
182 std::map<int, base::MemoryMappedFile::Region> regions; | 172 std::map<int, base::MemoryMappedFile::Region> regions; |
183 GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess( | 173 GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess( |
184 *cmd_line, child_process_id, files_to_register.get() | 174 *cmd_line, child_process_id, files_to_register.get() |
185 #if defined(OS_ANDROID) | 175 #if defined(OS_ANDROID) |
186 , ®ions | 176 , ®ions |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 kAndroidICUDataDescriptor, | 232 kAndroidICUDataDescriptor, |
243 base::i18n::GetIcuDataFileHandle(®ions[kAndroidICUDataDescriptor])); | 233 base::i18n::GetIcuDataFileHandle(®ions[kAndroidICUDataDescriptor])); |
244 | 234 |
245 // Android WebView runs in single process, ensure that we never get here | 235 // Android WebView runs in single process, ensure that we never get here |
246 // when running in single process mode. | 236 // when running in single process mode. |
247 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); | 237 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); |
248 | 238 |
249 StartChildProcess( | 239 StartChildProcess( |
250 cmd_line->argv(), child_process_id, std::move(files_to_register), regions, | 240 cmd_line->argv(), child_process_id, std::move(files_to_register), regions, |
251 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id, | 241 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id, |
252 begin_launch_time, base::Passed(&ipcfd), | 242 begin_launch_time, base::Passed(&mojo_fd))); |
253 base::Passed(&mojo_fd))); | |
254 | 243 |
255 #elif defined(OS_POSIX) | 244 #elif defined(OS_POSIX) |
256 // We need to close the client end of the IPC channel to reliably detect | 245 // We need to close the client end of the IPC channel to reliably detect |
257 // child termination. | 246 // child termination. |
258 | 247 |
259 #if !defined(OS_MACOSX) | 248 #if !defined(OS_MACOSX) |
260 ZygoteHandle* zygote_handle = delegate->GetZygote(); | 249 ZygoteHandle* zygote_handle = delegate->GetZygote(); |
261 // If |zygote_handle| is null, a zygote should not be used. | 250 // If |zygote_handle| is null, a zygote should not be used. |
262 if (zygote_handle) { | 251 if (zygote_handle) { |
263 // This code runs on the PROCESS_LAUNCHER thread so race conditions are not | 252 // This code runs on the PROCESS_LAUNCHER thread so race conditions are not |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 #if defined(ENABLE_PLUGINS) | 430 #if defined(ENABLE_PLUGINS) |
442 process_type == switches::kPpapiPluginProcess || | 431 process_type == switches::kPpapiPluginProcess || |
443 #endif | 432 #endif |
444 process_type == switches::kUtilityProcess) | 433 process_type == switches::kUtilityProcess) |
445 << "Unsupported process type: " << process_type; | 434 << "Unsupported process type: " << process_type; |
446 | 435 |
447 // Non-sandboxed utility or renderer process are currently not supported. | 436 // Non-sandboxed utility or renderer process are currently not supported. |
448 DCHECK(process_type == switches::kGpuProcess || | 437 DCHECK(process_type == switches::kGpuProcess || |
449 !cmd_line->HasSwitch(switches::kNoSandbox)); | 438 !cmd_line->HasSwitch(switches::kNoSandbox)); |
450 | 439 |
451 // We need to close the client end of the IPC channel to reliably detect | |
452 // child termination. We will close this fd after we create the child | |
453 // process which is asynchronous on Android. | |
454 base::ScopedFD ipcfd(delegate->TakeIpcFd().release()); | |
455 #endif | 440 #endif |
456 NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch, | 441 NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch, |
457 weak_factory_.GetWeakPtr(), | 442 weak_factory_.GetWeakPtr(), |
458 terminate_child_on_shutdown_)); | 443 terminate_child_on_shutdown_)); |
459 mojo::edk::ScopedPlatformHandle client_handle; | 444 mojo::edk::ScopedPlatformHandle client_handle; |
460 #if defined(OS_WIN) | 445 #if defined(OS_WIN) |
461 if (delegate->ShouldLaunchElevated()) { | 446 if (delegate->ShouldLaunchElevated()) { |
462 mojo::edk::NamedPlatformChannelPair named_pair; | 447 mojo::edk::NamedPlatformChannelPair named_pair; |
463 mojo_host_platform_handle_ = named_pair.PassServerHandle(); | 448 mojo_host_platform_handle_ = named_pair.PassServerHandle(); |
464 named_pair.PrepareToPassClientHandleToChildProcess(cmd_line); | 449 named_pair.PrepareToPassClientHandleToChildProcess(cmd_line); |
465 } else | 450 } else |
466 #endif | 451 #endif |
467 { | 452 { |
468 mojo::edk::PlatformChannelPair channel_pair; | 453 mojo::edk::PlatformChannelPair channel_pair; |
469 mojo_host_platform_handle_ = channel_pair.PassServerHandle(); | 454 mojo_host_platform_handle_ = channel_pair.PassServerHandle(); |
470 client_handle = channel_pair.PassClientHandle(); | 455 client_handle = channel_pair.PassClientHandle(); |
471 } | 456 } |
472 BrowserThread::PostTask( | 457 BrowserThread::PostTask( |
473 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 458 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
474 base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_, | 459 base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_, |
475 child_process_id, delegate, | 460 child_process_id, delegate, |
476 #if defined(OS_ANDROID) | |
477 base::Passed(&ipcfd), | |
478 #endif | |
479 base::Passed(&client_handle), cmd_line)); | 461 base::Passed(&client_handle), cmd_line)); |
480 } | 462 } |
481 | 463 |
482 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) { | 464 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) { |
483 DCHECK(CalledOnValidThread()); | 465 DCHECK(CalledOnValidThread()); |
484 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | 466 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
485 if (zygote_) { | 467 if (zygote_) { |
486 termination_status_ = zygote_->GetTerminationStatus( | 468 termination_status_ = zygote_->GetTerminationStatus( |
487 process_.Handle(), known_dead, &exit_code_); | 469 process_.Handle(), known_dead, &exit_code_); |
488 } else if (known_dead) { | 470 } else if (known_dead) { |
(...skipping 23 matching lines...) Expand all Loading... |
512 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 494 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
513 base::Bind(&SetProcessBackgroundedOnLauncherThread, | 495 base::Bind(&SetProcessBackgroundedOnLauncherThread, |
514 base::Passed(&to_pass), background)); | 496 base::Passed(&to_pass), background)); |
515 } | 497 } |
516 | 498 |
517 void ChildProcessLauncher::DidLaunch( | 499 void ChildProcessLauncher::DidLaunch( |
518 base::WeakPtr<ChildProcessLauncher> instance, | 500 base::WeakPtr<ChildProcessLauncher> instance, |
519 bool terminate_on_shutdown, | 501 bool terminate_on_shutdown, |
520 ZygoteHandle zygote, | 502 ZygoteHandle zygote, |
521 #if defined(OS_ANDROID) | 503 #if defined(OS_ANDROID) |
522 base::ScopedFD ipcfd, | |
523 base::ScopedFD mojo_fd, | 504 base::ScopedFD mojo_fd, |
524 #endif | 505 #endif |
525 base::Process process, | 506 base::Process process, |
526 int error_code) { | 507 int error_code) { |
527 if (!process.IsValid()) | 508 if (!process.IsValid()) |
528 LOG(ERROR) << "Failed to launch child process"; | 509 LOG(ERROR) << "Failed to launch child process"; |
529 | 510 |
530 if (instance.get()) { | 511 if (instance.get()) { |
531 instance->Notify(zygote, | 512 instance->Notify(zygote, std::move(process), error_code); |
532 #if defined(OS_ANDROID) | |
533 std::move(ipcfd), | |
534 #endif | |
535 std::move(process), | |
536 error_code); | |
537 } else { | 513 } else { |
538 if (process.IsValid() && terminate_on_shutdown) { | 514 if (process.IsValid() && terminate_on_shutdown) { |
539 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So | 515 // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So |
540 // don't this on the UI/IO threads. | 516 // don't this on the UI/IO threads. |
541 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 517 BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
542 base::Bind(&TerminateOnLauncherThread, zygote, | 518 base::Bind(&TerminateOnLauncherThread, zygote, |
543 base::Passed(&process))); | 519 base::Passed(&process))); |
544 } | 520 } |
545 } | 521 } |
546 } | 522 } |
547 | 523 |
548 void ChildProcessLauncher::Notify(ZygoteHandle zygote, | 524 void ChildProcessLauncher::Notify(ZygoteHandle zygote, |
549 #if defined(OS_ANDROID) | |
550 base::ScopedFD ipcfd, | |
551 #endif | |
552 base::Process process, | 525 base::Process process, |
553 int error_code) { | 526 int error_code) { |
554 DCHECK(CalledOnValidThread()); | 527 DCHECK(CalledOnValidThread()); |
555 starting_ = false; | 528 starting_ = false; |
556 process_ = std::move(process); | 529 process_ = std::move(process); |
557 | 530 |
558 if (process_.IsValid()) { | 531 if (process_.IsValid()) { |
559 // Set up Mojo IPC to the new process. | 532 // Set up Mojo IPC to the new process. |
560 mojo::edk::ChildProcessLaunched(process_.Handle(), | 533 mojo::edk::ChildProcessLaunched(process_.Handle(), |
561 std::move(mojo_host_platform_handle_), | 534 std::move(mojo_host_platform_handle_), |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 } | 588 } |
616 | 589 |
617 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest( | 590 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest( |
618 Client* client) { | 591 Client* client) { |
619 Client* ret = client_; | 592 Client* ret = client_; |
620 client_ = client; | 593 client_ = client; |
621 return ret; | 594 return ret; |
622 } | 595 } |
623 | 596 |
624 } // namespace content | 597 } // namespace content |
OLD | NEW |