OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "mojo/shell/runner/child/runner_connection.h" | 5 #include "mojo/shell/runner/child/runner_connection.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 ~RunnerConnectionImpl() override { | 89 ~RunnerConnectionImpl() override { |
90 controller_runner_->PostTask( | 90 controller_runner_->PostTask( |
91 FROM_HERE, base::Bind(&RunnerConnectionImpl::ShutdownOnControllerThread, | 91 FROM_HERE, base::Bind(&RunnerConnectionImpl::ShutdownOnControllerThread, |
92 base::Unretained(this))); | 92 base::Unretained(this))); |
93 controller_thread_.Stop(); | 93 controller_thread_.Stop(); |
94 } | 94 } |
95 | 95 |
96 // Returns true if a connection to the runner has been established and | 96 // Returns true if a connection to the runner has been established and |
97 // |request| has been modified, false if no connection was established. | 97 // |request| has been modified, false if no connection was established. |
98 bool WaitForApplicationRequest(InterfaceRequest<mojom::ShellClient>* request, | 98 bool WaitForApplicationRequest(InterfaceRequest<mojom::ShellClient>* request, |
99 ScopedMessagePipeHandle handle); | 99 ScopedMessagePipeHandle handle, |
| 100 bool exit_on_error); |
100 | 101 |
101 ChildControllerImpl* controller() const { return controller_.get(); } | 102 ChildControllerImpl* controller() const { return controller_.get(); } |
102 | 103 |
103 void set_controller(scoped_ptr<ChildControllerImpl> controller) { | 104 void set_controller(scoped_ptr<ChildControllerImpl> controller) { |
104 controller_ = std::move(controller); | 105 controller_ = std::move(controller); |
105 } | 106 } |
106 | 107 |
107 private: | 108 private: |
108 void StartControllerThread() { | 109 void StartControllerThread() { |
109 base::Thread::Options controller_thread_options; | 110 base::Thread::Options controller_thread_options; |
(...skipping 24 matching lines...) Expand all Loading... |
134 | 135 |
135 // TODO(vtl): Pass in the result from |MainMain()|. | 136 // TODO(vtl): Pass in the result from |MainMain()|. |
136 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED); | 137 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED); |
137 } | 138 } |
138 | 139 |
139 // To be executed on the controller thread. Creates the |ChildController|, | 140 // To be executed on the controller thread. Creates the |ChildController|, |
140 // etc. | 141 // etc. |
141 static void Create(RunnerConnectionImpl* connection, | 142 static void Create(RunnerConnectionImpl* connection, |
142 const GotApplicationRequestCallback& callback, | 143 const GotApplicationRequestCallback& callback, |
143 ScopedMessagePipeHandle runner_handle, | 144 ScopedMessagePipeHandle runner_handle, |
144 const Blocker::Unblocker& unblocker) { | 145 const Blocker::Unblocker& unblocker, |
| 146 bool exit_on_error) { |
145 DCHECK(connection); | 147 DCHECK(connection); |
146 DCHECK(!connection->controller()); | 148 DCHECK(!connection->controller()); |
147 | 149 |
148 scoped_ptr<ChildControllerImpl> impl( | 150 scoped_ptr<ChildControllerImpl> impl( |
149 new ChildControllerImpl(connection, callback, unblocker)); | 151 new ChildControllerImpl(connection, callback, unblocker, |
| 152 exit_on_error)); |
150 | 153 |
151 impl->Bind(std::move(runner_handle)); | 154 impl->Bind(std::move(runner_handle)); |
152 | 155 |
153 connection->set_controller(std::move(impl)); | 156 connection->set_controller(std::move(impl)); |
154 } | 157 } |
155 | 158 |
156 void Bind(ScopedMessagePipeHandle handle) { | 159 void Bind(ScopedMessagePipeHandle handle) { |
157 binding_.Bind(std::move(handle)); | 160 binding_.Bind(std::move(handle)); |
158 binding_.set_connection_error_handler([this]() { OnConnectionError(); }); | 161 binding_.set_connection_error_handler([this]() { OnConnectionError(); }); |
159 } | 162 } |
160 | 163 |
161 void OnConnectionError() { | 164 void OnConnectionError() { |
162 // A connection error means the connection to the shell is lost. This is not | 165 // A connection error means the connection to the shell is lost. This is not |
163 // recoverable. | 166 // recoverable. |
164 DLOG(ERROR) << "Connection error to the shell."; | 167 DLOG(ERROR) << "Connection error to the shell."; |
165 _exit(1); | 168 if (exit_on_error_) { |
| 169 _exit(1); |
| 170 } else if (on_app_complete_.is_null()) { |
| 171 // If we failed before we could even get a ShellClient request from the |
| 172 // shell, signal failure to the RunnerConnection, as it's still blocking |
| 173 // on a response. |
| 174 unblocker_.Unblock( |
| 175 base::Bind(&ChildControllerImpl::ReturnApplicationRequestOnMainThread, |
| 176 callback_, nullptr)); |
| 177 } |
166 } | 178 } |
167 | 179 |
168 // |mojom::ChildController| methods: | 180 // |mojom::ChildController| methods: |
169 void StartApp(InterfaceRequest<mojom::ShellClient> request, | 181 void StartApp(InterfaceRequest<mojom::ShellClient> request, |
170 const StartAppCallback& on_app_complete) override { | 182 const StartAppCallback& on_app_complete) override { |
171 DCHECK(thread_checker_.CalledOnValidThread()); | 183 DCHECK(thread_checker_.CalledOnValidThread()); |
172 | 184 |
173 on_app_complete_ = on_app_complete; | 185 on_app_complete_ = on_app_complete; |
174 unblocker_.Unblock( | 186 unblocker_.Unblock( |
175 base::Bind(&ChildControllerImpl::ReturnApplicationRequestOnMainThread, | 187 base::Bind(&ChildControllerImpl::ReturnApplicationRequestOnMainThread, |
176 callback_, base::Passed(&request))); | 188 callback_, base::Passed(&request))); |
177 } | 189 } |
178 | 190 |
179 void ExitNow(int32_t exit_code) override { | 191 void ExitNow(int32_t exit_code) override { |
180 DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")"; | 192 DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")"; |
181 _exit(exit_code); | 193 _exit(exit_code); |
182 } | 194 } |
183 | 195 |
184 private: | 196 private: |
185 ChildControllerImpl(RunnerConnectionImpl* connection, | 197 ChildControllerImpl(RunnerConnectionImpl* connection, |
186 const GotApplicationRequestCallback& callback, | 198 const GotApplicationRequestCallback& callback, |
187 const Blocker::Unblocker& unblocker) | 199 const Blocker::Unblocker& unblocker, |
| 200 bool exit_on_error) |
188 : connection_(connection), | 201 : connection_(connection), |
189 callback_(callback), | 202 callback_(callback), |
190 unblocker_(unblocker), | 203 unblocker_(unblocker), |
191 binding_(this) {} | 204 binding_(this), |
| 205 exit_on_error_(exit_on_error) {} |
192 | 206 |
193 static void ReturnApplicationRequestOnMainThread( | 207 static void ReturnApplicationRequestOnMainThread( |
194 const GotApplicationRequestCallback& callback, | 208 const GotApplicationRequestCallback& callback, |
195 InterfaceRequest<mojom::ShellClient> request) { | 209 InterfaceRequest<mojom::ShellClient> request) { |
196 callback.Run(std::move(request)); | 210 callback.Run(std::move(request)); |
197 } | 211 } |
198 | 212 |
199 base::ThreadChecker thread_checker_; | 213 base::ThreadChecker thread_checker_; |
200 RunnerConnectionImpl* const connection_; | 214 RunnerConnectionImpl* const connection_; |
201 GotApplicationRequestCallback callback_; | 215 GotApplicationRequestCallback callback_; |
202 Blocker::Unblocker unblocker_; | 216 Blocker::Unblocker unblocker_; |
203 StartAppCallback on_app_complete_; | 217 StartAppCallback on_app_complete_; |
204 | 218 |
205 Binding<ChildController> binding_; | 219 Binding<ChildController> binding_; |
206 | 220 |
| 221 bool exit_on_error_; |
| 222 |
207 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); | 223 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); |
208 }; | 224 }; |
209 | 225 |
210 bool RunnerConnectionImpl::WaitForApplicationRequest( | 226 bool RunnerConnectionImpl::WaitForApplicationRequest( |
211 InterfaceRequest<mojom::ShellClient>* request, | 227 InterfaceRequest<mojom::ShellClient>* request, |
212 ScopedMessagePipeHandle handle) { | 228 ScopedMessagePipeHandle handle, |
| 229 bool exit_on_error) { |
213 // If a valid message pipe to the runner was not provided, look for one on the | 230 // If a valid message pipe to the runner was not provided, look for one on the |
214 // command line. | 231 // command line. |
215 if (!handle.is_valid()) { | 232 if (!handle.is_valid()) { |
216 edk::ScopedPlatformHandle platform_channel = | 233 edk::ScopedPlatformHandle platform_channel = |
217 edk::PlatformChannelPair::PassClientHandleFromParentProcess( | 234 edk::PlatformChannelPair::PassClientHandleFromParentProcess( |
218 *base::CommandLine::ForCurrentProcess()); | 235 *base::CommandLine::ForCurrentProcess()); |
219 if (!platform_channel.is_valid()) | 236 if (!platform_channel.is_valid()) |
220 return false; | 237 return false; |
221 edk::SetParentPipeHandle(std::move(platform_channel)); | 238 edk::SetParentPipeHandle(std::move(platform_channel)); |
222 std::string primordial_pipe_token = | 239 std::string primordial_pipe_token = |
223 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 240 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
224 switches::kPrimordialPipeToken); | 241 switches::kPrimordialPipeToken); |
225 handle = edk::CreateChildMessagePipe(primordial_pipe_token); | 242 handle = edk::CreateChildMessagePipe(primordial_pipe_token); |
226 } | 243 } |
227 | 244 |
228 DCHECK(handle.is_valid()); | 245 DCHECK(handle.is_valid()); |
229 | 246 |
230 Blocker blocker; | 247 Blocker blocker; |
231 controller_runner_->PostTask( | 248 controller_runner_->PostTask( |
232 FROM_HERE, | 249 FROM_HERE, |
233 base::Bind( | 250 base::Bind( |
234 &ChildControllerImpl::Create, base::Unretained(this), | 251 &ChildControllerImpl::Create, base::Unretained(this), |
235 base::Bind(&OnGotApplicationRequest, base::Unretained(request)), | 252 base::Bind(&OnGotApplicationRequest, request), base::Passed(&handle), |
236 base::Passed(&handle), blocker.GetUnblocker())); | 253 blocker.GetUnblocker(), exit_on_error)); |
237 blocker.Block(); | 254 blocker.Block(); |
238 | 255 |
239 return true; | 256 return request->is_pending(); |
240 } | 257 } |
241 | 258 |
242 } // namespace | 259 } // namespace |
243 | 260 |
244 RunnerConnection::~RunnerConnection() {} | 261 RunnerConnection::~RunnerConnection() {} |
245 | 262 |
246 // static | 263 // static |
247 RunnerConnection* RunnerConnection::ConnectToRunner( | 264 RunnerConnection* RunnerConnection::ConnectToRunner( |
248 InterfaceRequest<mojom::ShellClient>* request, | 265 InterfaceRequest<mojom::ShellClient>* request, |
249 ScopedMessagePipeHandle handle) { | 266 ScopedMessagePipeHandle handle, |
| 267 bool exit_on_error) { |
250 RunnerConnectionImpl* connection = new RunnerConnectionImpl; | 268 RunnerConnectionImpl* connection = new RunnerConnectionImpl; |
251 if (!connection->WaitForApplicationRequest(request, std::move(handle))) { | 269 if (!connection->WaitForApplicationRequest( |
| 270 request, std::move(handle), exit_on_error)) { |
252 delete connection; | 271 delete connection; |
253 return nullptr; | 272 return nullptr; |
254 } | 273 } |
255 return connection; | 274 return connection; |
256 } | 275 } |
257 | 276 |
258 RunnerConnection::RunnerConnection() {} | 277 RunnerConnection::RunnerConnection() {} |
259 | 278 |
260 } // namespace shell | 279 } // namespace shell |
261 } // namespace mojo | 280 } // namespace mojo |
OLD | NEW |