1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/event_listener_map.h"
7 #include "base/values.h"
9 #include "chrome/browser/extensions/event_router.h"
10 #include "ipc/ipc_message.h"
12 namespace extensions {
14 typedef EventFilter::MatcherID MatcherID;
16 EventListener::EventListener(const std::string& event_name,
17 const std::string& extension_id,
18 content::RenderProcessHost* process,
19 scoped_ptr<DictionaryValue> filter)
20 : event_name(event_name),
21 extension_id(extension_id),
23 filter(filter.Pass()),
26 EventListener::~EventListener() {}
28 bool EventListener::Equals(const EventListener* other) const {
29 // We don't check matcher_id equality because we want a listener with a
30 // filter that hasn't been added to EventFilter to match one that is
31 // equivalent but has.
32 return event_name == other->event_name &&
33 extension_id == other->extension_id &&
34 process == other->process &&
35 ((!!filter.get()) == (!!other->filter.get())) &&
36 (!filter.get() || filter->Equals(other->filter.get()));
39 scoped_ptr<EventListener> EventListener::Copy() const {
40 scoped_ptr<DictionaryValue> filter_copy;
42 filter_copy.reset(filter->DeepCopy());
43 return scoped_ptr<EventListener>(new EventListener(event_name, extension_id,
48 EventListenerMap::EventListenerMap(Delegate* delegate)
49 : delegate_(delegate) {
52 EventListenerMap::~EventListenerMap() {}
54 bool EventListenerMap::AddListener(scoped_ptr<EventListener> listener) {
55 if (HasListener(listener.get()))
57 if (listener->filter) {
58 scoped_ptr<EventMatcher> matcher(ParseEventMatcher(listener->filter.get()));
59 MatcherID id = event_filter_.AddEventMatcher(listener->event_name,
61 listener->matcher_id = id;
62 listeners_by_matcher_id_[id] = listener.get();
63 filtered_events_.insert(listener->event_name);
65 linked_ptr<EventListener> listener_ptr(listener.release());
66 listeners_[listener_ptr->event_name].push_back(listener_ptr);
68 delegate_->OnListenerAdded(listener_ptr.get());
73 scoped_ptr<EventMatcher> EventListenerMap::ParseEventMatcher(
74 DictionaryValue* filter_dict) {
75 return scoped_ptr<EventMatcher>(new EventMatcher(
76 scoped_ptr<DictionaryValue>(filter_dict->DeepCopy()), MSG_ROUTING_NONE));
79 bool EventListenerMap::RemoveListener(const EventListener* listener) {
80 ListenerList& listeners = listeners_[listener->event_name];
81 for (ListenerList::iterator it = listeners.begin(); it != listeners.end();
83 if ((*it)->Equals(listener)) {
84 CleanupListener(it->get());
85 // Popping from the back should be cheaper than erase(it).
86 std::swap(*it, listeners.back());
88 delegate_->OnListenerRemoved(listener);
95 bool EventListenerMap::HasListenerForEvent(const std::string& event_name) {
96 ListenerMap::iterator it = listeners_.find(event_name);
97 return it != listeners_.end() && !it->second.empty();
100 bool EventListenerMap::HasListenerForExtension(
101 const std::string& extension_id,
102 const std::string& event_name) {
103 ListenerMap::iterator it = listeners_.find(event_name);
104 if (it == listeners_.end())
107 for (ListenerList::iterator it2 = it->second.begin();
108 it2 != it->second.end(); it2++) {
109 if ((*it2)->extension_id == extension_id)
115 bool EventListenerMap::HasListener(const EventListener* listener) {
116 ListenerMap::iterator it = listeners_.find(listener->event_name);
117 if (it == listeners_.end())
119 for (ListenerList::iterator it2 = it->second.begin();
120 it2 != it->second.end(); it2++) {
121 if ((*it2)->Equals(listener)) {
128 bool EventListenerMap::HasProcessListener(content::RenderProcessHost* process,
129 const std::string& extension_id) {
130 for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
132 for (ListenerList::iterator it2 = it->second.begin();
133 it2 != it->second.end(); it2++) {
134 if ((*it2)->process == process && (*it2)->extension_id == extension_id)
141 void EventListenerMap::RemoveLazyListenersForExtension(
142 const std::string& extension_id) {
143 for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
145 for (ListenerList::iterator it2 = it->second.begin();
146 it2 != it->second.end();) {
147 if (!(*it2)->process && (*it2)->extension_id == extension_id) {
148 CleanupListener(it2->get());
149 it2 = it->second.erase(it2);
157 void EventListenerMap::LoadUnfilteredLazyListeners(
158 const std::string& extension_id,
159 const std::set<std::string>& event_names) {
160 for (std::set<std::string>::const_iterator it = event_names.begin();
161 it != event_names.end(); ++it) {
162 AddListener(scoped_ptr<EventListener>(new EventListener(
163 *it, extension_id, NULL, scoped_ptr<DictionaryValue>())));
167 void EventListenerMap::LoadFilteredLazyListeners(
168 const std::string& extension_id,
169 const DictionaryValue& filtered) {
170 for (DictionaryValue::Iterator it(filtered); !it.IsAtEnd(); it.Advance()) {
171 // We skip entries if they are malformed.
172 const base::ListValue* filter_list = NULL;
173 if (!it.value().GetAsList(&filter_list))
175 for (size_t i = 0; i < filter_list->GetSize(); i++) {
176 const DictionaryValue* filter = NULL;
177 if (!filter_list->GetDictionary(i, &filter))
179 AddListener(scoped_ptr<EventListener>(new EventListener(
180 it.key(), extension_id, NULL,
181 scoped_ptr<DictionaryValue>(filter->DeepCopy()))));
186 std::set<const EventListener*> EventListenerMap::GetEventListeners(
187 const Event& event) {
188 std::set<const EventListener*> interested_listeners;
189 if (IsFilteredEvent(event)) {
190 // Look up the interested listeners via the EventFilter.
191 std::set<MatcherID> ids =
192 event_filter_.MatchEvent(event.event_name, event.filter_info,
194 for (std::set<MatcherID>::iterator id = ids.begin(); id != ids.end();
196 EventListener* listener = listeners_by_matcher_id_[*id];
198 interested_listeners.insert(listener);
201 ListenerList& listeners = listeners_[event.event_name];
202 for (ListenerList::const_iterator it = listeners.begin();
203 it != listeners.end(); it++) {
204 interested_listeners.insert(it->get());
208 return interested_listeners;
211 void EventListenerMap::RemoveListenersForProcess(
212 const content::RenderProcessHost* process) {
214 for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
216 for (ListenerList::iterator it2 = it->second.begin();
217 it2 != it->second.end();) {
218 if ((*it2)->process == process) {
219 linked_ptr<EventListener> listener(*it2);
220 CleanupListener(it2->get());
221 it2 = it->second.erase(it2);
222 delegate_->OnListenerRemoved(listener.get());
230 void EventListenerMap::CleanupListener(EventListener* listener) {
231 // If the listener doesn't have a filter then we have nothing to clean up.
232 if (listener->matcher_id == -1)
234 event_filter_.RemoveEventMatcher(listener->matcher_id);
235 CHECK_EQ(1u, listeners_by_matcher_id_.erase(listener->matcher_id));
238 bool EventListenerMap::IsFilteredEvent(const Event& event) const {
239 return filtered_events_.count(event.event_name) > 0u;
242 } // namespace extensions