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