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