Chromium Code Reviews| Index: chrome/browser/download/chrome_download_manager_delegate_unittest.cc |
| diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc |
| index 66172cb15c4cb3579de298534d72d3498620aa5d..fa70edcff44efc88057e292d349662f8c6bc6ee4 100644 |
| --- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc |
| +++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc |
| @@ -5,10 +5,13 @@ |
| #include <stddef.h> |
| #include <stdint.h> |
| +#include <string> |
| + |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/location.h" |
| +#include "base/memory/ptr_util.h" |
| #include "base/run_loop.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| @@ -17,6 +20,7 @@ |
| #include "chrome/browser/download/download_item_model.h" |
| #include "chrome/browser/download/download_prefs.h" |
| #include "chrome/browser/download/download_target_info.h" |
| +#include "chrome/common/features.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| #include "chrome/test/base/testing_profile.h" |
| @@ -36,10 +40,17 @@ |
| #include "chrome/browser/safe_browsing/download_protection_service.h" |
| #endif |
| -#if !defined(OS_ANDROID) |
| +#if defined(ENABLE_PLUGINS) |
| #include "content/public/browser/plugin_service.h" |
| #endif |
| +#if BUILDFLAG(ANDROID_JAVA_UI) |
| +#include "chrome/browser/infobars/infobar_service.h" |
| +#include "components/infobars/core/infobar.h" |
| +#include "components/infobars/core/infobar_delegate.h" |
| +#include "components/infobars/core/infobar_manager.h" |
| +#endif |
| + |
| using ::testing::AtMost; |
| using ::testing::Invoke; |
| using ::testing::Ref; |
| @@ -83,6 +94,18 @@ ACTION_P2(ScheduleCallback2, result0, result1) { |
| FROM_HERE, base::Bind(arg0, result0, result1)); |
| } |
| +// Struct for holding the result of calling DetermineDownloadTarget. |
| +struct DetermineDownloadTargetResult { |
| + base::FilePath target_path; |
| + content::DownloadItem::TargetDisposition disposition = |
| + content::DownloadItem::TARGET_DISPOSITION_OVERWRITE; |
| + content::DownloadDangerType danger_type = |
| + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS; |
| + base::FilePath intermediate_path; |
| + content::DownloadInterruptReason interrupt_reason = |
| + content::DOWNLOAD_INTERRUPT_REASON_NONE; |
| +}; |
| + |
| // Subclass of the ChromeDownloadManagerDelegate that uses a mock |
| // DownloadProtectionService. |
| class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { |
| @@ -93,6 +116,10 @@ class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { |
| .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); |
| ON_CALL(*this, GetDownloadProtectionService()) |
| .WillByDefault(Return(nullptr)); |
| + ON_CALL(*this, MockReserveVirtualPath(_, _, _, _, _)) |
| + .WillByDefault(::testing::DoAll( |
| + ::testing::SetArgPointee<4>(DownloadTargetResult::SUCCESS), |
| + ::testing::ReturnArg<1>())); |
| } |
| ~TestChromeDownloadManagerDelegate() override {} |
| @@ -111,22 +138,20 @@ class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { |
| DownloadPathReservationTracker::FilenameConflictAction conflict_action, |
| const DownloadPathReservationTracker::ReservedPathCallback& callback) |
| override { |
| - // Pretend the path reservation succeeded without any change to |
| - // |target_path|. |
| + DownloadTargetResult result = DownloadTargetResult::SUCCESS; |
| + base::FilePath path_to_return = MockReserveVirtualPath( |
| + download, virtual_path, create_directory, conflict_action, &result); |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| - FROM_HERE, base::Bind(callback, virtual_path, true)); |
| + FROM_HERE, base::Bind(callback, path_to_return, result)); |
| } |
| - void PromptUserForDownloadPath( |
| - DownloadItem* download, |
| - const base::FilePath& suggested_path, |
| - const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) |
| - override { |
| - base::FilePath return_path = MockPromptUserForDownloadPath(download, |
| - suggested_path, |
| - callback); |
| - callback.Run(return_path); |
| - } |
| + MOCK_METHOD5( |
| + MockReserveVirtualPath, |
| + base::FilePath(content::DownloadItem*, |
| + const base::FilePath&, |
| + bool, |
| + DownloadPathReservationTracker::FilenameConflictAction, |
| + DownloadTargetResult*)); |
| void CheckDownloadUrl(DownloadItem* download, |
| const base::FilePath& virtual_path, |
| @@ -137,21 +162,31 @@ class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { |
| MOCK_METHOD0(GetDownloadProtectionService, |
| safe_browsing::DownloadProtectionService*()); |
| - MOCK_METHOD3( |
| - MockPromptUserForDownloadPath, |
| - base::FilePath( |
| - DownloadItem*, |
| - const base::FilePath&, |
| - const DownloadTargetDeterminerDelegate::FileSelectedCallback&)); |
| + MOCK_METHOD4( |
| + RequestConfirmation, |
| + void(DownloadItem*, |
| + const base::FilePath&, |
| + DownloadConfirmationReason, |
| + const DownloadTargetDeterminerDelegate::FileSelectedCallback&)); |
| MOCK_METHOD2(MockCheckDownloadUrl, |
| content::DownloadDangerType(DownloadItem*, |
| const base::FilePath&)); |
| + |
| + void RequestConfirmationConcrete( |
| + DownloadItem* download_item, |
| + const base::FilePath& path, |
| + DownloadConfirmationReason reason, |
| + const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) { |
| + ChromeDownloadManagerDelegate::RequestConfirmation(download_item, path, |
| + reason, callback); |
| + } |
| }; |
| class ChromeDownloadManagerDelegateTest |
| : public ChromeRenderViewHostTestHarness { |
| public: |
| + // Result of calling DetermineDownloadTarget. |
| ChromeDownloadManagerDelegateTest(); |
| // ::testing::Test |
| @@ -174,7 +209,7 @@ class ChromeDownloadManagerDelegateTest |
| void SetDefaultDownloadPath(const base::FilePath& path); |
| void DetermineDownloadTarget(DownloadItem* download, |
| - DownloadTargetInfo* result); |
| + DetermineDownloadTargetResult* result); |
| // Invokes ChromeDownloadManagerDelegate::CheckForFileExistence and waits for |
| // the asynchronous callback. The result passed into |
| @@ -203,7 +238,9 @@ void ChromeDownloadManagerDelegateTest::SetUp() { |
| ChromeRenderViewHostTestHarness::SetUp(); |
| CHECK(profile()); |
| - delegate_.reset(new TestChromeDownloadManagerDelegate(profile())); |
| + delegate_ = |
| + base::MakeUnique<::testing::NiceMock<TestChromeDownloadManagerDelegate>>( |
| + profile()); |
| delegate_->SetDownloadManager(download_manager_.get()); |
| pref_service_ = profile()->GetTestingPrefService(); |
| web_contents()->SetDelegate(&web_contents_delegate_); |
| @@ -274,22 +311,25 @@ void ChromeDownloadManagerDelegateTest::SetDefaultDownloadPath( |
| pref_service_->SetFilePath(prefs::kSaveFileDefaultDirectory, path); |
| } |
| -void StoreDownloadTargetInfo(const base::Closure& closure, |
| - DownloadTargetInfo* target_info, |
| - const base::FilePath& target_path, |
| - DownloadItem::TargetDisposition target_disposition, |
| - content::DownloadDangerType danger_type, |
| - const base::FilePath& intermediate_path) { |
| - target_info->target_path = target_path; |
| - target_info->target_disposition = target_disposition; |
| - target_info->danger_type = danger_type; |
| - target_info->intermediate_path = intermediate_path; |
| +void StoreDownloadTargetInfo( |
| + const base::Closure& closure, |
| + DetermineDownloadTargetResult* result, |
| + const base::FilePath& target_path, |
| + DownloadItem::TargetDisposition target_disposition, |
| + content::DownloadDangerType danger_type, |
| + const base::FilePath& intermediate_path, |
| + content::DownloadInterruptReason interrupt_reason) { |
| + result->target_path = target_path; |
| + result->disposition = target_disposition; |
| + result->danger_type = danger_type; |
| + result->intermediate_path = intermediate_path; |
| + result->interrupt_reason = interrupt_reason; |
| closure.Run(); |
| } |
| void ChromeDownloadManagerDelegateTest::DetermineDownloadTarget( |
| DownloadItem* download_item, |
| - DownloadTargetInfo* result) { |
| + DetermineDownloadTargetResult* result) { |
| base::RunLoop loop_runner; |
| delegate()->DetermineDownloadTarget( |
| download_item, |
| @@ -336,9 +376,7 @@ DownloadPrefs* ChromeDownloadManagerDelegateTest::download_prefs() { |
| } // namespace |
| -// There is no "save as" context menu option on Android. |
| -#if !BUILDFLAG(ANDROID_JAVA_UI) |
| -TEST_F(ChromeDownloadManagerDelegateTest, StartDownload_LastSavePath) { |
| +TEST_F(ChromeDownloadManagerDelegateTest, LastSavePath) { |
| GURL download_url("http://example.com/foo.txt"); |
| std::unique_ptr<content::MockDownloadItem> save_as_download = |
| @@ -362,27 +400,27 @@ TEST_F(ChromeDownloadManagerDelegateTest, StartDownload_LastSavePath) { |
| { |
| // When the prompt is displayed for the first download, the user selects a |
| // path in a different directory. |
| - DownloadTargetInfo result; |
| + DetermineDownloadTargetResult result; |
| base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt")); |
| base::FilePath user_selected_path(GetPathInDownloadDir("bar/baz.txt")); |
| - EXPECT_CALL(*delegate(), |
| - MockPromptUserForDownloadPath(save_as_download.get(), |
| - expected_prompt_path, _)) |
| - .WillOnce(Return(user_selected_path)); |
| + EXPECT_CALL(*delegate(), RequestConfirmation(save_as_download.get(), |
| + expected_prompt_path, _, _)) |
| + .WillOnce(WithArg<3>(ScheduleCallback2( |
| + DownloadConfirmationResult::CONFIRMED, user_selected_path))); |
| DetermineDownloadTarget(save_as_download.get(), &result); |
| EXPECT_EQ(user_selected_path, result.target_path); |
| VerifyAndClearExpectations(); |
| } |
| { |
| - // The prompt path for the second download is the user selected directroy |
| + // The prompt path for the second download is the user selected directory |
| // from the previous download. |
| - DownloadTargetInfo result; |
| + DetermineDownloadTargetResult result; |
| base::FilePath expected_prompt_path(GetPathInDownloadDir("bar/foo.txt")); |
| - EXPECT_CALL(*delegate(), |
| - MockPromptUserForDownloadPath(save_as_download.get(), |
| - expected_prompt_path, _)) |
| - .WillOnce(Return(base::FilePath())); |
| + EXPECT_CALL(*delegate(), RequestConfirmation(save_as_download.get(), |
| + expected_prompt_path, _, _)) |
| + .WillOnce(WithArg<3>(ScheduleCallback2( |
| + DownloadConfirmationResult::CANCELED, base::FilePath()))); |
| DetermineDownloadTarget(save_as_download.get(), &result); |
| VerifyAndClearExpectations(); |
| } |
| @@ -390,7 +428,7 @@ TEST_F(ChromeDownloadManagerDelegateTest, StartDownload_LastSavePath) { |
| { |
| // Start an automatic download. This one should get the default download |
| // path since the last download path only affects Save As downloads. |
| - DownloadTargetInfo result; |
| + DetermineDownloadTargetResult result; |
| base::FilePath expected_path(GetPathInDownloadDir("foo.txt")); |
| DetermineDownloadTarget(automatic_download.get(), &result); |
| EXPECT_EQ(expected_path, result.target_path); |
| @@ -400,20 +438,50 @@ TEST_F(ChromeDownloadManagerDelegateTest, StartDownload_LastSavePath) { |
| { |
| // The prompt path for the next download should be the default. |
| download_prefs()->SetSaveFilePath(download_prefs()->DownloadPath()); |
| - DownloadTargetInfo result; |
| + DetermineDownloadTargetResult result; |
| base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt")); |
| - EXPECT_CALL(*delegate(), |
| - MockPromptUserForDownloadPath(save_as_download.get(), |
| - expected_prompt_path, _)) |
| - .WillOnce(Return(base::FilePath())); |
| + EXPECT_CALL(*delegate(), RequestConfirmation(save_as_download.get(), |
| + expected_prompt_path, _, _)) |
| + .WillOnce(WithArg<3>(ScheduleCallback2( |
| + DownloadConfirmationResult::CANCELED, base::FilePath()))); |
| DetermineDownloadTarget(save_as_download.get(), &result); |
| VerifyAndClearExpectations(); |
| } |
| } |
| -#endif // !BUILDFLAG(ANDROID_JAVA_UI) |
| + |
| +TEST_F(ChromeDownloadManagerDelegateTest, ConflictAction) { |
| + const GURL kUrl("http://example.com/foo"); |
| + const std::string kTargetDisposition("attachment; filename=\"foo.txt\""); |
| + |
| + std::unique_ptr<content::MockDownloadItem> download_item = |
| + CreateActiveDownloadItem(0); |
| + EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(kUrl)); |
| + EXPECT_CALL(*download_item, GetContentDisposition()) |
| + .WillRepeatedly(Return(kTargetDisposition)); |
| + |
| + base::FilePath kExpectedPath = GetPathInDownloadDir("bar.txt"); |
| + |
| + DetermineDownloadTargetResult result; |
| + |
| + EXPECT_CALL(*delegate(), MockReserveVirtualPath(_, _, _, _, _)) |
| + .WillOnce(::testing::DoAll( |
| + ::testing::SetArgPointee<4>(DownloadTargetResult::CONFLICT), |
| + ::testing::ReturnArg<1>())); |
| + EXPECT_CALL( |
| + *delegate(), |
| + RequestConfirmation(_, _, DownloadConfirmationReason::TARGET_CONFLICT, _)) |
| + .WillOnce(WithArg<3>(ScheduleCallback2( |
| + DownloadConfirmationResult::CONFIRMED, kExpectedPath))); |
| + DetermineDownloadTarget(download_item.get(), &result); |
| + EXPECT_EQ(content::DownloadItem::TARGET_DISPOSITION_PROMPT, |
| + result.disposition); |
| + EXPECT_EQ(kExpectedPath, result.target_path); |
| + |
| + VerifyAndClearExpectations(); |
| +} |
| TEST_F(ChromeDownloadManagerDelegateTest, MaybeDangerousContent) { |
| -#if !defined(OS_ANDROID) |
| +#if defined(ENABLE_PLUGINS) |
| content::PluginService::GetInstance()->Init(); |
| #endif |
| @@ -433,13 +501,13 @@ TEST_F(ChromeDownloadManagerDelegateTest, MaybeDangerousContent) { |
| "attachment; filename=\"foo.swf\""); |
| EXPECT_CALL(*download_item, GetContentDisposition()) |
| .WillRepeatedly(Return(kDangerousContentDisposition)); |
| - DownloadTargetInfo target_info; |
| - DetermineDownloadTarget(download_item.get(), &target_info); |
| + DetermineDownloadTargetResult result; |
| + DetermineDownloadTarget(download_item.get(), &result); |
| EXPECT_EQ(DownloadFileType::DANGEROUS, |
| DownloadItemModel(download_item.get()).GetDangerLevel()); |
| EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| - target_info.danger_type); |
| + result.danger_type); |
| } |
| { |
| @@ -447,12 +515,12 @@ TEST_F(ChromeDownloadManagerDelegateTest, MaybeDangerousContent) { |
| "attachment; filename=\"foo.txt\""); |
| EXPECT_CALL(*download_item, GetContentDisposition()) |
| .WillRepeatedly(Return(kSafeContentDisposition)); |
| - DownloadTargetInfo target_info; |
| - DetermineDownloadTarget(download_item.get(), &target_info); |
| + DetermineDownloadTargetResult result; |
| + DetermineDownloadTarget(download_item.get(), &result); |
| EXPECT_EQ(DownloadFileType::NOT_DANGEROUS, |
| DownloadItemModel(download_item.get()).GetDangerLevel()); |
| EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| - target_info.danger_type); |
| + result.danger_type); |
| } |
| { |
| @@ -460,12 +528,12 @@ TEST_F(ChromeDownloadManagerDelegateTest, MaybeDangerousContent) { |
| "attachment; filename=\"foo.crx\""); |
| EXPECT_CALL(*download_item, GetContentDisposition()) |
| .WillRepeatedly(Return(kModerateContentDisposition)); |
| - DownloadTargetInfo target_info; |
| - DetermineDownloadTarget(download_item.get(), &target_info); |
| + DetermineDownloadTargetResult result; |
| + DetermineDownloadTarget(download_item.get(), &result); |
| EXPECT_EQ(DownloadFileType::ALLOW_ON_USER_GESTURE, |
| DownloadItemModel(download_item.get()).GetDangerLevel()); |
| EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| - target_info.danger_type); |
| + result.danger_type); |
| } |
| } |
| @@ -685,3 +753,111 @@ TEST_P(ChromeDownloadManagerDelegateTestWithSafeBrowsing, CheckClientDownload) { |
| } |
| #endif // FULL_SAFE_BROWSING |
| + |
| +#if BUILDFLAG(ANDROID_JAVA_UI) |
| + |
| +namespace { |
| + |
| +class AndroidDownloadInfobarCounter |
| + : public infobars::InfoBarManager::Observer { |
| + public: |
| + explicit AndroidDownloadInfobarCounter(content::WebContents* web_contents) { |
| + infobar_service_ = InfoBarService::FromWebContents(web_contents); |
| + infobar_service_->AddObserver(this); |
| + } |
| + |
| + ~AndroidDownloadInfobarCounter() { infobar_service_->RemoveObserver(this); } |
| + |
| + int infobar_count() const { return infobar_count_; } |
| + |
| + private: |
| + void OnInfoBarAdded(infobars::InfoBar* infobar) override { |
| + if (infobar->delegate()->GetIdentifier() == |
| + infobars::InfoBarDelegate:: |
| + CHROME_DOWNLOAD_MANAGER_OVERWRITE_INFOBAR_DELEGATE) { |
| + ++infobar_count_; |
| + } |
| + infobar->delegate()->InfoBarDismissed(); |
| + infobar->RemoveSelf(); |
| + } |
| + |
| + InfoBarService* infobar_service_ = nullptr; |
| + int infobar_count_ = 0; |
| +}; |
| + |
| +} // namespace |
| + |
| +TEST_F(ChromeDownloadManagerDelegateTest, RequestConfirmation_Android) { |
| + EXPECT_CALL(*delegate(), RequestConfirmation(_, _, _, _)) |
| + .WillRepeatedly(Invoke( |
| + delegate(), |
| + &TestChromeDownloadManagerDelegate::RequestConfirmationConcrete)); |
| + InfoBarService::CreateForWebContents(web_contents()); |
| + base::FilePath fake_path = GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt")); |
| + GURL url("http://example.com"); |
| + AndroidDownloadInfobarCounter infobar_counter(web_contents()); |
| + |
| + struct { |
| + DownloadConfirmationReason confirmation_reason; |
| + DownloadConfirmationResult expected_result; |
| + bool use_web_contents; |
| + bool expect_full_path; |
| + } kTestCases[] = { |
| + {DownloadConfirmationReason::TARGET_NOT_WRITEABLE, |
| + DownloadConfirmationResult::CANCELED, true, false}, |
| + |
| + {DownloadConfirmationReason::NAME_TOO_LONG, |
| + DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, true, true}, |
| + |
| + {DownloadConfirmationReason::TARGET_NO_SPACE, |
| + DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, true, true}, |
| + |
| + {DownloadConfirmationReason::SAVE_AS, |
| + DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, true, true}, |
| + |
| + {DownloadConfirmationReason::PREFERENCE, |
| + DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, true, true}, |
| + |
| + // This case results in an infobar. The logic above dismisses the infobar |
| + // and counts it for testing. The functionality of the infobar is not |
| + // tested here other than that dimssing the infobar is treated as a user |
| + // initiated cancellation. |
| + {DownloadConfirmationReason::TARGET_CONFLICT, |
| + DownloadConfirmationResult::CANCELED, true, false}, |
| + |
| + {DownloadConfirmationReason::TARGET_CONFLICT, |
| + DownloadConfirmationResult::CANCELED, false, false}, |
| + |
| + {DownloadConfirmationReason::UNEXPECTED, |
| + DownloadConfirmationResult::CANCELED, true, false}, |
| + }; |
| + |
| + for (const auto& test_case : kTestCases) { |
| + std::unique_ptr<content::MockDownloadItem> download_item = |
| + CreateActiveDownloadItem(1); |
| + EXPECT_CALL(*download_item, GetWebContents()) |
| + .WillRepeatedly( |
| + Return(test_case.use_web_contents ? web_contents() : nullptr)); |
| + EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(url)); |
| + |
| + base::RunLoop loop; |
| + const auto callback = base::Bind( |
| + [](const base::Closure& closure, |
| + DownloadConfirmationResult expected_result, |
| + const base::FilePath& expected_path, |
| + DownloadConfirmationResult actual_result, |
| + const base::FilePath& actual_path) { |
| + EXPECT_EQ(expected_result, actual_result); |
| + EXPECT_EQ(expected_path, actual_path); |
| + closure.Run(); |
| + }, |
| + loop.QuitClosure(), test_case.expected_result, |
| + test_case.expect_full_path ? fake_path : base::FilePath()); |
| + delegate()->RequestConfirmation(download_item.get(), fake_path, |
| + test_case.confirmation_reason, callback); |
| + loop.Run(); |
| + } |
| + |
| + EXPECT_EQ(1, infobar_counter.infobar_count()); |
|
svaldez
2016/10/28 17:29:35
Possible check this within the loop, so that you a
asanka
2016/11/07 19:50:15
Good point. Done.
|
| +} |
| +#endif |