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 "mojo/shell/app_child_process.h" | 5 #include "mojo/shell/app_child_process.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.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/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
16 #include "base/scoped_native_library.h" | 16 #include "base/scoped_native_library.h" |
17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
18 #include "base/synchronization/waitable_event.h" | 18 #include "base/synchronization/waitable_event.h" |
19 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
20 #include "base/threading/thread_checker.h" | 20 #include "base/threading/thread_checker.h" |
21 #include "mojo/common/message_pump_mojo.h" | 21 #include "mojo/common/message_pump_mojo.h" |
22 #include "mojo/embedder/embedder.h" | 22 #include "mojo/embedder/embedder.h" |
23 #include "mojo/public/cpp/bindings/remote_ptr.h" | |
24 #include "mojo/public/cpp/system/core.h" | 23 #include "mojo/public/cpp/system/core.h" |
25 #include "mojo/shell/app_child_process.mojom.h" | 24 #include "mojo/shell/app_child_process.mojom.h" |
26 | 25 |
27 namespace mojo { | 26 namespace mojo { |
28 namespace shell { | 27 namespace shell { |
29 | 28 |
30 namespace { | 29 namespace { |
31 | 30 |
32 // Blocker --------------------------------------------------------------------- | 31 // Blocker --------------------------------------------------------------------- |
33 | 32 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 base::WaitableEvent event_; | 74 base::WaitableEvent event_; |
76 base::Closure run_after_; | 75 base::Closure run_after_; |
77 | 76 |
78 DISALLOW_COPY_AND_ASSIGN(Blocker); | 77 DISALLOW_COPY_AND_ASSIGN(Blocker); |
79 }; | 78 }; |
80 | 79 |
81 // AppContext ------------------------------------------------------------------ | 80 // AppContext ------------------------------------------------------------------ |
82 | 81 |
83 class AppChildControllerImpl; | 82 class AppChildControllerImpl; |
84 | 83 |
| 84 static void DestroyController(scoped_ptr<AppChildControllerImpl> controller) { |
| 85 } |
| 86 |
85 // Should be created and initialized on the main thread. | 87 // Should be created and initialized on the main thread. |
86 class AppContext { | 88 class AppContext { |
87 public: | 89 public: |
88 AppContext() | 90 AppContext() |
89 : io_thread_("io_thread"), | 91 : io_thread_("io_thread"), |
90 controller_thread_("controller_thread") {} | 92 controller_thread_("controller_thread") {} |
91 ~AppContext() {} | 93 ~AppContext() {} |
92 | 94 |
93 void Init() { | 95 void Init() { |
94 // Initialize Mojo before starting any threads. | 96 // Initialize Mojo before starting any threads. |
95 embedder::Init(); | 97 embedder::Init(); |
96 | 98 |
97 // Create and start our I/O thread. | 99 // Create and start our I/O thread. |
98 base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); | 100 base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); |
99 CHECK(io_thread_.StartWithOptions(io_thread_options)); | 101 CHECK(io_thread_.StartWithOptions(io_thread_options)); |
100 io_runner_ = io_thread_.message_loop_proxy().get(); | 102 io_runner_ = io_thread_.message_loop_proxy().get(); |
101 CHECK(io_runner_); | 103 CHECK(io_runner_); |
102 | 104 |
103 // Create and start our controller thread. | 105 // Create and start our controller thread. |
104 base::Thread::Options controller_thread_options; | 106 base::Thread::Options controller_thread_options; |
105 controller_thread_options.message_loop_type = | 107 controller_thread_options.message_loop_type = |
106 base::MessageLoop::TYPE_CUSTOM; | 108 base::MessageLoop::TYPE_CUSTOM; |
107 controller_thread_options.message_pump_factory = | 109 controller_thread_options.message_pump_factory = |
108 base::Bind(&common::MessagePumpMojo::Create); | 110 base::Bind(&common::MessagePumpMojo::Create); |
109 CHECK(controller_thread_.StartWithOptions(controller_thread_options)); | 111 CHECK(controller_thread_.StartWithOptions(controller_thread_options)); |
110 controller_runner_ = controller_thread_.message_loop_proxy().get(); | 112 controller_runner_ = controller_thread_.message_loop_proxy().get(); |
111 CHECK(controller_runner_); | 113 CHECK(controller_runner_); |
112 } | 114 } |
113 | 115 |
| 116 void Shutdown() { |
| 117 controller_runner_->PostTask( |
| 118 FROM_HERE, |
| 119 base::Bind(&DestroyController, base::Passed(&controller_))); |
| 120 } |
| 121 |
114 base::SingleThreadTaskRunner* io_runner() const { | 122 base::SingleThreadTaskRunner* io_runner() const { |
115 return io_runner_.get(); | 123 return io_runner_.get(); |
116 } | 124 } |
117 | 125 |
118 base::SingleThreadTaskRunner* controller_runner() const { | 126 base::SingleThreadTaskRunner* controller_runner() const { |
119 return controller_runner_.get(); | 127 return controller_runner_.get(); |
120 } | 128 } |
121 | 129 |
122 AppChildControllerImpl* controller() const { | 130 AppChildControllerImpl* controller() const { |
123 return controller_.get(); | 131 return controller_.get(); |
(...skipping 14 matching lines...) Expand all Loading... |
138 scoped_refptr<base::SingleThreadTaskRunner> io_runner_; | 146 scoped_refptr<base::SingleThreadTaskRunner> io_runner_; |
139 | 147 |
140 base::Thread controller_thread_; | 148 base::Thread controller_thread_; |
141 scoped_refptr<base::SingleThreadTaskRunner> controller_runner_; | 149 scoped_refptr<base::SingleThreadTaskRunner> controller_runner_; |
142 | 150 |
143 DISALLOW_COPY_AND_ASSIGN(AppContext); | 151 DISALLOW_COPY_AND_ASSIGN(AppContext); |
144 }; | 152 }; |
145 | 153 |
146 // AppChildControllerImpl ------------------------------------------------------ | 154 // AppChildControllerImpl ------------------------------------------------------ |
147 | 155 |
148 class AppChildControllerImpl : public mojo_shell::AppChildController { | 156 class AppChildControllerImpl : public InterfaceImpl<AppChildController> { |
149 public: | 157 public: |
150 virtual ~AppChildControllerImpl() { | 158 virtual ~AppChildControllerImpl() { |
151 DCHECK(thread_checker_.CalledOnValidThread()); | 159 DCHECK(thread_checker_.CalledOnValidThread()); |
| 160 |
| 161 // TODO(vtl): Pass in the result from |MainMain()|. |
| 162 if (controller_client_) |
| 163 controller_client_->AppCompleted(MOJO_RESULT_UNIMPLEMENTED); |
152 } | 164 } |
153 | 165 |
154 // To be executed on the controller thread. Creates the |AppChildController|, | 166 // To be executed on the controller thread. Creates the |AppChildController|, |
155 // etc. | 167 // etc. |
156 static void Init( | 168 static void Init( |
157 AppContext* app_context, | 169 AppContext* app_context, |
158 embedder::ScopedPlatformHandle platform_channel, | 170 embedder::ScopedPlatformHandle platform_channel, |
159 const Blocker::Unblocker& unblocker) { | 171 const Blocker::Unblocker& unblocker) { |
160 DCHECK(app_context); | 172 DCHECK(app_context); |
161 DCHECK(platform_channel.is_valid()); | 173 DCHECK(platform_channel.is_valid()); |
162 | 174 |
163 DCHECK(!app_context->controller()); | 175 DCHECK(!app_context->controller()); |
164 app_context->set_controller( | 176 |
165 make_scoped_ptr(new AppChildControllerImpl(app_context, unblocker))); | 177 scoped_ptr<AppChildControllerImpl> impl( |
166 app_context->controller()->CreateChannel(platform_channel.Pass()); | 178 new AppChildControllerImpl(app_context, unblocker)); |
| 179 |
| 180 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( |
| 181 platform_channel.Pass(), |
| 182 app_context->io_runner(), |
| 183 base::Bind(&AppChildControllerImpl::DidCreateChannel, |
| 184 base::Unretained(impl.get())), |
| 185 base::MessageLoopProxy::current())); |
| 186 |
| 187 BindToPipe(impl.get(), host_message_pipe.Pass()); |
| 188 |
| 189 app_context->set_controller(impl.Pass()); |
167 } | 190 } |
168 | 191 |
169 void Shutdown() { | 192 virtual void OnConnectionError() OVERRIDE { |
170 DVLOG(2) << "AppChildControllerImpl::Shutdown()"; | 193 // TODO(darin): How should we handle a connection error here? |
171 DCHECK(thread_checker_.CalledOnValidThread()); | |
172 | |
173 // TODO(vtl): Pass in the result from |MainMain()|. | |
174 controller_client_->AppCompleted(MOJO_RESULT_UNIMPLEMENTED); | |
175 | |
176 // TODO(vtl): Drain then destroy the channel (on the I/O thread). | |
177 | |
178 // This will destroy this object. | |
179 app_context_->set_controller(scoped_ptr<AppChildControllerImpl>()); | |
180 } | 194 } |
181 | 195 |
182 // |AppChildController| method: | 196 // |AppChildController| methods: |
| 197 |
| 198 virtual void SetClient(AppChildControllerClient* client) OVERRIDE { |
| 199 controller_client_ = client; |
| 200 } |
| 201 |
183 virtual void StartApp(const String& app_path, | 202 virtual void StartApp(const String& app_path, |
184 ScopedMessagePipeHandle service) OVERRIDE { | 203 ScopedMessagePipeHandle service) OVERRIDE { |
185 DVLOG(2) << "AppChildControllerImpl::StartApp(" | 204 DVLOG(2) << "AppChildControllerImpl::StartApp(" |
186 << app_path.To<std::string>() << ", ...)"; | 205 << app_path.To<std::string>() << ", ...)"; |
187 DCHECK(thread_checker_.CalledOnValidThread()); | 206 DCHECK(thread_checker_.CalledOnValidThread()); |
188 | 207 |
| 208 // TODO(darin): Add TypeConverter for FilePath <-> mojo::String. |
189 unblocker_.Unblock(base::Bind(&AppChildControllerImpl::StartAppOnMainThread, | 209 unblocker_.Unblock(base::Bind(&AppChildControllerImpl::StartAppOnMainThread, |
190 base::FilePath::FromUTF8Unsafe( | 210 base::FilePath::FromUTF8Unsafe( |
191 app_path.To<std::string>()), | 211 app_path.To<std::string>()), |
192 base::Passed(&service))); | 212 base::Passed(&service))); |
193 } | 213 } |
194 | 214 |
195 private: | 215 private: |
196 AppChildControllerImpl(AppContext* app_context, | 216 AppChildControllerImpl(AppContext* app_context, |
197 const Blocker::Unblocker& unblocker) | 217 const Blocker::Unblocker& unblocker) |
198 : app_context_(app_context), | 218 : app_context_(app_context), |
199 unblocker_(unblocker), | 219 unblocker_(unblocker), |
| 220 controller_client_(NULL), |
200 channel_info_(NULL) { | 221 channel_info_(NULL) { |
201 } | 222 } |
202 | 223 |
203 void CreateChannel(embedder::ScopedPlatformHandle platform_channel) { | |
204 DVLOG(2) << "AppChildControllerImpl::CreateChannel()"; | |
205 DCHECK(thread_checker_.CalledOnValidThread()); | |
206 | |
207 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( | |
208 platform_channel.Pass(), | |
209 app_context_->io_runner(), | |
210 base::Bind(&AppChildControllerImpl::DidCreateChannel, | |
211 base::Unretained(this)), | |
212 base::MessageLoopProxy::current())); | |
213 controller_client_.reset( | |
214 mojo_shell::ScopedAppChildControllerClientHandle( | |
215 mojo_shell::AppChildControllerClientHandle( | |
216 host_message_pipe.release().value())), this); | |
217 } | |
218 | |
219 // Callback for |embedder::CreateChannel()|. | 224 // Callback for |embedder::CreateChannel()|. |
220 void DidCreateChannel(embedder::ChannelInfo* channel_info) { | 225 void DidCreateChannel(embedder::ChannelInfo* channel_info) { |
221 DVLOG(2) << "AppChildControllerImpl::DidCreateChannel()"; | 226 DVLOG(2) << "AppChildControllerImpl::DidCreateChannel()"; |
222 DCHECK(thread_checker_.CalledOnValidThread()); | 227 DCHECK(thread_checker_.CalledOnValidThread()); |
223 channel_info_ = channel_info; | 228 channel_info_ = channel_info; |
224 } | 229 } |
225 | 230 |
226 static void StartAppOnMainThread(const base::FilePath& app_path, | 231 static void StartAppOnMainThread(const base::FilePath& app_path, |
227 ScopedMessagePipeHandle service) { | 232 ScopedMessagePipeHandle service) { |
228 // TODO(vtl): This is copied from in_process_dynamic_service_runner.cc. | 233 // TODO(vtl): This is copied from in_process_dynamic_service_runner.cc. |
(...skipping 26 matching lines...) Expand all Loading... |
255 MojoResult result = main_function(service.release().value()); | 260 MojoResult result = main_function(service.release().value()); |
256 if (result < MOJO_RESULT_OK) | 261 if (result < MOJO_RESULT_OK) |
257 LOG(ERROR) << "MojoMain returned an error: " << result; | 262 LOG(ERROR) << "MojoMain returned an error: " << result; |
258 } while (false); | 263 } while (false); |
259 } | 264 } |
260 | 265 |
261 base::ThreadChecker thread_checker_; | 266 base::ThreadChecker thread_checker_; |
262 AppContext* const app_context_; | 267 AppContext* const app_context_; |
263 Blocker::Unblocker unblocker_; | 268 Blocker::Unblocker unblocker_; |
264 | 269 |
265 RemotePtr<mojo_shell::AppChildControllerClient> controller_client_; | 270 AppChildControllerClient* controller_client_; |
266 embedder::ChannelInfo* channel_info_; | 271 embedder::ChannelInfo* channel_info_; |
267 | 272 |
268 DISALLOW_COPY_AND_ASSIGN(AppChildControllerImpl); | 273 DISALLOW_COPY_AND_ASSIGN(AppChildControllerImpl); |
269 }; | 274 }; |
270 | 275 |
271 } // namespace | 276 } // namespace |
272 | 277 |
273 // AppChildProcess ------------------------------------------------------------- | 278 // AppChildProcess ------------------------------------------------------------- |
274 | 279 |
275 AppChildProcess::AppChildProcess() { | 280 AppChildProcess::AppChildProcess() { |
276 } | 281 } |
277 | 282 |
278 AppChildProcess::~AppChildProcess() { | 283 AppChildProcess::~AppChildProcess() { |
279 } | 284 } |
280 | 285 |
281 void AppChildProcess::Main() { | 286 void AppChildProcess::Main() { |
282 DVLOG(2) << "AppChildProcess::Main()"; | 287 DVLOG(2) << "AppChildProcess::Main()"; |
283 | 288 |
284 AppContext app_context; | 289 AppContext app_context; |
285 app_context.Init(); | 290 app_context.Init(); |
286 | 291 |
287 Blocker blocker; | 292 Blocker blocker; |
288 app_context.controller_runner()->PostTask( | 293 app_context.controller_runner()->PostTask( |
289 FROM_HERE, | 294 FROM_HERE, |
290 base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context), | 295 base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context), |
291 base::Passed(platform_channel()), blocker.GetUnblocker())); | 296 base::Passed(platform_channel()), blocker.GetUnblocker())); |
292 // This will block, then run whatever the controller wants. | 297 // This will block, then run whatever the controller wants. |
293 blocker.Block(); | 298 blocker.Block(); |
294 | 299 |
295 app_context.controller_runner()->PostTask( | 300 app_context.Shutdown(); |
296 FROM_HERE, | |
297 base::Bind(&AppChildControllerImpl::Shutdown, | |
298 base::Unretained(app_context.controller()))); | |
299 } | 301 } |
300 | 302 |
301 } // namespace shell | 303 } // namespace shell |
302 } // namespace mojo | 304 } // namespace mojo |
OLD | NEW |