Fix layout of the Connection Tab of the Origin Info Bubble.
[chromium-blink-merge.git] / mojo / runner / child_process_host.cc
blobf5fe0f54f22308a033c32d1bd81fb610e3a6cbe0
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/runner/child_process_host.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "base/message_loop/message_loop.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 "base/thread_task_runner_handle.h"
18 #include "mojo/edk/embedder/embedder.h"
19 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
20 #include "mojo/public/cpp/system/core.h"
21 #include "mojo/runner/context.h"
22 #include "mojo/runner/switches.h"
23 #include "mojo/runner/task_runners.h"
25 #if defined(OS_LINUX) && !defined(OS_ANDROID)
26 #include "sandbox/linux/services/namespace_sandbox.h"
27 #endif
29 namespace mojo {
30 namespace runner {
32 ChildProcessHost::ChildProcessHost(Context* context,
33 bool start_sandboxed,
34 const base::FilePath& app_path)
35 : context_(context),
36 start_sandboxed_(start_sandboxed),
37 app_path_(app_path),
38 channel_info_(nullptr) {
39 platform_channel_ = platform_channel_pair_.PassServerHandle();
40 CHECK(platform_channel_.is_valid());
43 ChildProcessHost::~ChildProcessHost() {
44 if (child_process_.IsValid()) {
45 LOG(WARNING) << "Destroying ChildProcessHost with unjoined child";
46 child_process_.Close();
50 void ChildProcessHost::Start() {
51 DCHECK(!child_process_.IsValid());
52 DCHECK(platform_channel_.is_valid());
54 ScopedMessagePipeHandle handle(embedder::CreateChannel(
55 platform_channel_.Pass(),
56 base::Bind(&ChildProcessHost::DidCreateChannel, base::Unretained(this)),
57 base::ThreadTaskRunnerHandle::Get()));
59 controller_.Bind(InterfacePtrInfo<ChildController>(handle.Pass(), 0u));
61 CHECK(base::PostTaskAndReplyWithResult(
62 context_->task_runners()->blocking_pool(), FROM_HERE,
63 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)),
64 base::Bind(&ChildProcessHost::DidStart, base::Unretained(this))));
67 int ChildProcessHost::Join() {
68 DCHECK(child_process_.IsValid());
69 int rv = -1;
70 LOG_IF(ERROR, !child_process_.WaitForExit(&rv))
71 << "Failed to wait for child process";
72 child_process_.Close();
73 return rv;
76 void ChildProcessHost::StartApp(
77 InterfaceRequest<Application> application_request,
78 const ChildController::StartAppCallback& on_app_complete) {
79 DCHECK(controller_);
81 on_app_complete_ = on_app_complete;
82 controller_->StartApp(
83 application_request.Pass(),
84 base::Bind(&ChildProcessHost::AppCompleted, base::Unretained(this)));
87 void ChildProcessHost::ExitNow(int32_t exit_code) {
88 DCHECK(controller_);
90 controller_->ExitNow(exit_code);
93 void ChildProcessHost::DidStart(bool success) {
94 DVLOG(2) << "ChildProcessHost::DidStart()";
96 if (!success) {
97 LOG(ERROR) << "Failed to start child process";
98 AppCompleted(MOJO_RESULT_UNKNOWN);
99 return;
103 bool ChildProcessHost::DoLaunch() {
104 const base::CommandLine* parent_command_line =
105 base::CommandLine::ForCurrentProcess();
106 base::CommandLine child_command_line(parent_command_line->GetProgram());
107 child_command_line.AppendArguments(*parent_command_line, false);
108 child_command_line.AppendSwitchPath(switches::kChildProcess, app_path_);
110 if (start_sandboxed_)
111 child_command_line.AppendSwitch(switches::kEnableSandbox);
113 embedder::HandlePassingInformation handle_passing_info;
114 platform_channel_pair_.PrepareToPassClientHandleToChildProcess(
115 &child_command_line, &handle_passing_info);
117 base::LaunchOptions options;
118 #if defined(OS_WIN)
119 options.handles_to_inherit = &handle_passing_info;
120 #elif defined(OS_POSIX)
121 handle_passing_info.push_back(std::make_pair(STDIN_FILENO, STDIN_FILENO));
122 handle_passing_info.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO));
123 handle_passing_info.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO));
124 options.fds_to_remap = &handle_passing_info;
125 #endif
126 DVLOG(2) << "Launching child with command line: "
127 << child_command_line.GetCommandLineString();
128 #if defined(OS_LINUX) && !defined(OS_ANDROID)
129 if (start_sandboxed_) {
130 child_process_ =
131 sandbox::NamespaceSandbox::LaunchProcess(child_command_line, options);
132 if (!child_process_.IsValid()) {
133 LOG(ERROR) << "Starting the process with a sandbox failed. Missing kernel"
134 << " support.";
135 return false;
137 } else
138 #endif
139 child_process_ = base::LaunchProcess(child_command_line, options);
141 if (!child_process_.IsValid())
142 return false;
144 platform_channel_pair_.ChildProcessLaunched();
145 return true;
148 void ChildProcessHost::AppCompleted(int32_t result) {
149 if (!on_app_complete_.is_null()) {
150 auto on_app_complete = on_app_complete_;
151 on_app_complete_.reset();
152 on_app_complete.Run(result);
156 void ChildProcessHost::DidCreateChannel(embedder::ChannelInfo* channel_info) {
157 DVLOG(2) << "AppChildProcessHost::DidCreateChannel()";
159 CHECK(channel_info);
160 channel_info_ = channel_info;
163 } // namespace runner
164 } // namespace mojo