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_SET_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ 7 8 #include <algorithm> 9 #include <utility> 10 #include <vector> 11 12 #include "base/bind.h" 13 #include "base/callback.h" 14 #include "base/macros.h" 15 #include "base/memory/weak_ptr.h" 16 #include "mojo/public/cpp/bindings/binding.h" 17 18 namespace mojo { 19 20 // Use this class to manage a set of bindings, which are automatically destroyed 21 // and removed from the set when the pipe they are bound to is disconnected. 22 template <typename Interface> 23 class BindingSet { 24 public: BindingSet()25 BindingSet() {} ~BindingSet()26 ~BindingSet() { CloseAllBindings(); } 27 set_connection_error_handler(const base::Closure & error_handler)28 void set_connection_error_handler(const base::Closure& error_handler) { 29 error_handler_ = error_handler; 30 } 31 AddBinding(Interface * impl,InterfaceRequest<Interface> request)32 void AddBinding(Interface* impl, InterfaceRequest<Interface> request) { 33 auto binding = new Element(impl, std::move(request)); 34 binding->set_connection_error_handler( 35 base::Bind(&BindingSet::OnConnectionError, base::Unretained(this))); 36 bindings_.push_back(binding->GetWeakPtr()); 37 } 38 39 // Returns an InterfacePtr bound to one end of a pipe whose other end is 40 // bound to |this|. CreateInterfacePtrAndBind(Interface * impl)41 InterfacePtr<Interface> CreateInterfacePtrAndBind(Interface* impl) { 42 InterfacePtr<Interface> interface_ptr; 43 AddBinding(impl, GetProxy(&interface_ptr)); 44 return interface_ptr; 45 } 46 CloseAllBindings()47 void CloseAllBindings() { 48 for (const auto& it : bindings_) { 49 if (it) { 50 it->Close(); 51 delete it.get(); 52 } 53 } 54 bindings_.clear(); 55 } 56 empty()57 bool empty() const { return bindings_.empty(); } 58 59 private: 60 class Element { 61 public: Element(Interface * impl,InterfaceRequest<Interface> request)62 Element(Interface* impl, InterfaceRequest<Interface> request) 63 : binding_(impl, std::move(request)), weak_ptr_factory_(this) { 64 binding_.set_connection_error_handler( 65 base::Bind(&Element::OnConnectionError, base::Unretained(this))); 66 } 67 ~Element()68 ~Element() {} 69 set_connection_error_handler(const base::Closure & error_handler)70 void set_connection_error_handler(const base::Closure& error_handler) { 71 error_handler_ = error_handler; 72 } 73 GetWeakPtr()74 base::WeakPtr<Element> GetWeakPtr() { 75 return weak_ptr_factory_.GetWeakPtr(); 76 } 77 Close()78 void Close() { binding_.Close(); } 79 OnConnectionError()80 void OnConnectionError() { 81 base::Closure error_handler = error_handler_; 82 delete this; 83 if (!error_handler.is_null()) 84 error_handler.Run(); 85 } 86 87 private: 88 Binding<Interface> binding_; 89 base::Closure error_handler_; 90 base::WeakPtrFactory<Element> weak_ptr_factory_; 91 92 DISALLOW_COPY_AND_ASSIGN(Element); 93 }; 94 OnConnectionError()95 void OnConnectionError() { 96 // Clear any deleted bindings. 97 bindings_.erase(std::remove_if(bindings_.begin(), bindings_.end(), 98 [](const base::WeakPtr<Element>& p) { 99 return p.get() == nullptr; 100 }), 101 bindings_.end()); 102 103 if (!error_handler_.is_null()) 104 error_handler_.Run(); 105 } 106 107 base::Closure error_handler_; 108 std::vector<base::WeakPtr<Element>> bindings_; 109 110 DISALLOW_COPY_AND_ASSIGN(BindingSet); 111 }; 112 113 } // namespace mojo 114 115 #endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ 116