| 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 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/debug/alias.h" | 13 #include "base/debug/alias.h" |
| 14 #include "base/debug/dump_without_crashing.h" | 14 #include "base/debug/dump_without_crashing.h" |
| 15 #include "base/debug/stack_trace.h" | 15 #include "base/debug/stack_trace.h" |
| 16 #include "base/feature_list.h" | 16 #include "base/feature_list.h" |
| 17 #include "base/files/file_path.h" | 17 #include "base/files/file_path.h" |
| 18 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 19 #include "base/memory/shared_memory.h" | 19 #include "base/memory/shared_memory.h" |
| 20 #include "base/message_loop/message_loop.h" | 20 #include "base/message_loop/message_loop.h" |
| 21 #include "base/metrics/histogram_macros.h" | 21 #include "base/metrics/histogram_macros.h" |
| 22 #include "base/rand_util.h" | 22 #include "base/rand_util.h" |
| 23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
| 24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
| 25 #include "content/child/request_extra_data.h" | 25 #include "content/child/request_extra_data.h" |
| 26 #include "content/child/resource_scheduling_filter.h" | 26 #include "content/child/resource_scheduling_filter.h" |
| 27 #include "content/child/shared_memory_received_data_factory.h" | 27 #include "content/child/shared_memory_received_data_factory.h" |
| 28 #include "content/child/site_isolation_stats_gatherer.h" | 28 #include "content/child/site_isolation_stats_gatherer.h" |
| 29 #include "content/child/sync_load_response.h" | 29 #include "content/child/sync_load_response.h" |
| 30 #include "content/child/url_response_body_consumer.h" | 30 #include "content/child/url_loader_client_impl.h" |
| 31 #include "content/common/inter_process_time_ticks_converter.h" | 31 #include "content/common/inter_process_time_ticks_converter.h" |
| 32 #include "content/common/navigation_params.h" | 32 #include "content/common/navigation_params.h" |
| 33 #include "content/common/resource_messages.h" | 33 #include "content/common/resource_messages.h" |
| 34 #include "content/common/resource_request.h" | 34 #include "content/common/resource_request.h" |
| 35 #include "content/common/resource_request_completion_status.h" | 35 #include "content/common/resource_request_completion_status.h" |
| 36 #include "content/public/child/fixed_received_data.h" | 36 #include "content/public/child/fixed_received_data.h" |
| 37 #include "content/public/child/request_peer.h" | 37 #include "content/public/child/request_peer.h" |
| 38 #include "content/public/child/resource_dispatcher_delegate.h" | 38 #include "content/public/child/resource_dispatcher_delegate.h" |
| 39 #include "content/public/common/content_features.h" | 39 #include "content/public/common/content_features.h" |
| 40 #include "content/public/common/resource_response.h" | 40 #include "content/public/common/resource_response.h" |
| 41 #include "content/public/common/resource_type.h" | 41 #include "content/public/common/resource_type.h" |
| 42 #include "mojo/public/cpp/bindings/associated_binding.h" | |
| 43 #include "mojo/public/cpp/bindings/associated_group.h" | 42 #include "mojo/public/cpp/bindings/associated_group.h" |
| 44 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" | |
| 45 #include "net/base/net_errors.h" | 43 #include "net/base/net_errors.h" |
| 46 #include "net/base/request_priority.h" | 44 #include "net/base/request_priority.h" |
| 47 #include "net/http/http_response_headers.h" | 45 #include "net/http/http_response_headers.h" |
| 48 | 46 |
| 49 namespace content { | 47 namespace content { |
| 50 | 48 |
| 51 namespace { | 49 namespace { |
| 52 | 50 |
| 53 // Converts |time| from a remote to local TimeTicks, overwriting the original | 51 // Converts |time| from a remote to local TimeTicks, overwriting the original |
| 54 // value. | 52 // value. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 69 | 67 |
| 70 // Each resource request is assigned an ID scoped to this process. | 68 // Each resource request is assigned an ID scoped to this process. |
| 71 int MakeRequestID() { | 69 int MakeRequestID() { |
| 72 // NOTE: The resource_dispatcher_host also needs probably unique | 70 // NOTE: The resource_dispatcher_host also needs probably unique |
| 73 // request_ids, so they count down from -2 (-1 is a special we're | 71 // request_ids, so they count down from -2 (-1 is a special we're |
| 74 // screwed value), while the renderer process counts up. | 72 // screwed value), while the renderer process counts up. |
| 75 static int next_request_id = 0; | 73 static int next_request_id = 0; |
| 76 return next_request_id++; | 74 return next_request_id++; |
| 77 } | 75 } |
| 78 | 76 |
| 79 class URLLoaderClientImpl final : public mojom::URLLoaderClient { | |
| 80 public: | |
| 81 URLLoaderClientImpl(int request_id, | |
| 82 ResourceDispatcher* resource_dispatcher, | |
| 83 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | |
| 84 : binding_(this), | |
| 85 request_id_(request_id), | |
| 86 resource_dispatcher_(resource_dispatcher), | |
| 87 task_runner_(std::move(task_runner)) {} | |
| 88 ~URLLoaderClientImpl() override { | |
| 89 if (body_consumer_) | |
| 90 body_consumer_->Cancel(); | |
| 91 } | |
| 92 | |
| 93 void OnReceiveResponse( | |
| 94 const ResourceResponseHead& response_head, | |
| 95 mojom::DownloadedTempFilePtr downloaded_file) override { | |
| 96 has_received_response_ = true; | |
| 97 if (body_consumer_) | |
| 98 body_consumer_->Start(); | |
| 99 downloaded_file_ = std::move(downloaded_file); | |
| 100 resource_dispatcher_->OnMessageReceived( | |
| 101 ResourceMsg_ReceivedResponse(request_id_, response_head)); | |
| 102 } | |
| 103 | |
| 104 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, | |
| 105 const ResourceResponseHead& response_head) override { | |
| 106 DCHECK(!has_received_response_); | |
| 107 DCHECK(!body_consumer_); | |
| 108 resource_dispatcher_->OnMessageReceived(ResourceMsg_ReceivedRedirect( | |
| 109 request_id_, redirect_info, response_head)); | |
| 110 } | |
| 111 | |
| 112 void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override { | |
| 113 resource_dispatcher_->OnMessageReceived( | |
| 114 ResourceMsg_DataDownloaded(request_id_, data_len, encoded_data_len)); | |
| 115 } | |
| 116 | |
| 117 void OnTransferSizeUpdated(int32_t transfer_size_diff) override { | |
| 118 resource_dispatcher_->OnTransferSizeUpdated(request_id_, | |
| 119 transfer_size_diff); | |
| 120 } | |
| 121 | |
| 122 void OnStartLoadingResponseBody( | |
| 123 mojo::ScopedDataPipeConsumerHandle body) override { | |
| 124 DCHECK(!body_consumer_); | |
| 125 body_consumer_ = new URLResponseBodyConsumer( | |
| 126 request_id_, resource_dispatcher_, std::move(body), task_runner_); | |
| 127 if (has_received_response_) | |
| 128 body_consumer_->Start(); | |
| 129 } | |
| 130 | |
| 131 void OnComplete(const ResourceRequestCompletionStatus& status) override { | |
| 132 if (!body_consumer_) { | |
| 133 resource_dispatcher_->OnMessageReceived( | |
| 134 ResourceMsg_RequestComplete(request_id_, status)); | |
| 135 return; | |
| 136 } | |
| 137 body_consumer_->OnComplete(status); | |
| 138 } | |
| 139 | |
| 140 void Bind(mojom::URLLoaderClientAssociatedPtrInfo* client_ptr_info, | |
| 141 mojo::AssociatedGroup* associated_group) { | |
| 142 binding_.Bind(client_ptr_info, associated_group); | |
| 143 } | |
| 144 | |
| 145 private: | |
| 146 mojo::AssociatedBinding<mojom::URLLoaderClient> binding_; | |
| 147 scoped_refptr<URLResponseBodyConsumer> body_consumer_; | |
| 148 mojom::DownloadedTempFilePtr downloaded_file_; | |
| 149 const int request_id_; | |
| 150 bool has_received_response_ = false; | |
| 151 ResourceDispatcher* const resource_dispatcher_; | |
| 152 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 153 }; | |
| 154 | |
| 155 void CheckSchemeForReferrerPolicy(const ResourceRequest& request) { | 77 void CheckSchemeForReferrerPolicy(const ResourceRequest& request) { |
| 156 if ((request.referrer_policy == blink::WebReferrerPolicyDefault || | 78 if ((request.referrer_policy == blink::WebReferrerPolicyDefault || |
| 157 request.referrer_policy == | 79 request.referrer_policy == |
| 158 blink::WebReferrerPolicyNoReferrerWhenDowngrade) && | 80 blink::WebReferrerPolicyNoReferrerWhenDowngrade) && |
| 159 request.referrer.SchemeIsCryptographic() && | 81 request.referrer.SchemeIsCryptographic() && |
| 160 !request.url.SchemeIsCryptographic()) { | 82 !request.url.SchemeIsCryptographic()) { |
| 161 LOG(FATAL) << "Trying to send secure referrer for insecure request " | 83 LOG(FATAL) << "Trying to send secure referrer for insecure request " |
| 162 << "without an appropriate referrer policy.\n" | 84 << "without an appropriate referrer policy.\n" |
| 163 << "URL = " << request.url << "\n" | 85 << "URL = " << request.url << "\n" |
| 164 << "Referrer = " << request.referrer; | 86 << "Referrer = " << request.referrer; |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 strncpy(url_copy, info.response_url.spec().c_str(), | 463 strncpy(url_copy, info.response_url.spec().c_str(), |
| 542 sizeof(url_copy)); | 464 sizeof(url_copy)); |
| 543 base::debug::Alias(&url_copy); | 465 base::debug::Alias(&url_copy); |
| 544 base::debug::Alias(&request_time); | 466 base::debug::Alias(&request_time); |
| 545 base::debug::DumpWithoutCrashing(); | 467 base::debug::DumpWithoutCrashing(); |
| 546 should_dump = false; | 468 should_dump = false; |
| 547 } | 469 } |
| 548 } | 470 } |
| 549 // Cancel the request if it didn't complete, and clean it up so the bridge | 471 // Cancel the request if it didn't complete, and clean it up so the bridge |
| 550 // will receive no more messages. | 472 // will receive no more messages. |
| 551 if (info.completion_time.is_null()) | 473 if (info.completion_time.is_null() && !info.url_loader) |
| 552 message_sender_->Send(new ResourceHostMsg_CancelRequest(request_id)); | 474 message_sender_->Send(new ResourceHostMsg_CancelRequest(request_id)); |
| 553 RemovePendingRequest(request_id); | 475 RemovePendingRequest(request_id); |
| 554 } | 476 } |
| 555 | 477 |
| 556 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { | 478 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { |
| 557 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 479 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 558 if (!request_info) { | 480 if (!request_info) { |
| 559 DLOG(ERROR) << "unknown request"; | 481 DLOG(ERROR) << "unknown request"; |
| 560 return; | 482 return; |
| 561 } | 483 } |
| 562 if (value) { | 484 if (value) { |
| 563 request_info->is_deferred = value; | 485 request_info->is_deferred = value; |
| 486 if (request_info->url_loader_client) |
| 487 request_info->url_loader_client->SetDefersLoading(); |
| 564 } else if (request_info->is_deferred) { | 488 } else if (request_info->is_deferred) { |
| 565 request_info->is_deferred = false; | 489 request_info->is_deferred = false; |
| 490 if (request_info->url_loader_client) |
| 491 request_info->url_loader_client->UnsetDefersLoading(); |
| 566 | 492 |
| 567 FollowPendingRedirect(request_id, request_info); | 493 FollowPendingRedirect(request_id, request_info); |
| 568 | 494 |
| 569 main_thread_task_runner_->PostTask( | 495 main_thread_task_runner_->PostTask( |
| 570 FROM_HERE, base::Bind(&ResourceDispatcher::FlushDeferredMessages, | 496 FROM_HERE, base::Bind(&ResourceDispatcher::FlushDeferredMessages, |
| 571 weak_factory_.GetWeakPtr(), request_id)); | 497 weak_factory_.GetWeakPtr(), request_id)); |
| 572 } | 498 } |
| 573 } | 499 } |
| 574 | 500 |
| 575 void ResourceDispatcher::DidChangePriority(int request_id, | 501 void ResourceDispatcher::DidChangePriority(int request_id, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData) | 550 IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData) |
| 625 IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData) | 551 IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData) |
| 626 IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete) | 552 IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete) |
| 627 IPC_END_MESSAGE_MAP() | 553 IPC_END_MESSAGE_MAP() |
| 628 } | 554 } |
| 629 | 555 |
| 630 void ResourceDispatcher::FlushDeferredMessages(int request_id) { | 556 void ResourceDispatcher::FlushDeferredMessages(int request_id) { |
| 631 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 557 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
| 632 if (!request_info || request_info->is_deferred) | 558 if (!request_info || request_info->is_deferred) |
| 633 return; | 559 return; |
| 560 |
| 561 if (request_info->url_loader) |
| 562 request_info->url_loader_client->FlushDeferredMessages(); |
| 563 |
| 634 // Because message handlers could result in request_info being destroyed, | 564 // Because message handlers could result in request_info being destroyed, |
| 635 // we need to work with a stack reference to the deferred queue. | 565 // we need to work with a stack reference to the deferred queue. |
| 636 MessageQueue q; | 566 MessageQueue q; |
| 637 q.swap(request_info->deferred_message_queue); | 567 q.swap(request_info->deferred_message_queue); |
| 638 while (!q.empty()) { | 568 while (!q.empty()) { |
| 639 IPC::Message* m = q.front(); | 569 IPC::Message* m = q.front(); |
| 640 q.pop_front(); | 570 q.pop_front(); |
| 641 DispatchMessage(*m); | 571 DispatchMessage(*m); |
| 642 delete m; | 572 delete m; |
| 643 // We need to find the request again in the list as it may have completed | 573 // We need to find the request again in the list as it may have completed |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 delete message; | 807 delete message; |
| 878 } | 808 } |
| 879 } | 809 } |
| 880 | 810 |
| 881 void ResourceDispatcher::SetResourceSchedulingFilter( | 811 void ResourceDispatcher::SetResourceSchedulingFilter( |
| 882 scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter) { | 812 scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter) { |
| 883 resource_scheduling_filter_ = resource_scheduling_filter; | 813 resource_scheduling_filter_ = resource_scheduling_filter; |
| 884 } | 814 } |
| 885 | 815 |
| 886 } // namespace content | 816 } // namespace content |
| OLD | NEW |