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