Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 | 111 |
| 112 // At this point, all dangerous downloads have had their files removed | 112 // At this point, all dangerous downloads have had their files removed |
| 113 // and all in progress downloads have been cancelled. We can now delete | 113 // and all in progress downloads have been cancelled. We can now delete |
| 114 // anything left. | 114 // anything left. |
| 115 STLDeleteElements(&downloads_); | 115 STLDeleteElements(&downloads_); |
| 116 | 116 |
| 117 // And clear all non-owning containers. | 117 // And clear all non-owning containers. |
| 118 in_progress_.clear(); | 118 in_progress_.clear(); |
| 119 active_downloads_.clear(); | |
| 119 #if !defined(NDEBUG) | 120 #if !defined(NDEBUG) |
| 120 save_page_as_downloads_.clear(); | 121 save_page_as_downloads_.clear(); |
| 121 #endif | 122 #endif |
| 122 | 123 |
| 123 file_manager_ = NULL; | 124 file_manager_ = NULL; |
| 124 | 125 |
| 125 // Make sure the save as dialog doesn't notify us back if we're gone before | 126 // Make sure the save as dialog doesn't notify us back if we're gone before |
| 126 // it returns. | 127 // it returns. |
| 127 if (select_file_dialog_.get()) | 128 if (select_file_dialog_.get()) |
| 128 select_file_dialog_->ListenerDestroyed(); | 129 select_file_dialog_->ListenerDestroyed(); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 AttachDownloadItem(info, info->suggested_path); | 417 AttachDownloadItem(info, info->suggested_path); |
| 417 } | 418 } |
| 418 } | 419 } |
| 419 | 420 |
| 420 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { | 421 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { |
| 421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 422 | 423 |
| 423 DownloadItem* download = new DownloadItem(this, *info, | 424 DownloadItem* download = new DownloadItem(this, *info, |
| 424 profile_->IsOffTheRecord()); | 425 profile_->IsOffTheRecord()); |
| 425 DCHECK(!ContainsKey(in_progress_, info->download_id)); | 426 DCHECK(!ContainsKey(in_progress_, info->download_id)); |
| 427 DCHECK(!ContainsKey(active_downloads_, info->download_id)); | |
| 426 downloads_.insert(download); | 428 downloads_.insert(download); |
| 429 active_downloads_[info->download_id] = download; | |
| 427 } | 430 } |
| 428 | 431 |
| 429 void DownloadManager::AttachDownloadItem(DownloadCreateInfo* info, | 432 void DownloadManager::AttachDownloadItem(DownloadCreateInfo* info, |
| 430 const FilePath& target_path) { | 433 const FilePath& target_path) { |
| 431 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 432 | 435 |
| 433 scoped_ptr<DownloadCreateInfo> infop(info); | 436 scoped_ptr<DownloadCreateInfo> infop(info); |
| 434 info->path = target_path; | 437 info->path = target_path; |
| 435 | 438 |
| 436 // NOTE(ahendrickson) We will be adding a new map |active_downloads_|, into | 439 // NOTE(ahendrickson) Eventually |active_downloads_| will replace |
| 437 // which we will be adding the download as soon as it's created. This will | 440 // |in_progress_|, but we don't want to change the semantics yet. |
| 438 // make this loop unnecessary. | |
| 439 // Eventually |active_downloads_| will replace |in_progress_|, but we don't | |
| 440 // want to change the semantics yet. | |
| 441 DCHECK(!ContainsKey(in_progress_, info->download_id)); | 441 DCHECK(!ContainsKey(in_progress_, info->download_id)); |
| 442 DownloadItem* download = NULL; | 442 DCHECK(ContainsKey(active_downloads_, info->download_id)); |
| 443 for (std::set<DownloadItem*>::iterator i = downloads_.begin(); | 443 DownloadItem* download = active_downloads_[info->download_id]; |
| 444 i != downloads_.end(); ++i) { | |
| 445 DownloadItem* item = (*i); | |
| 446 if (item && (item->id() == info->download_id)) { | |
| 447 download = item; | |
| 448 break; | |
| 449 } | |
| 450 } | |
| 451 DCHECK(download != NULL); | 444 DCHECK(download != NULL); |
| 445 DCHECK(ContainsKey(downloads_, download)); | |
| 446 | |
| 452 download->SetFileCheckResults(info->path, | 447 download->SetFileCheckResults(info->path, |
| 453 info->is_dangerous, | 448 info->is_dangerous, |
| 454 info->path_uniquifier, | 449 info->path_uniquifier, |
| 455 info->prompt_user_for_save_location, | 450 info->prompt_user_for_save_location, |
| 456 info->is_extension_install, | 451 info->is_extension_install, |
| 457 info->original_name); | 452 info->original_name); |
| 458 in_progress_[info->download_id] = download; | 453 in_progress_[info->download_id] = download; |
| 459 | 454 |
| 460 bool download_finished = ContainsKey(pending_finished_downloads_, | 455 bool download_finished = ContainsKey(pending_finished_downloads_, |
| 461 info->download_id); | 456 info->download_id); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 495 pending_finished_downloads_[info->download_id]); | 490 pending_finished_downloads_[info->download_id]); |
| 496 } | 491 } |
| 497 | 492 |
| 498 download_history_->AddEntry(*info, download, | 493 download_history_->AddEntry(*info, download, |
| 499 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); | 494 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); |
| 500 | 495 |
| 501 UpdateAppIcon(); | 496 UpdateAppIcon(); |
| 502 } | 497 } |
| 503 | 498 |
| 504 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { | 499 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { |
| 505 DownloadMap::iterator it = in_progress_.find(download_id); | 500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 506 if (it != in_progress_.end()) { | 501 DownloadMap::iterator it = active_downloads_.find(download_id); |
| 502 if (it != active_downloads_.end()) { | |
| 507 DownloadItem* download = it->second; | 503 DownloadItem* download = it->second; |
| 508 download->Update(size); | 504 if (download->state() == DownloadItem::IN_PROGRESS) { |
| 509 download_history_->UpdateEntry(download); | 505 download->Update(size); |
| 506 download_history_->UpdateEntry(download); | |
| 507 } | |
| 510 } | 508 } |
| 511 UpdateAppIcon(); | 509 UpdateAppIcon(); |
| 512 } | 510 } |
| 513 | 511 |
| 514 void DownloadManager::OnAllDataSaved(int32 download_id, int64 size) { | 512 void DownloadManager::OnAllDataSaved(int32 download_id, int64 size) { |
| 515 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id | 513 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
| 516 << " size = " << size; | 514 << " size = " << size; |
| 517 DownloadMap::iterator it = in_progress_.find(download_id); | 515 DownloadMap::iterator it = in_progress_.find(download_id); |
| 518 if (it == in_progress_.end()) { | 516 if (it == in_progress_.end()) { |
| 519 // The download is done, but the user hasn't selected a final location for | 517 // The download is done, but the user hasn't selected a final location for |
| 520 // it yet (the Save As dialog box is probably still showing), so just keep | 518 // it yet (the Save As dialog box is probably still showing), so just keep |
| 521 // track of the fact that this download id is complete, when the | 519 // track of the fact that this download id is complete, when the |
| 522 // DownloadItem is constructed later we'll notify its completion then. | 520 // DownloadItem is constructed later we'll notify its completion then. |
| 523 PendingFinishedMap::iterator erase_it = | 521 DCHECK(!ContainsKey(pending_finished_downloads_, download_id)); |
| 524 pending_finished_downloads_.find(download_id); | |
| 525 DCHECK(erase_it == pending_finished_downloads_.end()); | |
| 526 pending_finished_downloads_[download_id] = size; | 522 pending_finished_downloads_[download_id] = size; |
| 527 VLOG(20) << __FUNCTION__ << "()" << " Added download_id = " << download_id | 523 VLOG(20) << __FUNCTION__ << "()" << " Added download_id = " << download_id |
| 528 << " to pending_finished_downloads_"; | 524 << " to pending_finished_downloads_"; |
| 529 return; | 525 return; |
| 530 } | 526 } |
| 531 | 527 |
| 532 // Remove the id from the list of pending ids. | 528 // Remove the id from the list of pending ids. |
| 533 PendingFinishedMap::iterator erase_it = | 529 PendingFinishedMap::iterator erase_it = |
| 534 pending_finished_downloads_.find(download_id); | 530 pending_finished_downloads_.find(download_id); |
| 535 if (erase_it != pending_finished_downloads_.end()) { | 531 if (erase_it != pending_finished_downloads_.end()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 NewRunnableMethod( | 565 NewRunnableMethod( |
| 570 this, &DownloadManager::ProceedWithFinishedDangerousDownload, | 566 this, &DownloadManager::ProceedWithFinishedDangerousDownload, |
| 571 download->db_handle(), | 567 download->db_handle(), |
| 572 download->full_path(), download->target_name())); | 568 download->full_path(), download->target_name())); |
| 573 return; | 569 return; |
| 574 } | 570 } |
| 575 | 571 |
| 576 download->OnSafeDownloadFinished(file_manager_); | 572 download->OnSafeDownloadFinished(file_manager_); |
| 577 } | 573 } |
| 578 | 574 |
| 575 void DownloadManager::RemoveFromActiveList(int32 download_id) { | |
| 576 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 577 | |
|
brettw
2011/01/10 20:49:23
I'd say just remove this blank line, it doesn't he
| |
| 578 active_downloads_.erase(download_id); | |
| 579 } | |
| 580 | |
| 579 void DownloadManager::DownloadRenamedToFinalName(int download_id, | 581 void DownloadManager::DownloadRenamedToFinalName(int download_id, |
| 580 const FilePath& full_path) { | 582 const FilePath& full_path) { |
| 581 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id | 583 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
| 582 << " full_path = \"" << full_path.value() << "\""; | 584 << " full_path = \"" << full_path.value() << "\""; |
| 583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 585 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 584 DownloadItem* item = GetDownloadItem(download_id); | 586 DownloadItem* item = GetDownloadItem(download_id); |
| 585 if (!item) | 587 if (!item) |
| 586 return; | 588 return; |
| 587 item->OnDownloadRenamedToFinalName(full_path); | 589 item->OnDownloadRenamedToFinalName(full_path); |
| 588 } | 590 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 // name when calling GetFileNameToReportUser(). | 640 // name when calling GetFileNameToReportUser(). |
| 639 download->set_path_uniquifier(new_path_uniquifier); | 641 download->set_path_uniquifier(new_path_uniquifier); |
| 640 RenameDownload(download, new_path); | 642 RenameDownload(download, new_path); |
| 641 } | 643 } |
| 642 | 644 |
| 643 // Continue the download finished sequence. | 645 // Continue the download finished sequence. |
| 644 download->Finished(); | 646 download->Finished(); |
| 645 } | 647 } |
| 646 | 648 |
| 647 void DownloadManager::DownloadCancelled(int32 download_id) { | 649 void DownloadManager::DownloadCancelled(int32 download_id) { |
| 650 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 648 DownloadMap::iterator it = in_progress_.find(download_id); | 651 DownloadMap::iterator it = in_progress_.find(download_id); |
| 649 if (it == in_progress_.end()) | 652 if (it == in_progress_.end()) |
| 650 return; | 653 return; |
| 651 DownloadItem* download = it->second; | 654 DownloadItem* download = it->second; |
| 652 | 655 |
| 653 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id | 656 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
| 654 << " download = " << download->DebugString(true); | 657 << " download = " << download->DebugString(true); |
| 655 | 658 |
| 656 // Clean up will happen when the history system create callback runs if we | 659 // Clean up will happen when the history system create callback runs if we |
| 657 // don't have a valid db_handle yet. | 660 // don't have a valid db_handle yet. |
| 658 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { | 661 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { |
| 659 in_progress_.erase(it); | 662 in_progress_.erase(it); |
| 663 active_downloads_.erase(download_id); | |
| 660 download_history_->UpdateEntry(download); | 664 download_history_->UpdateEntry(download); |
| 661 } | 665 } |
| 662 | 666 |
| 663 DownloadCancelledInternal(download_id, | 667 DownloadCancelledInternal(download_id, |
| 664 download->render_process_id(), | 668 download->render_process_id(), |
| 665 download->request_id()); | 669 download->request_id()); |
| 666 UpdateAppIcon(); | 670 UpdateAppIcon(); |
| 667 } | 671 } |
| 668 | 672 |
| 669 void DownloadManager::DownloadCancelledInternal(int download_id, | 673 void DownloadManager::DownloadCancelledInternal(int download_id, |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 948 } | 952 } |
| 949 NotifyModelChanged(); | 953 NotifyModelChanged(); |
| 950 } | 954 } |
| 951 | 955 |
| 952 // Once the new DownloadItem's creation info has been committed to the history | 956 // Once the new DownloadItem's creation info has been committed to the history |
| 953 // service, we associate the DownloadItem with the db handle, update our | 957 // service, we associate the DownloadItem with the db handle, update our |
| 954 // 'history_downloads_' map and inform observers. | 958 // 'history_downloads_' map and inform observers. |
| 955 void DownloadManager::OnCreateDownloadEntryComplete( | 959 void DownloadManager::OnCreateDownloadEntryComplete( |
| 956 DownloadCreateInfo info, | 960 DownloadCreateInfo info, |
| 957 int64 db_handle) { | 961 int64 db_handle) { |
| 962 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 958 DownloadMap::iterator it = in_progress_.find(info.download_id); | 963 DownloadMap::iterator it = in_progress_.find(info.download_id); |
| 959 DCHECK(it != in_progress_.end()); | 964 DCHECK(it != in_progress_.end()); |
| 960 | 965 |
| 961 DownloadItem* download = it->second; | 966 DownloadItem* download = it->second; |
| 962 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle | 967 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle |
| 963 << " download_id = " << info.download_id | 968 << " download_id = " << info.download_id |
| 964 << " download = " << download->DebugString(true); | 969 << " download = " << download->DebugString(true); |
| 965 | 970 |
| 966 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 971 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
| 967 // call this function with an invalid |db_handle|. For instance, this can | 972 // call this function with an invalid |db_handle|. For instance, this can |
| 968 // happen when the history database is offline. We cannot have multiple | 973 // happen when the history database is offline. We cannot have multiple |
| 969 // DownloadItems with the same invalid db_handle, so we need to assign a | 974 // DownloadItems with the same invalid db_handle, so we need to assign a |
| 970 // unique |db_handle| here. | 975 // unique |db_handle| here. |
| 971 if (db_handle == DownloadHistory::kUninitializedHandle) | 976 if (db_handle == DownloadHistory::kUninitializedHandle) |
| 972 db_handle = download_history_->GetNextFakeDbHandle(); | 977 db_handle = download_history_->GetNextFakeDbHandle(); |
| 973 | 978 |
| 974 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); | 979 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); |
| 975 download->set_db_handle(db_handle); | 980 download->set_db_handle(db_handle); |
| 976 | 981 |
| 977 // Insert into our full map. | 982 // Insert into our full map. |
| 978 DCHECK(history_downloads_.find(download->db_handle()) == | 983 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); |
| 979 history_downloads_.end()); | |
| 980 history_downloads_[download->db_handle()] = download; | 984 history_downloads_[download->db_handle()] = download; |
| 981 | 985 |
| 982 // Show in the appropropriate browser UI. | 986 // Show in the appropriate browser UI. |
| 983 ShowDownloadInBrowser(info, download); | 987 ShowDownloadInBrowser(info, download); |
| 984 | 988 |
| 985 // Inform interested objects about the new download. | 989 // Inform interested objects about the new download. |
| 986 NotifyModelChanged(); | 990 NotifyModelChanged(); |
| 987 | 991 |
| 988 // If this download has been completed before we've received the db handle, | 992 // If this download has been completed before we've received the db handle, |
| 989 // post one final message to the history service so that it can be properly | 993 // post one final message to the history service so that it can be properly |
| 990 // in sync with the DownloadItem's completion status, and also inform any | 994 // in sync with the DownloadItem's completion status, and also inform any |
| 991 // observers so that they get more than just the start notification. | 995 // observers so that they get more than just the start notification. |
| 992 if (download->state() != DownloadItem::IN_PROGRESS) { | 996 if (download->state() != DownloadItem::IN_PROGRESS) { |
| 993 in_progress_.erase(it); | 997 in_progress_.erase(it); |
| 998 // TODO(ahendrickson) -- We don't actually know whether or not we can | |
| 999 // remove the download item from the |active_downloads_| map, as there | |
| 1000 // is no state in |DownloadItem::DownloadState| to indicate that the | |
| 1001 // downloads system is done with an item. Fix this when we have a | |
| 1002 // proper final state to check for. | |
| 1003 active_downloads_.erase(info.download_id); | |
| 994 download_history_->UpdateEntry(download); | 1004 download_history_->UpdateEntry(download); |
| 995 download->UpdateObservers(); | 1005 download->UpdateObservers(); |
| 996 } | 1006 } |
| 997 | 1007 |
| 998 UpdateAppIcon(); | 1008 UpdateAppIcon(); |
| 999 } | 1009 } |
| 1000 | 1010 |
| 1001 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, | 1011 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, |
| 1002 DownloadItem* download) { | 1012 DownloadItem* download) { |
| 1003 // The 'contents' may no longer exist if the user closed the tab before we | 1013 // The 'contents' may no longer exist if the user closed the tab before we |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1037 } | 1047 } |
| 1038 return NULL; | 1048 return NULL; |
| 1039 } | 1049 } |
| 1040 | 1050 |
| 1041 // Confirm that everything in all maps is also in |downloads_|, and that | 1051 // Confirm that everything in all maps is also in |downloads_|, and that |
| 1042 // everything in |downloads_| is also in some other map. | 1052 // everything in |downloads_| is also in some other map. |
| 1043 void DownloadManager::AssertContainersConsistent() const { | 1053 void DownloadManager::AssertContainersConsistent() const { |
| 1044 #if !defined(NDEBUG) | 1054 #if !defined(NDEBUG) |
| 1045 // Turn everything into sets. | 1055 // Turn everything into sets. |
| 1046 DownloadSet in_progress_set, history_set; | 1056 DownloadSet in_progress_set, history_set; |
| 1047 const DownloadMap* input_maps[] = {&in_progress_, &history_downloads_}; | 1057 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; |
| 1048 DownloadSet* local_sets[] = {&in_progress_set, &history_set}; | 1058 DownloadSet* local_sets[] = {&in_progress_set, &history_set}; |
| 1049 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); | 1059 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); |
| 1050 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { | 1060 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { |
| 1051 for (DownloadMap::const_iterator it = input_maps[i]->begin(); | 1061 for (DownloadMap::const_iterator it = input_maps[i]->begin(); |
| 1052 it != input_maps[i]->end(); it++) { | 1062 it != input_maps[i]->end(); it++) { |
| 1053 local_sets[i]->insert(&*it->second); | 1063 local_sets[i]->insert(&*it->second); |
| 1054 } | 1064 } |
| 1055 } | 1065 } |
| 1056 | 1066 |
| 1057 // Check if each set is fully present in downloads, and create a union. | 1067 // Check if each set is fully present in downloads, and create a union. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1104 observed_download_manager_->RemoveObserver(this); | 1114 observed_download_manager_->RemoveObserver(this); |
| 1105 } | 1115 } |
| 1106 | 1116 |
| 1107 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1117 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
| 1108 observing_download_manager_->NotifyModelChanged(); | 1118 observing_download_manager_->NotifyModelChanged(); |
| 1109 } | 1119 } |
| 1110 | 1120 |
| 1111 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1121 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1112 observed_download_manager_ = NULL; | 1122 observed_download_manager_ = NULL; |
| 1113 } | 1123 } |
| OLD | NEW |