Chromium Code Reviews| 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 deferred_messages_.emplace_back(std::move(messages.back())); | |
|
kinuko
2016/12/27 01:52:21
nit: can we add a comment (or documentary DCHECK)
yhirano
2016/12/27 07:32:54
Done.
| |
| 87 return; | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 if (body_consumer_) { | |
| 92 // When we have |body_consumer_|, the completion message is dispatched by | |
| 93 // it, not by this object. | |
| 94 DCHECK(!has_completion_message); | |
| 95 // Dispatch the response body. | |
| 96 body_consumer_->UnsetDefersLoading(); | |
| 97 return; | |
| 98 } | |
| 99 | |
| 100 // Dispatch the completion message. | |
| 101 if (has_completion_message) { | |
| 102 DCHECK_GT(messages.size(), 0u); | |
| 103 DCHECK_EQ(messages.back().type(), | |
| 104 static_cast<uint32_t>(ResourceMsg_RequestComplete::ID)); | |
| 105 Dispatch(messages.back()); | |
| 106 } | |
| 107 } | |
| 108 | |
| 37 void URLLoaderClientImpl::OnReceiveResponse( | 109 void URLLoaderClientImpl::OnReceiveResponse( |
| 38 const ResourceResponseHead& response_head, | 110 const ResourceResponseHead& response_head, |
| 39 mojom::DownloadedTempFilePtr downloaded_file) { | 111 mojom::DownloadedTempFilePtr downloaded_file) { |
| 40 has_received_response_ = true; | 112 has_received_response_ = true; |
| 41 if (body_consumer_) | 113 if (body_consumer_) |
| 42 body_consumer_->Start(); | 114 body_consumer_->Start(); |
| 43 downloaded_file_ = std::move(downloaded_file); | 115 downloaded_file_ = std::move(downloaded_file); |
| 44 Dispatch(ResourceMsg_ReceivedResponse(request_id_, response_head)); | 116 Dispatch(ResourceMsg_ReceivedResponse(request_id_, response_head)); |
| 45 } | 117 } |
| 46 | 118 |
| 47 void URLLoaderClientImpl::OnReceiveRedirect( | 119 void URLLoaderClientImpl::OnReceiveRedirect( |
| 48 const net::RedirectInfo& redirect_info, | 120 const net::RedirectInfo& redirect_info, |
| 49 const ResourceResponseHead& response_head) { | 121 const ResourceResponseHead& response_head) { |
| 50 DCHECK(!has_received_response_); | 122 DCHECK(!has_received_response_); |
| 51 DCHECK(!body_consumer_); | 123 DCHECK(!body_consumer_); |
| 52 Dispatch( | 124 Dispatch( |
| 53 ResourceMsg_ReceivedRedirect(request_id_, redirect_info, response_head)); | 125 ResourceMsg_ReceivedRedirect(request_id_, redirect_info, response_head)); |
| 54 } | 126 } |
| 55 | 127 |
| 56 void URLLoaderClientImpl::OnDataDownloaded(int64_t data_len, | 128 void URLLoaderClientImpl::OnDataDownloaded(int64_t data_len, |
| 57 int64_t encoded_data_len) { | 129 int64_t encoded_data_len) { |
| 58 Dispatch(ResourceMsg_DataDownloaded(request_id_, data_len, encoded_data_len)); | 130 Dispatch(ResourceMsg_DataDownloaded(request_id_, data_len, encoded_data_len)); |
| 59 } | 131 } |
| 60 | 132 |
| 61 void URLLoaderClientImpl::OnTransferSizeUpdated(int32_t transfer_size_diff) { | 133 void URLLoaderClientImpl::OnTransferSizeUpdated(int32_t transfer_size_diff) { |
| 62 resource_dispatcher_->OnTransferSizeUpdated(request_id_, | 134 if (is_deferred_) { |
| 63 transfer_size_diff); | 135 accumulated_transfer_size_diff_during_deferred_ += transfer_size_diff; |
| 136 } else { | |
| 137 resource_dispatcher_->OnTransferSizeUpdated(request_id_, | |
| 138 transfer_size_diff); | |
| 139 } | |
| 64 } | 140 } |
| 65 | 141 |
| 66 void URLLoaderClientImpl::OnStartLoadingResponseBody( | 142 void URLLoaderClientImpl::OnStartLoadingResponseBody( |
| 67 mojo::ScopedDataPipeConsumerHandle body) { | 143 mojo::ScopedDataPipeConsumerHandle body) { |
| 68 DCHECK(!body_consumer_); | 144 DCHECK(!body_consumer_); |
| 69 body_consumer_ = new URLResponseBodyConsumer( | 145 body_consumer_ = new URLResponseBodyConsumer( |
| 70 request_id_, resource_dispatcher_, std::move(body), task_runner_); | 146 request_id_, resource_dispatcher_, std::move(body), task_runner_); |
| 71 if (has_received_response_) | 147 if (has_received_response_) |
| 72 body_consumer_->Start(); | 148 body_consumer_->Start(); |
| 149 if (is_deferred_) | |
| 150 body_consumer_->SetDefersLoading(); | |
| 73 } | 151 } |
| 74 | 152 |
| 75 void URLLoaderClientImpl::OnComplete( | 153 void URLLoaderClientImpl::OnComplete( |
| 76 const ResourceRequestCompletionStatus& status) { | 154 const ResourceRequestCompletionStatus& status) { |
| 77 if (!body_consumer_) { | 155 if (!body_consumer_) { |
| 78 Dispatch(ResourceMsg_RequestComplete(request_id_, status)); | 156 Dispatch(ResourceMsg_RequestComplete(request_id_, status)); |
| 79 return; | 157 return; |
| 80 } | 158 } |
| 81 body_consumer_->OnComplete(status); | 159 body_consumer_->OnComplete(status); |
| 82 } | 160 } |
| 83 | 161 |
| 84 void URLLoaderClientImpl::Dispatch(const IPC::Message& message) { | 162 void URLLoaderClientImpl::Dispatch(const IPC::Message& message) { |
| 85 resource_dispatcher_->OnMessageReceived(message); | 163 if (is_deferred_) { |
| 164 deferred_messages_.push_back(message); | |
| 165 } else if (deferred_messages_.size() > 0) { | |
| 166 deferred_messages_.push_back(message); | |
| 167 FlushDeferredMessages(); | |
| 168 } else { | |
| 169 resource_dispatcher_->DispatchMessage(message); | |
| 170 } | |
| 86 } | 171 } |
| 87 | 172 |
| 88 } // namespace content | 173 } // namespace content |
| OLD | NEW |