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
3 // found in the LICENSE file.
4
5 #include "net/base/filter.h"
6 #include "net/base/filter_unittest.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8
9 class FilterTest : public testing::Test {
10 };
11
TEST(FilterTest,ContentTypeId)12 TEST(FilterTest, ContentTypeId) {
13 // Check for basic translation of Content-Encoding, including case variations.
14 EXPECT_EQ(Filter::FILTER_TYPE_DEFLATE,
15 Filter::ConvertEncodingToType("deflate"));
16 EXPECT_EQ(Filter::FILTER_TYPE_DEFLATE,
17 Filter::ConvertEncodingToType("deflAte"));
18 EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
19 Filter::ConvertEncodingToType("gzip"));
20 EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
21 Filter::ConvertEncodingToType("GzIp"));
22 EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
23 Filter::ConvertEncodingToType("x-gzip"));
24 EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
25 Filter::ConvertEncodingToType("X-GzIp"));
26 EXPECT_EQ(Filter::FILTER_TYPE_SDCH,
27 Filter::ConvertEncodingToType("sdch"));
28 EXPECT_EQ(Filter::FILTER_TYPE_SDCH,
29 Filter::ConvertEncodingToType("sDcH"));
30 EXPECT_EQ(Filter::FILTER_TYPE_UNSUPPORTED,
31 Filter::ConvertEncodingToType("weird"));
32 EXPECT_EQ(Filter::FILTER_TYPE_UNSUPPORTED,
33 Filter::ConvertEncodingToType("strange"));
34 }
35
36 // Check various fixups that modify content encoding lists.
TEST(FilterTest,ApacheGzip)37 TEST(FilterTest, ApacheGzip) {
38 const int kInputBufferSize(100);
39 MockFilterContext filter_context(kInputBufferSize);
40 filter_context.SetSdchResponse(false);
41
42 // Check that redundant gzip mime type removes only solo gzip encoding.
43 const std::string kGzipMime1("application/x-gzip");
44 const std::string kGzipMime2("application/gzip");
45 const std::string kGzipMime3("application/x-gunzip");
46 std::vector<Filter::FilterType> encoding_types;
47
48 // First show it removes the gzip, given any gzip style mime type.
49 encoding_types.clear();
50 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
51 filter_context.SetMimeType(kGzipMime1);
52 Filter::FixupEncodingTypes(filter_context, &encoding_types);
53 EXPECT_TRUE(encoding_types.empty());
54
55 encoding_types.clear();
56 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
57 filter_context.SetMimeType(kGzipMime2);
58 Filter::FixupEncodingTypes(filter_context, &encoding_types);
59 EXPECT_TRUE(encoding_types.empty());
60
61 encoding_types.clear();
62 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
63 filter_context.SetMimeType(kGzipMime3);
64 Filter::FixupEncodingTypes(filter_context, &encoding_types);
65 EXPECT_TRUE(encoding_types.empty());
66
67 // Check to be sure it doesn't remove everything when it has such a type.
68 encoding_types.clear();
69 encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
70 filter_context.SetMimeType(kGzipMime1);
71 Filter::FixupEncodingTypes(filter_context, &encoding_types);
72 ASSERT_EQ(1U, encoding_types.size());
73 EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types.front());
74
75 // Check to be sure that gzip can survive with other mime types.
76 encoding_types.clear();
77 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
78 filter_context.SetMimeType("other/mime");
79 Filter::FixupEncodingTypes(filter_context, &encoding_types);
80 ASSERT_EQ(1U, encoding_types.size());
81 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
82 }
83
TEST(FilterTest,SdchEncoding)84 TEST(FilterTest, SdchEncoding) {
85 // Handle content encodings including SDCH.
86 const std::string kTextHtmlMime("text/html");
87 const int kInputBufferSize(100);
88 MockFilterContext filter_context(kInputBufferSize);
89 filter_context.SetSdchResponse(true);
90
91 std::vector<Filter::FilterType> encoding_types;
92
93 // Check for most common encoding, and verify it survives unchanged.
94 encoding_types.clear();
95 encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
96 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
97 filter_context.SetMimeType(kTextHtmlMime);
98 Filter::FixupEncodingTypes(filter_context, &encoding_types);
99 ASSERT_EQ(2U, encoding_types.size());
100 EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]);
101 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types[1]);
102
103 // Unchanged even with other mime types.
104 encoding_types.clear();
105 encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
106 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
107 filter_context.SetMimeType("other/type");
108 Filter::FixupEncodingTypes(filter_context, &encoding_types);
109 ASSERT_EQ(2U, encoding_types.size());
110 EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]);
111 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types[1]);
112
113 // Solo SDCH is extended to include optional gunzip.
114 encoding_types.clear();
115 encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
116 Filter::FixupEncodingTypes(filter_context, &encoding_types);
117 ASSERT_EQ(2U, encoding_types.size());
118 EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]);
119 EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
120 }
121
TEST(FilterTest,MissingSdchEncoding)122 TEST(FilterTest, MissingSdchEncoding) {
123 // Handle interesting case where entire SDCH encoding assertion "got lost."
124 const std::string kTextHtmlMime("text/html");
125 const int kInputBufferSize(100);
126 MockFilterContext filter_context(kInputBufferSize);
127 filter_context.SetSdchResponse(true);
128
129 std::vector<Filter::FilterType> encoding_types;
130
131 // Loss of encoding, but it was an SDCH response with html type.
132 encoding_types.clear();
133 filter_context.SetMimeType(kTextHtmlMime);
134 Filter::FixupEncodingTypes(filter_context, &encoding_types);
135 ASSERT_EQ(2U, encoding_types.size());
136 EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
137 EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
138
139 // Loss of encoding, but it was an SDCH response with a prefix that says it
140 // was an html type. Note that it *should* be the case that a precise match
141 // with "text/html" we be collected by GetMimeType() and passed in, but we
142 // coded the fixup defensively (scanning for a prefix of "text/html", so this
143 // is an example which could survive such confusion in the caller).
144 encoding_types.clear();
145 filter_context.SetMimeType("text/html; charset=UTF-8");
146 Filter::FixupEncodingTypes(filter_context, &encoding_types);
147 ASSERT_EQ(2U, encoding_types.size());
148 EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
149 EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
150
151 // No encoding, but it was an SDCH response with non-html type.
152 encoding_types.clear();
153 filter_context.SetMimeType("other/mime");
154 Filter::FixupEncodingTypes(filter_context, &encoding_types);
155 ASSERT_EQ(2U, encoding_types.size());
156 EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
157 EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
158 }
159
TEST(FilterTest,Svgz)160 TEST(FilterTest, Svgz) {
161 const int kInputBufferSize(100);
162 MockFilterContext filter_context(kInputBufferSize);
163
164 // Check that svgz files are only decompressed when not downloading.
165 const std::string kSvgzMime("image/svg+xml");
166 const std::string kSvgzUrl("http://ignore.com/foo.svgz");
167 const std::string kSvgUrl("http://ignore.com/foo.svg");
168 std::vector<Filter::FilterType> encoding_types;
169
170 // Test svgz extension
171 encoding_types.clear();
172 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
173 filter_context.SetDownload(false);
174 filter_context.SetMimeType(kSvgzMime);
175 filter_context.SetURL(GURL(kSvgzUrl));
176 Filter::FixupEncodingTypes(filter_context, &encoding_types);
177 ASSERT_EQ(1U, encoding_types.size());
178 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
179
180 encoding_types.clear();
181 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
182 filter_context.SetDownload(true);
183 filter_context.SetMimeType(kSvgzMime);
184 filter_context.SetURL(GURL(kSvgzUrl));
185 Filter::FixupEncodingTypes(filter_context, &encoding_types);
186 EXPECT_TRUE(encoding_types.empty());
187
188 // Test svg extension
189 encoding_types.clear();
190 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
191 filter_context.SetDownload(false);
192 filter_context.SetMimeType(kSvgzMime);
193 filter_context.SetURL(GURL(kSvgUrl));
194 Filter::FixupEncodingTypes(filter_context, &encoding_types);
195 ASSERT_EQ(1U, encoding_types.size());
196 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
197
198 encoding_types.clear();
199 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
200 filter_context.SetDownload(true);
201 filter_context.SetMimeType(kSvgzMime);
202 filter_context.SetURL(GURL(kSvgUrl));
203 Filter::FixupEncodingTypes(filter_context, &encoding_types);
204 ASSERT_EQ(1U, encoding_types.size());
205 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
206 }
207
TEST(FilterTest,UnsupportedMimeGzip)208 TEST(FilterTest, UnsupportedMimeGzip) {
209 // From issue 8170 - handling files with Content-Encoding: x-gzip
210 const int kInputBufferSize(100);
211 MockFilterContext filter_context(kInputBufferSize);
212 std::vector<Filter::FilterType> encoding_types;
213 const std::string kTarMime("application/x-tar");
214 const std::string kCpioMime("application/x-cpio");
215 const std::string kTarUrl("http://ignore.com/foo.tar");
216 const std::string kTargzUrl("http://ignore.com/foo.tar.gz");
217 const std::string kTgzUrl("http://ignore.com/foo.tgz");
218 const std::string kBadTgzUrl("http://ignore.com/foo.targz");
219 const std::string kUrl("http://ignore.com/foo");
220
221 // Firefox 3 does not decompress when we have unsupported mime types for
222 // certain filenames.
223 encoding_types.clear();
224 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
225 filter_context.SetDownload(false);
226 filter_context.SetMimeType(kTarMime);
227 filter_context.SetURL(GURL(kTargzUrl));
228 Filter::FixupEncodingTypes(filter_context, &encoding_types);
229 EXPECT_TRUE(encoding_types.empty());
230
231 encoding_types.clear();
232 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
233 filter_context.SetDownload(false);
234 filter_context.SetMimeType(kTarMime);
235 filter_context.SetURL(GURL(kTgzUrl));
236 Filter::FixupEncodingTypes(filter_context, &encoding_types);
237 EXPECT_TRUE(encoding_types.empty());
238
239 encoding_types.clear();
240 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
241 filter_context.SetDownload(false);
242 filter_context.SetMimeType(kCpioMime);
243 filter_context.SetURL(GURL(kTgzUrl));
244 Filter::FixupEncodingTypes(filter_context, &encoding_types);
245 EXPECT_TRUE(encoding_types.empty());
246
247 // Same behavior for downloads.
248 encoding_types.clear();
249 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
250 filter_context.SetDownload(true);
251 filter_context.SetMimeType(kCpioMime);
252 filter_context.SetURL(GURL(kTgzUrl));
253 Filter::FixupEncodingTypes(filter_context, &encoding_types);
254 EXPECT_TRUE(encoding_types.empty());
255
256 // Unsupported mime type with wrong file name, decompressed.
257 encoding_types.clear();
258 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
259 filter_context.SetDownload(false);
260 filter_context.SetMimeType(kTarMime);
261 filter_context.SetURL(GURL(kUrl));
262 Filter::FixupEncodingTypes(filter_context, &encoding_types);
263 ASSERT_EQ(1U, encoding_types.size());
264 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
265
266 encoding_types.clear();
267 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
268 filter_context.SetDownload(false);
269 filter_context.SetMimeType(kTarMime);
270 filter_context.SetURL(GURL(kTarUrl));
271 Filter::FixupEncodingTypes(filter_context, &encoding_types);
272 ASSERT_EQ(1U, encoding_types.size());
273 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
274
275 encoding_types.clear();
276 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
277 filter_context.SetDownload(false);
278 filter_context.SetMimeType(kTarMime);
279 filter_context.SetURL(GURL(kBadTgzUrl));
280 Filter::FixupEncodingTypes(filter_context, &encoding_types);
281 ASSERT_EQ(1U, encoding_types.size());
282 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
283
284 // Same behavior for downloads.
285 encoding_types.clear();
286 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
287 filter_context.SetDownload(true);
288 filter_context.SetMimeType(kTarMime);
289 filter_context.SetURL(GURL(kBadTgzUrl));
290 Filter::FixupEncodingTypes(filter_context, &encoding_types);
291 ASSERT_EQ(1U, encoding_types.size());
292 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
293 }
294
TEST(FilterTest,SupportedMimeGzip)295 TEST(FilterTest, SupportedMimeGzip) {
296 // From issue 16430 - Files with supported mime types should be decompressed,
297 // even though these files end in .gz/.tgz.
298 const int kInputBufferSize(100);
299 MockFilterContext filter_context(kInputBufferSize);
300 std::vector<Filter::FilterType> encoding_types;
301 const std::string kGzUrl("http://ignore.com/foo.gz");
302 const std::string kUrl("http://ignore.com/foo");
303 const std::string kHtmlMime("text/html");
304 const std::string kJavascriptMime("text/javascript");
305
306 // For files that does not end in .gz/.tgz, we always decompress.
307 encoding_types.clear();
308 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
309 filter_context.SetDownload(false);
310 filter_context.SetMimeType(kHtmlMime);
311 filter_context.SetURL(GURL(kUrl));
312 Filter::FixupEncodingTypes(filter_context, &encoding_types);
313 ASSERT_EQ(1U, encoding_types.size());
314 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
315
316 encoding_types.clear();
317 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
318 filter_context.SetDownload(true);
319 filter_context.SetMimeType(kHtmlMime);
320 filter_context.SetURL(GURL(kUrl));
321 Filter::FixupEncodingTypes(filter_context, &encoding_types);
322 ASSERT_EQ(1U, encoding_types.size());
323 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
324
325 // And also decompress files that end in .gz/.tgz.
326 encoding_types.clear();
327 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
328 filter_context.SetDownload(false);
329 filter_context.SetMimeType(kHtmlMime);
330 filter_context.SetURL(GURL(kGzUrl));
331 Filter::FixupEncodingTypes(filter_context, &encoding_types);
332 ASSERT_EQ(1U, encoding_types.size());
333 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
334
335 encoding_types.clear();
336 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
337 filter_context.SetDownload(false);
338 filter_context.SetMimeType(kJavascriptMime);
339 filter_context.SetURL(GURL(kGzUrl));
340 Filter::FixupEncodingTypes(filter_context, &encoding_types);
341 ASSERT_EQ(1U, encoding_types.size());
342 EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
343
344 // Except on downloads, where they just get saved.
345 encoding_types.clear();
346 encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
347 filter_context.SetDownload(true);
348 filter_context.SetMimeType(kHtmlMime);
349 filter_context.SetURL(GURL(kGzUrl));
350 Filter::FixupEncodingTypes(filter_context, &encoding_types);
351 EXPECT_TRUE(encoding_types.empty());
352 }
353