summaryrefslogtreecommitdiffstats
path: root/net/url_request
diff options
context:
space:
mode:
authorjar@google.com <jar@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-15 21:21:37 +0000
committerjar@google.com <jar@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-15 21:21:37 +0000
commitc631b6aabef4753d124fcda8fcd1ea3d6931803d (patch)
tree2d35566d0b4a6ea39c421c7b7bab9a42a1b6b15f /net/url_request
parent9e82059e9496cd01dc4766197196c9d3330fa842 (diff)
downloadchromium_src-c631b6aabef4753d124fcda8fcd1ea3d6931803d.zip
chromium_src-c631b6aabef4753d124fcda8fcd1ea3d6931803d.tar.gz
chromium_src-c631b6aabef4753d124fcda8fcd1ea3d6931803d.tar.bz2
Add a lot of robustness to SDCH filter decoding
a) Do meta-refresh (and partially disable sdch) when we have an sdch decode error early on (due to lack of dictionary). b) Gracefully handle proxy removal of "gzip" in "content-encoding: sdch,gzip". c) Recover from completely stripped content encoding (in response to a request for which we advertised an SDCH dictionary) by using a filter that can optionally decode sdch with an optional gzip as well. Some field tests have shown problems with this protocol's transit across the ether. The general approach we've adopted is to stop using SDCH on the problematic site when we have problems. This will prevent a malicious site from shutting down all use of SDCH. r=kmixter,openvcdiff,huanr Review URL: http://codereview.chromium.org/6433 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3420 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/url_request')
-rw-r--r--net/url_request/url_request_http_job.cc60
-rw-r--r--net/url_request/url_request_http_job.h1
-rw-r--r--net/url_request/url_request_job.cc4
-rw-r--r--net/url_request/url_request_job.h4
4 files changed, 66 insertions, 3 deletions
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index fe1332d..4539f13 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -173,11 +173,65 @@ bool URLRequestHttpJob::GetContentEncodings(
void* iter = NULL;
while (response_info_->headers->EnumerateHeader(&iter, "Content-Encoding",
&encoding_type)) {
- encoding_types->push_back(encoding_type);
+ encoding_types->push_back(StringToLowerASCII(encoding_type));
}
+
+ // TODO(jar): Transition to returning enums, rather than strings, and perform
+ // all content encoding fixups here, rather than doing some in the
+ // FilterFactor(). Note that enums generated can be more specific than mere
+ // restatement of strings. For example, rather than just having a GZIP
+ // encoding we can have a GZIP_OPTIONAL encoding to help with odd SDCH related
+ // fixups.
+
+ // TODO(jar): Refactor code so that content-encoding error recovery is
+ // testable via unit tests.
+
+ if (!IsSdchResponse())
+ return !encoding_types->empty();
+
+ // If content encoding included SDCH, then everything is fine.
+ if (!encoding_types->empty() && ("sdch" == encoding_types->front()))
+ return !encoding_types->empty();
+
+ // SDCH "search results" protective hack: To make sure we don't break the only
+ // currently deployed SDCH enabled server, be VERY cautious about proxies that
+ // strip all content-encoding to not include sdch. IF we don't see content
+ // encodings that seem to match what we'd expect from a server that asked us
+ // to use a dictionary (and we advertised said dictionary in the GET), then
+ // we set the encoding to (try to) use SDCH to decode. Note that SDCH will
+ // degrade into a pass-through filter if it doesn't have a viable dictionary
+ // hash in its header. Also note that a solo "sdch" will implicitly create
+ // a "sdch,gzip" decoding filter, where the gzip portion will degrade to a
+ // pass through if a gzip header is not encountered. Hence we can replace
+ // "gzip" with "sdch" and "everything will work."
+ // The one failure mode comes when we advertise a dictionary, and the server
+ // tries to *send* a gzipped file (not gzip encode content), and then we could
+ // do a gzip decode :-(. Since current server support does not ever see such
+ // a transfer, we are safe (for now).
+
+ std::string mime_type;
+ GetMimeType(&mime_type);
+ if (std::string::npos != mime_type.find_first_of("text/html")) {
+ // Suspicious case: Advertised dictionary, but server didn't use sdch, even
+ // though it is text_html content.
+ if (encoding_types->empty())
+ SdchManager::SdchErrorRecovery(SdchManager::ADDED_CONTENT_ENCODING);
+ else if (encoding_types->size() == 1)
+ SdchManager::SdchErrorRecovery(SdchManager::FIXED_CONTENT_ENCODING);
+ else
+ SdchManager::SdchErrorRecovery(SdchManager::FIXED_CONTENT_ENCODINGS);
+ encoding_types->clear();
+ encoding_types->push_back("sdch"); // Handle SDCH/GZIP-opt encoding.
+ }
+
return !encoding_types->empty();
}
+bool URLRequestHttpJob::IsSdchResponse() const {
+ return response_info_ &&
+ (request_info_.load_flags & net::LOAD_SDCH_DICTIONARY_ADVERTISED);
+}
+
bool URLRequestHttpJob::IsRedirectResponse(GURL* location,
int* http_status_code) {
if (!response_info_)
@@ -516,9 +570,11 @@ void URLRequestHttpJob::AddExtraHeaders() {
std::string avail_dictionaries;
SdchManager::Global()->GetAvailDictionaryList(request_->url(),
&avail_dictionaries);
- if (!avail_dictionaries.empty())
+ if (!avail_dictionaries.empty()) {
request_info_.extra_headers += "Avail-Dictionary: "
+ avail_dictionaries + "\r\n";
+ request_info_.load_flags |= net::LOAD_SDCH_DICTIONARY_ADVERTISED;
+ }
scoped_ptr<FileVersionInfo> file_version_info(
FileVersionInfo::CreateFileVersionInfoForCurrentModule());
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 908db2c..b984722 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -42,6 +42,7 @@ class URLRequestHttpJob : public URLRequestJob {
virtual bool GetResponseCookies(std::vector<std::string>* cookies);
virtual int GetResponseCode();
virtual bool GetContentEncodings(std::vector<std::string>* encoding_type);
+ virtual bool IsSdchResponse() const;
virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
virtual bool IsSafeRedirect(const GURL& location);
virtual bool NeedsAuth();
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 0501286..f4924bb 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -52,8 +52,10 @@ void URLRequestJob::SetupFilter() {
std::string mime_type;
GetMimeType(&mime_type);
filter_.reset(Filter::Factory(encoding_types, mime_type, kFilterBufSize));
- if (filter_.get())
+ if (filter_.get()) {
filter_->SetURL(request_->url());
+ filter_->SetMimeType(mime_type);
+ }
}
}
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 1e4a089..2df62fd 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -123,6 +123,10 @@ class URLRequestJob : public base::RefCountedThreadSafe<URLRequestJob> {
return false;
}
+ // Find out if this is a response to a request that advertised an SDCH
+ // dictionary. Only makes sense for some types of requests.
+ virtual bool IsSdchResponse() const { return false; }
+
// Called to setup stream filter for this request. An example of filter is
// content encoding/decoding.
void SetupFilter();