Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6278)

Unified Diff: chrome/browser/extensions/event_listener_map.cc

Issue 10514013: Filtered events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: split out event_filter changes Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/event_listener_map.cc
diff --git a/chrome/browser/extensions/event_listener_map.cc b/chrome/browser/extensions/event_listener_map.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f78ecc315a7721a789c8fc33968b8cd6f0abe991
--- /dev/null
+++ b/chrome/browser/extensions/event_listener_map.cc
@@ -0,0 +1,208 @@
+// Copyright (c) 2012 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 "chrome/browser/extensions/event_listener_map.h"
+
+#include "base/values.h"
+
+#include "chrome/browser/extensions/extension_event_router.h"
+
+EventListener::EventListener(const std::string& event_name,
+ const std::string& extension_id,
+ content::RenderProcessHost* process,
+ scoped_ptr<DictionaryValue> filter)
+ : event_name(event_name),
+ extension_id(extension_id),
+ process(process),
+ filter(filter.Pass()),
+ matcher_id(-1) {}
+
+EventListener::~EventListener() {}
+
+bool EventListener::Equals(const EventListener* other) {
+ // We don't check matcher_id equality because we want a listener with a
+ // filter that hasn't been added to EventFilter to match one that is
+ // equivalent but has.
+ return event_name == other->event_name &&
+ extension_id == other->extension_id &&
+ process == other->process &&
+ ((!!filter.get()) == (!!other->filter.get())) &&
+ (!filter.get() || filter->Equals(other->filter.get()));
+}
+
+scoped_ptr<EventListener> EventListener::Copy() const {
+ scoped_ptr<DictionaryValue> filter_copy;
+ if (filter.get())
+ filter_copy.reset(filter->DeepCopy());
+ return scoped_ptr<EventListener>(new EventListener(event_name, extension_id,
+ process,
+ filter_copy.Pass()));
+}
+
+EventListenerMap::EventListenerMap() {
+}
+
+EventListenerMap::~EventListenerMap() {}
+
+bool EventListenerMap::AddListener(scoped_ptr<EventListener> listener) {
+ if (HasListener(listener.get()))
+ return false;
+ if (listener->filter.get()) {
+ scoped_ptr<EventMatcher> matcher(ParseEventMatcer(listener->filter.get()));
+ int id = event_filter_.AddEventMatcher(listener->event_name,
+ matcher.Pass());
+ listener->matcher_id = id;
+ listeners_by_matcher_id_.insert(std::make_pair(id, listener.get()));
Matt Perry 2012/06/13 01:24:27 listeners_by_matcher_id_[id] = listener.get()
koz (OOO until 15th September) 2012/06/14 02:15:55 Done.
+ filtered_events_.insert(listener->event_name);
+ }
+ linked_ptr<EventListener> listener_ptr(listener.release());
+ listeners_[listener_ptr->event_name].push_back(listener_ptr);
+
+ return true;
+}
+
+scoped_ptr<EventMatcher> EventListenerMap::ParseEventMatcer(
Matt Perry 2012/06/13 01:24:27 typo - Matcer
koz (OOO until 15th September) 2012/06/14 02:15:55 Done.
+ DictionaryValue* filter_dict) {
+ return scoped_ptr<EventMatcher>(new EventMatcher(
+ scoped_ptr<DictionaryValue>(filter_dict->DeepCopy())));
+}
+
+bool EventListenerMap::RemoveListener(scoped_ptr<EventListener> listener) {
+ ListenerList& listeners = listeners_[listener->event_name];
+ for (ListenerList::iterator it = listeners.begin(); it != listeners.end();) {
+ if ((*it)->Equals(listener.get())) {
+ CleanupListener(it->get());
+ it = listeners.erase(it);
+ return true;
+ } else {
+ it++;
+ }
+ }
+ return false;
+}
+
+bool EventListenerMap::AnyListenersForEvent(const std::string& event_name) {
+ ListenerMap::iterator it = listeners_.find(event_name);
+ return it != listeners_.end() && !it->second.empty();
+}
+
+bool EventListenerMap::AnyListenersForExtension(
+ const std::string& extension_id, const std::string& event_name) {
+ ListenerMap::iterator it = listeners_.find(event_name);
+ if (it == listeners_.end())
+ return false;
+
+ for (ListenerList::iterator it2 = it->second.begin();
+ it2 != it->second.end(); it2++) {
+ if ((*it2)->extension_id == extension_id)
+ return true;
+ }
+ return false;
+}
+
+bool EventListenerMap::HasListener(const EventListener* listener) {
+ ListenerMap::iterator it = listeners_.find(listener->event_name);
+ if (it == listeners_.end())
+ return false;
+ for (ListenerList::iterator it2 = it->second.begin();
+ it2 != it->second.end(); it2++) {
+ if ((*it2)->Equals(listener)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void EventListenerMap::RemoveLazyListenersFor(const std::string extension_id) {
+ for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
+ it++) {
+ for (ListenerList::iterator it2 = it->second.begin();
+ it2 != it->second.end();) {
+ if (!(*it2)->process && (*it2)->extension_id == extension_id) {
+ CleanupListener(it2->get());
+ it2 = it->second.erase(it2);
+ } else {
+ it2++;
+ }
+ }
+ }
+}
+
+void EventListenerMap::AddLazyListenersFromPreferences(
+ const std::string& extension_id,
+ std::set<std::string>& unfiltered,
+ const DictionaryValue& filtered) {
+ for (std::set<std::string>::iterator it = unfiltered.begin();
+ it != unfiltered.end(); ++it) {
+ scoped_ptr<EventListener> listener(new EventListener(
+ *it, extension_id, NULL,
+ scoped_ptr<DictionaryValue>()));
+ AddListener(listener.Pass());
+ }
+
+ for (DictionaryValue::key_iterator it = filtered.begin_keys();
+ it != filtered.end_keys(); ++it) {
+ DictionaryValue* filter;
+ CHECK(filtered.GetDictionary(*it, &filter));
Matt Perry 2012/06/13 01:24:27 Prefs can get corrupted, so don't rely on them bei
koz (OOO until 15th September) 2012/06/14 02:15:55 Done.
+ scoped_ptr<EventListener> listener(new EventListener(
+ *it, extension_id, NULL,
+ scoped_ptr<DictionaryValue>(filter->DeepCopy())));
+ AddListener(listener.Pass());
+ }
+}
+
+scoped_ptr<std::set<const EventListener*> > EventListenerMap::GetEventTargets(
+ const ExtensionEvent& event) {
+ scoped_ptr<std::set<const EventListener*> > interested_listeners(
+ new std::set<const EventListener*>);
+ if (IsFilteredEvent(event)) {
+ // Look up the interested listeners via the EventFilter.
+ std::set<int> ids = event_filter_.MatchEvent(event.event_name, event.info);
+ for (std::set<int>::iterator id = ids.begin(); id != ids.end(); id++) {
+ EventListener* listener = listeners_by_matcher_id_[*id];
+ CHECK(listener);
+ interested_listeners->insert(listener);
+ }
+ } else {
+ ListenerList& listeners = listeners_[event.event_name];
+ for (ListenerList::const_iterator it = listeners.begin();
+ it != listeners.end(); it++) {
+ interested_listeners->insert(it->get());
+ }
+ }
+
+ return interested_listeners.Pass();
+}
+
+EventListenerMap::ListenerList EventListenerMap::RemoveListenersForProcess(
+ const content::RenderProcessHost* process) {
+ CHECK(process);
+ ListenerList result;
+ for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
+ it++) {
+ for (ListenerList::iterator it2 = it->second.begin();
+ it2 != it->second.end();) {
+ if ((*it2)->process == process) {
+ result.push_back(*it2);
+ CleanupListener(it2->get());
+ it2 = it->second.erase(it2);
+ } else {
+ it2++;
+ }
+ }
+ }
+ return result;
+}
+
+void EventListenerMap::CleanupListener(EventListener* listener) {
+ // If the listener doesn't have a filter then we have nothing to clean up.
+ if (listener->matcher_id == -1)
+ return;
+ event_filter_.RemoveEventMatcher(listener->matcher_id);
+ CHECK_EQ(1u, listeners_by_matcher_id_.erase(listener->matcher_id));
+}
+
+bool EventListenerMap::IsFilteredEvent(const ExtensionEvent& event) const {
+ return filtered_events_.count(event.event_name) > 0u;
+}

Powered by Google App Engine
This is Rietveld 408576698