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