diff options
author | yoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-06 19:08:47 +0000 |
---|---|---|
committer | yoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-06 19:08:47 +0000 |
commit | 840eccefff0f2b79e86771216bd71ddde7e5726c (patch) | |
tree | 4fce9a28f4f2aa66c2deccca3dbc7adb18ba629d | |
parent | 8fd9eeeeeb2764568c5d4403bd0c564deb8201df (diff) | |
download | chromium_src-840eccefff0f2b79e86771216bd71ddde7e5726c.zip chromium_src-840eccefff0f2b79e86771216bd71ddde7e5726c.tar.gz chromium_src-840eccefff0f2b79e86771216bd71ddde7e5726c.tar.bz2 |
Add condition attribute for MIME media types from Content-Type header.
This only supports positive tests.
BUG=112155
Review URL: https://chromiumcodereview.appspot.com/10843065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150126 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 230 insertions, 13 deletions
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h index 0a84a84..95dc5b3 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/memory/linked_ptr.h" #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h" +#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h" #include "chrome/common/extensions/matcher/url_matcher.h" namespace extensions { diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc index d79eb3b..c52349d8 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.cc @@ -12,13 +12,16 @@ #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h" #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h" #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" +#include "chrome/common/extensions/extension_error_utils.h" #include "content/public/browser/resource_request_info.h" +#include "net/http/http_util.h" +#include "net/http/http_request_headers.h" #include "net/url_request/url_request.h" namespace { // Error messages. -const char kUnknownConditionAttribute[] = "Unknown matching condition: '%s'"; -const char kInvalidValue[] = "Condition '%s' has an invalid value"; +const char kUnknownConditionAttribute[] = "Unknown matching condition: '*'"; +const char kInvalidValue[] = "Condition '*' has an invalid value"; } namespace helpers = extension_web_request_api_helpers; @@ -38,8 +41,9 @@ WebRequestConditionAttribute::~WebRequestConditionAttribute() {} // static bool WebRequestConditionAttribute::IsKnownType( const std::string& instance_type) { - return WebRequestConditionAttributeResourceType::IsMatchingType( - instance_type); + return + WebRequestConditionAttributeResourceType::IsMatchingType(instance_type) || + WebRequestConditionAttributeContentType::IsMatchingType(instance_type); } // static @@ -50,13 +54,15 @@ WebRequestConditionAttribute::Create( std::string* error) { if (WebRequestConditionAttributeResourceType::IsMatchingType(name)) { return WebRequestConditionAttributeResourceType::Create(name, value, error); + } else if (WebRequestConditionAttributeContentType::IsMatchingType(name)) { + return WebRequestConditionAttributeContentType::Create(name, value, error); } - *error = base::StringPrintf(kUnknownConditionAttribute, name.c_str()); + *error = ExtensionErrorUtils::FormatErrorMessage(kUnknownConditionAttribute, + name); return scoped_ptr<WebRequestConditionAttribute>(NULL); } - // // WebRequestConditionAttributeResourceType // @@ -83,9 +89,10 @@ WebRequestConditionAttributeResourceType::Create( std::string* error) { DCHECK(IsMatchingType(name)); - const ListValue* value_as_list = 0; + const ListValue* value_as_list = NULL; if (!value->GetAsList(&value_as_list)) { - *error = base::StringPrintf(kInvalidValue, keys::kResourceTypeKey); + *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidValue, + keys::kResourceTypeKey); return scoped_ptr<WebRequestConditionAttribute>(NULL); } @@ -97,7 +104,8 @@ WebRequestConditionAttributeResourceType::Create( ResourceType::Type type = ResourceType::LAST_TYPE; if (!value_as_list->GetString(i, &resource_type_string) || !helpers::ParseResourceType(resource_type_string, &type)) { - *error = base::StringPrintf(kInvalidValue, keys::kResourceTypeKey); + *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidValue, + keys::kResourceTypeKey); return scoped_ptr<WebRequestConditionAttribute>(NULL); } passed_types.push_back(type); @@ -130,4 +138,77 @@ WebRequestConditionAttributeResourceType::GetType() const { return CONDITION_RESOURCE_TYPE; } +// +// WebRequestConditionAttributeContentType +// + +WebRequestConditionAttributeContentType:: +WebRequestConditionAttributeContentType( + const std::vector<std::string>& content_types) + : content_types_(content_types) {} + +WebRequestConditionAttributeContentType:: +~WebRequestConditionAttributeContentType() {} + +// static +bool WebRequestConditionAttributeContentType::IsMatchingType( + const std::string& instance_type) { + return instance_type == keys::kContentTypeKey; +} + +// static +scoped_ptr<WebRequestConditionAttribute> +WebRequestConditionAttributeContentType::Create( + const std::string& name, + const base::Value* value, + std::string* error) { + std::vector<std::string> content_types; + + const ListValue* value_as_list = NULL; + if (!value->GetAsList(&value_as_list)) { + *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidValue, + keys::kContentTypeKey); + return scoped_ptr<WebRequestConditionAttribute>(NULL); + } + + for (ListValue::const_iterator it = value_as_list->begin(); + it != value_as_list->end(); ++it) { + std::string content_type; + if (!(*it)->GetAsString(&content_type)) { + *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidValue, + keys::kContentTypeKey); + return scoped_ptr<WebRequestConditionAttribute>(NULL); + } + content_types.push_back(content_type); + } + return scoped_ptr<WebRequestConditionAttribute>( + new WebRequestConditionAttributeContentType(content_types)); +} + +int WebRequestConditionAttributeContentType::GetStages() const { + return ON_HEADERS_RECEIVED; +} + +bool WebRequestConditionAttributeContentType::IsFulfilled( + const WebRequestRule::RequestData& request_data) { + if (!(request_data.stage & GetStages())) + return false; + std::string content_type; + request_data.original_response_headers->GetNormalizedHeader( + net::HttpRequestHeaders::kContentType, &content_type); + std::string mime_type; + std::string charset; + bool had_charset; + net::HttpUtil::ParseContentType( + content_type, &mime_type, &charset, &had_charset, NULL); + + return std::find(content_types_.begin(), content_types_.end(), + mime_type) != content_types_.end(); +} + +WebRequestConditionAttribute::Type +WebRequestConditionAttributeContentType::GetType() const { + return CONDITION_CONTENT_TYPE; +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h index ca420aa..cec4b55 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h @@ -31,7 +31,8 @@ namespace extensions { class WebRequestConditionAttribute { public: enum Type { - CONDITION_RESOURCE_TYPE + CONDITION_RESOURCE_TYPE, + CONDITION_CONTENT_TYPE }; WebRequestConditionAttribute(); @@ -100,6 +101,36 @@ class WebRequestConditionAttributeResourceType DISALLOW_COPY_AND_ASSIGN(WebRequestConditionAttributeResourceType); }; +// Condition that checks whether a response's Content-Type header has a +// certain MIME media type. +class WebRequestConditionAttributeContentType + : public WebRequestConditionAttribute { + public: + virtual ~WebRequestConditionAttributeContentType(); + + static bool IsMatchingType(const std::string& instance_type); + + // Factory method, see WebRequestConditionAttribute::Create. + static scoped_ptr<WebRequestConditionAttribute> Create( + const std::string& name, + const base::Value* value, + std::string* error); + + // Implementation of WebRequestConditionAttribute: + virtual int GetStages() const OVERRIDE; + virtual bool IsFulfilled(const WebRequestRule::RequestData& request_data) + OVERRIDE; + virtual Type GetType() const OVERRIDE; + + private: + explicit WebRequestConditionAttributeContentType( + const std::vector<std::string>& content_types); + + std::vector<std::string> content_types_; + + DISALLOW_COPY_AND_ASSIGN(WebRequestConditionAttributeContentType); +}; + } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_CONDITION_ATTRIBUTE_H_ diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc index 791ac06..641d070 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc @@ -4,12 +4,14 @@ #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h" +#include "base/file_path.h" #include "base/message_loop.h" #include "base/values.h" #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h" #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h" #include "content/public/browser/resource_request_info.h" #include "net/url_request/url_request_test_util.h" +#include "net/test/test_server.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -44,6 +46,12 @@ TEST(WebRequestConditionAttributeTest, CreateConditionAttribute) { EXPECT_FALSE(error.empty()); EXPECT_FALSE(result.get()); + error.clear(); + result = WebRequestConditionAttribute::Create( + keys::kContentTypeKey, &string_value, &error); + EXPECT_FALSE(error.empty()); + EXPECT_FALSE(result.get()); + // Test success error.clear(); result = WebRequestConditionAttribute::Create( @@ -83,4 +91,53 @@ TEST(WebRequestConditionAttributeTest, TestResourceType) { WebRequestRule::RequestData(&url_request_fail, ON_BEFORE_REQUEST))); } +TEST(WebRequestConditionAttributeTest, TestContentType) { + // Necessary for TestURLRequest. + MessageLoop message_loop(MessageLoop::TYPE_IO); + + std::string error; + scoped_ptr<WebRequestConditionAttribute> result; + + net::TestServer test_server( + net::TestServer::TYPE_HTTP, + net::TestServer::kLocalhost, + FilePath(FILE_PATH_LITERAL( + "chrome/test/data/extensions/api_test/webrequest/declarative"))); + ASSERT_TRUE(test_server.Start()); + + TestURLRequestContext context; + TestDelegate delegate; + TestURLRequest url_request(test_server.GetURL("headers.html"), + &delegate, &context); + url_request.Start(); + MessageLoop::current()->Run(); + + ListValue content_types; + content_types.Append(Value::CreateStringValue("text/html")); + scoped_ptr<WebRequestConditionAttribute> attribute_ok = + WebRequestConditionAttribute::Create( + keys::kContentTypeKey, &content_types, &error); + EXPECT_EQ("", error); + ASSERT_TRUE(attribute_ok.get()); + + EXPECT_FALSE(attribute_ok->IsFulfilled( + WebRequestRule::RequestData(&url_request, ON_BEFORE_REQUEST, + url_request.response_headers()))); + EXPECT_TRUE(attribute_ok->IsFulfilled( + WebRequestRule::RequestData(&url_request, ON_HEADERS_RECEIVED, + url_request.response_headers()))); + + content_types.Clear(); + content_types.Append(Value::CreateStringValue("something/invalid")); + scoped_ptr<WebRequestConditionAttribute> attribute_fail = + WebRequestConditionAttribute::Create( + keys::kContentTypeKey, &content_types, &error); + EXPECT_EQ("", error); + ASSERT_TRUE(attribute_fail.get()); + + EXPECT_FALSE(attribute_fail->IsFulfilled( + WebRequestRule::RequestData(&url_request, ON_HEADERS_RECEIVED, + url_request.response_headers()))); +} + } // 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 8ec9d26..5a629b1 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[] = "declarativeWebRequest.onRequest"; // Keys of dictionaries. const char kCookieKey[] = "cookie"; +const char kContentTypeKey[] = "contentType"; const char kDirectionKey[] = "direction"; const char kDomainKey[] = "domain"; const char kExpiresKey[] = "expires"; diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h index 4dc1942..3603591 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h @@ -15,6 +15,7 @@ extern const char kOnRequest[]; // Keys of dictionaries. extern const char kCookieKey[]; +extern const char kContentTypeKey[]; extern const char kDirectionKey[]; extern const char kDomainKey[]; extern const char kExpiresKey[]; diff --git a/chrome/common/extensions/api/declarative_web_request.json b/chrome/common/extensions/api/declarative_web_request.json index 675eebd..2752367 100644 --- a/chrome/common/extensions/api/declarative_web_request.json +++ b/chrome/common/extensions/api/declarative_web_request.json @@ -23,6 +23,12 @@ "description": "Matches if the request type of a request is contained in the list. Requests that cannot match any of the types will be filtered out.", "items": { "type": "string", "enum": ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"] } }, + "contentType": { + "type": "array", + "optional": true, + "description": "Matches if the MIME media type of a response (from the HTTP Content-Type header) is contained in the list.", + "items": { "type": "string" } + }, "instanceType": { "type": "string", "enum": ["declarativeWebRequest.RequestMatcher"], "nodoc": true diff --git a/chrome/common/extensions/docs/extensions/declarativeWebRequest.html b/chrome/common/extensions/docs/extensions/declarativeWebRequest.html index 44ab433..6dc32f0 100644 --- a/chrome/common/extensions/docs/extensions/declarativeWebRequest.html +++ b/chrome/common/extensions/docs/extensions/declarativeWebRequest.html @@ -774,6 +774,36 @@ very fast URL matching algorithm for hundreds of thousands of URLs. <!-- OBJECT EVENT FIELDS --> <!-- FUNCTION PARAMETERS --> </div> + </div><div> + <div> + <dt> + <var>contentType</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span id="typeTemplate"> + <span> + <span> + array of <span><span> + <span> + <span>string</span> + </span> + </span></span> + </span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd>Matches if the MIME media type of a response (from the HTTP Content-Type header) is contained in the list.</dd> + <!-- OBJECT PROPERTIES --> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> </div> </dl> </dd> diff --git a/chrome/test/data/extensions/api_test/webrequest/declarative/headers.html b/chrome/test/data/extensions/api_test/webrequest/declarative/headers.html new file mode 100644 index 0000000..31174e9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/declarative/headers.html @@ -0,0 +1 @@ +Nothing here. See .mock-http-headers. diff --git a/chrome/test/data/extensions/api_test/webrequest/declarative/headers.html.mock-http-headers b/chrome/test/data/extensions/api_test/webrequest/declarative/headers.html.mock-http-headers new file mode 100644 index 0000000..6020fce --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/declarative/headers.html.mock-http-headers @@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Content-Type: text/html; UTF-8 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 f40b735..16bdf3f 100644 --- a/chrome/test/data/extensions/api_test/webrequest/test_declarative.js +++ b/chrome/test/data/extensions/api_test/webrequest/test_declarative.js @@ -51,6 +51,11 @@ function getURLHttpRedirectTest() { "files/extensions/api_test/webrequest/declarative/a.html"); } +function getURLHttpWithHeaders() { + return getServerURL( + "files/extensions/api_test/webrequest/declarative/headers.html"); +} + function getURLSetCookie() { return getServerURL('set-cookie?Foo=Bar'); } @@ -83,7 +88,7 @@ runTests([ { label: "onErrorOccurred", event: "onErrorOccurred", details: { - url: getURLHttpSimple(), + url: getURLHttpWithHeaders(), fromCache: false, error: "net::ERR_BLOCKED_BY_CLIENT" } @@ -98,10 +103,11 @@ runTests([ 'ports': [testServerPort, [1000, 2000]], 'schemes': ["http"] }, - 'resourceType': ["main_frame"]})], + 'resourceType': ["main_frame"], + 'contentType': ["text/html"]})], 'actions': [new CancelRequest()]} ], - function() {navigateAndWait(getURLHttpSimple());} + function() {navigateAndWait(getURLHttpWithHeaders());} ); }, |