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

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/profiles/profile.h" 33 #include "chrome/browser/profiles/profile.h"
34 #include "chrome/browser/tab_contents/tab_util.h" 34 #include "chrome/browser/tab_contents/tab_util.h"
35 #include "chrome/common/chrome_paths.h" 35 #include "chrome/common/chrome_paths.h"
36 #include "chrome/common/pref_names.h" 36 #include "chrome/common/pref_names.h"
37 #include "content/browser/browser_thread.h" 37 #include "content/browser/browser_thread.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(DownloadManagerDelegate* delegate, 52 DownloadManager::DownloadManager(DownloadManagerDelegate* delegate,
52 DownloadStatusUpdater* status_updater) 53 DownloadStatusUpdater* status_updater)
53 : shutdown_needed_(false), 54 : shutdown_needed_(false),
54 profile_(NULL), 55 profile_(NULL),
55 file_manager_(NULL), 56 file_manager_(NULL),
56 status_updater_(status_updater->AsWeakPtr()), 57 status_updater_(status_updater->AsWeakPtr()),
58 next_save_page_id_(0),
57 delegate_(delegate) { 59 delegate_(delegate) {
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 }
(...skipping 48 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 download_history_.reset(); 133 download_history_.reset();
133 download_prefs_.reset(); 134 download_prefs_.reset();
134 135
135 shutdown_needed_ = false; 136 shutdown_needed_ = false;
136 } 137 }
137 138
138 void DownloadManager::GetTemporaryDownloads( 139 void DownloadManager::GetTemporaryDownloads(
139 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 140 const FilePath& dir_path, DownloadVector* result) {
140 DCHECK(result); 141 DCHECK(result);
141 142
142 for (DownloadMap::iterator it = history_downloads_.begin(); 143 for (DownloadMap::iterator it = history_downloads_.begin();
143 it != history_downloads_.end(); ++it) { 144 it != history_downloads_.end(); ++it) {
144 if (it->second->is_temporary() && 145 if (it->second->is_temporary() &&
145 it->second->full_path().DirName() == dir_path) 146 it->second->full_path().DirName() == dir_path)
146 result->push_back(it->second); 147 result->push_back(it->second);
147 } 148 }
148 } 149 }
149 150
150 void DownloadManager::GetAllDownloads( 151 void DownloadManager::GetAllDownloads(
151 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 152 const FilePath& dir_path, DownloadVector* result) {
152 DCHECK(result); 153 DCHECK(result);
153 154
154 for (DownloadMap::iterator it = history_downloads_.begin(); 155 for (DownloadMap::iterator it = history_downloads_.begin();
155 it != history_downloads_.end(); ++it) { 156 it != history_downloads_.end(); ++it) {
156 if (!it->second->is_temporary() && 157 if (!it->second->is_temporary() &&
157 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) 158 (dir_path.empty() || it->second->full_path().DirName() == dir_path))
158 result->push_back(it->second); 159 result->push_back(it->second);
159 } 160 }
160 } 161 }
161 162
162 void DownloadManager::GetCurrentDownloads( 163 void DownloadManager::GetCurrentDownloads(
163 const FilePath& dir_path, std::vector<DownloadItem*>* result) { 164 const FilePath& dir_path, DownloadVector* result) {
164 DCHECK(result); 165 DCHECK(result);
165 166
166 for (DownloadMap::iterator it = history_downloads_.begin(); 167 for (DownloadMap::iterator it = history_downloads_.begin();
167 it != history_downloads_.end(); ++it) { 168 it != history_downloads_.end(); ++it) {
168 DownloadItem* item =it->second; 169 DownloadItem* item =it->second;
169 // Skip temporary items. 170 // Skip temporary items.
170 if (item->is_temporary()) 171 if (item->is_temporary())
171 continue; 172 continue;
172 // Skip items that have all their data, and are OK to save. 173 // Skip items that have all their data, and are OK to save.
173 if (!item->IsPartialDownload() && 174 if (!item->IsPartialDownload() &&
174 (item->safety_state() != DownloadItem::DANGEROUS)) 175 (item->safety_state() != DownloadItem::DANGEROUS))
175 continue; 176 continue;
176 // Skip items that don't match |dir_path|. 177 // Skip items that don't match |dir_path|.
177 // If |dir_path| is empty, all remaining items match. 178 // If |dir_path| is empty, all remaining items match.
178 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path)) 179 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
179 continue; 180 continue;
180 181
181 result->push_back(item); 182 result->push_back(item);
182 } 183 }
183 184
184 // If we have a parent profile, let it add its downloads to the results. 185 // If we have a parent profile, let it add its downloads to the results.
185 Profile* original_profile = profile_->GetOriginalProfile(); 186 Profile* original_profile = profile_->GetOriginalProfile();
186 if (original_profile != profile_) 187 if (original_profile != profile_)
187 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path, 188 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
188 result); 189 result);
189 } 190 }
190 191
191 void DownloadManager::SearchDownloads(const string16& query, 192 void DownloadManager::SearchDownloads(const string16& query,
192 std::vector<DownloadItem*>* result) { 193 DownloadVector* result) {
193 DCHECK(result); 194 DCHECK(result);
194 195
195 string16 query_lower(base::i18n::ToLower(query)); 196 string16 query_lower(base::i18n::ToLower(query));
196 197
197 for (DownloadMap::iterator it = history_downloads_.begin(); 198 for (DownloadMap::iterator it = history_downloads_.begin();
198 it != history_downloads_.end(); ++it) { 199 it != history_downloads_.end(); ++it) {
199 DownloadItem* download_item = it->second; 200 DownloadItem* download_item = it->second;
200 201
201 if (download_item->is_temporary() || download_item->is_extension_install()) 202 if (download_item->is_temporary() || download_item->is_extension_install())
202 continue; 203 continue;
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 BrowserThread::FILE, FROM_HERE, 871 BrowserThread::FILE, FROM_HERE,
871 NewRunnableMethod( 872 NewRunnableMethod(
872 file_manager_, &DownloadFileManager::CancelDownload, download_id)); 873 file_manager_, &DownloadFileManager::CancelDownload, download_id));
873 } 874 }
874 875
875 void DownloadManager::UpdateAppIcon() { 876 void DownloadManager::UpdateAppIcon() {
876 if (status_updater_) 877 if (status_updater_)
877 status_updater_->Update(); 878 status_updater_->Update();
878 } 879 }
879 880
881 int DownloadManager::RemoveDownloadItems(
882 const DownloadVector& pending_deletes) {
883 if (pending_deletes.empty())
884 return 0;
885
886 // Delete from internal maps.
887 for (DownloadVector::const_iterator it = pending_deletes.begin();
888 it != pending_deletes.end();
889 ++it) {
890 DownloadItem* download = *it;
891 DCHECK(download);
892 history_downloads_.erase(download->db_handle());
893 save_page_downloads_.erase(download->id());
894 downloads_.erase(download);
895 }
896
897 // Tell observers to refresh their views.
898 NotifyModelChanged();
899
900 // Delete the download items themselves.
901 const int num_deleted = static_cast<int>(pending_deletes.size());
902 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
903 return num_deleted;
904 }
905
880 void DownloadManager::RemoveDownload(int64 download_handle) { 906 void DownloadManager::RemoveDownload(int64 download_handle) {
881 DownloadMap::iterator it = history_downloads_.find(download_handle); 907 DownloadMap::iterator it = history_downloads_.find(download_handle);
882 if (it == history_downloads_.end()) 908 if (it == history_downloads_.end())
883 return; 909 return;
884 910
885 // Make history update. 911 // Make history update.
886 DownloadItem* download = it->second; 912 DownloadItem* download = it->second;
887 download_history_->RemoveEntry(download); 913 download_history_->RemoveEntry(download);
888 914
889 // Remove from our tables and delete. 915 // Remove from our tables and delete.
890 history_downloads_.erase(it); 916 int downloads_count = RemoveDownloadItems(DownloadVector(1, download));
891 int downloads_count = downloads_.erase(download);
892 DCHECK_EQ(1, downloads_count); 917 DCHECK_EQ(1, downloads_count);
893
894 // Tell observers to refresh their views.
895 NotifyModelChanged();
896
897 delete download;
898 } 918 }
899 919
900 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, 920 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
901 const base::Time remove_end) { 921 const base::Time remove_end) {
902 download_history_->RemoveEntriesBetween(remove_begin, remove_end); 922 download_history_->RemoveEntriesBetween(remove_begin, remove_end);
903 923
904 // All downloads visible to the user will be in the history, 924 // All downloads visible to the user will be in the history,
905 // so scan that map. 925 // so scan that map.
906 DownloadMap::iterator it = history_downloads_.begin(); 926 DownloadVector pending_deletes;
907 std::vector<DownloadItem*> pending_deletes; 927 for (DownloadMap::const_iterator it = history_downloads_.begin();
908 while (it != history_downloads_.end()) { 928 it != history_downloads_.end();
929 ++it) {
909 DownloadItem* download = it->second; 930 DownloadItem* download = it->second;
910 if (download->start_time() >= remove_begin && 931 if (download->start_time() >= remove_begin &&
911 (remove_end.is_null() || download->start_time() < remove_end) && 932 (remove_end.is_null() || download->start_time() < remove_end) &&
912 (download->IsComplete() || 933 (download->IsComplete() || download->IsCancelled())) {
913 download->IsCancelled() ||
914 download->IsInterrupted())) {
915 AssertQueueStateConsistent(download); 934 AssertQueueStateConsistent(download);
916
917 // Remove from the map and move to the next in the list.
918 history_downloads_.erase(it++);
919
920 // Also remove it from any completed dangerous downloads.
921 pending_deletes.push_back(download); 935 pending_deletes.push_back(download);
922
923 continue;
924 } 936 }
925
926 ++it;
927 } 937 }
928 938 return RemoveDownloadItems(pending_deletes);
929 // If we aren't deleting anything, we're done.
930 if (pending_deletes.empty())
931 return 0;
932
933 // Remove the chosen downloads from the main owning container.
934 for (std::vector<DownloadItem*>::iterator it = pending_deletes.begin();
935 it != pending_deletes.end(); it++) {
936 downloads_.erase(*it);
937 }
938
939 // Tell observers to refresh their views.
940 NotifyModelChanged();
941
942 // Delete the download items themselves.
943 int num_deleted = static_cast<int>(pending_deletes.size());
944
945 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
946 pending_deletes.clear();
947
948 return num_deleted;
949 } 939 }
950 940
951 int DownloadManager::RemoveDownloads(const base::Time remove_begin) { 941 int DownloadManager::RemoveDownloads(const base::Time remove_begin) {
952 return RemoveDownloadsBetween(remove_begin, base::Time()); 942 return RemoveDownloadsBetween(remove_begin, base::Time());
953 } 943 }
954 944
955 int DownloadManager::RemoveAllDownloads() { 945 int DownloadManager::RemoveAllDownloads() {
956 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) { 946 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) {
957 // This is an incognito downloader. Clear All should clear main download 947 // This is an incognito downloader. Clear All should clear main download
958 // manager as well. 948 // manager as well.
959 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads(); 949 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads();
960 } 950 }
961 // The null times make the date range unbounded. 951 // The null times make the date range unbounded.
962 return RemoveDownloadsBetween(base::Time(), base::Time()); 952 return RemoveDownloadsBetween(base::Time(), base::Time());
963 } 953 }
964 954
965 void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download) {
966 #if !defined(NDEBUG)
967 save_page_as_downloads_.insert(download);
968 #endif
969 downloads_.insert(download);
970 // Add to history and notify observers.
971 AddDownloadItemToHistory(download, DownloadHistory::kUninitializedHandle);
972 NotifyModelChanged();
973 }
974
975 // Initiate a download of a specific URL. We send the request to the 955 // Initiate a download of a specific URL. We send the request to the
976 // ResourceDispatcherHost, and let it send us responses like a regular 956 // ResourceDispatcherHost, and let it send us responses like a regular
977 // download. 957 // download.
978 void DownloadManager::DownloadUrl(const GURL& url, 958 void DownloadManager::DownloadUrl(const GURL& url,
979 const GURL& referrer, 959 const GURL& referrer,
980 const std::string& referrer_charset, 960 const std::string& referrer_charset,
981 TabContents* tab_contents) { 961 TabContents* tab_contents) {
982 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), 962 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(),
983 tab_contents); 963 tab_contents);
984 } 964 }
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 1138
1159 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508 1139 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508
1160 // is fixed. 1140 // is fixed.
1161 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle); 1141 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle);
1162 1142
1163 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); 1143 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
1164 download->set_db_handle(db_handle); 1144 download->set_db_handle(db_handle);
1165 1145
1166 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); 1146 DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
1167 history_downloads_[download->db_handle()] = download; 1147 history_downloads_[download->db_handle()] = download;
1148
1149 // Show in the appropriate browser UI.
1150 // This includes buttons to save or cancel, for a dangerous download.
1151 ShowDownloadInBrowser(download);
1152
1153 // Inform interested objects about the new download.
1154 NotifyModelChanged();
1168 } 1155 }
1169 1156
1170 // Once the new DownloadItem's creation info has been committed to the history 1157 // Once the new DownloadItem's creation info has been committed to the history
1171 // service, we associate the DownloadItem with the db handle, update our 1158 // service, we associate the DownloadItem with the db handle, update our
1172 // 'history_downloads_' map and inform observers. 1159 // 'history_downloads_' map and inform observers.
1173 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, 1160 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
1174 int64 db_handle) { 1161 int64 db_handle) {
1175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1176 DownloadItem* download = GetActiveDownloadItem(download_id); 1163 DownloadItem* download = GetActiveDownloadItem(download_id);
1177 if (!download) 1164 if (!download)
1178 return; 1165 return;
1179 1166
1180 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 1167 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
1181 << " download_id = " << download_id 1168 << " download_id = " << download_id
1182 << " download = " << download->DebugString(true); 1169 << " download = " << download->DebugString(true);
1183 1170
1184 AddDownloadItemToHistory(download, db_handle); 1171 AddDownloadItemToHistory(download, db_handle);
1185 1172
1186 // Show in the appropriate browser UI.
1187 // This includes buttons to save or cancel, for a dangerous download.
1188 ShowDownloadInBrowser(download);
1189
1190 // Inform interested objects about the new download.
1191 NotifyModelChanged();
1192
1193 // If the download is still in progress, try to complete it. 1173 // If the download is still in progress, try to complete it.
1194 // 1174 //
1195 // Otherwise, download has been cancelled or interrupted before we've 1175 // Otherwise, download has been cancelled or interrupted before we've
1196 // received the DB handle. We post one final message to the history 1176 // received the DB handle. We post one final message to the history
1197 // service so that it can be properly in sync with the DownloadItem's 1177 // service so that it can be properly in sync with the DownloadItem's
1198 // completion status, and also inform any observers so that they get 1178 // completion status, and also inform any observers so that they get
1199 // more than just the start notification. 1179 // more than just the start notification.
1200 if (download->IsInProgress()) { 1180 if (download->IsInProgress()) {
1201 MaybeCompleteDownload(download); 1181 MaybeCompleteDownload(download);
1202 } else { 1182 } else {
(...skipping 47 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
« no previous file with comments | « chrome/browser/download/download_manager.h ('k') | chrome/browser/download/save_page_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698