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

Side by Side Diff: content/common/mojo/mojo_shell_connection_impl.cc

Issue 2398783002: Rename a bunch of Mojo Application stuff to reference Services. (Closed)
Patch Set: . Created 4 years, 2 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 | « content/common/mojo/mojo_shell_connection_impl.h ('k') | content/common/service_manager/DEPS » ('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 2016 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 "content/common/mojo/mojo_shell_connection_impl.h"
6
7 #include <queue>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/lazy_instance.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/threading/thread_checker.h"
18 #include "content/common/mojo/embedded_application_runner.h"
19 #include "content/public/common/connection_filter.h"
20 #include "mojo/public/cpp/bindings/binding_set.h"
21 #include "mojo/public/cpp/system/message_pipe.h"
22 #include "services/shell/public/cpp/service.h"
23 #include "services/shell/public/cpp/service_context.h"
24 #include "services/shell/public/interfaces/service_factory.mojom.h"
25 #include "services/shell/runner/common/client_util.h"
26
27 namespace content {
28 namespace {
29
30 base::LazyInstance<std::unique_ptr<MojoShellConnection>>::Leaky
31 g_connection_for_process = LAZY_INSTANCE_INITIALIZER;
32
33 MojoShellConnection::Factory* mojo_shell_connection_factory = nullptr;
34
35 } // namespace
36
37 // A ref-counted object which owns the IO thread state of a
38 // MojoShellConnectionImpl. This includes Service and ServiceFactory
39 // bindings.
40 class MojoShellConnectionImpl::IOThreadContext
41 : public base::RefCountedThreadSafe<IOThreadContext>,
42 public shell::Service,
43 public shell::InterfaceFactory<shell::mojom::ServiceFactory>,
44 public shell::mojom::ServiceFactory {
45 public:
46 using InitializeCallback = base::Callback<void(const shell::Identity&)>;
47 using ServiceFactoryCallback =
48 base::Callback<void(shell::mojom::ServiceRequest, const std::string&)>;
49
50 IOThreadContext(shell::mojom::ServiceRequest service_request,
51 scoped_refptr<base::SequencedTaskRunner> io_task_runner,
52 std::unique_ptr<shell::Connector> io_thread_connector,
53 shell::mojom::ConnectorRequest connector_request)
54 : pending_service_request_(std::move(service_request)),
55 io_task_runner_(io_task_runner),
56 io_thread_connector_(std::move(io_thread_connector)),
57 pending_connector_request_(std::move(connector_request)),
58 weak_factory_(this) {
59 // This will be reattached by any of the IO thread functions on first call.
60 io_thread_checker_.DetachFromThread();
61 }
62
63 // Safe to call from any thread.
64 void Start(const InitializeCallback& initialize_callback,
65 const ServiceFactoryCallback& create_service_callback,
66 const base::Closure& stop_callback) {
67 DCHECK(!started_);
68
69 started_ = true;
70 callback_task_runner_ = base::ThreadTaskRunnerHandle::Get();
71 initialize_handler_ = initialize_callback;
72 create_service_callback_ = create_service_callback;
73 stop_callback_ = stop_callback;
74 io_task_runner_->PostTask(
75 FROM_HERE, base::Bind(&IOThreadContext::StartOnIOThread, this));
76 }
77
78 // Safe to call from whichever thread called Start() (or may have called
79 // Start()). Must be called before IO thread shutdown.
80 void ShutDown() {
81 if (!started_)
82 return;
83
84 bool posted = io_task_runner_->PostTask(
85 FROM_HERE, base::Bind(&IOThreadContext::ShutDownOnIOThread, this));
86 DCHECK(posted);
87 }
88
89 // Safe to call any time before a message is received from a process.
90 // i.e. can be called when starting the process but not afterwards.
91 int AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) {
92 base::AutoLock lock(lock_);
93
94 int id = ++next_filter_id_;
95
96 // We should never hit this in practice, but let's crash just in case.
97 CHECK_NE(id, kInvalidConnectionFilterId);
98
99 connection_filters_[id] = std::move(filter);
100 return id;
101 }
102
103 void RemoveConnectionFilter(int filter_id) {
104 io_task_runner_->PostTask(
105 FROM_HERE,
106 base::Bind(&IOThreadContext::RemoveConnectionFilterOnIOThread, this,
107 filter_id));
108 }
109
110 // Safe to call any time before Start() is called.
111 void SetDefaultBinderForBrowserConnection(
112 const shell::InterfaceRegistry::Binder& binder) {
113 DCHECK(!started_);
114 default_browser_binder_ = base::Bind(
115 &IOThreadContext::CallBinderOnTaskRunner,
116 base::ThreadTaskRunnerHandle::Get(), binder);
117 }
118
119 private:
120 friend class base::RefCountedThreadSafe<IOThreadContext>;
121
122 class MessageLoopObserver : public base::MessageLoop::DestructionObserver {
123 public:
124 explicit MessageLoopObserver(base::WeakPtr<IOThreadContext> context)
125 : context_(context) {
126 base::MessageLoop::current()->AddDestructionObserver(this);
127 }
128
129 ~MessageLoopObserver() override {
130 base::MessageLoop::current()->RemoveDestructionObserver(this);
131 }
132
133 void ShutDown() {
134 if (!is_active_)
135 return;
136
137 // The call into |context_| below may reenter ShutDown(), hence we set
138 // |is_active_| to false here.
139 is_active_ = false;
140 if (context_)
141 context_->ShutDownOnIOThread();
142
143 delete this;
144 }
145
146 private:
147 void WillDestroyCurrentMessageLoop() override {
148 DCHECK(is_active_);
149 ShutDown();
150 }
151
152 bool is_active_ = true;
153 base::WeakPtr<IOThreadContext> context_;
154
155 DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver);
156 };
157
158 ~IOThreadContext() override {}
159
160 void StartOnIOThread() {
161 // Should bind |io_thread_checker_| to the context's thread.
162 DCHECK(io_thread_checker_.CalledOnValidThread());
163 service_context_.reset(new shell::ServiceContext(
164 this, std::move(pending_service_request_),
165 std::move(io_thread_connector_),
166 std::move(pending_connector_request_)));
167
168 // MessageLoopObserver owns itself.
169 message_loop_observer_ =
170 new MessageLoopObserver(weak_factory_.GetWeakPtr());
171 }
172
173 void ShutDownOnIOThread() {
174 DCHECK(io_thread_checker_.CalledOnValidThread());
175
176 weak_factory_.InvalidateWeakPtrs();
177
178 // Note that this method may be invoked by MessageLoopObserver observing
179 // MessageLoop destruction. In that case, this call to ShutDown is
180 // effectively a no-op. In any case it's safe.
181 if (message_loop_observer_) {
182 message_loop_observer_->ShutDown();
183 message_loop_observer_ = nullptr;
184 }
185
186 // Resetting the ServiceContext below may otherwise release the last
187 // reference to this IOThreadContext. We keep it alive until the stack
188 // unwinds.
189 scoped_refptr<IOThreadContext> keepalive(this);
190
191 factory_bindings_.CloseAllBindings();
192 service_context_.reset();
193
194 ClearConnectionFiltersOnIOThread();
195 }
196
197 void ClearConnectionFiltersOnIOThread() {
198 base::AutoLock lock(lock_);
199 connection_filters_.clear();
200 }
201
202 void RemoveConnectionFilterOnIOThread(int filter_id) {
203 base::AutoLock lock(lock_);
204 auto it = connection_filters_.find(filter_id);
205 DCHECK(it != connection_filters_.end());
206 connection_filters_.erase(it);
207 }
208
209 void OnBrowserConnectionLost() {
210 DCHECK(io_thread_checker_.CalledOnValidThread());
211 has_browser_connection_ = false;
212 }
213
214 /////////////////////////////////////////////////////////////////////////////
215 // shell::Service implementation
216
217 void OnStart(const shell::Identity& identity) override {
218 DCHECK(io_thread_checker_.CalledOnValidThread());
219 DCHECK(!initialize_handler_.is_null());
220 id_ = identity;
221
222 InitializeCallback handler = base::ResetAndReturn(&initialize_handler_);
223 callback_task_runner_->PostTask(FROM_HERE, base::Bind(handler, identity));
224 }
225
226 bool OnConnect(const shell::Identity& remote_identity,
227 shell::InterfaceRegistry* registry) override {
228 DCHECK(io_thread_checker_.CalledOnValidThread());
229 std::string remote_app = remote_identity.name();
230 if (remote_app == "service:shell") {
231 // Only expose the SCF interface to the shell.
232 registry->AddInterface<shell::mojom::ServiceFactory>(this);
233 return true;
234 }
235
236 bool accept = false;
237 {
238 base::AutoLock lock(lock_);
239 for (auto& entry : connection_filters_) {
240 accept |= entry.second->OnConnect(remote_identity, registry,
241 service_context_->connector());
242 }
243 }
244
245 if (remote_identity.name() == "service:content_browser" &&
246 !has_browser_connection_) {
247 has_browser_connection_ = true;
248 registry->set_default_binder(default_browser_binder_);
249 registry->SetConnectionLostClosure(
250 base::Bind(&IOThreadContext::OnBrowserConnectionLost, this));
251 return true;
252 }
253
254 // If no filters were interested, reject the connection.
255 return accept;
256 }
257
258 bool OnStop() override {
259 ClearConnectionFiltersOnIOThread();
260 callback_task_runner_->PostTask(FROM_HERE, stop_callback_);
261 return true;
262 }
263
264 /////////////////////////////////////////////////////////////////////////////
265 // shell::InterfaceFactory<shell::mojom::ServiceFactory> implementation
266
267 void Create(const shell::Identity& remote_identity,
268 shell::mojom::ServiceFactoryRequest request) override {
269 DCHECK(io_thread_checker_.CalledOnValidThread());
270 factory_bindings_.AddBinding(this, std::move(request));
271 }
272
273 /////////////////////////////////////////////////////////////////////////////
274 // shell::mojom::ServiceFactory implementation
275
276 void CreateService(shell::mojom::ServiceRequest request,
277 const std::string& name) override {
278 DCHECK(io_thread_checker_.CalledOnValidThread());
279 callback_task_runner_->PostTask(
280 FROM_HERE,
281 base::Bind(create_service_callback_, base::Passed(&request), name));
282 }
283
284 static void CallBinderOnTaskRunner(
285 scoped_refptr<base::SequencedTaskRunner> task_runner,
286 const shell::InterfaceRegistry::Binder& binder,
287 const std::string& interface_name,
288 mojo::ScopedMessagePipeHandle request_handle) {
289 task_runner->PostTask(FROM_HERE, base::Bind(binder, interface_name,
290 base::Passed(&request_handle)));
291 }
292
293 base::ThreadChecker io_thread_checker_;
294 bool started_ = false;
295
296 // Temporary state established on construction and consumed on the IO thread
297 // once the connection is started.
298 shell::mojom::ServiceRequest pending_service_request_;
299 scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
300 std::unique_ptr<shell::Connector> io_thread_connector_;
301 shell::mojom::ConnectorRequest pending_connector_request_;
302
303 // TaskRunner on which to run our owner's callbacks, i.e. the ones passed to
304 // Start().
305 scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
306
307 // Callback to run once Service::OnStart is invoked.
308 InitializeCallback initialize_handler_;
309
310 // Callback to run when a new Service request is received.
311 ServiceFactoryCallback create_service_callback_;
312
313 // Callback to run if the service is stopped by the service manager.
314 base::Closure stop_callback_;
315
316 // Called once a connection has been received from the browser process & the
317 // default binder (below) has been set up.
318 bool has_browser_connection_ = false;
319
320 shell::Identity id_;
321
322 // Default binder callback used for the browser connection's
323 // InterfaceRegistry.
324 //
325 // TODO(rockot): Remove this once all interfaces exposed to the browser are
326 // exposed via a ConnectionFilter.
327 shell::InterfaceRegistry::Binder default_browser_binder_;
328
329 std::unique_ptr<shell::ServiceContext> service_context_;
330 mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_;
331 int next_filter_id_ = kInvalidConnectionFilterId;
332
333 // Not owned.
334 MessageLoopObserver* message_loop_observer_ = nullptr;
335
336 // Guards |connection_filters_|.
337 base::Lock lock_;
338 std::map<int, std::unique_ptr<ConnectionFilter>> connection_filters_;
339
340 base::WeakPtrFactory<IOThreadContext> weak_factory_;
341
342 DISALLOW_COPY_AND_ASSIGN(IOThreadContext);
343 };
344
345 ////////////////////////////////////////////////////////////////////////////////
346 // MojoShellConnection, public:
347
348 // static
349 void MojoShellConnection::SetForProcess(
350 std::unique_ptr<MojoShellConnection> connection) {
351 DCHECK(!g_connection_for_process.Get());
352 g_connection_for_process.Get() = std::move(connection);
353 }
354
355 // static
356 MojoShellConnection* MojoShellConnection::GetForProcess() {
357 return g_connection_for_process.Get().get();
358 }
359
360 // static
361 void MojoShellConnection::DestroyForProcess() {
362 // This joins the shell controller thread.
363 g_connection_for_process.Get().reset();
364 }
365
366 // static
367 void MojoShellConnection::SetFactoryForTest(Factory* factory) {
368 DCHECK(!g_connection_for_process.Get());
369 mojo_shell_connection_factory = factory;
370 }
371
372 // static
373 std::unique_ptr<MojoShellConnection> MojoShellConnection::Create(
374 shell::mojom::ServiceRequest request,
375 scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
376 if (mojo_shell_connection_factory)
377 return mojo_shell_connection_factory->Run();
378 return base::MakeUnique<MojoShellConnectionImpl>(
379 std::move(request), io_task_runner);
380 }
381
382 MojoShellConnection::~MojoShellConnection() {}
383
384 ////////////////////////////////////////////////////////////////////////////////
385 // MojoShellConnectionImpl, public:
386
387 MojoShellConnectionImpl::MojoShellConnectionImpl(
388 shell::mojom::ServiceRequest request,
389 scoped_refptr<base::SequencedTaskRunner> io_task_runner)
390 : weak_factory_(this) {
391 shell::mojom::ConnectorRequest connector_request;
392 connector_ = shell::Connector::Create(&connector_request);
393
394 std::unique_ptr<shell::Connector> io_thread_connector = connector_->Clone();
395 context_ = new IOThreadContext(
396 std::move(request), io_task_runner, std::move(io_thread_connector),
397 std::move(connector_request));
398 }
399
400 MojoShellConnectionImpl::~MojoShellConnectionImpl() {
401 context_->ShutDown();
402 }
403
404 ////////////////////////////////////////////////////////////////////////////////
405 // MojoShellConnectionImpl, MojoShellConnection implementation:
406
407 void MojoShellConnectionImpl::Start() {
408 context_->Start(
409 base::Bind(&MojoShellConnectionImpl::OnContextInitialized,
410 weak_factory_.GetWeakPtr()),
411 base::Bind(&MojoShellConnectionImpl::CreateService,
412 weak_factory_.GetWeakPtr()),
413 base::Bind(&MojoShellConnectionImpl::OnConnectionLost,
414 weak_factory_.GetWeakPtr()));
415 }
416
417 void MojoShellConnectionImpl::SetInitializeHandler(
418 const base::Closure& handler) {
419 DCHECK(initialize_handler_.is_null());
420 initialize_handler_ = handler;
421 }
422
423 shell::Connector* MojoShellConnectionImpl::GetConnector() {
424 return connector_.get();
425 }
426
427 const shell::Identity& MojoShellConnectionImpl::GetIdentity() const {
428 return identity_;
429 }
430
431 void MojoShellConnectionImpl::SetConnectionLostClosure(
432 const base::Closure& closure) {
433 connection_lost_handler_ = closure;
434 }
435
436 void MojoShellConnectionImpl::SetupInterfaceRequestProxies(
437 shell::InterfaceRegistry* registry,
438 shell::InterfaceProvider* provider) {
439 // It's safe to bind |registry| as a raw pointer because the caller must
440 // guarantee that it outlives |this|, and |this| is bound as a weak ptr here.
441 context_->SetDefaultBinderForBrowserConnection(
442 base::Bind(&MojoShellConnectionImpl::GetInterface,
443 weak_factory_.GetWeakPtr(), registry));
444
445 // TODO(beng): remove provider parameter.
446 }
447
448 int MojoShellConnectionImpl::AddConnectionFilter(
449 std::unique_ptr<ConnectionFilter> filter) {
450 return context_->AddConnectionFilter(std::move(filter));
451 }
452
453 void MojoShellConnectionImpl::RemoveConnectionFilter(int filter_id) {
454 context_->RemoveConnectionFilter(filter_id);
455 }
456
457 void MojoShellConnectionImpl::AddEmbeddedService(
458 const std::string& name,
459 const MojoApplicationInfo& info) {
460 std::unique_ptr<EmbeddedApplicationRunner> app(
461 new EmbeddedApplicationRunner(name, info));
462 AddServiceRequestHandler(
463 name, base::Bind(&EmbeddedApplicationRunner::BindServiceRequest,
464 base::Unretained(app.get())));
465 auto result = embedded_apps_.insert(std::make_pair(name, std::move(app)));
466 DCHECK(result.second);
467 }
468
469 void MojoShellConnectionImpl::AddServiceRequestHandler(
470 const std::string& name,
471 const ServiceRequestHandler& handler) {
472 auto result = request_handlers_.insert(std::make_pair(name, handler));
473 DCHECK(result.second);
474 }
475
476 void MojoShellConnectionImpl::CreateService(
477 shell::mojom::ServiceRequest request,
478 const std::string& name) {
479 auto it = request_handlers_.find(name);
480 if (it != request_handlers_.end())
481 it->second.Run(std::move(request));
482 }
483
484 void MojoShellConnectionImpl::OnContextInitialized(
485 const shell::Identity& identity) {
486 identity_ = identity;
487 if (!initialize_handler_.is_null())
488 base::ResetAndReturn(&initialize_handler_).Run();
489 }
490
491 void MojoShellConnectionImpl::OnConnectionLost() {
492 if (!connection_lost_handler_.is_null())
493 connection_lost_handler_.Run();
494 }
495
496 void MojoShellConnectionImpl::GetInterface(
497 shell::mojom::InterfaceProvider* provider,
498 const std::string& interface_name,
499 mojo::ScopedMessagePipeHandle request_handle) {
500 provider->GetInterface(interface_name, std::move(request_handle));
501 }
502
503 } // namespace content
504
OLDNEW
« no previous file with comments | « content/common/mojo/mojo_shell_connection_impl.h ('k') | content/common/service_manager/DEPS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698