| Index: net/filter/stream_source_util.cc
|
| diff --git a/net/filter/stream_source_util.cc b/net/filter/stream_source_util.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..02ae53f72a64377a8e7d24aeb7f58857125f4032
|
| --- /dev/null
|
| +++ b/net/filter/stream_source_util.cc
|
| @@ -0,0 +1,108 @@
|
| +// 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_util.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"
|
| +#include "net/filter/stream_source.h"
|
| +#include "net/http/http_response_headers.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +const char kDeflate[] = "deflate";
|
| +const char kGZip[] = "gzip";
|
| +const char kSdch[] = "sdch";
|
| +const char kXGZip[] = "x-gzip";
|
| +const char kBrotli[] = "br";
|
| +
|
| +std::unique_ptr<StreamSource> BuildSource(
|
| + std::unique_ptr<StreamSource> previous,
|
| + StreamSource::SourceType type) {
|
| + std::unique_ptr<FilterStreamSource> next = nullptr;
|
| + if (type == StreamSource::TYPE_BROTLI) {
|
| + next = CreateBrotliStreamSource(std::move(previous));
|
| + } else if (type == StreamSource::TYPE_SDCH) {
|
| + next.reset(new SdchStreamSource(std::move(previous), nullptr));
|
| + } else if (type == StreamSource::TYPE_GZIP ||
|
| + type == StreamSource::TYPE_DEFLATE ||
|
| + type == StreamSource::TYPE_GZIP_FALLBACK) {
|
| + GzipStreamSource::GzipStreamSourceMode mode;
|
| + if (type == StreamSource::TYPE_DEFLATE) {
|
| + mode = GzipStreamSource::GZIP_STREAM_SOURCE_DEFLATE;
|
| + } else if (type == StreamSource::TYPE_GZIP) {
|
| + mode = GzipStreamSource::GZIP_STREAM_SOURCE_GZIP;
|
| + } else {
|
| + mode = GzipStreamSource::GZIP_STREAM_SOURCE_GZIP_WITH_FALLBACK;
|
| + }
|
| + next.reset(new GzipStreamSource(std::move(previous), mode));
|
| + }
|
| + if (!next->Init())
|
| + return nullptr;
|
| + return std::move(next);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +std::unique_ptr<StreamSource> StreamSourceUtil::BuildSourceChain(
|
| + std::unique_ptr<StreamSource> previous,
|
| + HttpResponseHeaders* headers) {
|
| + std::string type;
|
| + std::vector<StreamSource::SourceType> types;
|
| + size_t iter = 0;
|
| + while (headers->EnumerateHeader(&iter, "Content-Encoding", &type)) {
|
| + if (base::LowerCaseEqualsASCII(type, kBrotli)) {
|
| + types.push_back(StreamSource::TYPE_BROTLI);
|
| + } else if (base::LowerCaseEqualsASCII(type, kDeflate)) {
|
| + types.push_back(StreamSource::TYPE_DEFLATE);
|
| + } else if (base::LowerCaseEqualsASCII(type, kGZip) ||
|
| + base::LowerCaseEqualsASCII(type, kXGZip)) {
|
| + types.push_back(StreamSource::TYPE_GZIP);
|
| + } else if (base::LowerCaseEqualsASCII(type, kSdch)) {
|
| + types.push_back(StreamSource::TYPE_SDCH);
|
| + }
|
| + }
|
| +
|
| + // 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) == StreamSource::TYPE_SDCH)
|
| + types.insert(types.begin(), StreamSource::TYPE_GZIP_FALLBACK);
|
| +
|
| + for (const auto& type : types) {
|
| + previous = BuildSource(std::move(previous), type);
|
| + if (previous == nullptr)
|
| + return nullptr;
|
| + }
|
| +
|
| + return previous;
|
| +}
|
| +
|
| +std::string StreamSourceUtil::SourceTypeAsString(
|
| + StreamSource::SourceType type) {
|
| + switch (type) {
|
| +#define STREAM_SOURCE_TYPE(label) \
|
| + case StreamSource::TYPE_##label: \
|
| + return #label;
|
| +#include "net/filter/stream_source_type_list.h"
|
| +#undef STREAM_SOURCE_TYPE
|
| + default:
|
| + NOTREACHED();
|
| + return nullptr;
|
| + }
|
| +}
|
| +
|
| +std::string StreamSourceUtil::OrderedStreamSourceList(StreamSource* source) {
|
| + if (source->previous()) {
|
| + return SourceTypeAsString(source->type()) + "," +
|
| + OrderedStreamSourceList(source->previous());
|
| + } else {
|
| + return SourceTypeAsString(source->type());
|
| + }
|
| +}
|
| +
|
| +} // namespace net
|
|
|