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

Side by Side Diff: content/browser/loader/buffered_resource_handler.cc

Issue 2005273002: Move MimeTypeResourceHandler before ThrottlingResourceHandler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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 "content/browser/loader/buffered_resource_handler.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "content/public/common/resource_response.h"
11 #include "net/base/io_buffer.h"
12
13 namespace content {
14
15 namespace {
16
17 // Used to write into an existing IOBuffer at a given offset.
18 class DependentIOBuffer : public net::WrappedIOBuffer {
19 public:
20 DependentIOBuffer(net::IOBuffer* buf, int offset)
21 : net::WrappedIOBuffer(buf->data() + offset), buf_(buf) {}
22
23 private:
24 ~DependentIOBuffer() override {}
25
26 scoped_refptr<net::IOBuffer> buf_;
27 };
28
29 } // namespace
30
31 BufferedResourceHandler::BufferedResourceHandler(
32 std::unique_ptr<ResourceHandler> next_handler,
33 net::URLRequest* request,
34 int max_bytes_to_buffer)
35 : LayeredResourceHandler(request, std::move(next_handler)),
36 state_(STATE_STARTING),
37 max_bytes_to_buffer_(max_bytes_to_buffer),
38 read_buffer_size_(0),
39 bytes_read_(0),
40 weak_ptr_factory_(this) {}
41
42 BufferedResourceHandler::~BufferedResourceHandler() {}
43
44 bool BufferedResourceHandler::CanStartReplayInResponseStarted() {
45 return true;
46 }
47
48 bool BufferedResourceHandler::CanStartReplayInReadCompleted() {
49 return true;
50 }
51
52 bool BufferedResourceHandler::WillStartReplay(bool* defer) {
53 return true;
54 }
55
56 void BufferedResourceHandler::SetController(ResourceController* controller) {
57 ResourceHandler::SetController(controller);
58
59 // Downstream handlers see the BufferedResourceHandler as their
60 // ResourceController, which allows it to consume part or all of the resource
61 // response, and then later replay it to downstream handler.
62 DCHECK(next_handler_.get());
63 next_handler_->SetController(this);
64 }
65
66 bool BufferedResourceHandler::OnResponseStarted(ResourceResponse* response,
67 bool* defer) {
68 response_ = response;
69
70 state_ = STATE_BUFFERING;
71
72 if (!CanStartReplayInResponseStarted()) {
73 return true;
74 }
75
76 return ProcessReplay(defer);
77 }
78
79 bool BufferedResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
80 int* buf_size,
81 int min_size) {
82 if (state_ == STATE_STREAMING)
83 return next_handler_->OnWillRead(buf, buf_size, min_size);
84
85 DCHECK_EQ(-1, min_size);
86
87 if (read_buffer_.get()) {
88 CHECK_LT(bytes_read_, read_buffer_size_);
89 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_);
90 *buf_size = read_buffer_size_ - bytes_read_;
91 } else {
92 if (!next_handler_->OnWillRead(buf, buf_size, min_size))
93 return false;
94
95 read_buffer_ = *buf;
96 read_buffer_size_ = *buf_size;
97 DCHECK_GE(read_buffer_size_, max_bytes_to_buffer_ * 2);
98 }
99 return true;
100 }
101
102 bool BufferedResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
103 if (state_ == STATE_STREAMING)
104 return next_handler_->OnReadCompleted(bytes_read, defer);
105
106 DCHECK_EQ(state_, STATE_BUFFERING);
107 bytes_read_ += bytes_read;
108
109 if (!CanStartReplayInReadCompleted() && (bytes_read > 0))
110 return true;
111
112 return ProcessReplay(defer);
113 }
114
115 void BufferedResourceHandler::OnResponseCompleted(
116 const net::URLRequestStatus& status,
117 const std::string& security_info,
118 bool* defer) {
119 // Upon completion, act like a pass-through handler in case the downstream
120 // handler defers OnResponseCompleted.
121 state_ = STATE_STREAMING;
122
123 next_handler_->OnResponseCompleted(status, security_info, defer);
124 }
125
126 void BufferedResourceHandler::InstallNewLeafHandler(
127 std::unique_ptr<ResourceHandler> new_handler,
128 const std::string& payload_for_old_handler) {
129 // If acting as a pass-through handler, install the new leaf handler right
130 // away.
131 if (state_ == STATE_STARTING || state_ == STATE_STREAMING) {
132 LayeredResourceHandler::InstallNewLeafHandler(std::move(new_handler),
133 payload_for_old_handler);
134 return;
135 }
136
137 // Store the handler so that it can be properly installed when replaying the
138 // response.
139 new_leaf_handler_ = std::move(new_handler);
140 payload_for_old_handler_ = payload_for_old_handler;
141 new_leaf_handler_->SetController(this);
142 }
143
144 void BufferedResourceHandler::Resume() {
145 // If no information is currently being transmitted to downstream handlers,
146 // they should not attempt to resume the request.
147 if (state_ == STATE_BUFFERING || state_ == STATE_PROCESSING) {
148 NOTREACHED();
149 return;
150 }
151
152 // If the BufferingHandler is acting as a pass-through handler, just ask the
153 // upwards ResourceController to resume the request.
154 if (state_ == STATE_STARTING || state_ == STATE_STREAMING) {
155 controller()->Resume();
156 return;
157 }
158
159 // Otherwise proceed with the replay of the response. If it is successful,
160 // resume the request.
161 bool defer = false;
162 if (!ProcessReplay(&defer)) {
163 Cancel();
164 } else if (!defer) {
165 DCHECK(state_ == STATE_STREAMING);
166 controller()->Resume();
167 }
168 }
169
170 void BufferedResourceHandler::Cancel() {
171 controller()->Cancel();
172 }
173
174 void BufferedResourceHandler::CancelAndIgnore() {
175 controller()->CancelAndIgnore();
176 }
177
178 void BufferedResourceHandler::CancelWithError(int error_code) {
179 controller()->CancelWithError(error_code);
180 }
181
182 bool BufferedResourceHandler::ProcessReplay(bool* defer) {
183 bool return_value = true;
184 while (!*defer && return_value && state_ != STATE_STREAMING) {
185 switch (state_) {
186 case STATE_BUFFERING:
187 return_value = MaybeStartReplay(defer);
188 break;
189 case STATE_PROCESSING:
190 return_value = ReplayResponseReceived(defer);
191 break;
192 case STATE_REPLAYING_RESPONSE_RECEIVED:
193 return_value = ReplayResponseReceivedNewHandler(defer);
194 break;
195 case STATE_REPLAYING_RESPONSE_RECEIVED_NEW_HANDLER:
196 return_value = ReplayReadCompleted(defer);
197 break;
198 default:
199 NOTREACHED();
200 break;
201 }
202 }
203 return return_value;
204 }
205
206 bool BufferedResourceHandler::MaybeStartReplay(bool* defer) {
207 if (!WillStartReplay(defer))
208 return false;
209
210 if (*defer)
211 state_ = STATE_BUFFERING;
212 else
213 state_ = STATE_PROCESSING;
214
215 return true;
216 }
217
218 bool BufferedResourceHandler::ReplayResponseReceived(bool* defer) {
219 DCHECK(state_ == STATE_PROCESSING);
220 state_ = STATE_REPLAYING_RESPONSE_RECEIVED;
221 return next_handler_->OnResponseStarted(response_.get(), defer);
222 }
223
224 bool BufferedResourceHandler::ReplayResponseReceivedNewHandler(bool* defer) {
225 DCHECK(state_ == STATE_REPLAYING_RESPONSE_RECEIVED);
226 state_ = STATE_REPLAYING_RESPONSE_RECEIVED_NEW_HANDLER;
227 if (new_leaf_handler_)
228 return new_leaf_handler_->OnResponseStarted(response_.get(), defer);
229 return true;
230 }
231
232 bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) {
233 DCHECK(state_ == STATE_REPLAYING_RESPONSE_RECEIVED_NEW_HANDLER);
234
235 // First, install the new leaf ResourceHandler (if any), before calling
236 // OnReadCompleted on the downstream ResourceHandlers. This should also take
237 // care of delivering the payload for the old ResourceHandler.
238 if (new_leaf_handler_) {
239 // Copy the buffered data to the new leaf ResourceHandler if needed.
240 if (read_buffer_.get()) {
241 scoped_refptr<net::IOBuffer> new_buffer;
242 int buf_len = 0;
243 if (!new_leaf_handler_->OnWillRead(&new_buffer, &buf_len, bytes_read_))
244 return false;
245 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
246 memcpy(new_buffer->data(), read_buffer_->data(), bytes_read_);
247 }
248 LayeredResourceHandler::InstallNewLeafHandler(std::move(new_leaf_handler_),
249 payload_for_old_handler_);
250 }
251
252 state_ = STATE_STREAMING;
253
254 if (!read_buffer_.get())
255 return true;
256
257 bool result = next_handler_->OnReadCompleted(bytes_read_, defer);
258
259 read_buffer_ = NULL;
260 read_buffer_size_ = 0;
261 bytes_read_ = 0;
262
263 return result;
264 }
265
266 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698