OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/download_manager.h" | 5 #include "content/browser/download/download_manager.h" |
6 | 6 |
7 #include <iterator> | 7 #include <iterator> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/i18n/case_conversion.h" | 12 #include "base/i18n/case_conversion.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
15 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
17 #include "base/sys_string_conversions.h" | 17 #include "base/sys_string_conversions.h" |
18 #include "base/task.h" | |
19 #include "build/build_config.h" | 18 #include "build/build_config.h" |
20 #include "content/browser/browser_context.h" | 19 #include "content/browser/browser_context.h" |
21 #include "content/browser/browser_thread.h" | 20 #include "content/browser/browser_thread.h" |
22 #include "content/browser/download/download_create_info.h" | 21 #include "content/browser/download/download_create_info.h" |
23 #include "content/browser/download/download_file_manager.h" | 22 #include "content/browser/download/download_file_manager.h" |
24 #include "content/browser/download/download_item.h" | 23 #include "content/browser/download/download_item.h" |
25 #include "content/browser/download/download_persistent_store_info.h" | 24 #include "content/browser/download/download_persistent_store_info.h" |
26 #include "content/browser/download/download_stats.h" | 25 #include "content/browser/download/download_stats.h" |
27 #include "content/browser/download/download_status_updater.h" | 26 #include "content/browser/download/download_status_updater.h" |
28 #include "content/browser/download/interrupt_reasons.h" | 27 #include "content/browser/download/interrupt_reasons.h" |
29 #include "content/browser/renderer_host/render_process_host.h" | 28 #include "content/browser/renderer_host/render_process_host.h" |
30 #include "content/browser/renderer_host/render_view_host.h" | 29 #include "content/browser/renderer_host/render_view_host.h" |
31 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 30 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
32 #include "content/browser/tab_contents/tab_contents.h" | 31 #include "content/browser/tab_contents/tab_contents.h" |
33 #include "content/public/browser/content_browser_client.h" | 32 #include "content/public/browser/content_browser_client.h" |
34 #include "content/public/browser/download_manager_delegate.h" | 33 #include "content/public/browser/download_manager_delegate.h" |
35 #include "content/public/browser/notification_service.h" | 34 #include "content/public/browser/notification_service.h" |
36 #include "content/public/browser/notification_types.h" | 35 #include "content/public/browser/notification_types.h" |
37 | 36 |
38 namespace { | 37 namespace { |
39 | 38 |
40 void BeginDownload( | 39 // Param structs exist because base::Bind can only handle 6 args. |
41 const GURL& url, | 40 struct URLParams { |
42 const GURL& referrer, | 41 URLParams(const GURL& url, const GURL& referrer) |
43 const DownloadSaveInfo& save_info, | 42 : url_(url), referrer_(referrer) {} |
44 ResourceDispatcherHost* resource_dispatcher_host, | 43 GURL url_; |
45 int render_process_id, | 44 GURL referrer_; |
46 int render_view_id, | 45 }; |
47 const content::ResourceContext* context) { | 46 |
48 net::URLRequest* request = new net::URLRequest(url, resource_dispatcher_host); | 47 struct RenderParams { |
49 request->set_referrer(referrer.spec()); | 48 RenderParams(int rpi, int rvi) |
| 49 : render_process_id_(rpi), render_view_id_(rvi) {} |
| 50 int render_process_id_; |
| 51 int render_view_id_; |
| 52 }; |
| 53 |
| 54 void BeginDownload(const URLParams& url_params, |
| 55 const DownloadSaveInfo& save_info, |
| 56 ResourceDispatcherHost* resource_dispatcher_host, |
| 57 const RenderParams& render_params, |
| 58 const content::ResourceContext* context) { |
| 59 net::URLRequest* request = new net::URLRequest(url_params.url_, |
| 60 resource_dispatcher_host); |
| 61 request->set_referrer(url_params.referrer_.spec()); |
50 resource_dispatcher_host->BeginDownload( | 62 resource_dispatcher_host->BeginDownload( |
51 request, | 63 request, save_info, true, |
52 save_info, | |
53 true, | |
54 DownloadResourceHandler::OnStartedCallback(), | 64 DownloadResourceHandler::OnStartedCallback(), |
55 render_process_id, | 65 render_params.render_process_id_, |
56 render_view_id, | 66 render_params.render_view_id_, |
57 *context); | 67 *context); |
58 } | 68 } |
59 | 69 |
60 } // namespace | 70 } // namespace |
61 | 71 |
62 DownloadManager::DownloadManager(content::DownloadManagerDelegate* delegate, | 72 DownloadManager::DownloadManager(content::DownloadManagerDelegate* delegate, |
63 DownloadStatusUpdater* status_updater) | 73 DownloadStatusUpdater* status_updater) |
64 : shutdown_needed_(false), | 74 : shutdown_needed_(false), |
65 browser_context_(NULL), | 75 browser_context_(NULL), |
66 next_id_(0), | 76 next_id_(0), |
(...skipping 20 matching lines...) Expand all Loading... |
87 << " shutdown_needed_ = " << shutdown_needed_; | 97 << " shutdown_needed_ = " << shutdown_needed_; |
88 if (!shutdown_needed_) | 98 if (!shutdown_needed_) |
89 return; | 99 return; |
90 shutdown_needed_ = false; | 100 shutdown_needed_ = false; |
91 | 101 |
92 FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown()); | 102 FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown()); |
93 // TODO(benjhayden): Consider clearing observers_. | 103 // TODO(benjhayden): Consider clearing observers_. |
94 | 104 |
95 if (file_manager_) { | 105 if (file_manager_) { |
96 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 106 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
97 NewRunnableMethod(file_manager_, | 107 base::Bind(&DownloadFileManager::OnDownloadManagerShutdown, |
98 &DownloadFileManager::OnDownloadManagerShutdown, | 108 file_manager_, make_scoped_refptr(this))); |
99 make_scoped_refptr(this))); | |
100 } | 109 } |
101 | 110 |
102 AssertContainersConsistent(); | 111 AssertContainersConsistent(); |
103 | 112 |
104 // Go through all downloads in downloads_. Dangerous ones we need to | 113 // Go through all downloads in downloads_. Dangerous ones we need to |
105 // remove on disk, and in progress ones we need to cancel. | 114 // remove on disk, and in progress ones we need to cancel. |
106 for (DownloadSet::iterator it = downloads_.begin(); it != downloads_.end();) { | 115 for (DownloadSet::iterator it = downloads_.begin(); it != downloads_.end();) { |
107 DownloadItem* download = *it; | 116 DownloadItem* download = *it; |
108 | 117 |
109 // Save iterator from potential erases in this set done by called code. | 118 // Save iterator from potential erases in this set done by called code. |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 CheckForFileRemoval(it->second); | 265 CheckForFileRemoval(it->second); |
257 } | 266 } |
258 } | 267 } |
259 | 268 |
260 void DownloadManager::CheckForFileRemoval(DownloadItem* download_item) { | 269 void DownloadManager::CheckForFileRemoval(DownloadItem* download_item) { |
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
262 if (download_item->IsComplete() && | 271 if (download_item->IsComplete() && |
263 !download_item->file_externally_removed()) { | 272 !download_item->file_externally_removed()) { |
264 BrowserThread::PostTask( | 273 BrowserThread::PostTask( |
265 BrowserThread::FILE, FROM_HERE, | 274 BrowserThread::FILE, FROM_HERE, |
266 NewRunnableMethod(this, | 275 base::Bind(&DownloadManager::CheckForFileRemovalOnFileThread, |
267 &DownloadManager::CheckForFileRemovalOnFileThread, | 276 this, download_item->db_handle(), |
268 download_item->db_handle(), | 277 download_item->GetTargetFilePath())); |
269 download_item->GetTargetFilePath())); | |
270 } | 278 } |
271 } | 279 } |
272 | 280 |
273 void DownloadManager::CheckForFileRemovalOnFileThread( | 281 void DownloadManager::CheckForFileRemovalOnFileThread( |
274 int64 db_handle, const FilePath& path) { | 282 int64 db_handle, const FilePath& path) { |
275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
276 if (!file_util::PathExists(path)) { | 284 if (!file_util::PathExists(path)) { |
277 BrowserThread::PostTask( | 285 BrowserThread::PostTask( |
278 BrowserThread::UI, FROM_HERE, | 286 BrowserThread::UI, FROM_HERE, |
279 NewRunnableMethod(this, | 287 base::Bind(&DownloadManager::OnFileRemovalDetected, this, db_handle)); |
280 &DownloadManager::OnFileRemovalDetected, | |
281 db_handle)); | |
282 } | 288 } |
283 } | 289 } |
284 | 290 |
285 void DownloadManager::OnFileRemovalDetected(int64 db_handle) { | 291 void DownloadManager::OnFileRemovalDetected(int64 db_handle) { |
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
287 DownloadMap::iterator it = history_downloads_.find(db_handle); | 293 DownloadMap::iterator it = history_downloads_.find(db_handle); |
288 if (it != history_downloads_.end()) { | 294 if (it != history_downloads_.end()) { |
289 DownloadItem* download_item = it->second; | 295 DownloadItem* download_item = it->second; |
290 download_item->OnDownloadedFileRemoved(); | 296 download_item->OnDownloadedFileRemoved(); |
291 } | 297 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 in_progress_[download_id] = download; | 370 in_progress_[download_id] = download; |
365 UpdateDownloadProgress(); // Reflect entry into in_progress_. | 371 UpdateDownloadProgress(); // Reflect entry into in_progress_. |
366 | 372 |
367 // Rename to intermediate name. | 373 // Rename to intermediate name. |
368 FilePath download_path; | 374 FilePath download_path; |
369 if (!delegate_->OverrideIntermediatePath(download, &download_path)) | 375 if (!delegate_->OverrideIntermediatePath(download, &download_path)) |
370 download_path = download->full_path(); | 376 download_path = download->full_path(); |
371 | 377 |
372 BrowserThread::PostTask( | 378 BrowserThread::PostTask( |
373 BrowserThread::FILE, FROM_HERE, | 379 BrowserThread::FILE, FROM_HERE, |
374 NewRunnableMethod( | 380 base::Bind(&DownloadFileManager::RenameInProgressDownloadFile, |
375 file_manager_, &DownloadFileManager::RenameInProgressDownloadFile, | 381 file_manager_, download->global_id(), download_path)); |
376 download->global_id(), download_path)); | |
377 | 382 |
378 download->Rename(download_path); | 383 download->Rename(download_path); |
379 | 384 |
380 delegate_->AddItemToPersistentStore(download); | 385 delegate_->AddItemToPersistentStore(download); |
381 } | 386 } |
382 | 387 |
383 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { | 388 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { |
384 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
385 DownloadMap::iterator it = active_downloads_.find(download_id); | 390 DownloadMap::iterator it = active_downloads_.find(download_id); |
386 if (it != active_downloads_.end()) { | 391 if (it != active_downloads_.end()) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
528 | 533 |
529 DownloadItem* item = GetDownloadItem(download_id); | 534 DownloadItem* item = GetDownloadItem(download_id); |
530 if (!item) | 535 if (!item) |
531 return; | 536 return; |
532 | 537 |
533 if (item->safety_state() == DownloadItem::SAFE) { | 538 if (item->safety_state() == DownloadItem::SAFE) { |
534 DCHECK_EQ(0, uniquifier) << "We should not uniquify SAFE downloads twice"; | 539 DCHECK_EQ(0, uniquifier) << "We should not uniquify SAFE downloads twice"; |
535 } | 540 } |
536 | 541 |
537 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, NewRunnableMethod( | 542 BrowserThread::PostTask( |
538 file_manager_, | 543 BrowserThread::FILE, FROM_HERE, |
539 &DownloadFileManager::CompleteDownload, | 544 base::Bind(&DownloadFileManager::CompleteDownload, |
540 item->global_id())); | 545 file_manager_, item->global_id())); |
541 | 546 |
542 if (uniquifier) | 547 if (uniquifier) |
543 item->set_path_uniquifier(uniquifier); | 548 item->set_path_uniquifier(uniquifier); |
544 | 549 |
545 item->OnDownloadRenamedToFinalName(full_path); | 550 item->OnDownloadRenamedToFinalName(full_path); |
546 delegate_->UpdatePathForItemInPersistentStore(item, full_path); | 551 delegate_->UpdatePathForItemInPersistentStore(item, full_path); |
547 } | 552 } |
548 | 553 |
549 void DownloadManager::CancelDownload(int32 download_id) { | 554 void DownloadManager::CancelDownload(int32 download_id) { |
550 DownloadItem* download = GetActiveDownload(download_id); | 555 DownloadItem* download = GetActiveDownload(download_id); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 void DownloadManager::DownloadUrlToFile(const GURL& url, | 716 void DownloadManager::DownloadUrlToFile(const GURL& url, |
712 const GURL& referrer, | 717 const GURL& referrer, |
713 const std::string& referrer_charset, | 718 const std::string& referrer_charset, |
714 const DownloadSaveInfo& save_info, | 719 const DownloadSaveInfo& save_info, |
715 TabContents* tab_contents) { | 720 TabContents* tab_contents) { |
716 DCHECK(tab_contents); | 721 DCHECK(tab_contents); |
717 ResourceDispatcherHost* resource_dispatcher_host = | 722 ResourceDispatcherHost* resource_dispatcher_host = |
718 content::GetContentClient()->browser()->GetResourceDispatcherHost(); | 723 content::GetContentClient()->browser()->GetResourceDispatcherHost(); |
719 // We send a pointer to content::ResourceContext, instead of the usual | 724 // We send a pointer to content::ResourceContext, instead of the usual |
720 // reference, so that a copy of the object isn't made. | 725 // reference, so that a copy of the object isn't made. |
721 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 726 // base::Bind can't handle 7 args, so we use URLParams and RenderParams. |
722 NewRunnableFunction(&BeginDownload, | 727 BrowserThread::PostTask( |
723 url, | 728 BrowserThread::IO, FROM_HERE, |
724 referrer, | 729 base::Bind(&BeginDownload, |
725 save_info, | 730 URLParams(url, referrer), save_info, resource_dispatcher_host, |
726 resource_dispatcher_host, | 731 RenderParams(tab_contents->GetRenderProcessHost()->id(), |
727 tab_contents->GetRenderProcessHost()->id(), | 732 tab_contents->render_view_host()->routing_id()), |
728 tab_contents->render_view_host()->routing_id(), | 733 &tab_contents->browser_context()->GetResourceContext())); |
729 &tab_contents->browser_context()-> | |
730 GetResourceContext())); | |
731 } | 734 } |
732 | 735 |
733 void DownloadManager::AddObserver(Observer* observer) { | 736 void DownloadManager::AddObserver(Observer* observer) { |
734 observers_.AddObserver(observer); | 737 observers_.AddObserver(observer); |
735 observer->ModelChanged(); | 738 observer->ModelChanged(); |
736 } | 739 } |
737 | 740 |
738 void DownloadManager::RemoveObserver(Observer* observer) { | 741 void DownloadManager::RemoveObserver(Observer* observer) { |
739 observers_.RemoveObserver(observer); | 742 observers_.RemoveObserver(observer); |
740 } | 743 } |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 void DownloadManager::MarkDownloadOpened(DownloadItem* download) { | 1088 void DownloadManager::MarkDownloadOpened(DownloadItem* download) { |
1086 delegate_->UpdateItemInPersistentStore(download); | 1089 delegate_->UpdateItemInPersistentStore(download); |
1087 int num_unopened = 0; | 1090 int num_unopened = 0; |
1088 for (DownloadMap::iterator it = history_downloads_.begin(); | 1091 for (DownloadMap::iterator it = history_downloads_.begin(); |
1089 it != history_downloads_.end(); ++it) { | 1092 it != history_downloads_.end(); ++it) { |
1090 if (it->second->IsComplete() && !it->second->opened()) | 1093 if (it->second->IsComplete() && !it->second->opened()) |
1091 ++num_unopened; | 1094 ++num_unopened; |
1092 } | 1095 } |
1093 download_stats::RecordOpensOutstanding(num_unopened); | 1096 download_stats::RecordOpensOutstanding(num_unopened); |
1094 } | 1097 } |
OLD | NEW |