Home | History | Annotate | Download | only in filter
      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