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 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading |
6 | 6 |
7 #include "content/child/resource_dispatcher.h" | 7 #include "content/child/resource_dispatcher.h" |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 return true; | 122 return true; |
123 } | 123 } |
124 } | 124 } |
125 | 125 |
126 DispatchMessage(message); | 126 DispatchMessage(message); |
127 return true; | 127 return true; |
128 } | 128 } |
129 | 129 |
130 ResourceDispatcher::PendingRequestInfo* | 130 ResourceDispatcher::PendingRequestInfo* |
131 ResourceDispatcher::GetPendingRequestInfo(int request_id) { | 131 ResourceDispatcher::GetPendingRequestInfo(int request_id) { |
132 PendingRequestList::iterator it = pending_requests_.find(request_id); | 132 PendingRequestMap::iterator it = pending_requests_.find(request_id); |
133 if (it == pending_requests_.end()) { | 133 if (it == pending_requests_.end()) { |
134 // This might happen for kill()ed requests on the webkit end. | 134 // This might happen for kill()ed requests on the webkit end. |
135 return NULL; | 135 return NULL; |
136 } | 136 } |
137 return &(it->second); | 137 return it->second.get(); |
138 } | 138 } |
139 | 139 |
140 void ResourceDispatcher::OnUploadProgress(int request_id, | 140 void ResourceDispatcher::OnUploadProgress(int request_id, |
141 int64_t position, | 141 int64_t position, |
142 int64_t size) { | 142 int64_t size) { |
143 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 143 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
144 if (!request_info) | 144 if (!request_info) |
145 return; | 145 return; |
146 | 146 |
147 request_info->peer->OnUploadProgress(position, size); | 147 request_info->peer->OnUploadProgress(position, size); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 // potentially remove it. | 331 // potentially remove it. |
332 request_info = GetPendingRequestInfo(request_id); | 332 request_info = GetPendingRequestInfo(request_id); |
333 if (!request_info) | 333 if (!request_info) |
334 return; | 334 return; |
335 // We update the response_url here so that we can send it to | 335 // We update the response_url here so that we can send it to |
336 // SiteIsolationStatsGatherer later when OnReceivedResponse is called. | 336 // SiteIsolationStatsGatherer later when OnReceivedResponse is called. |
337 request_info->response_url = redirect_info.new_url; | 337 request_info->response_url = redirect_info.new_url; |
338 request_info->pending_redirect_message.reset( | 338 request_info->pending_redirect_message.reset( |
339 new ResourceHostMsg_FollowRedirect(request_id)); | 339 new ResourceHostMsg_FollowRedirect(request_id)); |
340 if (!request_info->is_deferred) { | 340 if (!request_info->is_deferred) { |
341 FollowPendingRedirect(request_id, *request_info); | 341 FollowPendingRedirect(request_id, request_info); |
342 } | 342 } |
343 } else { | 343 } else { |
344 Cancel(request_id); | 344 Cancel(request_id); |
345 } | 345 } |
346 } | 346 } |
347 | 347 |
348 void ResourceDispatcher::FollowPendingRedirect( | 348 void ResourceDispatcher::FollowPendingRedirect( |
349 int request_id, | 349 int request_id, |
350 PendingRequestInfo& request_info) { | 350 PendingRequestInfo* request_info) { |
351 IPC::Message* msg = request_info.pending_redirect_message.release(); | 351 IPC::Message* msg = request_info->pending_redirect_message.release(); |
352 if (msg) | 352 if (msg) |
353 message_sender_->Send(msg); | 353 message_sender_->Send(msg); |
354 } | 354 } |
355 | 355 |
356 void ResourceDispatcher::OnRequestComplete( | 356 void ResourceDispatcher::OnRequestComplete( |
357 int request_id, | 357 int request_id, |
358 const ResourceMsg_RequestCompleteData& request_complete_data) { | 358 const ResourceMsg_RequestCompleteData& request_complete_data) { |
359 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); | 359 TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete"); |
360 | 360 |
361 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 361 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 RequestPeer* peer = request_info->peer; | 414 RequestPeer* peer = request_info->peer; |
415 peer->OnCompletedRequest(request_complete_data.error_code, | 415 peer->OnCompletedRequest(request_complete_data.error_code, |
416 request_complete_data.was_ignored_by_handler, | 416 request_complete_data.was_ignored_by_handler, |
417 request_complete_data.exists_in_cache, | 417 request_complete_data.exists_in_cache, |
418 request_complete_data.security_info, | 418 request_complete_data.security_info, |
419 renderer_completion_time, | 419 renderer_completion_time, |
420 request_complete_data.encoded_data_length); | 420 request_complete_data.encoded_data_length); |
421 } | 421 } |
422 | 422 |
423 bool ResourceDispatcher::RemovePendingRequest(int request_id) { | 423 bool ResourceDispatcher::RemovePendingRequest(int request_id) { |
424 PendingRequestList::iterator it = pending_requests_.find(request_id); | 424 PendingRequestMap::iterator it = pending_requests_.find(request_id); |
425 if (it == pending_requests_.end()) | 425 if (it == pending_requests_.end()) |
426 return false; | 426 return false; |
427 | 427 |
428 PendingRequestInfo& request_info = it->second; | 428 PendingRequestInfo* request_info = it->second.get(); |
429 | 429 |
430 bool release_downloaded_file = request_info.download_to_file; | 430 bool release_downloaded_file = request_info->download_to_file; |
431 | 431 |
432 ReleaseResourcesInMessageQueue(&request_info.deferred_message_queue); | 432 ReleaseResourcesInMessageQueue(&request_info->deferred_message_queue); |
433 pending_requests_.erase(it); | 433 pending_requests_.erase(it); |
434 | 434 |
435 if (release_downloaded_file) { | 435 if (release_downloaded_file) { |
436 message_sender_->Send( | 436 message_sender_->Send( |
437 new ResourceHostMsg_ReleaseDownloadedFile(request_id)); | 437 new ResourceHostMsg_ReleaseDownloadedFile(request_id)); |
438 } | 438 } |
439 | 439 |
440 if (resource_scheduling_filter_.get()) | 440 if (resource_scheduling_filter_.get()) |
441 resource_scheduling_filter_->ClearRequestIdTaskRunner(request_id); | 441 resource_scheduling_filter_->ClearRequestIdTaskRunner(request_id); |
442 | 442 |
443 return true; | 443 return true; |
444 } | 444 } |
445 | 445 |
446 void ResourceDispatcher::Cancel(int request_id) { | 446 void ResourceDispatcher::Cancel(int request_id) { |
447 PendingRequestList::iterator it = pending_requests_.find(request_id); | 447 PendingRequestMap::iterator it = pending_requests_.find(request_id); |
448 if (it == pending_requests_.end()) { | 448 if (it == pending_requests_.end()) { |
449 DVLOG(1) << "unknown request"; | 449 DVLOG(1) << "unknown request"; |
450 return; | 450 return; |
451 } | 451 } |
452 | 452 |
453 // |completion_time.is_null()| is a proxy for OnRequestComplete never being | 453 // |completion_time.is_null()| is a proxy for OnRequestComplete never being |
454 // called. | 454 // called. |
455 // TODO(csharrison): Remove this code when crbug.com/557430 is resolved. | 455 // TODO(csharrison): Remove this code when crbug.com/557430 is resolved. |
456 // ~250,000 ERR_ABORTED coming into canary with |request_time| < 100ms. Sample | 456 // ~250,000 ERR_ABORTED coming into canary with |request_time| < 100ms. Sample |
457 // by .01% to get something reasonable. | 457 // by .01% to get something reasonable. |
458 PendingRequestInfo& info = it->second; | 458 const PendingRequestInfo& info = *it->second; |
459 int64_t request_time = | 459 int64_t request_time = |
460 (base::TimeTicks::Now() - info.request_start).InMilliseconds(); | 460 (base::TimeTicks::Now() - info.request_start).InMilliseconds(); |
461 if (info.resource_type == ResourceType::RESOURCE_TYPE_MAIN_FRAME && | 461 if (info.resource_type == ResourceType::RESOURCE_TYPE_MAIN_FRAME && |
462 info.completion_time.is_null() && request_time < 100 && | 462 info.completion_time.is_null() && request_time < 100 && |
463 base::RandDouble() < .0001) { | 463 base::RandDouble() < .0001) { |
464 static bool should_dump = true; | 464 static bool should_dump = true; |
465 if (should_dump) { | 465 if (should_dump) { |
466 char url_copy[256] = {0}; | 466 char url_copy[256] = {0}; |
467 strncpy(url_copy, info.response_url.spec().c_str(), | 467 strncpy(url_copy, info.response_url.spec().c_str(), |
468 sizeof(url_copy)); | 468 sizeof(url_copy)); |
469 base::debug::Alias(&url_copy); | 469 base::debug::Alias(&url_copy); |
470 base::debug::Alias(&request_time); | 470 base::debug::Alias(&request_time); |
471 base::debug::DumpWithoutCrashing(); | 471 base::debug::DumpWithoutCrashing(); |
472 should_dump = false; | 472 should_dump = false; |
473 } | 473 } |
474 } | 474 } |
475 // Cancel the request, and clean it up so the bridge will receive no more | 475 // Cancel the request, and clean it up so the bridge will receive no more |
476 // messages. | 476 // messages. |
477 message_sender_->Send(new ResourceHostMsg_CancelRequest(request_id)); | 477 message_sender_->Send(new ResourceHostMsg_CancelRequest(request_id)); |
478 RemovePendingRequest(request_id); | 478 RemovePendingRequest(request_id); |
479 } | 479 } |
480 | 480 |
481 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { | 481 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { |
482 PendingRequestList::iterator it = pending_requests_.find(request_id); | 482 PendingRequestMap::iterator it = pending_requests_.find(request_id); |
483 if (it == pending_requests_.end()) { | 483 if (it == pending_requests_.end()) { |
484 DLOG(ERROR) << "unknown request"; | 484 DLOG(ERROR) << "unknown request"; |
485 return; | 485 return; |
486 } | 486 } |
487 PendingRequestInfo& request_info = it->second; | 487 PendingRequestInfo* request_info = it->second.get(); |
488 if (value) { | 488 if (value) { |
489 request_info.is_deferred = value; | 489 request_info->is_deferred = value; |
490 } else if (request_info.is_deferred) { | 490 } else if (request_info->is_deferred) { |
491 request_info.is_deferred = false; | 491 request_info->is_deferred = false; |
492 | 492 |
493 FollowPendingRedirect(request_id, request_info); | 493 FollowPendingRedirect(request_id, request_info); |
494 | 494 |
495 main_thread_task_runner_->PostTask( | 495 main_thread_task_runner_->PostTask( |
496 FROM_HERE, base::Bind(&ResourceDispatcher::FlushDeferredMessages, | 496 FROM_HERE, base::Bind(&ResourceDispatcher::FlushDeferredMessages, |
497 weak_factory_.GetWeakPtr(), request_id)); | 497 weak_factory_.GetWeakPtr(), request_id)); |
498 } | 498 } |
499 } | 499 } |
500 | 500 |
501 void ResourceDispatcher::DidChangePriority(int request_id, | 501 void ResourceDispatcher::DidChangePriority(int request_id, |
(...skipping 13 matching lines...) Expand all Loading... |
515 DCHECK(!request_info->threaded_data_provider); | 515 DCHECK(!request_info->threaded_data_provider); |
516 request_info->threaded_data_provider = new ThreadedDataProvider( | 516 request_info->threaded_data_provider = new ThreadedDataProvider( |
517 request_id, threaded_data_receiver, request_info->buffer, | 517 request_id, threaded_data_receiver, request_info->buffer, |
518 request_info->buffer_size, main_thread_task_runner_); | 518 request_info->buffer_size, main_thread_task_runner_); |
519 return true; | 519 return true; |
520 } | 520 } |
521 | 521 |
522 return false; | 522 return false; |
523 } | 523 } |
524 | 524 |
525 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo() | |
526 : peer(NULL), | |
527 threaded_data_provider(NULL), | |
528 resource_type(RESOURCE_TYPE_SUB_RESOURCE), | |
529 is_deferred(false), | |
530 download_to_file(false), | |
531 buffer_size(0), | |
532 data_offset(-1) { | |
533 } | |
534 | |
535 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( | 525 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( |
536 RequestPeer* peer, | 526 RequestPeer* peer, |
537 ResourceType resource_type, | 527 ResourceType resource_type, |
538 int origin_pid, | 528 int origin_pid, |
539 const GURL& frame_origin, | 529 const GURL& frame_origin, |
540 const GURL& request_url, | 530 const GURL& request_url, |
541 bool download_to_file) | 531 bool download_to_file) |
542 : peer(peer), | 532 : peer(peer), |
543 threaded_data_provider(NULL), | |
544 resource_type(resource_type), | 533 resource_type(resource_type), |
545 origin_pid(origin_pid), | 534 origin_pid(origin_pid), |
546 is_deferred(false), | |
547 url(request_url), | 535 url(request_url), |
548 frame_origin(frame_origin), | 536 frame_origin(frame_origin), |
549 response_url(request_url), | 537 response_url(request_url), |
550 download_to_file(download_to_file), | 538 download_to_file(download_to_file), |
551 request_start(base::TimeTicks::Now()), | 539 request_start(base::TimeTicks::Now()) { |
552 data_offset(-1) { | |
553 } | 540 } |
554 | 541 |
555 ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() { | 542 ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() { |
556 if (threaded_data_provider) | 543 if (threaded_data_provider) |
557 threaded_data_provider->Stop(); | 544 threaded_data_provider->Stop(); |
558 } | 545 } |
559 | 546 |
560 void ResourceDispatcher::DispatchMessage(const IPC::Message& message) { | 547 void ResourceDispatcher::DispatchMessage(const IPC::Message& message) { |
561 IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message) | 548 IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message) |
562 IPC_MESSAGE_HANDLER(ResourceMsg_UploadProgress, OnUploadProgress) | 549 IPC_MESSAGE_HANDLER(ResourceMsg_UploadProgress, OnUploadProgress) |
563 IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedResponse, OnReceivedResponse) | 550 IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedResponse, OnReceivedResponse) |
564 IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedCachedMetadata, | 551 IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedCachedMetadata, |
565 OnReceivedCachedMetadata) | 552 OnReceivedCachedMetadata) |
566 IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedRedirect, OnReceivedRedirect) | 553 IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedRedirect, OnReceivedRedirect) |
567 IPC_MESSAGE_HANDLER(ResourceMsg_SetDataBuffer, OnSetDataBuffer) | 554 IPC_MESSAGE_HANDLER(ResourceMsg_SetDataBuffer, OnSetDataBuffer) |
568 IPC_MESSAGE_HANDLER(ResourceMsg_DataReceivedDebug, OnReceivedDataDebug) | 555 IPC_MESSAGE_HANDLER(ResourceMsg_DataReceivedDebug, OnReceivedDataDebug) |
569 IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData) | 556 IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData) |
570 IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData) | 557 IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData) |
571 IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete) | 558 IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete) |
572 IPC_END_MESSAGE_MAP() | 559 IPC_END_MESSAGE_MAP() |
573 } | 560 } |
574 | 561 |
575 void ResourceDispatcher::FlushDeferredMessages(int request_id) { | 562 void ResourceDispatcher::FlushDeferredMessages(int request_id) { |
576 PendingRequestList::iterator it = pending_requests_.find(request_id); | 563 PendingRequestMap::iterator it = pending_requests_.find(request_id); |
577 if (it == pending_requests_.end()) // The request could have become invalid. | 564 if (it == pending_requests_.end()) // The request could have become invalid. |
578 return; | 565 return; |
579 PendingRequestInfo& request_info = it->second; | 566 PendingRequestInfo* request_info = it->second.get(); |
580 if (request_info.is_deferred) | 567 if (request_info->is_deferred) |
581 return; | 568 return; |
582 // Because message handlers could result in request_info being destroyed, | 569 // Because message handlers could result in request_info being destroyed, |
583 // we need to work with a stack reference to the deferred queue. | 570 // we need to work with a stack reference to the deferred queue. |
584 MessageQueue q; | 571 MessageQueue q; |
585 q.swap(request_info.deferred_message_queue); | 572 q.swap(request_info->deferred_message_queue); |
586 while (!q.empty()) { | 573 while (!q.empty()) { |
587 IPC::Message* m = q.front(); | 574 IPC::Message* m = q.front(); |
588 q.pop_front(); | 575 q.pop_front(); |
589 DispatchMessage(*m); | 576 DispatchMessage(*m); |
590 delete m; | 577 delete m; |
591 // If this request is deferred in the context of the above message, then | 578 // If this request is deferred in the context of the above message, then |
592 // we should honor the same and stop dispatching further messages. | 579 // we should honor the same and stop dispatching further messages. |
593 // We need to find the request again in the list as it may have completed | 580 // We need to find the request again in the list as it may have completed |
594 // by now and the request_info instance above may be invalid. | 581 // by now and the request_info instance above may be invalid. |
595 PendingRequestList::iterator index = pending_requests_.find(request_id); | 582 PendingRequestMap::iterator index = pending_requests_.find(request_id); |
596 if (index != pending_requests_.end()) { | 583 if (index != pending_requests_.end()) { |
597 PendingRequestInfo& pending_request = index->second; | 584 PendingRequestInfo* pending_request = index->second.get(); |
598 if (pending_request.is_deferred) { | 585 if (pending_request->is_deferred) { |
599 pending_request.deferred_message_queue.swap(q); | 586 pending_request->deferred_message_queue.swap(q); |
600 return; | 587 return; |
601 } | 588 } |
602 } | 589 } |
603 } | 590 } |
604 } | 591 } |
605 | 592 |
606 void ResourceDispatcher::StartSync(const RequestInfo& request_info, | 593 void ResourceDispatcher::StartSync(const RequestInfo& request_info, |
607 ResourceRequestBody* request_body, | 594 ResourceRequestBody* request_body, |
608 SyncLoadResponse* response) { | 595 SyncLoadResponse* response) { |
609 scoped_ptr<ResourceHostMsg_Request> request = | 596 scoped_ptr<ResourceHostMsg_Request> request = |
(...skipping 26 matching lines...) Expand all Loading... |
636 int ResourceDispatcher::StartAsync(const RequestInfo& request_info, | 623 int ResourceDispatcher::StartAsync(const RequestInfo& request_info, |
637 ResourceRequestBody* request_body, | 624 ResourceRequestBody* request_body, |
638 RequestPeer* peer) { | 625 RequestPeer* peer) { |
639 GURL frame_origin; | 626 GURL frame_origin; |
640 scoped_ptr<ResourceHostMsg_Request> request = | 627 scoped_ptr<ResourceHostMsg_Request> request = |
641 CreateRequest(request_info, request_body, &frame_origin); | 628 CreateRequest(request_info, request_body, &frame_origin); |
642 | 629 |
643 // Compute a unique request_id for this renderer process. | 630 // Compute a unique request_id for this renderer process. |
644 int request_id = MakeRequestID(); | 631 int request_id = MakeRequestID(); |
645 pending_requests_[request_id] = | 632 pending_requests_[request_id] = |
646 PendingRequestInfo(peer, | 633 make_scoped_ptr(new PendingRequestInfo(peer, |
647 request->resource_type, | 634 request->resource_type, |
648 request->origin_pid, | 635 request->origin_pid, |
649 frame_origin, | 636 frame_origin, |
650 request->url, | 637 request->url, |
651 request_info.download_to_file); | 638 request_info.download_to_file)); |
652 | 639 |
653 if (resource_scheduling_filter_.get() && | 640 if (resource_scheduling_filter_.get() && |
654 request_info.loading_web_task_runner) { | 641 request_info.loading_web_task_runner) { |
655 resource_scheduling_filter_->SetRequestIdTaskRunner( | 642 resource_scheduling_filter_->SetRequestIdTaskRunner( |
656 request_id, | 643 request_id, |
657 make_scoped_ptr(request_info.loading_web_task_runner->clone())); | 644 make_scoped_ptr(request_info.loading_web_task_runner->clone())); |
658 } | 645 } |
659 | 646 |
660 message_sender_->Send(new ResourceHostMsg_RequestResource( | 647 message_sender_->Send(new ResourceHostMsg_RequestResource( |
661 request_info.routing_id, request_id, *request)); | 648 request_info.routing_id, request_id, *request)); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 *frame_origin = extra_data->frame_origin(); | 851 *frame_origin = extra_data->frame_origin(); |
865 return request; | 852 return request; |
866 } | 853 } |
867 | 854 |
868 void ResourceDispatcher::SetResourceSchedulingFilter( | 855 void ResourceDispatcher::SetResourceSchedulingFilter( |
869 scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter) { | 856 scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter) { |
870 resource_scheduling_filter_ = resource_scheduling_filter; | 857 resource_scheduling_filter_ = resource_scheduling_filter; |
871 } | 858 } |
872 | 859 |
873 } // namespace content | 860 } // namespace content |
OLD | NEW |