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