OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_impl.h" | 5 #include "content/browser/download/download_manager_impl.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" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 | 43 |
44 using content::BrowserThread; | 44 using content::BrowserThread; |
45 using content::DownloadId; | 45 using content::DownloadId; |
46 using content::DownloadItem; | 46 using content::DownloadItem; |
47 using content::DownloadPersistentStoreInfo; | 47 using content::DownloadPersistentStoreInfo; |
48 using content::ResourceDispatcherHostImpl; | 48 using content::ResourceDispatcherHostImpl; |
49 using content::WebContents; | 49 using content::WebContents; |
50 | 50 |
51 namespace { | 51 namespace { |
52 | 52 |
53 // This is just used to remember which DownloadItems come from SavePage. | |
54 class SavePageExternalData : public DownloadItem::ExternalData { | |
55 public: | |
56 // A spoonful of syntactic sugar. | |
57 static SavePageExternalData* Get(DownloadItem* item) { | |
Randy Smith (Not in Mondays)
2012/07/10 19:06:05
Why not make this return bool? That's what you're
benjhayden
2012/07/10 20:00:08
Done.
| |
58 DownloadItem::ExternalData* data = item->GetExternalData(Key()); | |
59 return data ? static_cast<SavePageExternalData*>(data) : NULL; | |
60 } | |
61 | |
62 explicit SavePageExternalData(DownloadItem* item) { | |
63 item->SetExternalData(Key(), this); | |
64 } | |
65 virtual ~SavePageExternalData() {} | |
66 | |
67 private: | |
68 static const void* Key() { | |
69 return reinterpret_cast<const void*>(&SavePageExternalData::Get); | |
asanka
2012/07/10 18:43:31
Multiple functions with identical code can be alia
Randy Smith (Not in Mondays)
2012/07/10 19:06:05
Agreed. I also think it's useful for debugging (i
benjhayden
2012/07/10 20:00:08
Done.
benjhayden
2012/07/10 20:00:08
Done.
| |
70 } | |
71 | |
72 DISALLOW_COPY_AND_ASSIGN(SavePageExternalData); | |
73 }; | |
74 | |
53 void BeginDownload(content::DownloadUrlParameters* params) { | 75 void BeginDownload(content::DownloadUrlParameters* params) { |
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
55 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and | 77 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and |
56 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so | 78 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so |
57 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. | 79 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. |
58 scoped_ptr<net::URLRequest> request(new net::URLRequest( | 80 scoped_ptr<net::URLRequest> request(new net::URLRequest( |
59 params->url(), | 81 params->url(), |
60 NULL, | 82 NULL, |
61 params->resource_context()->GetRequestContext())); | 83 params->resource_context()->GetRequestContext())); |
62 request->set_referrer(params->referrer().url.spec()); | 84 request->set_referrer(params->referrer().url.spec()); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 // in DownloadItem destruction. | 320 // in DownloadItem destruction. |
299 DownloadMap downloads_to_delete; | 321 DownloadMap downloads_to_delete; |
300 downloads_to_delete.swap(downloads_); | 322 downloads_to_delete.swap(downloads_); |
301 | 323 |
302 active_downloads_.clear(); | 324 active_downloads_.clear(); |
303 STLDeleteValues(&downloads_to_delete); | 325 STLDeleteValues(&downloads_to_delete); |
304 | 326 |
305 // We'll have nothing more to report to the observers after this point. | 327 // We'll have nothing more to report to the observers after this point. |
306 observers_.Clear(); | 328 observers_.Clear(); |
307 | 329 |
308 DCHECK(save_page_downloads_.empty()); | |
309 | |
310 file_manager_ = NULL; | 330 file_manager_ = NULL; |
311 if (delegate_) | 331 if (delegate_) |
312 delegate_->Shutdown(); | 332 delegate_->Shutdown(); |
313 } | 333 } |
314 | 334 |
315 void DownloadManagerImpl::GetTemporaryDownloads( | 335 void DownloadManagerImpl::GetTemporaryDownloads( |
316 const FilePath& dir_path, DownloadVector* result) { | 336 const FilePath& dir_path, DownloadVector* result) { |
317 DCHECK(result); | 337 DCHECK(result); |
318 | 338 |
319 for (DownloadMap::iterator it = downloads_.begin(); | 339 for (DownloadMap::iterator it = downloads_.begin(); |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 page_url, | 552 page_url, |
533 is_otr, | 553 is_otr, |
534 GetNextId(), | 554 GetNextId(), |
535 mime_type, | 555 mime_type, |
536 bound_net_log); | 556 bound_net_log); |
537 | 557 |
538 download->AddObserver(observer); | 558 download->AddObserver(observer); |
539 | 559 |
540 DCHECK(!ContainsKey(downloads_, download->GetId())); | 560 DCHECK(!ContainsKey(downloads_, download->GetId())); |
541 downloads_[download->GetId()] = download; | 561 downloads_[download->GetId()] = download; |
542 DCHECK(!ContainsKey(save_page_downloads_, download->GetId())); | 562 DCHECK(!SavePageExternalData::Get(download)); |
543 save_page_downloads_[download->GetId()] = download; | 563 new SavePageExternalData(download); |
564 DCHECK(SavePageExternalData::Get(download)); | |
544 | 565 |
545 // Will notify the observer in the callback. | 566 // Will notify the observer in the callback. |
546 if (delegate_) | 567 if (delegate_) |
547 delegate_->AddItemToPersistentStore(download); | 568 delegate_->AddItemToPersistentStore(download); |
548 | 569 |
549 return download; | 570 return download; |
550 } | 571 } |
551 | 572 |
552 // The target path for the download item is now valid. We proceed with the | 573 // The target path for the download item is now valid. We proceed with the |
553 // determination of an intermediate path. | 574 // determination of an intermediate path. |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
796 const DownloadVector& pending_deletes) { | 817 const DownloadVector& pending_deletes) { |
797 if (pending_deletes.empty()) | 818 if (pending_deletes.empty()) |
798 return 0; | 819 return 0; |
799 | 820 |
800 // Delete from internal maps. | 821 // Delete from internal maps. |
801 for (DownloadVector::const_iterator it = pending_deletes.begin(); | 822 for (DownloadVector::const_iterator it = pending_deletes.begin(); |
802 it != pending_deletes.end(); | 823 it != pending_deletes.end(); |
803 ++it) { | 824 ++it) { |
804 DownloadItem* download = *it; | 825 DownloadItem* download = *it; |
805 DCHECK(download); | 826 DCHECK(download); |
806 save_page_downloads_.erase(download->GetId()); | |
807 downloads_.erase(download->GetId()); | 827 downloads_.erase(download->GetId()); |
808 } | 828 } |
809 | 829 |
810 // Tell observers to refresh their views. | 830 // Tell observers to refresh their views. |
811 NotifyModelChanged(); | 831 NotifyModelChanged(); |
812 | 832 |
813 // Delete the download items themselves. | 833 // Delete the download items themselves. |
814 const int num_deleted = static_cast<int>(pending_deletes.size()); | 834 const int num_deleted = static_cast<int>(pending_deletes.size()); |
815 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end()); | 835 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end()); |
816 return num_deleted; | 836 return num_deleted; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
967 // This includes buttons to save or cancel, for a dangerous download. | 987 // This includes buttons to save or cancel, for a dangerous download. |
968 ShowDownloadInBrowser(download); | 988 ShowDownloadInBrowser(download); |
969 | 989 |
970 // Inform interested objects about the new download. | 990 // Inform interested objects about the new download. |
971 NotifyModelChanged(); | 991 NotifyModelChanged(); |
972 } | 992 } |
973 | 993 |
974 | 994 |
975 void DownloadManagerImpl::OnItemAddedToPersistentStore(int32 download_id, | 995 void DownloadManagerImpl::OnItemAddedToPersistentStore(int32 download_id, |
976 int64 db_handle) { | 996 int64 db_handle) { |
977 if (save_page_downloads_.count(download_id)) { | 997 DownloadItem* item = GetDownload(download_id); |
998 // It's valid that we don't find a matching item, i.e. on shutdown. | |
999 if (!item) | |
1000 return; | |
1001 if (SavePageExternalData::Get(item)) { | |
978 OnSavePageItemAddedToPersistentStore(download_id, db_handle); | 1002 OnSavePageItemAddedToPersistentStore(download_id, db_handle); |
979 } else if (active_downloads_.count(download_id)) { | 1003 } else { |
980 OnDownloadItemAddedToPersistentStore(download_id, db_handle); | 1004 OnDownloadItemAddedToPersistentStore(download_id, db_handle); |
981 } | 1005 } |
982 // It's valid that we don't find a matching item, i.e. on shutdown. | |
983 } | 1006 } |
984 | 1007 |
985 // Once the new DownloadItem has been committed to the persistent store, | 1008 // Once the new DownloadItem has been committed to the persistent store, |
986 // associate it with its db_handle (TODO(benjhayden) merge db_handle with id), | 1009 // associate it with its db_handle (TODO(benjhayden) merge db_handle with id), |
987 // show it in the browser (TODO(benjhayden) the ui should observe us instead), | 1010 // show it in the browser (TODO(benjhayden) the ui should observe us instead), |
988 // and notify observers (TODO(benjhayden) observers should be able to see the | 1011 // and notify observers (TODO(benjhayden) observers should be able to see the |
989 // item when it's created so they can observe it directly. Are there any | 1012 // item when it's created so they can observe it directly. Are there any |
990 // clients that actually need to know when the item is added to the history?). | 1013 // clients that actually need to know when the item is added to the history?). |
991 void DownloadManagerImpl::OnDownloadItemAddedToPersistentStore( | 1014 void DownloadManagerImpl::OnDownloadItemAddedToPersistentStore( |
992 int32 download_id, int64 db_handle) { | 1015 int32 download_id, int64 db_handle) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1069 if (ContainsKey(active_downloads_, download_id)) | 1092 if (ContainsKey(active_downloads_, download_id)) |
1070 return active_downloads_[download_id]; | 1093 return active_downloads_[download_id]; |
1071 return NULL; | 1094 return NULL; |
1072 } | 1095 } |
1073 | 1096 |
1074 // Confirm that everything in all maps is also in |downloads_|, and that | 1097 // Confirm that everything in all maps is also in |downloads_|, and that |
1075 // everything in |downloads_| is also in some other map. | 1098 // everything in |downloads_| is also in some other map. |
1076 void DownloadManagerImpl::AssertContainersConsistent() const { | 1099 void DownloadManagerImpl::AssertContainersConsistent() const { |
1077 #if !defined(NDEBUG) | 1100 #if !defined(NDEBUG) |
1078 // Turn everything into sets. | 1101 // Turn everything into sets. |
1079 const DownloadMap* input_maps[] = {&active_downloads_, | 1102 const DownloadMap* input_maps[] = {&active_downloads_}; |
1080 &save_page_downloads_}; | 1103 DownloadSet active_set; |
1081 DownloadSet active_set, save_page_set; | 1104 DownloadSet* all_sets[] = {&active_set}; |
1082 DownloadSet* all_sets[] = {&active_set, &save_page_set}; | |
1083 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(all_sets)); | 1105 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(all_sets)); |
1084 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { | 1106 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { |
1085 for (DownloadMap::const_iterator it = input_maps[i]->begin(); | 1107 for (DownloadMap::const_iterator it = input_maps[i]->begin(); |
1086 it != input_maps[i]->end(); ++it) { | 1108 it != input_maps[i]->end(); ++it) { |
1087 all_sets[i]->insert(&*it->second); | 1109 all_sets[i]->insert(&*it->second); |
1088 } | 1110 } |
1089 } | 1111 } |
1090 | 1112 |
1091 DownloadSet all_downloads; | 1113 DownloadSet all_downloads; |
1092 for (DownloadMap::const_iterator it = downloads_.begin(); | 1114 for (DownloadMap::const_iterator it = downloads_.begin(); |
(...skipping 23 matching lines...) Expand all Loading... | |
1116 // Shutdown) the result will be that the SavePage system will not be able to | 1138 // Shutdown) the result will be that the SavePage system will not be able to |
1117 // properly update the download item (which no longer exists) or the download | 1139 // properly update the download item (which no longer exists) or the download |
1118 // history, but the action will complete properly anyway. This may lead to the | 1140 // history, but the action will complete properly anyway. This may lead to the |
1119 // history entry being wrong on a reload of chrome (specifically in the case of | 1141 // history entry being wrong on a reload of chrome (specifically in the case of |
1120 // Initiation -> History Callback -> Removal -> Completion), but there's no way | 1142 // Initiation -> History Callback -> Removal -> Completion), but there's no way |
1121 // to solve that without canceling on Remove (which would then update the DB). | 1143 // to solve that without canceling on Remove (which would then update the DB). |
1122 | 1144 |
1123 void DownloadManagerImpl::OnSavePageItemAddedToPersistentStore( | 1145 void DownloadManagerImpl::OnSavePageItemAddedToPersistentStore( |
1124 int32 download_id, int64 db_handle) { | 1146 int32 download_id, int64 db_handle) { |
1125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1126 | 1148 DownloadItem* download = GetDownload(download_id); |
1127 DownloadMap::const_iterator it = save_page_downloads_.find(download_id); | 1149 DCHECK(download); // TODO(benjhayden) Pass download in. |
Randy Smith (Not in Mondays)
2012/07/10 19:06:05
I don't understand the TODO?
benjhayden
2012/07/10 20:00:08
I realized that it would be easier to do the todo
| |
1128 // This can happen if the download manager is shutting down and all maps | |
1129 // have been cleared. | |
1130 if (it == save_page_downloads_.end()) | |
1131 return; | |
1132 | |
1133 DownloadItem* download = it->second; | |
1134 if (!download) { | |
1135 NOTREACHED(); | |
1136 return; | |
1137 } | |
1138 | 1150 |
1139 AddDownloadItemToHistory(download, db_handle); | 1151 AddDownloadItemToHistory(download, db_handle); |
1140 | 1152 |
1141 // Finalize this download if it finished before the history callback. | 1153 // Finalize this download if it finished before the history callback. |
1142 if (!download->IsInProgress()) | 1154 if (!download->IsInProgress()) |
1143 SavePageDownloadFinished(download); | 1155 SavePageDownloadFinished(download); |
1144 } | 1156 } |
1145 | 1157 |
1146 void DownloadManagerImpl::SavePageDownloadFinished(DownloadItem* download) { | 1158 void DownloadManagerImpl::SavePageDownloadFinished(DownloadItem* download) { |
1147 if (download->IsPersisted()) { | 1159 if (download->IsPersisted()) { |
1148 if (delegate_) | 1160 if (delegate_) |
1149 delegate_->UpdateItemInPersistentStore(download); | 1161 delegate_->UpdateItemInPersistentStore(download); |
1150 DCHECK(ContainsKey(save_page_downloads_, download->GetId())); | |
1151 save_page_downloads_.erase(download->GetId()); | |
1152 | |
1153 if (download->IsComplete()) | 1162 if (download->IsComplete()) |
1154 content::NotificationService::current()->Notify( | 1163 content::NotificationService::current()->Notify( |
1155 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, | 1164 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, |
1156 content::Source<DownloadManager>(this), | 1165 content::Source<DownloadManager>(this), |
1157 content::Details<DownloadItem>(download)); | 1166 content::Details<DownloadItem>(download)); |
1158 } | 1167 } |
1159 } | 1168 } |
1160 | 1169 |
1161 void DownloadManagerImpl::DownloadOpened(DownloadItem* download) { | 1170 void DownloadManagerImpl::DownloadOpened(DownloadItem* download) { |
1162 if (delegate_) | 1171 if (delegate_) |
(...skipping 21 matching lines...) Expand all Loading... | |
1184 void DownloadManagerImpl::DownloadRenamedToFinalName( | 1193 void DownloadManagerImpl::DownloadRenamedToFinalName( |
1185 DownloadItem* download) { | 1194 DownloadItem* download) { |
1186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1187 // If the rename failed, we receive an OnDownloadInterrupted() call before we | 1196 // If the rename failed, we receive an OnDownloadInterrupted() call before we |
1188 // receive the DownloadRenamedToFinalName() call. | 1197 // receive the DownloadRenamedToFinalName() call. |
1189 if (delegate_) { | 1198 if (delegate_) { |
1190 delegate_->UpdatePathForItemInPersistentStore( | 1199 delegate_->UpdatePathForItemInPersistentStore( |
1191 download, download->GetFullPath()); | 1200 download, download->GetFullPath()); |
1192 } | 1201 } |
1193 } | 1202 } |
OLD | NEW |