• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_
7 
8 #include <memory>
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/logging.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/single_thread_task_runner.h"
18 #include "mojo/public/cpp/bindings/associated_group.h"
19 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
20 #include "mojo/public/cpp/bindings/interface_id.h"
21 #include "mojo/public/cpp/bindings/interface_ptr.h"
22 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
23 #include "mojo/public/cpp/bindings/interface_request.h"
24 #include "mojo/public/cpp/bindings/lib/filter_chain.h"
25 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
26 #include "mojo/public/cpp/bindings/lib/router.h"
27 #include "mojo/public/cpp/bindings/message_header_validator.h"
28 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
29 #include "mojo/public/cpp/system/core.h"
30 
31 namespace mojo {
32 namespace internal {
33 
34 template <typename Interface, bool use_multiplex_router>
35 class BindingState;
36 
37 // Uses a single-threaded, dedicated router. If |Interface| doesn't have any
38 // methods to pass associated interface pointers or requests, there won't be
39 // multiple interfaces running on the underlying message pipe. In that case, we
40 // can use this specialization to reduce cost.
41 template <typename Interface>
42 class BindingState<Interface, false> {
43  public:
BindingState(Interface * impl)44   explicit BindingState(Interface* impl) : impl_(impl) {
45     stub_.set_sink(impl_);
46   }
47 
~BindingState()48   ~BindingState() { Close(); }
49 
Bind(ScopedMessagePipeHandle handle,scoped_refptr<base::SingleThreadTaskRunner> runner)50   void Bind(ScopedMessagePipeHandle handle,
51             scoped_refptr<base::SingleThreadTaskRunner> runner) {
52     DCHECK(!router_);
53     internal::FilterChain filters;
54     filters.Append<MessageHeaderValidator>(Interface::Name_);
55     filters.Append<typename Interface::RequestValidator_>();
56 
57     router_ =
58         new internal::Router(std::move(handle), std::move(filters),
59                              Interface::HasSyncMethods_, std::move(runner));
60     router_->set_incoming_receiver(&stub_);
61     router_->set_connection_error_handler(
62         base::Bind(&BindingState::RunConnectionErrorHandler,
63                    base::Unretained(this)));
64   }
65 
HasAssociatedInterfaces()66   bool HasAssociatedInterfaces() const { return false; }
67 
PauseIncomingMethodCallProcessing()68   void PauseIncomingMethodCallProcessing() {
69     DCHECK(router_);
70     router_->PauseIncomingMethodCallProcessing();
71   }
ResumeIncomingMethodCallProcessing()72   void ResumeIncomingMethodCallProcessing() {
73     DCHECK(router_);
74     router_->ResumeIncomingMethodCallProcessing();
75   }
76 
77   bool WaitForIncomingMethodCall(
78       MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) {
79     DCHECK(router_);
80     return router_->WaitForIncomingMessage(deadline);
81   }
82 
Close()83   void Close() {
84     if (!router_)
85       return;
86 
87     router_->CloseMessagePipe();
88     DestroyRouter();
89   }
90 
Unbind()91   InterfaceRequest<Interface> Unbind() {
92     InterfaceRequest<Interface> request =
93         MakeRequest<Interface>(router_->PassMessagePipe());
94     DestroyRouter();
95     return std::move(request);
96   }
97 
set_connection_error_handler(const base::Closure & error_handler)98   void set_connection_error_handler(const base::Closure& error_handler) {
99     DCHECK(is_bound());
100     connection_error_handler_ = error_handler;
101   }
102 
impl()103   Interface* impl() { return impl_; }
104 
is_bound()105   bool is_bound() const { return !!router_; }
106 
handle()107   MessagePipeHandle handle() const {
108     DCHECK(is_bound());
109     return router_->handle();
110   }
111 
associated_group()112   AssociatedGroup* associated_group() { return nullptr; }
113 
EnableTestingMode()114   void EnableTestingMode() {
115     DCHECK(is_bound());
116     router_->EnableTestingMode();
117   }
118 
119  private:
DestroyRouter()120   void DestroyRouter() {
121     router_->set_connection_error_handler(base::Closure());
122     delete router_;
123     router_ = nullptr;
124     connection_error_handler_.Reset();
125   }
126 
RunConnectionErrorHandler()127   void RunConnectionErrorHandler() {
128     if (!connection_error_handler_.is_null())
129       connection_error_handler_.Run();
130   }
131 
132   internal::Router* router_ = nullptr;
133   typename Interface::Stub_ stub_;
134   Interface* impl_;
135   base::Closure connection_error_handler_;
136 
137   DISALLOW_COPY_AND_ASSIGN(BindingState);
138 };
139 
140 // Uses a multiplexing router. If |Interface| has methods to pass associated
141 // interface pointers or requests, this specialization should be used.
142 template <typename Interface>
143 class BindingState<Interface, true> {
144  public:
BindingState(Interface * impl)145   explicit BindingState(Interface* impl) : impl_(impl) {
146     stub_.set_sink(impl_);
147   }
148 
~BindingState()149   ~BindingState() { Close(); }
150 
Bind(ScopedMessagePipeHandle handle,scoped_refptr<base::SingleThreadTaskRunner> runner)151   void Bind(ScopedMessagePipeHandle handle,
152             scoped_refptr<base::SingleThreadTaskRunner> runner) {
153     DCHECK(!router_);
154 
155     router_ = new internal::MultiplexRouter(false, std::move(handle), runner);
156     router_->SetMasterInterfaceName(Interface::Name_);
157     stub_.serialization_context()->group_controller = router_;
158 
159     endpoint_client_.reset(new InterfaceEndpointClient(
160         router_->CreateLocalEndpointHandle(kMasterInterfaceId),
161         &stub_, base::WrapUnique(new typename Interface::RequestValidator_()),
162         Interface::HasSyncMethods_, std::move(runner)));
163 
164     endpoint_client_->set_connection_error_handler(
165         base::Bind(&BindingState::RunConnectionErrorHandler,
166                    base::Unretained(this)));
167   }
168 
HasAssociatedInterfaces()169   bool HasAssociatedInterfaces() const {
170     return router_ ? router_->HasAssociatedEndpoints() : false;
171   }
172 
PauseIncomingMethodCallProcessing()173   void PauseIncomingMethodCallProcessing() {
174     DCHECK(router_);
175     router_->PauseIncomingMethodCallProcessing();
176   }
ResumeIncomingMethodCallProcessing()177   void ResumeIncomingMethodCallProcessing() {
178     DCHECK(router_);
179     router_->ResumeIncomingMethodCallProcessing();
180   }
181 
182   bool WaitForIncomingMethodCall(
183       MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) {
184     DCHECK(router_);
185     return router_->WaitForIncomingMessage(deadline);
186   }
187 
Close()188   void Close() {
189     if (!router_)
190       return;
191 
192     endpoint_client_.reset();
193     router_->CloseMessagePipe();
194     router_ = nullptr;
195     connection_error_handler_.Reset();
196   }
197 
Unbind()198   InterfaceRequest<Interface> Unbind() {
199     endpoint_client_.reset();
200     InterfaceRequest<Interface> request =
201         MakeRequest<Interface>(router_->PassMessagePipe());
202     router_ = nullptr;
203     connection_error_handler_.Reset();
204     return request;
205   }
206 
set_connection_error_handler(const base::Closure & error_handler)207   void set_connection_error_handler(const base::Closure& error_handler) {
208     DCHECK(is_bound());
209     connection_error_handler_ = error_handler;
210   }
211 
impl()212   Interface* impl() { return impl_; }
213 
is_bound()214   bool is_bound() const { return !!router_; }
215 
handle()216   MessagePipeHandle handle() const {
217     DCHECK(is_bound());
218     return router_->handle();
219   }
220 
associated_group()221   AssociatedGroup* associated_group() {
222     return endpoint_client_ ? endpoint_client_->associated_group() : nullptr;
223   }
224 
EnableTestingMode()225   void EnableTestingMode() {
226     DCHECK(is_bound());
227     router_->EnableTestingMode();
228   }
229 
230  private:
RunConnectionErrorHandler()231   void RunConnectionErrorHandler() {
232     if (!connection_error_handler_.is_null())
233       connection_error_handler_.Run();
234   }
235 
236   scoped_refptr<internal::MultiplexRouter> router_;
237   std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
238 
239   typename Interface::Stub_ stub_;
240   Interface* impl_;
241   base::Closure connection_error_handler_;
242 
243   DISALLOW_COPY_AND_ASSIGN(BindingState);
244 };
245 
246 }  // namesapce internal
247 }  // namespace mojo
248 
249 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_
250