| 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 active_downloads_.erase(download_id); |
| 578 } |
| 579 |
| 579 void DownloadManager::DownloadRenamedToFinalName(int download_id, | 580 void DownloadManager::DownloadRenamedToFinalName(int download_id, |
| 580 const FilePath& full_path) { | 581 const FilePath& full_path) { |
| 581 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id | 582 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
| 582 << " full_path = \"" << full_path.value() << "\""; | 583 << " full_path = \"" << full_path.value() << "\""; |
| 583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 584 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 584 DownloadItem* item = GetDownloadItem(download_id); | 585 DownloadItem* item = GetDownloadItem(download_id); |
| 585 if (!item) | 586 if (!item) |
| 586 return; | 587 return; |
| 587 item->OnDownloadRenamedToFinalName(full_path); | 588 item->OnDownloadRenamedToFinalName(full_path); |
| 588 } | 589 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 // name when calling GetFileNameToReportUser(). | 639 // name when calling GetFileNameToReportUser(). |
| 639 download->set_path_uniquifier(new_path_uniquifier); | 640 download->set_path_uniquifier(new_path_uniquifier); |
| 640 RenameDownload(download, new_path); | 641 RenameDownload(download, new_path); |
| 641 } | 642 } |
| 642 | 643 |
| 643 // Continue the download finished sequence. | 644 // Continue the download finished sequence. |
| 644 download->Finished(); | 645 download->Finished(); |
| 645 } | 646 } |
| 646 | 647 |
| 647 void DownloadManager::DownloadCancelled(int32 download_id) { | 648 void DownloadManager::DownloadCancelled(int32 download_id) { |
| 649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 648 DownloadMap::iterator it = in_progress_.find(download_id); | 650 DownloadMap::iterator it = in_progress_.find(download_id); |
| 649 if (it == in_progress_.end()) | 651 if (it == in_progress_.end()) |
| 650 return; | 652 return; |
| 651 DownloadItem* download = it->second; | 653 DownloadItem* download = it->second; |
| 652 | 654 |
| 653 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id | 655 VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
| 654 << " download = " << download->DebugString(true); | 656 << " download = " << download->DebugString(true); |
| 655 | 657 |
| 656 // Clean up will happen when the history system create callback runs if we | 658 // Clean up will happen when the history system create callback runs if we |
| 657 // don't have a valid db_handle yet. | 659 // don't have a valid db_handle yet. |
| 658 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { | 660 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { |
| 659 in_progress_.erase(it); | 661 in_progress_.erase(it); |
| 662 active_downloads_.erase(download_id); |
| 660 download_history_->UpdateEntry(download); | 663 download_history_->UpdateEntry(download); |
| 661 } | 664 } |
| 662 | 665 |
| 663 DownloadCancelledInternal(download_id, | 666 DownloadCancelledInternal(download_id, |
| 664 download->render_process_id(), | 667 download->render_process_id(), |
| 665 download->request_id()); | 668 download->request_id()); |
| 666 UpdateAppIcon(); | 669 UpdateAppIcon(); |
| 667 } | 670 } |
| 668 | 671 |
| 669 void DownloadManager::DownloadCancelledInternal(int download_id, | 672 void DownloadManager::DownloadCancelledInternal(int download_id, |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 } | 949 } |
| 947 NotifyModelChanged(); | 950 NotifyModelChanged(); |
| 948 } | 951 } |
| 949 | 952 |
| 950 // Once the new DownloadItem's creation info has been committed to the history | 953 // Once the new DownloadItem's creation info has been committed to the history |
| 951 // service, we associate the DownloadItem with the db handle, update our | 954 // service, we associate the DownloadItem with the db handle, update our |
| 952 // 'history_downloads_' map and inform observers. | 955 // 'history_downloads_' map and inform observers. |
| 953 void DownloadManager::OnCreateDownloadEntryComplete( | 956 void DownloadManager::OnCreateDownloadEntryComplete( |
| 954 DownloadCreateInfo info, | 957 DownloadCreateInfo info, |
| 955 int64 db_handle) { | 958 int64 db_handle) { |
| 959 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 956 DownloadMap::iterator it = in_progress_.find(info.download_id); | 960 DownloadMap::iterator it = in_progress_.find(info.download_id); |
| 957 DCHECK(it != in_progress_.end()); | 961 DCHECK(it != in_progress_.end()); |
| 958 | 962 |
| 959 DownloadItem* download = it->second; | 963 DownloadItem* download = it->second; |
| 960 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle | 964 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle |
| 961 << " download_id = " << info.download_id | 965 << " download_id = " << info.download_id |
| 962 << " download = " << download->DebugString(true); | 966 << " download = " << download->DebugString(true); |
| 963 | 967 |
| 964 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 968 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
| 965 // call this function with an invalid |db_handle|. For instance, this can | 969 // call this function with an invalid |db_handle|. For instance, this can |
| 966 // happen when the history database is offline. We cannot have multiple | 970 // happen when the history database is offline. We cannot have multiple |
| 967 // DownloadItems with the same invalid db_handle, so we need to assign a | 971 // DownloadItems with the same invalid db_handle, so we need to assign a |
| 968 // unique |db_handle| here. | 972 // unique |db_handle| here. |
| 969 if (db_handle == DownloadHistory::kUninitializedHandle) | 973 if (db_handle == DownloadHistory::kUninitializedHandle) |
| 970 db_handle = download_history_->GetNextFakeDbHandle(); | 974 db_handle = download_history_->GetNextFakeDbHandle(); |
| 971 | 975 |
| 972 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); | 976 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); |
| 973 download->set_db_handle(db_handle); | 977 download->set_db_handle(db_handle); |
| 974 | 978 |
| 975 // Insert into our full map. | 979 // Insert into our full map. |
| 976 DCHECK(history_downloads_.find(download->db_handle()) == | 980 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); |
| 977 history_downloads_.end()); | |
| 978 history_downloads_[download->db_handle()] = download; | 981 history_downloads_[download->db_handle()] = download; |
| 979 | 982 |
| 980 // Show in the appropropriate browser UI. | 983 // Show in the appropriate browser UI. |
| 981 ShowDownloadInBrowser(info, download); | 984 ShowDownloadInBrowser(info, download); |
| 982 | 985 |
| 983 // Inform interested objects about the new download. | 986 // Inform interested objects about the new download. |
| 984 NotifyModelChanged(); | 987 NotifyModelChanged(); |
| 985 | 988 |
| 986 // If this download has been completed before we've received the db handle, | 989 // If this download has been completed before we've received the db handle, |
| 987 // post one final message to the history service so that it can be properly | 990 // post one final message to the history service so that it can be properly |
| 988 // in sync with the DownloadItem's completion status, and also inform any | 991 // in sync with the DownloadItem's completion status, and also inform any |
| 989 // observers so that they get more than just the start notification. | 992 // observers so that they get more than just the start notification. |
| 990 if (download->state() != DownloadItem::IN_PROGRESS) { | 993 if (download->state() != DownloadItem::IN_PROGRESS) { |
| 991 in_progress_.erase(it); | 994 in_progress_.erase(it); |
| 995 // TODO(ahendrickson) -- We don't actually know whether or not we can |
| 996 // remove the download item from the |active_downloads_| map, as there |
| 997 // is no state in |DownloadItem::DownloadState| to indicate that the |
| 998 // downloads system is done with an item. Fix this when we have a |
| 999 // proper final state to check for. |
| 1000 active_downloads_.erase(info.download_id); |
| 992 download_history_->UpdateEntry(download); | 1001 download_history_->UpdateEntry(download); |
| 993 download->UpdateObservers(); | 1002 download->UpdateObservers(); |
| 994 } | 1003 } |
| 995 | 1004 |
| 996 UpdateAppIcon(); | 1005 UpdateAppIcon(); |
| 997 } | 1006 } |
| 998 | 1007 |
| 999 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, | 1008 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, |
| 1000 DownloadItem* download) { | 1009 DownloadItem* download) { |
| 1001 // The 'contents' may no longer exist if the user closed the tab before we | 1010 // 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... |
| 1035 } | 1044 } |
| 1036 return NULL; | 1045 return NULL; |
| 1037 } | 1046 } |
| 1038 | 1047 |
| 1039 // Confirm that everything in all maps is also in |downloads_|, and that | 1048 // Confirm that everything in all maps is also in |downloads_|, and that |
| 1040 // everything in |downloads_| is also in some other map. | 1049 // everything in |downloads_| is also in some other map. |
| 1041 void DownloadManager::AssertContainersConsistent() const { | 1050 void DownloadManager::AssertContainersConsistent() const { |
| 1042 #if !defined(NDEBUG) | 1051 #if !defined(NDEBUG) |
| 1043 // Turn everything into sets. | 1052 // Turn everything into sets. |
| 1044 DownloadSet in_progress_set, history_set; | 1053 DownloadSet in_progress_set, history_set; |
| 1045 const DownloadMap* input_maps[] = {&in_progress_, &history_downloads_}; | 1054 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; |
| 1046 DownloadSet* local_sets[] = {&in_progress_set, &history_set}; | 1055 DownloadSet* local_sets[] = {&in_progress_set, &history_set}; |
| 1047 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); | 1056 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); |
| 1048 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { | 1057 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { |
| 1049 for (DownloadMap::const_iterator it = input_maps[i]->begin(); | 1058 for (DownloadMap::const_iterator it = input_maps[i]->begin(); |
| 1050 it != input_maps[i]->end(); it++) { | 1059 it != input_maps[i]->end(); it++) { |
| 1051 local_sets[i]->insert(&*it->second); | 1060 local_sets[i]->insert(&*it->second); |
| 1052 } | 1061 } |
| 1053 } | 1062 } |
| 1054 | 1063 |
| 1055 // Check if each set is fully present in downloads, and create a union. | 1064 // 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... |
| 1102 observed_download_manager_->RemoveObserver(this); | 1111 observed_download_manager_->RemoveObserver(this); |
| 1103 } | 1112 } |
| 1104 | 1113 |
| 1105 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1114 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
| 1106 observing_download_manager_->NotifyModelChanged(); | 1115 observing_download_manager_->NotifyModelChanged(); |
| 1107 } | 1116 } |
| 1108 | 1117 |
| 1109 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1118 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1110 observed_download_manager_ = NULL; | 1119 observed_download_manager_ = NULL; |
| 1111 } | 1120 } |
| OLD | NEW |