1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2014 The Chromium Authors. All rights reserved.
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file.
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <algorithm>
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <utility>
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <vector>
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/bind.h"
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/callback.h"
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/macros.h"
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/memory/weak_ptr.h"
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/binding.h"
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo {
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use this class to manage a set of bindings, which are automatically destroyed
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// and removed from the set when the pipe they are bound to is disconnected.
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztemplate <typename Interface>
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass BindingSet {
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public:
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  BindingSet() {}
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ~BindingSet() { CloseAllBindings(); }
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void set_connection_error_handler(const base::Closure& error_handler) {
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    error_handler_ = error_handler;
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void AddBinding(Interface* impl, InterfaceRequest<Interface> request) {
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    auto binding = new Element(impl, std::move(request));
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    binding->set_connection_error_handler(
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        base::Bind(&BindingSet::OnConnectionError, base::Unretained(this)));
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    bindings_.push_back(binding->GetWeakPtr());
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Returns an InterfacePtr bound to one end of a pipe whose other end is
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // bound to |this|.
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  InterfacePtr<Interface> CreateInterfacePtrAndBind(Interface* impl) {
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    InterfacePtr<Interface> interface_ptr;
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    AddBinding(impl, GetProxy(&interface_ptr));
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return interface_ptr;
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void CloseAllBindings() {
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for (const auto& it : bindings_) {
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      if (it) {
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        it->Close();
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        delete it.get();
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      }
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    bindings_.clear();
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool empty() const { return bindings_.empty(); }
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private:
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  class Element {
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez   public:
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Element(Interface* impl, InterfaceRequest<Interface> request)
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        : binding_(impl, std::move(request)), weak_ptr_factory_(this) {
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      binding_.set_connection_error_handler(
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          base::Bind(&Element::OnConnectionError, base::Unretained(this)));
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ~Element() {}
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    void set_connection_error_handler(const base::Closure& error_handler) {
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      error_handler_ = error_handler;
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    base::WeakPtr<Element> GetWeakPtr() {
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return weak_ptr_factory_.GetWeakPtr();
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    void Close() { binding_.Close(); }
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    void OnConnectionError() {
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      base::Closure error_handler = error_handler_;
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      delete this;
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      if (!error_handler.is_null())
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        error_handler.Run();
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez   private:
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Binding<Interface> binding_;
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    base::Closure error_handler_;
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    base::WeakPtrFactory<Element> weak_ptr_factory_;
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DISALLOW_COPY_AND_ASSIGN(Element);
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  };
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void OnConnectionError() {
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // Clear any deleted bindings.
97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    bindings_.erase(std::remove_if(bindings_.begin(), bindings_.end(),
98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                   [](const base::WeakPtr<Element>& p) {
99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                     return p.get() == nullptr;
100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                   }),
101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                    bindings_.end());
102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (!error_handler_.is_null())
104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      error_handler_.Run();
105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  base::Closure error_handler_;
108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  std::vector<base::WeakPtr<Element>> bindings_;
109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DISALLOW_COPY_AND_ASSIGN(BindingSet);
111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez};
112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace mojo
114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
116