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

Side by Side Diff: mojo/runner/child/runner_connection.cc

Issue 1419293003: Allow mojo_runner to connect to arbitrary executables. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 1 month 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/runner/child/runner_connection.h ('k') | mojo/runner/child/test_native_service.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 2015 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/runner/child/runner_connection.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/thread.h"
14 #include "base/threading/thread_checker.h"
15 #include "mojo/message_pump/message_pump_mojo.h"
16 #include "mojo/public/cpp/bindings/binding.h"
17 #include "mojo/runner/child/child_controller.mojom.h"
18 #include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
19 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
20 #include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
21
22 namespace mojo {
23 namespace runner {
24 namespace {
25
26 // Blocks a thread until another thread unblocks it, at which point it unblocks
27 // and runs a closure provided by that thread.
28 class Blocker {
29 public:
30 class Unblocker {
31 public:
32 explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {}
33 ~Unblocker() {}
34
35 void Unblock(base::Closure run_after) {
36 DCHECK(blocker_);
37 DCHECK(blocker_->run_after_.is_null());
38 blocker_->run_after_ = run_after;
39 blocker_->event_.Signal();
40 blocker_ = nullptr;
41 }
42
43 private:
44 Blocker* blocker_;
45
46 // Copy and assign allowed.
47 };
48
49 Blocker() : event_(true, false) {}
50 ~Blocker() {}
51
52 void Block() {
53 DCHECK(run_after_.is_null());
54 event_.Wait();
55 if (!run_after_.is_null())
56 run_after_.Run();
57 }
58
59 Unblocker GetUnblocker() { return Unblocker(this); }
60
61 private:
62 base::WaitableEvent event_;
63 base::Closure run_after_;
64
65 DISALLOW_COPY_AND_ASSIGN(Blocker);
66 };
67
68 using GotApplicationRequestCallback =
69 base::Callback<void(InterfaceRequest<Application>)>;
70
71 void OnGotApplicationRequest(InterfaceRequest<Application>* out_request,
72 InterfaceRequest<Application> request) {
73 *out_request = request.Pass();
74 }
75
76 class ChildControllerImpl;
77
78 class RunnerConnectionImpl : public RunnerConnection {
79 public:
80 RunnerConnectionImpl() : controller_thread_("controller_thread") {
81 StartControllerThread();
82 }
83 ~RunnerConnectionImpl() override {
84 controller_runner_->PostTask(
85 FROM_HERE, base::Bind(&RunnerConnectionImpl::ShutdownOnControllerThread,
86 base::Unretained(this)));
87 controller_thread_.Stop();
88 }
89
90 // Returns true if a connection to the runner has been established and
91 // |request| has been modified, false if no connection was established.
92 bool WaitForApplicationRequest(InterfaceRequest<Application>* request);
93
94 ChildControllerImpl* controller() const { return controller_.get(); }
95
96 void set_controller(scoped_ptr<ChildControllerImpl> controller) {
97 controller_ = controller.Pass();
98 }
99
100 private:
101 void StartControllerThread() {
102 base::Thread::Options controller_thread_options;
103 controller_thread_options.message_loop_type =
104 base::MessageLoop::TYPE_CUSTOM;
105 controller_thread_options.message_pump_factory =
106 base::Bind(&common::MessagePumpMojo::Create);
107 CHECK(controller_thread_.StartWithOptions(controller_thread_options));
108 controller_runner_ = controller_thread_.task_runner().get();
109 CHECK(controller_runner_.get());
110 }
111
112 void ShutdownOnControllerThread() { controller_.reset(); }
113
114 base::Thread controller_thread_;
115 scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
116
117 // Accessed only on the controller thread.
118 scoped_ptr<ChildControllerImpl> controller_;
119
120 DISALLOW_COPY_AND_ASSIGN(RunnerConnectionImpl);
121 };
122
123 class ChildControllerImpl : public ChildController {
124 public:
125 ~ChildControllerImpl() override {
126 DCHECK(thread_checker_.CalledOnValidThread());
127
128 // TODO(vtl): Pass in the result from |MainMain()|.
129 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED);
130 }
131
132 // To be executed on the controller thread. Creates the |ChildController|,
133 // etc.
134 static void Create(RunnerConnectionImpl* connection,
135 const GotApplicationRequestCallback& callback,
136 embedder::ScopedPlatformHandle platform_channel,
137 const Blocker::Unblocker& unblocker) {
138 DCHECK(connection);
139 DCHECK(platform_channel.is_valid());
140
141 DCHECK(!connection->controller());
142
143 scoped_ptr<ChildControllerImpl> impl(
144 new ChildControllerImpl(connection, callback, unblocker));
145
146 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
147 platform_channel.Pass(),
148 base::Bind(&ChildControllerImpl::DidCreateChannel,
149 base::Unretained(impl.get())),
150 base::ThreadTaskRunnerHandle::Get()));
151
152 impl->Bind(host_message_pipe.Pass());
153
154 connection->set_controller(impl.Pass());
155 }
156
157 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
158
159 void OnConnectionError() {
160 // A connection error means the connection to the shell is lost. This is not
161 // recoverable.
162 LOG(ERROR) << "Connection error to the shell.";
163 _exit(1);
164 }
165
166 // |ChildController| methods:
167 void StartApp(InterfaceRequest<Application> application_request,
168 const StartAppCallback& on_app_complete) override {
169 DCHECK(thread_checker_.CalledOnValidThread());
170
171 on_app_complete_ = on_app_complete;
172 unblocker_.Unblock(
173 base::Bind(&ChildControllerImpl::ReturnApplicationRequestOnMainThread,
174 callback_, base::Passed(&application_request)));
175 }
176
177 void ExitNow(int32_t exit_code) override {
178 DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")";
179 _exit(exit_code);
180 }
181
182 private:
183 ChildControllerImpl(RunnerConnectionImpl* connection,
184 const GotApplicationRequestCallback& callback,
185 const Blocker::Unblocker& unblocker)
186 : connection_(connection),
187 callback_(callback),
188 unblocker_(unblocker),
189 channel_info_(nullptr),
190 binding_(this) {
191 binding_.set_connection_error_handler([this]() { OnConnectionError(); });
192 }
193
194 // Callback for |embedder::CreateChannel()|.
195 void DidCreateChannel(embedder::ChannelInfo* channel_info) {
196 DVLOG(2) << "ChildControllerImpl::DidCreateChannel()";
197 DCHECK(thread_checker_.CalledOnValidThread());
198 channel_info_ = channel_info;
199 }
200
201 static void ReturnApplicationRequestOnMainThread(
202 const GotApplicationRequestCallback& callback,
203 InterfaceRequest<Application> application_request) {
204 callback.Run(application_request.Pass());
205 }
206
207 base::ThreadChecker thread_checker_;
208 RunnerConnectionImpl* const connection_;
209 GotApplicationRequestCallback callback_;
210 Blocker::Unblocker unblocker_;
211 StartAppCallback on_app_complete_;
212
213 embedder::ChannelInfo* channel_info_;
214 Binding<ChildController> binding_;
215
216 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl);
217 };
218
219 bool RunnerConnectionImpl::WaitForApplicationRequest(
220 InterfaceRequest<Application>* request) {
221 embedder::ScopedPlatformHandle platform_channel =
222 embedder::PlatformChannelPair::PassClientHandleFromParentProcess(
223 *base::CommandLine::ForCurrentProcess());
224 if (!platform_channel.is_valid())
225 return false;
226
227 Blocker blocker;
228 controller_runner_->PostTask(
229 FROM_HERE,
230 base::Bind(
231 &ChildControllerImpl::Create, base::Unretained(this),
232 base::Bind(&OnGotApplicationRequest, base::Unretained(request)),
233 base::Passed(&platform_channel), blocker.GetUnblocker()));
234 blocker.Block();
235
236 return true;
237 }
238
239 } // namespace
240
241 RunnerConnection::~RunnerConnection() {}
242
243 // static
244 RunnerConnection* RunnerConnection::ConnectToRunner(
245 InterfaceRequest<Application>* request) {
246 RunnerConnectionImpl* connection = new RunnerConnectionImpl;
247 if (!connection->WaitForApplicationRequest(request)) {
248 delete connection;
249 return nullptr;
250 }
251 return connection;
252 }
253
254 RunnerConnection::RunnerConnection() {}
255
256 } // namespace runner
257 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/runner/child/runner_connection.h ('k') | mojo/runner/child/test_native_service.mojom » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698