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

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

Issue 2251853002: Add net::SourceStream and net::FilterSourceStream (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix a typo 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"
mmenke 2016/08/18 16:18:41 include net_errors.h
xunjieli 2016/08/19 14:31:39 Done.
12
13 namespace net {
14
15 namespace {
16
17 const size_t kBufferSize = 32 * 1024;
18
19 } // namespace
20
21 FilterSourceStream::FilterSourceStream(SourceType type,
22 std::unique_ptr<SourceStream> upstream)
23 : SourceStream(type),
24 upstream_(std::move(upstream)),
25 next_state_(STATE_NONE),
26 output_buffer_size_(0),
27 upstream_end_reached_(false) {
28 DCHECK(upstream_);
mmenke 2016/08/18 16:18:41 include logging.h
xunjieli 2016/08/19 14:31:39 Done.
29 }
30
31 FilterSourceStream::~FilterSourceStream() {}
32
33 int FilterSourceStream::Read(IOBuffer* read_buffer,
34 int read_buffer_size,
35 const CompletionCallback& callback) {
36 DCHECK_EQ(STATE_NONE, next_state_);
37 DCHECK(read_buffer);
38 DCHECK_LT(0, read_buffer_size);
39
40 // Allocate a BlockBuffer during first Read().
41 if (!input_buffer_)
42 input_buffer_ = new IOBufferWithSize(kBufferSize);
43
44 if (drainable_input_buffer_ == nullptr) {
mmenke 2016/08/18 16:18:41 This check is the same as checking if !input_buffe
xunjieli 2016/08/19 14:31:39 Done. Good catch!
45 // This is first Read(), start with reading data from |upstream_|.
46 next_state_ = STATE_READ_DATA;
47 } else {
48 // Otherwise start with filtering data, which tells us whether this stream
49 // needs input data.
50 next_state_ = STATE_FILTER_DATA;
51 }
52
53 output_buffer_ = read_buffer;
54 output_buffer_size_ = read_buffer_size;
55 int rv = DoLoop(OK);
56
57 if (rv == ERR_IO_PENDING)
58 callback_ = callback;
59 return rv;
60 }
61
62 std::string FilterSourceStream::OrderedTypeStringList() const {
63 std::string next_type_string = upstream_->OrderedTypeStringList();
64 if (next_type_string.empty())
65 return GetTypeAsString();
66 return next_type_string + "," + GetTypeAsString();
67 }
68
69 int FilterSourceStream::DoLoop(int result) {
70 DCHECK_NE(STATE_NONE, next_state_);
71
72 int rv = result;
73 do {
74 State state = next_state_;
75 next_state_ = STATE_NONE;
76 switch (state) {
77 case STATE_READ_DATA:
78 rv = DoReadData();
79 break;
80 case STATE_READ_DATA_COMPLETE:
81 rv = DoReadDataComplete(rv);
82 break;
83 case STATE_FILTER_DATA:
84 DCHECK_LE(0, rv);
85 rv = DoFilterData();
86 break;
87 default:
88 NOTREACHED() << "bad state: " << state;
89 rv = ERR_UNEXPECTED;
90 break;
91 }
92 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
93 return rv;
94 }
95
96 int FilterSourceStream::DoReadData() {
97 // Read more data means subclasses have consumed all input or this is the
98 // first read in which case the |drainable_input_buffer_| is not initialized.
99 DCHECK(drainable_input_buffer_ == nullptr ||
100 0 == drainable_input_buffer_->BytesRemaining());
101
102 // Use base::Unretained here is safe because |this| owns |upstream_|.
103 int rv = upstream_->Read(input_buffer_.get(), kBufferSize,
104 base::Bind(&FilterSourceStream::OnNextReadCompleted,
105 base::Unretained(this)));
106
107 if (rv != ERR_IO_PENDING)
108 next_state_ = STATE_READ_DATA_COMPLETE;
mmenke 2016/08/18 16:18:41 The general way this is done is to unconditionally
xunjieli 2016/08/19 14:31:39 Done.
109 return rv;
110 }
111
112 int FilterSourceStream::DoReadDataComplete(int result) {
113 DCHECK_NE(ERR_IO_PENDING, result);
114
115 // If EOF is read (result == OK), also pass that to the the filter.
116 if (result >= OK) {
117 drainable_input_buffer_ =
118 new DrainableIOBuffer(input_buffer_.get(), result);
119 next_state_ = STATE_FILTER_DATA;
120 }
121 if (result <= OK)
122 upstream_end_reached_ = true;
123 return result;
124 }
125
126 void FilterSourceStream::OnNextReadCompleted(int result) {
mmenke 2016/08/18 16:18:42 DCHECK_EQ on next_state_'s value?
xunjieli 2016/08/19 14:31:39 Done.
127 next_state_ = STATE_READ_DATA_COMPLETE;
128 int rv = DoLoop(result);
129 if (rv != ERR_IO_PENDING) {
mmenke 2016/08/18 16:18:42 nit: Early is generally preferred.
xunjieli 2016/08/19 14:31:39 Done.
130 output_buffer_ = nullptr;
131 output_buffer_size_ = 0;
132
133 base::ResetAndReturn(&callback_).Run(rv);
134 }
135 }
136
137 int FilterSourceStream::DoFilterData() {
138 DCHECK(output_buffer_);
139 DCHECK(drainable_input_buffer_);
140
141 int bytes_output = FilterData(output_buffer_.get(), output_buffer_size_,
142 drainable_input_buffer_.get());
143 if (bytes_output == ERR_CONTENT_DECODING_FAILED) {
144 UMA_HISTOGRAM_ENUMERATION("Net.ContentDecodingFailed.FilterType", type(),
145 TYPE_MAX);
146 }
147 // FilterData() is not allowed to return ERR_IO_PENDING.
148 DCHECK_NE(ERR_IO_PENDING, bytes_output);
149
150 // If data can still be read from |upstream_| and filter did not return any
151 // data, it is likely that the filter needs more input.
152 if (bytes_output == OK && !upstream_end_reached_)
153 next_state_ = STATE_READ_DATA;
154 return bytes_output;
155 }
156
157 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698