OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "shell/child_process_host.h" | 5 #include "shell/child_process_host.h" |
6 | 6 |
7 #include "base/base_switches.h" | 7 #include "base/base_switches.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/macros.h" | 13 #include "base/macros.h" |
14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
15 #include "base/process/kill.h" | 15 #include "base/process/kill.h" |
16 #include "base/process/launch.h" | 16 #include "base/process/launch.h" |
17 #include "base/task_runner.h" | 17 #include "base/task_runner.h" |
18 #include "base/task_runner_util.h" | 18 #include "base/task_runner_util.h" |
19 #include "mojo/edk/embedder/embedder.h" | 19 #include "mojo/edk/embedder/embedder.h" |
20 #include "mojo/public/cpp/system/message_pipe.h" | 20 #include "mojo/public/cpp/system/message_pipe.h" |
21 #include "shell/context.h" | 21 #include "shell/context.h" |
22 #include "shell/switches.h" | 22 #include "shell/switches.h" |
23 #include "shell/task_runners.h" | 23 #include "shell/task_runners.h" |
24 | 24 |
25 namespace mojo { | |
26 namespace shell { | 25 namespace shell { |
27 | 26 |
28 ChildProcessHost::ChildProcessHost(Context* context) | 27 ChildProcessHost::ChildProcessHost(Context* context) |
29 : context_(context), channel_info_(nullptr) { | 28 : context_(context), channel_info_(nullptr) { |
30 } | 29 } |
31 | 30 |
32 ChildProcessHost::~ChildProcessHost() { | 31 ChildProcessHost::~ChildProcessHost() { |
33 DCHECK(!child_process_.IsValid()); | 32 DCHECK(!child_process_.IsValid()); |
34 } | 33 } |
35 | 34 |
36 void ChildProcessHost::Start() { | 35 void ChildProcessHost::Start() { |
37 DCHECK(!child_process_.IsValid()); | 36 DCHECK(!child_process_.IsValid()); |
38 | 37 |
39 ScopedMessagePipeHandle handle(embedder::CreateChannel( | 38 mojo::ScopedMessagePipeHandle handle(mojo::embedder::CreateChannel( |
40 platform_channel_pair_.PassServerHandle(), | 39 platform_channel_pair_.PassServerHandle(), |
41 context_->task_runners()->io_runner(), | 40 context_->task_runners()->io_runner(), |
42 base::Bind(&ChildProcessHost::DidCreateChannel, base::Unretained(this)), | 41 base::Bind(&ChildProcessHost::DidCreateChannel, base::Unretained(this)), |
43 base::MessageLoop::current()->message_loop_proxy())); | 42 base::MessageLoop::current()->message_loop_proxy())); |
44 | 43 |
45 controller_.Bind(handle.Pass()); | 44 controller_.Bind(handle.Pass()); |
46 controller_.set_error_handler(this); | 45 controller_.set_error_handler(this); |
47 | 46 |
48 CHECK(base::PostTaskAndReplyWithResult( | 47 CHECK(base::PostTaskAndReplyWithResult( |
49 context_->task_runners()->blocking_pool(), FROM_HERE, | 48 context_->task_runners()->blocking_pool(), FROM_HERE, |
50 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), | 49 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), |
51 base::Bind(&ChildProcessHost::DidStart, base::Unretained(this)))); | 50 base::Bind(&ChildProcessHost::DidStart, base::Unretained(this)))); |
52 } | 51 } |
53 | 52 |
54 int ChildProcessHost::Join() { | 53 int ChildProcessHost::Join() { |
55 DCHECK(child_process_.IsValid()); | 54 DCHECK(child_process_.IsValid()); |
56 int rv = -1; | 55 int rv = -1; |
57 LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) | 56 LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) |
58 << "Failed to wait for child process"; | 57 << "Failed to wait for child process"; |
59 child_process_.Close(); | 58 child_process_.Close(); |
60 return rv; | 59 return rv; |
61 } | 60 } |
62 | 61 |
63 void ChildProcessHost::StartApp( | 62 void ChildProcessHost::StartApp( |
64 const String& app_path, | 63 const mojo::String& app_path, |
65 bool clean_app_path, | 64 bool clean_app_path, |
66 InterfaceRequest<Application> application_request, | 65 mojo::InterfaceRequest<mojo::Application> application_request, |
67 const ChildController::StartAppCallback& on_app_complete) { | 66 const ChildController::StartAppCallback& on_app_complete) { |
68 DCHECK(controller_); | 67 DCHECK(controller_); |
69 | 68 |
70 on_app_complete_ = on_app_complete; | 69 on_app_complete_ = on_app_complete; |
71 controller_->StartApp( | 70 controller_->StartApp( |
72 app_path, clean_app_path, application_request.Pass(), | 71 app_path, clean_app_path, application_request.Pass(), |
73 base::Bind(&ChildProcessHost::AppCompleted, base::Unretained(this))); | 72 base::Bind(&ChildProcessHost::AppCompleted, base::Unretained(this))); |
74 } | 73 } |
75 | 74 |
76 void ChildProcessHost::ExitNow(int32_t exit_code) { | 75 void ChildProcessHost::ExitNow(int32_t exit_code) { |
77 DCHECK(controller_); | 76 DCHECK(controller_); |
78 | 77 |
79 controller_->ExitNow(exit_code); | 78 controller_->ExitNow(exit_code); |
80 } | 79 } |
81 | 80 |
82 void ChildProcessHost::DidStart(bool success) { | 81 void ChildProcessHost::DidStart(bool success) { |
83 DVLOG(2) << "ChildProcessHost::DidStart()"; | 82 DVLOG(2) << "ChildProcessHost::DidStart()"; |
84 | 83 |
85 if (!success) { | 84 if (!success) { |
86 LOG(ERROR) << "Failed to start app child process"; | 85 LOG(ERROR) << "Failed to start app child process"; |
87 AppCompleted(MOJO_RESULT_UNKNOWN); | 86 AppCompleted(MOJO_RESULT_UNKNOWN); |
88 return; | 87 return; |
89 } | 88 } |
90 } | 89 } |
91 | 90 |
92 // Callback for |embedder::CreateChannel()|. | 91 // Callback for |mojo::embedder::CreateChannel()|. |
93 void ChildProcessHost::DidCreateChannel(embedder::ChannelInfo* channel_info) { | 92 void ChildProcessHost::DidCreateChannel( |
| 93 mojo::embedder::ChannelInfo* channel_info) { |
94 DVLOG(2) << "ChildProcessHost::DidCreateChannel()"; | 94 DVLOG(2) << "ChildProcessHost::DidCreateChannel()"; |
95 | 95 |
96 CHECK(channel_info); | 96 CHECK(channel_info); |
97 channel_info_ = channel_info; | 97 channel_info_ = channel_info; |
98 } | 98 } |
99 | 99 |
100 bool ChildProcessHost::DoLaunch() { | 100 bool ChildProcessHost::DoLaunch() { |
101 static const char* kForwardSwitches[] = { | 101 static const char* kForwardSwitches[] = { |
102 switches::kTraceToConsole, switches::kV, switches::kVModule, | 102 switches::kTraceToConsole, switches::kV, switches::kVModule, |
103 }; | 103 }; |
104 | 104 |
105 base::CommandLine child_command_line(context_->mojo_shell_child_path()); | 105 base::CommandLine child_command_line(context_->mojo_shell_child_path()); |
106 child_command_line.CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(), | 106 child_command_line.CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(), |
107 kForwardSwitches, | 107 kForwardSwitches, |
108 arraysize(kForwardSwitches)); | 108 arraysize(kForwardSwitches)); |
109 child_command_line.AppendSwitch(switches::kChildProcess); | 109 child_command_line.AppendSwitch(switches::kChildProcess); |
110 | 110 |
111 embedder::HandlePassingInformation handle_passing_info; | 111 mojo::embedder::HandlePassingInformation handle_passing_info; |
112 platform_channel_pair_.PrepareToPassClientHandleToChildProcess( | 112 platform_channel_pair_.PrepareToPassClientHandleToChildProcess( |
113 &child_command_line, &handle_passing_info); | 113 &child_command_line, &handle_passing_info); |
114 | 114 |
115 base::LaunchOptions options; | 115 base::LaunchOptions options; |
116 options.fds_to_remap = &handle_passing_info; | 116 options.fds_to_remap = &handle_passing_info; |
117 DVLOG(2) << "Launching child with command line: " | 117 DVLOG(2) << "Launching child with command line: " |
118 << child_command_line.GetCommandLineString(); | 118 << child_command_line.GetCommandLineString(); |
119 child_process_ = base::LaunchProcess(child_command_line, options); | 119 child_process_ = base::LaunchProcess(child_command_line, options); |
120 if (!child_process_.IsValid()) | 120 if (!child_process_.IsValid()) |
121 return false; | 121 return false; |
122 | 122 |
123 platform_channel_pair_.ChildProcessLaunched(); | 123 platform_channel_pair_.ChildProcessLaunched(); |
124 return true; | 124 return true; |
125 } | 125 } |
126 | 126 |
127 void ChildProcessHost::AppCompleted(int32_t result) { | 127 void ChildProcessHost::AppCompleted(int32_t result) { |
128 if (!on_app_complete_.is_null()) { | 128 if (!on_app_complete_.is_null()) { |
129 auto on_app_complete = on_app_complete_; | 129 auto on_app_complete = on_app_complete_; |
130 on_app_complete_.reset(); | 130 on_app_complete_.reset(); |
131 on_app_complete.Run(result); | 131 on_app_complete.Run(result); |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 void ChildProcessHost::OnConnectionError() { | 135 void ChildProcessHost::OnConnectionError() { |
136 AppCompleted(MOJO_RESULT_UNKNOWN); | 136 AppCompleted(MOJO_RESULT_UNKNOWN); |
137 } | 137 } |
138 | 138 |
139 } // namespace shell | 139 } // namespace shell |
140 } // namespace mojo | |
OLD | NEW |