Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: chrome/browser/download/download_manager.cc

Issue 7277073: Support for adding save page download items into downloads history. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 24 matching lines...) Expand all
35 #include "chrome/browser/ui/browser.h" 35 #include "chrome/browser/ui/browser.h"
36 #include "chrome/browser/ui/browser_list.h" 36 #include "chrome/browser/ui/browser_list.h"
37 #include "chrome/common/chrome_paths.h" 37 #include "chrome/common/chrome_paths.h"
38 #include "chrome/common/pref_names.h" 38 #include "chrome/common/pref_names.h"
39 #include "content/browser/browser_thread.h" 39 #include "content/browser/browser_thread.h"
40 #include "content/browser/renderer_host/render_process_host.h" 40 #include "content/browser/renderer_host/render_process_host.h"
41 #include "content/browser/renderer_host/render_view_host.h" 41 #include "content/browser/renderer_host/render_view_host.h"
42 #include "content/browser/renderer_host/resource_dispatcher_host.h" 42 #include "content/browser/renderer_host/resource_dispatcher_host.h"
43 #include "content/browser/tab_contents/tab_contents.h" 43 #include "content/browser/tab_contents/tab_contents.h"
44 #include "content/common/content_notification_types.h" 44 #include "content/common/content_notification_types.h"
45 #include "content/common/notification_service.h"
45 #include "googleurl/src/gurl.h" 46 #include "googleurl/src/gurl.h"
46 #include "grit/generated_resources.h" 47 #include "grit/generated_resources.h"
47 #include "grit/theme_resources.h" 48 #include "grit/theme_resources.h"
48 #include "net/base/mime_util.h" 49 #include "net/base/mime_util.h"
49 #include "net/base/net_util.h" 50 #include "net/base/net_util.h"
50 #include "ui/base/l10n/l10n_util.h" 51 #include "ui/base/l10n/l10n_util.h"
51 #include "ui/base/resource/resource_bundle.h" 52 #include "ui/base/resource/resource_bundle.h"
52 53
53 DownloadManager::DownloadManager(DownloadStatusUpdater* status_updater) 54 DownloadManager::DownloadManager(DownloadStatusUpdater* status_updater)
54 : shutdown_needed_(false), 55 : shutdown_needed_(false),
55 profile_(NULL), 56 profile_(NULL),
56 file_manager_(NULL), 57 file_manager_(NULL),
57 status_updater_(status_updater->AsWeakPtr()) { 58 status_updater_(status_updater->AsWeakPtr()),
59 next_save_page_id_(0) {
58 if (status_updater_) 60 if (status_updater_)
59 status_updater_->AddDelegate(this); 61 status_updater_->AddDelegate(this);
60 } 62 }
61 63
62 DownloadManager::~DownloadManager() { 64 DownloadManager::~DownloadManager() {
63 DCHECK(!shutdown_needed_); 65 DCHECK(!shutdown_needed_);
64 if (status_updater_) 66 if (status_updater_)
65 status_updater_->RemoveDelegate(this); 67 status_updater_->RemoveDelegate(this);
66 } 68 }
67 69
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 // anything left. 117 // anything left.
116 118
117 // Copy downloads_ to separate container so as not to set off checks 119 // Copy downloads_ to separate container so as not to set off checks
118 // in DownloadItem destruction. 120 // in DownloadItem destruction.
119 DownloadSet downloads_to_delete; 121 DownloadSet downloads_to_delete;
120 downloads_to_delete.swap(downloads_); 122 downloads_to_delete.swap(downloads_);
121 123
122 in_progress_.clear(); 124 in_progress_.clear();
123 active_downloads_.clear(); 125 active_downloads_.clear();
124 history_downloads_.clear(); 126 history_downloads_.clear();
125 #if !defined(NDEBUG)
126 save_page_as_downloads_.clear();
127 #endif
128 STLDeleteElements(&downloads_to_delete); 127 STLDeleteElements(&downloads_to_delete);
129 128
129 DCHECK(save_page_downloads_.empty());
130
130 file_manager_ = NULL; 131 file_manager_ = NULL;
131 132
132 // Make sure the save as dialog doesn't notify us back if we're gone before 133 // Make sure the save as dialog doesn't notify us back if we're gone before
133 // it returns. 134 // it returns.
134 if (select_file_dialog_.get()) 135 if (select_file_dialog_.get())
135 select_file_dialog_->ListenerDestroyed(); 136 select_file_dialog_->ListenerDestroyed();
136 137
137 download_history_.reset(); 138 download_history_.reset();
138 download_prefs_.reset(); 139 download_prefs_.reset();
139 140
140 shutdown_needed_ = false; 141 shutdown_needed_ = false;
141 } 142 }
142 143
143 void DownloadManager::GetTemporaryDownloads( 144 void DownloadManager::GetTemporaryDownloads(
144 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 145 const FilePath& dir_path, DownloadVector* result) {
145 DCHECK(result); 146 DCHECK(result);
146 147
147 for (DownloadMap::iterator it = history_downloads_.begin(); 148 for (DownloadMap::iterator it = history_downloads_.begin();
148 it != history_downloads_.end(); ++it) { 149 it != history_downloads_.end(); ++it) {
149 if (it->second->is_temporary() && 150 if (it->second->is_temporary() &&
150 it->second->full_path().DirName() == dir_path) 151 it->second->full_path().DirName() == dir_path)
151 result->push_back(it->second); 152 result->push_back(it->second);
152 } 153 }
153 } 154 }
154 155
155 void DownloadManager::GetAllDownloads( 156 void DownloadManager::GetAllDownloads(
156 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 157 const FilePath& dir_path, DownloadVector* result) {
157 DCHECK(result); 158 DCHECK(result);
158 159
159 for (DownloadMap::iterator it = history_downloads_.begin(); 160 for (DownloadMap::iterator it = history_downloads_.begin();
160 it != history_downloads_.end(); ++it) { 161 it != history_downloads_.end(); ++it) {
161 if (!it->second->is_temporary() && 162 if (!it->second->is_temporary() &&
162 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) 163 (dir_path.empty() || it->second->full_path().DirName() == dir_path))
163 result->push_back(it->second); 164 result->push_back(it->second);
164 } 165 }
165 } 166 }
166 167
167 void DownloadManager::GetCurrentDownloads( 168 void DownloadManager::GetCurrentDownloads(
168 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 169 const FilePath& dir_path, DownloadVector* result) {
169 DCHECK(result); 170 DCHECK(result);
170 171
171 for (DownloadMap::iterator it = history_downloads_.begin(); 172 for (DownloadMap::iterator it = history_downloads_.begin();
172 it != history_downloads_.end(); ++it) { 173 it != history_downloads_.end(); ++it) {
173 DownloadItem* item =it->second; 174 DownloadItem* item =it->second;
174 // Skip temporary items. 175 // Skip temporary items.
175 if (item->is_temporary()) 176 if (item->is_temporary())
176 continue; 177 continue;
177 // Skip items that have all their data, and are OK to save. 178 // Skip items that have all their data, and are OK to save.
178 if (!item->IsPartialDownload() && 179 if (!item->IsPartialDownload() &&
179 (item->safety_state() != DownloadItem::DANGEROUS)) 180 (item->safety_state() != DownloadItem::DANGEROUS))
180 continue; 181 continue;
181 // Skip items that don't match |dir_path|. 182 // Skip items that don't match |dir_path|.
182 // If |dir_path| is empty, all remaining items match. 183 // If |dir_path| is empty, all remaining items match.
183 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path)) 184 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
184 continue; 185 continue;
185 186
186 result->push_back(item); 187 result->push_back(item);
187 } 188 }
188 189
189 // If we have a parent profile, let it add its downloads to the results. 190 // If we have a parent profile, let it add its downloads to the results.
190 Profile* original_profile = profile_->GetOriginalProfile(); 191 Profile* original_profile = profile_->GetOriginalProfile();
191 if (original_profile != profile_) 192 if (original_profile != profile_)
192 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path, 193 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
193 result); 194 result);
194 } 195 }
195 196
196 void DownloadManager::SearchDownloads(const string16& query, 197 void DownloadManager::SearchDownloads(const string16& query,
197 std::vector<DownloadItem*>* result) { 198 DownloadVector* result) {
198 DCHECK(result); 199 DCHECK(result);
199 200
200 string16 query_lower(base::i18n::ToLower(query)); 201 string16 query_lower(base::i18n::ToLower(query));
201 202
202 for (DownloadMap::iterator it = history_downloads_.begin(); 203 for (DownloadMap::iterator it = history_downloads_.begin();
203 it != history_downloads_.end(); ++it) { 204 it != history_downloads_.end(); ++it) {
204 DownloadItem* download_item = it->second; 205 DownloadItem* download_item = it->second;
205 206
206 if (download_item->is_temporary() || download_item->is_extension_install()) 207 if (download_item->is_temporary() || download_item->is_extension_install())
207 continue; 208 continue;
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 BrowserThread::FILE, FROM_HERE, 893 BrowserThread::FILE, FROM_HERE,
893 NewRunnableMethod( 894 NewRunnableMethod(
894 file_manager_, &DownloadFileManager::CancelDownload, download_id)); 895 file_manager_, &DownloadFileManager::CancelDownload, download_id));
895 } 896 }
896 897
897 void DownloadManager::UpdateAppIcon() { 898 void DownloadManager::UpdateAppIcon() {
898 if (status_updater_) 899 if (status_updater_)
899 status_updater_->Update(); 900 status_updater_->Update();
900 } 901 }
901 902
903 int DownloadManager::RemoveDownloadItems(const DownloadSet& pending_deletes) {
904 if (pending_deletes.empty())
905 return 0;
906
907 // Delete from internal maps.
908 for (DownloadSet::const_iterator it = pending_deletes.begin();
909 it != pending_deletes.end();
910 ++it) {
911 DownloadItem* download = *it;
912 DCHECK(download);
913 history_downloads_.erase(download->db_handle());
914 save_page_downloads_.erase(download->id());
915 downloads_.erase(download);
916 }
917
918 // Tell observers to refresh their views.
919 NotifyModelChanged();
920
921 // Delete the download items themselves.
922 const int num_deleted = static_cast<int>(pending_deletes.size());
923 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
924 return num_deleted;
925 }
926
902 void DownloadManager::RemoveDownload(int64 download_handle) { 927 void DownloadManager::RemoveDownload(int64 download_handle) {
903 DownloadMap::iterator it = history_downloads_.find(download_handle); 928 DownloadMap::iterator it = history_downloads_.find(download_handle);
904 if (it == history_downloads_.end()) 929 if (it == history_downloads_.end())
905 return; 930 return;
906 931
907 // Make history update. 932 // Make history update.
908 DownloadItem* download = it->second; 933 DownloadItem* download = it->second;
909 download_history_->RemoveEntry(download); 934 download_history_->RemoveEntry(download);
910 935
911 // Remove from our tables and delete. 936 // Remove from our tables and delete.
912 history_downloads_.erase(it); 937 DownloadSet pending_deletes;
913 int downloads_count = downloads_.erase(download); 938 pending_deletes.insert(download);
939 int downloads_count = RemoveDownloadItems(pending_deletes);
914 DCHECK_EQ(1, downloads_count); 940 DCHECK_EQ(1, downloads_count);
915
916 // Tell observers to refresh their views.
917 NotifyModelChanged();
918
919 delete download;
920 } 941 }
921 942
922 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, 943 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
923 const base::Time remove_end) { 944 const base::Time remove_end) {
924 download_history_->RemoveEntriesBetween(remove_begin, remove_end); 945 download_history_->RemoveEntriesBetween(remove_begin, remove_end);
925 946
926 // All downloads visible to the user will be in the history, 947 // All downloads visible to the user will be in the history,
927 // so scan that map. 948 // so scan that map.
928 DownloadMap::iterator it = history_downloads_.begin(); 949 DownloadSet pending_deletes;
929 std::vector<DownloadItem*> pending_deletes; 950 for (DownloadMap::iterator it = history_downloads_.begin();
930 while (it != history_downloads_.end()) { 951 it != history_downloads_.end();
952 ++it) {
931 DownloadItem* download = it->second; 953 DownloadItem* download = it->second;
932 if (download->start_time() >= remove_begin && 954 if (download->start_time() >= remove_begin &&
933 (remove_end.is_null() || download->start_time() < remove_end) && 955 (remove_end.is_null() || download->start_time() < remove_end) &&
934 (download->IsComplete() || 956 (download->IsComplete() ||
935 download->IsCancelled() || 957 download->IsCancelled() ||
936 download->IsInterrupted())) { 958 download->IsInterrupted())) {
937 AssertQueueStateConsistent(download); 959 AssertQueueStateConsistent(download);
938 960
939 // Remove from the map and move to the next in the list. 961 pending_deletes.insert(download);
940 history_downloads_.erase(it++);
941
942 // Also remove it from any completed dangerous downloads.
943 pending_deletes.push_back(download);
944
945 continue;
946 } 962 }
947
948 ++it;
949 } 963 }
950 964 return RemoveDownloadItems(pending_deletes);
951 // If we aren't deleting anything, we're done.
952 if (pending_deletes.empty())
953 return 0;
954
955 // Remove the chosen downloads from the main owning container.
956 for (std::vector<DownloadItem*>::iterator it = pending_deletes.begin();
957 it != pending_deletes.end(); it++) {
958 downloads_.erase(*it);
959 }
960
961 // Tell observers to refresh their views.
962 NotifyModelChanged();
963
964 // Delete the download items themselves.
965 int num_deleted = static_cast<int>(pending_deletes.size());
966
967 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
968 pending_deletes.clear();
969
970 return num_deleted;
971 } 965 }
972 966
973 int DownloadManager::RemoveDownloads(const base::Time remove_begin) { 967 int DownloadManager::RemoveDownloads(const base::Time remove_begin) {
974 return RemoveDownloadsBetween(remove_begin, base::Time()); 968 return RemoveDownloadsBetween(remove_begin, base::Time());
975 } 969 }
976 970
977 int DownloadManager::RemoveAllDownloads() { 971 int DownloadManager::RemoveAllDownloads() {
978 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) { 972 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) {
979 // This is an incognito downloader. Clear All should clear main download 973 // This is an incognito downloader. Clear All should clear main download
980 // manager as well. 974 // manager as well.
981 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads(); 975 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads();
982 } 976 }
983 // The null times make the date range unbounded. 977 // The null times make the date range unbounded.
984 return RemoveDownloadsBetween(base::Time(), base::Time()); 978 return RemoveDownloadsBetween(base::Time(), base::Time());
985 } 979 }
986 980
987 void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download) {
988 #if !defined(NDEBUG)
989 save_page_as_downloads_.insert(download);
990 #endif
991 downloads_.insert(download);
992 // Add to history and notify observers.
993 AddDownloadItemToHistory(download, DownloadHistory::kUninitializedHandle);
994 NotifyModelChanged();
995 }
996
997 // Initiate a download of a specific URL. We send the request to the 981 // Initiate a download of a specific URL. We send the request to the
998 // ResourceDispatcherHost, and let it send us responses like a regular 982 // ResourceDispatcherHost, and let it send us responses like a regular
999 // download. 983 // download.
1000 void DownloadManager::DownloadUrl(const GURL& url, 984 void DownloadManager::DownloadUrl(const GURL& url,
1001 const GURL& referrer, 985 const GURL& referrer,
1002 const std::string& referrer_charset, 986 const std::string& referrer_charset,
1003 TabContents* tab_contents) { 987 TabContents* tab_contents) {
1004 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), 988 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(),
1005 tab_contents); 989 tab_contents);
1006 } 990 }
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 1164
1181 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508 1165 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508
1182 // is fixed. 1166 // is fixed.
1183 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle); 1167 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle);
1184 1168
1185 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); 1169 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
1186 download->set_db_handle(db_handle); 1170 download->set_db_handle(db_handle);
1187 1171
1188 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); 1172 DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
1189 history_downloads_[download->db_handle()] = download; 1173 history_downloads_[download->db_handle()] = download;
1174
1175 // Show in the appropriate browser UI.
1176 // This includes buttons to save or cancel, for a dangerous download.
1177 ShowDownloadInBrowser(download);
1178
1179 // Inform interested objects about the new download.
1180 NotifyModelChanged();
1190 } 1181 }
1191 1182
1192 // Once the new DownloadItem's creation info has been committed to the history 1183 // Once the new DownloadItem's creation info has been committed to the history
1193 // service, we associate the DownloadItem with the db handle, update our 1184 // service, we associate the DownloadItem with the db handle, update our
1194 // 'history_downloads_' map and inform observers. 1185 // 'history_downloads_' map and inform observers.
1195 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, 1186 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
1196 int64 db_handle) { 1187 int64 db_handle) {
1197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1198 DownloadItem* download = GetActiveDownloadItem(download_id); 1189 DownloadItem* download = GetActiveDownloadItem(download_id);
1199 if (!download) 1190 if (!download)
1200 return; 1191 return;
1201 1192
1202 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 1193 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
1203 << " download_id = " << download_id 1194 << " download_id = " << download_id
1204 << " download = " << download->DebugString(true); 1195 << " download = " << download->DebugString(true);
1205 1196
1206 AddDownloadItemToHistory(download, db_handle); 1197 AddDownloadItemToHistory(download, db_handle);
1207 1198
1208 // Show in the appropriate browser UI.
1209 // This includes buttons to save or cancel, for a dangerous download.
1210 ShowDownloadInBrowser(download);
1211
1212 // Inform interested objects about the new download.
1213 NotifyModelChanged();
1214
1215 // If the download is still in progress, try to complete it. 1199 // If the download is still in progress, try to complete it.
1216 // 1200 //
1217 // Otherwise, download has been cancelled or interrupted before we've 1201 // Otherwise, download has been cancelled or interrupted before we've
1218 // received the DB handle. We post one final message to the history 1202 // received the DB handle. We post one final message to the history
1219 // service so that it can be properly in sync with the DownloadItem's 1203 // service so that it can be properly in sync with the DownloadItem's
1220 // completion status, and also inform any observers so that they get 1204 // completion status, and also inform any observers so that they get
1221 // more than just the start notification. 1205 // more than just the start notification.
1222 if (download->IsInProgress()) { 1206 if (download->IsInProgress()) {
1223 MaybeCompleteDownload(download); 1207 MaybeCompleteDownload(download);
1224 } else { 1208 } else {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 DownloadItem* download = active_downloads_[download_id]; 1262 DownloadItem* download = active_downloads_[download_id];
1279 DCHECK(download != NULL); 1263 DCHECK(download != NULL);
1280 return download; 1264 return download;
1281 } 1265 }
1282 1266
1283 // Confirm that everything in all maps is also in |downloads_|, and that 1267 // Confirm that everything in all maps is also in |downloads_|, and that
1284 // everything in |downloads_| is also in some other map. 1268 // everything in |downloads_| is also in some other map.
1285 void DownloadManager::AssertContainersConsistent() const { 1269 void DownloadManager::AssertContainersConsistent() const {
1286 #if !defined(NDEBUG) 1270 #if !defined(NDEBUG)
1287 // Turn everything into sets. 1271 // Turn everything into sets.
1288 DownloadSet active_set, history_set; 1272 const DownloadMap* input_maps[] = {&active_downloads_,
1289 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; 1273 &history_downloads_,
1290 DownloadSet* local_sets[] = {&active_set, &history_set}; 1274 &save_page_downloads_};
1291 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); 1275 DownloadSet active_set, history_set, save_page_set;
1276 DownloadSet* all_sets[] = {&active_set, &history_set, &save_page_set};
1277 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(all_sets));
1292 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { 1278 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
1293 for (DownloadMap::const_iterator it = input_maps[i]->begin(); 1279 for (DownloadMap::const_iterator it = input_maps[i]->begin();
1294 it != input_maps[i]->end(); it++) { 1280 it != input_maps[i]->end(); ++it) {
1295 local_sets[i]->insert(&*it->second); 1281 all_sets[i]->insert(&*it->second);
1296 } 1282 }
1297 } 1283 }
1298 1284
1299 // Check if each set is fully present in downloads, and create a union. 1285 // Check if each set is fully present in downloads, and create a union.
1300 const DownloadSet* all_sets[] = {&active_set, &history_set,
1301 &save_page_as_downloads_};
1302 DownloadSet downloads_union; 1286 DownloadSet downloads_union;
1303 for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) { 1287 for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) {
1304 DownloadSet remainder; 1288 DownloadSet remainder;
1305 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); 1289 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
1306 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), 1290 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
1307 downloads_.begin(), downloads_.end(), 1291 downloads_.begin(), downloads_.end(),
1308 insert_it); 1292 insert_it);
1309 DCHECK(remainder.empty()); 1293 DCHECK(remainder.empty());
1310 std::insert_iterator<DownloadSet> 1294 std::insert_iterator<DownloadSet>
1311 insert_union(downloads_union, downloads_union.end()); 1295 insert_union(downloads_union, downloads_union.end());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 observed_download_manager_->RemoveObserver(this); 1330 observed_download_manager_->RemoveObserver(this);
1347 } 1331 }
1348 1332
1349 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { 1333 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() {
1350 observing_download_manager_->NotifyModelChanged(); 1334 observing_download_manager_->NotifyModelChanged();
1351 } 1335 }
1352 1336
1353 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { 1337 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() {
1354 observed_download_manager_ = NULL; 1338 observed_download_manager_ = NULL;
1355 } 1339 }
1340
1341 void DownloadManager::SavePageDownloadStarted(DownloadItem* download) {
1342 DCHECK(!ContainsKey(save_page_downloads_, download->id()));
1343 downloads_.insert(download);
1344 save_page_downloads_[download->id()] = download;
1345
1346 // Add this entry to the history service.
1347 // Additionally, the UI is notified in the callback.
1348 download_history_->AddEntry(download,
1349 NewCallback(this, &DownloadManager::OnSavePageDownloadEntryAdded));
1350 }
1351
1352 // SavePackage will call SavePageDownloadFinished upon completion/cancellation.
1353 // The history callback will call OnSavePageDownloadEntryAdded.
1354 // If the download finishes before the history callback,
1355 // OnSavePageDownloadEntryAdded calls SavePageDownloadFinished, ensuring that
1356 // the history event is update regardless of the order in which these two events
1357 // complete.
1358 // If something removes the download item from the download manager (Remove,
1359 // Shutdown) the result will be that the SavePage system will not be able to
1360 // properly update the download item (which no longer exists) or the download
1361 // history, but the action will complete properly anyway. This may lead to the
1362 // history entry being wrong on a reload of chrome (specifically in the case of
1363 // Initiation -> History Callback -> Removal -> Completion), but there's no way
1364 // to solve that without canceling on Remove (which would then update the DB).
1365
1366 void DownloadManager::OnSavePageDownloadEntryAdded(int32 download_id,
1367 int64 db_handle) {
1368 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1369
1370 DownloadMap::const_iterator it = save_page_downloads_.find(download_id);
1371 // This can happen if the download manager is shutting down and all maps
1372 // have been cleared.
1373 if (it == save_page_downloads_.end())
1374 return;
1375
1376 DownloadItem* download = it->second;
1377 if (!download) {
1378 NOTREACHED();
1379 return;
1380 }
1381
1382 AddDownloadItemToHistory(download, db_handle);
1383
1384 // Finalize this download if it finished before the history callback.
1385 if (!download->IsInProgress())
1386 SavePageDownloadFinished(download);
1387 }
1388
1389 void DownloadManager::SavePageDownloadFinished(DownloadItem* download) {
1390 if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
1391 download_history_->UpdateEntry(download);
1392 DCHECK(ContainsKey(save_page_downloads_, download->id()));
1393 save_page_downloads_.erase(download->id());
1394
1395 if (download->IsComplete())
1396 NotificationService::current()->Notify(
1397 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1398 Source<DownloadManager>(this),
1399 Details<DownloadItem>(download));
1400 }
1401 }
1402
1403 int32 DownloadManager::GetNextSavePageId() {
1404 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1405 return next_save_page_id_++;
1406 }
1407
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698