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 "chrome/browser/download/download_manager.h" | 5 #include "chrome/browser/download/download_manager.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/i18n/case_conversion.h" | 9 #include "base/i18n/case_conversion.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 #include "grit/theme_resources.h" | 47 #include "grit/theme_resources.h" |
48 #include "net/base/mime_util.h" | 48 #include "net/base/mime_util.h" |
49 #include "net/base/net_util.h" | 49 #include "net/base/net_util.h" |
50 #include "ui/base/l10n/l10n_util.h" | 50 #include "ui/base/l10n/l10n_util.h" |
51 #include "ui/base/resource/resource_bundle.h" | 51 #include "ui/base/resource/resource_bundle.h" |
52 | 52 |
53 DownloadManager::DownloadManager(DownloadStatusUpdater* status_updater) | 53 DownloadManager::DownloadManager(DownloadStatusUpdater* status_updater) |
54 : shutdown_needed_(false), | 54 : shutdown_needed_(false), |
55 profile_(NULL), | 55 profile_(NULL), |
56 file_manager_(NULL), | 56 file_manager_(NULL), |
57 status_updater_(status_updater->AsWeakPtr()) { | 57 status_updater_(status_updater->AsWeakPtr()), |
58 next_save_page_id_(0) { | |
58 if (status_updater_) | 59 if (status_updater_) |
59 status_updater_->AddDelegate(this); | 60 status_updater_->AddDelegate(this); |
60 } | 61 } |
61 | 62 |
62 DownloadManager::~DownloadManager() { | 63 DownloadManager::~DownloadManager() { |
63 DCHECK(!shutdown_needed_); | 64 DCHECK(!shutdown_needed_); |
64 if (status_updater_) | 65 if (status_updater_) |
65 status_updater_->RemoveDelegate(this); | 66 status_updater_->RemoveDelegate(this); |
66 } | 67 } |
67 | 68 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 // anything left. | 116 // anything left. |
116 | 117 |
117 // Copy downloads_ to separate container so as not to set off checks | 118 // Copy downloads_ to separate container so as not to set off checks |
118 // in DownloadItem destruction. | 119 // in DownloadItem destruction. |
119 DownloadSet downloads_to_delete; | 120 DownloadSet downloads_to_delete; |
120 downloads_to_delete.swap(downloads_); | 121 downloads_to_delete.swap(downloads_); |
121 | 122 |
122 in_progress_.clear(); | 123 in_progress_.clear(); |
123 active_downloads_.clear(); | 124 active_downloads_.clear(); |
124 history_downloads_.clear(); | 125 history_downloads_.clear(); |
125 #if !defined(NDEBUG) | |
126 save_page_as_downloads_.clear(); | |
127 #endif | |
128 STLDeleteElements(&downloads_to_delete); | 126 STLDeleteElements(&downloads_to_delete); |
129 | 127 |
128 DCHECK(save_page_downloads_.empty()); | |
129 | |
130 file_manager_ = NULL; | 130 file_manager_ = NULL; |
131 | 131 |
132 // Make sure the save as dialog doesn't notify us back if we're gone before | 132 // Make sure the save as dialog doesn't notify us back if we're gone before |
133 // it returns. | 133 // it returns. |
134 if (select_file_dialog_.get()) | 134 if (select_file_dialog_.get()) |
135 select_file_dialog_->ListenerDestroyed(); | 135 select_file_dialog_->ListenerDestroyed(); |
136 | 136 |
137 download_history_.reset(); | 137 download_history_.reset(); |
138 download_prefs_.reset(); | 138 download_prefs_.reset(); |
139 | 139 |
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
905 if (it == history_downloads_.end()) | 905 if (it == history_downloads_.end()) |
906 return; | 906 return; |
907 | 907 |
908 // Make history update. | 908 // Make history update. |
909 DownloadItem* download = it->second; | 909 DownloadItem* download = it->second; |
910 download_history_->RemoveEntry(download); | 910 download_history_->RemoveEntry(download); |
911 | 911 |
912 // Remove from our tables and delete. | 912 // Remove from our tables and delete. |
913 history_downloads_.erase(it); | 913 history_downloads_.erase(it); |
914 int downloads_count = downloads_.erase(download); | 914 int downloads_count = downloads_.erase(download); |
915 DCHECK_EQ(1, downloads_count); | 915 DCHECK_EQ(1, downloads_count); |
Randy Smith (Not in Mondays)
2011/07/25 18:59:31
We need to remove the download from save_page_down
achuithb
2011/07/27 01:04:57
I took the liberty of pulling out all the code tha
Randy Smith (Not in Mondays)
2011/07/27 21:08:35
I think this was a good idea that probably proacti
| |
916 | 916 |
917 // Tell observers to refresh their views. | 917 // Tell observers to refresh their views. |
918 NotifyModelChanged(); | 918 NotifyModelChanged(); |
919 | 919 |
920 delete download; | 920 delete download; |
921 } | 921 } |
922 | 922 |
923 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, | 923 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, |
924 const base::Time remove_end) { | 924 const base::Time remove_end) { |
925 download_history_->RemoveEntriesBetween(remove_begin, remove_end); | 925 download_history_->RemoveEntriesBetween(remove_begin, remove_end); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 int DownloadManager::RemoveAllDownloads() { | 978 int DownloadManager::RemoveAllDownloads() { |
979 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) { | 979 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) { |
980 // This is an incognito downloader. Clear All should clear main download | 980 // This is an incognito downloader. Clear All should clear main download |
981 // manager as well. | 981 // manager as well. |
982 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads(); | 982 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads(); |
983 } | 983 } |
984 // The null times make the date range unbounded. | 984 // The null times make the date range unbounded. |
985 return RemoveDownloadsBetween(base::Time(), base::Time()); | 985 return RemoveDownloadsBetween(base::Time(), base::Time()); |
986 } | 986 } |
987 | 987 |
988 void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download) { | |
989 #if !defined(NDEBUG) | |
990 save_page_as_downloads_.insert(download); | |
991 #endif | |
992 downloads_.insert(download); | |
993 // Add to history and notify observers. | |
994 AddDownloadItemToHistory(download, DownloadHistory::kUninitializedHandle); | |
995 NotifyModelChanged(); | |
996 } | |
997 | |
998 // Initiate a download of a specific URL. We send the request to the | 988 // Initiate a download of a specific URL. We send the request to the |
999 // ResourceDispatcherHost, and let it send us responses like a regular | 989 // ResourceDispatcherHost, and let it send us responses like a regular |
1000 // download. | 990 // download. |
1001 void DownloadManager::DownloadUrl(const GURL& url, | 991 void DownloadManager::DownloadUrl(const GURL& url, |
1002 const GURL& referrer, | 992 const GURL& referrer, |
1003 const std::string& referrer_charset, | 993 const std::string& referrer_charset, |
1004 TabContents* tab_contents) { | 994 TabContents* tab_contents) { |
1005 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), | 995 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), |
1006 tab_contents); | 996 tab_contents); |
1007 } | 997 } |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1190 | 1180 |
1191 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508 | 1181 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508 |
1192 // is fixed. | 1182 // is fixed. |
1193 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle); | 1183 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle); |
1194 | 1184 |
1195 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); | 1185 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); |
1196 download->set_db_handle(db_handle); | 1186 download->set_db_handle(db_handle); |
1197 | 1187 |
1198 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); | 1188 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); |
1199 history_downloads_[download->db_handle()] = download; | 1189 history_downloads_[download->db_handle()] = download; |
1190 | |
1191 // Show in the appropriate browser UI. | |
1192 // This includes buttons to save or cancel, for a dangerous download. | |
1193 ShowDownloadInBrowser(download); | |
1194 | |
1195 // Inform interested objects about the new download. | |
1196 NotifyModelChanged(); | |
1200 } | 1197 } |
1201 | 1198 |
1202 // Once the new DownloadItem's creation info has been committed to the history | 1199 // Once the new DownloadItem's creation info has been committed to the history |
1203 // service, we associate the DownloadItem with the db handle, update our | 1200 // service, we associate the DownloadItem with the db handle, update our |
1204 // 'history_downloads_' map and inform observers. | 1201 // 'history_downloads_' map and inform observers. |
1205 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, | 1202 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, |
1206 int64 db_handle) { | 1203 int64 db_handle) { |
1207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1208 DownloadItem* download = GetActiveDownloadItem(download_id); | 1205 DownloadItem* download = GetActiveDownloadItem(download_id); |
1209 if (!download) | 1206 if (!download) |
1210 return; | 1207 return; |
1211 | 1208 |
1212 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle | 1209 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle |
1213 << " download_id = " << download_id | 1210 << " download_id = " << download_id |
1214 << " download = " << download->DebugString(true); | 1211 << " download = " << download->DebugString(true); |
1215 | 1212 |
1216 AddDownloadItemToHistory(download, db_handle); | 1213 AddDownloadItemToHistory(download, db_handle); |
1217 | 1214 |
1218 // Show in the appropriate browser UI. | |
1219 // This includes buttons to save or cancel, for a dangerous download. | |
1220 ShowDownloadInBrowser(download); | |
1221 | |
1222 // Inform interested objects about the new download. | |
1223 NotifyModelChanged(); | |
1224 | |
1225 // If the download is still in progress, try to complete it. | 1215 // If the download is still in progress, try to complete it. |
1226 // | 1216 // |
1227 // Otherwise, download has been cancelled or interrupted before we've | 1217 // Otherwise, download has been cancelled or interrupted before we've |
1228 // received the DB handle. We post one final message to the history | 1218 // received the DB handle. We post one final message to the history |
1229 // service so that it can be properly in sync with the DownloadItem's | 1219 // service so that it can be properly in sync with the DownloadItem's |
1230 // completion status, and also inform any observers so that they get | 1220 // completion status, and also inform any observers so that they get |
1231 // more than just the start notification. | 1221 // more than just the start notification. |
1232 if (download->IsInProgress()) { | 1222 if (download->IsInProgress()) { |
1233 MaybeCompleteDownload(download); | 1223 MaybeCompleteDownload(download); |
1234 } else { | 1224 } else { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1288 DownloadItem* download = active_downloads_[download_id]; | 1278 DownloadItem* download = active_downloads_[download_id]; |
1289 DCHECK(download != NULL); | 1279 DCHECK(download != NULL); |
1290 return download; | 1280 return download; |
1291 } | 1281 } |
1292 | 1282 |
1293 // Confirm that everything in all maps is also in |downloads_|, and that | 1283 // Confirm that everything in all maps is also in |downloads_|, and that |
1294 // everything in |downloads_| is also in some other map. | 1284 // everything in |downloads_| is also in some other map. |
1295 void DownloadManager::AssertContainersConsistent() const { | 1285 void DownloadManager::AssertContainersConsistent() const { |
1296 #if !defined(NDEBUG) | 1286 #if !defined(NDEBUG) |
1297 // Turn everything into sets. | 1287 // Turn everything into sets. |
1298 DownloadSet active_set, history_set; | 1288 const DownloadMap* input_maps[] = {&active_downloads_, |
1299 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; | 1289 &history_downloads_, |
1300 DownloadSet* local_sets[] = {&active_set, &history_set}; | 1290 &save_page_downloads_}; |
1301 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); | 1291 DownloadSet active_set, history_set, save_page_set; |
1292 DownloadSet* all_sets[] = {&active_set, &history_set, &save_page_set}; | |
1293 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(all_sets)); | |
1302 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { | 1294 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { |
1303 for (DownloadMap::const_iterator it = input_maps[i]->begin(); | 1295 for (DownloadMap::const_iterator it = input_maps[i]->begin(); |
1304 it != input_maps[i]->end(); it++) { | 1296 it != input_maps[i]->end(); ++it) { |
1305 local_sets[i]->insert(&*it->second); | 1297 all_sets[i]->insert(&*it->second); |
1306 } | 1298 } |
1307 } | 1299 } |
1308 | 1300 |
1309 // Check if each set is fully present in downloads, and create a union. | 1301 // Check if each set is fully present in downloads, and create a union. |
1310 const DownloadSet* all_sets[] = {&active_set, &history_set, | |
1311 &save_page_as_downloads_}; | |
1312 DownloadSet downloads_union; | 1302 DownloadSet downloads_union; |
1313 for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) { | 1303 for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) { |
1314 DownloadSet remainder; | 1304 DownloadSet remainder; |
1315 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); | 1305 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); |
1316 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), | 1306 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), |
1317 downloads_.begin(), downloads_.end(), | 1307 downloads_.begin(), downloads_.end(), |
1318 insert_it); | 1308 insert_it); |
1319 DCHECK(remainder.empty()); | 1309 DCHECK(remainder.empty()); |
1320 std::insert_iterator<DownloadSet> | 1310 std::insert_iterator<DownloadSet> |
1321 insert_union(downloads_union, downloads_union.end()); | 1311 insert_union(downloads_union, downloads_union.end()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1356 observed_download_manager_->RemoveObserver(this); | 1346 observed_download_manager_->RemoveObserver(this); |
1357 } | 1347 } |
1358 | 1348 |
1359 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1349 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
1360 observing_download_manager_->NotifyModelChanged(); | 1350 observing_download_manager_->NotifyModelChanged(); |
1361 } | 1351 } |
1362 | 1352 |
1363 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1353 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
1364 observed_download_manager_ = NULL; | 1354 observed_download_manager_ = NULL; |
1365 } | 1355 } |
1356 | |
1357 void DownloadManager::SavePageDownloadStarted(DownloadItem* download) { | |
1358 DCHECK(!ContainsKey(save_page_downloads_, download->id())); | |
1359 downloads_.insert(download); | |
1360 save_page_downloads_[download->id()] = download; | |
1361 | |
1362 // Add this entry to the history service. | |
1363 // Additionally, the UI is notified in the callback. | |
1364 download_history_->AddEntry(download, | |
1365 NewCallback(this, &DownloadManager::OnSavePageDownloadEntryAdded)); | |
1366 } | |
1367 | |
1368 void DownloadManager::OnSavePageDownloadEntryAdded(int32 download_id, | |
1369 int64 db_handle) { | |
1370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1371 | |
1372 DownloadMap::const_iterator it = save_page_downloads_.find(download_id); | |
1373 // This can happen if SavePageDownloadFinished happens before the history | |
1374 // callback. In that case, the download is stuck in pending downloads | |
1375 // state and never finishes. This will be fixed with the integration of | |
1376 // SavePackage into DownloadManager. | |
Randy Smith (Not in Mondays)
2011/07/25 18:59:31
This comment is no longer correct and should be up
achuithb
2011/07/27 01:04:57
I updated the comment. This can now only happen if
| |
1377 if (it == save_page_downloads_.end()) | |
1378 return; | |
1379 | |
1380 DownloadItem* download = it->second; | |
1381 DCHECK(download); | |
1382 if (!download) | |
1383 return; | |
1384 | |
1385 AddDownloadItemToHistory(download, db_handle); | |
1386 | |
1387 // Finalize this download if it terminated before the history callback. | |
1388 if (!download->IsInProgress()) | |
1389 SavePageDownloadFinished(download); | |
1390 } | |
1391 | |
1392 void DownloadManager::SavePageDownloadFinished(DownloadItem* download) { | |
1393 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { | |
1394 download_history_->UpdateEntry(download); | |
1395 DCHECK(ContainsKey(save_page_downloads_, download->id())); | |
1396 save_page_downloads_.erase(download->id()); | |
1397 } | |
1398 } | |
1399 | |
1400 int32 DownloadManager::GetNextSavePageId() { | |
1401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1402 return next_save_page_id_++; | |
1403 } | |
1404 | |
OLD | NEW |