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 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. 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 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 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 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 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 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 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