• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_ASSOCIATED_BINDING_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/single_thread_task_runner.h"
19 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
20 #include "mojo/public/cpp/bindings/associated_interface_request.h"
21 #include "mojo/public/cpp/bindings/bindings_export.h"
22 #include "mojo/public/cpp/bindings/connection_error_callback.h"
23 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
24 #include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
25 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
26 
27 namespace mojo {
28 
29 class MessageReceiver;
30 
31 // Base class used to factor out code in AssociatedBinding<T> expansions, in
32 // particular for Bind().
33 class MOJO_CPP_BINDINGS_EXPORT AssociatedBindingBase {
34  public:
35   AssociatedBindingBase();
36   ~AssociatedBindingBase();
37 
38   // Adds a message filter to be notified of each incoming message before
39   // dispatch. If a filter returns |false| from Accept(), the message is not
40   // dispatched and the pipe is closed. Filters cannot be removed.
41   void AddFilter(std::unique_ptr<MessageReceiver> filter);
42 
43   // Closes the associated interface. Puts this object into a state where it can
44   // be rebound.
45   void Close();
46 
47   // Similar to the method above, but also specifies a disconnect reason.
48   void CloseWithReason(uint32_t custom_reason, const std::string& description);
49 
50   // Sets an error handler that will be called if a connection error occurs.
51   //
52   // This method may only be called after this AssociatedBinding has been bound
53   // to a message pipe. The error handler will be reset when this
54   // AssociatedBinding is unbound or closed.
55   void set_connection_error_handler(base::OnceClosure error_handler);
56 
57   void set_connection_error_with_reason_handler(
58       ConnectionErrorWithReasonCallback error_handler);
59 
60   // Indicates whether the associated binding has been completed.
is_bound()61   bool is_bound() const { return !!endpoint_client_; }
62 
63   explicit operator bool() const { return !!endpoint_client_; }
64 
65   // Sends a message on the underlying message pipe and runs the current
66   // message loop until its response is received. This can be used in tests to
67   // verify that no message was sent on a message pipe in response to some
68   // stimulus.
69   void FlushForTesting();
70 
71  protected:
72   void BindImpl(ScopedInterfaceEndpointHandle handle,
73                 MessageReceiverWithResponderStatus* receiver,
74                 std::unique_ptr<MessageReceiver> payload_validator,
75                 bool expect_sync_requests,
76                 scoped_refptr<base::SingleThreadTaskRunner> runner,
77                 uint32_t interface_version);
78 
79   std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
80 };
81 
82 // Represents the implementation side of an associated interface. It is similar
83 // to Binding, except that it doesn't own a message pipe handle.
84 //
85 // When you bind this class to a request, optionally you can specify a
86 // base::SingleThreadTaskRunner. This task runner must belong to the same
87 // thread. It will be used to dispatch incoming method calls and connection
88 // error notification. It is useful when you attach multiple task runners to a
89 // single thread for the purposes of task scheduling. Please note that
90 // incoming synchronous method calls may not be run from this task runner, when
91 // they reenter outgoing synchronous calls on the same thread.
92 template <typename Interface,
93           typename ImplRefTraits = RawPtrImplRefTraits<Interface>>
94 class AssociatedBinding : public AssociatedBindingBase {
95  public:
96   using ImplPointerType = typename ImplRefTraits::PointerType;
97 
98   // Constructs an incomplete associated binding that will use the
99   // implementation |impl|. It may be completed with a subsequent call to the
100   // |Bind| method.
AssociatedBinding(ImplPointerType impl)101   explicit AssociatedBinding(ImplPointerType impl) {
102     stub_.set_sink(std::move(impl));
103   }
104 
105   // Constructs a completed associated binding of |impl|. |impl| must outlive
106   // the binding.
107   AssociatedBinding(
108       ImplPointerType impl,
109       AssociatedInterfaceRequest<Interface> request,
110       scoped_refptr<base::SingleThreadTaskRunner> runner = nullptr)
AssociatedBinding(std::move (impl))111       : AssociatedBinding(std::move(impl)) {
112     Bind(std::move(request), std::move(runner));
113   }
114 
~AssociatedBinding()115   ~AssociatedBinding() {}
116 
117   // Sets up this object as the implementation side of an associated interface.
118   void Bind(AssociatedInterfaceRequest<Interface> request,
119             scoped_refptr<base::SingleThreadTaskRunner> runner = nullptr) {
120     BindImpl(request.PassHandle(), &stub_,
121              base::WrapUnique(new typename Interface::RequestValidator_()),
122              Interface::HasSyncMethods_, std::move(runner),
123              Interface::Version_);
124   }
125 
126   // Unbinds and returns the associated interface request so it can be
127   // used in another context, such as on another sequence or with a different
128   // implementation. Puts this object into a state where it can be rebound.
Unbind()129   AssociatedInterfaceRequest<Interface> Unbind() {
130     DCHECK(endpoint_client_);
131     AssociatedInterfaceRequest<Interface> request(
132         endpoint_client_->PassHandle());
133     endpoint_client_.reset();
134     return request;
135   }
136 
137   // Returns the interface implementation that was previously specified.
impl()138   Interface* impl() { return ImplRefTraits::GetRawPointer(&stub_.sink()); }
139 
140   // Allows test code to swap the interface implementation.
SwapImplForTesting(ImplPointerType new_impl)141   ImplPointerType SwapImplForTesting(ImplPointerType new_impl) {
142     Interface* old_impl = impl();
143     stub_.set_sink(std::move(new_impl));
144     return old_impl;
145   }
146 
147  private:
148   typename Interface::template Stub_<ImplRefTraits> stub_;
149 
150   DISALLOW_COPY_AND_ASSIGN(AssociatedBinding);
151 };
152 
153 }  // namespace mojo
154 
155 #endif  // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
156