- add sources.
[platform/framework/web/crosswalk.git] / src / extensions / common / event_filter.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 "extensions/common/event_filter.h"
6
7 #include "extensions/common/matcher/url_matcher_factory.h"
8 #include "ipc/ipc_message.h"
9
10 namespace extensions {
11
12 EventFilter::EventMatcherEntry::EventMatcherEntry(
13     scoped_ptr<EventMatcher> event_matcher,
14     URLMatcher* url_matcher,
15     const URLMatcherConditionSet::Vector& condition_sets)
16     : event_matcher_(event_matcher.Pass()),
17       url_matcher_(url_matcher) {
18   for (URLMatcherConditionSet::Vector::const_iterator it =
19        condition_sets.begin(); it != condition_sets.end(); it++)
20     condition_set_ids_.push_back((*it)->id());
21   url_matcher_->AddConditionSets(condition_sets);
22 }
23
24 EventFilter::EventMatcherEntry::~EventMatcherEntry() {
25   url_matcher_->RemoveConditionSets(condition_set_ids_);
26 }
27
28 void EventFilter::EventMatcherEntry::DontRemoveConditionSetsInDestructor() {
29   condition_set_ids_.clear();
30 }
31
32 EventFilter::EventFilter()
33     : next_id_(0),
34       next_condition_set_id_(0) {
35 }
36
37 EventFilter::~EventFilter() {
38   // Normally when an event matcher entry is removed from event_matchers_ it
39   // will remove its condition sets from url_matcher_, but as url_matcher_ is
40   // being destroyed anyway there is no need to do that step here.
41   for (EventMatcherMultiMap::iterator it = event_matchers_.begin();
42        it != event_matchers_.end(); it++) {
43     for (EventMatcherMap::iterator it2 = it->second.begin();
44          it2 != it->second.end(); it2++) {
45       it2->second->DontRemoveConditionSetsInDestructor();
46     }
47   }
48 }
49
50 EventFilter::MatcherID
51 EventFilter::AddEventMatcher(const std::string& event_name,
52                              scoped_ptr<EventMatcher> matcher) {
53   MatcherID id = next_id_++;
54   URLMatcherConditionSet::Vector condition_sets;
55   if (!CreateConditionSets(id, matcher.get(), &condition_sets))
56     return -1;
57
58   for (URLMatcherConditionSet::Vector::iterator it = condition_sets.begin();
59        it != condition_sets.end(); it++) {
60     condition_set_id_to_event_matcher_id_.insert(
61         std::make_pair((*it)->id(), id));
62   }
63   id_to_event_name_[id] = event_name;
64   event_matchers_[event_name][id] = linked_ptr<EventMatcherEntry>(
65       new EventMatcherEntry(matcher.Pass(), &url_matcher_, condition_sets));
66   return id;
67 }
68
69 EventMatcher* EventFilter::GetEventMatcher(MatcherID id) {
70   DCHECK(id_to_event_name_.find(id) != id_to_event_name_.end());
71   const std::string& event_name = id_to_event_name_[id];
72   return event_matchers_[event_name][id]->event_matcher();
73 }
74
75 const std::string& EventFilter::GetEventName(MatcherID id) {
76   DCHECK(id_to_event_name_.find(id) != id_to_event_name_.end());
77   return id_to_event_name_[id];
78 }
79
80 bool EventFilter::CreateConditionSets(
81     MatcherID id,
82     EventMatcher* matcher,
83     URLMatcherConditionSet::Vector* condition_sets) {
84   if (matcher->GetURLFilterCount() == 0) {
85     // If there are no URL filters then we want to match all events, so create a
86     // URLFilter from an empty dictionary.
87     base::DictionaryValue empty_dict;
88     return AddDictionaryAsConditionSet(&empty_dict, condition_sets);
89   }
90   for (int i = 0; i < matcher->GetURLFilterCount(); i++) {
91     base::DictionaryValue* url_filter;
92     if (!matcher->GetURLFilter(i, &url_filter))
93       return false;
94     if (!AddDictionaryAsConditionSet(url_filter, condition_sets))
95       return false;
96   }
97   return true;
98 }
99
100 bool EventFilter::AddDictionaryAsConditionSet(
101     base::DictionaryValue* url_filter,
102     URLMatcherConditionSet::Vector* condition_sets) {
103   std::string error;
104   URLMatcherConditionSet::ID condition_set_id = next_condition_set_id_++;
105   condition_sets->push_back(URLMatcherFactory::CreateFromURLFilterDictionary(
106       url_matcher_.condition_factory(),
107       url_filter,
108       condition_set_id,
109       &error));
110   if (!error.empty()) {
111     LOG(ERROR) << "CreateFromURLFilterDictionary failed: " << error;
112     url_matcher_.ClearUnusedConditionSets();
113     condition_sets->clear();
114     return false;
115   }
116   return true;
117 }
118
119 std::string EventFilter::RemoveEventMatcher(MatcherID id) {
120   std::map<MatcherID, std::string>::iterator it = id_to_event_name_.find(id);
121   std::string event_name = it->second;
122   // EventMatcherEntry's destructor causes the condition set ids to be removed
123   // from url_matcher_.
124   event_matchers_[event_name].erase(id);
125   id_to_event_name_.erase(it);
126   return event_name;
127 }
128
129 std::set<EventFilter::MatcherID> EventFilter::MatchEvent(
130     const std::string& event_name, const EventFilteringInfo& event_info,
131     int routing_id) {
132   std::set<MatcherID> matchers;
133
134   EventMatcherMultiMap::iterator it = event_matchers_.find(event_name);
135   if (it == event_matchers_.end())
136     return matchers;
137
138   EventMatcherMap& matcher_map = it->second;
139   GURL url_to_match_against = event_info.has_url() ? event_info.url() : GURL();
140   std::set<URLMatcherConditionSet::ID> matching_condition_set_ids =
141       url_matcher_.MatchURL(url_to_match_against);
142   for (std::set<URLMatcherConditionSet::ID>::iterator it =
143        matching_condition_set_ids.begin();
144        it != matching_condition_set_ids.end(); it++) {
145     std::map<URLMatcherConditionSet::ID, MatcherID>::iterator matcher_id =
146         condition_set_id_to_event_matcher_id_.find(*it);
147     if (matcher_id == condition_set_id_to_event_matcher_id_.end()) {
148       NOTREACHED() << "id not found in condition set map (" << (*it) << ")";
149       continue;
150     }
151     MatcherID id = matcher_id->second;
152     EventMatcherMap::iterator matcher_entry = matcher_map.find(id);
153     if (matcher_entry == matcher_map.end()) {
154       // Matcher must be for a different event.
155       continue;
156     }
157     const EventMatcher* event_matcher = matcher_entry->second->event_matcher();
158     // The context that installed the event listener should be the same context
159     // as the one where the event listener is called.
160     if ((routing_id != MSG_ROUTING_NONE) &&
161         (event_matcher->GetRoutingID() != routing_id)) {
162       continue;
163     }
164     if (event_matcher->MatchNonURLCriteria(event_info)) {
165       CHECK(!event_matcher->HasURLFilters() || event_info.has_url());
166       matchers.insert(id);
167     }
168   }
169
170   return matchers;
171 }
172
173 int EventFilter::GetMatcherCountForEvent(const std::string& name) {
174   EventMatcherMultiMap::const_iterator it = event_matchers_.find(name);
175   if (it == event_matchers_.end())
176     return 0;
177
178   return it->second.size();
179 }
180
181 }  // namespace extensions