diff options
author | MHX348@motorola.com <MHX348@motorola.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-12 04:45:58 +0000 |
---|---|---|
committer | MHX348@motorola.com <MHX348@motorola.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-12 04:45:58 +0000 |
commit | 4b3e1928facf6e98d4a386601c6a568bcab69372 (patch) | |
tree | fe2f8f5e5a0beec65e60f161905d7d246debfaa8 /extensions/common | |
parent | 071d96b541fbc0370354a9fae78e5e87fdbe542d (diff) | |
download | chromium_src-4b3e1928facf6e98d4a386601c6a568bcab69372.zip chromium_src-4b3e1928facf6e98d4a386601c6a568bcab69372.tar.gz chromium_src-4b3e1928facf6e98d4a386601c6a568bcab69372.tar.bz2 |
Move EventFilter, EventFilteringInfo and EventMatcher
classes to extensions/common/
TBR=ben@chromium.org
BUG=162530
Review URL: https://chromiumcodereview.appspot.com/12208078
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181849 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions/common')
-rw-r--r-- | extensions/common/event_filter.cc | 172 | ||||
-rw-r--r-- | extensions/common/event_filter.h | 126 | ||||
-rw-r--r-- | extensions/common/event_filter_unittest.cc | 244 | ||||
-rw-r--r-- | extensions/common/event_filtering_info.cc | 48 | ||||
-rw-r--r-- | extensions/common/event_filtering_info.h | 47 | ||||
-rw-r--r-- | extensions/common/event_matcher.cc | 47 | ||||
-rw-r--r-- | extensions/common/event_matcher.h | 50 |
7 files changed, 734 insertions, 0 deletions
diff --git a/extensions/common/event_filter.cc b/extensions/common/event_filter.cc new file mode 100644 index 0000000..e5d6b1d --- /dev/null +++ b/extensions/common/event_filter.cc @@ -0,0 +1,172 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/event_filter.h" + +#include "extensions/common/matcher/url_matcher_factory.h" + +namespace extensions { + +EventFilter::EventMatcherEntry::EventMatcherEntry( + scoped_ptr<EventMatcher> event_matcher, + URLMatcher* url_matcher, + const URLMatcherConditionSet::Vector& condition_sets) + : event_matcher_(event_matcher.Pass()), + url_matcher_(url_matcher) { + for (URLMatcherConditionSet::Vector::const_iterator it = + condition_sets.begin(); it != condition_sets.end(); it++) + condition_set_ids_.push_back((*it)->id()); + url_matcher_->AddConditionSets(condition_sets); +} + +EventFilter::EventMatcherEntry::~EventMatcherEntry() { + url_matcher_->RemoveConditionSets(condition_set_ids_); +} + +void EventFilter::EventMatcherEntry::DontRemoveConditionSetsInDestructor() { + condition_set_ids_.clear(); +} + +EventFilter::EventFilter() + : next_id_(0), + next_condition_set_id_(0) { +} + +EventFilter::~EventFilter() { + // Normally when an event matcher entry is removed from event_matchers_ it + // will remove its condition sets from url_matcher_, but as url_matcher_ is + // being destroyed anyway there is no need to do that step here. + for (EventMatcherMultiMap::iterator it = event_matchers_.begin(); + it != event_matchers_.end(); it++) { + for (EventMatcherMap::iterator it2 = it->second.begin(); + it2 != it->second.end(); it2++) { + it2->second->DontRemoveConditionSetsInDestructor(); + } + } +} + +EventFilter::MatcherID +EventFilter::AddEventMatcher(const std::string& event_name, + scoped_ptr<EventMatcher> matcher) { + MatcherID id = next_id_++; + URLMatcherConditionSet::Vector condition_sets; + if (!CreateConditionSets(id, matcher.get(), &condition_sets)) + return -1; + + for (URLMatcherConditionSet::Vector::iterator it = condition_sets.begin(); + it != condition_sets.end(); it++) { + condition_set_id_to_event_matcher_id_.insert( + std::make_pair((*it)->id(), id)); + } + id_to_event_name_[id] = event_name; + event_matchers_[event_name][id] = linked_ptr<EventMatcherEntry>( + new EventMatcherEntry(matcher.Pass(), &url_matcher_, condition_sets)); + return id; +} + +EventMatcher* EventFilter::GetEventMatcher(MatcherID id) { + DCHECK(id_to_event_name_.find(id) != id_to_event_name_.end()); + const std::string& event_name = id_to_event_name_[id]; + return event_matchers_[event_name][id]->event_matcher(); +} + +const std::string& EventFilter::GetEventName(MatcherID id) { + DCHECK(id_to_event_name_.find(id) != id_to_event_name_.end()); + return id_to_event_name_[id]; +} + +bool EventFilter::CreateConditionSets( + MatcherID id, + EventMatcher* matcher, + URLMatcherConditionSet::Vector* condition_sets) { + if (matcher->GetURLFilterCount() == 0) { + // If there are no URL filters then we want to match all events, so create a + // URLFilter from an empty dictionary. + base::DictionaryValue empty_dict; + return AddDictionaryAsConditionSet(&empty_dict, condition_sets); + } + for (int i = 0; i < matcher->GetURLFilterCount(); i++) { + base::DictionaryValue* url_filter; + if (!matcher->GetURLFilter(i, &url_filter)) + return false; + if (!AddDictionaryAsConditionSet(url_filter, condition_sets)) + return false; + } + return true; +} + +bool EventFilter::AddDictionaryAsConditionSet( + base::DictionaryValue* url_filter, + URLMatcherConditionSet::Vector* condition_sets) { + std::string error; + URLMatcherConditionSet::ID condition_set_id = next_condition_set_id_++; + condition_sets->push_back(URLMatcherFactory::CreateFromURLFilterDictionary( + url_matcher_.condition_factory(), + url_filter, + condition_set_id, + &error)); + if (!error.empty()) { + LOG(ERROR) << "CreateFromURLFilterDictionary failed: " << error; + url_matcher_.ClearUnusedConditionSets(); + condition_sets->clear(); + return false; + } + return true; +} + +std::string EventFilter::RemoveEventMatcher(MatcherID id) { + std::map<MatcherID, std::string>::iterator it = id_to_event_name_.find(id); + std::string event_name = it->second; + // EventMatcherEntry's destructor causes the condition set ids to be removed + // from url_matcher_. + event_matchers_[event_name].erase(id); + id_to_event_name_.erase(it); + return event_name; +} + +std::set<EventFilter::MatcherID> EventFilter::MatchEvent( + const std::string& event_name, const EventFilteringInfo& event_info) { + std::set<MatcherID> matchers; + EventMatcherMultiMap::iterator it = event_matchers_.find(event_name); + if (it == event_matchers_.end()) + return matchers; + + EventMatcherMap& matcher_map = it->second; + GURL url_to_match_against = event_info.has_url() ? event_info.url() : GURL(); + std::set<URLMatcherConditionSet::ID> matching_condition_set_ids = + url_matcher_.MatchURL(url_to_match_against); + for (std::set<URLMatcherConditionSet::ID>::iterator it = + matching_condition_set_ids.begin(); + it != matching_condition_set_ids.end(); it++) { + std::map<URLMatcherConditionSet::ID, MatcherID>::iterator matcher_id = + condition_set_id_to_event_matcher_id_.find(*it); + if (matcher_id == condition_set_id_to_event_matcher_id_.end()) { + NOTREACHED() << "id not found in condition set map (" << (*it) << ")"; + continue; + } + MatcherID id = matcher_id->second; + EventMatcherMap::iterator matcher_entry = matcher_map.find(id); + if (matcher_entry == matcher_map.end()) { + // Matcher must be for a different event. + continue; + } + const EventMatcher* event_matcher = matcher_entry->second->event_matcher(); + if (event_matcher->MatchNonURLCriteria(event_info)) { + CHECK(!event_matcher->HasURLFilters() || event_info.has_url()); + matchers.insert(id); + } + } + + return matchers; +} + +int EventFilter::GetMatcherCountForEvent(const std::string& name) { + EventMatcherMultiMap::const_iterator it = event_matchers_.find(name); + if (it == event_matchers_.end()) + return 0; + + return it->second.size(); +} + +} // namespace extensions diff --git a/extensions/common/event_filter.h b/extensions/common/event_filter.h new file mode 100644 index 0000000..efde6035 --- /dev/null +++ b/extensions/common/event_filter.h @@ -0,0 +1,126 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_COMMON_EVENT_FILTER_H_ +#define EXTENSIONS_COMMON_EVENT_FILTER_H_ + +#include <map> +#include <set> + +#include "base/memory/linked_ptr.h" +#include "extensions/common/event_filtering_info.h" +#include "extensions/common/event_matcher.h" +#include "extensions/common/matcher/url_matcher.h" + +namespace extensions { + +// Matches incoming events against a collection of EventMatchers. Each added +// EventMatcher is given an id which is returned by MatchEvent() when it is +// passed a matching event. +class EventFilter { + public: + typedef int MatcherID; + EventFilter(); + ~EventFilter(); + + // Adds an event matcher that will be used in calls to MatchEvent(). Returns + // the id of the matcher, or -1 if there was an error. + MatcherID AddEventMatcher(const std::string& event_name, + scoped_ptr<EventMatcher> matcher); + + // Retrieve the EventMatcher with the given id. + EventMatcher* GetEventMatcher(MatcherID id); + + // Retrieve the name of the event that the EventMatcher specified by |id| is + // referring to. + const std::string& GetEventName(MatcherID id); + + // Removes an event matcher, returning the name of the event that it was for. + std::string RemoveEventMatcher(MatcherID id); + + // Match an event named |event_name| with filtering info |event_info| against + // our set of event matchers. Returns a set of ids that correspond to the + // event matchers that matched the event. + // TODO(koz): Add a std::string* parameter for retrieving error messages. + std::set<MatcherID> MatchEvent(const std::string& event_name, + const EventFilteringInfo& event_info); + + int GetMatcherCountForEvent(const std::string& event_name); + + // For testing. + bool IsURLMatcherEmpty() const { + return url_matcher_.IsEmpty(); + } + + private: + class EventMatcherEntry { + public: + // Adds |condition_sets| to |url_matcher| on construction and removes them + // again on destruction. |condition_sets| should be the + // URLMatcherConditionSets that match the URL constraints specified by + // |event_matcher|. + EventMatcherEntry(scoped_ptr<EventMatcher> event_matcher, + URLMatcher* url_matcher, + const URLMatcherConditionSet::Vector& condition_sets); + ~EventMatcherEntry(); + + // Prevents the removal of condition sets when this class is destroyed. We + // call this in EventFilter's destructor so that we don't do the costly + // removal of condition sets when the URLMatcher is going to be destroyed + // and clean them up anyway. + void DontRemoveConditionSetsInDestructor(); + + EventMatcher* event_matcher() { + return event_matcher_.get(); + } + + private: + scoped_ptr<EventMatcher> event_matcher_; + // The id sets in url_matcher_ that this EventMatcher owns. + std::vector<URLMatcherConditionSet::ID> condition_set_ids_; + URLMatcher* url_matcher_; + + DISALLOW_COPY_AND_ASSIGN(EventMatcherEntry); + }; + + // Maps from a matcher id to an event matcher entry. + typedef std::map<MatcherID, linked_ptr<EventMatcherEntry> > EventMatcherMap; + + // Maps from event name to the map of matchers that are registered for it. + typedef std::map<std::string, EventMatcherMap> EventMatcherMultiMap; + + // Adds the list of URL filters in |matcher| to the URL matcher, having + // matches for those URLs map to |id|. + bool CreateConditionSets(MatcherID id, + EventMatcher* matcher, + URLMatcherConditionSet::Vector* condition_sets); + + bool AddDictionaryAsConditionSet( + base::DictionaryValue* url_filter, + URLMatcherConditionSet::Vector* condition_sets); + + URLMatcher url_matcher_; + EventMatcherMultiMap event_matchers_; + + // The next id to assign to an EventMatcher. + MatcherID next_id_; + + // The next id to assign to a condition set passed to URLMatcher. + URLMatcherConditionSet::ID next_condition_set_id_; + + // Maps condition set ids, which URLMatcher operates in, to event matcher + // ids, which the interface to this class operates in. As each EventFilter + // can specify many condition sets this is a many to one relationship. + std::map<URLMatcherConditionSet::ID, MatcherID> + condition_set_id_to_event_matcher_id_; + + // Maps from event matcher ids to the name of the event they match on. + std::map<MatcherID, std::string> id_to_event_name_; + + DISALLOW_COPY_AND_ASSIGN(EventFilter); +}; + +} // namespace extensions + +#endif // EXTENSIONS_COMMON_EVENT_FILTER_H_ diff --git a/extensions/common/event_filter_unittest.cc b/extensions/common/event_filter_unittest.cc new file mode 100644 index 0000000..9b7f4ba --- /dev/null +++ b/extensions/common/event_filter_unittest.cc @@ -0,0 +1,244 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "extensions/common/event_filter.h" +#include "extensions/common/event_filtering_info.h" +#include "extensions/common/event_matcher.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +class EventFilterUnittest : public testing::Test { + public: + EventFilterUnittest() { + google_event_.SetURL(GURL("http://google.com")); + yahoo_event_.SetURL(GURL("http://yahoo.com")); + random_url_event_.SetURL(GURL("http://www.something-else.com")); + empty_url_event_.SetURL(GURL()); + } + + protected: + scoped_ptr<base::Value> HostSuffixDict(const std::string& host_suffix) { + scoped_ptr<base::DictionaryValue> dict(new DictionaryValue()); + dict->Set("hostSuffix", base::Value::CreateStringValue(host_suffix)); + return scoped_ptr<base::Value>(dict.release()); + } + + scoped_ptr<base::ListValue> ValueAsList(scoped_ptr<base::Value> value) { + scoped_ptr<base::ListValue> result(new base::ListValue()); + result->Append(value.release()); + return result.Pass(); + } + + scoped_ptr<EventMatcher> AllURLs() { + return scoped_ptr<EventMatcher>(new EventMatcher( + scoped_ptr<DictionaryValue>(new DictionaryValue))); + } + + scoped_ptr<EventMatcher> HostSuffixMatcher(const std::string& host_suffix) { + return MatcherFromURLFilterList(ValueAsList(HostSuffixDict(host_suffix))); + } + + scoped_ptr<EventMatcher> MatcherFromURLFilterList( + scoped_ptr<ListValue> url_filter_list) { + scoped_ptr<DictionaryValue> filter_dict(new DictionaryValue); + filter_dict->Set("url", url_filter_list.release()); + return scoped_ptr<EventMatcher>(new EventMatcher(filter_dict.Pass())); + } + + EventFilter event_filter_; + EventFilteringInfo empty_event_; + EventFilteringInfo google_event_; + EventFilteringInfo yahoo_event_; + EventFilteringInfo random_url_event_; + EventFilteringInfo empty_url_event_; +}; + +TEST_F(EventFilterUnittest, NoMatchersMatchIfEmpty) { + std::set<int> matches = event_filter_.MatchEvent("some-event", + empty_event_); + ASSERT_EQ(0u, matches.size()); +} + +TEST_F(EventFilterUnittest, AddingEventMatcherDoesntCrash) { + event_filter_.AddEventMatcher("event1", AllURLs()); +} + +TEST_F(EventFilterUnittest, + DontMatchAgainstMatchersForDifferentEvents) { + event_filter_.AddEventMatcher("event1", AllURLs()); + std::set<int> matches = event_filter_.MatchEvent("event2", + empty_event_); + ASSERT_EQ(0u, matches.size()); +} + +TEST_F(EventFilterUnittest, DoMatchAgainstMatchersForSameEvent) { + int id = event_filter_.AddEventMatcher("event1", AllURLs()); + std::set<int> matches = event_filter_.MatchEvent("event1", + google_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id)); +} + +TEST_F(EventFilterUnittest, DontMatchUnlessMatcherMatches) { + EventFilteringInfo info; + info.SetURL(GURL("http://www.yahoo.com")); + event_filter_.AddEventMatcher("event1", HostSuffixMatcher("google.com")); + std::set<int> matches = event_filter_.MatchEvent("event1", info); + ASSERT_TRUE(matches.empty()); +} + +TEST_F(EventFilterUnittest, RemovingAnEventMatcherStopsItMatching) { + int id = event_filter_.AddEventMatcher("event1", AllURLs()); + event_filter_.RemoveEventMatcher(id); + std::set<int> matches = event_filter_.MatchEvent("event1", + empty_event_); + ASSERT_TRUE(matches.empty()); +} + +TEST_F(EventFilterUnittest, MultipleEventMatches) { + int id1 = event_filter_.AddEventMatcher("event1", AllURLs()); + int id2 = event_filter_.AddEventMatcher("event1", AllURLs()); + std::set<int> matches = event_filter_.MatchEvent("event1", + google_event_); + ASSERT_EQ(2u, matches.size()); + ASSERT_EQ(1u, matches.count(id1)); + ASSERT_EQ(1u, matches.count(id2)); +} + +TEST_F(EventFilterUnittest, TestURLMatching) { + EventFilteringInfo info; + info.SetURL(GURL("http://www.google.com")); + int id = event_filter_.AddEventMatcher("event1", + HostSuffixMatcher("google.com")); + std::set<int> matches = event_filter_.MatchEvent("event1", info); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id)); +} + +TEST_F(EventFilterUnittest, TestMultipleURLFiltersMatchOnAny) { + scoped_ptr<base::ListValue> filters(new base::ListValue()); + filters->Append(HostSuffixDict("google.com").release()); + filters->Append(HostSuffixDict("yahoo.com").release()); + + scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList(filters.Pass())); + int id = event_filter_.AddEventMatcher("event1", matcher.Pass()); + + { + std::set<int> matches = event_filter_.MatchEvent("event1", + google_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id)); + } + { + std::set<int> matches = event_filter_.MatchEvent("event1", + yahoo_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id)); + } + { + std::set<int> matches = event_filter_.MatchEvent("event1", + random_url_event_); + ASSERT_EQ(0u, matches.size()); + } +} + +TEST_F(EventFilterUnittest, TestStillMatchesAfterRemoval) { + int id1 = event_filter_.AddEventMatcher("event1", AllURLs()); + int id2 = event_filter_.AddEventMatcher("event1", AllURLs()); + + event_filter_.RemoveEventMatcher(id1); + { + std::set<int> matches = event_filter_.MatchEvent("event1", + google_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id2)); + } +} + +TEST_F(EventFilterUnittest, TestMatchesOnlyAgainstPatternsForCorrectEvent) { + int id1 = event_filter_.AddEventMatcher("event1", AllURLs()); + event_filter_.AddEventMatcher("event2", AllURLs()); + + { + std::set<int> matches = event_filter_.MatchEvent("event1", + google_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id1)); + } +} + +TEST_F(EventFilterUnittest, TestGetMatcherCountForEvent) { + ASSERT_EQ(0, event_filter_.GetMatcherCountForEvent("event1")); + int id1 = event_filter_.AddEventMatcher("event1", AllURLs()); + ASSERT_EQ(1, event_filter_.GetMatcherCountForEvent("event1")); + int id2 = event_filter_.AddEventMatcher("event1", AllURLs()); + ASSERT_EQ(2, event_filter_.GetMatcherCountForEvent("event1")); + event_filter_.RemoveEventMatcher(id1); + ASSERT_EQ(1, event_filter_.GetMatcherCountForEvent("event1")); + event_filter_.RemoveEventMatcher(id2); + ASSERT_EQ(0, event_filter_.GetMatcherCountForEvent("event1")); +} + +TEST_F(EventFilterUnittest, RemoveEventMatcherReturnsEventName) { + int id1 = event_filter_.AddEventMatcher("event1", AllURLs()); + int id2 = event_filter_.AddEventMatcher("event1", AllURLs()); + int id3 = event_filter_.AddEventMatcher("event2", AllURLs()); + + ASSERT_EQ("event1", event_filter_.RemoveEventMatcher(id1)); + ASSERT_EQ("event1", event_filter_.RemoveEventMatcher(id2)); + ASSERT_EQ("event2", event_filter_.RemoveEventMatcher(id3)); +} + +TEST_F(EventFilterUnittest, InvalidURLFilterCantBeAdded) { + scoped_ptr<base::ListValue> filter_list(new base::ListValue()); + filter_list->Append(new base::ListValue()); // Should be a dict. + scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList( + filter_list.Pass())); + int id1 = event_filter_.AddEventMatcher("event1", matcher.Pass()); + EXPECT_TRUE(event_filter_.IsURLMatcherEmpty()); + ASSERT_EQ(-1, id1); +} + +TEST_F(EventFilterUnittest, EmptyListOfURLFiltersMatchesAllURLs) { + scoped_ptr<base::ListValue> filter_list(new base::ListValue()); + scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList( + scoped_ptr<ListValue>(new ListValue))); + int id = event_filter_.AddEventMatcher("event1", matcher.Pass()); + std::set<int> matches = event_filter_.MatchEvent("event1", + google_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id)); +} + +TEST_F(EventFilterUnittest, + InternalURLMatcherShouldBeEmptyWhenThereAreNoEventMatchers) { + ASSERT_TRUE(event_filter_.IsURLMatcherEmpty()); + int id = event_filter_.AddEventMatcher("event1", + HostSuffixMatcher("google.com")); + ASSERT_FALSE(event_filter_.IsURLMatcherEmpty()); + event_filter_.RemoveEventMatcher(id); + ASSERT_TRUE(event_filter_.IsURLMatcherEmpty()); +} + +TEST_F(EventFilterUnittest, EmptyURLsShouldBeMatchedByEmptyURLFilters) { + int id = event_filter_.AddEventMatcher("event1", AllURLs()); + std::set<int> matches = event_filter_.MatchEvent("event1", empty_url_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id)); +} + +TEST_F(EventFilterUnittest, + EmptyURLsShouldBeMatchedByEmptyURLFiltersWithAnEmptyItem) { + scoped_ptr<EventMatcher> matcher(MatcherFromURLFilterList(ValueAsList( + scoped_ptr<Value>(new DictionaryValue())))); + int id = event_filter_.AddEventMatcher("event1", matcher.Pass()); + std::set<int> matches = event_filter_.MatchEvent("event1", empty_url_event_); + ASSERT_EQ(1u, matches.size()); + ASSERT_EQ(1u, matches.count(id)); +} + +} // namespace extensions diff --git a/extensions/common/event_filtering_info.cc b/extensions/common/event_filtering_info.cc new file mode 100644 index 0000000..009dcaa --- /dev/null +++ b/extensions/common/event_filtering_info.cc @@ -0,0 +1,48 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/event_filtering_info.h" + +#include "base/json/json_writer.h" +#include "base/values.h" + +namespace extensions { + +EventFilteringInfo::EventFilteringInfo() + : has_url_(false) { +} + +EventFilteringInfo::~EventFilteringInfo() { +} + +void EventFilteringInfo::SetURL(const GURL& url) { + url_ = url; + has_url_ = true; +} + +std::string EventFilteringInfo::AsJSONString() const { + std::string result; + base::DictionaryValue value; + if (has_url_) + value.SetString("url", url_.spec()); + + base::JSONWriter::Write(&value, &result); + return result; +} + +scoped_ptr<base::Value> EventFilteringInfo::AsValue() const { + if (IsEmpty()) + return scoped_ptr<base::Value>(base::Value::CreateNullValue()); + + scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); + if (has_url_) + result->SetString("url", url_.spec()); + return result.PassAs<base::Value>(); +} + +bool EventFilteringInfo::IsEmpty() const { + return !has_url_; +} + +} // namespace extensions diff --git a/extensions/common/event_filtering_info.h b/extensions/common/event_filtering_info.h new file mode 100644 index 0000000..2fee9c1 --- /dev/null +++ b/extensions/common/event_filtering_info.h @@ -0,0 +1,47 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_COMMON_EVENT_FILTERING_INFO_H_ +#define EXTENSIONS_COMMON_EVENT_FILTERING_INFO_H_ + +#include "base/memory/scoped_ptr.h" +#include "googleurl/src/gurl.h" + +namespace base { +class Value; +} + +namespace extensions { + +// Extra information about an event that is used in event filtering. +// +// This is the information that is matched against criteria specified in JS +// extension event listeners. Eg: +// +// chrome.someApi.onSomeEvent.addListener(cb, +// {url: [{hostSuffix: 'google.com'}], +// tabId: 1}); +class EventFilteringInfo { + public: + EventFilteringInfo(); + ~EventFilteringInfo(); + void SetURL(const GURL& url); + + bool has_url() const { return has_url_; } + const GURL& url() const { return url_; } + + std::string AsJSONString() const; + scoped_ptr<base::Value> AsValue() const; + bool IsEmpty() const; + + private: + bool has_url_; + GURL url_; + + // Allow implicit copy and assignment. +}; + +} // namespace extensions + +#endif // EXTENSIONS_COMMON_EVENT_FILTERING_INFO_H_ diff --git a/extensions/common/event_matcher.cc b/extensions/common/event_matcher.cc new file mode 100644 index 0000000..c982937 --- /dev/null +++ b/extensions/common/event_matcher.cc @@ -0,0 +1,47 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/event_matcher.h" + +#include "extensions/common/event_filtering_info.h" + +namespace { +const char kUrlFiltersKey[] = "url"; +} + +namespace extensions { + +EventMatcher::EventMatcher(scoped_ptr<base::DictionaryValue> filter) + : filter_(filter.Pass()) { +} + +EventMatcher::~EventMatcher() { +} + +bool EventMatcher::MatchNonURLCriteria( + const EventFilteringInfo& event_info) const { + // There is currently no criteria apart from URL criteria. + return true; +} + +int EventMatcher::GetURLFilterCount() const { + base::ListValue* url_filters = NULL; + if (filter_->GetList(kUrlFiltersKey, &url_filters)) + return url_filters->GetSize(); + return 0; +} + +bool EventMatcher::GetURLFilter(int i, base::DictionaryValue** url_filter_out) { + base::ListValue* url_filters = NULL; + if (filter_->GetList(kUrlFiltersKey, &url_filters)) { + return url_filters->GetDictionary(i, url_filter_out); + } + return false; +} + +int EventMatcher::HasURLFilters() const { + return GetURLFilterCount() != 0; +} + +} // namespace extensions diff --git a/extensions/common/event_matcher.h b/extensions/common/event_matcher.h new file mode 100644 index 0000000..bb28419 --- /dev/null +++ b/extensions/common/event_matcher.h @@ -0,0 +1,50 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_COMMON_EVENT_MATCHER_H_ +#define EXTENSIONS_COMMON_EVENT_MATCHER_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/values.h" + +namespace extensions { + +class EventFilteringInfo; + +// Matches EventFilteringInfos against a set of criteria. This is intended to +// be used by EventFilter which performs efficient URL matching across +// potentially many EventMatchers itself. This is why this class only exposes +// MatchNonURLCriteria() - URL matching is handled by EventFilter. +class EventMatcher { + public: + explicit EventMatcher(scoped_ptr<base::DictionaryValue> filter); + ~EventMatcher(); + + // Returns true if |event_info| satisfies this matcher's criteria, not taking + // into consideration any URL criteria. + bool MatchNonURLCriteria(const EventFilteringInfo& event_info) const; + + int GetURLFilterCount() const; + bool GetURLFilter(int i, base::DictionaryValue** url_filter_out); + + int HasURLFilters() const; + + base::DictionaryValue* value() const { + return filter_.get(); + } + + private: + // Contains a dictionary that corresponds to a single event filter, eg: + // + // {url: [{hostSuffix: 'google.com'}]} + // + // The valid filter keys are event-specific. + scoped_ptr<base::DictionaryValue> filter_; + + DISALLOW_COPY_AND_ASSIGN(EventMatcher); +}; + +} // namespace extensions + +#endif // EXTENSIONS_COMMON_EVENT_MATCHER_H_ |