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

Side by Side Diff: net/base/filter.cc

Issue 8018: Clean up filter and content encoding handling ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/filter.h ('k') | net/base/filter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/filter.h" 5 #include "net/base/filter.h"
6 6
7 #include "base/string_util.h" 7 #include "base/string_util.h"
8 #include "net/base/gzip_filter.h" 8 #include "net/base/gzip_filter.h"
9 #include "net/base/bzip2_filter.h" 9 #include "net/base/bzip2_filter.h"
10 #include "net/base/sdch_filter.h" 10 #include "net/base/sdch_filter.h"
11 11
12 namespace { 12 namespace {
13 13
14 // Filter types: 14 // Filter types (using canonical lower case only):
15 const char kDeflate[] = "deflate"; 15 const char kDeflate[] = "deflate";
16 const char kGZip[] = "gzip"; 16 const char kGZip[] = "gzip";
17 const char kXGZip[] = "x-gzip"; 17 const char kXGZip[] = "x-gzip";
18 const char kBZip2[] = "bzip2"; 18 const char kBZip2[] = "bzip2";
19 const char kXBZip2[] = "x-bzip2"; 19 const char kXBZip2[] = "x-bzip2";
20 const char kSdch[] = "sdch"; 20 const char kSdch[] = "sdch";
21 // compress and x-compress are currently not supported. If we decide to support 21 // compress and x-compress are currently not supported. If we decide to support
22 // them, we'll need the same mime type compatibility hack we have for gzip. For 22 // them, we'll need the same mime type compatibility hack we have for gzip. For
23 // more information, see Firefox's nsHttpChannel::ProcessNormal. 23 // more information, see Firefox's nsHttpChannel::ProcessNormal.
24 const char kCompress[] = "compress"; 24 const char kCompress[] = "compress";
25 const char kXCompress[] = "x-compress"; 25 const char kXCompress[] = "x-compress";
26 const char kIdentity[] = "identity"; 26 const char kIdentity[] = "identity";
27 const char kUncompressed[] = "uncompressed"; 27 const char kUncompressed[] = "uncompressed";
28 28
29 // Mime types: 29 // Mime types:
30 const char kApplicationXGzip[] = "application/x-gzip"; 30 const char kApplicationXGzip[] = "application/x-gzip";
31 const char kApplicationGzip[] = "application/gzip"; 31 const char kApplicationGzip[] = "application/gzip";
32 const char kApplicationXGunzip[] = "application/x-gunzip"; 32 const char kApplicationXGunzip[] = "application/x-gunzip";
33 const char kApplicationXCompress[] = "application/x-compress"; 33 const char kApplicationXCompress[] = "application/x-compress";
34 const char kApplicationCompress[] = "application/compress"; 34 const char kApplicationCompress[] = "application/compress";
35 const char kTextHtml[] = "text/html";
35 36
36 } // namespace 37 } // namespace
37 38
38 Filter* Filter::Factory(const std::vector<std::string>& filter_types, 39 Filter* Filter::Factory(const std::vector<FilterType>& filter_types,
39 const std::string& mime_type,
40 int buffer_size) { 40 int buffer_size) {
41 if (filter_types.empty() || buffer_size < 0) 41 if (filter_types.empty() || buffer_size < 0)
42 return NULL; 42 return NULL;
43 43
44 std::string safe_mime_type = (filter_types.size() > 1) ? "" : mime_type;
45 Filter* filter_list = NULL; // Linked list of filters. 44 Filter* filter_list = NULL; // Linked list of filters.
46 FilterType type_id = FILTER_TYPE_UNSUPPORTED;
47 for (size_t i = 0; i < filter_types.size(); i++) { 45 for (size_t i = 0; i < filter_types.size(); i++) {
48 type_id = ConvertEncodingToType(filter_types[i], safe_mime_type); 46 filter_list = PrependNewFilter(filter_types[i], buffer_size, filter_list);
49 filter_list = PrependNewFilter(type_id, buffer_size, filter_list);
50 if (!filter_list) 47 if (!filter_list)
51 return NULL; 48 return NULL;
52 } 49 }
53 50
54 // Handle proxy that changes content encoding "sdch,gzip" into "sdch".
55 if (1 == filter_types.size() && FILTER_TYPE_SDCH == type_id)
56 filter_list = PrependNewFilter(FILTER_TYPE_GZIP_HELPING_SDCH, buffer_size,
57 filter_list);
58 return filter_list; 51 return filter_list;
59 } 52 }
60 53
61 // static 54 // static
62 Filter::FilterType Filter::ConvertEncodingToType(const std::string& filter_type, 55 Filter::FilterType Filter::ConvertEncodingToType(
63 const std::string& mime_type) { 56 const std::string& filter_type) {
64 FilterType type_id; 57 FilterType type_id;
65 if (LowerCaseEqualsASCII(filter_type, kDeflate)) { 58 if (LowerCaseEqualsASCII(filter_type, kDeflate)) {
66 type_id = FILTER_TYPE_DEFLATE; 59 type_id = FILTER_TYPE_DEFLATE;
67 } else if (LowerCaseEqualsASCII(filter_type, kGZip) || 60 } else if (LowerCaseEqualsASCII(filter_type, kGZip) ||
68 LowerCaseEqualsASCII(filter_type, kXGZip)) { 61 LowerCaseEqualsASCII(filter_type, kXGZip)) {
69 if (LowerCaseEqualsASCII(mime_type, kApplicationXGzip) || 62 type_id = FILTER_TYPE_GZIP;
70 LowerCaseEqualsASCII(mime_type, kApplicationGzip) ||
71 LowerCaseEqualsASCII(mime_type, kApplicationXGunzip)) {
72 // The server has told us that it sent us gziped content with a gzip
73 // content encoding. Sadly, Apache mistakenly sets these headers for all
74 // .gz files. We match Firefox's nsHttpChannel::ProcessNormal and ignore
75 // the Content-Encoding here.
76 // TODO(jar): Move all this encoding type "fixup" into the
77 // GetContentEncoding() methods. Combine this defaulting with SDCH fixup.
78 type_id = FILTER_TYPE_UNSUPPORTED;
79 } else {
80 type_id = FILTER_TYPE_GZIP;
81 }
82 } else if (LowerCaseEqualsASCII(filter_type, kBZip2) || 63 } else if (LowerCaseEqualsASCII(filter_type, kBZip2) ||
83 LowerCaseEqualsASCII(filter_type, kXBZip2)) { 64 LowerCaseEqualsASCII(filter_type, kXBZip2)) {
84 type_id = FILTER_TYPE_BZIP2; 65 type_id = FILTER_TYPE_BZIP2;
85 } else if (LowerCaseEqualsASCII(filter_type, kSdch)) { 66 } else if (LowerCaseEqualsASCII(filter_type, kSdch)) {
86 type_id = FILTER_TYPE_SDCH; 67 type_id = FILTER_TYPE_SDCH;
87 } else { 68 } else {
88 // Note we also consider "identity" and "uncompressed" UNSUPPORTED as 69 // Note we also consider "identity" and "uncompressed" UNSUPPORTED as
89 // filter should be disabled in such cases. 70 // filter should be disabled in such cases.
90 type_id = FILTER_TYPE_UNSUPPORTED; 71 type_id = FILTER_TYPE_UNSUPPORTED;
91 } 72 }
92 return type_id; 73 return type_id;
93 } 74 }
94 75
95 // static 76 // static
77 void Filter::FixupEncodingTypes(
78 bool is_sdch_response,
79 const std::string& mime_type,
80 std::vector<FilterType>* encoding_types) {
81
82 if ((1 == encoding_types->size()) &&
83 (FILTER_TYPE_GZIP == encoding_types->front())) {
84 if (LowerCaseEqualsASCII(mime_type, kApplicationXGzip) ||
85 LowerCaseEqualsASCII(mime_type, kApplicationGzip) ||
86 LowerCaseEqualsASCII(mime_type, kApplicationXGunzip))
87 // The server has told us that it sent us gziped content with a gzip
88 // content encoding. Sadly, Apache mistakenly sets these headers for all
89 // .gz files. We match Firefox's nsHttpChannel::ProcessNormal and ignore
90 // the Content-Encoding here.
91 encoding_types->clear();
92 return;
93 }
94
95 if (!is_sdch_response)
96 return;
97
98 // If content encoding included SDCH, then everything is fine.
99 if (!encoding_types->empty() &&
100 (FILTER_TYPE_SDCH == encoding_types->front())) {
101 // Some proxies (found currently in Argentina) strip the Content-Encoding
102 // text from "sdch,gzip" to a mere "sdch" without modifying the compressed
103 // payload. To handle this gracefully, we simulate the "probably" deleted
104 // ",gzip" by appending a tentative gzip decode, which will default to a
105 // no-op pass through filter if it doesn't get gzip headers where expected.
106 if (1 == encoding_types->size())
107 encoding_types->push_back(FILTER_TYPE_GZIP_HELPING_SDCH);
108 return;
109 }
110
111 // SDCH "search results" protective hack: To make sure we don't break the only
112 // currently deployed SDCH enabled server! Be VERY cautious about proxies that
113 // strip all content-encoding to not include sdch. IF we don't see content
114 // encodings that seem to match what we'd expect from a server that asked us
115 // to use a dictionary (and we advertised said dictionary in the GET), then
116 // we set the encoding to (try to) use SDCH to decode. Note that SDCH will
117 // degrade into a pass-through filter if it doesn't have a viable dictionary
118 // hash in its header. Also note that a solo "sdch" will implicitly create
119 // a "sdch,gzip" decoding filter, where the gzip portion will degrade to a
120 // pass through if a gzip header is not encountered. Hence we can replace
121 // "gzip" with "sdch" and "everything will work."
122 // The one failure mode comes when we advertise a dictionary, and the server
123 // tries to *send* a gzipped file (not gzip encode content), and then we could
124 // do a gzip decode :-(. Since current server support does not ever see such
125 // a transfer, we are safe (for now).
126 if (LowerCaseEqualsASCII(mime_type, kTextHtml)) {
127 // Suspicious case: Advertised dictionary, but server didn't use sdch, even
128 // though it is text_html content.
129 if (encoding_types->empty())
130 SdchManager::SdchErrorRecovery(SdchManager::ADDED_CONTENT_ENCODING);
131 else if (1 == encoding_types->size())
132 SdchManager::SdchErrorRecovery(SdchManager::FIXED_CONTENT_ENCODING);
133 else
134 SdchManager::SdchErrorRecovery(SdchManager::FIXED_CONTENT_ENCODINGS);
135 encoding_types->clear();
136 encoding_types->push_back(FILTER_TYPE_SDCH);
137 encoding_types->push_back(FILTER_TYPE_GZIP_HELPING_SDCH);
138 return;
139 }
140
141 // It didn't have SDCH encoding... but it wasn't HTML... so maybe it really
142 // wasn't SDCH encoded. It would be nice if we knew this, and didn't bother
143 // to propose a dictionary etc., but current SDCH spec does not provide a nice
144 // way for us to conclude that. Perhaps in the future, this case will be much
145 // more rare.
146 return;
147 }
148
149 // static
96 Filter* Filter::PrependNewFilter(FilterType type_id, int buffer_size, 150 Filter* Filter::PrependNewFilter(FilterType type_id, int buffer_size,
97 Filter* filter_list) { 151 Filter* filter_list) {
98 Filter* first_filter = NULL; // Soon to be start of chain. 152 Filter* first_filter = NULL; // Soon to be start of chain.
99 switch (type_id) { 153 switch (type_id) {
100 case FILTER_TYPE_GZIP_HELPING_SDCH: 154 case FILTER_TYPE_GZIP_HELPING_SDCH:
101 case FILTER_TYPE_DEFLATE: 155 case FILTER_TYPE_DEFLATE:
102 case FILTER_TYPE_GZIP: { 156 case FILTER_TYPE_GZIP: {
103 scoped_ptr<GZipFilter> gz_filter(new GZipFilter()); 157 scoped_ptr<GZipFilter> gz_filter(new GZipFilter());
104 if (gz_filter->InitBuffer(buffer_size)) { 158 if (gz_filter->InitBuffer(buffer_size)) {
105 if (gz_filter->InitDecoding(type_id)) { 159 if (gz_filter->InitDecoding(type_id)) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 stream_data_len_ = stream_data_len; 294 stream_data_len_ = stream_data_len;
241 return true; 295 return true;
242 } 296 }
243 297
244 void Filter::SetURL(const GURL& url) { 298 void Filter::SetURL(const GURL& url) {
245 url_ = url; 299 url_ = url;
246 if (next_filter_.get()) 300 if (next_filter_.get())
247 next_filter_->SetURL(url); 301 next_filter_->SetURL(url);
248 } 302 }
249 303
250 void Filter::SetMimeType(std::string& mime_type) { 304 void Filter::SetMimeType(const std::string& mime_type) {
251 mime_type_ = mime_type; 305 mime_type_ = mime_type;
252 if (next_filter_.get()) 306 if (next_filter_.get())
253 next_filter_->SetMimeType(mime_type); 307 next_filter_->SetMimeType(mime_type);
254 } 308 }
255 309
OLDNEW
« no previous file with comments | « net/base/filter.h ('k') | net/base/filter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698