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