| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/browser/download/url_downloader.h" | 5 #include "content/browser/download/url_downloader.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/threading/sequenced_task_runner_handle.h" | 10 #include "base/threading/sequenced_task_runner_handle.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 base::WeakPtr<DownloadManagerImpl> download_manager_impl_; | 67 base::WeakPtr<DownloadManagerImpl> download_manager_impl_; |
| 68 scoped_refptr<base::SequencedTaskRunner> downloader_task_runner_; | 68 scoped_refptr<base::SequencedTaskRunner> downloader_task_runner_; |
| 69 | 69 |
| 70 DISALLOW_COPY_AND_ASSIGN(RequestHandle); | 70 DISALLOW_COPY_AND_ASSIGN(RequestHandle); |
| 71 }; | 71 }; |
| 72 | 72 |
| 73 // static | 73 // static |
| 74 scoped_ptr<UrlDownloader> UrlDownloader::BeginDownload( | 74 scoped_ptr<UrlDownloader> UrlDownloader::BeginDownload( |
| 75 base::WeakPtr<DownloadManagerImpl> download_manager, | 75 base::WeakPtr<DownloadManagerImpl> download_manager, |
| 76 scoped_ptr<net::URLRequest> request, | 76 scoped_ptr<net::URLRequest> request, |
| 77 const Referrer& referrer, | 77 const Referrer& referrer) { |
| 78 bool prefer_cache, | |
| 79 scoped_ptr<DownloadSaveInfo> save_info, | |
| 80 uint32_t download_id, | |
| 81 const DownloadUrlParameters::OnStartedCallback& started_callback) { | |
| 82 if (!referrer.url.is_valid()) | 78 if (!referrer.url.is_valid()) |
| 83 request->SetReferrer(std::string()); | 79 request->SetReferrer(std::string()); |
| 84 else | 80 else |
| 85 request->SetReferrer(referrer.url.spec()); | 81 request->SetReferrer(referrer.url.spec()); |
| 86 | 82 |
| 87 int extra_load_flags = net::LOAD_NORMAL; | |
| 88 if (prefer_cache) { | |
| 89 // If there is upload data attached, only retrieve from cache because there | |
| 90 // is no current mechanism to prompt the user for their consent for a | |
| 91 // re-post. For GETs, try to retrieve data from the cache and skip | |
| 92 // validating the entry if present. | |
| 93 if (request->get_upload() != NULL) | |
| 94 extra_load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
| 95 else | |
| 96 extra_load_flags |= net::LOAD_PREFERRING_CACHE; | |
| 97 } else { | |
| 98 extra_load_flags |= net::LOAD_DISABLE_CACHE; | |
| 99 } | |
| 100 request->SetLoadFlags(request->load_flags() | extra_load_flags); | |
| 101 | |
| 102 if (request->url().SchemeIs(url::kBlobScheme)) | 83 if (request->url().SchemeIs(url::kBlobScheme)) |
| 103 return nullptr; | 84 return nullptr; |
| 104 | 85 |
| 105 // From this point forward, the |UrlDownloader| is responsible for | 86 // From this point forward, the |UrlDownloader| is responsible for |
| 106 // |started_callback|. | 87 // |started_callback|. |
| 107 scoped_ptr<UrlDownloader> downloader( | 88 scoped_ptr<UrlDownloader> downloader( |
| 108 new UrlDownloader(std::move(request), download_manager, | 89 new UrlDownloader(std::move(request), download_manager)); |
| 109 std::move(save_info), download_id, started_callback)); | |
| 110 downloader->Start(); | 90 downloader->Start(); |
| 111 | 91 |
| 112 return downloader; | 92 return downloader; |
| 113 } | 93 } |
| 114 | 94 |
| 115 UrlDownloader::UrlDownloader( | 95 UrlDownloader::UrlDownloader(scoped_ptr<net::URLRequest> request, |
| 116 scoped_ptr<net::URLRequest> request, | 96 base::WeakPtr<DownloadManagerImpl> manager) |
| 117 base::WeakPtr<DownloadManagerImpl> manager, | |
| 118 scoped_ptr<DownloadSaveInfo> save_info, | |
| 119 uint32_t download_id, | |
| 120 const DownloadUrlParameters::OnStartedCallback& on_started_callback) | |
| 121 : request_(std::move(request)), | 97 : request_(std::move(request)), |
| 122 manager_(manager), | 98 manager_(manager), |
| 123 download_id_(download_id), | 99 core_(request_.get(), this), |
| 124 on_started_callback_(on_started_callback), | |
| 125 handler_( | |
| 126 request_.get(), | |
| 127 std::move(save_info), | |
| 128 base::Bind(&UrlDownloader::ResumeReading, base::Unretained(this))), | |
| 129 weak_ptr_factory_(this) {} | 100 weak_ptr_factory_(this) {} |
| 130 | 101 |
| 131 UrlDownloader::~UrlDownloader() { | 102 UrlDownloader::~UrlDownloader() { |
| 132 CallStartedCallbackOnFailure(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); | |
| 133 } | 103 } |
| 134 | 104 |
| 135 void UrlDownloader::Start() { | 105 void UrlDownloader::Start() { |
| 136 DCHECK(!request_->is_pending()); | 106 DCHECK(!request_->is_pending()); |
| 137 | 107 |
| 138 if (!request_->status().is_success()) | 108 if (!request_->status().is_success()) |
| 139 return; | 109 return; |
| 140 | 110 |
| 141 request_->set_delegate(this); | 111 request_->set_delegate(this); |
| 142 request_->Start(); | 112 request_->Start(); |
| 143 } | 113 } |
| 144 | 114 |
| 145 void UrlDownloader::OnReceivedRedirect(net::URLRequest* request, | 115 void UrlDownloader::OnReceivedRedirect(net::URLRequest* request, |
| 146 const net::RedirectInfo& redirect_info, | 116 const net::RedirectInfo& redirect_info, |
| 147 bool* defer_redirect) { | 117 bool* defer_redirect) { |
| 148 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); | 118 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); |
| 149 request_->CancelWithError(net::ERR_ABORTED); | 119 request_->CancelWithError(net::ERR_ABORTED); |
| 150 } | 120 } |
| 151 | 121 |
| 152 void UrlDownloader::OnResponseStarted(net::URLRequest* request) { | 122 void UrlDownloader::OnResponseStarted(net::URLRequest* request) { |
| 153 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); | 123 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); |
| 154 | 124 |
| 155 if (!request_->status().is_success()) { | 125 if (!request_->status().is_success()) { |
| 156 ResponseCompleted(); | 126 ResponseCompleted(); |
| 157 return; | 127 return; |
| 158 } | 128 } |
| 159 | 129 |
| 160 scoped_ptr<DownloadCreateInfo> create_info; | 130 if (core_.OnResponseStarted(std::string())) |
| 161 scoped_ptr<ByteStreamReader> stream_reader; | |
| 162 | |
| 163 handler_.OnResponseStarted(&create_info, &stream_reader); | |
| 164 | |
| 165 create_info->download_id = download_id_; | |
| 166 create_info->request_handle.reset( | |
| 167 new RequestHandle(weak_ptr_factory_.GetWeakPtr(), manager_, | |
| 168 base::SequencedTaskRunnerHandle::Get())); | |
| 169 BrowserThread::PostTask( | |
| 170 BrowserThread::UI, FROM_HERE, | |
| 171 base::Bind(&DownloadManagerImpl::StartDownload, manager_, | |
| 172 base::Passed(&create_info), base::Passed(&stream_reader), | |
| 173 base::ResetAndReturn(&on_started_callback_))); | |
| 174 | |
| 175 if (request_->status().is_success()) | |
| 176 StartReading(false); // Read the first chunk. | 131 StartReading(false); // Read the first chunk. |
| 177 else | 132 else |
| 178 ResponseCompleted(); | 133 ResponseCompleted(); |
| 179 } | 134 } |
| 180 | 135 |
| 181 void UrlDownloader::StartReading(bool is_continuation) { | 136 void UrlDownloader::StartReading(bool is_continuation) { |
| 182 int bytes_read; | 137 int bytes_read; |
| 183 | 138 |
| 184 // Make sure we track the buffer in at least one place. This ensures it gets | 139 // Make sure we track the buffer in at least one place. This ensures it gets |
| 185 // deleted even in the case the request has already finished its job and | 140 // deleted even in the case the request has already finished its job and |
| 186 // doesn't use the buffer. | 141 // doesn't use the buffer. |
| 187 scoped_refptr<net::IOBuffer> buf; | 142 scoped_refptr<net::IOBuffer> buf; |
| 188 int buf_size; | 143 int buf_size; |
| 189 if (!handler_.OnWillRead(&buf, &buf_size, -1)) { | 144 if (!core_.OnWillRead(&buf, &buf_size, -1)) { |
| 190 request_->CancelWithError(net::ERR_ABORTED); | 145 request_->CancelWithError(net::ERR_ABORTED); |
| 191 base::SequencedTaskRunnerHandle::Get()->PostTask( | 146 base::SequencedTaskRunnerHandle::Get()->PostTask( |
| 192 FROM_HERE, base::Bind(&UrlDownloader::ResponseCompleted, | 147 FROM_HERE, base::Bind(&UrlDownloader::ResponseCompleted, |
| 193 weak_ptr_factory_.GetWeakPtr())); | 148 weak_ptr_factory_.GetWeakPtr())); |
| 194 return; | 149 return; |
| 195 } | 150 } |
| 196 | 151 |
| 197 DCHECK(buf.get()); | 152 DCHECK(buf.get()); |
| 198 DCHECK(buf_size > 0); | 153 DCHECK(buf_size > 0); |
| 199 | 154 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 222 // bytes_read == -1 always implies an error. | 177 // bytes_read == -1 always implies an error. |
| 223 if (bytes_read == -1 || !request_->status().is_success()) { | 178 if (bytes_read == -1 || !request_->status().is_success()) { |
| 224 ResponseCompleted(); | 179 ResponseCompleted(); |
| 225 return; | 180 return; |
| 226 } | 181 } |
| 227 | 182 |
| 228 DCHECK(bytes_read >= 0); | 183 DCHECK(bytes_read >= 0); |
| 229 DCHECK(request_->status().is_success()); | 184 DCHECK(request_->status().is_success()); |
| 230 | 185 |
| 231 bool defer = false; | 186 bool defer = false; |
| 232 if (!handler_.OnReadCompleted(bytes_read, &defer)) { | 187 if (!core_.OnReadCompleted(bytes_read, &defer)) { |
| 233 request_->CancelWithError(net::ERR_ABORTED); | 188 request_->CancelWithError(net::ERR_ABORTED); |
| 234 return; | 189 return; |
| 235 } else if (defer) { | 190 } else if (defer) { |
| 236 return; | 191 return; |
| 237 } | 192 } |
| 238 | 193 |
| 239 if (!request_->status().is_success()) | 194 if (!request_->status().is_success()) |
| 240 return; | 195 return; |
| 241 | 196 |
| 242 if (bytes_read > 0) { | 197 if (bytes_read > 0) { |
| 243 StartReading(true); // Read the next chunk. | 198 StartReading(true); // Read the next chunk. |
| 244 } else { | 199 } else { |
| 245 // URLRequest reported an EOF. Call ResponseCompleted. | 200 // URLRequest reported an EOF. Call ResponseCompleted. |
| 246 DCHECK_EQ(0, bytes_read); | 201 DCHECK_EQ(0, bytes_read); |
| 247 ResponseCompleted(); | 202 ResponseCompleted(); |
| 248 } | 203 } |
| 249 } | 204 } |
| 250 | 205 |
| 251 void UrlDownloader::ResponseCompleted() { | 206 void UrlDownloader::ResponseCompleted() { |
| 252 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); | 207 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); |
| 253 | 208 |
| 254 handler_.OnResponseCompleted(request_->status()); | 209 core_.OnResponseCompleted(request_->status()); |
| 210 Destroy(); |
| 211 } |
| 212 |
| 213 void UrlDownloader::OnStart( |
| 214 scoped_ptr<DownloadCreateInfo> create_info, |
| 215 scoped_ptr<ByteStreamReader> stream_reader, |
| 216 const DownloadUrlParameters::OnStartedCallback& callback) { |
| 217 create_info->request_handle.reset( |
| 218 new RequestHandle(weak_ptr_factory_.GetWeakPtr(), manager_, |
| 219 base::SequencedTaskRunnerHandle::Get())); |
| 220 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 221 base::Bind(&DownloadManagerImpl::StartDownload, |
| 222 manager_, base::Passed(&create_info), |
| 223 base::Passed(&stream_reader), callback)); |
| 224 } |
| 225 |
| 226 void UrlDownloader::OnReadyToRead() { |
| 227 if (request_->status().is_success()) |
| 228 StartReading(false); // Read the next chunk (OK to complete synchronously). |
| 229 else |
| 230 ResponseCompleted(); |
| 231 } |
| 232 |
| 233 void UrlDownloader::PauseRequest() { |
| 234 core_.PauseRequest(); |
| 235 } |
| 236 |
| 237 void UrlDownloader::ResumeRequest() { |
| 238 core_.ResumeRequest(); |
| 239 } |
| 240 |
| 241 void UrlDownloader::CancelRequest() { |
| 242 Destroy(); |
| 243 } |
| 244 |
| 245 void UrlDownloader::Destroy() { |
| 255 BrowserThread::PostTask( | 246 BrowserThread::PostTask( |
| 256 BrowserThread::UI, FROM_HERE, | 247 BrowserThread::UI, FROM_HERE, |
| 257 base::Bind(&DownloadManagerImpl::RemoveUrlDownloader, manager_, this)); | 248 base::Bind(&DownloadManagerImpl::RemoveUrlDownloader, manager_, this)); |
| 258 } | |
| 259 | |
| 260 void UrlDownloader::ResumeReading() { | |
| 261 if (request_->status().is_success()) { | |
| 262 StartReading(false); // Read the next chunk (OK to complete synchronously). | |
| 263 } else { | |
| 264 ResponseCompleted(); | |
| 265 } | |
| 266 } | |
| 267 | |
| 268 void UrlDownloader::CallStartedCallbackOnFailure( | |
| 269 DownloadInterruptReason result) { | |
| 270 if (on_started_callback_.is_null()) | |
| 271 return; | |
| 272 BrowserThread::PostTask( | |
| 273 BrowserThread::UI, FROM_HERE, | |
| 274 base::Bind(base::ResetAndReturn(&on_started_callback_), nullptr, result)); | |
| 275 } | |
| 276 | |
| 277 void UrlDownloader::PauseRequest() { | |
| 278 handler_.PauseRequest(); | |
| 279 } | |
| 280 | |
| 281 void UrlDownloader::ResumeRequest() { | |
| 282 handler_.ResumeRequest(); | |
| 283 } | |
| 284 | |
| 285 void UrlDownloader::CancelRequest() { | |
| 286 BrowserThread::PostTask( | |
| 287 BrowserThread::UI, FROM_HERE, | |
| 288 base::Bind(&DownloadManagerImpl::RemoveUrlDownloader, manager_, this)); | |
| 289 } | 249 } |
| 290 | 250 |
| 291 } // namespace content | 251 } // namespace content |
| OLD | NEW |