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

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

Issue 2760223002: Revert of Allow MojoAsyncResourceHandler::OnWillRead to complete asyncronously (Closed)
Patch Set: Created 3 years, 9 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/mojo_async_resource_handler.h" 5 #include "content/browser/loader/mojo_async_resource_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 10 matching lines...) Expand all
21 #include "content/browser/loader/resource_controller.h" 21 #include "content/browser/loader/resource_controller.h"
22 #include "content/browser/loader/resource_dispatcher_host_impl.h" 22 #include "content/browser/loader/resource_dispatcher_host_impl.h"
23 #include "content/browser/loader/resource_request_info_impl.h" 23 #include "content/browser/loader/resource_request_info_impl.h"
24 #include "content/browser/loader/resource_scheduler.h" 24 #include "content/browser/loader/resource_scheduler.h"
25 #include "content/browser/loader/upload_progress_tracker.h" 25 #include "content/browser/loader/upload_progress_tracker.h"
26 #include "content/common/resource_request_completion_status.h" 26 #include "content/common/resource_request_completion_status.h"
27 #include "content/public/browser/global_request_id.h" 27 #include "content/public/browser/global_request_id.h"
28 #include "content/public/common/resource_response.h" 28 #include "content/public/common/resource_response.h"
29 #include "mojo/public/c/system/data_pipe.h" 29 #include "mojo/public/c/system/data_pipe.h"
30 #include "mojo/public/cpp/bindings/message.h" 30 #include "mojo/public/cpp/bindings/message.h"
31 #include "net/base/io_buffer.h"
31 #include "net/base/mime_sniffer.h" 32 #include "net/base/mime_sniffer.h"
32 #include "net/base/net_errors.h"
33 #include "net/url_request/redirect_info.h" 33 #include "net/url_request/redirect_info.h"
34 34
35 namespace content { 35 namespace content {
36 namespace { 36 namespace {
37 37
38 int g_allocation_size = MojoAsyncResourceHandler::kDefaultAllocationSize; 38 int g_allocation_size = MojoAsyncResourceHandler::kDefaultAllocationSize;
39 39
40 // MimeTypeResourceHandler *implicitly* requires that the buffer size 40 // MimeTypeResourceHandler *implicitly* requires that the buffer size
41 // returned from OnWillRead should be larger than certain size. 41 // returned from OnWillRead should be larger than certain size.
42 // TODO(yhirano): Fix MimeTypeResourceHandler. 42 // TODO(yhirano): Fix MimeTypeResourceHandler.
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 base::Unretained(this))); 220 base::Unretained(this)));
221 } 221 }
222 222
223 controller->Resume(); 223 controller->Resume();
224 } 224 }
225 225
226 void MojoAsyncResourceHandler::OnWillRead( 226 void MojoAsyncResourceHandler::OnWillRead(
227 scoped_refptr<net::IOBuffer>* buf, 227 scoped_refptr<net::IOBuffer>* buf,
228 int* buf_size, 228 int* buf_size,
229 std::unique_ptr<ResourceController> controller) { 229 std::unique_ptr<ResourceController> controller) {
230 // |buffer_| is set to nullptr on successful read completion (Except for the
231 // final 0-byte read, so this DCHECK will also catch OnWillRead being called
232 // after OnReadCompelted(0)).
233 DCHECK(!buffer_);
234 DCHECK_EQ(0u, buffer_offset_);
235
236 if (!CheckForSufficientResource()) { 230 if (!CheckForSufficientResource()) {
237 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); 231 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
238 return; 232 return;
239 } 233 }
240 234
241 bool first_call = false;
242 if (!shared_writer_) { 235 if (!shared_writer_) {
243 first_call = true;
244 MojoCreateDataPipeOptions options; 236 MojoCreateDataPipeOptions options;
245 options.struct_size = sizeof(MojoCreateDataPipeOptions); 237 options.struct_size = sizeof(MojoCreateDataPipeOptions);
246 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; 238 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
247 options.element_num_bytes = 1; 239 options.element_num_bytes = 1;
248 options.capacity_num_bytes = g_allocation_size; 240 options.capacity_num_bytes = g_allocation_size;
249 mojo::DataPipe data_pipe(options); 241 mojo::DataPipe data_pipe(options);
250 242
251 DCHECK(data_pipe.producer_handle.is_valid()); 243 DCHECK(data_pipe.producer_handle.is_valid());
252 DCHECK(data_pipe.consumer_handle.is_valid()); 244 DCHECK(data_pipe.consumer_handle.is_valid());
253 245
254 response_body_consumer_handle_ = std::move(data_pipe.consumer_handle); 246 response_body_consumer_handle_ = std::move(data_pipe.consumer_handle);
255 shared_writer_ = new SharedWriter(std::move(data_pipe.producer_handle)); 247 shared_writer_ = new SharedWriter(std::move(data_pipe.producer_handle));
256 handle_watcher_.Watch(shared_writer_->writer(), MOJO_HANDLE_SIGNAL_WRITABLE, 248 handle_watcher_.Watch(shared_writer_->writer(), MOJO_HANDLE_SIGNAL_WRITABLE,
257 base::Bind(&MojoAsyncResourceHandler::OnWritable, 249 base::Bind(&MojoAsyncResourceHandler::OnWritable,
258 base::Unretained(this))); 250 base::Unretained(this)));
259 handle_watcher_.ArmOrNotify(); 251 handle_watcher_.ArmOrNotify();
260 }
261 252
262 bool defer = false; 253 bool defer = false;
263 if (!AllocateWriterIOBuffer(&buffer_, &defer)) { 254 scoped_refptr<net::IOBufferWithSize> buffer;
264 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); 255 if (!AllocateWriterIOBuffer(&buffer, &defer)) {
265 return;
266 }
267
268 if (defer) {
269 DCHECK(!buffer_);
270 parent_buffer_ = buf;
271 parent_buffer_size_ = buf_size;
272 HoldController(std::move(controller));
273 request()->LogBlockedBy("MojoAsyncResourceHandler");
274 did_defer_on_will_read_ = true;
275 return;
276 }
277
278 // The first call to OnWillRead must return a buffer of at least
279 // kMinAllocationSize. If the Mojo buffer is too small, need to allocate an
280 // intermediary buffer.
281 if (first_call && static_cast<size_t>(buffer_->size()) < kMinAllocationSize) {
282 // The allocated buffer is too small, so need to create an intermediary one.
283 if (EndWrite(0) != MOJO_RESULT_OK) {
284 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); 256 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
285 return; 257 return;
286 } 258 }
259 if (!defer) {
260 if (static_cast<size_t>(buffer->size()) >= kMinAllocationSize) {
261 *buf = buffer_ = buffer;
262 *buf_size = buffer_->size();
263 controller->Resume();
264 return;
265 }
266
267 // The allocated buffer is too small.
268 if (EndWrite(0) != MOJO_RESULT_OK) {
269 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
270 return;
271 }
272 }
287 DCHECK(!is_using_io_buffer_not_from_writer_); 273 DCHECK(!is_using_io_buffer_not_from_writer_);
288 is_using_io_buffer_not_from_writer_ = true; 274 is_using_io_buffer_not_from_writer_ = true;
289 buffer_ = new net::IOBufferWithSize(kMinAllocationSize); 275 buffer_ = new net::IOBufferWithSize(kMinAllocationSize);
290 } 276 }
291 277
278 DCHECK_EQ(0u, buffer_offset_);
292 *buf = buffer_; 279 *buf = buffer_;
293 *buf_size = buffer_->size(); 280 *buf_size = buffer_->size();
294 controller->Resume(); 281 controller->Resume();
295 } 282 }
296 283
297 void MojoAsyncResourceHandler::OnReadCompleted( 284 void MojoAsyncResourceHandler::OnReadCompleted(
298 int bytes_read, 285 int bytes_read,
299 std::unique_ptr<ResourceController> controller) { 286 std::unique_ptr<ResourceController> controller) {
300 DCHECK(!has_controller()); 287 DCHECK(!has_controller());
301 DCHECK_GE(bytes_read, 0); 288 DCHECK_GE(bytes_read, 0);
302 DCHECK(buffer_); 289 DCHECK(buffer_);
303 290
304 if (bytes_read == 0) { 291 if (!bytes_read) {
305 // Note that |buffer_| is not cleared here, which will cause a DCHECK on
306 // subsequent OnWillRead calls.
307 controller->Resume(); 292 controller->Resume();
308 return; 293 return;
309 } 294 }
310 295
311 const ResourceRequestInfoImpl* info = GetRequestInfo(); 296 const ResourceRequestInfoImpl* info = GetRequestInfo();
312 if (info->ShouldReportRawHeaders()) { 297 if (info->ShouldReportRawHeaders()) {
313 auto transfer_size_diff = CalculateRecentlyReceivedBytes(); 298 auto transfer_size_diff = CalculateRecentlyReceivedBytes();
314 if (transfer_size_diff > 0) 299 if (transfer_size_diff > 0)
315 url_loader_client_->OnTransferSizeUpdated(transfer_size_diff); 300 url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
316 } 301 }
317 302
318 if (response_body_consumer_handle_.is_valid()) { 303 if (response_body_consumer_handle_.is_valid()) {
319 // Send the data pipe on the first OnReadCompleted call. 304 // Send the data pipe on the first OnReadCompleted call.
320 url_loader_client_->OnStartLoadingResponseBody( 305 url_loader_client_->OnStartLoadingResponseBody(
321 std::move(response_body_consumer_handle_)); 306 std::move(response_body_consumer_handle_));
322 response_body_consumer_handle_.reset(); 307 response_body_consumer_handle_.reset();
323 } 308 }
324 309
325 if (is_using_io_buffer_not_from_writer_) { 310 if (is_using_io_buffer_not_from_writer_) {
326 // Couldn't allocate a large enough buffer on the data pipe in OnWillRead. 311 // Couldn't allocate a buffer on the data pipe in OnWillRead.
327 DCHECK_EQ(0u, buffer_bytes_read_); 312 DCHECK_EQ(0u, buffer_bytes_read_);
328 buffer_bytes_read_ = bytes_read; 313 buffer_bytes_read_ = bytes_read;
329 bool defer = false; 314 bool defer = false;
330 if (!CopyReadDataToDataPipe(&defer)) { 315 if (!CopyReadDataToDataPipe(&defer)) {
331 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); 316 controller->Cancel();
332 return; 317 return;
333 } 318 }
334 if (defer) { 319 if (defer) {
335 request()->LogBlockedBy("MojoAsyncResourceHandler"); 320 request()->LogBlockedBy("MojoAsyncResourceHandler");
336 did_defer_on_writing_ = true; 321 did_defer_on_writing_ = true;
337 HoldController(std::move(controller)); 322 HoldController(std::move(controller));
338 return; 323 return;
339 } 324 }
340 controller->Resume(); 325 controller->Resume();
341 return; 326 return;
342 } 327 }
343 328
344 if (EndWrite(bytes_read) != MOJO_RESULT_OK) { 329 if (EndWrite(bytes_read) != MOJO_RESULT_OK) {
345 controller->Cancel(); 330 controller->Cancel();
346 return; 331 return;
347 } 332 }
333 // Allocate a buffer for the next OnWillRead call here, because OnWillRead
334 // doesn't have |defer| parameter.
335 bool defer = false;
336 if (!AllocateWriterIOBuffer(&buffer_, &defer)) {
337 controller->Cancel();
338 return;
339 }
340 if (defer) {
341 request()->LogBlockedBy("MojoAsyncResourceHandler");
342 did_defer_on_writing_ = true;
343 HoldController(std::move(controller));
344 return;
345 }
348 346
349 buffer_ = nullptr;
350 controller->Resume(); 347 controller->Resume();
351 } 348 }
352 349
353 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { 350 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
354 url_loader_client_->OnDataDownloaded(bytes_downloaded, 351 url_loader_client_->OnDataDownloaded(bytes_downloaded,
355 CalculateRecentlyReceivedBytes()); 352 CalculateRecentlyReceivedBytes());
356 } 353 }
357 354
358 void MojoAsyncResourceHandler::FollowRedirect() { 355 void MojoAsyncResourceHandler::FollowRedirect() {
359 if (!request()->status().is_success()) { 356 if (!request()->status().is_success()) {
360 DVLOG(1) << "FollowRedirect for invalid request"; 357 DVLOG(1) << "FollowRedirect for invalid request";
361 return; 358 return;
362 } 359 }
363 if (!did_defer_on_redirect_) { 360 if (!did_defer_on_redirect_) {
364 DVLOG(1) << "Malformed FollowRedirect request"; 361 DVLOG(1) << "Malformed FollowRedirect request";
365 ReportBadMessage("Malformed FollowRedirect request"); 362 ReportBadMessage("Malformed FollowRedirect request");
366 return; 363 return;
367 } 364 }
368 365
369 DCHECK(!did_defer_on_will_read_);
370 DCHECK(!did_defer_on_writing_); 366 DCHECK(!did_defer_on_writing_);
371 did_defer_on_redirect_ = false; 367 did_defer_on_redirect_ = false;
372 request()->LogUnblocked(); 368 request()->LogUnblocked();
373 Resume(); 369 Resume();
374 } 370 }
375 371
376 void MojoAsyncResourceHandler::SetPriority(net::RequestPriority priority, 372 void MojoAsyncResourceHandler::SetPriority(net::RequestPriority priority,
377 int32_t intra_priority_value) { 373 int32_t intra_priority_value) {
378 ResourceDispatcherHostImpl::Get()->scheduler()->ReprioritizeRequest( 374 ResourceDispatcherHostImpl::Get()->scheduler()->ReprioritizeRequest(
379 request(), priority, intra_priority_value); 375 request(), priority, intra_priority_value);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 request_complete_data.completion_time = base::TimeTicks::Now(); 447 request_complete_data.completion_time = base::TimeTicks::Now();
452 request_complete_data.encoded_data_length = 448 request_complete_data.encoded_data_length =
453 request()->GetTotalReceivedBytes(); 449 request()->GetTotalReceivedBytes();
454 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); 450 request_complete_data.encoded_body_length = request()->GetRawBodyBytes();
455 451
456 url_loader_client_->OnComplete(request_complete_data); 452 url_loader_client_->OnComplete(request_complete_data);
457 controller->Resume(); 453 controller->Resume();
458 } 454 }
459 455
460 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) { 456 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) {
461 while (buffer_bytes_read_ > 0) { 457 while (true) {
462 scoped_refptr<net::IOBufferWithSize> dest; 458 scoped_refptr<net::IOBufferWithSize> dest;
463 if (!AllocateWriterIOBuffer(&dest, defer)) 459 if (!AllocateWriterIOBuffer(&dest, defer))
464 return false; 460 return false;
465 if (*defer) 461 if (*defer)
466 return true; 462 return true;
463 if (buffer_bytes_read_ == 0) {
464 // All bytes are copied. Save the buffer for the next OnWillRead call.
465 buffer_ = std::move(dest);
466 return true;
467 }
467 468
468 size_t copied_size = 469 size_t copied_size =
469 std::min(buffer_bytes_read_, static_cast<size_t>(dest->size())); 470 std::min(buffer_bytes_read_, static_cast<size_t>(dest->size()));
470 memcpy(dest->data(), buffer_->data() + buffer_offset_, copied_size); 471 memcpy(dest->data(), buffer_->data() + buffer_offset_, copied_size);
471 buffer_offset_ += copied_size; 472 buffer_offset_ += copied_size;
472 buffer_bytes_read_ -= copied_size; 473 buffer_bytes_read_ -= copied_size;
473 if (EndWrite(copied_size) != MOJO_RESULT_OK) 474 if (EndWrite(copied_size) != MOJO_RESULT_OK)
474 return false; 475 return false;
476
477 if (buffer_bytes_read_ == 0) {
478 // All bytes are copied.
479 buffer_offset_ = 0;
480 is_using_io_buffer_not_from_writer_ = false;
481 }
475 } 482 }
476
477 // All bytes are copied.
478 buffer_ = nullptr;
479 buffer_offset_ = 0;
480 is_using_io_buffer_not_from_writer_ = false;
481 return true;
482 } 483 }
483 484
484 bool MojoAsyncResourceHandler::AllocateWriterIOBuffer( 485 bool MojoAsyncResourceHandler::AllocateWriterIOBuffer(
485 scoped_refptr<net::IOBufferWithSize>* buf, 486 scoped_refptr<net::IOBufferWithSize>* buf,
486 bool* defer) { 487 bool* defer) {
487 void* data = nullptr; 488 void* data = nullptr;
488 uint32_t available = 0; 489 uint32_t available = 0;
489 MojoResult result = BeginWrite(&data, &available); 490 MojoResult result = BeginWrite(&data, &available);
490 if (result == MOJO_RESULT_SHOULD_WAIT) { 491 if (result == MOJO_RESULT_SHOULD_WAIT) {
491 *defer = true; 492 *defer = true;
492 return true; 493 return true;
493 } 494 }
494 if (result != MOJO_RESULT_OK) 495 if (result != MOJO_RESULT_OK)
495 return false; 496 return false;
496 DCHECK_GT(available, 0u);
497 *buf = new WriterIOBuffer(shared_writer_, data, available); 497 *buf = new WriterIOBuffer(shared_writer_, data, available);
498 return true; 498 return true;
499 } 499 }
500 500
501 bool MojoAsyncResourceHandler::CheckForSufficientResource() { 501 bool MojoAsyncResourceHandler::CheckForSufficientResource() {
502 if (has_checked_for_sufficient_resources_) 502 if (has_checked_for_sufficient_resources_)
503 return true; 503 return true;
504 has_checked_for_sufficient_resources_ = true; 504 has_checked_for_sufficient_resources_ = true;
505 505
506 if (rdh_->HasSufficientResourcesForRequest(request())) 506 if (rdh_->HasSufficientResourcesForRequest(request()))
507 return true; 507 return true;
508 508
509 return false; 509 return false;
510 } 510 }
511 511
512 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { 512 void MojoAsyncResourceHandler::OnWritable(MojoResult result) {
513 if (did_defer_on_will_read_) {
514 DCHECK(has_controller());
515 DCHECK(!did_defer_on_writing_);
516 DCHECK(!did_defer_on_redirect_);
517
518 did_defer_on_will_read_ = false;
519
520 scoped_refptr<net::IOBuffer>* parent_buffer = parent_buffer_;
521 parent_buffer_ = nullptr;
522 int* parent_buffer_size = parent_buffer_size_;
523 parent_buffer_size_ = nullptr;
524 OnWillRead(parent_buffer, parent_buffer_size, ReleaseController());
525 return;
526 }
527
528 if (!did_defer_on_writing_) 513 if (!did_defer_on_writing_)
529 return; 514 return;
530 DCHECK(has_controller()); 515 DCHECK(has_controller());
531 DCHECK(!did_defer_on_redirect_); 516 DCHECK(!did_defer_on_redirect_);
532 did_defer_on_writing_ = false; 517 did_defer_on_writing_ = false;
533 518
534 DCHECK(is_using_io_buffer_not_from_writer_); 519 if (is_using_io_buffer_not_from_writer_) {
535 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents 520 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents
536 // to the data pipe. 521 // to the data pipe.
537 DCHECK_GT(buffer_bytes_read_, 0u); 522 DCHECK_GT(buffer_bytes_read_, 0u);
538 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { 523 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) {
539 CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); 524 CancelWithError(net::ERR_FAILED);
540 return; 525 return;
526 }
527 } else {
528 // Allocate a buffer for the next OnWillRead call here.
529 if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) {
530 CancelWithError(net::ERR_FAILED);
531 return;
532 }
541 } 533 }
542 534
543 if (did_defer_on_writing_) { 535 if (did_defer_on_writing_) {
544 // Continue waiting. 536 // Continue waiting.
545 return; 537 return;
546 } 538 }
547 request()->LogUnblocked(); 539 request()->LogUnblocked();
548 Resume(); 540 Resume();
549 } 541 }
550 542
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 base::Bind(&MojoAsyncResourceHandler::OnUploadProgressACK, 584 base::Bind(&MojoAsyncResourceHandler::OnUploadProgressACK,
593 weak_factory_.GetWeakPtr())); 585 weak_factory_.GetWeakPtr()));
594 } 586 }
595 587
596 void MojoAsyncResourceHandler::OnUploadProgressACK() { 588 void MojoAsyncResourceHandler::OnUploadProgressACK() {
597 if (upload_progress_tracker_) 589 if (upload_progress_tracker_)
598 upload_progress_tracker_->OnAckReceived(); 590 upload_progress_tracker_->OnAckReceived();
599 } 591 }
600 592
601 } // namespace content 593 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/mojo_async_resource_handler.h ('k') | content/browser/loader/mojo_async_resource_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698