- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / event_listener_map.cc
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.
4
5 #include "chrome/browser/extensions/event_listener_map.h"
6
7 #include "base/values.h"
8
9 #include "chrome/browser/extensions/event_router.h"
10 #include "ipc/ipc_message.h"
11
12 namespace extensions {
13
14 typedef EventFilter::MatcherID MatcherID;
15
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),
22       process(process),
23       filter(filter.Pass()),
24       matcher_id(-1) {}
25
26 EventListener::~EventListener() {}
27
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()));
37 }
38
39 scoped_ptr<EventListener> EventListener::Copy() const {
40   scoped_ptr<DictionaryValue> filter_copy;
41   if (filter)
42     filter_copy.reset(filter->DeepCopy());
43   return scoped_ptr<EventListener>(new EventListener(event_name, extension_id,
44                                                      process,
45                                                      filter_copy.Pass()));
46 }
47
48 EventListenerMap::EventListenerMap(Delegate* delegate)
49     : delegate_(delegate) {
50 }
51
52 EventListenerMap::~EventListenerMap() {}
53
54 bool EventListenerMap::AddListener(scoped_ptr<EventListener> listener) {
55   if (HasListener(listener.get()))
56     return false;
57   if (listener->filter) {
58     scoped_ptr<EventMatcher> matcher(ParseEventMatcher(listener->filter.get()));
59     MatcherID id = event_filter_.AddEventMatcher(listener->event_name,
60                                                  matcher.Pass());
61     listener->matcher_id = id;
62     listeners_by_matcher_id_[id] = listener.get();
63     filtered_events_.insert(listener->event_name);
64   }
65   linked_ptr<EventListener> listener_ptr(listener.release());
66   listeners_[listener_ptr->event_name].push_back(listener_ptr);
67
68   delegate_->OnListenerAdded(listener_ptr.get());
69
70   return true;
71 }
72
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));
77 }
78
79 bool EventListenerMap::RemoveListener(const EventListener* listener) {
80   ListenerList& listeners = listeners_[listener->event_name];
81   for (ListenerList::iterator it = listeners.begin(); it != listeners.end();
82        it++) {
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());
87       listeners.pop_back();
88       delegate_->OnListenerRemoved(listener);
89       return true;
90     }
91   }
92   return false;
93 }
94
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();
98 }
99
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())
105     return false;
106
107   for (ListenerList::iterator it2 = it->second.begin();
108        it2 != it->second.end(); it2++) {
109     if ((*it2)->extension_id == extension_id)
110       return true;
111   }
112   return false;
113 }
114
115 bool EventListenerMap::HasListener(const EventListener* listener) {
116   ListenerMap::iterator it = listeners_.find(listener->event_name);
117   if (it == listeners_.end())
118     return false;
119   for (ListenerList::iterator it2 = it->second.begin();
120        it2 != it->second.end(); it2++) {
121     if ((*it2)->Equals(listener)) {
122       return true;
123     }
124   }
125   return false;
126 }
127
128 bool EventListenerMap::HasProcessListener(content::RenderProcessHost* process,
129                                           const std::string& extension_id) {
130   for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
131        it++) {
132     for (ListenerList::iterator it2 = it->second.begin();
133          it2 != it->second.end(); it2++) {
134       if ((*it2)->process == process && (*it2)->extension_id == extension_id)
135         return true;
136     }
137   }
138   return false;
139 }
140
141 void EventListenerMap::RemoveLazyListenersForExtension(
142     const std::string& extension_id) {
143   for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
144        it++) {
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);
150       } else {
151         it2++;
152       }
153     }
154   }
155 }
156
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>())));
164   }
165 }
166
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))
174       continue;
175     for (size_t i = 0; i < filter_list->GetSize(); i++) {
176       const DictionaryValue* filter = NULL;
177       if (!filter_list->GetDictionary(i, &filter))
178         continue;
179       AddListener(scoped_ptr<EventListener>(new EventListener(
180           it.key(), extension_id, NULL,
181           scoped_ptr<DictionaryValue>(filter->DeepCopy()))));
182     }
183   }
184 }
185
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,
193             MSG_ROUTING_NONE);
194     for (std::set<MatcherID>::iterator id = ids.begin(); id != ids.end();
195          id++) {
196       EventListener* listener = listeners_by_matcher_id_[*id];
197       CHECK(listener);
198       interested_listeners.insert(listener);
199     }
200   } else {
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());
205     }
206   }
207
208   return interested_listeners;
209 }
210
211 void EventListenerMap::RemoveListenersForProcess(
212     const content::RenderProcessHost* process) {
213   CHECK(process);
214   for (ListenerMap::iterator it = listeners_.begin(); it != listeners_.end();
215        it++) {
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());
223       } else {
224         it2++;
225       }
226     }
227   }
228 }
229
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)
233     return;
234   event_filter_.RemoveEventMatcher(listener->matcher_id);
235   CHECK_EQ(1u, listeners_by_matcher_id_.erase(listener->matcher_id));
236 }
237
238 bool EventListenerMap::IsFilteredEvent(const Event& event) const {
239   return filtered_events_.count(event.event_name) > 0u;
240 }
241
242 }  // namespace extensions