// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/base/filter.h" #include "net/base/mock_filter_context.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { class FilterTest : public testing::Test { }; TEST(FilterTest, ContentTypeId) { // Check for basic translation of Content-Encoding, including case variations. EXPECT_EQ(Filter::FILTER_TYPE_DEFLATE, Filter::ConvertEncodingToType("deflate")); EXPECT_EQ(Filter::FILTER_TYPE_DEFLATE, Filter::ConvertEncodingToType("deflAte")); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, Filter::ConvertEncodingToType("gzip")); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, Filter::ConvertEncodingToType("GzIp")); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, Filter::ConvertEncodingToType("x-gzip")); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, Filter::ConvertEncodingToType("X-GzIp")); EXPECT_EQ(Filter::FILTER_TYPE_SDCH, Filter::ConvertEncodingToType("sdch")); EXPECT_EQ(Filter::FILTER_TYPE_SDCH, Filter::ConvertEncodingToType("sDcH")); EXPECT_EQ(Filter::FILTER_TYPE_UNSUPPORTED, Filter::ConvertEncodingToType("weird")); EXPECT_EQ(Filter::FILTER_TYPE_UNSUPPORTED, Filter::ConvertEncodingToType("strange")); } // Check various fixups that modify content encoding lists. TEST(FilterTest, ApacheGzip) { MockFilterContext filter_context; filter_context.SetSdchResponse(false); // Check that redundant gzip mime type removes only solo gzip encoding. const std::string kGzipMime1("application/x-gzip"); const std::string kGzipMime2("application/gzip"); const std::string kGzipMime3("application/x-gunzip"); std::vector encoding_types; // First show it removes the gzip, given any gzip style mime type. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetMimeType(kGzipMime1); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetMimeType(kGzipMime2); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetMimeType(kGzipMime3); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); // Check to be sure it doesn't remove everything when it has such a type. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_SDCH); filter_context.SetMimeType(kGzipMime1); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types.front()); // Check to be sure that gzip can survive with other mime types. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetMimeType("other/mime"); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); } TEST(FilterTest, SdchEncoding) { // Handle content encodings including SDCH. const std::string kTextHtmlMime("text/html"); MockFilterContext filter_context; filter_context.SetSdchResponse(true); std::vector encoding_types; // Check for most common encoding, and verify it survives unchanged. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_SDCH); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetMimeType(kTextHtmlMime); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(2U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types[1]); // Unchanged even with other mime types. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_SDCH); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetMimeType("other/type"); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(2U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types[1]); // Solo SDCH is extended to include optional gunzip. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_SDCH); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(2U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]); EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]); } TEST(FilterTest, MissingSdchEncoding) { // Handle interesting case where entire SDCH encoding assertion "got lost." const std::string kTextHtmlMime("text/html"); MockFilterContext filter_context; filter_context.SetSdchResponse(true); std::vector encoding_types; // Loss of encoding, but it was an SDCH response with html type. encoding_types.clear(); filter_context.SetMimeType(kTextHtmlMime); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(2U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]); EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]); // Loss of encoding, but it was an SDCH response with a prefix that says it // was an html type. Note that it *should* be the case that a precise match // with "text/html" we be collected by GetMimeType() and passed in, but we // coded the fixup defensively (scanning for a prefix of "text/html", so this // is an example which could survive such confusion in the caller). encoding_types.clear(); filter_context.SetMimeType("text/html; charset=UTF-8"); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(2U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]); EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]); // No encoding, but it was an SDCH response with non-html type. encoding_types.clear(); filter_context.SetMimeType("other/mime"); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(2U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]); EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]); } TEST(FilterTest, Svgz) { MockFilterContext filter_context; // Check that svgz files are only decompressed when not downloading. const std::string kSvgzMime("image/svg+xml"); const std::string kSvgzUrl("http://ignore.com/foo.svgz"); const std::string kSvgUrl("http://ignore.com/foo.svg"); std::vector encoding_types; // Test svgz extension encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kSvgzMime); filter_context.SetURL(GURL(kSvgzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(true); filter_context.SetMimeType(kSvgzMime); filter_context.SetURL(GURL(kSvgzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); // Test svg extension encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kSvgzMime); filter_context.SetURL(GURL(kSvgUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(true); filter_context.SetMimeType(kSvgzMime); filter_context.SetURL(GURL(kSvgUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); } TEST(FilterTest, UnsupportedMimeGzip) { // From issue 8170 - handling files with Content-Encoding: x-gzip MockFilterContext filter_context; std::vector encoding_types; const std::string kTarMime("application/x-tar"); const std::string kCpioMime("application/x-cpio"); const std::string kTarUrl("http://ignore.com/foo.tar"); const std::string kTargzUrl("http://ignore.com/foo.tar.gz"); const std::string kTgzUrl("http://ignore.com/foo.tgz"); const std::string kBadTgzUrl("http://ignore.com/foo.targz"); const std::string kUrl("http://ignore.com/foo"); // Firefox 3 does not decompress when we have unsupported mime types for // certain filenames. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kTarMime); filter_context.SetURL(GURL(kTargzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kTarMime); filter_context.SetURL(GURL(kTgzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kCpioMime); filter_context.SetURL(GURL(kTgzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); // Same behavior for downloads. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(true); filter_context.SetMimeType(kCpioMime); filter_context.SetURL(GURL(kTgzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); // Unsupported mime type with wrong file name, decompressed. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kTarMime); filter_context.SetURL(GURL(kUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kTarMime); filter_context.SetURL(GURL(kTarUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kTarMime); filter_context.SetURL(GURL(kBadTgzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); // Same behavior for downloads. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(true); filter_context.SetMimeType(kTarMime); filter_context.SetURL(GURL(kBadTgzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); } TEST(FilterTest, SupportedMimeGzip) { // From issue 16430 - Files with supported mime types should be decompressed, // even though these files end in .gz/.tgz. MockFilterContext filter_context; std::vector encoding_types; const std::string kGzUrl("http://ignore.com/foo.gz"); const std::string kUrl("http://ignore.com/foo"); const std::string kHtmlMime("text/html"); const std::string kJavascriptMime("text/javascript"); // For files that does not end in .gz/.tgz, we always decompress. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kHtmlMime); filter_context.SetURL(GURL(kUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(true); filter_context.SetMimeType(kHtmlMime); filter_context.SetURL(GURL(kUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); // And also decompress files that end in .gz/.tgz. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kHtmlMime); filter_context.SetURL(GURL(kGzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(false); filter_context.SetMimeType(kJavascriptMime); filter_context.SetURL(GURL(kGzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); ASSERT_EQ(1U, encoding_types.size()); EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front()); // Except on downloads, where they just get saved. encoding_types.clear(); encoding_types.push_back(Filter::FILTER_TYPE_GZIP); filter_context.SetDownload(true); filter_context.SetMimeType(kHtmlMime); filter_context.SetURL(GURL(kGzUrl)); Filter::FixupEncodingTypes(filter_context, &encoding_types); EXPECT_TRUE(encoding_types.empty()); } } // namespace net