OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/download/download_file_manager.h" | 5 #include "chrome/browser/download/download_file_manager.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/task.h" | 8 #include "base/task.h" |
9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 resource_dispatcher_host_, | 195 resource_dispatcher_host_, |
196 info->child_id, | 196 info->child_id, |
197 info->request_id)); | 197 info->request_id)); |
198 delete info; | 198 delete info; |
199 delete download; | 199 delete download; |
200 return; | 200 return; |
201 } | 201 } |
202 | 202 |
203 DCHECK(GetDownloadFile(info->download_id) == NULL); | 203 DCHECK(GetDownloadFile(info->download_id) == NULL); |
204 downloads_[info->download_id] = download; | 204 downloads_[info->download_id] = download; |
205 info->path = download->full_path(); | 205 // TODO(phajdan.jr): fix the duplication of path info below. |
| 206 info->path = info->save_info.file_path; |
206 { | 207 { |
207 AutoLock lock(progress_lock_); | 208 AutoLock lock(progress_lock_); |
208 ui_progress_[info->download_id] = info->received_bytes; | 209 ui_progress_[info->download_id] = info->received_bytes; |
209 } | 210 } |
210 | 211 |
211 ChromeThread::PostTask( | 212 ChromeThread::PostTask( |
212 ChromeThread::UI, FROM_HERE, | 213 ChromeThread::UI, FROM_HERE, |
213 NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info)); | 214 NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info)); |
214 } | 215 } |
215 | 216 |
216 // We don't forward an update to the UI thread here, since we want to throttle | 217 // We don't forward an update to the UI thread here, since we want to throttle |
217 // the UI update rate via a periodic timer. If the user has cancelled the | 218 // the UI update rate via a periodic timer. If the user has cancelled the |
218 // download (in the UI thread), we may receive a few more updates before the IO | 219 // download (in the UI thread), we may receive a few more updates before the IO |
219 // thread gets the cancel message: we just delete the data since the | 220 // thread gets the cancel message: we just delete the data since the |
220 // DownloadFile has been deleted. | 221 // DownloadFile has been deleted. |
221 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { | 222 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { |
222 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | 223 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
223 std::vector<DownloadBuffer::Contents> contents; | 224 std::vector<DownloadBuffer::Contents> contents; |
224 { | 225 { |
225 AutoLock auto_lock(buffer->lock); | 226 AutoLock auto_lock(buffer->lock); |
226 contents.swap(buffer->contents); | 227 contents.swap(buffer->contents); |
227 } | 228 } |
228 | 229 |
| 230 // Keep track of how many bytes we have successfully saved to update |
| 231 // our progress status in the UI. |
| 232 int64 progress_bytes = 0; |
| 233 |
229 DownloadFile* download = GetDownloadFile(id); | 234 DownloadFile* download = GetDownloadFile(id); |
230 for (size_t i = 0; i < contents.size(); ++i) { | 235 for (size_t i = 0; i < contents.size(); ++i) { |
231 net::IOBuffer* data = contents[i].first; | 236 net::IOBuffer* data = contents[i].first; |
232 const int data_len = contents[i].second; | 237 const int data_len = contents[i].second; |
233 if (download) | 238 if (download) { |
234 download->AppendDataToFile(data->data(), data_len); | 239 if (download->AppendDataToFile(data->data(), data_len)) |
| 240 progress_bytes += data_len; |
| 241 } |
235 data->Release(); | 242 data->Release(); |
236 } | 243 } |
237 | 244 |
238 if (download) { | 245 if (download) { |
239 AutoLock lock(progress_lock_); | 246 AutoLock lock(progress_lock_); |
240 ui_progress_[download->id()] = download->bytes_so_far(); | 247 ui_progress_[download->id()] += progress_bytes; |
241 } | 248 } |
242 } | 249 } |
243 | 250 |
244 void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) { | 251 void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) { |
245 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | 252 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
246 delete buffer; | 253 delete buffer; |
247 DownloadFileMap::iterator it = downloads_.find(id); | 254 DownloadFileMap::iterator it = downloads_.find(id); |
248 if (it != downloads_.end()) { | 255 if (it != downloads_.end()) { |
249 DownloadFile* download = it->second; | 256 DownloadFile* download = it->second; |
250 download->set_in_progress(false); | 257 download->Finish(); |
| 258 |
| 259 int64 download_size = -1; |
| 260 { |
| 261 AutoLock lock(progress_lock_); |
| 262 download_size = ui_progress_[download->id()]; |
| 263 } |
251 | 264 |
252 ChromeThread::PostTask( | 265 ChromeThread::PostTask( |
253 ChromeThread::UI, FROM_HERE, | 266 ChromeThread::UI, FROM_HERE, |
254 NewRunnableMethod( | 267 NewRunnableMethod( |
255 this, &DownloadFileManager::OnDownloadFinished, | 268 this, &DownloadFileManager::OnDownloadFinished, |
256 id, download->bytes_so_far())); | 269 id, download_size)); |
257 | 270 |
258 // We need to keep the download around until the UI thread has finalized | 271 // We need to keep the download around until the UI thread has finalized |
259 // the name. | 272 // the name. |
260 if (download->path_renamed()) { | 273 if (download->path_renamed()) { |
261 downloads_.erase(it); | 274 downloads_.erase(it); |
262 delete download; | 275 delete download; |
263 } | 276 } |
264 } | 277 } |
265 | 278 |
266 if (downloads_.empty()) | 279 if (downloads_.empty()) |
267 ChromeThread::PostTask( | 280 ChromeThread::PostTask( |
268 ChromeThread::UI, FROM_HERE, | 281 ChromeThread::UI, FROM_HERE, |
269 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer)); | 282 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer)); |
270 } | 283 } |
271 | 284 |
272 // This method will be sent via a user action, or shutdown on the UI thread, and | 285 // This method will be sent via a user action, or shutdown on the UI thread, and |
273 // run on the download thread. Since this message has been sent from the UI | 286 // run on the download thread. Since this message has been sent from the UI |
274 // thread, the download may have already completed and won't exist in our map. | 287 // thread, the download may have already completed and won't exist in our map. |
275 void DownloadFileManager::CancelDownload(int id) { | 288 void DownloadFileManager::CancelDownload(int id) { |
276 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | 289 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
277 DownloadFileMap::iterator it = downloads_.find(id); | 290 DownloadFileMap::iterator it = downloads_.find(id); |
278 if (it != downloads_.end()) { | 291 if (it != downloads_.end()) { |
279 DownloadFile* download = it->second; | 292 DownloadFile* download = it->second; |
280 download->set_in_progress(false); | |
281 | |
282 download->Cancel(); | 293 download->Cancel(); |
283 | 294 |
284 ChromeThread::PostTask( | 295 ChromeThread::PostTask( |
285 ChromeThread::UI, FROM_HERE, | 296 ChromeThread::UI, FROM_HERE, |
286 NewRunnableMethod( | 297 NewRunnableMethod( |
287 this, &DownloadFileManager::RemoveDownloadFromUIProgress, | 298 this, &DownloadFileManager::RemoveDownloadFromUIProgress, |
288 download->id())); | 299 download->id())); |
289 | 300 |
290 if (download->path_renamed()) { | 301 if (download->path_renamed()) { |
291 downloads_.erase(it); | 302 downloads_.erase(it); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 } else { | 441 } else { |
431 // Error. Between the time the UI thread generated 'full_path' to the time | 442 // Error. Between the time the UI thread generated 'full_path' to the time |
432 // this code runs, something happened that prevents us from renaming. | 443 // this code runs, something happened that prevents us from renaming. |
433 DownloadManagerMap::iterator dmit = managers_.find(download->id()); | 444 DownloadManagerMap::iterator dmit = managers_.find(download->id()); |
434 if (dmit != managers_.end()) { | 445 if (dmit != managers_.end()) { |
435 DownloadManager* dlm = dmit->second; | 446 DownloadManager* dlm = dmit->second; |
436 ChromeThread::PostTask( | 447 ChromeThread::PostTask( |
437 ChromeThread::UI, FROM_HERE, | 448 ChromeThread::UI, FROM_HERE, |
438 NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id)); | 449 NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id)); |
439 } else { | 450 } else { |
440 ChromeThread::PostTask( | 451 download->CancelDownloadRequest(resource_dispatcher_host_); |
441 ChromeThread::IO, FROM_HERE, | |
442 NewRunnableFunction(&download_util::CancelDownloadRequest, | |
443 resource_dispatcher_host_, | |
444 download->child_id(), | |
445 download->request_id())); | |
446 } | 452 } |
447 } | 453 } |
448 | 454 |
449 // If the download has completed before we got this final name, we remove it | 455 // If the download has completed before we got this final name, we remove it |
450 // from our in progress map. | 456 // from our in progress map. |
451 if (!download->in_progress()) { | 457 if (!download->in_progress()) { |
452 downloads_.erase(it); | 458 downloads_.erase(it); |
453 delete download; | 459 delete download; |
454 } | 460 } |
455 | 461 |
456 if (downloads_.empty()) { | 462 if (downloads_.empty()) { |
457 ChromeThread::PostTask( | 463 ChromeThread::PostTask( |
458 ChromeThread::UI, FROM_HERE, | 464 ChromeThread::UI, FROM_HERE, |
459 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer)); | 465 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer)); |
460 } | 466 } |
461 } | 467 } |
462 | 468 |
OLD | NEW |