• 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_BINDING_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_
7 
8 #include <string>
9 #include <utility>
10 
11 #include "base/callback_forward.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #include "mojo/public/cpp/bindings/connection_error_callback.h"
17 #include "mojo/public/cpp/bindings/interface_ptr.h"
18 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
19 #include "mojo/public/cpp/bindings/interface_request.h"
20 #include "mojo/public/cpp/bindings/lib/binding_state.h"
21 #include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
22 #include "mojo/public/cpp/system/core.h"
23 
24 namespace mojo {
25 
26 class MessageReceiver;
27 
28 // Represents the binding of an interface implementation to a message pipe.
29 // When the |Binding| object is destroyed, the binding between the message pipe
30 // and the interface is torn down and the message pipe is closed, leaving the
31 // interface implementation in an unbound state.
32 //
33 // Example:
34 //
35 //   #include "foo.mojom.h"
36 //
37 //   class FooImpl : public Foo {
38 //    public:
39 //     explicit FooImpl(InterfaceRequest<Foo> request)
40 //         : binding_(this, std::move(request)) {}
41 //
42 //     // Foo implementation here.
43 //
44 //    private:
45 //     Binding<Foo> binding_;
46 //   };
47 //
48 //   class MyFooFactory : public InterfaceFactory<Foo> {
49 //    public:
50 //     void Create(..., InterfaceRequest<Foo> request) override {
51 //       auto f = new FooImpl(std::move(request));
52 //       // Do something to manage the lifetime of |f|. Use StrongBinding<> to
53 //       // delete FooImpl on connection errors.
54 //     }
55 //   };
56 //
57 // This class is thread hostile while bound to a message pipe. All calls to this
58 // class must be from the thread that bound it. The interface implementation's
59 // methods will be called from the thread that bound this. If a Binding is not
60 // bound to a message pipe, it may be bound or destroyed on any thread.
61 //
62 // When you bind this class to a message pipe, optionally you can specify a
63 // base::SingleThreadTaskRunner. This task runner must belong to the same
64 // thread. It will be used to dispatch incoming method calls and connection
65 // error notification. It is useful when you attach multiple task runners to a
66 // single thread for the purposes of task scheduling. Please note that incoming
67 // synchrounous method calls may not be run from this task runner, when they
68 // reenter outgoing synchrounous calls on the same thread.
69 template <typename Interface,
70           typename ImplRefTraits = RawPtrImplRefTraits<Interface>>
71 class Binding {
72  public:
73   using ImplPointerType = typename ImplRefTraits::PointerType;
74 
75   // Constructs an incomplete binding that will use the implementation |impl|.
76   // The binding may be completed with a subsequent call to the |Bind| method.
77   // Does not take ownership of |impl|, which must outlive the binding.
Binding(ImplPointerType impl)78   explicit Binding(ImplPointerType impl) : internal_state_(std::move(impl)) {}
79 
80   // Constructs a completed binding of message pipe |handle| to implementation
81   // |impl|. Does not take ownership of |impl|, which must outlive the binding.
82   Binding(ImplPointerType impl,
83           ScopedMessagePipeHandle handle,
84           scoped_refptr<base::SingleThreadTaskRunner> runner =
85               base::ThreadTaskRunnerHandle::Get())
Binding(std::move (impl))86       : Binding(std::move(impl)) {
87     Bind(std::move(handle), std::move(runner));
88   }
89 
90   // Constructs a completed binding of |impl| to a new message pipe, passing the
91   // client end to |ptr|, which takes ownership of it. The caller is expected to
92   // pass |ptr| on to the client of the service. Does not take ownership of any
93   // of the parameters. |impl| must outlive the binding. |ptr| only needs to
94   // last until the constructor returns.
95   Binding(ImplPointerType impl,
96           InterfacePtr<Interface>* ptr,
97           scoped_refptr<base::SingleThreadTaskRunner> runner =
98               base::ThreadTaskRunnerHandle::Get())
Binding(std::move (impl))99       : Binding(std::move(impl)) {
100     Bind(ptr, std::move(runner));
101   }
102 
103   // Constructs a completed binding of |impl| to the message pipe endpoint in
104   // |request|, taking ownership of the endpoint. Does not take ownership of
105   // |impl|, which must outlive the binding.
106   Binding(ImplPointerType impl,
107           InterfaceRequest<Interface> request,
108           scoped_refptr<base::SingleThreadTaskRunner> runner =
109               base::ThreadTaskRunnerHandle::Get())
Binding(std::move (impl))110       : Binding(std::move(impl)) {
111     Bind(request.PassMessagePipe(), std::move(runner));
112   }
113 
114   // Tears down the binding, closing the message pipe and leaving the interface
115   // implementation unbound.
~Binding()116   ~Binding() {}
117 
118   // Returns an InterfacePtr bound to one end of a pipe whose other end is
119   // bound to |this|.
120   InterfacePtr<Interface> CreateInterfacePtrAndBind(
121       scoped_refptr<base::SingleThreadTaskRunner> runner =
122           base::ThreadTaskRunnerHandle::Get()) {
123     InterfacePtr<Interface> interface_ptr;
124     Bind(&interface_ptr, std::move(runner));
125     return interface_ptr;
126   }
127 
128   // Completes a binding that was constructed with only an interface
129   // implementation. Takes ownership of |handle| and binds it to the previously
130   // specified implementation.
131   void Bind(ScopedMessagePipeHandle handle,
132             scoped_refptr<base::SingleThreadTaskRunner> runner =
133                 base::ThreadTaskRunnerHandle::Get()) {
134     internal_state_.Bind(std::move(handle), std::move(runner));
135   }
136 
137   // Completes a binding that was constructed with only an interface
138   // implementation by creating a new message pipe, binding one end of it to the
139   // previously specified implementation, and passing the other to |ptr|, which
140   // takes ownership of it. The caller is expected to pass |ptr| on to the
141   // eventual client of the service. Does not take ownership of |ptr|.
142   void Bind(InterfacePtr<Interface>* ptr,
143             scoped_refptr<base::SingleThreadTaskRunner> runner =
144                 base::ThreadTaskRunnerHandle::Get()) {
145     MessagePipe pipe;
146     ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0),
147                                           Interface::Version_),
148               runner);
149     Bind(std::move(pipe.handle1), std::move(runner));
150   }
151 
152   // Completes a binding that was constructed with only an interface
153   // implementation by removing the message pipe endpoint from |request| and
154   // binding it to the previously specified implementation.
155   void Bind(InterfaceRequest<Interface> request,
156             scoped_refptr<base::SingleThreadTaskRunner> runner =
157                 base::ThreadTaskRunnerHandle::Get()) {
158     Bind(request.PassMessagePipe(), std::move(runner));
159   }
160 
161   // Adds a message filter to be notified of each incoming message before
162   // dispatch. If a filter returns |false| from Accept(), the message is not
163   // dispatched and the pipe is closed. Filters cannot be removed.
AddFilter(std::unique_ptr<MessageReceiver> filter)164   void AddFilter(std::unique_ptr<MessageReceiver> filter) {
165     DCHECK(is_bound());
166     internal_state_.AddFilter(std::move(filter));
167   }
168 
169   // Whether there are any associated interfaces running on the pipe currently.
HasAssociatedInterfaces()170   bool HasAssociatedInterfaces() const {
171     return internal_state_.HasAssociatedInterfaces();
172   }
173 
174   // Stops processing incoming messages until
175   // ResumeIncomingMethodCallProcessing(), or WaitForIncomingMethodCall().
176   // Outgoing messages are still sent.
177   //
178   // No errors are detected on the message pipe while paused.
179   //
180   // This method may only be called if the object has been bound to a message
181   // pipe and there are no associated interfaces running.
PauseIncomingMethodCallProcessing()182   void PauseIncomingMethodCallProcessing() {
183     CHECK(!HasAssociatedInterfaces());
184     internal_state_.PauseIncomingMethodCallProcessing();
185   }
ResumeIncomingMethodCallProcessing()186   void ResumeIncomingMethodCallProcessing() {
187     internal_state_.ResumeIncomingMethodCallProcessing();
188   }
189 
190   // Blocks the calling thread until either a call arrives on the previously
191   // bound message pipe, the deadline is exceeded, or an error occurs. Returns
192   // true if a method was successfully read and dispatched.
193   //
194   // This method may only be called if the object has been bound to a message
195   // pipe and there are no associated interfaces running.
196   bool WaitForIncomingMethodCall(
197       MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) {
198     CHECK(!HasAssociatedInterfaces());
199     return internal_state_.WaitForIncomingMethodCall(deadline);
200   }
201 
202   // Closes the message pipe that was previously bound. Put this object into a
203   // state where it can be rebound to a new pipe.
Close()204   void Close() { internal_state_.Close(); }
205 
206   // Similar to the method above, but also specifies a disconnect reason.
CloseWithReason(uint32_t custom_reason,const std::string & description)207   void CloseWithReason(uint32_t custom_reason, const std::string& description) {
208     internal_state_.CloseWithReason(custom_reason, description);
209   }
210 
211   // Unbinds the underlying pipe from this binding and returns it so it can be
212   // used in another context, such as on another thread or with a different
213   // implementation. Put this object into a state where it can be rebound to a
214   // new pipe.
215   //
216   // This method may only be called if the object has been bound to a message
217   // pipe and there are no associated interfaces running.
218   //
219   // TODO(yzshen): For now, users need to make sure there is no one holding
220   // on to associated interface endpoint handles at both sides of the
221   // message pipe in order to call this method. We need a way to forcefully
222   // invalidate associated interface endpoint handles.
Unbind()223   InterfaceRequest<Interface> Unbind() {
224     CHECK(!HasAssociatedInterfaces());
225     return internal_state_.Unbind();
226   }
227 
228   // Sets an error handler that will be called if a connection error occurs on
229   // the bound message pipe.
230   //
231   // This method may only be called after this Binding has been bound to a
232   // message pipe. The error handler will be reset when this Binding is unbound
233   // or closed.
set_connection_error_handler(const base::Closure & error_handler)234   void set_connection_error_handler(const base::Closure& error_handler) {
235     DCHECK(is_bound());
236     internal_state_.set_connection_error_handler(error_handler);
237   }
238 
set_connection_error_with_reason_handler(const ConnectionErrorWithReasonCallback & error_handler)239   void set_connection_error_with_reason_handler(
240       const ConnectionErrorWithReasonCallback& error_handler) {
241     DCHECK(is_bound());
242     internal_state_.set_connection_error_with_reason_handler(error_handler);
243   }
244 
245   // Returns the interface implementation that was previously specified. Caller
246   // does not take ownership.
impl()247   Interface* impl() { return internal_state_.impl(); }
248 
249   // Indicates whether the binding has been completed (i.e., whether a message
250   // pipe has been bound to the implementation).
is_bound()251   bool is_bound() const { return internal_state_.is_bound(); }
252 
253   // Returns the value of the handle currently bound to this Binding which can
254   // be used to make explicit Wait/WaitMany calls. Requires that the Binding be
255   // bound. Ownership of the handle is retained by the Binding, it is not
256   // transferred to the caller.
handle()257   MessagePipeHandle handle() const { return internal_state_.handle(); }
258 
259   // Sends a no-op message on the underlying message pipe and runs the current
260   // message loop until its response is received. This can be used in tests to
261   // verify that no message was sent on a message pipe in response to some
262   // stimulus.
FlushForTesting()263   void FlushForTesting() { internal_state_.FlushForTesting(); }
264 
265   // Exposed for testing, should not generally be used.
EnableTestingMode()266   void EnableTestingMode() { internal_state_.EnableTestingMode(); }
267 
268  private:
269   internal::BindingState<Interface, ImplRefTraits> internal_state_;
270 
271   DISALLOW_COPY_AND_ASSIGN(Binding);
272 };
273 
274 }  // namespace mojo
275 
276 #endif  // MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_
277