1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "mojo/shell/child_process_host.h"
7 #include "base/base_switches.h"
9 #include "base/command_line.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/process/kill.h"
14 #include "base/process/launch.h"
15 #include "base/task_runner.h"
16 #include "base/task_runner_util.h"
17 #include "mojo/shell/context.h"
18 #include "mojo/shell/switches.h"
23 ChildProcessHost::ChildProcessHost(Context
* context
) : context_(context
) {
24 platform_channel_
= platform_channel_pair_
.PassServerHandle();
25 CHECK(platform_channel_
.is_valid());
28 ChildProcessHost::~ChildProcessHost() {
29 if (child_process_
.IsValid()) {
30 LOG(WARNING
) << "Destroying ChildProcessHost with unjoined child";
31 child_process_
.Close();
35 void ChildProcessHost::Start() {
36 DCHECK(!child_process_
.IsValid());
40 CHECK(base::PostTaskAndReplyWithResult(
41 context_
->task_runners()->blocking_pool(), FROM_HERE
,
42 base::Bind(&ChildProcessHost::DoLaunch
, base::Unretained(this)),
43 base::Bind(&ChildProcessHost::DidStart
, base::Unretained(this))));
46 int ChildProcessHost::Join() {
47 DCHECK(child_process_
.IsValid());
49 LOG_IF(ERROR
, !child_process_
.WaitForExit(&rv
))
50 << "Failed to wait for child process";
51 child_process_
.Close();
55 bool ChildProcessHost::DoLaunch() {
56 static const char* kForwardSwitches
[] = {
57 switches::kTraceToConsole
, switches::kV
, switches::kVModule
,
60 const base::CommandLine
* parent_command_line
=
61 base::CommandLine::ForCurrentProcess();
62 base::CommandLine
child_command_line(parent_command_line
->GetProgram());
63 child_command_line
.CopySwitchesFrom(*parent_command_line
, kForwardSwitches
,
64 arraysize(kForwardSwitches
));
65 child_command_line
.AppendSwitch(switches::kChildProcess
);
67 embedder::HandlePassingInformation handle_passing_info
;
68 platform_channel_pair_
.PrepareToPassClientHandleToChildProcess(
69 &child_command_line
, &handle_passing_info
);
71 base::LaunchOptions options
;
73 options
.start_hidden
= true;
74 options
.handles_to_inherit
= &handle_passing_info
;
75 #elif defined(OS_POSIX)
76 options
.fds_to_remap
= &handle_passing_info
;
78 DVLOG(2) << "Launching child with command line: "
79 << child_command_line
.GetCommandLineString();
80 child_process_
= base::LaunchProcess(child_command_line
, options
);
81 if (!child_process_
.IsValid())
84 platform_channel_pair_
.ChildProcessLaunched();