Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3823)

Unified Diff: chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc

Issue 9820003: Implementation of beginning of Declarative Web Request API backend (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7e28332291890342fddaa49e3a53d25259844078
--- /dev/null
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc
@@ -0,0 +1,311 @@
+// 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 "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"
+
+#include "base/logging.h"
+#include "base/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
+#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h"
+#include "net/url_request/url_request.h"
+
+namespace {
+static extensions::URLMatcherConditionSet::ID g_next_id = 0;
+
+// TODO(battre): improve error messaging to give more meaningful messages
+// to the extension developer.
+// Error messages:
+const char kExpectedDictionary[] = "A condition has to be a dictionary.";
+const char kConditionWithoutInstanceType[] = "A condition had no instanceType";
+const char kExpectedOtherConditionType[] = "Expected a condition of type "
+ "experimental.webRequest.RequestMatcher";
+const char kUnknownConditionAttribute[] = "UnKnown condition attribute '%s'";
+const char kConditionExpectedString[] =
+ "Condition '%s' expected a string value";
+
+// String literals from the JavaScript API:
+const char kRequestMatcher[] = "experimental.webRequest.RequestMatcher";
+const char kInstanceType[] = "instanceType";
+
+const char kHostContainsKey[] = "host_contains";
+const char kHostEqualsKey[] = "host_equals";
+const char kHostPrefixKey[] = "host_prefix";
+const char kHostSuffixKey[] = "host_suffix";
+const char kHostSuffixPathPrefixKey[] = "host_suffix_path_prefix";
+const char kPathContainsKey[] = "path_contains";
+const char kPathEqualsKey[] = "path_equals";
+const char kPathPrefixKey[] = "path_prefix";
+const char kPathSuffixKey[] = "path_suffix";
+const char kQueryContainsKey[] = "query_contains";
+const char kQueryEqualsKey[] = "query_equals";
+const char kQueryPrefixKey[] = "query_prefix";
+const char kQuerySuffixKey[] = "query_suffix";
+const char kURLContainsKey[] = "url_contains";
+const char kURLEqualsKey[] = "url_equals";
+const char kURLPrefixKey[] = "url_prefix";
+const char kURLSuffixKey[] = "url_suffix";
+
+// This is an array of all criteria that may be evaluated on the URL.
+// These MUST appear in alphabetical order in order to allow a binary search
+// on them.
+const char* kAllPathAttributes[] = {
Matt Perry 2012/03/22 01:34:43 Putting these in a global map would remove the alp
battre 2012/03/26 18:35:51 Done.
+ kHostContainsKey,
+ kHostEqualsKey,
+ kHostPrefixKey,
+ kHostSuffixKey,
+ // kHostSuffixPathPrefixKey, // TODO(battre): support this.
+ kPathContainsKey,
+ kPathEqualsKey,
+ kPathPrefixKey,
+ kPathSuffixKey,
+ kQueryContainsKey,
+ kQueryEqualsKey,
+ kQueryPrefixKey,
+ kQuerySuffixKey,
+ kURLContainsKey,
+ kURLEqualsKey,
+ kURLPrefixKey,
+ kURLSuffixKey
+};
+
+} // namespace
+
+namespace extensions {
+namespace declarative_webrequest {
+
+WebRequestCondition::WebRequestCondition(
+ const URLMatcherConditionSet& url_matcher_conditions,
+ const WebRequestConditionAttributes& condition_attributes)
+ : url_matcher_conditions_(url_matcher_conditions),
+ condition_attributes_(condition_attributes) {}
+
+WebRequestCondition::~WebRequestCondition() {}
+
+bool WebRequestCondition::IsFulfilled(
+ URLMatcherConditionSet::ID url_match,
+ net::URLRequest* request) const {
+ if (url_match != url_matcher_condition_set_id())
+ return false;
+
+ // All condition attributes must be fulfilled for a fulfilled condition.
+ for (WebRequestConditionAttributes::const_iterator i =
+ condition_attributes_.begin(); i != condition_attributes_.end(); ++i) {
+ if (!(*i)->IsFulfilled(request))
+ return false;
+ }
+ return true;
+}
+
+void WebRequestCondition::AppendURLMatcherConditionSet(
+ std::vector<URLMatcherConditionSet>* condition_sets) const {
+ condition_sets->push_back(url_matcher_conditions_);
+}
+
+WebRequestConditionCollection::WebRequestConditionCollection(
+ const std::vector<linked_ptr<WebRequestCondition> >& conditions)
+ : conditions_(conditions) {
+ for (Collection::iterator i = conditions_.begin(); i != conditions_.end();
+ ++i) {
+ URLMatcherConditionSet::ID trigger_id =
+ (*i)->url_matcher_condition_set_id();
+ match_triggers_[trigger_id] = i->get();
+ }
+}
+
+WebRequestConditionCollection::~WebRequestConditionCollection() {}
+
+bool WebRequestConditionCollection::IsFulfilled(
+ const std::set<URLMatcherConditionSet::ID>& url_matches,
+ net::URLRequest* request) const {
+ // The URL matcher found all SubstringPattern::ID in |url_matches|.
+ // Let's see whether any of these is the primary SubstringPattern::ID
+ // of a WebRequestCondition.
+ for (std::set<URLMatcherConditionSet::ID>::const_iterator i =
+ url_matches.begin(); i != url_matches.end(); ++i) {
+ MatchTriggers::const_iterator trigger = match_triggers_.find(*i);
+ if (trigger == match_triggers_.end())
+ continue;
+ if (trigger->second->IsFulfilled(*i, request))
Matt Perry 2012/03/22 23:07:25 Is it necessary to pass in the set ID? If the cond
battre 2012/03/26 18:35:51 Done.
+ return true;
+ }
+ return false;
+}
+
+void WebRequestConditionCollection::AppendURLMatcherConditionSets(
+ std::vector<URLMatcherConditionSet>* condition_sets) const {
+ for (Collection::const_iterator i = conditions_.begin();
+ i != conditions_.end(); ++i) {
+ (*i)->AppendURLMatcherConditionSet(condition_sets);
+ }
+}
+
+// static
+scoped_ptr<WebRequestCondition> WebRequestConditionFactory::CreateCondition(
+ URLMatcherConditionFactory* url_matcher_condition_factory,
+ const base::Value& condition,
+ std::string* error) {
+ const base::DictionaryValue* condition_dict = NULL;
+ if (!condition.GetAsDictionary(&condition_dict)) {
+ *error = kExpectedDictionary;
+ return scoped_ptr<WebRequestCondition>(NULL);
+ }
+
+ // Verify that we are dealing with a Condition whose type we understand.
+ std::string instance_type;
+ if (!condition_dict->GetString(kInstanceType, &instance_type)) {
+ *error = kConditionWithoutInstanceType;
+ return scoped_ptr<WebRequestCondition>(NULL);
+ }
+ if (instance_type != kRequestMatcher) {
+ *error = kExpectedOtherConditionType;
+ return scoped_ptr<WebRequestCondition>(NULL);
+ }
+
+ WebRequestConditionAttributes attributes;
+ URLMatcherConditionSet::Conditions url_matcher_conditions;
+ for (base::DictionaryValue::key_iterator key = condition_dict->begin_keys();
Matt Perry 2012/03/22 23:07:25 Give DictionaryValue::Iterator a try, since you ne
battre 2012/03/26 18:35:51 Done.
+ key != condition_dict->end_keys(); ++key) {
+ const std::string& condition_attribute_name = *key;
+ if (condition_attribute_name == kInstanceType)
+ continue;
+ Value* condition_attribute_value = NULL;
+ condition_dict->Get(condition_attribute_name, &condition_attribute_value);
+
+ if (condition_attribute_name == instance_type) {
Matt Perry 2012/03/22 23:07:25 When is this possible?
battre 2012/03/26 18:35:51 This was an error, I meant to compare to kInstance
+ // Skip this.
+ } else if (IsUrlMatcherConditionAttribute(condition_attribute_name)) {
+ URLMatcherCondition url_matcher_condition =
+ CreateURLMatcherCondition(
+ url_matcher_condition_factory,
+ condition_attribute_name,
+ condition_attribute_value,
+ error);
+ if (!error->empty())
+ return scoped_ptr<WebRequestCondition>(NULL);
+ url_matcher_conditions.insert(url_matcher_condition);
+ } else if (WebRequestConditionAttributeFactory::IsHandledByThisFactory(
+ condition_attribute_name)) {
+ scoped_ptr<WebRequestConditionAttribute> attribute =
+ WebRequestConditionAttributeFactory::Create(
+ condition_attribute_name,
+ condition_attribute_value,
+ error);
+ if (!error->empty())
+ return scoped_ptr<WebRequestCondition>(NULL);
+ attributes.push_back(make_linked_ptr(attribute.release()));
+ } else {
+ *error = base::StringPrintf(kUnknownConditionAttribute,
+ condition_attribute_name.c_str());
+ return scoped_ptr<WebRequestCondition>(NULL);
+ }
+ }
+
+ // As the URL is the preliminary matching criterion that triggers the tests
+ // for the remaining condition attributes, we insert an empty URL match if
+ // no other url match conditions were specified. Such an empty URL is always
+ // matched.
+ if (url_matcher_conditions.empty()) {
+ url_matcher_conditions.insert(
+ url_matcher_condition_factory->CreateHostPrefixCondition(""));
+ }
+
+ URLMatcherConditionSet url_matcher_condition_set(++g_next_id,
+ url_matcher_conditions);
+ return scoped_ptr<WebRequestCondition>(
+ new WebRequestCondition(url_matcher_condition_set, attributes));
+}
+
+// static
+scoped_ptr<WebRequestConditionCollection>
+WebRequestConditionFactory::CreateConditionCollection(
+ URLMatcherConditionFactory* url_matcher_condition_factory,
+ const AnyVector& conditions,
+ std::string* error) {
+ std::vector<linked_ptr<WebRequestCondition> > result;
+
+ for (AnyVector::const_iterator i = conditions.begin();
+ i != conditions.end(); ++i) {
+ CHECK(i->get());
+ scoped_ptr<WebRequestCondition> condition =
+ CreateCondition(url_matcher_condition_factory, (*i)->value(), error);
+ if (!error->empty())
+ return scoped_ptr<WebRequestConditionCollection>(NULL);
+ result.push_back(make_linked_ptr(condition.release()));
+ }
+
+ return scoped_ptr<WebRequestConditionCollection>(
+ new WebRequestConditionCollection(result));
+}
+
+// static
+std::vector<std::string> WebRequestConditionFactory::GetAllPathAttributes() {
+ return std::vector<std::string>(
+ kAllPathAttributes, kAllPathAttributes + arraysize(kAllPathAttributes));
+}
+
+// static
+bool WebRequestConditionFactory::IsUrlMatcherConditionAttribute(
+ const std::string& name) {
+ return std::binary_search(kAllPathAttributes,
+ kAllPathAttributes + arraysize(kAllPathAttributes),
+ name);
+}
+
+// static
+URLMatcherCondition WebRequestConditionFactory::CreateURLMatcherCondition(
+ URLMatcherConditionFactory* url_matcher_condition_factory,
+ const std::string& condition_attribute_name,
+ const base::Value* value,
+ std::string* error) {
+
+ std::string str_value;
+ if (!value->GetAsString(&str_value)) {
+ *error = base::StringPrintf(kConditionExpectedString,
+ condition_attribute_name.c_str());
+ return URLMatcherCondition();
+ }
+
+ URLMatcherConditionFactory* factory = url_matcher_condition_factory;
+ if (condition_attribute_name == kHostContainsKey) {
+ return factory->CreateHostContainsCondition(str_value);
+ } else if (condition_attribute_name == kHostEqualsKey) {
+ return factory->CreateHostEqualsCondition(str_value);
+ } else if (condition_attribute_name == kHostPrefixKey) {
+ return factory->CreateHostPrefixCondition(str_value);
+ } else if (condition_attribute_name == kHostSuffixKey) {
+ return factory->CreateHostSuffixCondition(str_value);
+ } else if (condition_attribute_name == kHostSuffixPathPrefixKey) {
+ NOTREACHED(); // Not implemented, yet.
+ } else if (condition_attribute_name == kPathContainsKey) {
+ return factory->CreatePathContainsCondition(str_value);
+ } else if (condition_attribute_name == kPathEqualsKey) {
+ return factory->CreatePathEqualsCondition(str_value);
+ } else if (condition_attribute_name == kPathPrefixKey) {
+ return factory->CreatePathPrefixCondition(str_value);
+ } else if (condition_attribute_name == kPathSuffixKey) {
+ return factory->CreatePathSuffixCondition(str_value);
+ } else if (condition_attribute_name == kQueryContainsKey) {
+ return factory->CreatePathContainsCondition(str_value);
+ } else if (condition_attribute_name == kQueryEqualsKey) {
+ return factory->CreateQueryEqualsCondition(str_value);
+ } else if (condition_attribute_name == kQueryPrefixKey) {
+ return factory->CreateQueryPrefixCondition(str_value);
+ } else if (condition_attribute_name == kQuerySuffixKey) {
+ return factory->CreateQuerySuffixCondition(str_value);
+ } else if (condition_attribute_name == kURLContainsKey) {
+ return factory->CreateURLContainsCondition(str_value);
+ } else if (condition_attribute_name == kURLEqualsKey) {
+ return factory->CreateURLEqualsCondition(str_value);
+ } else if (condition_attribute_name == kURLPrefixKey) {
+ return factory->CreateURLPrefixCondition(str_value);
+ } else if (condition_attribute_name == kURLSuffixKey) {
+ return factory->CreateURLSuffixCondition(str_value);
+ }
+ *error = "Unsupported url matching condition";
+ return URLMatcherCondition();
+}
+
+} // namespace declarative_webrequest
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698