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

Side by Side Diff: net/filter/filter_source_stream.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: add filter_source_stream_unittest.cc and address other comments Created 4 years, 4 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_source_stream.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 FilterSourceStream::FilterSourceStream(
22 SourceType type,
23 std::unique_ptr<SourceStream> next_stream)
24 : SourceStream(type),
25 next_stream_(std::move(next_stream)),
26 next_state_(STATE_NONE),
27 output_buffer_size_(0),
28 next_stream_end_reached_(false) {
29 DCHECK(next_stream_);
30 }
31
32 FilterSourceStream::~FilterSourceStream() {}
33
34 int FilterSourceStream::Read(IOBuffer* read_buffer,
35 size_t read_buffer_size,
36 const CompletionCallback& callback) {
37 // Allocate a BlockBuffer during first Read().
38 if (!input_buffer_)
39 input_buffer_ = new IOBufferWithSize(kBufferSize);
Randy Smith (Not in Mondays) 2016/08/09 20:28:30 Why not in the constructor?
xunjieli 2016/08/15 15:19:07 This is so that we don't initialize one unnecessar
Randy Smith (Not in Mondays) 2016/08/22 18:12:31 Hmmm. Ok. My shoot-from-the-hip is that it's a p
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 rv;
53 }
54
55 std::string FilterSourceStream::OrderedTypeStringList() const {
56 std::string next_type_string = next_stream_->OrderedTypeStringList();
57 if (next_type_string.empty())
58 return GetTypeAsString();
59 return next_type_string + "," + GetTypeAsString();
60 }
61
62 int FilterSourceStream::DoLoop(int result) {
63 DCHECK(this);
64 DCHECK_NE(STATE_NONE, next_state_);
65 int rv = result;
66 do {
67 State state = next_state_;
68 next_state_ = STATE_NONE;
69 switch (state) {
70 case STATE_READ_DATA:
71 rv = DoReadData();
72 break;
73 case STATE_READ_DATA_COMPLETE:
74 rv = DoReadDataComplete(rv);
75 break;
76 case STATE_FILTER_DATA:
77 rv = DoFilterData(rv);
78 break;
79 default:
80 NOTREACHED() << "bad state: " << state;
81 rv = ERR_UNEXPECTED;
82 break;
83 }
84 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
85 return rv;
86 }
87
88 int FilterSourceStream::DoReadData() {
89 // Read more data means subclasses have consumed all input or this is the
90 // first read in which case the |drainable_input_buffer_| is not initialized.
91 DCHECK(drainable_input_buffer_ == nullptr ||
92 0 == drainable_input_buffer_->BytesRemaining());
93 // Use base::Unretained here is safe because |this| owns |next_stream_|.
94 int rv =
95 next_stream_->Read(input_buffer_.get(), kBufferSize,
96 base::Bind(&FilterSourceStream::OnNextReadCompleted,
97 base::Unretained(this)));
98
99 if (rv != ERR_IO_PENDING)
100 next_state_ = STATE_READ_DATA_COMPLETE;
101 return rv;
102 }
103
104 int FilterSourceStream::DoReadDataComplete(int result) {
105 DCHECK_NE(ERR_IO_PENDING, result);
106
107 // If EOF is read (result == OK), also pass that to the the filter.
108 if (result >= OK) {
109 drainable_input_buffer_ =
110 new DrainableIOBuffer(input_buffer_.get(), result);
111 next_state_ = STATE_FILTER_DATA;
112 }
113 if (result <= OK)
114 next_stream_end_reached_ = true;
115 return result;
116 }
117
118 void FilterSourceStream::OnNextReadCompleted(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 FilterSourceStream::DoFilterData(int result) {
126 DCHECK(output_buffer_);
127 DCHECK_LE(0, result);
128
129 // This is first Read(), short circuit it and go straight to read data from
130 // |next_stream_|.
131 if (drainable_input_buffer_ == nullptr) {
132 next_state_ = STATE_READ_DATA;
133 return OK;
134 }
135
136 int bytes_output = FilterData(output_buffer_.get(), output_buffer_size_,
137 drainable_input_buffer_.get());
138 if (bytes_output == ERR_CONTENT_DECODING_FAILED) {
139 UMA_HISTOGRAM_ENUMERATION("Net.ContentDecodingFailed.FilterType", type(),
140 TYPE_MAX);
141 }
142 // FilterData() is not allowed to return ERR_IO_PENDING.
143 DCHECK_NE(ERR_IO_PENDING, bytes_output);
144
145 // If can still read data from |next_stream_| and filter did not return any
Randy Smith (Not in Mondays) 2016/08/09 20:28:30 nit, rephrasing: "If data can still be read from |
xunjieli 2016/08/15 15:19:07 Done.
146 // data, it is likely that the filter needs more input.
147 if (bytes_output == OK && !next_stream_end_reached_)
148 next_state_ = STATE_READ_DATA;
Randy Smith (Not in Mondays) 2016/08/09 20:28:30 Would an assertion that drainable_input_buffer_ ha
xunjieli 2016/08/15 15:19:07 DoReadData() already has a DCHECK.
Randy Smith (Not in Mondays) 2016/08/22 18:12:31 Acknowledged.
149 return bytes_output;
150 }
151
152 void FilterSourceStream::DoCallback(int result) {
153 DCHECK_NE(ERR_IO_PENDING, result);
154 DCHECK(!callback_.is_null());
155
156 output_buffer_ = nullptr;
157 output_buffer_size_ = 0;
158
159 base::ResetAndReturn(&callback_).Run(result);
160 }
161
162 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698