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

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 22 matching lines...) Expand all
33 #include "chrome/browser/tab_contents/tab_util.h" 33 #include "chrome/browser/tab_contents/tab_util.h"
34 #include "chrome/common/chrome_paths.h" 34 #include "chrome/common/chrome_paths.h"
35 #include "chrome/common/pref_names.h" 35 #include "chrome/common/pref_names.h"
36 #include "content/browser/browser_thread.h" 36 #include "content/browser/browser_thread.h"
37 #include "content/browser/content_browser_client.h" 37 #include "content/browser/content_browser_client.h"
38 #include "content/browser/renderer_host/render_process_host.h" 38 #include "content/browser/renderer_host/render_process_host.h"
39 #include "content/browser/renderer_host/render_view_host.h" 39 #include "content/browser/renderer_host/render_view_host.h"
40 #include "content/browser/renderer_host/resource_dispatcher_host.h" 40 #include "content/browser/renderer_host/resource_dispatcher_host.h"
41 #include "content/browser/tab_contents/tab_contents.h" 41 #include "content/browser/tab_contents/tab_contents.h"
42 #include "content/common/content_notification_types.h" 42 #include "content/common/content_notification_types.h"
43 #include "content/common/notification_service.h"
43 #include "googleurl/src/gurl.h" 44 #include "googleurl/src/gurl.h"
44 #include "grit/generated_resources.h" 45 #include "grit/generated_resources.h"
45 #include "grit/theme_resources.h" 46 #include "grit/theme_resources.h"
46 #include "net/base/mime_util.h" 47 #include "net/base/mime_util.h"
47 #include "net/base/net_util.h" 48 #include "net/base/net_util.h"
48 #include "ui/base/l10n/l10n_util.h" 49 #include "ui/base/l10n/l10n_util.h"
49 #include "ui/base/resource/resource_bundle.h" 50 #include "ui/base/resource/resource_bundle.h"
50 51
51 DownloadManager::DownloadManager(DownloadStatusUpdater* status_updater) 52 DownloadManager::DownloadManager(DownloadStatusUpdater* status_updater)
52 : shutdown_needed_(false), 53 : shutdown_needed_(false),
53 profile_(NULL), 54 profile_(NULL),
54 file_manager_(NULL), 55 file_manager_(NULL),
55 status_updater_(status_updater->AsWeakPtr()) { 56 status_updater_(status_updater->AsWeakPtr()),
57 next_save_page_id_(0) {
56 if (status_updater_) 58 if (status_updater_)
57 status_updater_->AddDelegate(this); 59 status_updater_->AddDelegate(this);
58 } 60 }
59 61
60 DownloadManager::~DownloadManager() { 62 DownloadManager::~DownloadManager() {
61 DCHECK(!shutdown_needed_); 63 DCHECK(!shutdown_needed_);
62 if (status_updater_) 64 if (status_updater_)
63 status_updater_->RemoveDelegate(this); 65 status_updater_->RemoveDelegate(this);
64 } 66 }
65 67
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 // anything left. 115 // anything left.
114 116
115 // Copy downloads_ to separate container so as not to set off checks 117 // Copy downloads_ to separate container so as not to set off checks
116 // in DownloadItem destruction. 118 // in DownloadItem destruction.
117 DownloadSet downloads_to_delete; 119 DownloadSet downloads_to_delete;
118 downloads_to_delete.swap(downloads_); 120 downloads_to_delete.swap(downloads_);
119 121
120 in_progress_.clear(); 122 in_progress_.clear();
121 active_downloads_.clear(); 123 active_downloads_.clear();
122 history_downloads_.clear(); 124 history_downloads_.clear();
123 #if !defined(NDEBUG)
124 save_page_as_downloads_.clear();
125 #endif
126 STLDeleteElements(&downloads_to_delete); 125 STLDeleteElements(&downloads_to_delete);
127 126
127 DCHECK(save_page_downloads_.empty());
128
128 file_manager_ = NULL; 129 file_manager_ = NULL;
129 130
130 download_history_.reset(); 131 download_history_.reset();
131 download_prefs_.reset(); 132 download_prefs_.reset();
132 133
133 shutdown_needed_ = false; 134 shutdown_needed_ = false;
134 } 135 }
135 136
136 void DownloadManager::GetTemporaryDownloads( 137 void DownloadManager::GetTemporaryDownloads(
137 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 138 const FilePath& dir_path, DownloadVector* result) {
138 DCHECK(result); 139 DCHECK(result);
139 140
140 for (DownloadMap::iterator it = history_downloads_.begin(); 141 for (DownloadMap::iterator it = history_downloads_.begin();
141 it != history_downloads_.end(); ++it) { 142 it != history_downloads_.end(); ++it) {
142 if (it->second->is_temporary() && 143 if (it->second->is_temporary() &&
143 it->second->full_path().DirName() == dir_path) 144 it->second->full_path().DirName() == dir_path)
144 result->push_back(it->second); 145 result->push_back(it->second);
145 } 146 }
146 } 147 }
147 148
148 void DownloadManager::GetAllDownloads( 149 void DownloadManager::GetAllDownloads(
149 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 150 const FilePath& dir_path, DownloadVector* result) {
150 DCHECK(result); 151 DCHECK(result);
151 152
152 for (DownloadMap::iterator it = history_downloads_.begin(); 153 for (DownloadMap::iterator it = history_downloads_.begin();
153 it != history_downloads_.end(); ++it) { 154 it != history_downloads_.end(); ++it) {
154 if (!it->second->is_temporary() && 155 if (!it->second->is_temporary() &&
155 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) 156 (dir_path.empty() || it->second->full_path().DirName() == dir_path))
156 result->push_back(it->second); 157 result->push_back(it->second);
157 } 158 }
158 } 159 }
159 160
160 void DownloadManager::GetCurrentDownloads( 161 void DownloadManager::GetCurrentDownloads(
161 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 162 const FilePath& dir_path, DownloadVector* result) {
162 DCHECK(result); 163 DCHECK(result);
163 164
164 for (DownloadMap::iterator it = history_downloads_.begin(); 165 for (DownloadMap::iterator it = history_downloads_.begin();
165 it != history_downloads_.end(); ++it) { 166 it != history_downloads_.end(); ++it) {
166 DownloadItem* item =it->second; 167 DownloadItem* item =it->second;
167 // Skip temporary items. 168 // Skip temporary items.
168 if (item->is_temporary()) 169 if (item->is_temporary())
169 continue; 170 continue;
170 // Skip items that have all their data, and are OK to save. 171 // Skip items that have all their data, and are OK to save.
171 if (!item->IsPartialDownload() && 172 if (!item->IsPartialDownload() &&
172 (item->safety_state() != DownloadItem::DANGEROUS)) 173 (item->safety_state() != DownloadItem::DANGEROUS))
173 continue; 174 continue;
174 // Skip items that don't match |dir_path|. 175 // Skip items that don't match |dir_path|.
175 // If |dir_path| is empty, all remaining items match. 176 // If |dir_path| is empty, all remaining items match.
176 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path)) 177 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
177 continue; 178 continue;
178 179
179 result->push_back(item); 180 result->push_back(item);
180 } 181 }
181 182
182 // If we have a parent profile, let it add its downloads to the results. 183 // If we have a parent profile, let it add its downloads to the results.
183 Profile* original_profile = profile_->GetOriginalProfile(); 184 Profile* original_profile = profile_->GetOriginalProfile();
184 if (original_profile != profile_) 185 if (original_profile != profile_)
185 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path, 186 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
186 result); 187 result);
187 } 188 }
188 189
189 void DownloadManager::SearchDownloads(const string16& query, 190 void DownloadManager::SearchDownloads(const string16& query,
190 std::vector<DownloadItem*>* result) { 191 DownloadVector* result) {
191 DCHECK(result); 192 DCHECK(result);
192 193
193 string16 query_lower(base::i18n::ToLower(query)); 194 string16 query_lower(base::i18n::ToLower(query));
194 195
195 for (DownloadMap::iterator it = history_downloads_.begin(); 196 for (DownloadMap::iterator it = history_downloads_.begin();
196 it != history_downloads_.end(); ++it) { 197 it != history_downloads_.end(); ++it) {
197 DownloadItem* download_item = it->second; 198 DownloadItem* download_item = it->second;
198 199
199 if (download_item->is_temporary() || download_item->is_extension_install()) 200 if (download_item->is_temporary() || download_item->is_extension_install())
200 continue; 201 continue;
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 BrowserThread::FILE, FROM_HERE, 869 BrowserThread::FILE, FROM_HERE,
869 NewRunnableMethod( 870 NewRunnableMethod(
870 file_manager_, &DownloadFileManager::CancelDownload, download_id)); 871 file_manager_, &DownloadFileManager::CancelDownload, download_id));
871 } 872 }
872 873
873 void DownloadManager::UpdateAppIcon() { 874 void DownloadManager::UpdateAppIcon() {
874 if (status_updater_) 875 if (status_updater_)
875 status_updater_->Update(); 876 status_updater_->Update();
876 } 877 }
877 878
879 int DownloadManager::RemoveDownloadItems(
880 const DownloadVector& pending_deletes) {
881 if (pending_deletes.empty())
882 return 0;
883
884 // Delete from internal maps.
885 for (DownloadVector::const_iterator it = pending_deletes.begin();
886 it != pending_deletes.end();
887 ++it) {
888 DownloadItem* download = *it;
889 DCHECK(download);
890 history_downloads_.erase(download->db_handle());
891 save_page_downloads_.erase(download->id());
892 downloads_.erase(download);
893 }
894
895 // Tell observers to refresh their views.
896 NotifyModelChanged();
897
898 // Delete the download items themselves.
899 const int num_deleted = static_cast<int>(pending_deletes.size());
900 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
901 return num_deleted;
902 }
903
878 void DownloadManager::RemoveDownload(int64 download_handle) { 904 void DownloadManager::RemoveDownload(int64 download_handle) {
879 DownloadMap::iterator it = history_downloads_.find(download_handle); 905 DownloadMap::iterator it = history_downloads_.find(download_handle);
880 if (it == history_downloads_.end()) 906 if (it == history_downloads_.end())
881 return; 907 return;
882 908
883 // Make history update. 909 // Make history update.
884 DownloadItem* download = it->second; 910 DownloadItem* download = it->second;
885 download_history_->RemoveEntry(download); 911 download_history_->RemoveEntry(download);
886 912
887 // Remove from our tables and delete. 913 // Remove from our tables and delete.
888 history_downloads_.erase(it); 914 int downloads_count = RemoveDownloadItems(DownloadVector(1, download));
889 int downloads_count = downloads_.erase(download);
890 DCHECK_EQ(1, downloads_count); 915 DCHECK_EQ(1, downloads_count);
891
892 // Tell observers to refresh their views.
893 NotifyModelChanged();
894
895 delete download;
896 } 916 }
897 917
898 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, 918 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
899 const base::Time remove_end) { 919 const base::Time remove_end) {
900 download_history_->RemoveEntriesBetween(remove_begin, remove_end); 920 download_history_->RemoveEntriesBetween(remove_begin, remove_end);
901 921
902 // All downloads visible to the user will be in the history, 922 // All downloads visible to the user will be in the history,
903 // so scan that map. 923 // so scan that map.
904 DownloadMap::iterator it = history_downloads_.begin(); 924 DownloadVector pending_deletes;
905 std::vector<DownloadItem*> pending_deletes; 925 for (DownloadMap::const_iterator it = history_downloads_.begin();
906 while (it != history_downloads_.end()) { 926 it != history_downloads_.end();
927 ++it) {
907 DownloadItem* download = it->second; 928 DownloadItem* download = it->second;
908 if (download->start_time() >= remove_begin && 929 if (download->start_time() >= remove_begin &&
909 (remove_end.is_null() || download->start_time() < remove_end) && 930 (remove_end.is_null() || download->start_time() < remove_end) &&
910 (download->IsComplete() || 931 (download->IsComplete() || download->IsCancelled())) {
911 download->IsCancelled() ||
912 download->IsInterrupted())) {
913 AssertQueueStateConsistent(download); 932 AssertQueueStateConsistent(download);
914
915 // Remove from the map and move to the next in the list.
916 history_downloads_.erase(it++);
917
918 // Also remove it from any completed dangerous downloads.
919 pending_deletes.push_back(download); 933 pending_deletes.push_back(download);
920
921 continue;
922 } 934 }
923
924 ++it;
925 } 935 }
926 936 return RemoveDownloadItems(pending_deletes);
927 // If we aren't deleting anything, we're done.
928 if (pending_deletes.empty())
929 return 0;
930
931 // Remove the chosen downloads from the main owning container.
932 for (std::vector<DownloadItem*>::iterator it = pending_deletes.begin();
933 it != pending_deletes.end(); it++) {
934 downloads_.erase(*it);
935 }
936
937 // Tell observers to refresh their views.
938 NotifyModelChanged();
939
940 // Delete the download items themselves.
941 int num_deleted = static_cast<int>(pending_deletes.size());
942
943 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
944 pending_deletes.clear();
945
946 return num_deleted;
947 } 937 }
948 938
949 int DownloadManager::RemoveDownloads(const base::Time remove_begin) { 939 int DownloadManager::RemoveDownloads(const base::Time remove_begin) {
950 return RemoveDownloadsBetween(remove_begin, base::Time()); 940 return RemoveDownloadsBetween(remove_begin, base::Time());
951 } 941 }
952 942
953 int DownloadManager::RemoveAllDownloads() { 943 int DownloadManager::RemoveAllDownloads() {
954 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) { 944 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) {
955 // This is an incognito downloader. Clear All should clear main download 945 // This is an incognito downloader. Clear All should clear main download
956 // manager as well. 946 // manager as well.
957 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads(); 947 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads();
958 } 948 }
959 // The null times make the date range unbounded. 949 // The null times make the date range unbounded.
960 return RemoveDownloadsBetween(base::Time(), base::Time()); 950 return RemoveDownloadsBetween(base::Time(), base::Time());
961 } 951 }
962 952
963 void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download) {
964 #if !defined(NDEBUG)
965 save_page_as_downloads_.insert(download);
966 #endif
967 downloads_.insert(download);
968 // Add to history and notify observers.
969 AddDownloadItemToHistory(download, DownloadHistory::kUninitializedHandle);
970 NotifyModelChanged();
971 }
972
973 // Initiate a download of a specific URL. We send the request to the 953 // Initiate a download of a specific URL. We send the request to the
974 // ResourceDispatcherHost, and let it send us responses like a regular 954 // ResourceDispatcherHost, and let it send us responses like a regular
975 // download. 955 // download.
976 void DownloadManager::DownloadUrl(const GURL& url, 956 void DownloadManager::DownloadUrl(const GURL& url,
977 const GURL& referrer, 957 const GURL& referrer,
978 const std::string& referrer_charset, 958 const std::string& referrer_charset,
979 TabContents* tab_contents) { 959 TabContents* tab_contents) {
980 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), 960 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(),
981 tab_contents); 961 tab_contents);
982 } 962 }
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 1136
1157 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508 1137 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508
1158 // is fixed. 1138 // is fixed.
1159 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle); 1139 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle);
1160 1140
1161 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); 1141 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
1162 download->set_db_handle(db_handle); 1142 download->set_db_handle(db_handle);
1163 1143
1164 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); 1144 DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
1165 history_downloads_[download->db_handle()] = download; 1145 history_downloads_[download->db_handle()] = download;
1146
1147 // Show in the appropriate browser UI.
1148 // This includes buttons to save or cancel, for a dangerous download.
1149 ShowDownloadInBrowser(download);
1150
1151 // Inform interested objects about the new download.
1152 NotifyModelChanged();
1166 } 1153 }
1167 1154
1168 // Once the new DownloadItem's creation info has been committed to the history 1155 // Once the new DownloadItem's creation info has been committed to the history
1169 // service, we associate the DownloadItem with the db handle, update our 1156 // service, we associate the DownloadItem with the db handle, update our
1170 // 'history_downloads_' map and inform observers. 1157 // 'history_downloads_' map and inform observers.
1171 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, 1158 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
1172 int64 db_handle) { 1159 int64 db_handle) {
1173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1174 DownloadItem* download = GetActiveDownloadItem(download_id); 1161 DownloadItem* download = GetActiveDownloadItem(download_id);
1175 if (!download) 1162 if (!download)
1176 return; 1163 return;
1177 1164
1178 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 1165 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
1179 << " download_id = " << download_id 1166 << " download_id = " << download_id
1180 << " download = " << download->DebugString(true); 1167 << " download = " << download->DebugString(true);
1181 1168
1182 AddDownloadItemToHistory(download, db_handle); 1169 AddDownloadItemToHistory(download, db_handle);
1183 1170
1184 // Show in the appropriate browser UI.
1185 // This includes buttons to save or cancel, for a dangerous download.
1186 ShowDownloadInBrowser(download);
1187
1188 // Inform interested objects about the new download.
1189 NotifyModelChanged();
1190
1191 // If the download is still in progress, try to complete it. 1171 // If the download is still in progress, try to complete it.
1192 // 1172 //
1193 // Otherwise, download has been cancelled or interrupted before we've 1173 // Otherwise, download has been cancelled or interrupted before we've
1194 // received the DB handle. We post one final message to the history 1174 // received the DB handle. We post one final message to the history
1195 // service so that it can be properly in sync with the DownloadItem's 1175 // service so that it can be properly in sync with the DownloadItem's
1196 // completion status, and also inform any observers so that they get 1176 // completion status, and also inform any observers so that they get
1197 // more than just the start notification. 1177 // more than just the start notification.
1198 if (download->IsInProgress()) { 1178 if (download->IsInProgress()) {
1199 MaybeCompleteDownload(download); 1179 MaybeCompleteDownload(download);
1200 } else { 1180 } else {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 DownloadItem* download = active_downloads_[download_id]; 1230 DownloadItem* download = active_downloads_[download_id];
1251 DCHECK(download != NULL); 1231 DCHECK(download != NULL);
1252 return download; 1232 return download;
1253 } 1233 }
1254 1234
1255 // Confirm that everything in all maps is also in |downloads_|, and that 1235 // Confirm that everything in all maps is also in |downloads_|, and that
1256 // everything in |downloads_| is also in some other map. 1236 // everything in |downloads_| is also in some other map.
1257 void DownloadManager::AssertContainersConsistent() const { 1237 void DownloadManager::AssertContainersConsistent() const {
1258 #if !defined(NDEBUG) 1238 #if !defined(NDEBUG)
1259 // Turn everything into sets. 1239 // Turn everything into sets.
1260 DownloadSet active_set, history_set; 1240 const DownloadMap* input_maps[] = {&active_downloads_,
1261 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; 1241 &history_downloads_,
1262 DownloadSet* local_sets[] = {&active_set, &history_set}; 1242 &save_page_downloads_};
1263 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); 1243 DownloadSet active_set, history_set, save_page_set;
1244 DownloadSet* all_sets[] = {&active_set, &history_set, &save_page_set};
1245 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(all_sets));
1264 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { 1246 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
1265 for (DownloadMap::const_iterator it = input_maps[i]->begin(); 1247 for (DownloadMap::const_iterator it = input_maps[i]->begin();
1266 it != input_maps[i]->end(); it++) { 1248 it != input_maps[i]->end(); ++it) {
1267 local_sets[i]->insert(&*it->second); 1249 all_sets[i]->insert(&*it->second);
1268 } 1250 }
1269 } 1251 }
1270 1252
1271 // Check if each set is fully present in downloads, and create a union. 1253 // Check if each set is fully present in downloads, and create a union.
1272 const DownloadSet* all_sets[] = {&active_set, &history_set,
1273 &save_page_as_downloads_};
1274 DownloadSet downloads_union; 1254 DownloadSet downloads_union;
1275 for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) { 1255 for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) {
1276 DownloadSet remainder; 1256 DownloadSet remainder;
1277 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin()); 1257 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
1278 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(), 1258 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
1279 downloads_.begin(), downloads_.end(), 1259 downloads_.begin(), downloads_.end(),
1280 insert_it); 1260 insert_it);
1281 DCHECK(remainder.empty()); 1261 DCHECK(remainder.empty());
1282 std::insert_iterator<DownloadSet> 1262 std::insert_iterator<DownloadSet>
1283 insert_union(downloads_union, downloads_union.end()); 1263 insert_union(downloads_union, downloads_union.end());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 observed_download_manager_->RemoveObserver(this); 1298 observed_download_manager_->RemoveObserver(this);
1319 } 1299 }
1320 1300
1321 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { 1301 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() {
1322 observing_download_manager_->NotifyModelChanged(); 1302 observing_download_manager_->NotifyModelChanged();
1323 } 1303 }
1324 1304
1325 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { 1305 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() {
1326 observed_download_manager_ = NULL; 1306 observed_download_manager_ = NULL;
1327 } 1307 }
1308
1309 void DownloadManager::SavePageDownloadStarted(DownloadItem* download) {
1310 DCHECK(!ContainsKey(save_page_downloads_, download->id()));
1311 downloads_.insert(download);
1312 save_page_downloads_[download->id()] = download;
1313
1314 // Add this entry to the history service.
1315 // Additionally, the UI is notified in the callback.
1316 download_history_->AddEntry(download,
1317 NewCallback(this, &DownloadManager::OnSavePageDownloadEntryAdded));
1318 }
1319
1320 // SavePackage will call SavePageDownloadFinished upon completion/cancellation.
1321 // The history callback will call OnSavePageDownloadEntryAdded.
1322 // If the download finishes before the history callback,
1323 // OnSavePageDownloadEntryAdded calls SavePageDownloadFinished, ensuring that
1324 // the history event is update regardless of the order in which these two events
1325 // complete.
1326 // If something removes the download item from the download manager (Remove,
1327 // Shutdown) the result will be that the SavePage system will not be able to
1328 // properly update the download item (which no longer exists) or the download
1329 // history, but the action will complete properly anyway. This may lead to the
1330 // history entry being wrong on a reload of chrome (specifically in the case of
1331 // Initiation -> History Callback -> Removal -> Completion), but there's no way
1332 // to solve that without canceling on Remove (which would then update the DB).
1333
1334 void DownloadManager::OnSavePageDownloadEntryAdded(int32 download_id,
1335 int64 db_handle) {
1336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1337
1338 DownloadMap::const_iterator it = save_page_downloads_.find(download_id);
1339 // This can happen if the download manager is shutting down and all maps
1340 // have been cleared.
1341 if (it == save_page_downloads_.end())
1342 return;
1343
1344 DownloadItem* download = it->second;
1345 if (!download) {
1346 NOTREACHED();
1347 return;
1348 }
1349
1350 AddDownloadItemToHistory(download, db_handle);
1351
1352 // Finalize this download if it finished before the history callback.
1353 if (!download->IsInProgress())
1354 SavePageDownloadFinished(download);
1355 }
1356
1357 void DownloadManager::SavePageDownloadFinished(DownloadItem* download) {
1358 if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
1359 download_history_->UpdateEntry(download);
1360 DCHECK(ContainsKey(save_page_downloads_, download->id()));
1361 save_page_downloads_.erase(download->id());
1362
1363 if (download->IsComplete())
1364 NotificationService::current()->Notify(
1365 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1366 Source<DownloadManager>(this),
1367 Details<DownloadItem>(download));
1368 }
1369 }
1370
1371 int32 DownloadManager::GetNextSavePageId() {
1372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1373 return next_save_page_id_++;
1374 }
1375
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698