Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / mojo / shell / child_process_host.cc
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.
4
5 #include "mojo/shell/child_process_host.h"
6
7 #include "base/base_switches.h"
8 #include "base/bind.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"
20
21 namespace mojo {
22 namespace shell {
23
24 ChildProcessHost::ChildProcessHost(Context* context,
25                                    Delegate* delegate,
26                                    ChildProcess::Type type)
27     : context_(context),
28       delegate_(delegate),
29       type_(type),
30       child_process_handle_(base::kNullProcessHandle) {
31   DCHECK(delegate);
32   platform_channel_ = platform_channel_pair_.PassServerHandle();
33   CHECK(platform_channel_.is_valid());
34 }
35
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;
41   }
42 }
43
44 void ChildProcessHost::Start() {
45   DCHECK_EQ(child_process_handle_, base::kNullProcessHandle);
46
47   delegate_->WillStart();
48
49   CHECK(base::PostTaskAndReplyWithResult(
50       context_->task_runners()->blocking_pool(),
51       FROM_HERE,
52       base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)),
53       base::Bind(&ChildProcessHost::DidLaunch, base::Unretained(this))));
54 }
55
56 int ChildProcessHost::Join() {
57   DCHECK_NE(child_process_handle_, base::kNullProcessHandle);
58   int rv = -1;
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;
63   return rv;
64 }
65
66 bool ChildProcessHost::DoLaunch() {
67   static const char* kForwardSwitches[] = {
68     switches::kTraceToConsole,
69     switches::kV,
70     switches::kVModule,
71   };
72
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_)));
80
81   embedder::HandlePassingInformation handle_passing_info;
82   platform_channel_pair_.PrepareToPassClientHandleToChildProcess(
83       &child_command_line, &handle_passing_info);
84
85   base::LaunchOptions options;
86 #if defined(OS_WIN)
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;
91 #endif
92
93   if (!base::LaunchProcess(child_command_line, options, &child_process_handle_))
94     return false;
95
96   platform_channel_pair_.ChildProcessLaunched();
97   return true;
98 }
99
100 void ChildProcessHost::DidLaunch(bool success) {
101   delegate_->DidStart(success);
102 }
103
104 }  // namespace shell
105 }  // namespace mojo