1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/shell/child_process_host.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/base_switches.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/command_line.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/location.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/macros.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/process/kill.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/process/launch.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/task_runner.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/task_runner_util.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/shell/context.h" 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/shell/switches.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace mojo { 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace shell { 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ChildProcessHost::ChildProcessHost(Context* context, 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Delegate* delegate, 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ChildProcess::Type type) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : context_(context), 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_(delegate), 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type_(type), 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) child_process_handle_(base::kNullProcessHandle) { 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(delegate); 3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) platform_channel_ = platform_channel_pair_.PassServerHandle(); 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CHECK(platform_channel_.is_valid()); 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ChildProcessHost::~ChildProcessHost() { 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (child_process_handle_ != base::kNullProcessHandle) { 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(WARNING) << "Destroying ChildProcessHost with unjoined child"; 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::CloseProcessHandle(child_process_handle_); 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) child_process_handle_ = base::kNullProcessHandle; 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ChildProcessHost::Start() { 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(child_process_handle_, base::kNullProcessHandle); 4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) delegate_->WillStart(); 4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CHECK(base::PostTaskAndReplyWithResult( 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) context_->task_runners()->blocking_pool(), 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&ChildProcessHost::DidLaunch, base::Unretained(this)))); 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int ChildProcessHost::Join() { 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_NE(child_process_handle_, base::kNullProcessHandle); 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int rv = -1; 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG_IF(ERROR, !base::WaitForExitCode(child_process_handle_, &rv)) 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Failed to wait for child process"; 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::CloseProcessHandle(child_process_handle_); 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) child_process_handle_ = base::kNullProcessHandle; 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return rv; 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ChildProcessHost::DoLaunch() { 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const char* kForwardSwitches[] = { 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switches::kTraceToConsole, 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switches::kV, 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switches::kVModule, 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::CommandLine* parent_command_line = 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine::ForCurrentProcess(); 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine child_command_line(parent_command_line->GetProgram()); 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) child_command_line.CopySwitchesFrom(*parent_command_line, kForwardSwitches, 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) arraysize(kForwardSwitches)); 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) child_command_line.AppendSwitchASCII( 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switches::kChildProcessType, base::IntToString(static_cast<int>(type_))); 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) embedder::HandlePassingInformation handle_passing_info; 8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) platform_channel_pair_.PrepareToPassClientHandleToChildProcess( 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &child_command_line, &handle_passing_info); 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::LaunchOptions options; 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN) 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) options.start_hidden = true; 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) options.handles_to_inherit = &handle_passing_info; 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_POSIX) 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) options.fds_to_remap = &handle_passing_info; 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!base::LaunchProcess(child_command_line, options, &child_process_handle_)) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) platform_channel_pair_.ChildProcessLaunched(); 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ChildProcessHost::DidLaunch(bool success) { 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->DidStart(success); 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace shell 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace mojo 106