OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/async_resource_handler.h" | 5 #include "content/browser/loader/async_resource_handler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 if (buffer_->CanAllocate()) | 242 if (buffer_->CanAllocate()) |
243 ResumeIfDeferred(); | 243 ResumeIfDeferred(); |
244 } | 244 } |
245 } | 245 } |
246 | 246 |
247 void AsyncResourceHandler::OnUploadProgressACK(int request_id) { | 247 void AsyncResourceHandler::OnUploadProgressACK(int request_id) { |
248 if (upload_progress_tracker_) | 248 if (upload_progress_tracker_) |
249 upload_progress_tracker_->OnAckReceived(); | 249 upload_progress_tracker_->OnAckReceived(); |
250 } | 250 } |
251 | 251 |
252 bool AsyncResourceHandler::OnRequestRedirected( | 252 void AsyncResourceHandler::OnRequestRedirected( |
253 const net::RedirectInfo& redirect_info, | 253 const net::RedirectInfo& redirect_info, |
254 ResourceResponse* response, | 254 ResourceResponse* response, |
255 bool* defer) { | 255 std::unique_ptr<ResourceController> controller) { |
256 ResourceMessageFilter* filter = GetFilter(); | 256 ResourceMessageFilter* filter = GetFilter(); |
257 if (!filter) | 257 if (!filter) { |
258 return false; | 258 controller->Cancel(); |
259 | 259 return; |
260 *defer = did_defer_ = true; | 260 } |
261 OnDefer(); | |
262 | 261 |
263 NetLogObserver::PopulateResponseInfo(request(), response); | 262 NetLogObserver::PopulateResponseInfo(request(), response); |
264 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); | 263 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); |
265 reported_transfer_size_ = 0; | 264 reported_transfer_size_ = 0; |
266 response->head.request_start = request()->creation_time(); | 265 response->head.request_start = request()->creation_time(); |
267 response->head.response_start = TimeTicks::Now(); | 266 response->head.response_start = TimeTicks::Now(); |
268 // TODO(davidben): Is it necessary to pass the new first party URL for | 267 // TODO(davidben): Is it necessary to pass the new first party URL for |
269 // cookies? The only case where it can change is top-level navigation requests | 268 // cookies? The only case where it can change is top-level navigation requests |
270 // and hopefully those will eventually all be owned by the browser. It's | 269 // and hopefully those will eventually all be owned by the browser. It's |
271 // possible this is still needed while renderer-owned ones exist. | 270 // possible this is still needed while renderer-owned ones exist. |
272 return filter->Send(new ResourceMsg_ReceivedRedirect( | 271 if (!filter->Send(new ResourceMsg_ReceivedRedirect( |
273 GetRequestID(), redirect_info, response->head)); | 272 GetRequestID(), redirect_info, response->head))) { |
| 273 controller->Cancel(); |
| 274 } else { |
| 275 did_defer_ = true; |
| 276 OnDefer(); |
| 277 set_controller(std::move(controller)); |
| 278 } |
274 } | 279 } |
275 | 280 |
276 bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response, | 281 void AsyncResourceHandler::OnResponseStarted( |
277 bool* defer) { | 282 ResourceResponse* response, |
| 283 std::unique_ptr<ResourceController> controller) { |
278 // For changes to the main frame, inform the renderer of the new URL's | 284 // For changes to the main frame, inform the renderer of the new URL's |
279 // per-host settings before the request actually commits. This way the | 285 // per-host settings before the request actually commits. This way the |
280 // renderer will be able to set these precisely at the time the | 286 // renderer will be able to set these precisely at the time the |
281 // request commits, avoiding the possibility of e.g. zooming the old content | 287 // request commits, avoiding the possibility of e.g. zooming the old content |
282 // or of having to layout the new content twice. | 288 // or of having to layout the new content twice. |
| 289 DCHECK(!has_controller()); |
283 | 290 |
284 response_started_ticks_ = base::TimeTicks::Now(); | 291 response_started_ticks_ = base::TimeTicks::Now(); |
285 | 292 |
286 // We want to send a final upload progress message prior to sending the | 293 // We want to send a final upload progress message prior to sending the |
287 // response complete message even if we're waiting for an ack to to a | 294 // response complete message even if we're waiting for an ack to to a |
288 // previous upload progress message. | 295 // previous upload progress message. |
289 if (upload_progress_tracker_) { | 296 if (upload_progress_tracker_) { |
290 upload_progress_tracker_->OnUploadCompleted(); | 297 upload_progress_tracker_->OnUploadCompleted(); |
291 upload_progress_tracker_ = nullptr; | 298 upload_progress_tracker_ = nullptr; |
292 } | 299 } |
293 | 300 |
294 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 301 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
295 if (rdh_->delegate()) { | 302 if (rdh_->delegate()) { |
296 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), | 303 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), |
297 response); | 304 response); |
298 } | 305 } |
299 | 306 |
300 ResourceMessageFilter* filter = GetFilter(); | 307 ResourceMessageFilter* filter = GetFilter(); |
301 if (!filter) | 308 if (!filter) { |
302 return false; | 309 controller->Cancel(); |
| 310 return; |
| 311 } |
303 | 312 |
304 NetLogObserver::PopulateResponseInfo(request(), response); | 313 NetLogObserver::PopulateResponseInfo(request(), response); |
305 response->head.encoded_data_length = request()->raw_header_size(); | 314 response->head.encoded_data_length = request()->raw_header_size(); |
306 | 315 |
307 // If the parent handler downloaded the resource to a file, grant the child | 316 // If the parent handler downloaded the resource to a file, grant the child |
308 // read permissions on it. | 317 // read permissions on it. |
309 if (!response->head.download_file_path.empty()) { | 318 if (!response->head.download_file_path.empty()) { |
310 rdh_->RegisterDownloadedTempFile( | 319 rdh_->RegisterDownloadedTempFile( |
311 info->GetChildID(), info->GetRequestID(), | 320 info->GetChildID(), info->GetRequestID(), |
312 response->head.download_file_path); | 321 response->head.download_file_path); |
313 } | 322 } |
314 | 323 |
315 response->head.request_start = request()->creation_time(); | 324 response->head.request_start = request()->creation_time(); |
316 response->head.response_start = TimeTicks::Now(); | 325 response->head.response_start = TimeTicks::Now(); |
317 filter->Send( | 326 filter->Send( |
318 new ResourceMsg_ReceivedResponse(GetRequestID(), response->head)); | 327 new ResourceMsg_ReceivedResponse(GetRequestID(), response->head)); |
319 sent_received_response_msg_ = true; | 328 sent_received_response_msg_ = true; |
320 | 329 |
321 if (request()->response_info().metadata.get()) { | 330 if (request()->response_info().metadata.get()) { |
322 std::vector<char> copy(request()->response_info().metadata->data(), | 331 std::vector<char> copy(request()->response_info().metadata->data(), |
323 request()->response_info().metadata->data() + | 332 request()->response_info().metadata->data() + |
324 request()->response_info().metadata->size()); | 333 request()->response_info().metadata->size()); |
325 filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy)); | 334 filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy)); |
326 } | 335 } |
327 | 336 |
328 inlining_helper_->OnResponseReceived(*response); | 337 inlining_helper_->OnResponseReceived(*response); |
329 return true; | 338 controller->Resume(); |
330 } | 339 } |
331 | 340 |
332 bool AsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 341 void AsyncResourceHandler::OnWillStart( |
| 342 const GURL& url, |
| 343 std::unique_ptr<ResourceController> controller) { |
333 ResourceMessageFilter* filter = GetFilter(); | 344 ResourceMessageFilter* filter = GetFilter(); |
334 if (!filter) | 345 if (!filter) { |
335 return false; | 346 controller->Cancel(); |
| 347 return; |
| 348 } |
336 | 349 |
337 if (GetRequestInfo()->is_upload_progress_enabled() && | 350 if (GetRequestInfo()->is_upload_progress_enabled() && |
338 request()->has_upload()) { | 351 request()->has_upload()) { |
339 upload_progress_tracker_ = base::MakeUnique<UploadProgressTracker>( | 352 upload_progress_tracker_ = base::MakeUnique<UploadProgressTracker>( |
340 FROM_HERE, | 353 FROM_HERE, |
341 base::BindRepeating(&AsyncResourceHandler::SendUploadProgress, | 354 base::BindRepeating(&AsyncResourceHandler::SendUploadProgress, |
342 base::Unretained(this)), | 355 base::Unretained(this)), |
343 request()); | 356 request()); |
344 } | 357 } |
345 return true; | 358 controller->Resume(); |
346 } | 359 } |
347 | 360 |
348 bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 361 bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
349 int* buf_size, | 362 int* buf_size, |
350 int min_size) { | 363 int min_size) { |
| 364 DCHECK(!has_controller()); |
351 DCHECK_EQ(-1, min_size); | 365 DCHECK_EQ(-1, min_size); |
352 | 366 |
| 367 // TODO(mmenke): Should fail with ERR_INSUFFICIENT_RESOURCES here. |
353 if (!CheckForSufficientResource()) | 368 if (!CheckForSufficientResource()) |
354 return false; | 369 return false; |
355 | 370 |
356 // Return early if InliningHelper allocates the buffer, so that we should | 371 // Return early if InliningHelper allocates the buffer, so that we should |
357 // inline the data into the IPC message without allocating SharedMemory. | 372 // inline the data into the IPC message without allocating SharedMemory. |
358 if (inlining_helper_->PrepareInlineBufferIfApplicable(buf, buf_size)) | 373 if (inlining_helper_->PrepareInlineBufferIfApplicable(buf, buf_size)) |
359 return true; | 374 return true; |
360 | 375 |
361 if (!EnsureResourceBufferIsInitialized()) | 376 if (!EnsureResourceBufferIsInitialized()) |
362 return false; | 377 return false; |
363 | 378 |
364 DCHECK(buffer_->CanAllocate()); | 379 DCHECK(buffer_->CanAllocate()); |
365 char* memory = buffer_->Allocate(&allocation_size_); | 380 char* memory = buffer_->Allocate(&allocation_size_); |
366 CHECK(memory); | 381 CHECK(memory); |
367 | 382 |
368 *buf = new DependentIOBuffer(buffer_.get(), memory); | 383 *buf = new DependentIOBuffer(buffer_.get(), memory); |
369 *buf_size = allocation_size_; | 384 *buf_size = allocation_size_; |
370 | 385 |
371 return true; | 386 return true; |
372 } | 387 } |
373 | 388 |
374 bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 389 void AsyncResourceHandler::OnReadCompleted( |
| 390 int bytes_read, |
| 391 std::unique_ptr<ResourceController> controller) { |
| 392 DCHECK(!has_controller()); |
375 DCHECK_GE(bytes_read, 0); | 393 DCHECK_GE(bytes_read, 0); |
376 | 394 |
377 if (!bytes_read) | 395 if (!bytes_read) { |
378 return true; | 396 controller->Resume(); |
| 397 return; |
| 398 } |
379 | 399 |
380 ResourceMessageFilter* filter = GetFilter(); | 400 ResourceMessageFilter* filter = GetFilter(); |
381 if (!filter) | 401 if (!filter) { |
382 return false; | 402 controller->Cancel(); |
| 403 return; |
| 404 } |
383 | 405 |
384 int encoded_data_length = CalculateEncodedDataLengthToReport(); | 406 int encoded_data_length = CalculateEncodedDataLengthToReport(); |
385 if (!first_chunk_read_) | 407 if (!first_chunk_read_) |
386 encoded_data_length -= request()->raw_header_size(); | 408 encoded_data_length -= request()->raw_header_size(); |
387 | 409 |
388 first_chunk_read_ = true; | 410 first_chunk_read_ = true; |
389 | 411 |
390 // Return early if InliningHelper handled the received data. | 412 // Return early if InliningHelper handled the received data. |
391 if (inlining_helper_->SendInlinedDataIfApplicable( | 413 if (inlining_helper_->SendInlinedDataIfApplicable( |
392 bytes_read, encoded_data_length, filter, | 414 bytes_read, encoded_data_length, filter, GetRequestID())) { |
393 GetRequestID())) | 415 controller->Resume(); |
394 return true; | 416 return; |
| 417 } |
395 | 418 |
396 buffer_->ShrinkLastAllocation(bytes_read); | 419 buffer_->ShrinkLastAllocation(bytes_read); |
397 | 420 |
398 if (!sent_data_buffer_msg_) { | 421 if (!sent_data_buffer_msg_) { |
399 base::SharedMemoryHandle handle = base::SharedMemory::DuplicateHandle( | 422 base::SharedMemoryHandle handle = base::SharedMemory::DuplicateHandle( |
400 buffer_->GetSharedMemory().handle()); | 423 buffer_->GetSharedMemory().handle()); |
401 if (!base::SharedMemory::IsHandleValid(handle)) | 424 if (!base::SharedMemory::IsHandleValid(handle)) { |
402 return false; | 425 controller->Cancel(); |
| 426 return; |
| 427 } |
403 filter->Send(new ResourceMsg_SetDataBuffer( | 428 filter->Send(new ResourceMsg_SetDataBuffer( |
404 GetRequestID(), handle, buffer_->GetSharedMemory().mapped_size(), | 429 GetRequestID(), handle, buffer_->GetSharedMemory().mapped_size(), |
405 filter->peer_pid())); | 430 filter->peer_pid())); |
406 sent_data_buffer_msg_ = true; | 431 sent_data_buffer_msg_ = true; |
407 } | 432 } |
408 | 433 |
409 int data_offset = buffer_->GetLastAllocationOffset(); | 434 int data_offset = buffer_->GetLastAllocationOffset(); |
410 | 435 |
411 filter->Send(new ResourceMsg_DataReceived(GetRequestID(), data_offset, | 436 filter->Send(new ResourceMsg_DataReceived(GetRequestID(), data_offset, |
412 bytes_read, encoded_data_length)); | 437 bytes_read, encoded_data_length)); |
413 ++pending_data_count_; | 438 ++pending_data_count_; |
414 | 439 |
415 if (!buffer_->CanAllocate()) { | 440 if (!buffer_->CanAllocate()) { |
416 *defer = did_defer_ = true; | 441 did_defer_ = true; |
417 OnDefer(); | 442 OnDefer(); |
| 443 set_controller(std::move(controller)); |
| 444 } else { |
| 445 controller->Resume(); |
418 } | 446 } |
419 | |
420 return true; | |
421 } | 447 } |
422 | 448 |
423 void AsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { | 449 void AsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
424 int encoded_data_length = CalculateEncodedDataLengthToReport(); | 450 int encoded_data_length = CalculateEncodedDataLengthToReport(); |
425 | 451 |
426 ResourceMessageFilter* filter = GetFilter(); | 452 ResourceMessageFilter* filter = GetFilter(); |
427 if (filter) { | 453 if (filter) { |
428 filter->Send(new ResourceMsg_DataDownloaded( | 454 filter->Send(new ResourceMsg_DataDownloaded( |
429 GetRequestID(), bytes_downloaded, encoded_data_length)); | 455 GetRequestID(), bytes_downloaded, encoded_data_length)); |
430 } | 456 } |
431 } | 457 } |
432 | 458 |
433 void AsyncResourceHandler::OnResponseCompleted( | 459 void AsyncResourceHandler::OnResponseCompleted( |
434 const net::URLRequestStatus& status, | 460 const net::URLRequestStatus& status, |
435 bool* defer) { | 461 std::unique_ptr<ResourceController> controller) { |
436 ResourceMessageFilter* filter = GetFilter(); | 462 ResourceMessageFilter* filter = GetFilter(); |
437 if (!filter) | 463 if (!filter) { |
| 464 controller->Resume(); |
438 return; | 465 return; |
| 466 } |
439 | 467 |
440 // Ensure sending the final upload progress message here, since | 468 // Ensure sending the final upload progress message here, since |
441 // OnResponseCompleted can be called without OnResponseStarted on cancellation | 469 // OnResponseCompleted can be called without OnResponseStarted on cancellation |
442 // or error cases. | 470 // or error cases. |
443 if (upload_progress_tracker_) { | 471 if (upload_progress_tracker_) { |
444 upload_progress_tracker_->OnUploadCompleted(); | 472 upload_progress_tracker_->OnUploadCompleted(); |
445 upload_progress_tracker_ = nullptr; | 473 upload_progress_tracker_ = nullptr; |
446 } | 474 } |
447 | 475 |
448 // If we crash here, figure out what URL the renderer was requesting. | 476 // If we crash here, figure out what URL the renderer was requesting. |
(...skipping 26 matching lines...) Expand all Loading... |
475 request_complete_data.exists_in_cache = request()->response_info().was_cached; | 503 request_complete_data.exists_in_cache = request()->response_info().was_cached; |
476 request_complete_data.completion_time = TimeTicks::Now(); | 504 request_complete_data.completion_time = TimeTicks::Now(); |
477 request_complete_data.encoded_data_length = | 505 request_complete_data.encoded_data_length = |
478 request()->GetTotalReceivedBytes(); | 506 request()->GetTotalReceivedBytes(); |
479 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); | 507 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); |
480 filter->Send( | 508 filter->Send( |
481 new ResourceMsg_RequestComplete(GetRequestID(), request_complete_data)); | 509 new ResourceMsg_RequestComplete(GetRequestID(), request_complete_data)); |
482 | 510 |
483 if (status.is_success()) | 511 if (status.is_success()) |
484 RecordHistogram(); | 512 RecordHistogram(); |
| 513 controller->Resume(); |
485 } | 514 } |
486 | 515 |
487 bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() { | 516 bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() { |
488 DCHECK(has_checked_for_sufficient_resources_); | 517 DCHECK(has_checked_for_sufficient_resources_); |
489 | 518 |
490 if (buffer_.get() && buffer_->IsInitialized()) | 519 if (buffer_.get() && buffer_->IsInitialized()) |
491 return true; | 520 return true; |
492 | 521 |
493 buffer_ = new ResourceBuffer(); | 522 buffer_ = new ResourceBuffer(); |
494 return buffer_->Initialize(kBufferSize, | 523 return buffer_->Initialize(kBufferSize, |
495 kMinAllocationSize, | 524 kMinAllocationSize, |
496 kMaxAllocationSize); | 525 kMaxAllocationSize); |
497 } | 526 } |
498 | 527 |
499 void AsyncResourceHandler::ResumeIfDeferred() { | 528 void AsyncResourceHandler::ResumeIfDeferred() { |
500 if (did_defer_) { | 529 if (did_defer_) { |
501 did_defer_ = false; | 530 did_defer_ = false; |
502 request()->LogUnblocked(); | 531 request()->LogUnblocked(); |
503 controller()->Resume(); | 532 Resume(); |
504 } | 533 } |
505 } | 534 } |
506 | 535 |
507 void AsyncResourceHandler::OnDefer() { | 536 void AsyncResourceHandler::OnDefer() { |
508 request()->LogBlockedBy("AsyncResourceHandler"); | 537 request()->LogBlockedBy("AsyncResourceHandler"); |
509 } | 538 } |
510 | 539 |
511 bool AsyncResourceHandler::CheckForSufficientResource() { | 540 bool AsyncResourceHandler::CheckForSufficientResource() { |
512 if (has_checked_for_sufficient_resources_) | 541 if (has_checked_for_sufficient_resources_) |
513 return true; | 542 return true; |
514 has_checked_for_sufficient_resources_ = true; | 543 has_checked_for_sufficient_resources_ = true; |
515 | 544 |
516 if (rdh_->HasSufficientResourcesForRequest(request())) | 545 if (rdh_->HasSufficientResourcesForRequest(request())) |
517 return true; | 546 return true; |
518 | 547 |
519 controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); | |
520 return false; | 548 return false; |
521 } | 549 } |
522 | 550 |
523 int AsyncResourceHandler::CalculateEncodedDataLengthToReport() { | 551 int AsyncResourceHandler::CalculateEncodedDataLengthToReport() { |
524 const auto transfer_size = request()->GetTotalReceivedBytes(); | 552 const auto transfer_size = request()->GetTotalReceivedBytes(); |
525 const auto difference = transfer_size - reported_transfer_size_; | 553 const auto difference = transfer_size - reported_transfer_size_; |
526 reported_transfer_size_ = transfer_size; | 554 reported_transfer_size_ = transfer_size; |
527 return difference; | 555 return difference; |
528 } | 556 } |
529 | 557 |
(...skipping 26 matching lines...) Expand all Loading... |
556 void AsyncResourceHandler::SendUploadProgress(int64_t current_position, | 584 void AsyncResourceHandler::SendUploadProgress(int64_t current_position, |
557 int64_t total_size) { | 585 int64_t total_size) { |
558 ResourceMessageFilter* filter = GetFilter(); | 586 ResourceMessageFilter* filter = GetFilter(); |
559 if (!filter) | 587 if (!filter) |
560 return; | 588 return; |
561 filter->Send(new ResourceMsg_UploadProgress( | 589 filter->Send(new ResourceMsg_UploadProgress( |
562 GetRequestID(), current_position, total_size)); | 590 GetRequestID(), current_position, total_size)); |
563 } | 591 } |
564 | 592 |
565 } // namespace content | 593 } // namespace content |
OLD | NEW |