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 <utility> 13 14 #include "base/bind.h" 15 #include "base/callback_forward.h" 16 #include "base/macros.h" 17 #include "base/memory/ptr_util.h" 18 #include "base/memory/ref_counted.h" 19 #include "base/single_thread_task_runner.h" 20 #include "mojo/public/cpp/bindings/associated_group.h" 21 #include "mojo/public/cpp/bindings/associated_group_controller.h" 22 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" 23 #include "mojo/public/cpp/bindings/interface_endpoint_client.h" 24 #include "mojo/public/cpp/bindings/interface_id.h" 25 #include "mojo/public/cpp/bindings/lib/control_message_proxy.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 interface_id()49 uint32_t interface_id() const { 50 DCHECK(is_bound()); 51 return endpoint_client_->interface_id(); 52 } 53 QueryVersion(const base::Callback<void (uint32_t)> & callback)54 void QueryVersion(const base::Callback<void(uint32_t)>& callback) { 55 // Do a static cast in case the interface contains methods with the same 56 // name. It is safe to capture |this| because the callback won't be run 57 // after this object goes away. 58 static_cast<ControlMessageProxy*>(proxy_.get()) 59 ->QueryVersion(base::Bind(&AssociatedInterfacePtrState::OnQueryVersion, 60 base::Unretained(this), callback)); 61 } 62 RequireVersion(uint32_t version)63 void RequireVersion(uint32_t version) { 64 if (version <= version_) 65 return; 66 67 version_ = version; 68 // Do a static cast in case the interface contains methods with the same 69 // name. 70 static_cast<ControlMessageProxy*>(proxy_.get())->RequireVersion(version); 71 } 72 Swap(AssociatedInterfacePtrState * other)73 void Swap(AssociatedInterfacePtrState* other) { 74 using std::swap; 75 swap(other->endpoint_client_, endpoint_client_); 76 swap(other->proxy_, proxy_); 77 swap(other->version_, version_); 78 } 79 Bind(AssociatedInterfacePtrInfo<Interface> info,scoped_refptr<base::SingleThreadTaskRunner> runner)80 void Bind(AssociatedInterfacePtrInfo<Interface> info, 81 scoped_refptr<base::SingleThreadTaskRunner> runner) { 82 DCHECK(!endpoint_client_); 83 DCHECK(!proxy_); 84 DCHECK_EQ(0u, version_); 85 DCHECK(info.is_valid()); 86 87 version_ = info.version(); 88 endpoint_client_.reset(new InterfaceEndpointClient( 89 info.PassHandle(), nullptr, 90 base::WrapUnique(new typename Interface::ResponseValidator_()), false, 91 std::move(runner))); 92 proxy_.reset(new Proxy(endpoint_client_.get())); 93 proxy_->serialization_context()->group_controller = 94 endpoint_client_->group_controller(); 95 } 96 97 // After this method is called, the object is in an invalid state and 98 // shouldn't be reused. PassInterface()99 AssociatedInterfacePtrInfo<Interface> PassInterface() { 100 ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle(); 101 endpoint_client_.reset(); 102 proxy_.reset(); 103 return AssociatedInterfacePtrInfo<Interface>(std::move(handle), version_); 104 } 105 is_bound()106 bool is_bound() const { return !!endpoint_client_; } 107 encountered_error()108 bool encountered_error() const { 109 return endpoint_client_ ? endpoint_client_->encountered_error() : false; 110 } 111 set_connection_error_handler(const base::Closure & error_handler)112 void set_connection_error_handler(const base::Closure& error_handler) { 113 DCHECK(endpoint_client_); 114 endpoint_client_->set_connection_error_handler(error_handler); 115 } 116 117 // Returns true if bound and awaiting a response to a message. has_pending_callbacks()118 bool has_pending_callbacks() const { 119 return endpoint_client_ && endpoint_client_->has_pending_responders(); 120 } 121 associated_group()122 AssociatedGroup* associated_group() { 123 return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; 124 } 125 126 private: 127 using Proxy = typename Interface::Proxy_; 128 OnQueryVersion(const base::Callback<void (uint32_t)> & callback,uint32_t version)129 void OnQueryVersion(const base::Callback<void(uint32_t)>& callback, 130 uint32_t version) { 131 version_ = version; 132 callback.Run(version); 133 } 134 135 std::unique_ptr<InterfaceEndpointClient> endpoint_client_; 136 std::unique_ptr<Proxy> proxy_; 137 138 uint32_t version_; 139 140 DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrState); 141 }; 142 143 } // namespace internal 144 } // namespace mojo 145 146 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ 147