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_INTERFACE_PTR_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
7 
8 #include <stdint.h>
9 #include <utility>
10 
11 #include "base/callback_forward.h"
12 #include "base/logging.h"
13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
18 #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
19 
20 namespace mojo {
21 
22 class AssociatedGroup;
23 
24 // A pointer to a local proxy of a remote Interface implementation. Uses a
25 // message pipe to communicate with the remote implementation, and automatically
26 // closes the pipe and deletes the proxy on destruction. The pointer must be
27 // bound to a message pipe before the interface methods can be called.
28 //
29 // This class is thread hostile, as is the local proxy it manages, while bound
30 // to a message pipe. All calls to this class or the proxy should be from the
31 // same thread that bound it. If you need to move the proxy to a different
32 // thread, extract the InterfacePtrInfo (containing just the message pipe and
33 // any version information) using PassInterface(), pass it to a different
34 // thread, and create and bind a new InterfacePtr from that thread. If an
35 // InterfacePtr is not bound to a message pipe, it may be bound or destroyed on
36 // any thread.
37 template <typename Interface>
38 class InterfacePtr {
39  public:
40   // Constructs an unbound InterfacePtr.
InterfacePtr()41   InterfacePtr() {}
InterfacePtr(decltype (nullptr))42   InterfacePtr(decltype(nullptr)) {}
43 
44   // Takes over the binding of another InterfacePtr.
InterfacePtr(InterfacePtr && other)45   InterfacePtr(InterfacePtr&& other) {
46     internal_state_.Swap(&other.internal_state_);
47   }
48 
49   // Takes over the binding of another InterfacePtr, and closes any message pipe
50   // already bound to this pointer.
51   InterfacePtr& operator=(InterfacePtr&& other) {
52     reset();
53     internal_state_.Swap(&other.internal_state_);
54     return *this;
55   }
56 
57   // Assigning nullptr to this class causes it to close the currently bound
58   // message pipe (if any) and returns the pointer to the unbound state.
decltype(nullptr)59   InterfacePtr& operator=(decltype(nullptr)) {
60     reset();
61     return *this;
62   }
63 
64   // Closes the bound message pipe (if any) on destruction.
~InterfacePtr()65   ~InterfacePtr() {}
66 
67   // Binds the InterfacePtr to a remote implementation of Interface.
68   //
69   // Calling with an invalid |info| (containing an invalid message pipe handle)
70   // has the same effect as reset(). In this case, the InterfacePtr is not
71   // considered as bound.
72   //
73   // |runner| must belong to the same thread. It will be used to dispatch all
74   // callbacks and connection error notification. It is useful when you attach
75   // multiple task runners to a single thread for the purposes of task
76   // scheduling.
77   void Bind(InterfacePtrInfo<Interface> info,
78             scoped_refptr<base::SingleThreadTaskRunner> runner =
79                 base::ThreadTaskRunnerHandle::Get()) {
80     reset();
81     if (info.is_valid())
82       internal_state_.Bind(std::move(info), std::move(runner));
83   }
84 
85   // Returns whether or not this InterfacePtr is bound to a message pipe.
is_bound()86   bool is_bound() const { return internal_state_.is_bound(); }
87 
88   // Returns a raw pointer to the local proxy. Caller does not take ownership.
89   // Note that the local proxy is thread hostile, as stated above.
get()90   Interface* get() const { return internal_state_.instance(); }
91 
92   // Functions like a pointer to Interface. Must already be bound.
93   Interface* operator->() const { return get(); }
94   Interface& operator*() const { return *get(); }
95 
96   // Returns the version number of the interface that the remote side supports.
version()97   uint32_t version() const { return internal_state_.version(); }
98 
99   // Queries the max version that the remote side supports. On completion, the
100   // result will be returned as the input of |callback|. The version number of
101   // this interface pointer will also be updated.
QueryVersion(const base::Callback<void (uint32_t)> & callback)102   void QueryVersion(const base::Callback<void(uint32_t)>& callback) {
103     internal_state_.QueryVersion(callback);
104   }
105 
106   // If the remote side doesn't support the specified version, it will close its
107   // end of the message pipe asynchronously. This does nothing if it's already
108   // known that the remote side supports the specified version, i.e., if
109   // |version <= this->version()|.
110   //
111   // After calling RequireVersion() with a version not supported by the remote
112   // side, all subsequent calls to interface methods will be ignored.
RequireVersion(uint32_t version)113   void RequireVersion(uint32_t version) {
114     internal_state_.RequireVersion(version);
115   }
116 
117   // Closes the bound message pipe (if any) and returns the pointer to the
118   // unbound state.
reset()119   void reset() {
120     State doomed;
121     internal_state_.Swap(&doomed);
122   }
123 
124   // Whether there are any associated interfaces running on the pipe currently.
HasAssociatedInterfaces()125   bool HasAssociatedInterfaces() const {
126     return internal_state_.HasAssociatedInterfaces();
127   }
128 
129   // Indicates whether the message pipe has encountered an error. If true,
130   // method calls made on this interface will be dropped (and may already have
131   // been dropped).
encountered_error()132   bool encountered_error() const { return internal_state_.encountered_error(); }
133 
134   // Registers a handler to receive error notifications. The handler will be
135   // called from the thread that owns this InterfacePtr.
136   //
137   // This method may only be called after the InterfacePtr has been bound to a
138   // message pipe.
set_connection_error_handler(const base::Closure & error_handler)139   void set_connection_error_handler(const base::Closure& error_handler) {
140     internal_state_.set_connection_error_handler(error_handler);
141   }
142 
143   // Unbinds the InterfacePtr and returns the information which could be used
144   // to setup an InterfacePtr again. This method may be used to move the proxy
145   // to a different thread (see class comments for details).
146   //
147   // It is an error to call PassInterface() while:
148   //   - there are pending responses; or
149   //     TODO: fix this restriction, it's not always obvious when there is a
150   //     pending response.
151   //   - there are associated interfaces running.
152   //     TODO(yzshen): For now, users need to make sure there is no one holding
153   //     on to associated interface endpoint handles at both sides of the
154   //     message pipe in order to call this method. We need a way to forcefully
155   //     invalidate associated interface endpoint handles.
PassInterface()156   InterfacePtrInfo<Interface> PassInterface() {
157     CHECK(!HasAssociatedInterfaces());
158     CHECK(!internal_state_.has_pending_callbacks());
159     State state;
160     internal_state_.Swap(&state);
161 
162     return state.PassInterface();
163   }
164 
165   // Returns the associated group that this object belongs to. Returns null if:
166   //   - this object is not bound; or
167   //   - the interface doesn't have methods to pass associated interface
168   //     pointers or requests.
associated_group()169   AssociatedGroup* associated_group() {
170     return internal_state_.associated_group();
171   }
172 
Equals(const InterfacePtr & other)173   bool Equals(const InterfacePtr& other) const {
174     if (this == &other)
175       return true;
176 
177     // Now that the two refer to different objects, they are equivalent if
178     // and only if they are both null.
179     return !(*this) && !other;
180   }
181 
182   // DO NOT USE. Exposed only for internal use and for testing.
183   internal::InterfacePtrState<Interface, Interface::PassesAssociatedKinds_>*
internal_state()184   internal_state() {
185     return &internal_state_;
186   }
187 
188   // Allow InterfacePtr<> to be used in boolean expressions, but not
189   // implicitly convertible to a real bool (which is dangerous).
190  private:
191   // TODO(dcheng): Use an explicit conversion operator.
192   typedef internal::InterfacePtrState<Interface,
193                                       Interface::PassesAssociatedKinds_>
194       InterfacePtr::*Testable;
195 
196  public:
Testable()197   operator Testable() const {
198     return internal_state_.is_bound() ? &InterfacePtr::internal_state_
199                                       : nullptr;
200   }
201 
202  private:
203   // Forbid the == and != operators explicitly, otherwise InterfacePtr will be
204   // converted to Testable to do == or != comparison.
205   template <typename T>
206   bool operator==(const InterfacePtr<T>& other) const = delete;
207   template <typename T>
208   bool operator!=(const InterfacePtr<T>& other) const = delete;
209 
210   typedef internal::InterfacePtrState<Interface,
211                                       Interface::PassesAssociatedKinds_> State;
212   mutable State internal_state_;
213 
214   DISALLOW_COPY_AND_ASSIGN(InterfacePtr);
215 };
216 
217 // If |info| is valid (containing a valid message pipe handle), returns an
218 // InterfacePtr bound to it. Otherwise, returns an unbound InterfacePtr.
219 template <typename Interface>
220 InterfacePtr<Interface> MakeProxy(
221     InterfacePtrInfo<Interface> info,
222     scoped_refptr<base::SingleThreadTaskRunner> runner =
223         base::ThreadTaskRunnerHandle::Get()) {
224   InterfacePtr<Interface> ptr;
225   if (info.is_valid())
226     ptr.Bind(std::move(info), std::move(runner));
227   return std::move(ptr);
228 }
229 
230 }  // namespace mojo
231 
232 #endif  // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
233