OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/child/url_loader_client_impl.h" | 5 #include "content/child/url_loader_client_impl.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
9 #include "content/child/resource_dispatcher.h" | 9 #include "content/child/resource_dispatcher.h" |
10 #include "content/child/url_response_body_consumer.h" | 10 #include "content/child/url_response_body_consumer.h" |
11 #include "content/common/resource_messages.h" | 11 #include "content/common/resource_messages.h" |
12 #include "mojo/public/cpp/bindings/associated_group.h" | 12 #include "mojo/public/cpp/bindings/associated_group.h" |
13 #include "net/url_request/redirect_info.h" | 13 #include "net/url_request/redirect_info.h" |
14 | 14 |
15 namespace content { | 15 namespace content { |
16 | 16 |
17 URLLoaderClientImpl::URLLoaderClientImpl( | 17 URLLoaderClientImpl::URLLoaderClientImpl( |
18 int request_id, | 18 int request_id, |
19 ResourceDispatcher* resource_dispatcher, | 19 ResourceDispatcher* resource_dispatcher, |
20 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 20 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
21 : binding_(this), | 21 : binding_(this), |
22 request_id_(request_id), | 22 request_id_(request_id), |
23 resource_dispatcher_(resource_dispatcher), | 23 resource_dispatcher_(resource_dispatcher), |
24 task_runner_(std::move(task_runner)) {} | 24 task_runner_(std::move(task_runner)), |
| 25 weak_factory_(this) {} |
25 | 26 |
26 URLLoaderClientImpl::~URLLoaderClientImpl() { | 27 URLLoaderClientImpl::~URLLoaderClientImpl() { |
27 if (body_consumer_) | 28 if (body_consumer_) |
28 body_consumer_->Cancel(); | 29 body_consumer_->Cancel(); |
29 } | 30 } |
30 | 31 |
31 void URLLoaderClientImpl::Bind( | 32 void URLLoaderClientImpl::Bind( |
32 mojom::URLLoaderClientAssociatedPtrInfo* client_ptr_info, | 33 mojom::URLLoaderClientAssociatedPtrInfo* client_ptr_info, |
33 mojo::AssociatedGroup* associated_group) { | 34 mojo::AssociatedGroup* associated_group) { |
34 binding_.Bind(client_ptr_info, associated_group); | 35 binding_.Bind(client_ptr_info, associated_group); |
35 } | 36 } |
36 | 37 |
| 38 void URLLoaderClientImpl::SetDefersLoading() { |
| 39 is_deferred_ = true; |
| 40 if (body_consumer_) |
| 41 body_consumer_->SetDefersLoading(); |
| 42 } |
| 43 |
| 44 void URLLoaderClientImpl::UnsetDefersLoading() { |
| 45 is_deferred_ = false; |
| 46 } |
| 47 |
| 48 void URLLoaderClientImpl::FlushDeferredMessages() { |
| 49 DCHECK(!is_deferred_); |
| 50 std::vector<IPC::Message> messages; |
| 51 messages.swap(deferred_messages_); |
| 52 bool has_completion_message = false; |
| 53 base::WeakPtr<URLLoaderClientImpl> weak_this = weak_factory_.GetWeakPtr(); |
| 54 // First, dispatch all messages excluding the followings: |
| 55 // - response body (dispatched by |body_consumer_|) |
| 56 // - transfer size change (dispatched later) |
| 57 // - completion (dispatched by |body_consumer_| or dispatched later) |
| 58 for (size_t index = 0; index < messages.size(); ++index) { |
| 59 if (messages[index].type() == ResourceMsg_RequestComplete::ID) { |
| 60 // The completion message arrives at the end of the message queue. |
| 61 DCHECK(!has_completion_message); |
| 62 DCHECK_EQ(index, messages.size() - 1); |
| 63 has_completion_message = true; |
| 64 break; |
| 65 } |
| 66 Dispatch(messages[index]); |
| 67 if (!weak_this) |
| 68 return; |
| 69 if (is_deferred_) { |
| 70 deferred_messages_.insert(deferred_messages_.begin(), |
| 71 messages.begin() + index + 1, messages.end()); |
| 72 return; |
| 73 } |
| 74 } |
| 75 |
| 76 // Dispatch the transfer size update. |
| 77 if (accumulated_transfer_size_diff_during_deferred_ > 0) { |
| 78 auto transfer_size_diff = accumulated_transfer_size_diff_during_deferred_; |
| 79 accumulated_transfer_size_diff_during_deferred_ = 0; |
| 80 resource_dispatcher_->OnTransferSizeUpdated(request_id_, |
| 81 transfer_size_diff); |
| 82 if (!weak_this) |
| 83 return; |
| 84 if (is_deferred_) { |
| 85 if (has_completion_message) { |
| 86 DCHECK_GT(messages.size(), 0u); |
| 87 DCHECK_EQ(messages.back().type(), |
| 88 static_cast<uint32_t>(ResourceMsg_RequestComplete::ID)); |
| 89 deferred_messages_.emplace_back(std::move(messages.back())); |
| 90 } |
| 91 return; |
| 92 } |
| 93 } |
| 94 |
| 95 if (body_consumer_) { |
| 96 // When we have |body_consumer_|, the completion message is dispatched by |
| 97 // it, not by this object. |
| 98 DCHECK(!has_completion_message); |
| 99 // Dispatch the response body. |
| 100 body_consumer_->UnsetDefersLoading(); |
| 101 return; |
| 102 } |
| 103 |
| 104 // Dispatch the completion message. |
| 105 if (has_completion_message) { |
| 106 DCHECK_GT(messages.size(), 0u); |
| 107 DCHECK_EQ(messages.back().type(), |
| 108 static_cast<uint32_t>(ResourceMsg_RequestComplete::ID)); |
| 109 Dispatch(messages.back()); |
| 110 } |
| 111 } |
| 112 |
37 void URLLoaderClientImpl::OnReceiveResponse( | 113 void URLLoaderClientImpl::OnReceiveResponse( |
38 const ResourceResponseHead& response_head, | 114 const ResourceResponseHead& response_head, |
39 mojom::DownloadedTempFilePtr downloaded_file) { | 115 mojom::DownloadedTempFilePtr downloaded_file) { |
40 has_received_response_ = true; | 116 has_received_response_ = true; |
41 if (body_consumer_) | 117 if (body_consumer_) |
42 body_consumer_->Start(); | 118 body_consumer_->Start(); |
43 downloaded_file_ = std::move(downloaded_file); | 119 downloaded_file_ = std::move(downloaded_file); |
44 Dispatch(ResourceMsg_ReceivedResponse(request_id_, response_head)); | 120 Dispatch(ResourceMsg_ReceivedResponse(request_id_, response_head)); |
45 } | 121 } |
46 | 122 |
47 void URLLoaderClientImpl::OnReceiveRedirect( | 123 void URLLoaderClientImpl::OnReceiveRedirect( |
48 const net::RedirectInfo& redirect_info, | 124 const net::RedirectInfo& redirect_info, |
49 const ResourceResponseHead& response_head) { | 125 const ResourceResponseHead& response_head) { |
50 DCHECK(!has_received_response_); | 126 DCHECK(!has_received_response_); |
51 DCHECK(!body_consumer_); | 127 DCHECK(!body_consumer_); |
52 Dispatch( | 128 Dispatch( |
53 ResourceMsg_ReceivedRedirect(request_id_, redirect_info, response_head)); | 129 ResourceMsg_ReceivedRedirect(request_id_, redirect_info, response_head)); |
54 } | 130 } |
55 | 131 |
56 void URLLoaderClientImpl::OnDataDownloaded(int64_t data_len, | 132 void URLLoaderClientImpl::OnDataDownloaded(int64_t data_len, |
57 int64_t encoded_data_len) { | 133 int64_t encoded_data_len) { |
58 Dispatch(ResourceMsg_DataDownloaded(request_id_, data_len, encoded_data_len)); | 134 Dispatch(ResourceMsg_DataDownloaded(request_id_, data_len, encoded_data_len)); |
59 } | 135 } |
60 | 136 |
61 void URLLoaderClientImpl::OnTransferSizeUpdated(int32_t transfer_size_diff) { | 137 void URLLoaderClientImpl::OnTransferSizeUpdated(int32_t transfer_size_diff) { |
62 resource_dispatcher_->OnTransferSizeUpdated(request_id_, | 138 if (is_deferred_) { |
63 transfer_size_diff); | 139 accumulated_transfer_size_diff_during_deferred_ += transfer_size_diff; |
| 140 } else { |
| 141 resource_dispatcher_->OnTransferSizeUpdated(request_id_, |
| 142 transfer_size_diff); |
| 143 } |
64 } | 144 } |
65 | 145 |
66 void URLLoaderClientImpl::OnStartLoadingResponseBody( | 146 void URLLoaderClientImpl::OnStartLoadingResponseBody( |
67 mojo::ScopedDataPipeConsumerHandle body) { | 147 mojo::ScopedDataPipeConsumerHandle body) { |
68 DCHECK(!body_consumer_); | 148 DCHECK(!body_consumer_); |
69 body_consumer_ = new URLResponseBodyConsumer( | 149 body_consumer_ = new URLResponseBodyConsumer( |
70 request_id_, resource_dispatcher_, std::move(body), task_runner_); | 150 request_id_, resource_dispatcher_, std::move(body), task_runner_); |
71 if (has_received_response_) | 151 if (has_received_response_) |
72 body_consumer_->Start(); | 152 body_consumer_->Start(); |
| 153 if (is_deferred_) |
| 154 body_consumer_->SetDefersLoading(); |
73 } | 155 } |
74 | 156 |
75 void URLLoaderClientImpl::OnComplete( | 157 void URLLoaderClientImpl::OnComplete( |
76 const ResourceRequestCompletionStatus& status) { | 158 const ResourceRequestCompletionStatus& status) { |
77 if (!body_consumer_) { | 159 if (!body_consumer_) { |
78 Dispatch(ResourceMsg_RequestComplete(request_id_, status)); | 160 Dispatch(ResourceMsg_RequestComplete(request_id_, status)); |
79 return; | 161 return; |
80 } | 162 } |
81 body_consumer_->OnComplete(status); | 163 body_consumer_->OnComplete(status); |
82 } | 164 } |
83 | 165 |
84 void URLLoaderClientImpl::Dispatch(const IPC::Message& message) { | 166 void URLLoaderClientImpl::Dispatch(const IPC::Message& message) { |
85 resource_dispatcher_->OnMessageReceived(message); | 167 if (is_deferred_) { |
| 168 deferred_messages_.push_back(message); |
| 169 } else if (deferred_messages_.size() > 0) { |
| 170 deferred_messages_.push_back(message); |
| 171 FlushDeferredMessages(); |
| 172 } else { |
| 173 resource_dispatcher_->DispatchMessage(message); |
| 174 } |
86 } | 175 } |
87 | 176 |
88 } // namespace content | 177 } // namespace content |
OLD | NEW |