| 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 <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/string_util.h" | 7 #include "base/string_util.h" |
| 8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
| 9 #include "chrome/browser/chrome_thread.h" | 9 #include "chrome/browser/chrome_thread.h" |
| 10 #include "chrome/browser/download/download_file.h" |
| 11 #include "chrome/browser/download/download_file_manager.h" |
| 10 #include "chrome/browser/download/download_manager.h" | 12 #include "chrome/browser/download/download_manager.h" |
| 13 #include "chrome/browser/download/download_util.h" |
| 11 #include "chrome/browser/history/download_types.h" | 14 #include "chrome/browser/history/download_types.h" |
| 12 #include "chrome/common/pref_names.h" | 15 #include "chrome/common/pref_names.h" |
| 13 #include "chrome/test/testing_profile.h" | 16 #include "chrome/test/testing_profile.h" |
| 17 #include "testing/gmock/include/gmock/gmock.h" |
| 18 #include "testing/gmock_mutant.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 20 |
| 16 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 21 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 17 #include <locale.h> | 22 #include <locale.h> |
| 18 #endif | 23 #endif |
| 19 | 24 |
| 20 #if defined(OS_WIN) | 25 #if defined(OS_WIN) |
| 21 #define JPEG_EXT L".jpg" | 26 #define JPEG_EXT L".jpg" |
| 22 #define HTML_EXT L".htm" | 27 #define HTML_EXT L".htm" |
| 23 #define TXT_EXT L".txt" | 28 #define TXT_EXT L".txt" |
| 24 #define TAR_EXT L".tar" | 29 #define TAR_EXT L".tar" |
| 25 #elif defined(OS_MACOSX) | 30 #elif defined(OS_MACOSX) |
| 26 #define JPEG_EXT L".jpeg" | 31 #define JPEG_EXT L".jpeg" |
| 27 #define HTML_EXT L".html" | 32 #define HTML_EXT L".html" |
| 28 #define TXT_EXT L".txt" | 33 #define TXT_EXT L".txt" |
| 29 #define TAR_EXT L".tar" | 34 #define TAR_EXT L".tar" |
| 30 #else | 35 #else |
| 31 #define JPEG_EXT L".jpg" | 36 #define JPEG_EXT L".jpg" |
| 32 #define HTML_EXT L".html" | 37 #define HTML_EXT L".html" |
| 33 #define TXT_EXT L".txt" | 38 #define TXT_EXT L".txt" |
| 34 #define TAR_EXT L".tar" | 39 #define TAR_EXT L".tar" |
| 35 #endif | 40 #endif |
| 36 | 41 |
| 42 class MockDownloadManager : public DownloadManager { |
| 43 public: |
| 44 // Override some functions. |
| 45 virtual void UpdateAppIcon() { } |
| 46 virtual void UpdateHistoryForDownload(DownloadItem*) { } |
| 47 virtual void ContinueDownloadFinished(DownloadItem*) { } |
| 48 }; |
| 49 |
| 37 class DownloadManagerTest : public testing::Test { | 50 class DownloadManagerTest : public testing::Test { |
| 38 public: | 51 public: |
| 39 DownloadManagerTest() | 52 DownloadManagerTest() |
| 40 : profile_(new TestingProfile()), | 53 : profile_(new TestingProfile()), |
| 41 download_manager_(new DownloadManager()), | 54 download_manager_(new MockDownloadManager()), |
| 42 ui_thread_(ChromeThread::UI, &message_loop_) { | 55 ui_thread_(ChromeThread::UI, &message_loop_) { |
| 43 download_manager_->Init(profile_.get()); | 56 download_manager_->Init(profile_.get()); |
| 44 } | 57 } |
| 45 | 58 |
| 46 ~DownloadManagerTest() { | 59 ~DownloadManagerTest() { |
| 47 // profile_ must outlive download_manager_, so we explicitly delete | 60 // profile_ must outlive download_manager_, so we explicitly delete |
| 48 // download_manager_ first. | 61 // download_manager_ first. |
| 49 download_manager_.release(); | 62 download_manager_.release(); |
| 50 } | 63 } |
| 51 | 64 |
| 52 void GetGeneratedFilename(const std::string& content_disposition, | 65 void GetGeneratedFilename(const std::string& content_disposition, |
| 53 const std::string& url, | 66 const std::string& url, |
| 54 const std::string& mime_type, | 67 const std::string& mime_type, |
| 55 const std::string& referrer_charset, | 68 const std::string& referrer_charset, |
| 56 std::wstring* generated_name_string) { | 69 std::wstring* generated_name_string) { |
| 57 DownloadCreateInfo info; | 70 DownloadCreateInfo info; |
| 58 info.content_disposition = content_disposition; | 71 info.content_disposition = content_disposition; |
| 59 info.url = GURL(url); | 72 info.url = GURL(url); |
| 60 info.mime_type = mime_type; | 73 info.mime_type = mime_type; |
| 61 info.referrer_charset = referrer_charset; | 74 info.referrer_charset = referrer_charset; |
| 62 FilePath generated_name; | 75 FilePath generated_name; |
| 63 DownloadManager::GenerateFileNameFromInfo(&info, &generated_name); | 76 DownloadManager::GenerateFileNameFromInfo(&info, &generated_name); |
| 64 *generated_name_string = generated_name.ToWStringHack(); | 77 *generated_name_string = generated_name.ToWStringHack(); |
| 65 } | 78 } |
| 66 | 79 |
| 80 void AddDownloadToFileManager(int id, DownloadFile* download) { |
| 81 file_manager()->downloads_[id] = download; |
| 82 } |
| 83 |
| 67 protected: | 84 protected: |
| 68 scoped_ptr<TestingProfile> profile_; | 85 scoped_ptr<TestingProfile> profile_; |
| 69 scoped_refptr<DownloadManager> download_manager_; | 86 scoped_refptr<DownloadManager> download_manager_; |
| 87 scoped_refptr<DownloadFileManager> file_manager_; |
| 70 MessageLoopForUI message_loop_; | 88 MessageLoopForUI message_loop_; |
| 71 ChromeThread ui_thread_; | 89 ChromeThread ui_thread_; |
| 72 | 90 |
| 91 DownloadFileManager* file_manager() { |
| 92 if (!file_manager_) { |
| 93 file_manager_ = new DownloadFileManager(NULL); |
| 94 download_manager_->file_manager_ = file_manager_; |
| 95 } |
| 96 return file_manager_; |
| 97 } |
| 98 |
| 73 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest); | 99 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest); |
| 74 }; | 100 }; |
| 75 | 101 |
| 76 namespace { | 102 namespace { |
| 77 | 103 |
| 78 const struct { | 104 const struct { |
| 79 const char* disposition; | 105 const char* disposition; |
| 80 const char* url; | 106 const char* url; |
| 81 const char* mime_type; | 107 const char* mime_type; |
| 82 const wchar_t* expected_name; | 108 const wchar_t* expected_name; |
| (...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 info.prompt_user_for_save_location = kStartDownloadCases[i].save_as; | 714 info.prompt_user_for_save_location = kStartDownloadCases[i].save_as; |
| 689 info.url = GURL(kStartDownloadCases[i].url); | 715 info.url = GURL(kStartDownloadCases[i].url); |
| 690 info.mime_type = kStartDownloadCases[i].mime_type; | 716 info.mime_type = kStartDownloadCases[i].mime_type; |
| 691 | 717 |
| 692 download_manager_->StartDownload(&info); | 718 download_manager_->StartDownload(&info); |
| 693 | 719 |
| 694 EXPECT_EQ(kStartDownloadCases[i].expected_save_as, | 720 EXPECT_EQ(kStartDownloadCases[i].expected_save_as, |
| 695 info.prompt_user_for_save_location); | 721 info.prompt_user_for_save_location); |
| 696 } | 722 } |
| 697 } | 723 } |
| 724 |
| 725 namespace { |
| 726 |
| 727 const struct { |
| 728 FilePath::StringType suggested_path; |
| 729 bool is_dangerous; |
| 730 bool finish_before_rename; |
| 731 bool will_delete_crdownload; |
| 732 int expected_rename_count; |
| 733 } kDownloadRenameCases[] = { |
| 734 // Safe download, download finishes BEFORE rename. |
| 735 // Needs to be renamed only once. Crdownload file needs to be deleted. |
| 736 { FILE_PATH_LITERAL("foo.zip"), |
| 737 false, |
| 738 true, |
| 739 true, |
| 740 1, }, |
| 741 // Dangerous download, download finishes BEFORE rename. |
| 742 // Needs to be renamed only once. |
| 743 { FILE_PATH_LITERAL("unconfirmed xxx.crdownload"), |
| 744 true, |
| 745 true, |
| 746 false, |
| 747 1, }, |
| 748 // Safe download, download finishes AFTER rename. |
| 749 // Needs to be renamed twice. |
| 750 { FILE_PATH_LITERAL("foo.zip"), |
| 751 false, |
| 752 false, |
| 753 false, |
| 754 2, }, |
| 755 // Dangerous download, download finishes AFTER rename. |
| 756 // Needs to be renamed only once. |
| 757 { FILE_PATH_LITERAL("unconfirmed xxx.crdownload"), |
| 758 true, |
| 759 false, |
| 760 false, |
| 761 1, }, |
| 762 }; |
| 763 |
| 764 class MockDownloadFile : public DownloadFile { |
| 765 public: |
| 766 MockDownloadFile(DownloadCreateInfo* info) |
| 767 : DownloadFile(info), renamed_count_(0) { } |
| 768 virtual ~MockDownloadFile() { Destructed(); } |
| 769 MOCK_METHOD2(Rename, bool(const FilePath&, bool)); |
| 770 MOCK_METHOD0(DeleteCrDownload, void()); |
| 771 MOCK_METHOD0(Destructed, void()); |
| 772 |
| 773 bool TestMultipleRename( |
| 774 int expected_count, bool expected_final, const FilePath& expected, |
| 775 const FilePath& path, bool is_final_rename) { |
| 776 ++renamed_count_; |
| 777 EXPECT_EQ(expected_count, renamed_count_); |
| 778 EXPECT_EQ(expected_final, is_final_rename); |
| 779 EXPECT_EQ(expected.value(), path.value()); |
| 780 return true; |
| 781 } |
| 782 |
| 783 private: |
| 784 int renamed_count_; |
| 785 }; |
| 786 |
| 787 } // namespace |
| 788 |
| 789 TEST_F(DownloadManagerTest, DownloadRenameTest) { |
| 790 using ::testing::_; |
| 791 using ::testing::CreateFunctor; |
| 792 using ::testing::Invoke; |
| 793 using ::testing::Return; |
| 794 |
| 795 ChromeThread file_thread(ChromeThread::FILE, &message_loop_); |
| 796 |
| 797 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadRenameCases); ++i) { |
| 798 // |info| will be destroyed in download_manager_. |
| 799 DownloadCreateInfo* info(new DownloadCreateInfo); |
| 800 info->download_id = static_cast<int>(i); |
| 801 info->prompt_user_for_save_location = false; |
| 802 info->is_dangerous = kDownloadRenameCases[i].is_dangerous; |
| 803 FilePath new_path(kDownloadRenameCases[i].suggested_path); |
| 804 |
| 805 MockDownloadFile* download(new MockDownloadFile(info)); |
| 806 AddDownloadToFileManager(info->download_id, download); |
| 807 |
| 808 // |download| is owned by DownloadFileManager. |
| 809 ::testing::Mock::AllowLeak(download); |
| 810 EXPECT_CALL(*download, Destructed()).Times(1); |
| 811 |
| 812 if (kDownloadRenameCases[i].expected_rename_count == 1) { |
| 813 EXPECT_CALL(*download, Rename(new_path, true)).WillOnce(Return(true)); |
| 814 } else { |
| 815 ASSERT_EQ(2, kDownloadRenameCases[i].expected_rename_count); |
| 816 FilePath crdownload(download_util::GetCrDownloadPath(new_path)); |
| 817 EXPECT_CALL(*download, Rename(_, _)) |
| 818 .WillOnce(testing::WithArgs<0, 1>(Invoke(CreateFunctor( |
| 819 download, &MockDownloadFile::TestMultipleRename, |
| 820 1, false, crdownload)))) |
| 821 .WillOnce(testing::WithArgs<0, 1>(Invoke(CreateFunctor( |
| 822 download, &MockDownloadFile::TestMultipleRename, |
| 823 2, true, new_path)))); |
| 824 } |
| 825 |
| 826 if (kDownloadRenameCases[i].will_delete_crdownload) |
| 827 EXPECT_CALL(*download, DeleteCrDownload()).Times(1); |
| 828 |
| 829 if (kDownloadRenameCases[i].finish_before_rename) { |
| 830 download_manager_->DownloadFinished(i, 1024); |
| 831 download_manager_->FileSelected(new_path, i, info); |
| 832 } else { |
| 833 download_manager_->FileSelected(new_path, i, info); |
| 834 download_manager_->DownloadFinished(i, 1024); |
| 835 } |
| 836 |
| 837 message_loop_.RunAllPending(); |
| 838 } |
| 839 } |
| OLD | NEW |