1// Copyright (c) 2011 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/mock_filter_context.h"
7#include "testing/gtest/include/gtest/gtest.h"
8
9namespace net {
10
11class FilterTest : public testing::Test {
12};
13
14TEST(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.
39TEST(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
85TEST(FilterTest, SdchEncoding) {
86  // Handle content encodings including SDCH.
87  const std::string kTextHtmlMime("text/html");
88  MockFilterContext filter_context;
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
122TEST(FilterTest, MissingSdchEncoding) {
123  // Handle interesting case where entire SDCH encoding assertion "got lost."
124  const std::string kTextHtmlMime("text/html");
125  MockFilterContext filter_context;
126  filter_context.SetSdchResponse(true);
127
128  std::vector<Filter::FilterType> encoding_types;
129
130  // Loss of encoding, but it was an SDCH response with html type.
131  encoding_types.clear();
132  filter_context.SetMimeType(kTextHtmlMime);
133  Filter::FixupEncodingTypes(filter_context, &encoding_types);
134  ASSERT_EQ(2U, encoding_types.size());
135  EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
136  EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
137
138  // Loss of encoding, but it was an SDCH response with a prefix that says it
139  // was an html type.  Note that it *should* be the case that a precise match
140  // with "text/html" we be collected by GetMimeType() and passed in, but we
141  // coded the fixup defensively (scanning for a prefix of "text/html", so this
142  // is an example which could survive such confusion in the caller).
143  encoding_types.clear();
144  filter_context.SetMimeType("text/html; charset=UTF-8");
145  Filter::FixupEncodingTypes(filter_context, &encoding_types);
146  ASSERT_EQ(2U, encoding_types.size());
147  EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
148  EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
149
150  // No encoding, but it was an SDCH response with non-html type.
151  encoding_types.clear();
152  filter_context.SetMimeType("other/mime");
153  Filter::FixupEncodingTypes(filter_context, &encoding_types);
154  ASSERT_EQ(2U, encoding_types.size());
155  EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
156  EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
157}
158
159TEST(FilterTest, Svgz) {
160  MockFilterContext filter_context;
161
162  // Check that svgz files are only decompressed when not downloading.
163  const std::string kSvgzMime("image/svg+xml");
164  const std::string kSvgzUrl("http://ignore.com/foo.svgz");
165  const std::string kSvgUrl("http://ignore.com/foo.svg");
166  std::vector<Filter::FilterType> encoding_types;
167
168  // Test svgz extension
169  encoding_types.clear();
170  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
171  filter_context.SetDownload(false);
172  filter_context.SetMimeType(kSvgzMime);
173  filter_context.SetURL(GURL(kSvgzUrl));
174  Filter::FixupEncodingTypes(filter_context, &encoding_types);
175  ASSERT_EQ(1U, encoding_types.size());
176  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
177
178  encoding_types.clear();
179  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
180  filter_context.SetDownload(true);
181  filter_context.SetMimeType(kSvgzMime);
182  filter_context.SetURL(GURL(kSvgzUrl));
183  Filter::FixupEncodingTypes(filter_context, &encoding_types);
184  EXPECT_TRUE(encoding_types.empty());
185
186  // Test svg extension
187  encoding_types.clear();
188  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
189  filter_context.SetDownload(false);
190  filter_context.SetMimeType(kSvgzMime);
191  filter_context.SetURL(GURL(kSvgUrl));
192  Filter::FixupEncodingTypes(filter_context, &encoding_types);
193  ASSERT_EQ(1U, encoding_types.size());
194  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
195
196  encoding_types.clear();
197  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
198  filter_context.SetDownload(true);
199  filter_context.SetMimeType(kSvgzMime);
200  filter_context.SetURL(GURL(kSvgUrl));
201  Filter::FixupEncodingTypes(filter_context, &encoding_types);
202  ASSERT_EQ(1U, encoding_types.size());
203  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
204}
205
206TEST(FilterTest, UnsupportedMimeGzip) {
207  // From issue 8170 - handling files with Content-Encoding: x-gzip
208  MockFilterContext filter_context;
209  std::vector<Filter::FilterType> encoding_types;
210  const std::string kTarMime("application/x-tar");
211  const std::string kCpioMime("application/x-cpio");
212  const std::string kTarUrl("http://ignore.com/foo.tar");
213  const std::string kTargzUrl("http://ignore.com/foo.tar.gz");
214  const std::string kTgzUrl("http://ignore.com/foo.tgz");
215  const std::string kBadTgzUrl("http://ignore.com/foo.targz");
216  const std::string kUrl("http://ignore.com/foo");
217
218  // Firefox 3 does not decompress when we have unsupported mime types for
219  // certain filenames.
220  encoding_types.clear();
221  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
222  filter_context.SetDownload(false);
223  filter_context.SetMimeType(kTarMime);
224  filter_context.SetURL(GURL(kTargzUrl));
225  Filter::FixupEncodingTypes(filter_context, &encoding_types);
226  EXPECT_TRUE(encoding_types.empty());
227
228  encoding_types.clear();
229  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
230  filter_context.SetDownload(false);
231  filter_context.SetMimeType(kTarMime);
232  filter_context.SetURL(GURL(kTgzUrl));
233  Filter::FixupEncodingTypes(filter_context, &encoding_types);
234  EXPECT_TRUE(encoding_types.empty());
235
236  encoding_types.clear();
237  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
238  filter_context.SetDownload(false);
239  filter_context.SetMimeType(kCpioMime);
240  filter_context.SetURL(GURL(kTgzUrl));
241  Filter::FixupEncodingTypes(filter_context, &encoding_types);
242  EXPECT_TRUE(encoding_types.empty());
243
244  // Same behavior for downloads.
245  encoding_types.clear();
246  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
247  filter_context.SetDownload(true);
248  filter_context.SetMimeType(kCpioMime);
249  filter_context.SetURL(GURL(kTgzUrl));
250  Filter::FixupEncodingTypes(filter_context, &encoding_types);
251  EXPECT_TRUE(encoding_types.empty());
252
253  // Unsupported mime type with wrong file name, decompressed.
254  encoding_types.clear();
255  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
256  filter_context.SetDownload(false);
257  filter_context.SetMimeType(kTarMime);
258  filter_context.SetURL(GURL(kUrl));
259  Filter::FixupEncodingTypes(filter_context, &encoding_types);
260  ASSERT_EQ(1U, encoding_types.size());
261  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
262
263  encoding_types.clear();
264  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
265  filter_context.SetDownload(false);
266  filter_context.SetMimeType(kTarMime);
267  filter_context.SetURL(GURL(kTarUrl));
268  Filter::FixupEncodingTypes(filter_context, &encoding_types);
269  ASSERT_EQ(1U, encoding_types.size());
270  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
271
272  encoding_types.clear();
273  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
274  filter_context.SetDownload(false);
275  filter_context.SetMimeType(kTarMime);
276  filter_context.SetURL(GURL(kBadTgzUrl));
277  Filter::FixupEncodingTypes(filter_context, &encoding_types);
278  ASSERT_EQ(1U, encoding_types.size());
279  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
280
281  // Same behavior for downloads.
282  encoding_types.clear();
283  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
284  filter_context.SetDownload(true);
285  filter_context.SetMimeType(kTarMime);
286  filter_context.SetURL(GURL(kBadTgzUrl));
287  Filter::FixupEncodingTypes(filter_context, &encoding_types);
288  ASSERT_EQ(1U, encoding_types.size());
289  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
290}
291
292TEST(FilterTest, SupportedMimeGzip) {
293  // From issue 16430 - Files with supported mime types should be decompressed,
294  // even though these files end in .gz/.tgz.
295  MockFilterContext filter_context;
296  std::vector<Filter::FilterType> encoding_types;
297  const std::string kGzUrl("http://ignore.com/foo.gz");
298  const std::string kUrl("http://ignore.com/foo");
299  const std::string kHtmlMime("text/html");
300  const std::string kJavascriptMime("text/javascript");
301
302  // For files that does not end in .gz/.tgz, we always decompress.
303  encoding_types.clear();
304  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
305  filter_context.SetDownload(false);
306  filter_context.SetMimeType(kHtmlMime);
307  filter_context.SetURL(GURL(kUrl));
308  Filter::FixupEncodingTypes(filter_context, &encoding_types);
309  ASSERT_EQ(1U, encoding_types.size());
310  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
311
312  encoding_types.clear();
313  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
314  filter_context.SetDownload(true);
315  filter_context.SetMimeType(kHtmlMime);
316  filter_context.SetURL(GURL(kUrl));
317  Filter::FixupEncodingTypes(filter_context, &encoding_types);
318  ASSERT_EQ(1U, encoding_types.size());
319  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
320
321  // And also decompress files that end in .gz/.tgz.
322  encoding_types.clear();
323  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
324  filter_context.SetDownload(false);
325  filter_context.SetMimeType(kHtmlMime);
326  filter_context.SetURL(GURL(kGzUrl));
327  Filter::FixupEncodingTypes(filter_context, &encoding_types);
328  ASSERT_EQ(1U, encoding_types.size());
329  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
330
331  encoding_types.clear();
332  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
333  filter_context.SetDownload(false);
334  filter_context.SetMimeType(kJavascriptMime);
335  filter_context.SetURL(GURL(kGzUrl));
336  Filter::FixupEncodingTypes(filter_context, &encoding_types);
337  ASSERT_EQ(1U, encoding_types.size());
338  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
339
340  // Except on downloads, where they just get saved.
341  encoding_types.clear();
342  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
343  filter_context.SetDownload(true);
344  filter_context.SetMimeType(kHtmlMime);
345  filter_context.SetURL(GURL(kGzUrl));
346  Filter::FixupEncodingTypes(filter_context, &encoding_types);
347  EXPECT_TRUE(encoding_types.empty());
348}
349
350}  // namespace net
351