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