diff options
author | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 11:07:19 +0000 |
---|---|---|
committer | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 11:07:19 +0000 |
commit | b85d14c87edb87b9de3b945f001ef268ae5e9197 (patch) | |
tree | 1318d24e37044c58c41dde2d0550ba76aa301745 /net/http | |
parent | b89047e6dd3c90bee61d4043cff3fa487d2c2bbf (diff) | |
download | chromium_src-b85d14c87edb87b9de3b945f001ef268ae5e9197.zip chromium_src-b85d14c87edb87b9de3b945f001ef268ae5e9197.tar.gz chromium_src-b85d14c87edb87b9de3b945f001ef268ae5e9197.tar.bz2 |
Improve merging of header modifications in webRequest.OnHeadersReceived
This CL enables two independent extensions to modify headers of HTTP responses in case they don't conflict (two extension try to edit the same header).
BUG=none
TEST=no
Review URL: http://codereview.chromium.org/8511063
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110900 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_response_headers.cc | 45 | ||||
-rw-r--r-- | net/http/http_response_headers.h | 14 | ||||
-rw-r--r-- | net/http/http_response_headers_unittest.cc | 66 |
3 files changed, 125 insertions, 0 deletions
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index ad8ca3e..88b3f02 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc @@ -294,6 +294,42 @@ void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, Parse(new_raw_headers); } +void HttpResponseHeaders::MergeWithHeadersWithValue( + const std::string& raw_headers, + const std::string& header_to_remove_name, + const std::string& header_to_remove_value) { + std::string header_to_remove_name_lowercase(header_to_remove_name); + StringToLowerASCII(&header_to_remove_name_lowercase); + + std::string new_raw_headers(raw_headers); + for (size_t i = 0; i < parsed_.size(); ++i) { + DCHECK(!parsed_[i].is_continuation()); + + // Locate the start of the next header. + size_t k = i; + while (++k < parsed_.size() && parsed_[k].is_continuation()) {} + --k; + + std::string name(parsed_[i].name_begin, parsed_[i].name_end); + StringToLowerASCII(&name); + std::string value(parsed_[i].value_begin, parsed_[i].value_end); + if (name != header_to_remove_name_lowercase || + value != header_to_remove_value) { + // It's ok to preserve this header in the final result. + new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); + new_raw_headers.push_back('\0'); + } + + i = k; + } + new_raw_headers.push_back('\0'); + + // Make this object hold the new data. + raw_headers_.clear(); + parsed_.clear(); + Parse(new_raw_headers); +} + void HttpResponseHeaders::RemoveHeader(const std::string& name) { // Copy up to the null byte. This just copies the status line. std::string new_raw_headers(raw_headers_.c_str()); @@ -306,6 +342,15 @@ void HttpResponseHeaders::RemoveHeader(const std::string& name) { MergeWithHeaders(new_raw_headers, to_remove); } +void HttpResponseHeaders::RemoveHeaderWithValue(const std::string& name, + const std::string& value) { + // Copy up to the null byte. This just copies the status line. + std::string new_raw_headers(raw_headers_.c_str()); + new_raw_headers.push_back('\0'); + + MergeWithHeadersWithValue(new_raw_headers, name, value); +} + void HttpResponseHeaders::AddHeader(const std::string& header) { CheckDoesNotHaveEmbededNulls(header); DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); diff --git a/net/http/http_response_headers.h b/net/http/http_response_headers.h index 2cdc73e..c29964d 100644 --- a/net/http/http_response_headers.h +++ b/net/http/http_response_headers.h @@ -63,6 +63,10 @@ class NET_EXPORT HttpResponseHeaders // Removes all instances of a particular header. void RemoveHeader(const std::string& name); + // Removes a particular header. The header name is compared + // case-insensitively. + void RemoveHeaderWithValue(const std::string& name, const std::string& value); + // Adds a particular header. |header| has to be a single header without any // EOL termination, just [<header-name>: <header-values>] // If a header with the same name is already stored, the two headers are not @@ -300,6 +304,16 @@ class NET_EXPORT HttpResponseHeaders void MergeWithHeaders(const std::string& raw_headers, const HeaderSet& headers_to_remove); + // Replaces the current headers with the merged version of |raw_headers| and + // the current headers with out the header consisting of + // |header_to_remove_name| and |header_to_remove_value|. Note that + // |header_to_remove_name| is compared case-insensitively. + // Note that the header to remove is removed from the current headers (before + // the merge), not after the merge. + void MergeWithHeadersWithValue(const std::string& raw_headers, + const std::string& header_to_remove_name, + const std::string& header_to_remove_value); + // Adds the values from any 'cache-control: no-cache="foo,bar"' headers. void AddNonCacheableHeaders(HeaderSet* header_names) const; diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc index 4848510..eec259a 100644 --- a/net/http/http_response_headers_unittest.cc +++ b/net/http/http_response_headers_unittest.cc @@ -1624,6 +1624,72 @@ TEST(HttpResponseHeadersTest, RemoveHeader) { } } +TEST(HttpResponseHeadersTest, RemoveIndividualHeader) { + const struct { + const char* orig_headers; + const char* to_remove_name; + const char* to_remove_value; + const char* expected_headers; + } tests[] = { + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Cache-control: max-age=10000\n" + "Content-Length: 450\n", + + "Content-Length", + + "450", + + "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Cache-control: max-age=10000\n" + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive \n" + "Content-Length : 450 \n" + "Cache-control: max-age=10000\n", + + "Content-Length", + + "450", + + "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Cache-control: max-age=10000\n" + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive \n" + "Content-Length: 450\n" + "Cache-control: max-age=10000\n", + + "Content-Length", // Matching name. + + "999", // Mismatching value. + + "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Content-Length: 450\n" + "Cache-control: max-age=10000\n" + }, + + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + std::string orig_headers(tests[i].orig_headers); + HeadersToRaw(&orig_headers); + scoped_refptr<net::HttpResponseHeaders> parsed( + new net::HttpResponseHeaders(orig_headers)); + + std::string name(tests[i].to_remove_name); + std::string value(tests[i].to_remove_value); + parsed->RemoveHeaderWithValue(name, value); + + std::string resulting_headers; + parsed->GetNormalizedHeaders(&resulting_headers); + EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); + } +} + TEST(HttpResponseHeadersTest, ReplaceStatus) { const struct { const char* orig_headers; |