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_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ 7 8 #include <stdint.h> 9 10 #include <algorithm> // For |std::swap()|. 11 #include <memory> 12 #include <string> 13 #include <utility> 14 15 #include "base/bind.h" 16 #include "base/callback_forward.h" 17 #include "base/macros.h" 18 #include "base/memory/ptr_util.h" 19 #include "base/memory/ref_counted.h" 20 #include "base/single_thread_task_runner.h" 21 #include "mojo/public/cpp/bindings/associated_group.h" 22 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.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/interface_id.h" 26 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" 27 #include "mojo/public/cpp/system/message_pipe.h" 28 29 namespace mojo { 30 namespace internal { 31 32 template <typename Interface> 33 class AssociatedInterfacePtrState { 34 public: AssociatedInterfacePtrState()35 AssociatedInterfacePtrState() : version_(0u) {} 36 ~AssociatedInterfacePtrState()37 ~AssociatedInterfacePtrState() { 38 endpoint_client_.reset(); 39 proxy_.reset(); 40 } 41 instance()42 Interface* instance() { 43 // This will be null if the object is not bound. 44 return proxy_.get(); 45 } 46 version()47 uint32_t version() const { return version_; } 48 QueryVersion(const base::Callback<void (uint32_t)> & callback)49 void QueryVersion(const base::Callback<void(uint32_t)>& callback) { 50 // It is safe to capture |this| because the callback won't be run after this 51 // object goes away. 52 endpoint_client_->QueryVersion( 53 base::Bind(&AssociatedInterfacePtrState::OnQueryVersion, 54 base::Unretained(this), callback)); 55 } 56 RequireVersion(uint32_t version)57 void RequireVersion(uint32_t version) { 58 if (version <= version_) 59 return; 60 61 version_ = version; 62 endpoint_client_->RequireVersion(version); 63 } 64 FlushForTesting()65 void FlushForTesting() { endpoint_client_->FlushForTesting(); } 66 CloseWithReason(uint32_t custom_reason,const std::string & description)67 void CloseWithReason(uint32_t custom_reason, const std::string& description) { 68 endpoint_client_->CloseWithReason(custom_reason, description); 69 } 70 Swap(AssociatedInterfacePtrState * other)71 void Swap(AssociatedInterfacePtrState* other) { 72 using std::swap; 73 swap(other->endpoint_client_, endpoint_client_); 74 swap(other->proxy_, proxy_); 75 swap(other->version_, version_); 76 } 77 Bind(AssociatedInterfacePtrInfo<Interface> info,scoped_refptr<base::SingleThreadTaskRunner> runner)78 void Bind(AssociatedInterfacePtrInfo<Interface> info, 79 scoped_refptr<base::SingleThreadTaskRunner> runner) { 80 DCHECK(!endpoint_client_); 81 DCHECK(!proxy_); 82 DCHECK_EQ(0u, version_); 83 DCHECK(info.is_valid()); 84 85 version_ = info.version(); 86 // The version is only queried from the client so the value passed here 87 // will not be used. 88 endpoint_client_.reset(new InterfaceEndpointClient( 89 info.PassHandle(), nullptr, 90 base::WrapUnique(new typename Interface::ResponseValidator_()), false, 91 std::move(runner), 0u)); 92 proxy_.reset(new Proxy(endpoint_client_.get())); 93 } 94 95 // After this method is called, the object is in an invalid state and 96 // shouldn't be reused. PassInterface()97 AssociatedInterfacePtrInfo<Interface> PassInterface() { 98 ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle(); 99 endpoint_client_.reset(); 100 proxy_.reset(); 101 return AssociatedInterfacePtrInfo<Interface>(std::move(handle), version_); 102 } 103 is_bound()104 bool is_bound() const { return !!endpoint_client_; } 105 encountered_error()106 bool encountered_error() const { 107 return endpoint_client_ ? endpoint_client_->encountered_error() : false; 108 } 109 set_connection_error_handler(const base::Closure & error_handler)110 void set_connection_error_handler(const base::Closure& error_handler) { 111 DCHECK(endpoint_client_); 112 endpoint_client_->set_connection_error_handler(error_handler); 113 } 114 set_connection_error_with_reason_handler(const ConnectionErrorWithReasonCallback & error_handler)115 void set_connection_error_with_reason_handler( 116 const ConnectionErrorWithReasonCallback& error_handler) { 117 DCHECK(endpoint_client_); 118 endpoint_client_->set_connection_error_with_reason_handler(error_handler); 119 } 120 121 // Returns true if bound and awaiting a response to a message. has_pending_callbacks()122 bool has_pending_callbacks() const { 123 return endpoint_client_ && endpoint_client_->has_pending_responders(); 124 } 125 associated_group()126 AssociatedGroup* associated_group() { 127 return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; 128 } 129 ForwardMessage(Message message)130 void ForwardMessage(Message message) { endpoint_client_->Accept(&message); } 131 ForwardMessageWithResponder(Message message,std::unique_ptr<MessageReceiver> responder)132 void ForwardMessageWithResponder(Message message, 133 std::unique_ptr<MessageReceiver> responder) { 134 endpoint_client_->AcceptWithResponder(&message, responder.release()); 135 } 136 137 private: 138 using Proxy = typename Interface::Proxy_; 139 OnQueryVersion(const base::Callback<void (uint32_t)> & callback,uint32_t version)140 void OnQueryVersion(const base::Callback<void(uint32_t)>& callback, 141 uint32_t version) { 142 version_ = version; 143 callback.Run(version); 144 } 145 146 std::unique_ptr<InterfaceEndpointClient> endpoint_client_; 147 std::unique_ptr<Proxy> proxy_; 148 149 uint32_t version_; 150 151 DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrState); 152 }; 153 154 } // namespace internal 155 } // namespace mojo 156 157 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ 158