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