| Index: mojo/shell/child_process_host.cc | 
| diff --git a/mojo/shell/child_process_host.cc b/mojo/shell/child_process_host.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..b8f7508f2cfee51c039f105041f1b658b0e61d1c | 
| --- /dev/null | 
| +++ b/mojo/shell/child_process_host.cc | 
| @@ -0,0 +1,89 @@ | 
| +// Copyright 2014 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "mojo/shell/child_process_host.h" | 
| + | 
| +#include "base/base_switches.h" | 
| +#include "base/bind.h" | 
| +#include "base/command_line.h" | 
| +#include "base/location.h" | 
| +#include "base/logging.h" | 
| +#include "base/macros.h" | 
| +#include "base/process/kill.h" | 
| +#include "base/process/launch.h" | 
| +#include "base/task_runner.h" | 
| +#include "base/task_runner_util.h" | 
| +#include "mojo/shell/context.h" | 
| +#include "mojo/shell/switches.h" | 
| + | 
| +namespace mojo { | 
| +namespace shell { | 
| + | 
| +ChildProcessHost::ChildProcessHost(Context* context) : context_(context) { | 
| +  platform_channel_ = platform_channel_pair_.PassServerHandle(); | 
| +  CHECK(platform_channel_.is_valid()); | 
| +} | 
| + | 
| +ChildProcessHost::~ChildProcessHost() { | 
| +  if (child_process_.IsValid()) { | 
| +    LOG(WARNING) << "Destroying ChildProcessHost with unjoined child"; | 
| +    child_process_.Close(); | 
| +  } | 
| +} | 
| + | 
| +void ChildProcessHost::Start() { | 
| +  DCHECK(!child_process_.IsValid()); | 
| + | 
| +  WillStart(); | 
| + | 
| +  CHECK(base::PostTaskAndReplyWithResult( | 
| +      context_->task_runners()->blocking_pool(), FROM_HERE, | 
| +      base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), | 
| +      base::Bind(&ChildProcessHost::DidStart, base::Unretained(this)))); | 
| +} | 
| + | 
| +int ChildProcessHost::Join() { | 
| +  DCHECK(child_process_.IsValid()); | 
| +  int rv = -1; | 
| +  LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) | 
| +      << "Failed to wait for child process"; | 
| +  child_process_.Close(); | 
| +  return rv; | 
| +} | 
| + | 
| +bool ChildProcessHost::DoLaunch() { | 
| +  static const char* kForwardSwitches[] = { | 
| +      switches::kTraceToConsole, switches::kV, switches::kVModule, | 
| +  }; | 
| + | 
| +  const base::CommandLine* parent_command_line = | 
| +      base::CommandLine::ForCurrentProcess(); | 
| +  base::CommandLine child_command_line(parent_command_line->GetProgram()); | 
| +  child_command_line.CopySwitchesFrom(*parent_command_line, kForwardSwitches, | 
| +                                      arraysize(kForwardSwitches)); | 
| +  child_command_line.AppendSwitch(switches::kChildProcess); | 
| + | 
| +  embedder::HandlePassingInformation handle_passing_info; | 
| +  platform_channel_pair_.PrepareToPassClientHandleToChildProcess( | 
| +      &child_command_line, &handle_passing_info); | 
| + | 
| +  base::LaunchOptions options; | 
| +#if defined(OS_WIN) | 
| +  options.start_hidden = true; | 
| +  options.handles_to_inherit = &handle_passing_info; | 
| +#elif defined(OS_POSIX) | 
| +  options.fds_to_remap = &handle_passing_info; | 
| +#endif | 
| +  DVLOG(2) << "Launching child with command line: " | 
| +           << child_command_line.GetCommandLineString(); | 
| +  child_process_ = base::LaunchProcess(child_command_line, options); | 
| +  if (!child_process_.IsValid()) | 
| +    return false; | 
| + | 
| +  platform_channel_pair_.ChildProcessLaunched(); | 
| +  return true; | 
| +} | 
| + | 
| +}  // namespace shell | 
| +}  // namespace mojo | 
|  |