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

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: Rebaseline Created 4 years, 12 months 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/macros.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "third_party/brotli/dec/decode.h"
10
11 namespace net {
12
13 class BrotliFilter : public Filter {
14 public:
15 BrotliFilter(FilterType type)
16 : Filter(type), decoding_status_(DECODING_UNINITIALIZED) {}
17
18 ~BrotliFilter() override {
19 if (decoding_status_ != DECODING_UNINITIALIZED)
20 BrotliStateCleanup(brotli_state_.get());
21 }
22
23 // Initializes filter decoding mode and internal control blocks.
24 // The function returns true if success and false otherwise.
25 // The filter can only be initialized once.
26 bool InitDecoding() {
27 if (decoding_status_ != DECODING_UNINITIALIZED)
28 return false;
29
30 brotli_state_.reset(new BrotliState);
Ryan Sleevi 2015/12/28 19:30:53 Does this actually need to be a pointer? It seems
eustas 2015/12/29 13:15:39 No need. It just moved from previous patches. Done
31 BrotliStateInit(brotli_state_.get());
32
33 decoding_status_ = DECODING_IN_PROGRESS;
34 return true;
35 }
36
37 // Decodes the pre-filter data and writes the output into the |dest_buffer|
38 // passed in.
39 // The function returns FilterStatus. See filter.h for its description.
40 //
41 // Upon entry, |*dest_len| is the total size (in number of chars) of the
42 // destination buffer. Upon exit, |*dest_len| is the actual number of chars
43 // written into the destination buffer.
44 //
45 // This function will fail if there is no pre-filter data in the
46 // |stream_buffer_|. On the other hand, |*dest_len| can be 0 upon successful
47 // return. For example, decompressor may process some pre-filter data
48 // but not produce output yet.
49 FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len) override {
50 if (!dest_buffer || !dest_len || *dest_len <= 0)
51 return Filter::FILTER_ERROR;
52
53 if (decoding_status_ == DECODING_DONE) {
54 *dest_len = 0;
55 return Filter::FILTER_DONE;
56 }
57
58 if (decoding_status_ != DECODING_IN_PROGRESS)
59 return Filter::FILTER_ERROR;
60
61 size_t available_in = stream_data_len_;
62 const uint8_t* next_in = bit_cast<uint8_t*>(next_stream_data_);
63 size_t available_out = *dest_len;
64 uint8_t* next_out = bit_cast<uint8_t*>(dest_buffer);
65 size_t total_out = 0;
66 BrotliResult result =
67 BrotliDecompressStream(&available_in, &next_in, &available_out,
68 &next_out, &total_out, brotli_state_.get());
69 int bytes_written = *dest_len - available_out;
Ryan Sleevi 2015/12/28 19:30:53 DANGER: You're mixing signed and unsigned types in
eustas 2015/12/29 13:15:39 Good idea. Done.
70
71 Filter::FilterStatus status;
72 switch (result) {
73 case BROTLI_RESULT_ERROR: {
74 status = Filter::FILTER_ERROR;
75 break;
76 }
77 // Fall through.
Ryan Sleevi 2015/12/28 19:30:53 This comment doesn't seem correct; you break on li
eustas 2015/12/29 13:15:39 I meant that "case BROTLI_RESULT_NEEDS_MORE_OUTPUT
78 case BROTLI_RESULT_NEEDS_MORE_OUTPUT:
79 case BROTLI_RESULT_SUCCESS: {
80 status = Filter::FILTER_OK;
81 *dest_len = bytes_written;
82 stream_data_len_ = available_in;
83 next_stream_data_ = bit_cast<char*>(next_in);
84 if (result == BROTLI_RESULT_SUCCESS)
85 status = Filter::FILTER_DONE;
86 break;
87 }
88 case BROTLI_RESULT_NEEDS_MORE_INPUT: {
89 status = Filter::FILTER_NEED_MORE_DATA;
90 *dest_len = bytes_written;
91 stream_data_len_ = 0;
92 next_stream_data_ = nullptr;
93 break;
94 }
95 default: {
96 status = Filter::FILTER_ERROR;
97 break;
98 }
99 }
100
101 if (status == Filter::FILTER_DONE) {
102 decoding_status_ = DECODING_DONE;
103 } else if (status == Filter::FILTER_ERROR) {
104 decoding_status_ = DECODING_ERROR;
105 }
Ryan Sleevi 2015/12/28 19:30:53 Should this be a switch, rather than a conditional
eustas 2015/12/29 13:15:39 Backed this conditional to previous switch; now it
106
107 return status;
108 }
109
110 private:
111 enum DecodingStatus {
112 DECODING_UNINITIALIZED,
113 DECODING_IN_PROGRESS,
114 DECODING_DONE,
115 DECODING_ERROR
116 };
117
118 // Tracks the status of decoding.
119 // This variable is initialized by InitDecoding and updated only by
120 // ReadFilteredData.
121 DecodingStatus decoding_status_;
122
123 scoped_ptr<BrotliStateStruct> brotli_state_;
124
125 DISALLOW_COPY_AND_ASSIGN(BrotliFilter);
126 };
127
128 Filter* CreateBrotliFilter(Filter::FilterType type_id) {
129 scoped_ptr<BrotliFilter> brotli_filter(new BrotliFilter(type_id));
130 return brotli_filter->InitDecoding() ? brotli_filter.release() : nullptr;
131 }
132
133 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698