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

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

Issue 1662763002: [ON HOLD] Implement pull-based design for content decoding (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix compile on mac Created 4 years, 5 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 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/filter_stream_source.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/metrics/histogram_macros.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/strings/string_util.h"
12
13 namespace net {
14
15 namespace {
16
17 const size_t kBufferSize = 32 * 1024;
18
19 } // namespace
20
21 FilterStreamSource::FilterStreamSource(SourceType type,
22 std::unique_ptr<StreamSource> previous)
23 : StreamSource(type),
24 previous_(std::move(previous)),
25 next_state_(STATE_NONE),
26 output_buffer_size_(0),
27 previous_eof_reached_(false) {
28 DCHECK(previous_);
29 }
30
31 FilterStreamSource::~FilterStreamSource() {}
32
33 int FilterStreamSource::Read(IOBuffer* read_buffer,
34 size_t read_buffer_size,
35 const CompletionCallback& callback) {
36 // Allocate a BlockBuffer during first Read().
37 if (!input_buffer_) {
38 input_buffer_ = new IOBufferWithSize(kBufferSize);
39 drainable_input_buffer_ = new DrainableIOBuffer(input_buffer_.get(), 0);
40 }
41 // Start with filtering data, which tells us whether it needs input data.
42 next_state_ = STATE_FILTER_DATA;
43
44 output_buffer_ = read_buffer;
45 output_buffer_size_ = read_buffer_size;
46 int rv = DoLoop(OK);
47 if (rv > OK) {
48 return rv;
49 } else if (rv == ERR_IO_PENDING) {
50 callback_ = callback;
51 }
52 return static_cast<Error>(rv);
53 }
54
55 std::string FilterStreamSource::OrderedTypeStringList() const {
56 return previous_->OrderedTypeStringList() + "," + GetTypeAsString();
mmenke 2016/07/21 18:14:08 So will this be something like "NONE,GZIP" or "NON
xunjieli 2016/07/27 20:32:01 Done.
57 }
58
59 bool FilterStreamSource::Init() {
60 return true;
61 }
62
63 int FilterStreamSource::DoLoop(int result) {
64 CHECK(this);
65 DCHECK_NE(STATE_NONE, next_state_);
66 int rv = result;
67 do {
68 State state = next_state_;
69 next_state_ = STATE_NONE;
70 switch (state) {
71 case STATE_READ_DATA:
72 rv = DoReadData();
73 break;
74 case STATE_READ_DATA_COMPLETE:
75 rv = DoReadDataComplete(rv);
76 break;
77 case STATE_FILTER_DATA:
78 rv = DoFilterData(rv);
79 break;
80 case STATE_FILTER_DATA_COMPLETE:
81 rv = DoFilterDataComplete(rv);
82 break;
83 default:
84 NOTREACHED() << "bad state: " << state;
85 rv = ERR_UNEXPECTED;
86 break;
87 }
88 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
89 return rv;
90 }
91
92 int FilterStreamSource::DoReadData() {
93 DCHECK_EQ(0, drainable_input_buffer_->BytesRemaining());
94 // Use base::Unretained here is safe because |this| owns |previous_|.
95 int rv =
96 previous_->Read(input_buffer_.get(), kBufferSize,
97 base::Bind(&FilterStreamSource::OnPreviousReadCompleted,
98 base::Unretained(this)));
99
100 if (rv != ERR_IO_PENDING)
101 next_state_ = STATE_READ_DATA_COMPLETE;
102 return rv;
103 }
104
105 int FilterStreamSource::DoReadDataComplete(int result) {
106 CHECK_NE(ERR_IO_PENDING, result);
107
108 if (result > OK) {
109 drainable_input_buffer_ = new DrainableIOBuffer(
110 input_buffer_.get(), base::checked_cast<size_t>(result));
111 next_state_ = STATE_FILTER_DATA;
112 } else {
113 previous_eof_reached_ = true;
114 }
115 return result;
116 }
117
118 void FilterStreamSource::OnPreviousReadCompleted(int result) {
119 next_state_ = STATE_READ_DATA_COMPLETE;
120 int rv = DoLoop(result);
121 if (rv != ERR_IO_PENDING)
122 DoCallback(rv);
123 }
124
125 int FilterStreamSource::DoFilterData(int result) {
126 DCHECK(output_buffer_);
127 CHECK_LE(0, result);
128
129 int bytes_output = FilterData(output_buffer_.get(), output_buffer_size_,
130 drainable_input_buffer_.get());
131 if (bytes_output == ERR_CONTENT_DECODING_FAILED) {
132 UMA_HISTOGRAM_ENUMERATION("Net.ContentDecodingFailed.FilterType", type(),
133 TYPE_MAX);
134 }
135 // FilterData() is not allowed to return ERR_IO_PENDING.
136 CHECK_NE(ERR_IO_PENDING, bytes_output);
137
138 next_state_ = STATE_FILTER_DATA_COMPLETE;
139 return bytes_output;
140 }
141
142 int FilterStreamSource::DoFilterDataComplete(int result) {
143 DCHECK_NE(ERR_IO_PENDING, result);
144
145 if (result == OK && !previous_eof_reached_)
146 next_state_ = STATE_READ_DATA;
147 return result;
148 }
149
150 void FilterStreamSource::DoCallback(int result) {
151 CHECK_NE(ERR_IO_PENDING, result);
152
153 output_buffer_ = nullptr;
154 output_buffer_size_ = 0;
155
156 DCHECK(!callback_.is_null());
157 base::ResetAndReturn(&callback_).Run(result);
158 }
159
160 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698