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/strings/string_number_conversions.h"
16 #include "base/task_runner.h"
17 #include "base/task_runner_util.h"
18 #include "mojo/shell/context.h"
19 #include "mojo/shell/switches.h"
24 ChildProcessHost::ChildProcessHost(Context
* context
,
26 ChildProcess::Type type
)
30 child_process_handle_(base::kNullProcessHandle
) {
32 platform_channel_
= platform_channel_pair_
.PassServerHandle();
33 CHECK(platform_channel_
.is_valid());
36 ChildProcessHost::~ChildProcessHost() {
37 if (child_process_handle_
!= base::kNullProcessHandle
) {
38 LOG(WARNING
) << "Destroying ChildProcessHost with unjoined child";
39 base::CloseProcessHandle(child_process_handle_
);
40 child_process_handle_
= base::kNullProcessHandle
;
44 void ChildProcessHost::Start() {
45 DCHECK_EQ(child_process_handle_
, base::kNullProcessHandle
);
47 delegate_
->WillStart();
49 CHECK(base::PostTaskAndReplyWithResult(
50 context_
->task_runners()->blocking_pool(),
52 base::Bind(&ChildProcessHost::DoLaunch
, base::Unretained(this)),
53 base::Bind(&ChildProcessHost::DidLaunch
, base::Unretained(this))));
56 int ChildProcessHost::Join() {
57 DCHECK_NE(child_process_handle_
, base::kNullProcessHandle
);
59 // Note: |WaitForExitCode()| closes the process handle.
60 LOG_IF(ERROR
, !base::WaitForExitCode(child_process_handle_
, &rv
))
61 << "Failed to wait for child process";
62 child_process_handle_
= base::kNullProcessHandle
;
66 bool ChildProcessHost::DoLaunch() {
67 static const char* kForwardSwitches
[] = {
68 switches::kTraceToConsole
,
73 const base::CommandLine
* parent_command_line
=
74 base::CommandLine::ForCurrentProcess();
75 base::CommandLine
child_command_line(parent_command_line
->GetProgram());
76 child_command_line
.CopySwitchesFrom(*parent_command_line
, kForwardSwitches
,
77 arraysize(kForwardSwitches
));
78 child_command_line
.AppendSwitchASCII(
79 switches::kChildProcessType
, base::IntToString(static_cast<int>(type_
)));
81 embedder::HandlePassingInformation handle_passing_info
;
82 platform_channel_pair_
.PrepareToPassClientHandleToChildProcess(
83 &child_command_line
, &handle_passing_info
);
85 base::LaunchOptions options
;
87 options
.start_hidden
= true;
88 options
.handles_to_inherit
= &handle_passing_info
;
89 #elif defined(OS_POSIX)
90 options
.fds_to_remap
= &handle_passing_info
;
93 if (!base::LaunchProcess(child_command_line
, options
, &child_process_handle_
))
96 platform_channel_pair_
.ChildProcessLaunched();
100 void ChildProcessHost::DidLaunch(bool success
) {
101 delegate_
->DidStart(success
);