| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 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/stream_source_util.h" |
| 6 |
| 7 #include "base/strings/string_util.h" |
| 8 #include "net/filter/brotli_stream_source.h" |
| 9 #include "net/filter/gzip_stream_source.h" |
| 10 #include "net/filter/sdch_stream_source.h" |
| 11 #include "net/filter/stream_source.h" |
| 12 #include "net/http/http_response_headers.h" |
| 13 |
| 14 namespace net { |
| 15 |
| 16 namespace { |
| 17 |
| 18 const char kDeflate[] = "deflate"; |
| 19 const char kGZip[] = "gzip"; |
| 20 const char kSdch[] = "sdch"; |
| 21 const char kXGZip[] = "x-gzip"; |
| 22 const char kBrotli[] = "br"; |
| 23 |
| 24 std::unique_ptr<StreamSource> BuildSource( |
| 25 std::unique_ptr<StreamSource> previous, |
| 26 StreamSource::SourceType type) { |
| 27 std::unique_ptr<FilterStreamSource> next = nullptr; |
| 28 if (type == StreamSource::TYPE_BROTLI) { |
| 29 next = CreateBrotliStreamSource(std::move(previous)); |
| 30 } else if (type == StreamSource::TYPE_SDCH) { |
| 31 next.reset(new SdchStreamSource(std::move(previous), nullptr)); |
| 32 } else if (type == StreamSource::TYPE_GZIP || |
| 33 type == StreamSource::TYPE_DEFLATE || |
| 34 type == StreamSource::TYPE_GZIP_FALLBACK) { |
| 35 GzipStreamSource::GzipStreamSourceMode mode; |
| 36 if (type == StreamSource::TYPE_DEFLATE) { |
| 37 mode = GzipStreamSource::GZIP_STREAM_SOURCE_DEFLATE; |
| 38 } else if (type == StreamSource::TYPE_GZIP) { |
| 39 mode = GzipStreamSource::GZIP_STREAM_SOURCE_GZIP; |
| 40 } else { |
| 41 mode = GzipStreamSource::GZIP_STREAM_SOURCE_GZIP_WITH_FALLBACK; |
| 42 } |
| 43 next.reset(new GzipStreamSource(std::move(previous), mode)); |
| 44 } |
| 45 if (!next->Init()) |
| 46 return nullptr; |
| 47 return std::move(next); |
| 48 } |
| 49 |
| 50 } // namespace |
| 51 |
| 52 std::unique_ptr<StreamSource> StreamSourceUtil::BuildSourceChain( |
| 53 std::unique_ptr<StreamSource> previous, |
| 54 HttpResponseHeaders* headers) { |
| 55 std::string type; |
| 56 std::vector<StreamSource::SourceType> types; |
| 57 size_t iter = 0; |
| 58 while (headers->EnumerateHeader(&iter, "Content-Encoding", &type)) { |
| 59 if (base::LowerCaseEqualsASCII(type, kBrotli)) { |
| 60 types.push_back(StreamSource::TYPE_BROTLI); |
| 61 } else if (base::LowerCaseEqualsASCII(type, kDeflate)) { |
| 62 types.push_back(StreamSource::TYPE_DEFLATE); |
| 63 } else if (base::LowerCaseEqualsASCII(type, kGZip) || |
| 64 base::LowerCaseEqualsASCII(type, kXGZip)) { |
| 65 types.push_back(StreamSource::TYPE_GZIP); |
| 66 } else if (base::LowerCaseEqualsASCII(type, kSdch)) { |
| 67 types.push_back(StreamSource::TYPE_SDCH); |
| 68 } |
| 69 } |
| 70 |
| 71 // SDCH-specific hack: if the first filter is SDCH, add a gzip filter in front |
| 72 // of it in fallback mode. |
| 73 if (!types.empty() && types.at(0) == StreamSource::TYPE_SDCH) |
| 74 types.insert(types.begin(), StreamSource::TYPE_GZIP_FALLBACK); |
| 75 |
| 76 for (const auto& type : types) { |
| 77 previous = BuildSource(std::move(previous), type); |
| 78 if (previous == nullptr) |
| 79 return nullptr; |
| 80 } |
| 81 |
| 82 return previous; |
| 83 } |
| 84 |
| 85 std::string StreamSourceUtil::SourceTypeAsString( |
| 86 StreamSource::SourceType type) { |
| 87 switch (type) { |
| 88 #define STREAM_SOURCE_TYPE(label) \ |
| 89 case StreamSource::TYPE_##label: \ |
| 90 return #label; |
| 91 #include "net/filter/stream_source_type_list.h" |
| 92 #undef STREAM_SOURCE_TYPE |
| 93 default: |
| 94 NOTREACHED(); |
| 95 return nullptr; |
| 96 } |
| 97 } |
| 98 |
| 99 std::string StreamSourceUtil::OrderedStreamSourceList(StreamSource* source) { |
| 100 if (source->previous()) { |
| 101 return SourceTypeAsString(source->type()) + "," + |
| 102 OrderedStreamSourceList(source->previous()); |
| 103 } else { |
| 104 return SourceTypeAsString(source->type()); |
| 105 } |
| 106 } |
| 107 |
| 108 } // namespace net |
| OLD | NEW |