15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/filter.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/mock_filter_context.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FilterTest : public testing::Test {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(FilterTest, ContentTypeId) {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for basic translation of Content-Encoding, including case variations.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_DEFLATE,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("deflate"));
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_DEFLATE,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("deflAte"));
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("gzip"));
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("GzIp"));
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("x-gzip"));
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("X-GzIp"));
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("sdch"));
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("sDcH"));
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_UNSUPPORTED,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("weird"));
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_UNSUPPORTED,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Filter::ConvertEncodingToType("strange"));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check various fixups that modify content encoding lists.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(FilterTest, ApacheGzip) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockFilterContext filter_context;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetSdchResponse(false);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that redundant gzip mime type removes only solo gzip encoding.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kGzipMime1("application/x-gzip");
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kGzipMime2("application/gzip");
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kGzipMime3("application/x-gunzip");
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> encoding_types;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First show it removes the gzip, given any gzip style mime type.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kGzipMime1);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kGzipMime2);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kGzipMime3);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to be sure it doesn't remove everything when it has such a type.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kGzipMime1);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types.front());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to be sure that gzip can survive with other mime types.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType("other/mime");
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST(FilterTest, GzipContentDispositionFilename) {
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MockFilterContext filter_context;
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  filter_context.SetSdchResponse(false);
88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const std::string kGzipMime("application/x-tar");
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const std::string kContentDisposition("attachment; filename=\"foo.tgz\"");
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const std::string kURL("http://foo.com/getfoo.php");
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::vector<Filter::FilterType> encoding_types;
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  filter_context.SetMimeType(kGzipMime);
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  filter_context.SetURL(GURL(kURL));
97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  filter_context.SetContentDisposition(kContentDisposition);
98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Filter::FixupEncodingTypes(filter_context, &encoding_types);
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ASSERT_EQ(0U, encoding_types.size());
100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(FilterTest, SdchEncoding) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle content encodings including SDCH.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kTextHtmlMime("text/html");
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockFilterContext filter_context;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetSdchResponse(true);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> encoding_types;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for most common encoding, and verify it survives unchanged.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTextHtmlMime);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, encoding_types.size());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types[1]);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unchanged even with other mime types.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType("other/type");
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, encoding_types.size());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types[1]);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Solo SDCH is extended to include optional gunzip.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_SDCH);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, encoding_types.size());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH, encoding_types[0]);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(FilterTest, MissingSdchEncoding) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle interesting case where entire SDCH encoding assertion "got lost."
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kTextHtmlMime("text/html");
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockFilterContext filter_context;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetSdchResponse(true);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> encoding_types;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loss of encoding, but it was an SDCH response with html type.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTextHtmlMime);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, encoding_types.size());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loss of encoding, but it was an SDCH response with a prefix that says it
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was an html type.  Note that it *should* be the case that a precise match
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with "text/html" we be collected by GetMimeType() and passed in, but we
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // coded the fixup defensively (scanning for a prefix of "text/html", so this
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is an example which could survive such confusion in the caller).
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType("text/html; charset=UTF-8");
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, encoding_types.size());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No encoding, but it was an SDCH response with non-html type.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType("other/mime");
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, encoding_types.size());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_SDCH_POSSIBLE, encoding_types[0]);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP_HELPING_SDCH, encoding_types[1]);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(FilterTest, Svgz) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockFilterContext filter_context;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that svgz files are only decompressed when not downloading.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSvgzMime("image/svg+xml");
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSvgzUrl("http://ignore.com/foo.svgz");
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSvgUrl("http://ignore.com/foo.svg");
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> encoding_types;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test svgz extension
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kSvgzMime);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kSvgzUrl));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(true);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kSvgzMime);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kSvgzUrl));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test svg extension
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kSvgzMime);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kSvgUrl));
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(true);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kSvgzMime);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kSvgUrl));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(FilterTest, UnsupportedMimeGzip) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From issue 8170 - handling files with Content-Encoding: x-gzip
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockFilterContext filter_context;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> encoding_types;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kTarMime("application/x-tar");
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kCpioMime("application/x-cpio");
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kTarUrl("http://ignore.com/foo.tar");
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kTargzUrl("http://ignore.com/foo.tar.gz");
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kTgzUrl("http://ignore.com/foo.tgz");
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kBadTgzUrl("http://ignore.com/foo.targz");
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kUrl("http://ignore.com/foo");
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Firefox 3 does not decompress when we have unsupported mime types for
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certain filenames.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTarMime);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kTargzUrl));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTarMime);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kTgzUrl));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kCpioMime);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kTgzUrl));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same behavior for downloads.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(true);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kCpioMime);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kTgzUrl));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unsupported mime type with wrong file name, decompressed.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTarMime);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kUrl));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTarMime);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kTarUrl));
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTarMime);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kBadTgzUrl));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same behavior for downloads.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(true);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kTarMime);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kBadTgzUrl));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(FilterTest, SupportedMimeGzip) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From issue 16430 - Files with supported mime types should be decompressed,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // even though these files end in .gz/.tgz.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockFilterContext filter_context;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> encoding_types;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kGzUrl("http://ignore.com/foo.gz");
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kUrl("http://ignore.com/foo");
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kHtmlMime("text/html");
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kJavascriptMime("text/javascript");
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For files that does not end in .gz/.tgz, we always decompress.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kHtmlMime);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kUrl));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(true);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kHtmlMime);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kUrl));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And also decompress files that end in .gz/.tgz.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kHtmlMime);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kGzUrl));
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(false);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kJavascriptMime);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kGzUrl));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, encoding_types.size());
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Except on downloads, where they just get saved.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.clear();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetDownload(true);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetMimeType(kHtmlMime);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_context.SetURL(GURL(kGzUrl));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FixupEncodingTypes(filter_context, &encoding_types);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(encoding_types.empty());
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
368