Chromium Code Reviews| Index: net/filter/stream_source.cc |
| diff --git a/net/filter/stream_source.cc b/net/filter/stream_source.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f1c27b41db7111874029aab1832ba2060e30b8cd |
| --- /dev/null |
| +++ b/net/filter/stream_source.cc |
| @@ -0,0 +1,96 @@ |
| +// Copyright 2016 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/filter/stream_source.h" |
| + |
| +#include "base/strings/string_util.h" |
| +#include "net/filter/brotli_stream_source.h" |
| +#include "net/filter/gzip_stream_source.h" |
| +#include "net/filter/sdch_stream_source.h" |
| + |
| +namespace { |
| + |
| +const char kDeflate[] = "deflate"; |
| +const char kGZip[] = "gzip"; |
| +const char kSdch[] = "sdch"; |
| +const char kXGZip[] = "x-gzip"; |
| +const char kBrotli[] = "br"; |
| + |
| +enum SourceType { |
| + SOURCE_BROTLI, |
| + SOURCE_DEFLATE, |
| + SOURCE_GZIP, |
| + SOURCE_SDCH, |
| + SOURCE_GZIP_FALLBACK, |
| + SOURCE_INVALID, |
| +}; |
| + |
| +std::vector<SourceType> SourceTypeNamesToTypes( |
| + const std::vector<std::string>& types) { |
| + std::vector<SourceType> result; |
| + for (const auto& type : types) { |
| + if (base::LowerCaseEqualsASCII(type, kBrotli)) { |
| + result.push_back(SOURCE_BROTLI); |
| + } else if (base::LowerCaseEqualsASCII(type, kDeflate)) { |
| + result.push_back(SOURCE_DEFLATE); |
| + } else if (base::LowerCaseEqualsASCII(type, kGZip) || |
| + base::LowerCaseEqualsASCII(type, kXGZip)) { |
| + result.push_back(SOURCE_GZIP); |
| + } else if (base::LowerCaseEqualsASCII(type, kSdch)) { |
| + result.push_back(SOURCE_SDCH); |
| + } |
| + } |
| + return result; |
| +} |
| + |
| +scoped_ptr<net::StreamSource> BuildSource( |
| + scoped_ptr<net::StreamSource> current, |
| + SourceType type, |
| + net::SdchStreamSourceDelegate* delegate) { |
| + if (type == SOURCE_BROTLI) { |
| + scoped_ptr<net::BrotliStreamSource> next( |
| + new net::BrotliStreamSource(std::move(current))); |
| + current = std::move(next); |
| + } else if (type == SOURCE_SDCH) { |
| + scoped_ptr<net::SdchStreamSource> next( |
| + new net::SdchStreamSource(std::move(current), delegate)); |
| + if (next->Init()) |
| + current = std::move(next); |
| + } else if (type == SOURCE_GZIP || type == SOURCE_DEFLATE || |
| + type == SOURCE_GZIP_FALLBACK) { |
| + scoped_ptr<net::GzipStreamSource> next( |
| + new net::GzipStreamSource(std::move(current))); |
| + net::GzipStreamSource::GzipStreamSourceMode mode = |
| + type == SOURCE_DEFLATE |
| + ? net::GzipStreamSource::GZIP_STREAM_SOURCE_DEFLATE |
| + : net::GzipStreamSource::GZIP_STREAM_SOURCE_GZIP; |
| + bool fallback = type == SOURCE_GZIP_FALLBACK; |
| + if (next->Init(mode, fallback)) |
| + current = std::move(next); |
| + } |
| + return current; |
| +} |
| + |
| +} // namespace |
| + |
| +namespace net { |
| + |
| +scoped_ptr<StreamSource> StreamSource::BuildSourceChain( |
| + scoped_ptr<StreamSource> current, |
| + const std::vector<std::string>& type_names, |
| + SdchStreamSourceDelegate* sdch_delegate) { |
| + std::vector<SourceType> types = SourceTypeNamesToTypes(type_names); |
| + |
| + // SDCH-specific hack: if the first filter is SDCH, add a gzip filter in front |
| + // of it in fallback mode. |
| + if (!types.empty() && types.at(0) == SOURCE_SDCH) |
| + types.insert(types.begin(), SOURCE_GZIP_FALLBACK); |
| + |
| + for (const auto& type : types) |
| + current = BuildSource(std::move(current), type, sdch_delegate); |
|
mmenke
2016/02/18 22:58:28
if current ever ends up null after a BuildSource c
xunjieli
2016/03/03 23:00:09
Done.
Randy Smith (Not in Mondays)
2016/03/03 23:05:48
I've managed to lose track of the debate as to wha
|
| + |
| + return current; |
| +} |
| + |
| +} // namespace net |