| 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 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 // Check writability of the suggested path. If we can't write to it, default | 470 // Check writability of the suggested path. If we can't write to it, default |
| 471 // to the user's "My Documents" directory. We'll prompt them in this case. | 471 // to the user's "My Documents" directory. We'll prompt them in this case. |
| 472 FilePath dir = info->suggested_path.DirName(); | 472 FilePath dir = info->suggested_path.DirName(); |
| 473 FilePath filename = info->suggested_path.BaseName(); | 473 FilePath filename = info->suggested_path.BaseName(); |
| 474 if (!file_util::PathIsWritable(dir)) { | 474 if (!file_util::PathIsWritable(dir)) { |
| 475 info->prompt_user_for_save_location = true; | 475 info->prompt_user_for_save_location = true; |
| 476 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); | 476 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); |
| 477 info->suggested_path = info->suggested_path.Append(filename); | 477 info->suggested_path = info->suggested_path.Append(filename); |
| 478 } | 478 } |
| 479 | 479 |
| 480 // Do not add the path uniquifier if we are saving to a specific path as in | |
| 481 // the drag-out case. | |
| 482 if (info->save_info.file_path.empty()) { | |
| 483 info->path_uniquifier = download_util::GetUniquePathNumber( | |
| 484 info->suggested_path); | |
| 485 } | |
| 486 | |
| 487 // If the download is deemed dangerous, we'll use a temporary name for it. | 480 // If the download is deemed dangerous, we'll use a temporary name for it. |
| 488 if (info->is_dangerous) { | 481 if (info->is_dangerous) { |
| 489 info->original_name = FilePath(info->suggested_path).BaseName(); | 482 info->original_name = FilePath(info->suggested_path).BaseName(); |
| 490 // Create a temporary file to hold the file until the user approves its | 483 // Create a temporary file to hold the file until the user approves its |
| 491 // download. | 484 // download. |
| 492 FilePath::StringType file_name; | 485 FilePath::StringType file_name; |
| 493 FilePath path; | 486 FilePath path; |
| 494 while (path.empty()) { | 487 while (path.empty()) { |
| 495 SStringPrintf(&file_name, FILE_PATH_LITERAL("unconfirmed %d.download"), | 488 SStringPrintf(&file_name, FILE_PATH_LITERAL("unconfirmed %d.crdownload"), |
| 496 base::RandInt(0, 100000)); | 489 base::RandInt(0, 100000)); |
| 497 path = dir.Append(file_name); | 490 path = dir.Append(file_name); |
| 498 if (file_util::PathExists(path)) | 491 if (file_util::PathExists(path)) |
| 499 path = FilePath(); | 492 path = FilePath(); |
| 500 } | 493 } |
| 501 info->suggested_path = path; | 494 info->suggested_path = path; |
| 502 } else { | 495 } else { |
| 496 // Do not add the path uniquifier if we are saving to a specific path as in |
| 497 // the drag-out case. |
| 498 if (info->save_info.file_path.empty()) { |
| 499 info->path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( |
| 500 info->suggested_path); |
| 501 } |
| 503 // We know the final path, build it if necessary. | 502 // We know the final path, build it if necessary. |
| 504 if (info->path_uniquifier > 0) { | 503 if (info->path_uniquifier > 0) { |
| 505 download_util::AppendNumberToPath(&(info->suggested_path), | 504 download_util::AppendNumberToPath(&(info->suggested_path), |
| 506 info->path_uniquifier); | 505 info->path_uniquifier); |
| 507 // Setting path_uniquifier to 0 to make sure we don't try to unique it | 506 // Setting path_uniquifier to 0 to make sure we don't try to unique it |
| 508 // later on. | 507 // later on. |
| 509 info->path_uniquifier = 0; | 508 info->path_uniquifier = 0; |
| 510 } else if (info->path_uniquifier == -1) { | 509 } else if (info->path_uniquifier == -1) { |
| 511 // We failed to find a unique path. We have to prompt the user. | 510 // We failed to find a unique path. We have to prompt the user. |
| 512 info->prompt_user_for_save_location = true; | 511 info->prompt_user_for_save_location = true; |
| 513 } | 512 } |
| 514 } | 513 } |
| 515 | 514 |
| 515 // Create an empty file at the suggested path so that we don't allocate the |
| 516 // same "non-existant" path to multiple downloads. |
| 517 // See: http://code.google.com/p/chromium/issues/detail?id=3662 |
| 516 if (!info->prompt_user_for_save_location && | 518 if (!info->prompt_user_for_save_location && |
| 517 info->save_info.file_path.empty()) { | 519 info->save_info.file_path.empty()) { |
| 518 // Create an empty file at the suggested path so that we don't allocate the | 520 if (info->is_dangerous) |
| 519 // same "non-existant" path to multiple downloads. | 521 file_util::WriteFile(info->suggested_path, "", 0); |
| 520 // See: http://code.google.com/p/chromium/issues/detail?id=3662 | 522 else |
| 521 file_util::WriteFile(info->suggested_path, "", 0); | 523 file_util::WriteFile(download_util::GetCrDownloadPath( |
| 524 info->suggested_path), "", 0); |
| 522 } | 525 } |
| 523 | 526 |
| 524 // Now we return to the UI thread. | 527 // Now we return to the UI thread. |
| 525 ChromeThread::PostTask( | 528 ChromeThread::PostTask( |
| 526 ChromeThread::UI, FROM_HERE, | 529 ChromeThread::UI, FROM_HERE, |
| 527 NewRunnableMethod(this, | 530 NewRunnableMethod(this, |
| 528 &DownloadManager::OnPathExistenceAvailable, | 531 &DownloadManager::OnPathExistenceAvailable, |
| 529 info)); | 532 info)); |
| 530 } | 533 } |
| 531 | 534 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 profile_->IsOffTheRecord(), | 587 profile_->IsOffTheRecord(), |
| 585 info->is_extension_install, | 588 info->is_extension_install, |
| 586 !info->save_info.file_path.empty()); | 589 !info->save_info.file_path.empty()); |
| 587 download->set_manager(this); | 590 download->set_manager(this); |
| 588 in_progress_[info->download_id] = download; | 591 in_progress_[info->download_id] = download; |
| 589 } else { | 592 } else { |
| 590 NOTREACHED(); // Should not exist! | 593 NOTREACHED(); // Should not exist! |
| 591 return; | 594 return; |
| 592 } | 595 } |
| 593 | 596 |
| 594 // Called before DownloadFinished in order to avoid a race condition where we | |
| 595 // attempt to open a completed download before it has been renamed. | |
| 596 ChromeThread::PostTask( | |
| 597 ChromeThread::FILE, FROM_HERE, | |
| 598 NewRunnableMethod( | |
| 599 file_manager_, &DownloadFileManager::OnFinalDownloadName, | |
| 600 download->id(), target_path, this)); | |
| 601 | |
| 602 // If the download already completed by the time we reached this point, then | |
| 603 // notify observers that it did. | |
| 604 PendingFinishedMap::iterator pending_it = | 597 PendingFinishedMap::iterator pending_it = |
| 605 pending_finished_downloads_.find(info->download_id); | 598 pending_finished_downloads_.find(info->download_id); |
| 606 if (pending_it != pending_finished_downloads_.end()) | 599 bool download_finished = (pending_it != pending_finished_downloads_.end()); |
| 600 |
| 601 if (download_finished || info->is_dangerous) { |
| 602 // The download has already finished or the download is not safe. |
| 603 // We can now rename the file to its final name (or its tentative name |
| 604 // in dangerous download cases). |
| 605 ChromeThread::PostTask( |
| 606 ChromeThread::FILE, FROM_HERE, |
| 607 NewRunnableMethod( |
| 608 file_manager_, &DownloadFileManager::OnFinalDownloadName, |
| 609 download->id(), target_path, !info->is_dangerous, this)); |
| 610 } else { |
| 611 // The download hasn't finished and it is a safe download. We need to |
| 612 // rename it to its intermediate '.crdownload' path. |
| 613 FilePath download_path = download_util::GetCrDownloadPath(target_path); |
| 614 ChromeThread::PostTask( |
| 615 ChromeThread::FILE, FROM_HERE, |
| 616 NewRunnableMethod( |
| 617 file_manager_, &DownloadFileManager::OnIntermediateDownloadName, |
| 618 download->id(), download_path, this)); |
| 619 download->set_need_final_rename(true); |
| 620 } |
| 621 |
| 622 if (download_finished) { |
| 623 // If the download already completed by the time we reached this point, then |
| 624 // notify observers that it did. |
| 607 DownloadFinished(pending_it->first, pending_it->second); | 625 DownloadFinished(pending_it->first, pending_it->second); |
| 626 } |
| 608 | 627 |
| 609 download->Rename(target_path); | 628 download->Rename(target_path); |
| 610 | 629 |
| 611 // Do not store the download in the history database for a few special cases: | 630 // Do not store the download in the history database for a few special cases: |
| 612 // - incognito mode (that is the point of this mode) | 631 // - incognito mode (that is the point of this mode) |
| 613 // - extensions (users don't think of extension installation as 'downloading') | 632 // - extensions (users don't think of extension installation as 'downloading') |
| 614 // - temporary download, like in drag-and-drop | 633 // - temporary download, like in drag-and-drop |
| 615 // We have to make sure that these handles don't collide with normal db | 634 // We have to make sure that these handles don't collide with normal db |
| 616 // handles, so we use a negative value. Eventually, they could overlap, but | 635 // handles, so we use a negative value. Eventually, they could overlap, but |
| 617 // you'd have to do enough downloading that your ISP would likely stab you in | 636 // you'd have to do enough downloading that your ISP would likely stab you in |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 // We first need to rename the downloaded file from its temporary name to | 741 // We first need to rename the downloaded file from its temporary name to |
| 723 // its final name before we can continue. | 742 // its final name before we can continue. |
| 724 ChromeThread::PostTask( | 743 ChromeThread::PostTask( |
| 725 ChromeThread::FILE, FROM_HERE, | 744 ChromeThread::FILE, FROM_HERE, |
| 726 NewRunnableMethod( | 745 NewRunnableMethod( |
| 727 this, &DownloadManager::ProceedWithFinishedDangerousDownload, | 746 this, &DownloadManager::ProceedWithFinishedDangerousDownload, |
| 728 download->db_handle(), | 747 download->db_handle(), |
| 729 download->full_path(), download->original_name())); | 748 download->full_path(), download->original_name())); |
| 730 return; | 749 return; |
| 731 } | 750 } |
| 751 |
| 752 if (download->need_final_rename()) { |
| 753 ChromeThread::PostTask( |
| 754 ChromeThread::FILE, FROM_HERE, |
| 755 NewRunnableMethod( |
| 756 file_manager_, &DownloadFileManager::OnFinalDownloadName, |
| 757 download->id(), download->full_path(), false, this)); |
| 758 return; |
| 759 } |
| 760 |
| 732 ContinueDownloadFinished(download); | 761 ContinueDownloadFinished(download); |
| 733 } | 762 } |
| 734 | 763 |
| 735 void DownloadManager::DownloadRenamedToFinalName(int download_id, | 764 void DownloadManager::DownloadRenamedToFinalName(int download_id, |
| 736 const FilePath& full_path) { | 765 const FilePath& full_path) { |
| 737 DownloadMap::iterator it = downloads_.begin(); | 766 DownloadMap::iterator it = downloads_.begin(); |
| 738 while (it != downloads_.end()) { | 767 while (it != downloads_.end()) { |
| 739 DownloadItem* download = it->second; | 768 DownloadItem* download = it->second; |
| 740 if (download->id() == download_id) { | 769 if (download->id() == download_id) { |
| 741 // The download file is meant to be completed if both the filename is | 770 // The download file is meant to be completed if both the filename is |
| 742 // finalized and the file data is downloaded. The ordering of these two | 771 // finalized and the file data is downloaded. The ordering of these two |
| 743 // actions is indeterministic. Thus, if we are still in downloading the | 772 // actions is indeterministic. Thus, if we are still in downloading the |
| 744 // file, delay the notification. | 773 // file, delay the notification. |
| 745 download->set_name_finalized(true); | 774 download->set_name_finalized(true); |
| 746 if (download->state() == DownloadItem::COMPLETE) | 775 if (download->state() == DownloadItem::COMPLETE) |
| 747 download->NotifyObserversDownloadFileCompleted(); | 776 download->NotifyObserversDownloadFileCompleted(); |
| 777 |
| 778 // This was called from DownloadFinished; continue to call |
| 779 // ContinueDownloadFinished. |
| 780 if (download->need_final_rename()) { |
| 781 download->set_need_final_rename(false); |
| 782 ContinueDownloadFinished(download); |
| 783 } |
| 748 return; | 784 return; |
| 749 } | 785 } |
| 750 it++; | 786 it++; |
| 751 } | 787 } |
| 752 } | 788 } |
| 753 | 789 |
| 754 void DownloadManager::ContinueDownloadFinished(DownloadItem* download) { | 790 void DownloadManager::ContinueDownloadFinished(DownloadItem* download) { |
| 755 // If this was a dangerous download, it has now been approved and must be | 791 // If this was a dangerous download, it has now been approved and must be |
| 756 // removed from dangerous_finished_ so it does not get deleted on shutdown. | 792 // removed from dangerous_finished_ so it does not get deleted on shutdown. |
| 757 DownloadMap::iterator it = dangerous_finished_.find(download->id()); | 793 DownloadMap::iterator it = dangerous_finished_.find(download->id()); |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 observing_download_manager_->NotifyModelChanged(); | 1634 observing_download_manager_->NotifyModelChanged(); |
| 1599 } | 1635 } |
| 1600 | 1636 |
| 1601 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( | 1637 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( |
| 1602 std::vector<DownloadItem*>& downloads) { | 1638 std::vector<DownloadItem*>& downloads) { |
| 1603 } | 1639 } |
| 1604 | 1640 |
| 1605 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1641 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1606 observed_download_manager_ = NULL; | 1642 observed_download_manager_ = NULL; |
| 1607 } | 1643 } |
| OLD | NEW |