diff options
Diffstat (limited to 'chromium/content/browser/child_process_launcher.cc')
-rw-r--r-- | chromium/content/browser/child_process_launcher.cc | 121 |
1 files changed, 94 insertions, 27 deletions
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc index 57a6368cb7d..47205b630c1 100644 --- a/chromium/content/browser/child_process_launcher.cc +++ b/chromium/content/browser/child_process_launcher.cc @@ -13,6 +13,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" +#include "base/process/launch.h" #include "base/process/process.h" #include "base/strings/string_number_conversions.h" #include "base/synchronization/lock.h" @@ -23,9 +24,13 @@ #include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" #include "content/public/common/sandboxed_process_launcher_delegate.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" #if defined(OS_WIN) #include "base/files/file_path.h" +#include "base/win/scoped_handle.h" +#include "base/win/win_util.h" #include "content/common/sandbox_win.h" #include "content/public/common/sandbox_init.h" #elif defined(OS_MACOSX) @@ -39,8 +44,10 @@ #elif defined(OS_POSIX) #include "base/memory/singleton.h" #include "content/browser/renderer_host/render_sandbox_host_linux.h" +#include "content/browser/zygote_host/zygote_communication_linux.h" #include "content/browser/zygote_host/zygote_host_impl_linux.h" #include "content/common/child_process_sandbox_support_impl_linux.h" +#include "content/public/browser/zygote_handle_linux.h" #endif #if defined(OS_POSIX) @@ -53,9 +60,10 @@ namespace content { namespace { -typedef base::Callback<void(bool, +typedef base::Callback<void(ZygoteHandle, #if defined(OS_ANDROID) base::ScopedFD, + base::ScopedFD, #endif base::Process)> NotifyCallback; @@ -79,6 +87,7 @@ void OnChildProcessStartedAndroid(const NotifyCallback& callback, BrowserThread::ID client_thread_id, const base::TimeTicks begin_launch_time, base::ScopedFD ipcfd, + base::ScopedFD mojo_fd, base::ProcessHandle handle) { // This can be called on the launcher thread or UI thread. base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; @@ -87,8 +96,8 @@ void OnChildProcessStartedAndroid(const NotifyCallback& callback, base::Bind(&RecordHistogramsOnLauncherThread, launch_time)); base::Closure callback_on_client_thread( - base::Bind(callback, false, base::Passed(&ipcfd), - base::Passed(base::Process(handle)))); + base::Bind(callback, nullptr, base::Passed(&ipcfd), + base::Passed(&mojo_fd), base::Passed(base::Process(handle)))); if (BrowserThread::CurrentlyOn(client_thread_id)) { callback_on_client_thread.Run(); } else { @@ -105,18 +114,19 @@ void LaunchOnLauncherThread(const NotifyCallback& callback, #if defined(OS_ANDROID) base::ScopedFD ipcfd, #endif + mojo::edk::ScopedPlatformHandle client_handle, base::CommandLine* cmd_line) { DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); +#if !defined(OS_ANDROID) + ZygoteHandle zygote = nullptr; +#endif #if defined(OS_WIN) - bool use_zygote = false; bool launch_elevated = delegate->ShouldLaunchElevated(); #elif defined(OS_MACOSX) - bool use_zygote = false; base::EnvironmentMap env = delegate->GetEnvironment(); base::ScopedFD ipcfd = delegate->TakeIpcFd(); #elif defined(OS_POSIX) && !defined(OS_ANDROID) - bool use_zygote = delegate->ShouldUseZygote(); base::EnvironmentMap env = delegate->GetEnvironment(); base::ScopedFD ipcfd = delegate->TakeIpcFd(); #endif @@ -126,11 +136,19 @@ void LaunchOnLauncherThread(const NotifyCallback& callback, base::Process process; #if defined(OS_WIN) if (launch_elevated) { + // TODO(rockot): We may want to support Mojo IPC to elevated processes as + // well, but this isn't currently feasible without sharing a pipe path on + // the command line as elevated process launch goes through ShellExecuteEx. base::LaunchOptions options; options.start_hidden = true; process = base::LaunchElevatedProcess(*cmd_line, options); } else { - process = StartSandboxedProcess(delegate, cmd_line); + base::HandlesToInheritVector handles; + handles.push_back(client_handle.get().handle); + cmd_line->AppendSwitchASCII( + mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch, + base::UintToString(base::win::HandleToUint32(handles[0]))); + process = StartSandboxedProcess(delegate, cmd_line, handles); } #elif defined(OS_POSIX) std::string process_type = @@ -138,10 +156,17 @@ void LaunchOnLauncherThread(const NotifyCallback& callback, scoped_ptr<FileDescriptorInfo> files_to_register( FileDescriptorInfoImpl::Create()); + base::ScopedFD mojo_fd(client_handle.release().handle); + DCHECK(mojo_fd.is_valid()); + #if defined(OS_ANDROID) - files_to_register->Share(kPrimaryIPCChannel, ipcfd.get()); + if (ipcfd.get() != -1) + files_to_register->Share(kPrimaryIPCChannel, ipcfd.get()); + files_to_register->Share(kMojoIPCChannel, mojo_fd.get()); #else - files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd)); + if (ipcfd.get() != -1) + files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd)); + files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd)); #endif #endif @@ -154,6 +179,31 @@ void LaunchOnLauncherThread(const NotifyCallback& callback, #endif ); #if defined(V8_USE_EXTERNAL_STARTUP_DATA) + bool snapshot_loaded = false; +#if defined(OS_ANDROID) + base::MemoryMappedFile::Region region; + auto maybe_register = [®ion, ®ions, &files_to_register](int key, + int fd) { + if (fd != -1) { + files_to_register->Share(key, fd); + regions.insert(std::make_pair(key, region)); + } + }; + maybe_register( + kV8NativesDataDescriptor32, + gin::V8Initializer::GetOpenNativesFileForChildProcesses(®ion, true)); + maybe_register( + kV8NativesDataDescriptor64, + gin::V8Initializer::GetOpenNativesFileForChildProcesses(®ion, false)); + maybe_register( + kV8SnapshotDataDescriptor32, + gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(®ion, true)); + maybe_register( + kV8SnapshotDataDescriptor64, + gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(®ion, false)); + + snapshot_loaded = true; +#else base::PlatformFile natives_pf = gin::V8Initializer::GetOpenNativesFileForChildProcesses( ®ions[kV8NativesDataDescriptor]); @@ -167,13 +217,15 @@ void LaunchOnLauncherThread(const NotifyCallback& callback, // Failure to load the V8 snapshot is not necessarily an error. V8 can start // up (slower) without the snapshot. if (snapshot_pf != -1) { + snapshot_loaded = true; files_to_register->Share(kV8SnapshotDataDescriptor, snapshot_pf); regions.insert(std::make_pair(kV8SnapshotDataDescriptor, snapshot_region)); } +#endif if (process_type != switches::kZygoteProcess) { cmd_line->AppendSwitch(::switches::kV8NativesPassedByFD); - if (snapshot_pf != -1) { + if (snapshot_loaded) { cmd_line->AppendSwitch(::switches::kV8SnapshotPassedByFD); } } @@ -192,15 +244,24 @@ void LaunchOnLauncherThread(const NotifyCallback& callback, StartChildProcess( cmd_line->argv(), child_process_id, std::move(files_to_register), regions, base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id, - begin_launch_time, base::Passed(&ipcfd))); + begin_launch_time, base::Passed(&ipcfd), + base::Passed(&mojo_fd))); #elif defined(OS_POSIX) // We need to close the client end of the IPC channel to reliably detect // child termination. #if !defined(OS_MACOSX) - if (use_zygote) { - base::ProcessHandle handle = ZygoteHostImpl::GetInstance()->ForkRequest( + ZygoteHandle* zygote_handle = delegate->GetZygote(); + // If |zygote_handle| is null, a zygote should not be used. + if (zygote_handle) { + // This code runs on the PROCESS_LAUNCHER thread so race conditions are not + // an issue with the lazy initialization. + if (*zygote_handle == nullptr) { + *zygote_handle = CreateZygote(); + } + zygote = *zygote_handle; + base::ProcessHandle handle = zygote->ForkRequest( cmd_line->argv(), std::move(files_to_register), process_type); process = base::Process(handle); } else @@ -278,13 +339,11 @@ void LaunchOnLauncherThread(const NotifyCallback& callback, begin_launch_time); } BrowserThread::PostTask(client_thread_id, FROM_HERE, - base::Bind(callback, - use_zygote, - base::Passed(&process))); + base::Bind(callback, zygote, base::Passed(&process))); #endif // !defined(OS_ANDROID) } -void TerminateOnLauncherThread(bool zygote, base::Process process) { +void TerminateOnLauncherThread(ZygoteHandle zygote, base::Process process) { DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); #if defined(OS_ANDROID) VLOG(1) << "ChromeProcess: Stopping process with handle " @@ -300,7 +359,7 @@ void TerminateOnLauncherThread(bool zygote, base::Process process) { if (zygote) { // If the renderer was created via a zygote, we have to proxy the reaping // through the zygote process. - ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(process.Handle()); + zygote->EnsureProcessTerminated(process.Handle()); } else #endif // !OS_MACOSX base::EnsureProcessTerminated(std::move(process)); @@ -330,7 +389,7 @@ ChildProcessLauncher::ChildProcessLauncher( : client_(client), termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION), exit_code_(RESULT_CODE_NORMAL_EXIT), - zygote_(false), + zygote_(nullptr), starting_(true), #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \ @@ -386,6 +445,8 @@ void ChildProcessLauncher::Launch( NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch, weak_factory_.GetWeakPtr(), terminate_child_on_shutdown_)); + mojo::edk::ScopedPlatformHandle client_handle = + mojo_platform_channel_.PassClientHandle(); BrowserThread::PostTask( BrowserThread::PROCESS_LAUNCHER, FROM_HERE, base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_, @@ -393,15 +454,15 @@ void ChildProcessLauncher::Launch( #if defined(OS_ANDROID) base::Passed(&ipcfd), #endif - cmd_line)); + base::Passed(&client_handle), cmd_line)); } void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) { DCHECK(CalledOnValidThread()); #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) if (zygote_) { - termination_status_ = ZygoteHostImpl::GetInstance()-> - GetTerminationStatus(process_.Handle(), known_dead, &exit_code_); + termination_status_ = zygote_->GetTerminationStatus( + process_.Handle(), known_dead, &exit_code_); } else if (known_dead) { termination_status_ = base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_); @@ -434,9 +495,10 @@ void ChildProcessLauncher::SetProcessBackgrounded(bool background) { void ChildProcessLauncher::DidLaunch( base::WeakPtr<ChildProcessLauncher> instance, bool terminate_on_shutdown, - bool zygote, + ZygoteHandle zygote, #if defined(OS_ANDROID) base::ScopedFD ipcfd, + base::ScopedFD mojo_fd, #endif base::Process process) { if (!process.IsValid()) @@ -459,16 +521,21 @@ void ChildProcessLauncher::DidLaunch( } } -void ChildProcessLauncher::Notify( - bool zygote, +void ChildProcessLauncher::Notify(ZygoteHandle zygote, #if defined(OS_ANDROID) - base::ScopedFD ipcfd, + base::ScopedFD ipcfd, #endif - base::Process process) { + base::Process process) { DCHECK(CalledOnValidThread()); starting_ = false; process_ = std::move(process); + if (process_.IsValid()) { + // Set up Mojo IPC to the new process. + mojo::edk::ChildProcessLaunched(process_.Handle(), + mojo_platform_channel_.PassServerHandle()); + } + #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) zygote_ = zygote; #endif |