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