| 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 |