Add long running gmail memory benchmark for background tab.
[chromium-blink-merge.git] / mojo / runner / child_process_host.cc
blob1cf288c4ebcdade9db0c95794295ba526a744fe2
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 bool clean_app_path)
36 : context_(context),
37 start_sandboxed_(start_sandboxed),
38 app_path_(app_path),
39 clean_app_path_(clean_app_path),
40 channel_info_(nullptr) {
41 platform_channel_ = platform_channel_pair_.PassServerHandle();
42 CHECK(platform_channel_.is_valid());
45 ChildProcessHost::~ChildProcessHost() {
46 if (child_process_.IsValid()) {
47 LOG(WARNING) << "Destroying ChildProcessHost with unjoined child";
48 child_process_.Close();
52 void ChildProcessHost::Start() {
53 DCHECK(!child_process_.IsValid());
54 DCHECK(platform_channel_.is_valid());
56 ScopedMessagePipeHandle handle(embedder::CreateChannel(
57 platform_channel_.Pass(),
58 base::Bind(&ChildProcessHost::DidCreateChannel, base::Unretained(this)),
59 base::ThreadTaskRunnerHandle::Get()));
61 controller_.Bind(InterfacePtrInfo<ChildController>(handle.Pass(), 0u));
63 CHECK(base::PostTaskAndReplyWithResult(
64 context_->task_runners()->blocking_pool(), FROM_HERE,
65 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)),
66 base::Bind(&ChildProcessHost::DidStart, base::Unretained(this))));
69 int ChildProcessHost::Join() {
70 DCHECK(child_process_.IsValid());
71 int rv = -1;
72 LOG_IF(ERROR, !child_process_.WaitForExit(&rv))
73 << "Failed to wait for child process";
74 child_process_.Close();
75 return rv;
78 void ChildProcessHost::StartApp(
79 InterfaceRequest<Application> application_request,
80 const ChildController::StartAppCallback& on_app_complete) {
81 DCHECK(controller_);
83 on_app_complete_ = on_app_complete;
84 controller_->StartApp(
85 application_request.Pass(),
86 base::Bind(&ChildProcessHost::AppCompleted, base::Unretained(this)));
89 void ChildProcessHost::ExitNow(int32_t exit_code) {
90 DCHECK(controller_);
92 controller_->ExitNow(exit_code);
95 void ChildProcessHost::DidStart(bool success) {
96 DVLOG(2) << "ChildProcessHost::DidStart()";
98 if (!success) {
99 LOG(ERROR) << "Failed to start child process";
100 AppCompleted(MOJO_RESULT_UNKNOWN);
101 return;
105 bool ChildProcessHost::DoLaunch() {
106 const base::CommandLine* parent_command_line =
107 base::CommandLine::ForCurrentProcess();
108 base::CommandLine child_command_line(parent_command_line->GetProgram());
109 child_command_line.AppendArguments(*parent_command_line, false);
110 child_command_line.AppendSwitchPath(switches::kChildProcess, app_path_);
112 if (clean_app_path_)
113 child_command_line.AppendSwitch(switches::kDeleteAfterLoad);
115 if (start_sandboxed_)
116 child_command_line.AppendSwitch(switches::kEnableSandbox);
118 embedder::HandlePassingInformation handle_passing_info;
119 platform_channel_pair_.PrepareToPassClientHandleToChildProcess(
120 &child_command_line, &handle_passing_info);
122 base::LaunchOptions options;
123 #if defined(OS_WIN)
124 options.handles_to_inherit = &handle_passing_info;
125 #elif defined(OS_POSIX)
126 handle_passing_info.push_back(std::make_pair(STDIN_FILENO, STDIN_FILENO));
127 handle_passing_info.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO));
128 handle_passing_info.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO));
129 options.fds_to_remap = &handle_passing_info;
130 #endif
131 DVLOG(2) << "Launching child with command line: "
132 << child_command_line.GetCommandLineString();
133 #if defined(OS_LINUX) && !defined(OS_ANDROID)
134 if (start_sandboxed_) {
135 child_process_ =
136 sandbox::NamespaceSandbox::LaunchProcess(child_command_line, options);
137 if (!child_process_.IsValid()) {
138 LOG(ERROR) << "Starting the process with a sandbox failed. Missing kernel"
139 << " support.";
140 return false;
142 } else
143 #endif
144 child_process_ = base::LaunchProcess(child_command_line, options);
146 if (!child_process_.IsValid())
147 return false;
149 platform_channel_pair_.ChildProcessLaunched();
150 return true;
153 void ChildProcessHost::AppCompleted(int32_t result) {
154 if (!on_app_complete_.is_null()) {
155 auto on_app_complete = on_app_complete_;
156 on_app_complete_.reset();
157 on_app_complete.Run(result);
161 void ChildProcessHost::DidCreateChannel(embedder::ChannelInfo* channel_info) {
162 DVLOG(2) << "AppChildProcessHost::DidCreateChannel()";
164 CHECK(channel_info);
165 channel_info_ = channel_info;
168 } // namespace runner
169 } // namespace mojo