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

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

Issue 2668603003: Make ResourceHandler::OnWillRead able to complete asynchronously. (Closed)
Patch Set: One bot doesn't like 256 day timers. :( Created 3 years, 10 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/loader/intercepting_resource_handler.h" 5 #include "content/browser/loader/intercepting_resource_handler.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 response_ = response; 85 response_ = response;
86 86
87 // Otherwise, switch handlers. First, inform the original ResourceHandler 87 // Otherwise, switch handlers. First, inform the original ResourceHandler
88 // that this will be handled entirely by the new ResourceHandler. 88 // that this will be handled entirely by the new ResourceHandler.
89 HoldController(std::move(controller)); 89 HoldController(std::move(controller));
90 state_ = State::SWAPPING_HANDLERS; 90 state_ = State::SWAPPING_HANDLERS;
91 91
92 DoLoop(); 92 DoLoop();
93 } 93 }
94 94
95 bool InterceptingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, 95 void InterceptingResourceHandler::OnWillRead(
96 int* buf_size) { 96 scoped_refptr<net::IOBuffer>* buf,
97 if (state_ == State::PASS_THROUGH) 97 int* buf_size,
98 return next_handler_->OnWillRead(buf, buf_size); 98 std::unique_ptr<ResourceController> controller) {
99 if (state_ == State::PASS_THROUGH) {
100 next_handler_->OnWillRead(buf, buf_size, std::move(controller));
101 return;
102 }
99 103
100 DCHECK_EQ(State::STARTING, state_); 104 DCHECK_EQ(State::STARTING, state_);
105 DCHECK(!first_read_buffer_);
106 DCHECK_EQ(0, first_read_buffer_size_);
107 DCHECK(!parent_read_buffer_);
108 DCHECK(!parent_read_buffer_size_);
101 109
102 if (!next_handler_->OnWillRead(buf, buf_size)) 110 parent_read_buffer_ = buf;
103 return false; 111 parent_read_buffer_size_ = buf_size;
104 112
105 first_read_buffer_ = *buf; 113 state_ = State::SENDING_ON_WILL_READ_TO_OLD_HANDLER;
106 first_read_buffer_size_ = *buf_size; 114 HoldController(std::move(controller));
107 first_read_buffer_double_ = new net::IOBuffer(static_cast<size_t>(*buf_size)); 115 DoLoop();
108 *buf = first_read_buffer_double_;
109 return true;
110 } 116 }
111 117
112 void InterceptingResourceHandler::OnReadCompleted( 118 void InterceptingResourceHandler::OnReadCompleted(
113 int bytes_read, 119 int bytes_read,
114 std::unique_ptr<ResourceController> controller) { 120 std::unique_ptr<ResourceController> controller) {
115 DCHECK(!has_controller()); 121 DCHECK(!has_controller());
116 122
117 DCHECK_GE(bytes_read, 0); 123 DCHECK_GE(bytes_read, 0);
118 if (state_ == State::PASS_THROUGH) { 124 if (state_ == State::PASS_THROUGH) {
119 if (first_read_buffer_double_) { 125 if (first_read_buffer_double_) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 190
185 while (advance_to_next_state_) { 191 while (advance_to_next_state_) {
186 advance_to_next_state_ = false; 192 advance_to_next_state_ = false;
187 193
188 switch (state_) { 194 switch (state_) {
189 case State::STARTING: 195 case State::STARTING:
190 case State::WAITING_FOR_ON_READ_COMPLETED: 196 case State::WAITING_FOR_ON_READ_COMPLETED:
191 case State::PASS_THROUGH: 197 case State::PASS_THROUGH:
192 NOTREACHED(); 198 NOTREACHED();
193 break; 199 break;
200 case State::SENDING_ON_WILL_READ_TO_OLD_HANDLER:
201 SendOnWillReadToOldHandler();
202 break;
203 case State::WAITING_FOR_OLD_HANDLERS_BUFFER:
204 OnBufferReceived();
205 break;
194 case State::SENDING_ON_WILL_START_TO_NEW_HANDLER: 206 case State::SENDING_ON_WILL_START_TO_NEW_HANDLER:
195 SendOnResponseStartedToNewHandler(); 207 SendOnResponseStartedToNewHandler();
196 break; 208 break;
197 case State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER: 209 case State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER:
198 if (first_read_buffer_double_) { 210 if (first_read_buffer_double_) {
199 // OnWillRead has been called, so copying the data from 211 // OnWillRead has been called, so copying the data from
200 // |first_read_buffer_double_| to |first_read_buffer_| will be needed 212 // |first_read_buffer_double_| to |first_read_buffer_| will be needed
201 // when OnReadCompleted is called. 213 // when OnReadCompleted is called.
202 state_ = State::WAITING_FOR_ON_READ_COMPLETED; 214 state_ = State::WAITING_FOR_ON_READ_COMPLETED;
203 } else { 215 } else {
204 // OnWillRead has not been called, so no special handling will be 216 // OnWillRead has not been called, so no special handling will be
205 // needed from now on. 217 // needed from now on.
206 state_ = State::PASS_THROUGH; 218 state_ = State::PASS_THROUGH;
207 } 219 }
208 ResumeInternal(); 220 ResumeInternal();
209 break; 221 break;
210 case State::SWAPPING_HANDLERS: 222 case State::SWAPPING_HANDLERS:
211 SendOnResponseStartedToOldHandler(); 223 SendOnResponseStartedToOldHandler();
212 break; 224 break;
213 case State::SENDING_PAYLOAD_TO_OLD_HANDLER: 225 case State::SENDING_PAYLOAD_TO_OLD_HANDLER:
214 SendPayloadToOldHandler(); 226 SendPayloadToOldHandler();
215 break; 227 break;
228 case State::RECEIVING_BUFFER_FROM_OLD_HANDLER:
229 ReceivedBufferFromOldHandler();
230 break;
216 case State::SENDING_BUFFER_TO_NEW_HANDLER: 231 case State::SENDING_BUFFER_TO_NEW_HANDLER:
217 SendFirstReadBufferToNewHandler(); 232 SendFirstReadBufferToNewHandler();
218 break; 233 break;
234 case State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER:
235 ReceivedBufferFromNewHandler();
236 break;
219 } 237 }
220 } 238 }
221 } 239 }
222 240
223 void InterceptingResourceHandler::ResumeInternal() { 241 void InterceptingResourceHandler::ResumeInternal() {
224 DCHECK(has_controller()); 242 DCHECK(has_controller());
225 if (state_ == State::STARTING || 243 if (state_ == State::STARTING ||
226 state_ == State::WAITING_FOR_ON_READ_COMPLETED || 244 state_ == State::WAITING_FOR_ON_READ_COMPLETED ||
227 state_ == State::PASS_THROUGH) { 245 state_ == State::PASS_THROUGH) {
228 // Uninteresting Resume: just delegate to the original resource controller. 246 // Uninteresting Resume: just delegate to the original resource controller.
229 Resume(); 247 Resume();
230 return; 248 return;
231 } 249 }
232 250
233 // If called recusively from a DoLoop, advance state when returning to the 251 // If called recusively from a DoLoop, advance state when returning to the
234 // loop. 252 // loop.
235 if (in_do_loop_) { 253 if (in_do_loop_) {
236 DCHECK(!advance_to_next_state_); 254 DCHECK(!advance_to_next_state_);
237 advance_to_next_state_ = true; 255 advance_to_next_state_ = true;
238 return; 256 return;
239 } 257 }
240 258
241 // Can't call DoLoop synchronously, as it may call into |next_handler_| 259 // Can't call DoLoop synchronously, as it may call into |next_handler_|
242 // synchronously, which is what called Resume(). 260 // synchronously, which is what called Resume().
243 base::ThreadTaskRunnerHandle::Get()->PostTask( 261 base::ThreadTaskRunnerHandle::Get()->PostTask(
244 FROM_HERE, base::Bind(&InterceptingResourceHandler::DoLoop, 262 FROM_HERE, base::Bind(&InterceptingResourceHandler::DoLoop,
245 weak_ptr_factory_.GetWeakPtr())); 263 weak_ptr_factory_.GetWeakPtr()));
246 } 264 }
247 265
266 void InterceptingResourceHandler::SendOnWillReadToOldHandler() {
267 DCHECK_EQ(State::SENDING_ON_WILL_READ_TO_OLD_HANDLER, state_);
268
269 state_ = State::WAITING_FOR_OLD_HANDLERS_BUFFER;
270 next_handler_->OnWillRead(&first_read_buffer_, &first_read_buffer_size_,
271 base::MakeUnique<Controller>(this));
272 }
273
274 void InterceptingResourceHandler::OnBufferReceived() {
275 DCHECK_EQ(State::WAITING_FOR_OLD_HANDLERS_BUFFER, state_);
276
277 // TODO(mmenke): If this method is just going to allocate a double buffer
278 // anyways, can the call to the old handler's OnWillRead be removed? That
279 // would mean handling replaying data in the case that |next_handler_|'s
280 // buffer is smaller than the double buffer, but SendPayloadToOldHandler
281 // already handles that case, anyways, so could share that code with the
282 // no-swap path as well. Or better, just have MimeSniffingResourceHandler
283 // create and manage the buffer itself.
284 first_read_buffer_double_ =
285 new net::IOBuffer(static_cast<size_t>(first_read_buffer_size_));
286 *parent_read_buffer_ = first_read_buffer_double_;
287 *parent_read_buffer_size_ = first_read_buffer_size_;
288
289 parent_read_buffer_ = nullptr;
290 parent_read_buffer_size_ = nullptr;
291
292 state_ = State::STARTING;
293 Resume();
294 }
295
248 void InterceptingResourceHandler::SendOnResponseStartedToOldHandler() { 296 void InterceptingResourceHandler::SendOnResponseStartedToOldHandler() {
249 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; 297 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER;
250 next_handler_->OnResponseStarted(response_.get(), 298 next_handler_->OnResponseStarted(response_.get(),
251 base::MakeUnique<Controller>(this)); 299 base::MakeUnique<Controller>(this));
252 } 300 }
253 301
254 void InterceptingResourceHandler::SendPayloadToOldHandler() { 302 void InterceptingResourceHandler::SendPayloadToOldHandler() {
255 DCHECK_EQ(State::SENDING_PAYLOAD_TO_OLD_HANDLER, state_); 303 DCHECK_EQ(State::SENDING_PAYLOAD_TO_OLD_HANDLER, state_);
256 if (payload_bytes_written_ == payload_for_old_handler_.size()) { 304
305 if (static_cast<size_t>(payload_bytes_written_) ==
306 payload_for_old_handler_.size()) {
257 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 307 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
258 if (payload_for_old_handler_.empty()) { 308 if (payload_for_old_handler_.empty()) {
259 // If there is no payload, just finalize the request on the old handler. 309 // If there is no payload, just finalize the request on the old handler.
260 status = net::URLRequestStatus::FromError(net::ERR_ABORTED); 310 status = net::URLRequestStatus::FromError(net::ERR_ABORTED);
261 } 311 }
262 bool was_resumed = false; 312 bool was_resumed = false;
263 // TODO(mmenke): Get rid of NullResourceController and do something more 313 // TODO(mmenke): Get rid of NullResourceController and do something more
264 // reasonable. 314 // reasonable.
265 next_handler_->OnResponseCompleted( 315 next_handler_->OnResponseCompleted(
266 status, base::MakeUnique<NullResourceController>(&was_resumed)); 316 status, base::MakeUnique<NullResourceController>(&was_resumed));
267 DCHECK(was_resumed); 317 DCHECK(was_resumed);
268 318
269 next_handler_ = std::move(new_handler_); 319 next_handler_ = std::move(new_handler_);
270 state_ = State::SENDING_ON_WILL_START_TO_NEW_HANDLER; 320 state_ = State::SENDING_ON_WILL_START_TO_NEW_HANDLER;
271 next_handler_->OnWillStart(request()->url(), 321 next_handler_->OnWillStart(request()->url(),
272 base::MakeUnique<Controller>(this)); 322 base::MakeUnique<Controller>(this));
273 return; 323 return;
274 } 324 }
275 325
326 state_ = State::RECEIVING_BUFFER_FROM_OLD_HANDLER;
327
276 scoped_refptr<net::IOBuffer> buffer; 328 scoped_refptr<net::IOBuffer> buffer;
277 int size = 0; 329 // If |first_read_buffer_| is non-NULL, it was already received from
330 // |next_handler_| via OnWillRead. Can just use the buffer.
278 if (first_read_buffer_) { 331 if (first_read_buffer_) {
279 // |first_read_buffer_| is a buffer gotten from |next_handler_| via 332 DCHECK_GT(first_read_buffer_size_, 0);
280 // OnWillRead. Use the buffer.
281 buffer = first_read_buffer_;
282 size = first_read_buffer_size_;
283 333
284 first_read_buffer_ = nullptr; 334 ResumeInternal();
285 first_read_buffer_size_ = 0; 335 return;
286 } else {
287 if (!next_handler_->OnWillRead(&buffer, &size)) {
288 Cancel();
289 return;
290 }
291 } 336 }
292 337
293 size = std::min(size, static_cast<int>(payload_for_old_handler_.size() - 338 DCHECK(!first_read_buffer_size_);
294 payload_bytes_written_)); 339 next_handler_->OnWillRead(&first_read_buffer_, &first_read_buffer_size_,
295 memcpy(buffer->data(), 340 base::MakeUnique<Controller>(this));
296 payload_for_old_handler_.data() + payload_bytes_written_, size); 341 }
297 payload_bytes_written_ += size; 342
298 next_handler_->OnReadCompleted(size, base::MakeUnique<Controller>(this)); 343 void InterceptingResourceHandler::ReceivedBufferFromOldHandler() {
344 DCHECK_EQ(State::RECEIVING_BUFFER_FROM_OLD_HANDLER, state_);
345 DCHECK(first_read_buffer_);
346 DCHECK_GT(first_read_buffer_size_, 0);
347
348 int bytes_to_copy =
349 std::min(first_read_buffer_size_,
350 static_cast<int>(payload_for_old_handler_.size() -
351 payload_bytes_written_));
352 memcpy(first_read_buffer_->data(),
353 payload_for_old_handler_.data() + payload_bytes_written_,
354 bytes_to_copy);
355 payload_bytes_written_ += bytes_to_copy;
356
357 first_read_buffer_ = nullptr;
358 first_read_buffer_size_ = 0;
359
360 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER;
361 next_handler_->OnReadCompleted(bytes_to_copy,
362 base::MakeUnique<Controller>(this));
299 } 363 }
300 364
301 void InterceptingResourceHandler::SendOnResponseStartedToNewHandler() { 365 void InterceptingResourceHandler::SendOnResponseStartedToNewHandler() {
302 state_ = State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER; 366 state_ = State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER;
303 next_handler_->OnResponseStarted(response_.get(), 367 next_handler_->OnResponseStarted(response_.get(),
304 base::MakeUnique<Controller>(this)); 368 base::MakeUnique<Controller>(this));
305 } 369 }
306 370
307 void InterceptingResourceHandler::SendFirstReadBufferToNewHandler() { 371 void InterceptingResourceHandler::SendFirstReadBufferToNewHandler() {
308 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER); 372 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER);
373 DCHECK(!new_handler_read_buffer_);
374 DCHECK(!new_handler_read_buffer_size_);
309 375
310 if (first_read_buffer_bytes_written_ == first_read_buffer_bytes_read_) { 376 if (first_read_buffer_bytes_written_ == first_read_buffer_bytes_read_) {
311 state_ = State::PASS_THROUGH; 377 state_ = State::PASS_THROUGH;
312 first_read_buffer_double_ = nullptr; 378 first_read_buffer_double_ = nullptr;
313 ResumeInternal(); 379 ResumeInternal();
314 return; 380 return;
315 } 381 }
316 382
317 scoped_refptr<net::IOBuffer> buf; 383 next_handler_->OnWillRead(&new_handler_read_buffer_,
318 int size = 0; 384 &new_handler_read_buffer_size_,
319 if (!next_handler_->OnWillRead(&buf, &size)) { 385 base::MakeUnique<Controller>(this));
320 Cancel(); 386 state_ = State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER;
Charlie Harrison 2017/02/16 21:25:04 Shouldn't this go above the OnWillReadCall?
mmenke 2017/03/08 19:16:07 Done. Doesn't matter for correctness, but it's mo
321 return; 387 }
322 } 388
323 size = std::min(size, static_cast<int>(first_read_buffer_bytes_read_ - 389 void InterceptingResourceHandler::ReceivedBufferFromNewHandler() {
324 first_read_buffer_bytes_written_)); 390 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER);
325 memcpy(buf->data(), 391 DCHECK(new_handler_read_buffer_);
392 DCHECK(new_handler_read_buffer_size_);
393
394 int bytes_to_copy =
395 std::min(new_handler_read_buffer_size_,
396 static_cast<int>(first_read_buffer_bytes_read_ -
397 first_read_buffer_bytes_written_));
398 memcpy(new_handler_read_buffer_->data(),
326 first_read_buffer_double_->data() + first_read_buffer_bytes_written_, 399 first_read_buffer_double_->data() + first_read_buffer_bytes_written_,
327 size); 400 bytes_to_copy);
328 first_read_buffer_bytes_written_ += size; 401 first_read_buffer_bytes_written_ += bytes_to_copy;
329 next_handler_->OnReadCompleted(size, base::MakeUnique<Controller>(this)); 402
403 new_handler_read_buffer_ = nullptr;
404 new_handler_read_buffer_size_ = 0;
405
406 state_ = State::SENDING_BUFFER_TO_NEW_HANDLER;
407 next_handler_->OnReadCompleted(bytes_to_copy,
408 base::MakeUnique<Controller>(this));
330 } 409 }
331 410
332 } // namespace content 411 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698