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 |