Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(779)

Side by Side Diff: net/filter/brotli_filter.cc

Issue 1431723002: Add brotli content-encoding filter. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed nits Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/brotli_filter.h"
6
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "third_party/brotli/dec/decode.h"
12
13 namespace net {
14
15 #if !defined(DISABLE_BROTLI_SUPPORT)
Ryan Sleevi 2015/12/17 01:04:40 #if !BUILDFLAG(DISABLE_BROTLI_SUPPORT)
16 class BrotliFilter : public Filter {
17 public:
18 BrotliFilter(FilterType type, int buffer_size)
19 : Filter(type), decoding_status_(DECODING_UNINITIALIZED) {
20 InitBuffer(buffer_size);
21 }
22
23 ~BrotliFilter() override {
24 if (decoding_status_ != DECODING_UNINITIALIZED)
25 BrotliStateCleanup(brotli_state_.get());
26 }
27
28 // Initializes filter decoding mode and internal control blocks.
29 // The function returns true if success and false otherwise.
30 // The filter can only be initialized once.
31 bool InitDecoding() {
32 if (decoding_status_ != DECODING_UNINITIALIZED)
33 return false;
34
35 brotli_state_.reset(new BrotliState);
36 BrotliStateInit(brotli_state_.get());
37
38 decoding_status_ = DECODING_IN_PROGRESS;
39 return true;
40 }
41
42 // Decodes the pre-filter data and writes the output into the |dest_buffer|
43 // passed in.
44 // The function returns FilterStatus. See filter.h for its description.
45 //
46 // Upon entry, |*dest_len| is the total size (in number of chars) of the
47 // destination buffer. Upon exit, |*dest_len| is the actual number of chars
48 // written into the destination buffer.
49 //
50 // This function will fail if there is no pre-filter data in the
51 // |stream_buffer_|. On the other hand, |*dest_len| can be 0 upon successful
52 // return. For example, decompressor may process some pre-filter data
53 // but not produce output yet.
54 FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len) override {
55 if (!dest_buffer || !dest_len || *dest_len <= 0)
56 return Filter::FILTER_ERROR;
57
58 if (decoding_status_ == DECODING_DONE) {
59 *dest_len = 0;
60 return Filter::FILTER_DONE;
61 }
62
63 if (decoding_status_ != DECODING_IN_PROGRESS)
64 return Filter::FILTER_ERROR;
65
66 size_t available_in = stream_data_len_;
67 const uint8_t* next_in = bit_cast<uint8_t*>(next_stream_data_);
68 size_t available_out = *dest_len;
69 uint8_t* next_out = bit_cast<uint8_t*>(dest_buffer);
70 size_t total_out = 0;
71 BrotliResult result =
72 BrotliDecompressStream(&available_in, &next_in, &available_out,
73 &next_out, &total_out, brotli_state_.get());
74 int bytes_written = *dest_len - available_out;
75
76 Filter::FilterStatus status;
77 switch (result) {
78 case BROTLI_RESULT_ERROR: {
79 status = Filter::FILTER_ERROR;
80 break;
81 }
82 // Fall through.
83 case BROTLI_RESULT_NEEDS_MORE_OUTPUT:
84 case BROTLI_RESULT_SUCCESS: {
85 status = Filter::FILTER_OK;
86 *dest_len = bytes_written;
87 stream_data_len_ = available_in;
88 next_stream_data_ = bit_cast<char*>(next_in);
89 if (result == BROTLI_RESULT_SUCCESS)
90 status = Filter::FILTER_DONE;
91 break;
92 }
93 case BROTLI_RESULT_NEEDS_MORE_INPUT: {
94 status = Filter::FILTER_NEED_MORE_DATA;
95 *dest_len = bytes_written;
96 stream_data_len_ = 0;
97 next_stream_data_ = nullptr;
98 break;
99 }
100 default: {
101 status = Filter::FILTER_ERROR;
102 break;
103 }
104 }
105
106 if (status == Filter::FILTER_DONE) {
107 decoding_status_ = DECODING_DONE;
108 } else if (status == Filter::FILTER_ERROR) {
109 decoding_status_ = DECODING_ERROR;
110 }
111
112 return status;
113 }
114
115 private:
116 enum DecodingStatus {
117 DECODING_UNINITIALIZED,
118 DECODING_IN_PROGRESS,
119 DECODING_DONE,
120 DECODING_ERROR
121 };
122
123 // Tracks the status of decoding.
124 // This variable is initialized by InitDecoding and updated only by
125 // ReadFilteredData.
126 DecodingStatus decoding_status_;
127
128 scoped_ptr<BrotliStateStruct> brotli_state_;
129
130 DISALLOW_COPY_AND_ASSIGN(BrotliFilter);
131 };
132 #endif
133
134 Filter* CreateBrotliFilter(Filter::FilterType type_id, int buffer_size) {
135 #if !defined(DISABLE_BROTLI_SUPPORT)
136 scoped_ptr<BrotliFilter> brotli_filter(
137 new BrotliFilter(type_id, buffer_size));
138 return brotli_filter->InitDecoding() ? brotli_filter.release() : nullptr;
139 #else
140 return nullptr;
141 #endif
142 }
143
144 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698