Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(696)

Side by Side Diff: mojo/shell/app_child_process.cc

Issue 1049993002: Get mojo_shell building inside chromium checkout. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix presubmit Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/shell/app_child_process.h ('k') | mojo/shell/app_child_process.mojom » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/app_child_process.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/files/file_path.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/threading/thread.h"
19 #include "base/threading/thread_checker.h"
20 #include "mojo/common/message_pump_mojo.h"
21 #include "mojo/edk/embedder/embedder.h"
22 #include "mojo/edk/embedder/process_delegate.h"
23 #include "mojo/edk/embedder/simple_platform_support.h"
24 #include "mojo/public/cpp/system/core.h"
25 #include "mojo/shell/app_child_process.mojom.h"
26 #include "mojo/shell/native_application_support.h"
27
28 namespace mojo {
29 namespace shell {
30
31 namespace {
32
33 // Blocker ---------------------------------------------------------------------
34
35 // Blocks a thread until another thread unblocks it, at which point it unblocks
36 // and runs a closure provided by that thread.
37 class Blocker {
38 public:
39 class Unblocker {
40 public:
41 explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {}
42 ~Unblocker() {}
43
44 void Unblock(base::Closure run_after) {
45 DCHECK(blocker_);
46 DCHECK(blocker_->run_after_.is_null());
47 blocker_->run_after_ = run_after;
48 blocker_->event_.Signal();
49 blocker_ = nullptr;
50 }
51
52 private:
53 Blocker* blocker_;
54
55 // Copy and assign allowed.
56 };
57
58 Blocker() : event_(true, false) {}
59 ~Blocker() {}
60
61 void Block() {
62 DCHECK(run_after_.is_null());
63 event_.Wait();
64 run_after_.Run();
65 }
66
67 Unblocker GetUnblocker() { return Unblocker(this); }
68
69 private:
70 base::WaitableEvent event_;
71 base::Closure run_after_;
72
73 DISALLOW_COPY_AND_ASSIGN(Blocker);
74 };
75
76 // AppContext ------------------------------------------------------------------
77
78 class AppChildControllerImpl;
79
80 // Should be created and initialized on the main thread.
81 class AppContext : public embedder::ProcessDelegate {
82 public:
83 AppContext()
84 : io_thread_("io_thread"), controller_thread_("controller_thread") {}
85 ~AppContext() override {}
86
87 void Init() {
88 // Initialize Mojo before starting any threads.
89 embedder::Init(make_scoped_ptr(new embedder::SimplePlatformSupport()));
90
91 // Create and start our I/O thread.
92 base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0);
93 CHECK(io_thread_.StartWithOptions(io_thread_options));
94 io_runner_ = io_thread_.message_loop_proxy().get();
95 CHECK(io_runner_.get());
96
97 // Create and start our controller thread.
98 base::Thread::Options controller_thread_options;
99 controller_thread_options.message_loop_type =
100 base::MessageLoop::TYPE_CUSTOM;
101 controller_thread_options.message_pump_factory =
102 base::Bind(&common::MessagePumpMojo::Create);
103 CHECK(controller_thread_.StartWithOptions(controller_thread_options));
104 controller_runner_ = controller_thread_.message_loop_proxy().get();
105 CHECK(controller_runner_.get());
106
107 // TODO(vtl): This should be SLAVE, not NONE.
108 embedder::InitIPCSupport(embedder::ProcessType::NONE, controller_runner_,
109 this, io_runner_,
110 embedder::ScopedPlatformHandle());
111 }
112
113 void Shutdown() {
114 Blocker blocker;
115 shutdown_unblocker_ = blocker.GetUnblocker();
116 controller_runner_->PostTask(
117 FROM_HERE, base::Bind(&AppContext::ShutdownOnControllerThread,
118 base::Unretained(this)));
119 blocker.Block();
120 }
121
122 base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); }
123
124 base::SingleThreadTaskRunner* controller_runner() const {
125 return controller_runner_.get();
126 }
127
128 AppChildControllerImpl* controller() const { return controller_.get(); }
129
130 void set_controller(scoped_ptr<AppChildControllerImpl> controller) {
131 controller_ = controller.Pass();
132 }
133
134 private:
135 void ShutdownOnControllerThread() {
136 // First, destroy the controller.
137 controller_.reset();
138
139 // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete().
140 embedder::ShutdownIPCSupport();
141 }
142
143 // ProcessDelegate implementation.
144 void OnShutdownComplete() override {
145 shutdown_unblocker_.Unblock(base::Closure());
146 }
147
148 base::Thread io_thread_;
149 scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
150
151 base::Thread controller_thread_;
152 scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
153
154 // Accessed only on the controller thread.
155 scoped_ptr<AppChildControllerImpl> controller_;
156
157 // Used to unblock the main thread on shutdown.
158 Blocker::Unblocker shutdown_unblocker_;
159
160 DISALLOW_COPY_AND_ASSIGN(AppContext);
161 };
162
163 // AppChildControllerImpl ------------------------------------------------------
164
165 class AppChildControllerImpl : public AppChildController, public ErrorHandler {
166 public:
167 ~AppChildControllerImpl() override {
168 DCHECK(thread_checker_.CalledOnValidThread());
169
170 // TODO(vtl): Pass in the result from |MainMain()|.
171 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED);
172 }
173
174 // To be executed on the controller thread. Creates the |AppChildController|,
175 // etc.
176 static void Init(AppContext* app_context,
177 embedder::ScopedPlatformHandle platform_channel,
178 const Blocker::Unblocker& unblocker) {
179 DCHECK(app_context);
180 DCHECK(platform_channel.is_valid());
181
182 DCHECK(!app_context->controller());
183
184 scoped_ptr<AppChildControllerImpl> impl(
185 new AppChildControllerImpl(app_context, unblocker));
186
187 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
188 platform_channel.Pass(), app_context->io_runner(),
189 base::Bind(&AppChildControllerImpl::DidCreateChannel,
190 base::Unretained(impl.get())),
191 base::MessageLoopProxy::current()));
192
193 impl->Bind(host_message_pipe.Pass());
194
195 app_context->set_controller(impl.Pass());
196 }
197
198 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
199
200 // |ErrorHandler| methods:
201 void OnConnectionError() override {
202 // A connection error means the connection to the shell is lost. This is not
203 // recoverable.
204 LOG(ERROR) << "Connection error to the shell.";
205 _exit(1);
206 }
207
208 // |AppChildController| methods:
209 void StartApp(const String& app_path,
210 bool clean_app_path,
211 InterfaceRequest<Application> application_request,
212 const StartAppCallback& on_app_complete) override {
213 DVLOG(2) << "AppChildControllerImpl::StartApp(" << app_path << ", ...)";
214 DCHECK(thread_checker_.CalledOnValidThread());
215
216 on_app_complete_ = on_app_complete;
217 unblocker_.Unblock(base::Bind(&AppChildControllerImpl::StartAppOnMainThread,
218 base::FilePath::FromUTF8Unsafe(app_path),
219 clean_app_path
220 ? NativeApplicationCleanup::DELETE
221 : NativeApplicationCleanup::DONT_DELETE,
222 base::Passed(&application_request)));
223 }
224
225 void ExitNow(int32_t exit_code) override {
226 DVLOG(2) << "AppChildControllerImpl::ExitNow(" << exit_code << ")";
227 _exit(exit_code);
228 }
229
230 private:
231 AppChildControllerImpl(AppContext* app_context,
232 const Blocker::Unblocker& unblocker)
233 : app_context_(app_context),
234 unblocker_(unblocker),
235 channel_info_(nullptr),
236 binding_(this) {
237 binding_.set_error_handler(this);
238 }
239
240 // Callback for |embedder::CreateChannel()|.
241 void DidCreateChannel(embedder::ChannelInfo* channel_info) {
242 DVLOG(2) << "AppChildControllerImpl::DidCreateChannel()";
243 DCHECK(thread_checker_.CalledOnValidThread());
244 channel_info_ = channel_info;
245 }
246
247 static void StartAppOnMainThread(
248 const base::FilePath& app_path,
249 NativeApplicationCleanup cleanup,
250 InterfaceRequest<Application> application_request) {
251 // TODO(vtl): This is copied from in_process_native_runner.cc.
252 DVLOG(2) << "Loading/running Mojo app from " << app_path.value()
253 << " out of process";
254
255 // We intentionally don't unload the native library as its lifetime is the
256 // same as that of the process.
257 base::NativeLibrary app_library = LoadNativeApplication(app_path, cleanup);
258 RunNativeApplication(app_library, application_request.Pass());
259 }
260
261 base::ThreadChecker thread_checker_;
262 AppContext* const app_context_;
263 Blocker::Unblocker unblocker_;
264 StartAppCallback on_app_complete_;
265
266 embedder::ChannelInfo* channel_info_;
267 Binding<AppChildController> binding_;
268
269 DISALLOW_COPY_AND_ASSIGN(AppChildControllerImpl);
270 };
271
272 } // namespace
273
274 // AppChildProcess -------------------------------------------------------------
275
276 AppChildProcess::AppChildProcess() {
277 }
278
279 AppChildProcess::~AppChildProcess() {
280 }
281
282 void AppChildProcess::Main() {
283 DVLOG(2) << "AppChildProcess::Main()";
284
285 DCHECK(!base::MessageLoop::current());
286
287 AppContext app_context;
288 app_context.Init();
289
290 Blocker blocker;
291 app_context.controller_runner()->PostTask(
292 FROM_HERE,
293 base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context),
294 base::Passed(platform_channel()), blocker.GetUnblocker()));
295 // This will block, then run whatever the controller wants.
296 blocker.Block();
297
298 app_context.Shutdown();
299 }
300
301 } // namespace shell
302 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/shell/app_child_process.h ('k') | mojo/shell/app_child_process.mojom » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698