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