blob: 9a18b8ed2ed8bef2f6d2644e6a6d68da06520da4 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/renderer/bindings/listener_tracker.h"
#include "base/values.h"
#include "extensions/common/value_counter.h"
namespace extensions {
ListenerTracker::ListenerTracker() = default;
ListenerTracker::~ListenerTracker() = default;
bool ListenerTracker::AddUnfilteredListener(const std::string& context_owner_id,
const std::string& event_name) {
ListenerCountMap& listeners = unfiltered_listeners_[context_owner_id];
return ++listeners[event_name] == 1;
}
bool ListenerTracker::RemoveUnfilteredListener(
const std::string& context_owner_id,
const std::string& event_name) {
ListenerCountMap& listeners = unfiltered_listeners_[context_owner_id];
auto iter = listeners.find(event_name);
DCHECK(iter != listeners.end());
if (--(iter->second) == 0) {
listeners.erase(iter);
return true;
}
return false;
}
std::pair<bool, int> ListenerTracker::AddFilteredListener(
const std::string& context_owner_id,
const std::string& event_name,
std::unique_ptr<base::DictionaryValue> filter,
int routing_id) {
int filter_id = event_filter_.AddEventMatcher(
event_name,
std::make_unique<EventMatcher>(std::move(filter), routing_id));
if (filter_id == -1)
return std::make_pair(false, -1);
FilteredEventListenerKey key(context_owner_id, event_name);
std::unique_ptr<ValueCounter>& counts = filtered_listeners_[key];
if (!counts)
counts = std::make_unique<ValueCounter>();
const EventMatcher* matcher = event_filter_.GetEventMatcher(filter_id);
bool was_first_of_kind = counts->Add(*matcher->value());
return std::make_pair(was_first_of_kind, filter_id);
}
std::pair<bool, std::unique_ptr<base::DictionaryValue>>
ListenerTracker::RemoveFilteredListener(const std::string& context_owner_id,
const std::string& event_name,
int filter_id) {
EventMatcher* matcher = event_filter_.GetEventMatcher(filter_id);
DCHECK(matcher);
std::unique_ptr<base::DictionaryValue> filter_copy =
matcher->value()->CreateDeepCopy();
FilteredEventListenerKey key(context_owner_id, event_name);
FilteredListeners::const_iterator counts = filtered_listeners_.find(key);
bool was_last_of_kind = false;
DCHECK(counts != filtered_listeners_.end());
if (counts->second->Remove(*matcher->value())) {
if (counts->second->is_empty()) {
// Clean up if there are no more filters.
filtered_listeners_.erase(counts);
}
was_last_of_kind = true;
}
event_filter_.RemoveEventMatcher(filter_id);
return std::make_pair(was_last_of_kind, std::move(filter_copy));
}
std::set<int> ListenerTracker::GetMatchingFilteredListeners(
const std::string& event_name,
const EventFilteringInfo& filter,
int routing_id) {
return event_filter_.MatchEvent(event_name, filter, routing_id);
}
} // namespace extensions