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()) |
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 |