| OLD | NEW | 
|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ | 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ | 
| 6 #define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ | 6 #define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ | 
| 7 | 7 | 
| 8 #include <utility> | 8 #include <utility> | 
| 9 | 9 | 
| 10 #include "base/bind.h" | 10 #include "base/bind.h" | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 28   static RequestType GetProxy(ProxyType* proxy) { | 28   static RequestType GetProxy(ProxyType* proxy) { | 
| 29     return mojo::GetProxy(proxy); | 29     return mojo::GetProxy(proxy); | 
| 30   } | 30   } | 
| 31 }; | 31 }; | 
| 32 | 32 | 
| 33 enum class BindingSetDispatchMode { | 33 enum class BindingSetDispatchMode { | 
| 34   WITHOUT_CONTEXT, | 34   WITHOUT_CONTEXT, | 
| 35   WITH_CONTEXT, | 35   WITH_CONTEXT, | 
| 36 }; | 36 }; | 
| 37 | 37 | 
|  | 38 using BindingId = size_t; | 
|  | 39 | 
| 38 // Use this class to manage a set of bindings, which are automatically destroyed | 40 // Use this class to manage a set of bindings, which are automatically destroyed | 
| 39 // and removed from the set when the pipe they are bound to is disconnected. | 41 // and removed from the set when the pipe they are bound to is disconnected. | 
| 40 template <typename Interface, typename BindingType = Binding<Interface>> | 42 template <typename Interface, typename BindingType = Binding<Interface>> | 
| 41 class BindingSet { | 43 class BindingSet { | 
| 42  public: | 44  public: | 
|  | 45   using PreDispatchCallback = base::Callback<void(void*)>; | 
| 43   using Traits = BindingSetTraits<BindingType>; | 46   using Traits = BindingSetTraits<BindingType>; | 
| 44   using ProxyType = typename Traits::ProxyType; | 47   using ProxyType = typename Traits::ProxyType; | 
| 45   using RequestType = typename Traits::RequestType; | 48   using RequestType = typename Traits::RequestType; | 
| 46 | 49 | 
| 47   BindingSet() : BindingSet(BindingSetDispatchMode::WITHOUT_CONTEXT) {} | 50   BindingSet() : BindingSet(BindingSetDispatchMode::WITHOUT_CONTEXT) {} | 
| 48 | 51 | 
| 49   // Constructs a new BindingSet operating in |dispatch_mode|. If |WITH_CONTEXT| | 52   // Constructs a new BindingSet operating in |dispatch_mode|. If |WITH_CONTEXT| | 
| 50   // is used, AddBinding() supports a |context| argument, and dispatch_context() | 53   // is used, AddBinding() supports a |context| argument, and dispatch_context() | 
| 51   // may be called during message or error dispatch to identify which specific | 54   // may be called during message or error dispatch to identify which specific | 
| 52   // binding received the message or error. | 55   // binding received the message or error. | 
| 53   explicit BindingSet(BindingSetDispatchMode dispatch_mode) | 56   explicit BindingSet(BindingSetDispatchMode dispatch_mode) | 
| 54       : dispatch_mode_(dispatch_mode) {} | 57       : dispatch_mode_(dispatch_mode) {} | 
| 55 | 58 | 
| 56   void set_connection_error_handler(const base::Closure& error_handler) { | 59   void set_connection_error_handler(const base::Closure& error_handler) { | 
| 57     error_handler_ = error_handler; | 60     error_handler_ = error_handler; | 
| 58   } | 61   } | 
| 59 | 62 | 
|  | 63   // Sets a callback to be invoked immediately before dispatching any message or | 
|  | 64   // error received by any of the bindings in the set. This may only be used | 
|  | 65   // if the set was constructed with |BindingSetDispatchMode::WITH_CONTEXT|. | 
|  | 66   // |handler| is passed the context associated with the binding which received | 
|  | 67   // the message or event about to be dispatched. | 
|  | 68   void set_pre_dispatch_handler(const PreDispatchCallback& handler) { | 
|  | 69     DCHECK(SupportsContext()); | 
|  | 70     pre_dispatch_handler_ = handler; | 
|  | 71   } | 
|  | 72 | 
| 60   // Adds a new binding to the set which binds |request| to |impl|. If |context| | 73   // Adds a new binding to the set which binds |request| to |impl|. If |context| | 
| 61   // is non-null, dispatch_context() will reflect this value during the extent | 74   // is non-null, dispatch_context() will reflect this value during the extent | 
| 62   // of any message or error dispatch targeting this specific binding. Note that | 75   // of any message or error dispatch targeting this specific binding. Note that | 
| 63   // |context| may only be non-null if the BindingSet was constructed with | 76   // |context| may only be non-null if the BindingSet was constructed with | 
| 64   // |BindingSetDispatchMode::WITH_CONTEXT|. | 77   // |BindingSetDispatchMode::WITH_CONTEXT|. | 
| 65   void AddBinding(Interface* impl, | 78   BindingId AddBinding(Interface* impl, | 
| 66                   RequestType request, | 79                      RequestType request, | 
| 67                   void* context = nullptr) { | 80                      void* context = nullptr) { | 
| 68     DCHECK(!context || SupportsContext()); | 81     DCHECK(!context || SupportsContext()); | 
|  | 82     BindingId id = next_binding_id_++; | 
|  | 83     DCHECK_GE(next_binding_id_, 0u); | 
| 69     std::unique_ptr<Entry> entry = | 84     std::unique_ptr<Entry> entry = | 
| 70         base::MakeUnique<Entry>(impl, std::move(request), this, context); | 85         base::MakeUnique<Entry>(impl, std::move(request), this, id, context); | 
| 71     bindings_.insert(std::make_pair(entry.get(), std::move(entry))); | 86     bindings_.insert(std::make_pair(id, std::move(entry))); | 
|  | 87     return id; | 
|  | 88   } | 
|  | 89 | 
|  | 90   // Removes a binding from the set. Note that this is safe to call even if the | 
|  | 91   // binding corresponding to |id| has already been removed. | 
|  | 92   // | 
|  | 93   // Returns |true| if the binding was removed and |false| if it didn't exist. | 
|  | 94   bool RemoveBinding(BindingId id) { | 
|  | 95     auto it = bindings_.find(id); | 
|  | 96     if (it == bindings_.end()) | 
|  | 97       return false; | 
|  | 98     bindings_.erase(it); | 
|  | 99     return true; | 
| 72   } | 100   } | 
| 73 | 101 | 
| 74   // Returns a proxy bound to one end of a pipe whose other end is bound to | 102   // Returns a proxy bound to one end of a pipe whose other end is bound to | 
| 75   // |this|. | 103   // |this|. If |id_storage| is not null, |*id_storage| will be set to the ID | 
| 76   ProxyType CreateInterfacePtrAndBind(Interface* impl) { | 104   // of the added binding. | 
|  | 105   ProxyType CreateInterfacePtrAndBind(Interface* impl, | 
|  | 106                                       BindingId* id_storage = nullptr) { | 
| 77     ProxyType proxy; | 107     ProxyType proxy; | 
| 78     AddBinding(impl, Traits::GetProxy(&proxy)); | 108     BindingId id = AddBinding(impl, Traits::GetProxy(&proxy)); | 
|  | 109     if (id_storage) | 
|  | 110       *id_storage = id; | 
| 79     return proxy; | 111     return proxy; | 
| 80   } | 112   } | 
| 81 | 113 | 
| 82   void CloseAllBindings() { bindings_.clear(); } | 114   void CloseAllBindings() { bindings_.clear(); } | 
| 83 | 115 | 
| 84   bool empty() const { return bindings_.empty(); } | 116   bool empty() const { return bindings_.empty(); } | 
| 85 | 117 | 
| 86   // Implementations may call this when processing a dispatched message or | 118   // Implementations may call this when processing a dispatched message or | 
| 87   // error. During the extent of message or error dispatch, this will return the | 119   // error. During the extent of message or error dispatch, this will return the | 
| 88   // context associated with the specific binding which received the message or | 120   // context associated with the specific binding which received the message or | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 102   } | 134   } | 
| 103 | 135 | 
| 104  private: | 136  private: | 
| 105   friend class Entry; | 137   friend class Entry; | 
| 106 | 138 | 
| 107   class Entry { | 139   class Entry { | 
| 108    public: | 140    public: | 
| 109     Entry(Interface* impl, | 141     Entry(Interface* impl, | 
| 110           RequestType request, | 142           RequestType request, | 
| 111           BindingSet* binding_set, | 143           BindingSet* binding_set, | 
|  | 144           BindingId binding_id, | 
| 112           void* context) | 145           void* context) | 
| 113         : binding_(impl, std::move(request)), | 146         : binding_(impl, std::move(request)), | 
| 114           binding_set_(binding_set), | 147           binding_set_(binding_set), | 
|  | 148           binding_id_(binding_id), | 
| 115           context_(context) { | 149           context_(context) { | 
| 116       if (binding_set->SupportsContext()) | 150       if (binding_set->SupportsContext()) | 
| 117         binding_.AddFilter(base::MakeUnique<DispatchFilter>(this)); | 151         binding_.AddFilter(base::MakeUnique<DispatchFilter>(this)); | 
| 118       binding_.set_connection_error_handler(base::Bind( | 152       binding_.set_connection_error_handler(base::Bind( | 
| 119           &Entry::OnConnectionError, base::Unretained(this))); | 153           &Entry::OnConnectionError, base::Unretained(this))); | 
| 120     } | 154     } | 
| 121 | 155 | 
| 122     void FlushForTesting() { binding_.FlushForTesting(); } | 156     void FlushForTesting() { binding_.FlushForTesting(); } | 
| 123 | 157 | 
| 124    private: | 158    private: | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 140     }; | 174     }; | 
| 141 | 175 | 
| 142     void WillDispatch() { | 176     void WillDispatch() { | 
| 143       DCHECK(binding_set_->SupportsContext()); | 177       DCHECK(binding_set_->SupportsContext()); | 
| 144       binding_set_->SetDispatchContext(context_); | 178       binding_set_->SetDispatchContext(context_); | 
| 145     } | 179     } | 
| 146 | 180 | 
| 147     void OnConnectionError() { | 181     void OnConnectionError() { | 
| 148       if (binding_set_->SupportsContext()) | 182       if (binding_set_->SupportsContext()) | 
| 149         WillDispatch(); | 183         WillDispatch(); | 
| 150       binding_set_->OnConnectionError(this); | 184       binding_set_->OnConnectionError(binding_id_); | 
| 151     } | 185     } | 
| 152 | 186 | 
| 153     BindingType binding_; | 187     BindingType binding_; | 
| 154     BindingSet* const binding_set_; | 188     BindingSet* const binding_set_; | 
|  | 189     const BindingId binding_id_; | 
| 155     void* const context_; | 190     void* const context_; | 
| 156 | 191 | 
| 157     DISALLOW_COPY_AND_ASSIGN(Entry); | 192     DISALLOW_COPY_AND_ASSIGN(Entry); | 
| 158   }; | 193   }; | 
| 159 | 194 | 
| 160   void SetDispatchContext(void* context) { | 195   void SetDispatchContext(void* context) { | 
| 161     DCHECK(SupportsContext()); | 196     DCHECK(SupportsContext()); | 
| 162     dispatch_context_ = context; | 197     dispatch_context_ = context; | 
|  | 198     if (!pre_dispatch_handler_.is_null()) | 
|  | 199       pre_dispatch_handler_.Run(context); | 
| 163   } | 200   } | 
| 164 | 201 | 
| 165   bool SupportsContext() const { | 202   bool SupportsContext() const { | 
| 166     return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT; | 203     return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT; | 
| 167   } | 204   } | 
| 168 | 205 | 
| 169   void OnConnectionError(Entry* entry) { | 206   void OnConnectionError(BindingId id) { | 
| 170     auto it = bindings_.find(entry); | 207     auto it = bindings_.find(id); | 
| 171     DCHECK(it != bindings_.end()); | 208     DCHECK(it != bindings_.end()); | 
| 172     bindings_.erase(it); | 209     bindings_.erase(it); | 
| 173 | 210 | 
| 174     if (!error_handler_.is_null()) | 211     if (!error_handler_.is_null()) | 
| 175       error_handler_.Run(); | 212       error_handler_.Run(); | 
| 176   } | 213   } | 
| 177 | 214 | 
| 178   BindingSetDispatchMode dispatch_mode_; | 215   BindingSetDispatchMode dispatch_mode_; | 
| 179   base::Closure error_handler_; | 216   base::Closure error_handler_; | 
| 180   std::map<Entry*, std::unique_ptr<Entry>> bindings_; | 217   PreDispatchCallback pre_dispatch_handler_; | 
|  | 218   BindingId next_binding_id_ = 0; | 
|  | 219   std::map<BindingId, std::unique_ptr<Entry>> bindings_; | 
| 181   void* dispatch_context_ = nullptr; | 220   void* dispatch_context_ = nullptr; | 
| 182 | 221 | 
| 183   DISALLOW_COPY_AND_ASSIGN(BindingSet); | 222   DISALLOW_COPY_AND_ASSIGN(BindingSet); | 
| 184 }; | 223 }; | 
| 185 | 224 | 
| 186 }  // namespace mojo | 225 }  // namespace mojo | 
| 187 | 226 | 
| 188 #endif  // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ | 227 #endif  // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ | 
| OLD | NEW | 
|---|