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 182