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

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

Issue 7192016: chrome.experimental.downloads (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: DownloadQuery, single DownloadMap Created 9 years, 5 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
« no previous file with comments | « chrome/browser/download/download_manager.h ('k') | chrome/browser/download/download_prefs.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "base/path_service.h" 11 #include "base/path_service.h"
12 #include "base/rand_util.h" 12 #include "base/rand_util.h"
13 #include "base/stl_util-inl.h" 13 #include "base/stl_util-inl.h"
14 #include "base/stringprintf.h" 14 #include "base/stringprintf.h"
15 #include "base/sys_string_conversions.h" 15 #include "base/sys_string_conversions.h"
16 #include "base/task.h" 16 #include "base/task.h"
17 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "chrome/browser/browser_process.h" 19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/download/download_create_info.h" 20 #include "chrome/browser/download/download_create_info.h"
21 #include "chrome/browser/download/download_extensions.h" 21 #include "chrome/browser/download/download_extensions.h"
22 #include "chrome/browser/download/download_file_manager.h" 22 #include "chrome/browser/download/download_file_manager.h"
23 #include "chrome/browser/download/download_history.h" 23 #include "chrome/browser/download/download_history.h"
24 #include "chrome/browser/download/download_item.h" 24 #include "chrome/browser/download/download_item.h"
25 #include "chrome/browser/download/download_prefs.h" 25 #include "chrome/browser/download/download_prefs.h"
26 #include "chrome/browser/download/download_query.h"
26 #include "chrome/browser/download/download_request_handle.h" 27 #include "chrome/browser/download/download_request_handle.h"
27 #include "chrome/browser/download/download_safe_browsing_client.h" 28 #include "chrome/browser/download/download_safe_browsing_client.h"
28 #include "chrome/browser/download/download_status_updater.h" 29 #include "chrome/browser/download/download_status_updater.h"
29 #include "chrome/browser/download/download_util.h" 30 #include "chrome/browser/download/download_util.h"
30 #include "chrome/browser/extensions/extension_service.h" 31 #include "chrome/browser/extensions/extension_service.h"
31 #include "chrome/browser/history/download_history_info.h" 32 #include "chrome/browser/history/download_history_info.h"
32 #include "chrome/browser/platform_util.h" 33 #include "chrome/browser/platform_util.h"
33 #include "chrome/browser/profiles/profile.h" 34 #include "chrome/browser/profiles/profile.h"
34 #include "chrome/browser/tab_contents/tab_util.h" 35 #include "chrome/browser/tab_contents/tab_util.h"
35 #include "chrome/browser/ui/browser.h" 36 #include "chrome/browser/ui/browser.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 78
78 if (file_manager_) { 79 if (file_manager_) {
79 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 80 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
80 NewRunnableMethod(file_manager_, 81 NewRunnableMethod(file_manager_,
81 &DownloadFileManager::OnDownloadManagerShutdown, 82 &DownloadFileManager::OnDownloadManagerShutdown,
82 make_scoped_refptr(this))); 83 make_scoped_refptr(this)));
83 } 84 }
84 85
85 AssertContainersConsistent(); 86 AssertContainersConsistent();
86 87
87 // Go through all downloads in downloads_. Dangerous ones we need to 88 for (DownloadMap::iterator it = downloads_.begin(); it != downloads_.end();) {
88 // remove on disk, and in progress ones we need to cancel. 89 DownloadItem* download = it->second;
89 for (DownloadSet::iterator it = downloads_.begin(); it != downloads_.end();) { 90 ++it;
90 DownloadItem* download = *it;
91
92 // Save iterator from potential erases in this set done by called code.
93 // Iterators after an erasure point are still valid for lists and
94 // associative containers such as sets.
95 it++;
96
97 if (download->safety_state() == DownloadItem::DANGEROUS && 91 if (download->safety_state() == DownloadItem::DANGEROUS &&
98 download->IsPartialDownload()) { 92 download->IsPartialDownload()) {
99 // The user hasn't accepted it, so we need to remove it
100 // from the disk. This may or may not result in it being
101 // removed from the DownloadManager queues and deleted
102 // (specifically, DownloadManager::RemoveDownload only
103 // removes and deletes it if it's known to the history service)
104 // so the only thing we know after calling this function is that
105 // the download was deleted if-and-only-if it was removed
106 // from all queues.
107 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN); 93 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
108 } else if (download->IsPartialDownload()) { 94 } else if (download->IsPartialDownload()) {
109 download->Cancel(false); 95 download->Cancel(false);
110 download_history_->UpdateEntry(download); 96 download_history_->UpdateEntry(download);
111 } 97 }
112 } 98 }
113 99 STLValueDeleter<DownloadMap> delete_items(&downloads_);
114 // At this point, all dangerous downloads have had their files removed
115 // and all in progress downloads have been cancelled. We can now delete
116 // anything left.
117
118 // Copy downloads_ to separate container so as not to set off checks
119 // in DownloadItem destruction.
120 DownloadSet downloads_to_delete;
121 downloads_to_delete.swap(downloads_);
122
123 in_progress_.clear();
124 active_downloads_.clear();
125 history_downloads_.clear();
126 #if !defined(NDEBUG)
127 save_page_as_downloads_.clear();
128 #endif
129 STLDeleteElements(&downloads_to_delete);
130 100
131 file_manager_ = NULL; 101 file_manager_ = NULL;
132 102
133 // Make sure the save as dialog doesn't notify us back if we're gone before 103 // Make sure the save as dialog doesn't notify us back if we're gone before
134 // it returns. 104 // it returns.
135 if (select_file_dialog_.get()) 105 if (select_file_dialog_.get())
136 select_file_dialog_->ListenerDestroyed(); 106 select_file_dialog_->ListenerDestroyed();
137 107
138 download_history_.reset(); 108 download_history_.reset();
139 download_prefs_.reset(); 109 download_prefs_.reset();
140
141 shutdown_needed_ = false;
142 }
143
144 void DownloadManager::GetTemporaryDownloads(
145 const FilePath& dir_path, std::vector<DownloadItem*>* result) {
146 DCHECK(result);
147
148 for (DownloadMap::iterator it = history_downloads_.begin();
149 it != history_downloads_.end(); ++it) {
150 if (it->second->is_temporary() &&
151 it->second->full_path().DirName() == dir_path)
152 result->push_back(it->second);
153 }
154 }
155
156 void DownloadManager::GetAllDownloads(
157 const FilePath& dir_path, std::vector<DownloadItem*>* result) {
158 DCHECK(result);
159
160 for (DownloadMap::iterator it = history_downloads_.begin();
161 it != history_downloads_.end(); ++it) {
162 if (!it->second->is_temporary() &&
163 (dir_path.empty() || it->second->full_path().DirName() == dir_path))
164 result->push_back(it->second);
165 }
166 }
167
168 void DownloadManager::GetCurrentDownloads(
169 const FilePath& dir_path, std::vector<DownloadItem*>* result) {
170 DCHECK(result);
171
172 for (DownloadMap::iterator it = history_downloads_.begin();
173 it != history_downloads_.end(); ++it) {
174 DownloadItem* item =it->second;
175 // Skip temporary items.
176 if (item->is_temporary())
177 continue;
178 // Skip items that have all their data, and are OK to save.
179 if (!item->IsPartialDownload() &&
180 (item->safety_state() != DownloadItem::DANGEROUS))
181 continue;
182 // Skip items that don't match |dir_path|.
183 // If |dir_path| is empty, all remaining items match.
184 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
185 continue;
186
187 result->push_back(item);
188 }
189
190 // If we have a parent profile, let it add its downloads to the results.
191 Profile* original_profile = profile_->GetOriginalProfile();
192 if (original_profile != profile_)
193 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
194 result);
195 }
196
197 void DownloadManager::SearchDownloads(const string16& query,
198 std::vector<DownloadItem*>* result) {
199 DCHECK(result);
200
201 string16 query_lower(base::i18n::ToLower(query));
202
203 for (DownloadMap::iterator it = history_downloads_.begin();
204 it != history_downloads_.end(); ++it) {
205 DownloadItem* download_item = it->second;
206
207 if (download_item->is_temporary() || download_item->is_extension_install())
208 continue;
209
210 // Display Incognito downloads only in Incognito window, and vice versa.
211 // The Incognito Downloads page will get the list of non-Incognito downloads
212 // from its parent profile.
213 if (profile_->IsOffTheRecord() != download_item->is_otr())
214 continue;
215
216 if (download_item->MatchesQuery(query_lower))
217 result->push_back(download_item);
218 }
219
220 // If we have a parent profile, let it add its downloads to the results.
221 Profile* original_profile = profile_->GetOriginalProfile();
222 if (original_profile != profile_)
223 original_profile->GetDownloadManager()->SearchDownloads(query, result);
224 } 110 }
225 111
226 // Query the history service for information about all persisted downloads. 112 // Query the history service for information about all persisted downloads.
227 bool DownloadManager::Init(Profile* profile) { 113 bool DownloadManager::Init(Profile* profile) {
228 DCHECK(profile); 114 DCHECK(profile);
229 DCHECK(!shutdown_needed_) << "DownloadManager already initialized."; 115 DCHECK(!shutdown_needed_) << "DownloadManager already initialized.";
230 shutdown_needed_ = true; 116 shutdown_needed_ = true;
231 117
232 profile_ = profile; 118 profile_ = profile;
233 download_history_.reset(new DownloadHistory(profile)); 119 download_history_.reset(new DownloadHistory(profile));
(...skipping 22 matching lines...) Expand all
256 // history system of a new download. Since this method can be called while the 142 // history system of a new download. Since this method can be called while the
257 // history service thread is still reading the persistent state, we do not 143 // history service thread is still reading the persistent state, we do not
258 // insert the new DownloadItem into 'history_downloads_' or inform our 144 // insert the new DownloadItem into 'history_downloads_' or inform our
259 // observers at this point. OnCreateDownloadEntryComplete() handles that 145 // observers at this point. OnCreateDownloadEntryComplete() handles that
260 // finalization of the the download creation as a callback from the 146 // finalization of the the download creation as a callback from the
261 // history thread. 147 // history thread.
262 void DownloadManager::StartDownload(int32 download_id) { 148 void DownloadManager::StartDownload(int32 download_id) {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264 150
265 DownloadItem* download = GetActiveDownloadItem(download_id); 151 DownloadItem* download = GetActiveDownloadItem(download_id);
152 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download;
266 if (!download) 153 if (!download)
267 return; 154 return;
268 155
269 // Create a client to verify download URL with safebrowsing. 156 // Create a client to verify download URL with safebrowsing.
270 // It deletes itself after the callback. 157 // It deletes itself after the callback.
271 scoped_refptr<DownloadSBClient> sb_client = new DownloadSBClient( 158 scoped_refptr<DownloadSBClient> sb_client = new DownloadSBClient(
272 download_id, download->url_chain(), download->referrer_url()); 159 download_id, download->url_chain(), download->referrer_url());
273 sb_client->CheckDownloadUrl( 160 sb_client->CheckDownloadUrl(
274 NewCallback(this, &DownloadManager::CheckDownloadUrlDone)); 161 NewCallback(this, &DownloadManager::CheckDownloadUrlDone));
275 } 162 }
276 163
277 void DownloadManager::CheckForHistoryFilesRemoval() { 164 void DownloadManager::CheckForHistoryFilesRemoval() {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 for (DownloadMap::iterator it = history_downloads_.begin(); 166 DVLOG(1) << __PRETTY_FUNCTION__;
280 it != history_downloads_.end(); ++it) { 167 for (DownloadMap::iterator it = downloads_.begin();
168 it != downloads_.end(); ++it) {
281 CheckForFileRemoval(it->second); 169 CheckForFileRemoval(it->second);
282 } 170 }
283 } 171 }
284 172
285 void DownloadManager::CheckForFileRemoval(DownloadItem* download_item) { 173 void DownloadManager::CheckForFileRemoval(DownloadItem* download_item) {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
287 if (download_item->IsComplete() && 175 if (download_item->IsComplete() &&
288 !download_item->file_externally_removed()) { 176 !download_item->file_externally_removed()) {
177 DVLOG(1) << __PRETTY_FUNCTION__ << download_item->id();
289 BrowserThread::PostTask( 178 BrowserThread::PostTask(
290 BrowserThread::FILE, FROM_HERE, 179 BrowserThread::FILE, FROM_HERE,
291 NewRunnableMethod(this, 180 NewRunnableMethod(this,
292 &DownloadManager::CheckForFileRemovalOnFileThread, 181 &DownloadManager::CheckForFileRemovalOnFileThread,
293 download_item->db_handle(), 182 download_item->id(),
294 download_item->GetTargetFilePath())); 183 download_item->GetTargetFilePath()));
295 } 184 }
296 } 185 }
297 186
298 void DownloadManager::CheckForFileRemovalOnFileThread( 187 void DownloadManager::CheckForFileRemovalOnFileThread(
299 int64 db_handle, const FilePath& path) { 188 int64 id, const FilePath& path) {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
301 if (!file_util::PathExists(path)) { 190 if (!file_util::PathExists(path)) {
191 DVLOG(1) << __PRETTY_FUNCTION__ << " " << id;
302 BrowserThread::PostTask( 192 BrowserThread::PostTask(
303 BrowserThread::UI, FROM_HERE, 193 BrowserThread::UI, FROM_HERE,
304 NewRunnableMethod(this, 194 NewRunnableMethod(this,
305 &DownloadManager::OnFileRemovalDetected, 195 &DownloadManager::OnFileRemovalDetected,
306 db_handle)); 196 id));
307 } 197 }
308 } 198 }
309 199
310 void DownloadManager::OnFileRemovalDetected(int64 db_handle) { 200 void DownloadManager::OnFileRemovalDetected(int64 id) {
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312 DownloadMap::iterator it = history_downloads_.find(db_handle); 202 DVLOG(1) << __PRETTY_FUNCTION__ << " " << id;
313 if (it != history_downloads_.end()) { 203 DownloadMap::iterator it = downloads_.find(id);
204 if (it != downloads_.end()) {
205 DVLOG(1) << __PRETTY_FUNCTION__ << " " << id;
314 DownloadItem* download_item = it->second; 206 DownloadItem* download_item = it->second;
315 download_item->OnDownloadedFileRemoved(); 207 download_item->OnDownloadedFileRemoved();
316 } 208 }
317 } 209 }
318 210
319 void DownloadManager::CheckDownloadUrlDone(int32 download_id, 211 void DownloadManager::CheckDownloadUrlDone(int32 download_id,
320 bool is_dangerous_url) { 212 bool is_dangerous_url) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322 214
323 DownloadItem* download = GetActiveDownloadItem(download_id); 215 DownloadItem* download = GetActiveDownloadItem(download_id);
216 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " "
217 << is_dangerous_url << " " << download;
324 if (!download) 218 if (!download)
325 return; 219 return;
326 220
327 if (is_dangerous_url) 221 if (is_dangerous_url)
328 download->MarkUrlDangerous(); 222 download->MarkUrlDangerous();
329 223
330 download_history_->CheckVisitedReferrerBefore(download_id, 224 download_history_->CheckVisitedReferrerBefore(download_id,
331 download->referrer_url(), 225 download->referrer_url(),
332 NewCallback(this, &DownloadManager::CheckVisitedReferrerBeforeDone)); 226 NewCallback(this, &DownloadManager::CheckVisitedReferrerBeforeDone));
333 } 227 }
334 228
335 void DownloadManager::CheckVisitedReferrerBeforeDone( 229 void DownloadManager::CheckVisitedReferrerBeforeDone(
336 int32 download_id, 230 int32 download_id,
337 bool visited_referrer_before) { 231 bool visited_referrer_before) {
338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
339 233
340 DownloadItem* download = GetActiveDownloadItem(download_id); 234 DownloadItem* download = GetActiveDownloadItem(download_id);
235 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download;
341 if (!download) 236 if (!download)
342 return; 237 return;
343 238
344 // Check whether this download is for an extension install or not. 239 // Check whether this download is for an extension install or not.
345 // Allow extensions to be explicitly saved. 240 // Allow extensions to be explicitly saved.
346 DownloadStateInfo state = download->state_info(); 241 DownloadStateInfo state = download->state_info();
347 if (!state.prompt_user_for_save_location) { 242 if (!state.prompt_user_for_save_location) {
348 if (UserScript::IsURLUserScript(download->GetURL(), 243 if (UserScript::IsURLUserScript(download->GetURL(),
349 download->mime_type()) || 244 download->mime_type()) ||
350 (download->mime_type() == Extension::kMimeType)) { 245 (download->mime_type() == Extension::kMimeType)) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 &DownloadManager::CheckIfSuggestedPathExists, 302 &DownloadManager::CheckIfSuggestedPathExists,
408 download->id(), 303 download->id(),
409 state, 304 state,
410 download_prefs()->download_path())); 305 download_prefs()->download_path()));
411 } 306 }
412 307
413 void DownloadManager::CheckIfSuggestedPathExists(int32 download_id, 308 void DownloadManager::CheckIfSuggestedPathExists(int32 download_id,
414 DownloadStateInfo state, 309 DownloadStateInfo state,
415 const FilePath& default_path) { 310 const FilePath& default_path) {
416 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
312 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id;
417 313
418 // Make sure the default download directory exists. 314 // Make sure the default download directory exists.
419 // TODO(phajdan.jr): only create the directory when we're sure the user 315 // TODO(phajdan.jr): only create the directory when we're sure the user
420 // is going to save there and not to another directory of his choice. 316 // is going to save there and not to another directory of his choice.
421 file_util::CreateDirectory(default_path); 317 file_util::CreateDirectory(default_path);
422 318
423 // Check writability of the suggested path. If we can't write to it, default 319 // Check writability of the suggested path. If we can't write to it, default
424 // to the user's "My Documents" directory. We'll prompt them in this case. 320 // to the user's "My Documents" directory. We'll prompt them in this case.
425 FilePath dir = state.suggested_path.DirName(); 321 FilePath dir = state.suggested_path.DirName();
426 FilePath filename = state.suggested_path.BaseName(); 322 FilePath filename = state.suggested_path.BaseName();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 &DownloadManager::OnPathExistenceAvailable, 393 &DownloadManager::OnPathExistenceAvailable,
498 download_id, 394 download_id,
499 state)); 395 state));
500 } 396 }
501 397
502 void DownloadManager::OnPathExistenceAvailable( 398 void DownloadManager::OnPathExistenceAvailable(
503 int32 download_id, const DownloadStateInfo& new_state) { 399 int32 download_id, const DownloadStateInfo& new_state) {
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
505 401
506 DownloadItem* download = GetActiveDownloadItem(download_id); 402 DownloadItem* download = GetActiveDownloadItem(download_id);
403 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download << " " << download_id;
507 if (!download) 404 if (!download)
508 return; 405 return;
509 406
510 VLOG(20) << __FUNCTION__ << "()" 407 VLOG(20) << __FUNCTION__ << "()"
511 << " download = " << download->DebugString(true); 408 << " download = " << download->DebugString(true);
512 409
513 download->SetFileCheckResults(new_state); 410 download->SetFileCheckResults(new_state);
514 411
515 FilePath suggested_path = download->suggested_path(); 412 FilePath suggested_path = download->suggested_path();
516 413
(...skipping 30 matching lines...) Expand all
547 // No prompting for download, just continue with the suggested name. 444 // No prompting for download, just continue with the suggested name.
548 ContinueDownloadWithPath(download, suggested_path); 445 ContinueDownloadWithPath(download, suggested_path);
549 } 446 }
550 } 447 }
551 448
552 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { 449 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) {
553 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
554 451
555 DownloadItem* download = new DownloadItem(this, *info, 452 DownloadItem* download = new DownloadItem(this, *info,
556 profile_->IsOffTheRecord()); 453 profile_->IsOffTheRecord());
454 DVLOG(1) << __PRETTY_FUNCTION__ << " " << info->download_id << " "
455 << download;
557 int32 download_id = info->download_id; 456 int32 download_id = info->download_id;
558 DCHECK(!ContainsKey(in_progress_, download_id)); 457 DCHECK(!ContainsKey(downloads_, download_id));
559 DCHECK(!ContainsKey(active_downloads_, download_id)); 458 downloads_[download_id] = download;
560 downloads_.insert(download);
561 active_downloads_[download_id] = download;
562 } 459 }
563 460
564 void DownloadManager::ContinueDownloadWithPath(DownloadItem* download, 461 void DownloadManager::ContinueDownloadWithPath(DownloadItem* download,
565 const FilePath& chosen_file) { 462 const FilePath& chosen_file) {
566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
567 DCHECK(download); 464 DCHECK(download);
568 465
569 int32 download_id = download->id(); 466 int32 download_id = download->id();
570 467 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download
571 // NOTE(ahendrickson) Eventually |active_downloads_| will replace 468 << " " << chosen_file.value();
572 // |in_progress_|, but we don't want to change the semantics yet.
573 DCHECK(!ContainsKey(in_progress_, download_id));
574 DCHECK(ContainsKey(downloads_, download));
575 DCHECK(ContainsKey(active_downloads_, download_id));
576 469
577 // Make sure the initial file name is set only once. 470 // Make sure the initial file name is set only once.
578 DCHECK(download->full_path().empty()); 471 DCHECK(download->full_path().empty());
579 download->OnPathDetermined(chosen_file); 472 download->OnPathDetermined(chosen_file);
580 download->UpdateTarget(); 473 download->UpdateTarget();
581 474
582 VLOG(20) << __FUNCTION__ << "()" 475 VLOG(20) << __FUNCTION__ << "()"
583 << " download = " << download->DebugString(true); 476 << " download = " << download->DebugString(true);
584 477
585 in_progress_[download_id] = download; 478 UpdateAppIcon(); // Reflect entry into .
586 UpdateAppIcon(); // Reflect entry into in_progress_.
587 479
588 // Rename to intermediate name. 480 // Rename to intermediate name.
589 FilePath download_path; 481 FilePath download_path;
590 if (download->IsDangerous()) { 482 if (download->IsDangerous()) {
591 // The download is not safe. We can now rename the file to its 483 // The download is not safe. We can now rename the file to its
592 // tentative name using RenameInProgressDownloadFile. 484 // tentative name using RenameInProgressDownloadFile.
593 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're 485 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're
594 // renaming it to the same name. 486 // renaming it to the same name.
595 download_path = download->full_path(); 487 download_path = download->full_path();
596 } else { 488 } else {
(...skipping 12 matching lines...) Expand all
609 download->id(), download_path)); 501 download->id(), download_path));
610 502
611 download->Rename(download_path); 503 download->Rename(download_path);
612 504
613 download_history_->AddEntry(download, 505 download_history_->AddEntry(download,
614 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); 506 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete));
615 } 507 }
616 508
617 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { 509 void DownloadManager::UpdateDownload(int32 download_id, int64 size) {
618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
619 DownloadMap::iterator it = active_downloads_.find(download_id); 511 DownloadMap::iterator it = downloads_.find(download_id);
620 if (it != active_downloads_.end()) { 512 if (it != downloads_.end()) {
621 DownloadItem* download = it->second; 513 DownloadItem* download = it->second;
622 if (download->IsInProgress()) { 514 if (download->IsInProgress()) {
623 download->Update(size); 515 download->Update(size);
624 UpdateAppIcon(); // Reflect size updates. 516 UpdateAppIcon(); // Reflect size updates.
625 download_history_->UpdateEntry(download); 517 download_history_->UpdateEntry(download);
626 } 518 }
627 } 519 }
628 } 520 }
629 521
630 void DownloadManager::OnResponseCompleted(int32 download_id, 522 void DownloadManager::OnResponseCompleted(int32 download_id,
(...skipping 10 matching lines...) Expand all
641 OnAllDataSaved(download_id, size, hash); 533 OnAllDataSaved(download_id, size, hash);
642 } else { 534 } else {
643 OnDownloadError(download_id, size, os_error); 535 OnDownloadError(download_id, size, os_error);
644 } 536 }
645 } 537 }
646 538
647 void DownloadManager::OnAllDataSaved(int32 download_id, 539 void DownloadManager::OnAllDataSaved(int32 download_id,
648 int64 size, 540 int64 size,
649 const std::string& hash) { 541 const std::string& hash) {
650 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id 542 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
651 << " size = " << size; 543 << " size = " << size << " occam " << downloads_.count(download_id);
652 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 544 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
653 545
654 // If it's not in active_downloads_, that means it was cancelled; just 546 DownloadItem* download = downloads_[download_id];
655 // ignore the notification. 547 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << size << " "
656 if (active_downloads_.count(download_id) == 0) 548 << hash << " " << download;
549 if (!download) {
657 return; 550 return;
658 551 }
659 DownloadItem* download = active_downloads_[download_id];
660 download->OnAllDataSaved(size); 552 download->OnAllDataSaved(size);
661 553
662 // When hash is not available, it means either it is not calculated 554 // When hash is not available, it means either it is not calculated
663 // or there is error while it is calculated. We will skip the download hash 555 // or there is error while it is calculated. We will skip the download hash
664 // check in that case. 556 // check in that case.
665 if (!hash.empty()) { 557 if (!hash.empty()) {
666 scoped_refptr<DownloadSBClient> sb_client = 558 scoped_refptr<DownloadSBClient> sb_client =
667 new DownloadSBClient(download_id, 559 new DownloadSBClient(download_id,
668 download->url_chain(), 560 download->url_chain(),
669 download->referrer_url()); 561 download->referrer_url());
670 sb_client->CheckDownloadHash( 562 sb_client->CheckDownloadHash(
671 hash, NewCallback(this, &DownloadManager::CheckDownloadHashDone)); 563 hash, NewCallback(this, &DownloadManager::CheckDownloadHashDone));
672 } 564 }
673 MaybeCompleteDownload(download); 565 MaybeCompleteDownload(download);
674 } 566 }
675 567
676 // TODO(lzheng): This function currently works as a callback place holder. 568 // TODO(lzheng): This function currently works as a callback place holder.
677 // Once we decide the hash check is reliable, we could move the 569 // Once we decide the hash check is reliable, we could move the
678 // MaybeCompleteDownload in OnAllDataSaved to this function. 570 // MaybeCompleteDownload in OnAllDataSaved to this function.
679 void DownloadManager::CheckDownloadHashDone(int32 download_id, 571 void DownloadManager::CheckDownloadHashDone(int32 download_id,
680 bool is_dangerous_hash) { 572 bool is_dangerous_hash) {
681 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 573 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
682 DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id 574 DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id
683 << " is dangerous_hash: " << is_dangerous_hash; 575 << " is dangerous_hash: " << is_dangerous_hash;
684
685 // If it's not in active_downloads_, that means it was cancelled or
686 // the download already finished.
687 if (active_downloads_.count(download_id) == 0)
688 return;
689
690 DVLOG(1) << "CheckDownloadHashDone, url: "
691 << active_downloads_[download_id]->GetURL().spec();
692 } 576 }
693 577
694 void DownloadManager::AssertQueueStateConsistent(DownloadItem* download) { 578 void DownloadManager::AssertQueueStateConsistent(DownloadItem* download) {
695 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved. 579 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download;
696 if (download->state() == DownloadItem::REMOVING) {
697 CHECK(!ContainsKey(downloads_, download));
698 CHECK(!ContainsKey(active_downloads_, download->id()));
699 CHECK(!ContainsKey(in_progress_, download->id()));
700 CHECK(!ContainsKey(history_downloads_, download->db_handle()));
701 return;
702 }
703
704 // Should be in downloads_ if we're not REMOVING.
705 CHECK(ContainsKey(downloads_, download));
706
707 // Check history_downloads_ consistency.
708 if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
709 CHECK(ContainsKey(history_downloads_, download->db_handle()));
710 } else {
711 // TODO(rdsmith): Somewhat painful; make sure to disable in
712 // release builds after resolution of http://crbug.com/85408.
713 for (DownloadMap::iterator it = history_downloads_.begin();
714 it != history_downloads_.end(); ++it) {
715 CHECK(it->second != download);
716 }
717 }
718
719 CHECK(ContainsKey(active_downloads_, download->id()) ==
720 (download->state() == DownloadItem::IN_PROGRESS));
721 CHECK(ContainsKey(in_progress_, download->id()) ==
722 (download->state() == DownloadItem::IN_PROGRESS));
723 } 580 }
724 581
725 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) { 582 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
583 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download << " " << download->id();
726 // If we don't have all the data, the download is not ready for 584 // If we don't have all the data, the download is not ready for
727 // completion. 585 // completion.
728 if (!download->all_data_saved()) 586 if (!download->all_data_saved())
729 return false; 587 return false;
730 588
731 // If the download is dangerous, but not yet validated, it's not ready for 589 // If the download is dangerous, but not yet validated, it's not ready for
732 // completion. 590 // completion.
733 if (download->safety_state() == DownloadItem::DANGEROUS) 591 if (download->safety_state() == DownloadItem::DANGEROUS)
734 return false; 592 return false;
735 593
736 // If the download isn't active (e.g. has been cancelled) it's not
737 // ready for completion.
738 if (active_downloads_.count(download->id()) == 0)
739 return false;
740
741 // If the download hasn't been inserted into the history system
742 // (which occurs strictly after file name determination, intermediate
743 // file rename, and UI display) then it's not ready for completion.
744 if (download->db_handle() == DownloadHistory::kUninitializedHandle)
745 return false;
746
747 return true; 594 return true;
748 } 595 }
749 596
750 void DownloadManager::MaybeCompleteDownload(DownloadItem* download) { 597 void DownloadManager::MaybeCompleteDownload(DownloadItem* download) {
751 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 598 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
752 VLOG(20) << __FUNCTION__ << "()" << " download = " 599 VLOG(20) << __FUNCTION__ << "()" << " download = "
753 << download->DebugString(false); 600 << download->DebugString(false);
754 601
755 if (!IsDownloadReadyForCompletion(download)) 602 if (!IsDownloadReadyForCompletion(download))
756 return; 603 return;
757 604
758 // TODO(rdsmith): DCHECK that we only pass through this point 605 // TODO(rdsmith): DCHECK that we only pass through this point
759 // once per download. The natural way to do this is by a state 606 // once per download. The natural way to do this is by a state
760 // transition on the DownloadItem. 607 // transition on the DownloadItem.
761 608
762 // Confirm we're in the proper set of states to be here; 609 // Confirm we're in the proper set of states to be here;
763 // in in_progress_, have all data, have a history handle, (validated or safe). 610 // in , have all data, have a history handle, (validated or safe).
764 DCHECK_NE(DownloadItem::DANGEROUS, download->safety_state()); 611 DCHECK_NE(DownloadItem::DANGEROUS, download->safety_state());
765 DCHECK_EQ(1u, in_progress_.count(download->id()));
766 DCHECK(download->all_data_saved()); 612 DCHECK(download->all_data_saved());
767 DCHECK(download->db_handle() != DownloadHistory::kUninitializedHandle);
768 DCHECK_EQ(1u, history_downloads_.count(download->db_handle()));
769 613
770 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " 614 VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
771 << download->DebugString(false); 615 << download->DebugString(false);
772 616
773 // Remove the id from in_progress 617 UpdateAppIcon(); // Reflect removal from .
774 in_progress_.erase(download->id());
775 UpdateAppIcon(); // Reflect removal from in_progress_.
776 618
777 download_history_->UpdateEntry(download); 619 download_history_->UpdateEntry(download);
778 620
779 // Finish the download. 621 // Finish the download.
780 download->OnDownloadCompleting(file_manager_); 622 download->OnDownloadCompleting(file_manager_);
781 } 623 }
782 624
783 void DownloadManager::DownloadCompleted(int32 download_id) { 625 void DownloadManager::DownloadCompleted(int32 download_id) {
784 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 626 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
785 DownloadItem* download = GetDownloadItem(download_id); 627 DownloadItem* download = GetDownloadItem(download_id);
786 DCHECK(download); 628 DCHECK(download);
787 download_history_->UpdateEntry(download); 629 download_history_->UpdateEntry(download);
788 active_downloads_.erase(download_id);
789 } 630 }
790 631
791 void DownloadManager::OnDownloadRenamedToFinalName(int download_id, 632 void DownloadManager::OnDownloadRenamedToFinalName(int download_id,
792 const FilePath& full_path, 633 const FilePath& full_path,
793 int uniquifier) { 634 int uniquifier) {
794 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id 635 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
795 << " full_path = \"" << full_path.value() << "\"" 636 << " full_path = \"" << full_path.value() << "\""
796 << " uniquifier = " << uniquifier; 637 << " uniquifier = " << uniquifier;
797 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 638 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
798 639
(...skipping 12 matching lines...) Expand all
811 652
812 if (uniquifier) 653 if (uniquifier)
813 item->set_path_uniquifier(uniquifier); 654 item->set_path_uniquifier(uniquifier);
814 655
815 item->OnDownloadRenamedToFinalName(full_path); 656 item->OnDownloadRenamedToFinalName(full_path);
816 download_history_->UpdateDownloadPath(item, full_path); 657 download_history_->UpdateDownloadPath(item, full_path);
817 } 658 }
818 659
819 void DownloadManager::DownloadCancelled(int32 download_id) { 660 void DownloadManager::DownloadCancelled(int32 download_id) {
820 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 661 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
821 DownloadMap::iterator it = in_progress_.find(download_id); 662 DownloadItem* download = downloads_[download_id];
822 if (it == in_progress_.end()) 663 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download
823 return; 664 << " " << (download ? download->DebugString(true) : "");
824 DownloadItem* download = it->second; 665 DCHECK(download);
825 666 UpdateAppIcon(); // Reflect removal from .
826 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id 667 download_history_->UpdateEntry(download);
827 << " download = " << download->DebugString(true);
828
829 // Clean up will happen when the history system create callback runs if we
830 // don't have a valid db_handle yet.
831 if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
832 in_progress_.erase(it);
833 active_downloads_.erase(download_id);
834 UpdateAppIcon(); // Reflect removal from in_progress_.
835 download_history_->UpdateEntry(download);
836 }
837
838 DownloadCancelledInternal(download_id, download->request_handle()); 668 DownloadCancelledInternal(download_id, download->request_handle());
839 } 669 }
840 670
841 void DownloadManager::DownloadCancelledInternal( 671 void DownloadManager::DownloadCancelledInternal(
842 int download_id, DownloadRequestHandle request_handle) { 672 int download_id, DownloadRequestHandle request_handle) {
843 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 673 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
844 request_handle.CancelRequest(); 674 request_handle.CancelRequest();
845 675
846 BrowserThread::PostTask( 676 BrowserThread::PostTask(
847 BrowserThread::FILE, FROM_HERE, 677 BrowserThread::FILE, FROM_HERE,
848 NewRunnableMethod( 678 NewRunnableMethod(
849 file_manager_, &DownloadFileManager::CancelDownload, download_id)); 679 file_manager_, &DownloadFileManager::CancelDownload, download_id));
850 } 680 }
851 681
852 void DownloadManager::OnDownloadError(int32 download_id, 682 void DownloadManager::OnDownloadError(int32 download_id,
853 int64 size, 683 int64 size,
854 int os_error) { 684 int os_error) {
855 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 685 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
856 DownloadMap::iterator it = active_downloads_.find(download_id); 686 DownloadItem* download = downloads_[download_id];
857 // A cancel at the right time could remove the download from the 687 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download
858 // |active_downloads_| map before we get here. 688 << " " << (download ? download->DebugString(true) : "");
859 if (it == active_downloads_.end()) 689 DCHECK(download);
860 return;
861
862 DownloadItem* download = it->second;
863
864 VLOG(20) << __FUNCTION__ << "()" << " Error " << os_error
865 << " at offset " << download->received_bytes()
866 << " for download = " << download->DebugString(true);
867
868 download->Interrupted(size, os_error); 690 download->Interrupted(size, os_error);
869 691 UpdateAppIcon(); // Reflect removal from .
870 // TODO(ahendrickson) - Remove this when we add resuming of interrupted 692 download_history_->UpdateEntry(download);
871 // downloads, as we will keep the download item around in that case.
872 //
873 // Clean up will happen when the history system create callback runs if we
874 // don't have a valid db_handle yet.
875 if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
876 in_progress_.erase(download_id);
877 active_downloads_.erase(download_id);
878 UpdateAppIcon(); // Reflect removal from in_progress_.
879 download_history_->UpdateEntry(download);
880 }
881
882 BrowserThread::PostTask( 693 BrowserThread::PostTask(
883 BrowserThread::FILE, FROM_HERE, 694 BrowserThread::FILE, FROM_HERE,
884 NewRunnableMethod( 695 NewRunnableMethod(
885 file_manager_, &DownloadFileManager::CancelDownload, download_id)); 696 file_manager_, &DownloadFileManager::CancelDownload, download_id));
886 } 697 }
887 698
888 void DownloadManager::UpdateAppIcon() { 699 void DownloadManager::UpdateAppIcon() {
889 if (status_updater_) 700 if (status_updater_)
890 status_updater_->Update(); 701 status_updater_->Update();
891 } 702 }
892 703
893 void DownloadManager::RemoveDownload(int64 download_handle) { 704 void DownloadManager::RemoveDownload(int64 id) {
894 DownloadMap::iterator it = history_downloads_.find(download_handle); 705 DownloadMap::iterator it = downloads_.find(id);
895 if (it == history_downloads_.end()) 706 scoped_ptr<DownloadItem> download(it->second);
707 DVLOG(1) << __PRETTY_FUNCTION__ << " " << id << " " << download.get();
708 if (download.get() == NULL) {
896 return; 709 return;
710 }
711 download_history_->RemoveEntry(download.get());
712 downloads_.erase(it);
713 NotifyModelChanged();
714 }
897 715
898 // Make history update. 716 void DownloadManager::GetTemporaryDownloads(
899 DownloadItem* download = it->second; 717 const FilePath& dir_path, std::vector<DownloadItem*>* result) {
900 download_history_->RemoveEntry(download); 718 DCHECK(result);
901 719
902 // Remove from our tables and delete. 720 for (DownloadMap::iterator it = downloads_.begin();
903 history_downloads_.erase(it); 721 it != downloads_.end(); ++it) {
904 int downloads_count = downloads_.erase(download); 722 if (it->second->is_temporary() &&
905 DCHECK_EQ(1, downloads_count); 723 it->second->full_path().DirName() == dir_path)
724 result->push_back(it->second);
725 }
726 }
906 727
907 // Tell observers to refresh their views. 728 void DownloadManager::GetAllDownloads(
908 NotifyModelChanged(); 729 const FilePath& dir_path, std::vector<DownloadItem*>* result) {
730 DCHECK(result);
909 731
910 delete download; 732 for (DownloadMap::iterator it = downloads_.begin();
733 it != downloads_.end(); ++it) {
734 if (!it->second->is_temporary() &&
735 (dir_path.empty() || it->second->full_path().DirName() == dir_path))
736 result->push_back(it->second);
737 }
738 }
739
740 void DownloadManager::GetCurrentDownloads(
741 const FilePath& dir_path, std::vector<DownloadItem*>* result) {
742 DCHECK(result);
743
744 for (DownloadMap::iterator it = downloads_.begin();
745 it != downloads_.end(); ++it) {
746 DownloadItem* item =it->second;
747 // Skip temporary items.
748 if (item->is_temporary())
749 continue;
750 // Skip items that have all their data, and are OK to save.
751 if (!item->IsPartialDownload() &&
752 (item->safety_state() != DownloadItem::DANGEROUS))
753 continue;
754 // Skip items that don't match |dir_path|.
755 // If |dir_path| is empty, all remaining items match.
756 if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
757 continue;
758
759 result->push_back(item);
760 }
761
762 // If we have a parent profile, let it add its downloads to the results.
763 Profile* original_profile = profile_->GetOriginalProfile();
764 if (original_profile != profile_)
765 original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
766 result);
767 }
768
769 bool DownloadManager::Search(const download_util::DownloadQuery& query,
770 std::vector<DownloadItem*>* items,
771 std::string* error_msg,
772 ListValue* json_results) const {
773 std::vector<DownloadItem*> default_items;
774 if (items == NULL) {
775 items = &default_items;
776 }
777 for (DownloadMap::const_iterator it = downloads_.begin();
778 it != downloads_.end(); ++it) {
779 items->push_back(it->second);
780 }
781 return query.Search(items, error_msg, json_results);
782 }
783
784 void DownloadManager::SearchDownloads(const string16& query,
785 std::vector<DownloadItem*>* result) {
786 DCHECK(result);
787
788 string16 query_lower(base::i18n::ToLower(query));
789
790 for (DownloadMap::iterator it = downloads_.begin();
791 it != downloads_.end(); ++it) {
792 DownloadItem* download_item = it->second;
793
794 if (download_item->is_temporary() || download_item->is_extension_install())
795 continue;
796
797 // Display Incognito downloads only in Incognito window, and vice versa.
798 // The Incognito Downloads page will get the list of non-Incognito downloads
799 // from its parent profile.
800 if (profile_->IsOffTheRecord() != download_item->is_otr())
801 continue;
802
803 if (download_item->MatchesQuery(query_lower))
804 result->push_back(download_item);
805 }
806
807 // If we have a parent profile, let it add its downloads to the results.
808 Profile* original_profile = profile_->GetOriginalProfile();
809 if (original_profile != profile_)
810 original_profile->GetDownloadManager()->SearchDownloads(query, result);
911 } 811 }
912 812
913 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, 813 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
914 const base::Time remove_end) { 814 const base::Time remove_end) {
915 download_history_->RemoveEntriesBetween(remove_begin, remove_end); 815 download_history_->RemoveEntriesBetween(remove_begin, remove_end);
916
917 // All downloads visible to the user will be in the history,
918 // so scan that map.
919 DownloadMap::iterator it = history_downloads_.begin();
920 std::vector<DownloadItem*> pending_deletes; 816 std::vector<DownloadItem*> pending_deletes;
921 while (it != history_downloads_.end()) { 817 STLElementDeleter<std::vector<DownloadItem*> >
818 delete_pending_deletes(&pending_deletes);
819 for (DownloadMap::iterator it = downloads_.begin();
820 it != downloads_.end();) {
922 DownloadItem* download = it->second; 821 DownloadItem* download = it->second;
923 if (download->start_time() >= remove_begin && 822 if (download->start_time() >= remove_begin &&
924 (remove_end.is_null() || download->start_time() < remove_end) && 823 (remove_end.is_null() || download->start_time() < remove_end) &&
925 (download->IsComplete() || 824 (download->IsComplete() ||
926 download->IsCancelled() || 825 download->IsCancelled() ||
927 download->IsInterrupted())) { 826 download->IsInterrupted())) {
928 AssertQueueStateConsistent(download); 827 AssertQueueStateConsistent(download);
929 828 downloads_.erase(it++);
930 // Remove from the map and move to the next in the list.
931 history_downloads_.erase(it++);
932
933 // Also remove it from any completed dangerous downloads.
934 pending_deletes.push_back(download); 829 pending_deletes.push_back(download);
935 830 } else {
936 continue; 831 ++it;
937 } 832 }
938
939 ++it;
940 } 833 }
941 834 if (pending_deletes.empty()) {
942 // If we aren't deleting anything, we're done.
943 if (pending_deletes.empty())
944 return 0; 835 return 0;
945
946 // Remove the chosen downloads from the main owning container.
947 for (std::vector<DownloadItem*>::iterator it = pending_deletes.begin();
948 it != pending_deletes.end(); it++) {
949 downloads_.erase(*it);
950 } 836 }
951
952 // Tell observers to refresh their views.
953 NotifyModelChanged(); 837 NotifyModelChanged();
954
955 // Delete the download items themselves.
956 int num_deleted = static_cast<int>(pending_deletes.size()); 838 int num_deleted = static_cast<int>(pending_deletes.size());
957
958 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
959 pending_deletes.clear();
960
961 return num_deleted; 839 return num_deleted;
962 } 840 }
963 841
964 int DownloadManager::RemoveDownloads(const base::Time remove_begin) { 842 int DownloadManager::RemoveDownloads(const base::Time remove_begin) {
965 return RemoveDownloadsBetween(remove_begin, base::Time()); 843 return RemoveDownloadsBetween(remove_begin, base::Time());
966 } 844 }
967 845
968 int DownloadManager::RemoveAllDownloads() { 846 int DownloadManager::RemoveAllDownloads() {
969 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) { 847 if (this != profile_->GetOriginalProfile()->GetDownloadManager()) {
970 // This is an incognito downloader. Clear All should clear main download 848 // This is an incognito downloader. Clear All should clear main download
971 // manager as well. 849 // manager as well.
972 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads(); 850 profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads();
973 } 851 }
974 // The null times make the date range unbounded. 852 // The null times make the date range unbounded.
975 return RemoveDownloadsBetween(base::Time(), base::Time()); 853 return RemoveDownloadsBetween(base::Time(), base::Time());
976 } 854 }
977 855
978 void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download_item) { 856 void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download_item) {
979 #if !defined(NDEBUG) 857 #if !defined(NDEBUG)
980 save_page_as_downloads_.insert(download_item); 858 save_page_as_downloads_.insert(download_item);
981 #endif 859 #endif
982 downloads_.insert(download_item); 860 downloads_[download_item->id()] = download_item;
983 } 861 }
984 862
985 // Initiate a download of a specific URL. We send the request to the 863 // Initiate a download of a specific URL. We send the request to the
986 // ResourceDispatcherHost, and let it send us responses like a regular 864 // ResourceDispatcherHost, and let it send us responses like a regular
987 // download. 865 // download.
988 void DownloadManager::DownloadUrl(const GURL& url, 866 void DownloadManager::DownloadUrl(const GURL& url,
989 const GURL& referrer, 867 const GURL& referrer,
990 const std::string& referrer_charset, 868 const std::string& referrer_charset,
991 TabContents* tab_contents) { 869 TabContents* tab_contents) {
992 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), 870 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(),
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 if (extension.empty()) 906 if (extension.empty())
1029 return false; 907 return false;
1030 if (Extension::IsExtension(path)) 908 if (Extension::IsExtension(path))
1031 return false; 909 return false;
1032 DCHECK(extension[0] == FilePath::kExtensionSeparator); 910 DCHECK(extension[0] == FilePath::kExtensionSeparator);
1033 extension.erase(0, 1); 911 extension.erase(0, 1);
1034 return download_prefs_->IsAutoOpenEnabledForExtension(extension); 912 return download_prefs_->IsAutoOpenEnabledForExtension(extension);
1035 } 913 }
1036 914
1037 bool DownloadManager::IsDownloadProgressKnown() { 915 bool DownloadManager::IsDownloadProgressKnown() {
1038 for (DownloadMap::iterator i = in_progress_.begin(); 916 for (DownloadMap::iterator i = downloads_.begin();
1039 i != in_progress_.end(); ++i) { 917 i != downloads_.end(); ++i) {
1040 if (i->second->total_bytes() <= 0) 918 if (i->second->total_bytes() <= 0)
1041 return false; 919 return false;
1042 } 920 }
1043 921
1044 return true; 922 return true;
1045 } 923 }
1046 924
1047 int64 DownloadManager::GetInProgressDownloadCount() { 925 int64 DownloadManager::GetInProgressDownloadCount() {
1048 return in_progress_.size(); 926 return downloads_.size();
1049 } 927 }
1050 928
1051 int64 DownloadManager::GetReceivedDownloadBytes() { 929 int64 DownloadManager::GetReceivedDownloadBytes() {
1052 DCHECK(IsDownloadProgressKnown()); 930 DCHECK(IsDownloadProgressKnown());
1053 int64 received_bytes = 0; 931 int64 received_bytes = 0;
1054 for (DownloadMap::iterator i = in_progress_.begin(); 932 for (DownloadMap::iterator i = downloads_.begin();
1055 i != in_progress_.end(); ++i) { 933 i != downloads_.end(); ++i) {
1056 received_bytes += i->second->received_bytes(); 934 received_bytes += i->second->received_bytes();
1057 } 935 }
1058 return received_bytes; 936 return received_bytes;
1059 } 937 }
1060 938
1061 int64 DownloadManager::GetTotalDownloadBytes() { 939 int64 DownloadManager::GetTotalDownloadBytes() {
1062 DCHECK(IsDownloadProgressKnown()); 940 DCHECK(IsDownloadProgressKnown());
1063 int64 total_bytes = 0; 941 int64 total_bytes = 0;
1064 for (DownloadMap::iterator i = in_progress_.begin(); 942 for (DownloadMap::iterator i = downloads_.begin();
1065 i != in_progress_.end(); ++i) { 943 i != downloads_.end(); ++i) {
1066 total_bytes += i->second->total_bytes(); 944 total_bytes += i->second->total_bytes();
1067 } 945 }
1068 return total_bytes; 946 return total_bytes;
1069 } 947 }
1070 948
1071 void DownloadManager::FileSelected(const FilePath& path, 949 void DownloadManager::FileSelected(const FilePath& path,
1072 int index, void* params) { 950 int index, void* params) {
1073 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 951 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1074 952
1075 int32* id_ptr = reinterpret_cast<int32*>(params); 953 int32* id_ptr = reinterpret_cast<int32*>(params);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 1022
1145 MaybeCompleteDownload(download); 1023 MaybeCompleteDownload(download);
1146 } 1024 }
1147 1025
1148 // Operations posted to us from the history service ---------------------------- 1026 // Operations posted to us from the history service ----------------------------
1149 1027
1150 // The history service has retrieved all download entries. 'entries' contains 1028 // The history service has retrieved all download entries. 'entries' contains
1151 // 'DownloadHistoryInfo's in sorted order (by ascending start_time). 1029 // 'DownloadHistoryInfo's in sorted order (by ascending start_time).
1152 void DownloadManager::OnQueryDownloadEntriesComplete( 1030 void DownloadManager::OnQueryDownloadEntriesComplete(
1153 std::vector<DownloadHistoryInfo>* entries) { 1031 std::vector<DownloadHistoryInfo>* entries) {
1154 for (size_t i = 0; i < entries->size(); ++i) { 1032 for (std::vector<DownloadHistoryInfo>::iterator it = entries->begin();
1155 DownloadItem* download = new DownloadItem(this, entries->at(i)); 1033 it != entries->end(); ++it) {
1156 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); 1034 DownloadItem* download = new DownloadItem(this, *it);
1157 downloads_.insert(download); 1035 DVLOG(2) << __PRETTY_FUNCTION__ << " " << download->id() << " " << download;
1158 history_downloads_[download->db_handle()] = download; 1036 DCHECK(!ContainsKey(downloads_, download->id()));
1159 VLOG(20) << __FUNCTION__ << "()" << i << ">" 1037 downloads_[download->id()] = download;
1160 << " download = " << download->DebugString(true);
1161 } 1038 }
1162 NotifyModelChanged(); 1039 NotifyModelChanged();
1163 CheckForHistoryFilesRemoval(); 1040 CheckForHistoryFilesRemoval();
1164 } 1041 }
1165 1042
1166 // Once the new DownloadItem's creation info has been committed to the history 1043 // Once the new DownloadItem's creation info has been committed to the history
1167 // service, we associate the DownloadItem with the db handle, update our 1044 // service, we associate the DownloadItem with the db handle, update our
1168 // 'history_downloads_' map and inform observers. 1045 // 'history_downloads_' map and inform observers.
1169 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, 1046 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
1170 int64 db_handle) { 1047 int64 db_handle) {
1171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1048 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1172 DownloadItem* download = GetActiveDownloadItem(download_id); 1049 DownloadItem* download = GetActiveDownloadItem(download_id);
1050 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << db_handle
1051 << " " << download;
1173 if (!download) 1052 if (!download)
1174 return; 1053 return;
1175 1054
1176 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 1055 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
1177 << " download_id = " << download_id 1056 << " download_id = " << download_id
1178 << " download = " << download->DebugString(true); 1057 << " download = " << download->DebugString(true);
1179 1058
1180 // It's not immediately obvious, but HistoryBackend::CreateDownload() can
1181 // call this function with an invalid |db_handle|. For instance, this can
1182 // happen when the history database is offline. We cannot have multiple
1183 // DownloadItems with the same invalid db_handle, so we need to assign a
1184 // unique |db_handle| here.
1185 if (db_handle == DownloadHistory::kUninitializedHandle)
1186 db_handle = download_history_->GetNextFakeDbHandle();
1187
1188 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508
1189 // is fixed.
1190 CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle);
1191
1192 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
1193 download->set_db_handle(db_handle);
1194
1195 DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
1196 history_downloads_[download->db_handle()] = download;
1197
1198 // Show in the appropriate browser UI. 1059 // Show in the appropriate browser UI.
1199 // This includes buttons to save or cancel, for a dangerous download. 1060 // This includes buttons to save or cancel, for a dangerous download.
1200 ShowDownloadInBrowser(download); 1061 ShowDownloadInBrowser(download);
1201 1062
1202 // Inform interested objects about the new download. 1063 // Inform interested objects about the new download.
1203 NotifyModelChanged(); 1064 NotifyModelChanged();
1204 1065
1205 // If the download is still in progress, try to complete it. 1066 // If the download is still in progress, try to complete it.
1206 // 1067 //
1207 // Otherwise, download has been cancelled or interrupted before we've 1068 // Otherwise, download has been cancelled or interrupted before we've
1208 // received the DB handle. We post one final message to the history 1069 // received the DB handle. We post one final message to the history
1209 // service so that it can be properly in sync with the DownloadItem's 1070 // service so that it can be properly in sync with the DownloadItem's
1210 // completion status, and also inform any observers so that they get 1071 // completion status, and also inform any observers so that they get
1211 // more than just the start notification. 1072 // more than just the start notification.
1212 if (download->IsInProgress()) { 1073 if (download->IsInProgress()) {
1213 MaybeCompleteDownload(download); 1074 MaybeCompleteDownload(download);
1214 } else { 1075 } else {
1215 DCHECK(download->IsCancelled())
1216 << " download = " << download->DebugString(true);
1217 in_progress_.erase(download_id);
1218 active_downloads_.erase(download_id);
1219 download_history_->UpdateEntry(download); 1076 download_history_->UpdateEntry(download);
1220 download->UpdateObservers(); 1077 download->UpdateObservers();
1221 } 1078 }
1222 } 1079 }
1223 1080
1224 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) { 1081 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
1082 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download << " " << download->id();
1225 1083
1226 // The 'contents' may no longer exist if the user closed the tab before we 1084 // The 'contents' may no longer exist if the user closed the tab before we
1227 // get this start completion event. If it does, tell the origin TabContents 1085 // get this start completion event. If it does, tell the origin TabContents
1228 // to display its download shelf. 1086 // to display its download shelf.
1229 DownloadRequestHandle request_handle = download->request_handle(); 1087 DownloadRequestHandle request_handle = download->request_handle();
1230 TabContents* contents = request_handle.GetTabContents(); 1088 TabContents* contents = request_handle.GetTabContents();
1231 TabContentsWrapper* wrapper = NULL; 1089 TabContentsWrapper* wrapper = NULL;
1232 if (contents) 1090 if (contents)
1233 wrapper = TabContentsWrapper::GetCurrentWrapperForContents(contents); 1091 wrapper = TabContentsWrapper::GetCurrentWrapperForContents(contents);
1234 1092
(...skipping 15 matching lines...) Expand all
1250 // Clears the last download path, used to initialize "save as" dialogs. 1108 // Clears the last download path, used to initialize "save as" dialogs.
1251 void DownloadManager::ClearLastDownloadPath() { 1109 void DownloadManager::ClearLastDownloadPath() {
1252 last_download_path_ = FilePath(); 1110 last_download_path_ = FilePath();
1253 } 1111 }
1254 1112
1255 void DownloadManager::NotifyModelChanged() { 1113 void DownloadManager::NotifyModelChanged() {
1256 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged()); 1114 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged());
1257 } 1115 }
1258 1116
1259 DownloadItem* DownloadManager::GetDownloadItem(int download_id) { 1117 DownloadItem* DownloadManager::GetDownloadItem(int download_id) {
1260 // The |history_downloads_| map is indexed by the download's db_handle, 1118 DownloadItem* download = downloads_[download_id];
1261 // not its id, so we have to iterate. 1119 DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download;
1262 for (DownloadMap::iterator it = history_downloads_.begin(); 1120 return download;
1263 it != history_downloads_.end(); ++it) {
1264 DownloadItem* item = it->second;
1265 if (item->id() == download_id)
1266 return item;
1267 }
1268 return NULL;
1269 } 1121 }
1270 1122
1271 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) { 1123 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
1272 DCHECK(ContainsKey(active_downloads_, download_id)); 1124 return GetDownloadItem(download_id);
1273 DownloadItem* download = active_downloads_[download_id];
1274 DCHECK(download != NULL);
1275 return download;
1276 } 1125 }
1277 1126
1278 // Confirm that everything in all maps is also in |downloads_|, and that 1127 // Confirm that everything in all maps is also in |downloads_|, and that
1279 // everything in |downloads_| is also in some other map. 1128 // everything in |downloads_| is also in some other map.
1280 void DownloadManager::AssertContainersConsistent() const { 1129 void DownloadManager::AssertContainersConsistent() const {
1281 #if !defined(NDEBUG)
1282 // Turn everything into sets.
1283 DownloadSet active_set, history_set;
1284 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_};
1285 DownloadSet* local_sets[] = {&active_set, &history_set};
1286 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets));
1287 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
1288 for (DownloadMap::const_iterator it = input_maps[i]->begin();
1289 it != input_maps[i]->end(); it++) {
1290 local_sets[i]->insert(&*it->second);
1291 }
1292 }
1293
1294 // Check if each set is fully present in downloads, and create a union.
1295 const DownloadSet* all_sets[] = {&active_set, &history_set,
1296 &save_page_as_downloads_};
1297 DownloadSet downloads_union;
1298 for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) {
1299 DownloadSet remainder;
1300 std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
1301 std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
1302 downloads_.begin(), downloads_.end(),
1303 insert_it);
1304 DCHECK(remainder.empty());
1305 std::insert_iterator<DownloadSet>
1306 insert_union(downloads_union, downloads_union.end());
1307 std::set_union(downloads_union.begin(), downloads_union.end(),
1308 all_sets[i]->begin(), all_sets[i]->end(),
1309 insert_union);
1310 }
1311
1312 // Is everything in downloads_ present in one of the other sets?
1313 DownloadSet remainder;
1314 std::insert_iterator<DownloadSet>
1315 insert_remainder(remainder, remainder.begin());
1316 std::set_difference(downloads_.begin(), downloads_.end(),
1317 downloads_union.begin(), downloads_union.end(),
1318 insert_remainder);
1319 DCHECK(remainder.empty());
1320 #endif
1321 } 1130 }
1322 1131
1323 // DownloadManager::OtherDownloadManagerObserver implementation ---------------- 1132 // DownloadManager::OtherDownloadManagerObserver implementation ----------------
1324 1133
1325 DownloadManager::OtherDownloadManagerObserver::OtherDownloadManagerObserver( 1134 DownloadManager::OtherDownloadManagerObserver::OtherDownloadManagerObserver(
1326 DownloadManager* observing_download_manager) 1135 DownloadManager* observing_download_manager)
1327 : observing_download_manager_(observing_download_manager), 1136 : observing_download_manager_(observing_download_manager),
1328 observed_download_manager_(NULL) { 1137 observed_download_manager_(NULL) {
1329 if (observing_download_manager->profile_->GetOriginalProfile() == 1138 if (observing_download_manager->profile_->GetOriginalProfile() ==
1330 observing_download_manager->profile_) { 1139 observing_download_manager->profile_) {
(...skipping 10 matching lines...) Expand all
1341 observed_download_manager_->RemoveObserver(this); 1150 observed_download_manager_->RemoveObserver(this);
1342 } 1151 }
1343 1152
1344 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { 1153 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() {
1345 observing_download_manager_->NotifyModelChanged(); 1154 observing_download_manager_->NotifyModelChanged();
1346 } 1155 }
1347 1156
1348 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { 1157 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() {
1349 observed_download_manager_ = NULL; 1158 observed_download_manager_ = NULL;
1350 } 1159 }
OLDNEW
« no previous file with comments | « chrome/browser/download/download_manager.h ('k') | chrome/browser/download/download_prefs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698