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