• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_
7 
8 #include <stdint.h>
9 
10 #include <algorithm>  // For |std::swap()|.
11 #include <memory>
12 #include <string>
13 #include <utility>
14 
15 #include "base/bind.h"
16 #include "base/callback_forward.h"
17 #include "base/logging.h"
18 #include "base/macros.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/sequenced_task_runner.h"
22 #include "mojo/public/cpp/bindings/associated_group.h"
23 #include "mojo/public/cpp/bindings/bindings_export.h"
24 #include "mojo/public/cpp/bindings/connection_error_callback.h"
25 #include "mojo/public/cpp/bindings/filter_chain.h"
26 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
27 #include "mojo/public/cpp/bindings/interface_id.h"
28 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
29 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
30 #include "mojo/public/cpp/bindings/message_header_validator.h"
31 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
32 
33 namespace mojo {
34 namespace internal {
35 
36 class MOJO_CPP_BINDINGS_EXPORT InterfacePtrStateBase {
37  public:
38   InterfacePtrStateBase();
39   ~InterfacePtrStateBase();
40 
handle()41   MessagePipeHandle handle() const {
42     return router_ ? router_->handle() : handle_.get();
43   }
44 
version()45   uint32_t version() const { return version_; }
46 
is_bound()47   bool is_bound() const { return handle_.is_valid() || endpoint_client_; }
48 
encountered_error()49   bool encountered_error() const {
50     return endpoint_client_ ? endpoint_client_->encountered_error() : false;
51   }
52 
HasAssociatedInterfaces()53   bool HasAssociatedInterfaces() const {
54     return router_ ? router_->HasAssociatedEndpoints() : false;
55   }
56 
57   // Returns true if bound and awaiting a response to a message.
has_pending_callbacks()58   bool has_pending_callbacks() const {
59     return endpoint_client_ && endpoint_client_->has_pending_responders();
60   }
61 
62  protected:
endpoint_client()63   InterfaceEndpointClient* endpoint_client() const {
64     return endpoint_client_.get();
65   }
router()66   MultiplexRouter* router() const { return router_.get(); }
67 
68   void QueryVersion(const base::Callback<void(uint32_t)>& callback);
69   void RequireVersion(uint32_t version);
70   void Swap(InterfacePtrStateBase* other);
71   void Bind(ScopedMessagePipeHandle handle,
72             uint32_t version,
73             scoped_refptr<base::SequencedTaskRunner> task_runner);
74 
PassMessagePipe()75   ScopedMessagePipeHandle PassMessagePipe() {
76     endpoint_client_.reset();
77     return router_ ? router_->PassMessagePipe() : std::move(handle_);
78   }
79 
80   bool InitializeEndpointClient(
81       bool passes_associated_kinds,
82       bool has_sync_methods,
83       std::unique_ptr<MessageReceiver> payload_validator);
84 
85  private:
86   void OnQueryVersion(const base::Callback<void(uint32_t)>& callback,
87                       uint32_t version);
88 
89   scoped_refptr<MultiplexRouter> router_;
90 
91   std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
92 
93   // |router_| (as well as other members above) is not initialized until
94   // read/write with the message pipe handle is needed. |handle_| is valid
95   // between the Bind() call and the initialization of |router_|.
96   ScopedMessagePipeHandle handle_;
97   scoped_refptr<base::SequencedTaskRunner> runner_;
98 
99   uint32_t version_ = 0;
100 
101   DISALLOW_COPY_AND_ASSIGN(InterfacePtrStateBase);
102 };
103 
104 template <typename Interface>
105 class InterfacePtrState : public InterfacePtrStateBase {
106  public:
107   using Proxy = typename Interface::Proxy_;
108 
109   InterfacePtrState() = default;
110   ~InterfacePtrState() = default;
111 
instance()112   Proxy* instance() {
113     ConfigureProxyIfNecessary();
114 
115     // This will be null if the object is not bound.
116     return proxy_.get();
117   }
118 
QueryVersion(const base::Callback<void (uint32_t)> & callback)119   void QueryVersion(const base::Callback<void(uint32_t)>& callback) {
120     ConfigureProxyIfNecessary();
121     InterfacePtrStateBase::QueryVersion(callback);
122   }
123 
RequireVersion(uint32_t version)124   void RequireVersion(uint32_t version) {
125     ConfigureProxyIfNecessary();
126     InterfacePtrStateBase::RequireVersion(version);
127   }
128 
FlushForTesting()129   void FlushForTesting() {
130     ConfigureProxyIfNecessary();
131     endpoint_client()->FlushForTesting();
132   }
133 
CloseWithReason(uint32_t custom_reason,const std::string & description)134   void CloseWithReason(uint32_t custom_reason, const std::string& description) {
135     ConfigureProxyIfNecessary();
136     endpoint_client()->CloseWithReason(custom_reason, description);
137   }
138 
Swap(InterfacePtrState * other)139   void Swap(InterfacePtrState* other) {
140     using std::swap;
141     swap(other->proxy_, proxy_);
142     InterfacePtrStateBase::Swap(other);
143   }
144 
Bind(InterfacePtrInfo<Interface> info,scoped_refptr<base::SequencedTaskRunner> runner)145   void Bind(InterfacePtrInfo<Interface> info,
146             scoped_refptr<base::SequencedTaskRunner> runner) {
147     DCHECK(!proxy_);
148     InterfacePtrStateBase::Bind(info.PassHandle(), info.version(),
149                                 std::move(runner));
150   }
151 
152   // After this method is called, the object is in an invalid state and
153   // shouldn't be reused.
PassInterface()154   InterfacePtrInfo<Interface> PassInterface() {
155     proxy_.reset();
156     return InterfacePtrInfo<Interface>(PassMessagePipe(), version());
157   }
158 
set_connection_error_handler(base::OnceClosure error_handler)159   void set_connection_error_handler(base::OnceClosure error_handler) {
160     ConfigureProxyIfNecessary();
161 
162     DCHECK(endpoint_client());
163     endpoint_client()->set_connection_error_handler(std::move(error_handler));
164   }
165 
set_connection_error_with_reason_handler(ConnectionErrorWithReasonCallback error_handler)166   void set_connection_error_with_reason_handler(
167       ConnectionErrorWithReasonCallback error_handler) {
168     ConfigureProxyIfNecessary();
169 
170     DCHECK(endpoint_client());
171     endpoint_client()->set_connection_error_with_reason_handler(
172         std::move(error_handler));
173   }
174 
associated_group()175   AssociatedGroup* associated_group() {
176     ConfigureProxyIfNecessary();
177     return endpoint_client()->associated_group();
178   }
179 
EnableTestingMode()180   void EnableTestingMode() {
181     ConfigureProxyIfNecessary();
182     router()->EnableTestingMode();
183   }
184 
ForwardMessage(Message message)185   void ForwardMessage(Message message) {
186     ConfigureProxyIfNecessary();
187     endpoint_client()->Accept(&message);
188   }
189 
ForwardMessageWithResponder(Message message,std::unique_ptr<MessageReceiver> responder)190   void ForwardMessageWithResponder(Message message,
191                                    std::unique_ptr<MessageReceiver> responder) {
192     ConfigureProxyIfNecessary();
193     endpoint_client()->AcceptWithResponder(&message, std::move(responder));
194   }
195 
RaiseError()196   void RaiseError() {
197     ConfigureProxyIfNecessary();
198     endpoint_client()->RaiseError();
199   }
200 
201  private:
ConfigureProxyIfNecessary()202   void ConfigureProxyIfNecessary() {
203     // The proxy has been configured.
204     if (proxy_) {
205       DCHECK(router());
206       DCHECK(endpoint_client());
207       return;
208     }
209 
210     if (InitializeEndpointClient(
211             Interface::PassesAssociatedKinds_, Interface::HasSyncMethods_,
212             std::make_unique<typename Interface::ResponseValidator_>())) {
213       router()->SetMasterInterfaceName(Interface::Name_);
214       proxy_ = std::make_unique<Proxy>(endpoint_client());
215     }
216   }
217 
218   std::unique_ptr<Proxy> proxy_;
219 
220   DISALLOW_COPY_AND_ASSIGN(InterfacePtrState);
221 };
222 
223 }  // namespace internal
224 }  // namespace mojo
225 
226 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_
227