diff options
Diffstat (limited to 'chrome')
11 files changed, 272 insertions, 24 deletions
diff --git a/chrome/browser/extensions/api/declarative/url_matcher.cc b/chrome/browser/extensions/api/declarative/url_matcher.cc index 816c890..a366e1c 100644 --- a/chrome/browser/extensions/api/declarative/url_matcher.cc +++ b/chrome/browser/extensions/api/declarative/url_matcher.cc @@ -403,6 +403,37 @@ bool URLMatcherSchemeFilter::IsMatch(const GURL& url) const { } // +// URLMatcherPortFilter +// + +URLMatcherPortFilter::URLMatcherPortFilter( + const std::vector<URLMatcherPortFilter::Range>& ranges) + : ranges_(ranges) {} + +URLMatcherPortFilter::~URLMatcherPortFilter() {} + +bool URLMatcherPortFilter::IsMatch(const GURL& url) const { + int port = url.EffectiveIntPort(); + for (std::vector<Range>::const_iterator i = ranges_.begin(); + i != ranges_.end(); ++i) { + if (i->first <= port && port <= i->second) + return true; + } + return false; +} + +// static +URLMatcherPortFilter::Range URLMatcherPortFilter::CreateRange(int from, + int to) { + return Range(from, to); +} + +// static +URLMatcherPortFilter::Range URLMatcherPortFilter::CreateRange(int port) { + return Range(port, port); +} + +// // URLMatcherConditionSet // @@ -417,10 +448,12 @@ URLMatcherConditionSet::URLMatcherConditionSet( URLMatcherConditionSet::URLMatcherConditionSet( ID id, const Conditions& conditions, - scoped_ptr<URLMatcherSchemeFilter> scheme_filter) + scoped_ptr<URLMatcherSchemeFilter> scheme_filter, + scoped_ptr<URLMatcherPortFilter> port_filter) : id_(id), conditions_(conditions), - scheme_filter_(scheme_filter.Pass()) {} + scheme_filter_(scheme_filter.Pass()), + port_filter_(port_filter.Pass()) {} bool URLMatcherConditionSet::IsMatch( const std::set<SubstringPattern::ID>& matching_substring_patterns, @@ -432,6 +465,8 @@ bool URLMatcherConditionSet::IsMatch( } if (scheme_filter_.get() && !scheme_filter_->IsMatch(url)) return false; + if (port_filter_.get() && !port_filter_->IsMatch(url)) + return false; return true; } diff --git a/chrome/browser/extensions/api/declarative/url_matcher.h b/chrome/browser/extensions/api/declarative/url_matcher.h index 5fdacb2..9bec45b 100644 --- a/chrome/browser/extensions/api/declarative/url_matcher.h +++ b/chrome/browser/extensions/api/declarative/url_matcher.h @@ -194,6 +194,27 @@ class URLMatcherSchemeFilter { DISALLOW_COPY_AND_ASSIGN(URLMatcherSchemeFilter); }; +// This class represents a filter for port numbers to be hooked up into a +// URLMatcherConditionSet. +class URLMatcherPortFilter { + public: + // Boundaries of a port range (both ends are included). + typedef std::pair<int, int> Range; + explicit URLMatcherPortFilter(const std::vector<Range>& ranges); + ~URLMatcherPortFilter(); + bool IsMatch(const GURL& url) const; + + // Creates a port range [from, to]; both ends are included. + static Range CreateRange(int from, int to); + // Creates a port range containing a single port. + static Range CreateRange(int port); + + private: + std::vector<Range> ranges_; + + DISALLOW_COPY_AND_ASSIGN(URLMatcherPortFilter); +}; + // This class represents a set of conditions that all need to match on a // given URL in order to be considered a match. class URLMatcherConditionSet : public base::RefCounted<URLMatcherConditionSet> { @@ -205,11 +226,12 @@ class URLMatcherConditionSet : public base::RefCounted<URLMatcherConditionSet> { // Matches if all conditions in |conditions| are fulfilled. URLMatcherConditionSet(ID id, const Conditions& conditions); - // Matches if all conditions in |conditions| and |scheme_filter| are - // fulfilled. |scheme_filter| may be NULL, in which case, no restrictions - // are imposed on the scheme of a URL. + // Matches if all conditions in |conditions|, |scheme_filter| and + // |port_filter| are fulfilled. |scheme_filter| and |port_filter| may be NULL, + // in which case, no restrictions are imposed on the scheme/port of a URL. URLMatcherConditionSet(ID id, const Conditions& conditions, - scoped_ptr<URLMatcherSchemeFilter> scheme_filter); + scoped_ptr<URLMatcherSchemeFilter> scheme_filter, + scoped_ptr<URLMatcherPortFilter> port_filter); ID id() const { return id_; } const Conditions& conditions() const { return conditions_; } @@ -224,6 +246,7 @@ class URLMatcherConditionSet : public base::RefCounted<URLMatcherConditionSet> { ID id_; Conditions conditions_; scoped_ptr<URLMatcherSchemeFilter> scheme_filter_; + scoped_ptr<URLMatcherPortFilter> port_filter_; DISALLOW_COPY_AND_ASSIGN(URLMatcherConditionSet); }; diff --git a/chrome/browser/extensions/api/declarative/url_matcher_unittest.cc b/chrome/browser/extensions/api/declarative/url_matcher_unittest.cc index c32b78a..35c8183 100644 --- a/chrome/browser/extensions/api/declarative/url_matcher_unittest.cc +++ b/chrome/browser/extensions/api/declarative/url_matcher_unittest.cc @@ -45,6 +45,21 @@ TEST(URLMatcherSchemeFilter, TestMatching) { EXPECT_TRUE(filter2.IsMatch(non_matching_url)); } +TEST(URLMatcherPortFilter, TestMatching) { + std::vector<URLMatcherPortFilter::Range> ranges; + ranges.push_back(URLMatcherPortFilter::CreateRange(80, 90)); + ranges.push_back(URLMatcherPortFilter::CreateRange(8080)); + URLMatcherPortFilter filter(ranges); + EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com"))); + EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:80"))); + EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:81"))); + EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:90"))); + EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:8080"))); + EXPECT_FALSE(filter.IsMatch(GURL("http://www.example.com:79"))); + EXPECT_FALSE(filter.IsMatch(GURL("http://www.example.com:91"))); + EXPECT_FALSE(filter.IsMatch(GURL("https://www.example.com"))); +} + TEST(URLMatcherConditionTest, IsFullURLCondition) { SubstringPattern pattern("example.com", 1); EXPECT_FALSE(URLMatcherCondition(URLMatcherCondition::HOST_SUFFIX, @@ -317,6 +332,8 @@ TEST(URLMatcherConditionSetTest, Constructor) { TEST(URLMatcherConditionSetTest, Matching) { GURL url1("http://www.example.com/foo?bar=1"); GURL url2("http://foo.example.com/index.html"); + GURL url3("http://www.example.com:80/foo?bar=1"); + GURL url4("http://www.example.com:8080/foo?bar=1"); URLMatcherConditionFactory factory; URLMatcherCondition m1 = factory.CreateHostSuffixCondition("example.com"); @@ -339,18 +356,30 @@ TEST(URLMatcherConditionSetTest, Matching) { EXPECT_TRUE(condition_set->IsMatch(matching_substring_patterns, url1)); EXPECT_FALSE(condition_set->IsMatch(matching_substring_patterns, url2)); - // Test scheme filters. scoped_refptr<URLMatcherConditionSet> condition_set2( new URLMatcherConditionSet(1, conditions, scoped_ptr<URLMatcherSchemeFilter>( - new URLMatcherSchemeFilter("https")))); + new URLMatcherSchemeFilter("https")), + scoped_ptr<URLMatcherPortFilter>(NULL))); EXPECT_FALSE(condition_set2->IsMatch(matching_substring_patterns, url1)); scoped_refptr<URLMatcherConditionSet> condition_set3( new URLMatcherConditionSet(1, conditions, scoped_ptr<URLMatcherSchemeFilter>( - new URLMatcherSchemeFilter("http")))); + new URLMatcherSchemeFilter("http")), + scoped_ptr<URLMatcherPortFilter>(NULL))); EXPECT_TRUE(condition_set3->IsMatch(matching_substring_patterns, url1)); + + // Test port filters. + std::vector<URLMatcherPortFilter::Range> ranges; + ranges.push_back(URLMatcherPortFilter::CreateRange(80)); + scoped_ptr<URLMatcherPortFilter> filter(new URLMatcherPortFilter(ranges)); + scoped_refptr<URLMatcherConditionSet> condition_set4( + new URLMatcherConditionSet(1, conditions, + scoped_ptr<URLMatcherSchemeFilter>(NULL), filter.Pass())); + EXPECT_TRUE(condition_set4->IsMatch(matching_substring_patterns, url1)); + EXPECT_TRUE(condition_set4->IsMatch(matching_substring_patterns, url3)); + EXPECT_FALSE(condition_set4->IsMatch(matching_substring_patterns, url4)); } diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc index cf02de7..962131c 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc @@ -33,6 +33,7 @@ const char kConditionExpectedString[] = "Condition '%s' expected a string value"; const char kVectorOfStringsExpected[] = "Attribute '%s' expected a vector of strings"; +const char kInvalidPortRanges[] = "Invalid port ranges"; // String literals from the JavaScript API: const char kHostContainsKey[] = "host_contains"; @@ -179,6 +180,7 @@ scoped_ptr<WebRequestCondition> WebRequestCondition::Create( WebRequestConditionAttributes attributes; URLMatcherConditionSet::Conditions url_matcher_conditions; scoped_ptr<URLMatcherSchemeFilter> url_matcher_schema_filter; + scoped_ptr<URLMatcherPortFilter> url_matcher_port_filter; for (base::DictionaryValue::Iterator iter(*condition_dict); iter.HasNext(); iter.Advance()) { @@ -201,6 +203,11 @@ scoped_ptr<WebRequestCondition> WebRequestCondition::Create( &condition_attribute_value, error); if (!error->empty()) return scoped_ptr<WebRequestCondition>(NULL); + } else if (condition_attribute_name == keys::kPortsKey) { + url_matcher_port_filter = CreateURLMatcherPorts( + &condition_attribute_value, error); + if (!error->empty()) + return scoped_ptr<WebRequestCondition>(NULL); } else if (WebRequestConditionAttribute::IsKnownType( condition_attribute_name)) { scoped_ptr<WebRequestConditionAttribute> attribute = @@ -229,7 +236,7 @@ scoped_ptr<WebRequestCondition> WebRequestCondition::Create( scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set( new URLMatcherConditionSet(++g_next_id, url_matcher_conditions, - url_matcher_schema_filter.Pass())); + url_matcher_schema_filter.Pass(), url_matcher_port_filter.Pass())); return scoped_ptr<WebRequestCondition>( new WebRequestCondition(url_matcher_condition_set, attributes)); } @@ -270,6 +277,42 @@ scoped_ptr<URLMatcherSchemeFilter> WebRequestCondition::CreateURLMatcherScheme( new URLMatcherSchemeFilter(schemas)); } +// static +scoped_ptr<URLMatcherPortFilter> WebRequestCondition::CreateURLMatcherPorts( + const base::Value* value, + std::string* error) { + std::vector<URLMatcherPortFilter::Range> ranges; + const base::ListValue* value_list = NULL; + if (!value->GetAsList(&value_list)) { + *error = kInvalidPortRanges; + return scoped_ptr<URLMatcherPortFilter>(NULL); + } + + for (ListValue::const_iterator i = value_list->begin(); + i != value_list->end(); ++i) { + Value* entry = *i; + int port = 0; + base::ListValue* range = NULL; + if (entry->GetAsInteger(&port)) { + ranges.push_back(URLMatcherPortFilter::CreateRange(port)); + } else if (entry->GetAsList(&range)) { + int from = 0, to = 0; + if (range->GetSize() != 2u || + !range->GetInteger(0, &from) || + !range->GetInteger(1, &to)) { + *error = kInvalidPortRanges; + return scoped_ptr<URLMatcherPortFilter>(NULL); + } + ranges.push_back(URLMatcherPortFilter::CreateRange(from, to)); + } else { + *error = kInvalidPortRanges; + return scoped_ptr<URLMatcherPortFilter>(NULL); + } + } + + return scoped_ptr<URLMatcherPortFilter>(new URLMatcherPortFilter(ranges)); +} + // // WebRequestConditionSet // diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h index 65e2d18..73ec0b2 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h @@ -83,6 +83,9 @@ class WebRequestCondition { static scoped_ptr<URLMatcherSchemeFilter> CreateURLMatcherScheme( const base::Value* value, std::string* error); + static scoped_ptr<URLMatcherPortFilter> CreateURLMatcherPorts( + const base::Value* value, std::string* error); + scoped_refptr<URLMatcherConditionSet> url_matcher_conditions_; WebRequestConditionAttributes condition_attributes_; diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_unittest.cc index de2ecc5..9cfd654 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_unittest.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_unittest.cc @@ -161,4 +161,66 @@ TEST(WebRequestConditionTest, CreateConditionSet) { EXPECT_EQ(0, number_matches); } +TEST(WebRequestConditionTest, TestPortFilter) { + // Necessary for TestURLRequest. + MessageLoop message_loop(MessageLoop::TYPE_IO); + URLMatcher matcher; + + // Allow 80;1000-1010. + ListValue* port_range = new ListValue(); + port_range->Append(Value::CreateIntegerValue(1000)); + port_range->Append(Value::CreateIntegerValue(1010)); + ListValue* port_ranges = new ListValue(); + port_ranges->Append(Value::CreateIntegerValue(80)); + port_ranges->Append(port_range); + + DictionaryValue condition; + condition.Set(keys::kPortsKey, port_ranges); + condition.SetString("host_suffix", "example.com"); + condition.SetString(keys::kInstanceTypeKey, keys::kRequestMatcherType); + + linked_ptr<json_schema_compiler::any::Any> any_condition = + make_linked_ptr(new json_schema_compiler::any::Any); + any_condition->Init(condition); + WebRequestConditionSet::AnyVector conditions; + conditions.push_back(any_condition); + + // Test insertion + std::string error; + scoped_ptr<WebRequestConditionSet> result = + WebRequestConditionSet::Create(matcher.condition_factory(), + conditions, &error); + EXPECT_EQ("", error); + ASSERT_TRUE(result.get()); + EXPECT_EQ(1u, result->conditions().size()); + + // Tell the URLMatcher about our shiny new patterns. + URLMatcherConditionSet::Vector url_matcher_condition_set; + result->GetURLMatcherConditionSets(&url_matcher_condition_set); + matcher.AddConditionSets(url_matcher_condition_set); + + std::set<URLMatcherConditionSet::ID> url_match_ids; + + // Test various URLs. + GURL http_url("http://www.example.com"); + TestURLRequest http_request(http_url, NULL); + url_match_ids = matcher.MatchURL(http_url); + ASSERT_EQ(1u, url_match_ids.size()); + + GURL http_url_80("http://www.example.com:80"); + TestURLRequest http_request_80(http_url_80, NULL); + url_match_ids = matcher.MatchURL(http_url_80); + ASSERT_EQ(1u, url_match_ids.size()); + + GURL http_url_1000("http://www.example.com:1000"); + TestURLRequest http_request_1000(http_url_1000, NULL); + url_match_ids = matcher.MatchURL(http_url_1000); + ASSERT_EQ(1u, url_match_ids.size()); + + GURL http_url_2000("http://www.example.com:2000"); + TestURLRequest http_request_2000(http_url_2000, NULL); + url_match_ids = matcher.MatchURL(http_url_2000); + ASSERT_EQ(0u, url_match_ids.size()); +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc index 8d81b6a..3f03eb0 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc @@ -12,6 +12,7 @@ const char kOnRequest[] = "experimental.webRequest.onRequest"; // Keys of dictionaries. const char kInstanceTypeKey[] = "instanceType"; +const char kPortsKey[] = "ports"; const char kRedirectUrlKey[] = "redirectUrl"; const char kResourceTypeKey[] = "resourceType"; const char kSchemesKey[] = "schemes"; diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h index ff4aa52..ccab4e5 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h @@ -16,6 +16,7 @@ extern const char kOnRequest[]; // Keys of dictionaries. extern const char kInstanceTypeKey[]; +extern const char kPortsKey[]; extern const char kRedirectUrlKey[]; extern const char kResourceTypeKey[]; extern const char kSchemesKey[]; diff --git a/chrome/common/extensions/api/experimental.webRequest.json b/chrome/common/extensions/api/experimental.webRequest.json index d76d112..239a531 100644 --- a/chrome/common/extensions/api/experimental.webRequest.json +++ b/chrome/common/extensions/api/experimental.webRequest.json @@ -92,6 +92,17 @@ "optional": true, "items": { "type": "string" } }, + "ports": { + "type": "array", + "description": "Matches if the port of the URL is contained in any of the specified port lists. For example <code>[80, 443, [1000, 1200]]</code> matches all requests on port 80, 443 and in the range 1000-1200.", + "optional": true, + "items": { + "choices": [ + {"type": "integer", "description": "A specific port."}, + {"type": "array", "items": {"type": "integer"}, "description": "A pair of integers identiying the start and end (both inclusive) of a port range."} + ] + } + }, "resourceType": { "type": "array", "optional": true, diff --git a/chrome/common/extensions/docs/experimental.webRequest.html b/chrome/common/extensions/docs/experimental.webRequest.html index 4e8cee6..85e60e7 100644 --- a/chrome/common/extensions/docs/experimental.webRequest.html +++ b/chrome/common/extensions/docs/experimental.webRequest.html @@ -665,6 +665,36 @@ version of the WebRequest API. Please ignore this until we give notice. </div><div> <div> <dt> + <var>ports</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span id="typeTemplate"> + <span> + <span> + array of <span><span> + <span> + <span>integer or array of integer</span> + </span> + </span></span> + </span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd>Matches if the port of the URL is contained in any of the specified port lists. For example <code>[80, 443, [1000, 1200]]</code> matches all requests on port 80, 443 and in the range 1000-1200.</dd> + <!-- OBJECT PROPERTIES --> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> + </div><div> + <div> + <dt> <var>resourceType</var> <em> <!-- TYPE --> diff --git a/chrome/test/data/extensions/api_test/webrequest/test_declarative.js b/chrome/test/data/extensions/api_test/webrequest/test_declarative.js index dfcd9e8..07ea5c4 100644 --- a/chrome/test/data/extensions/api_test/webrequest/test_declarative.js +++ b/chrome/test/data/extensions/api_test/webrequest/test_declarative.js @@ -7,6 +7,15 @@ var RequestMatcher = chrome.experimental.webRequest.RequestMatcher; var CancelRequest = chrome.experimental.webRequest.CancelRequest; var RedirectRequest = chrome.experimental.webRequest.RedirectRequest; +function getURLHttpSimple() { + return getServerURL("files/extensions/api_test/webrequest/simpleLoad/a.html"); +} + +function getURLHttpComplex() { + return getServerURL( + "files/extensions/api_test/webrequest/complexLoad/a.html"); +} + runTests([ function testCancelRequest() { ignoreUnexpected = true; @@ -15,22 +24,22 @@ runTests([ { label: "onErrorOccurred", event: "onErrorOccurred", details: { - url: getURL("simpleLoad/a.html"), + url: getURLHttpSimple(), fromCache: false, error: "net::ERR_BLOCKED_BY_CLIENT" } }, ], [ ["onCompleted"] ]); - onRequest.addRules( [ {'conditions': [ new RequestMatcher({'path_suffix': ".html", 'resourceType': ["main_frame"], - 'schemes': ["chrome-extension"]})], + 'schemes': ["http"], + 'ports': [testServerPort, [1000, 2000]]})], 'actions': [new CancelRequest()]} ], - function() {navigateAndWait(getURL("simpleLoad/a.html"));} + function() {navigateAndWait(getURLHttpSimple());} ); }, @@ -42,15 +51,15 @@ runTests([ event: "onBeforeRequest", details: { type: "main_frame", - url: getURL("complexLoad/a.html"), - frameUrl: getURL("complexLoad/a.html") + url: getURLHttpComplex(), + frameUrl: getURLHttpComplex() }, }, { label: "onBeforeRedirect", event: "onBeforeRedirect", details: { - url: getURL("complexLoad/a.html"), - redirectUrl: getURL("simpleLoad/a.html"), + url: getURLHttpComplex(), + redirectUrl: getURLHttpSimple(), statusLine: "", statusCode: -1, fromCache: false, @@ -60,17 +69,18 @@ runTests([ event: "onBeforeRequest", details: { type: "main_frame", - url: getURL("simpleLoad/a.html"), - frameUrl: getURL("simpleLoad/a.html"), + url: getURLHttpSimple(), + frameUrl: getURLHttpSimple(), }, }, { label: "onCompleted", event: "onCompleted", details: { - url: getURL("simpleLoad/a.html"), + ip: "127.0.0.1", + url: getURLHttpSimple(), fromCache: false, statusCode: 200, - statusLine: "HTTP/1.1 200 OK", + statusLine: "HTTP/1.0 200 OK", } }, ], @@ -80,9 +90,9 @@ runTests([ onRequest.addRules( [ {'conditions': [new RequestMatcher({'path_suffix': ".html"})], 'actions': [ - new RedirectRequest({'redirectUrl': getURL("simpleLoad/a.html")})]} + new RedirectRequest({'redirectUrl': getURLHttpSimple()})]} ], - function() {navigateAndWait(getURL("complexLoad/a.html"));} + function() {navigateAndWait(getURLHttpComplex());} ); }, ]); |