| Index: mojo/public/cpp/bindings/binding_set.h
|
| diff --git a/mojo/public/cpp/bindings/binding_set.h b/mojo/public/cpp/bindings/binding_set.h
|
| index 69f17cc0f1cf1ecb0ec4e58e38d8952586e52511..ef5834cca054152df19c1bc0b644140ef01795d5 100644
|
| --- a/mojo/public/cpp/bindings/binding_set.h
|
| +++ b/mojo/public/cpp/bindings/binding_set.h
|
| @@ -35,11 +35,14 @@ enum class BindingSetDispatchMode {
|
| WITH_CONTEXT,
|
| };
|
|
|
| +using BindingId = size_t;
|
| +
|
| // Use this class to manage a set of bindings, which are automatically destroyed
|
| // and removed from the set when the pipe they are bound to is disconnected.
|
| template <typename Interface, typename BindingType = Binding<Interface>>
|
| class BindingSet {
|
| public:
|
| + using PreDispatchCallback = base::Callback<void(void*)>;
|
| using Traits = BindingSetTraits<BindingType>;
|
| using ProxyType = typename Traits::ProxyType;
|
| using RequestType = typename Traits::RequestType;
|
| @@ -57,25 +60,54 @@ class BindingSet {
|
| error_handler_ = error_handler;
|
| }
|
|
|
| + // Sets a callback to be invoked immediately before dispatching any message or
|
| + // error received by any of the bindings in the set. This may only be used
|
| + // if the set was constructed with |BindingSetDispatchMode::WITH_CONTEXT|.
|
| + // |handler| is passed the context associated with the binding which received
|
| + // the message or event about to be dispatched.
|
| + void set_pre_dispatch_handler(const PreDispatchCallback& handler) {
|
| + DCHECK(SupportsContext());
|
| + pre_dispatch_handler_ = handler;
|
| + }
|
| +
|
| // Adds a new binding to the set which binds |request| to |impl|. If |context|
|
| // is non-null, dispatch_context() will reflect this value during the extent
|
| // of any message or error dispatch targeting this specific binding. Note that
|
| // |context| may only be non-null if the BindingSet was constructed with
|
| // |BindingSetDispatchMode::WITH_CONTEXT|.
|
| - void AddBinding(Interface* impl,
|
| - RequestType request,
|
| - void* context = nullptr) {
|
| + BindingId AddBinding(Interface* impl,
|
| + RequestType request,
|
| + void* context = nullptr) {
|
| DCHECK(!context || SupportsContext());
|
| + BindingId id = next_binding_id_++;
|
| + DCHECK_GE(next_binding_id_, 0u);
|
| std::unique_ptr<Entry> entry =
|
| - base::MakeUnique<Entry>(impl, std::move(request), this, context);
|
| - bindings_.insert(std::make_pair(entry.get(), std::move(entry)));
|
| + base::MakeUnique<Entry>(impl, std::move(request), this, id, context);
|
| + bindings_.insert(std::make_pair(id, std::move(entry)));
|
| + return id;
|
| + }
|
| +
|
| + // Removes a binding from the set. Note that this is safe to call even if the
|
| + // binding corresponding to |id| has already been removed.
|
| + //
|
| + // Returns |true| if the binding was removed and |false| if it didn't exist.
|
| + bool RemoveBinding(BindingId id) {
|
| + auto it = bindings_.find(id);
|
| + if (it == bindings_.end())
|
| + return false;
|
| + bindings_.erase(it);
|
| + return true;
|
| }
|
|
|
| // Returns a proxy bound to one end of a pipe whose other end is bound to
|
| - // |this|.
|
| - ProxyType CreateInterfacePtrAndBind(Interface* impl) {
|
| + // |this|. If |id_storage| is not null, |*id_storage| will be set to the ID
|
| + // of the added binding.
|
| + ProxyType CreateInterfacePtrAndBind(Interface* impl,
|
| + BindingId* id_storage = nullptr) {
|
| ProxyType proxy;
|
| - AddBinding(impl, Traits::GetProxy(&proxy));
|
| + BindingId id = AddBinding(impl, Traits::GetProxy(&proxy));
|
| + if (id_storage)
|
| + *id_storage = id;
|
| return proxy;
|
| }
|
|
|
| @@ -109,9 +141,11 @@ class BindingSet {
|
| Entry(Interface* impl,
|
| RequestType request,
|
| BindingSet* binding_set,
|
| + BindingId binding_id,
|
| void* context)
|
| : binding_(impl, std::move(request)),
|
| binding_set_(binding_set),
|
| + binding_id_(binding_id),
|
| context_(context) {
|
| if (binding_set->SupportsContext())
|
| binding_.AddFilter(base::MakeUnique<DispatchFilter>(this));
|
| @@ -147,11 +181,12 @@ class BindingSet {
|
| void OnConnectionError() {
|
| if (binding_set_->SupportsContext())
|
| WillDispatch();
|
| - binding_set_->OnConnectionError(this);
|
| + binding_set_->OnConnectionError(binding_id_);
|
| }
|
|
|
| BindingType binding_;
|
| BindingSet* const binding_set_;
|
| + const BindingId binding_id_;
|
| void* const context_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(Entry);
|
| @@ -160,14 +195,16 @@ class BindingSet {
|
| void SetDispatchContext(void* context) {
|
| DCHECK(SupportsContext());
|
| dispatch_context_ = context;
|
| + if (!pre_dispatch_handler_.is_null())
|
| + pre_dispatch_handler_.Run(context);
|
| }
|
|
|
| bool SupportsContext() const {
|
| return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT;
|
| }
|
|
|
| - void OnConnectionError(Entry* entry) {
|
| - auto it = bindings_.find(entry);
|
| + void OnConnectionError(BindingId id) {
|
| + auto it = bindings_.find(id);
|
| DCHECK(it != bindings_.end());
|
| bindings_.erase(it);
|
|
|
| @@ -177,7 +214,9 @@ class BindingSet {
|
|
|
| BindingSetDispatchMode dispatch_mode_;
|
| base::Closure error_handler_;
|
| - std::map<Entry*, std::unique_ptr<Entry>> bindings_;
|
| + PreDispatchCallback pre_dispatch_handler_;
|
| + BindingId next_binding_id_ = 0;
|
| + std::map<BindingId, std::unique_ptr<Entry>> bindings_;
|
| void* dispatch_context_ = nullptr;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(BindingSet);
|
|
|