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 "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 return true; | 290 return true; |
291 } | 291 } |
292 | 292 |
293 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 293 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
294 if (!request_info) { | 294 if (!request_info) { |
295 // Release resources in the message if it is a data message. | 295 // Release resources in the message if it is a data message. |
296 ReleaseResourcesInDataMessage(message); | 296 ReleaseResourcesInDataMessage(message); |
297 return true; | 297 return true; |
298 } | 298 } |
299 | 299 |
300 // If the request has been canceled, only dispatch | |
301 // ResourceMsg_RequestComplete (otherwise resource leaks) and drop other | |
302 // messages. | |
303 if (request_info->is_canceled) { | |
304 if (message.type() == ResourceMsg_RequestComplete::ID) { | |
305 DispatchMessage(message); | |
306 } else { | |
307 ReleaseResourcesInDataMessage(message); | |
308 } | |
309 return true; | |
310 } | |
311 | |
300 if (request_info->is_deferred) { | 312 if (request_info->is_deferred) { |
301 request_info->deferred_message_queue.push_back(new IPC::Message(message)); | 313 request_info->deferred_message_queue.push_back(new IPC::Message(message)); |
302 return true; | 314 return true; |
303 } | 315 } |
304 // Make sure any deferred messages are dispatched before we dispatch more. | 316 // Make sure any deferred messages are dispatched before we dispatch more. |
305 if (!request_info->deferred_message_queue.empty()) { | 317 if (!request_info->deferred_message_queue.empty()) { |
306 FlushDeferredMessages(request_id); | 318 FlushDeferredMessages(request_id); |
307 // The request could have been deferred now. If yes then the current | 319 // The request could have been deferred now. If yes then the current |
308 // message has to be queued up. The request_info instance should remain | 320 // message has to be queued up. The request_info instance should remain |
309 // valid here as there are pending messages for it. | 321 // valid here as there are pending messages for it. |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
581 return true; | 593 return true; |
582 } | 594 } |
583 | 595 |
584 void ResourceDispatcher::CancelPendingRequest(int request_id) { | 596 void ResourceDispatcher::CancelPendingRequest(int request_id) { |
585 PendingRequestList::iterator it = pending_requests_.find(request_id); | 597 PendingRequestList::iterator it = pending_requests_.find(request_id); |
586 if (it == pending_requests_.end()) { | 598 if (it == pending_requests_.end()) { |
587 DVLOG(1) << "unknown request"; | 599 DVLOG(1) << "unknown request"; |
588 return; | 600 return; |
589 } | 601 } |
590 | 602 |
603 PendingRequestInfo& request_info = it->second; | |
604 request_info.is_canceled = true; | |
605 | |
606 // Because message handlers could result in request_info being destroyed, | |
607 // we need to work with a stack reference to the deferred queue. | |
608 MessageQueue queue; | |
609 queue.swap(request_info.deferred_message_queue); | |
610 // Removes pending requests. If ResourceMsg_RequestComplete was queued, | |
611 // dispatch it. | |
612 bool first_message = true; | |
613 while (!queue.empty()) { | |
614 IPC::Message* message = queue.front(); | |
mmenke
2014/05/08 17:54:00
optional: I think it would be a little cleaner to
| |
615 if (message->type() == ResourceMsg_RequestComplete::ID) { | |
616 if (first_message) { | |
617 // Dispatch as-is. | |
618 DispatchMessage(*message); | |
619 } else { | |
620 // If we skip some ResourceMsg_DataReceived and then dispatched the | |
621 // original ResourceMsg_RequestComplete(status=success), chrome will | |
622 // crash because it entered an unexpected state. So replace | |
623 // ResourceMsg_RequestComplete with failure status. | |
624 ResourceMsg_RequestCompleteData request_complete_data; | |
625 request_complete_data.error_code = net::ERR_ABORTED; | |
626 request_complete_data.was_ignored_by_handler = false; | |
627 request_complete_data.exists_in_cache = false; | |
628 request_complete_data.completion_time = base::TimeTicks(); | |
629 request_complete_data.encoded_data_length = 0; | |
630 | |
631 ResourceMsg_RequestComplete error_message(request_id, | |
632 request_complete_data); | |
633 DispatchMessage(error_message); | |
634 } | |
635 } else { | |
636 ReleaseResourcesInDataMessage(*message); | |
637 } | |
638 first_message = false; | |
639 queue.pop_front(); | |
640 delete message; | |
641 } | |
642 | |
591 // |request_id| will be removed from |pending_requests_| when | 643 // |request_id| will be removed from |pending_requests_| when |
592 // OnRequestComplete returns with ERR_ABORTED. | 644 // OnRequestComplete returns with ERR_ABORTED. |
593 message_sender()->Send(new ResourceHostMsg_CancelRequest(request_id)); | 645 message_sender()->Send(new ResourceHostMsg_CancelRequest(request_id)); |
594 } | 646 } |
595 | 647 |
596 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { | 648 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { |
597 PendingRequestList::iterator it = pending_requests_.find(request_id); | 649 PendingRequestList::iterator it = pending_requests_.find(request_id); |
598 if (it == pending_requests_.end()) { | 650 if (it == pending_requests_.end()) { |
599 DLOG(ERROR) << "unknown request"; | 651 DLOG(ERROR) << "unknown request"; |
600 return; | 652 return; |
(...skipping 19 matching lines...) Expand all Loading... | |
620 int intra_priority_value) { | 672 int intra_priority_value) { |
621 DCHECK(ContainsKey(pending_requests_, request_id)); | 673 DCHECK(ContainsKey(pending_requests_, request_id)); |
622 message_sender()->Send(new ResourceHostMsg_DidChangePriority( | 674 message_sender()->Send(new ResourceHostMsg_DidChangePriority( |
623 request_id, new_priority, intra_priority_value)); | 675 request_id, new_priority, intra_priority_value)); |
624 } | 676 } |
625 | 677 |
626 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo() | 678 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo() |
627 : peer(NULL), | 679 : peer(NULL), |
628 resource_type(ResourceType::SUB_RESOURCE), | 680 resource_type(ResourceType::SUB_RESOURCE), |
629 is_deferred(false), | 681 is_deferred(false), |
682 is_canceled(false), | |
630 blocked_response(false), | 683 blocked_response(false), |
631 buffer_size(0) { | 684 buffer_size(0) { |
632 } | 685 } |
633 | 686 |
634 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( | 687 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( |
635 RequestPeer* peer, | 688 RequestPeer* peer, |
636 ResourceType::Type resource_type, | 689 ResourceType::Type resource_type, |
637 int origin_pid, | 690 int origin_pid, |
638 const GURL& frame_origin, | 691 const GURL& frame_origin, |
639 const GURL& request_url) | 692 const GURL& request_url) |
640 : peer(peer), | 693 : peer(peer), |
641 resource_type(resource_type), | 694 resource_type(resource_type), |
642 origin_pid(origin_pid), | 695 origin_pid(origin_pid), |
643 is_deferred(false), | 696 is_deferred(false), |
697 is_canceled(false), | |
644 url(request_url), | 698 url(request_url), |
645 frame_origin(frame_origin), | 699 frame_origin(frame_origin), |
646 response_url(request_url), | 700 response_url(request_url), |
647 request_start(base::TimeTicks::Now()), | 701 request_start(base::TimeTicks::Now()), |
648 blocked_response(false) {} | 702 blocked_response(false) {} |
649 | 703 |
650 ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() {} | 704 ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() {} |
651 | 705 |
652 void ResourceDispatcher::DispatchMessage(const IPC::Message& message) { | 706 void ResourceDispatcher::DispatchMessage(const IPC::Message& message) { |
653 IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message) | 707 IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message) |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
805 void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) { | 859 void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) { |
806 while (!queue->empty()) { | 860 while (!queue->empty()) { |
807 IPC::Message* message = queue->front(); | 861 IPC::Message* message = queue->front(); |
808 ReleaseResourcesInDataMessage(*message); | 862 ReleaseResourcesInDataMessage(*message); |
809 queue->pop_front(); | 863 queue->pop_front(); |
810 delete message; | 864 delete message; |
811 } | 865 } |
812 } | 866 } |
813 | 867 |
814 } // namespace content | 868 } // namespace content |
OLD | NEW |