| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <string> |
| |
| #include "base/command_line.h" |
| #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" |
| #include "build/build_config.h" |
| #include "chrome/browser/download/chrome_download_manager_delegate.h" |
| #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/browser/safe_browsing/download_protection/download_protection_util.h" |
| #include "chrome/common/chrome_switches.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" |
| #include "components/prefs/pref_service.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "content/public/browser/download_interrupt_reasons.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_contents_delegate.h" |
| #include "content/public/test/mock_download_item.h" |
| #include "content/public/test/mock_download_manager.h" |
| #include "content/public/test/test_renderer_host.h" |
| #include "content/public/test/web_contents_tester.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| #if defined(FULL_SAFE_BROWSING) |
| #include "chrome/browser/safe_browsing/download_protection/download_protection_service.h" |
| #endif |
| |
| #if BUILDFLAG(ENABLE_PLUGINS) |
| #include "content/public/browser/plugin_service.h" |
| #endif |
| |
| #if defined(OS_ANDROID) |
| #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::AnyNumber; |
| using ::testing::AtMost; |
| using ::testing::DoAll; |
| using ::testing::Invoke; |
| using ::testing::Ref; |
| using ::testing::Return; |
| using ::testing::ReturnArg; |
| using ::testing::ReturnPointee; |
| using ::testing::ReturnRef; |
| using ::testing::ReturnRefOfCopy; |
| using ::testing::SetArgPointee; |
| using ::testing::WithArg; |
| using ::testing::_; |
| using content::DownloadItem; |
| using safe_browsing::DownloadFileType; |
| |
| namespace { |
| |
| class MockWebContentsDelegate : public content::WebContentsDelegate { |
| public: |
| ~MockWebContentsDelegate() override {} |
| }; |
| |
| // Google Mock action that posts a task to the current message loop that invokes |
| // the first argument of the mocked method as a callback. Said argument must be |
| // a base::Callback<void(ParamType0, ParamType1)>. |result0| and |result1| must |
| // be of ParamType0 and ParamType1 respectively and will be bound as such. |
| // |
| // Example: |
| // class FooClass { |
| // public: |
| // virtual void Foo(base::Callback<void(bool, std::string)> callback); |
| // }; |
| // ... |
| // EXPECT_CALL(mock_fooclass_instance, Foo(callback)) |
| // .WillOnce(ScheduleCallback2(false, "hello")); |
| // |
| ACTION_P2(ScheduleCallback2, result0, result1) { |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(arg0, result0, result1)); |
| } |
| |
| // Struct for holding the result of calling DetermineDownloadTarget. |
| struct DetermineDownloadTargetResult { |
| DetermineDownloadTargetResult(); |
| |
| base::FilePath target_path; |
| content::DownloadItem::TargetDisposition disposition; |
| content::DownloadDangerType danger_type; |
| base::FilePath intermediate_path; |
| content::DownloadInterruptReason interrupt_reason; |
| }; |
| |
| DetermineDownloadTargetResult::DetermineDownloadTargetResult() |
| : disposition(content::DownloadItem::TARGET_DISPOSITION_OVERWRITE), |
| danger_type(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
| interrupt_reason(content::DOWNLOAD_INTERRUPT_REASON_NONE) {} |
| |
| // Subclass of the ChromeDownloadManagerDelegate that replaces a few interaction |
| // points for ease of testing. |
| class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { |
| public: |
| explicit TestChromeDownloadManagerDelegate(Profile* profile) |
| : ChromeDownloadManagerDelegate(profile) { |
| ON_CALL(*this, MockCheckDownloadUrl(_, _)) |
| .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); |
| ON_CALL(*this, GetDownloadProtectionService()) |
| .WillByDefault(Return(nullptr)); |
| ON_CALL(*this, MockReserveVirtualPath(_, _, _, _, _)) |
| .WillByDefault(DoAll(SetArgPointee<4>(PathValidationResult::SUCCESS), |
| ReturnArg<1>())); |
| } |
| |
| ~TestChromeDownloadManagerDelegate() override {} |
| |
| // The concrete implementation talks to the ExtensionDownloadsEventRouter to |
| // dispatch a OnDeterminingFilename event. While we would like to test this as |
| // well in this unit test, we are currently going to rely on the extension |
| // browser test to provide test coverage here. Instead we are going to mock it |
| // out for unit tests. |
| void NotifyExtensions(content::DownloadItem* download, |
| const base::FilePath& suggested_virtual_path, |
| const NotifyExtensionsCallback& callback) override { |
| callback.Run(base::FilePath(), |
| DownloadPathReservationTracker::UNIQUIFY); |
| } |
| |
| // DownloadPathReservationTracker talks to the underlying file system. For |
| // tests we are going to mock it out so that we can test how |
| // ChromeDownloadManagerDelegate reponds to various DownloadTargetDeterminer |
| // results. |
| void ReserveVirtualPath( |
| content::DownloadItem* download, |
| const base::FilePath& virtual_path, |
| bool create_directory, |
| DownloadPathReservationTracker::FilenameConflictAction conflict_action, |
| const DownloadPathReservationTracker::ReservedPathCallback& callback) |
| override { |
| PathValidationResult result = PathValidationResult::SUCCESS; |
| base::FilePath path_to_return = MockReserveVirtualPath( |
| download, virtual_path, create_directory, conflict_action, &result); |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(callback, result, path_to_return)); |
| } |
| |
| MOCK_METHOD5( |
| MockReserveVirtualPath, |
| base::FilePath(content::DownloadItem*, |
| const base::FilePath&, |
| bool, |
| DownloadPathReservationTracker::FilenameConflictAction, |
| PathValidationResult*)); |
| |
| // The concrete implementation invokes SafeBrowsing's |
| // DownloadProtectionService. Now that SafeBrowsingService is testable, we |
| // should migrate to using TestSafeBrowsingService instead. |
| void CheckDownloadUrl(DownloadItem* download, |
| const base::FilePath& virtual_path, |
| const CheckDownloadUrlCallback& callback) override { |
| callback.Run(MockCheckDownloadUrl(download, virtual_path)); |
| } |
| |
| MOCK_METHOD2(MockCheckDownloadUrl, |
| content::DownloadDangerType(DownloadItem*, |
| const base::FilePath&)); |
| |
| MOCK_METHOD0(GetDownloadProtectionService, |
| safe_browsing::DownloadProtectionService*()); |
| |
| // The concrete implementation on desktop just invokes a file picker. Android |
| // has a non-trivial implementation. The former is tested via browser tests, |
| // and the latter is exercised in this unit test. |
| MOCK_METHOD4( |
| RequestConfirmation, |
| void(DownloadItem*, |
| const base::FilePath&, |
| DownloadConfirmationReason, |
| const DownloadTargetDeterminerDelegate::ConfirmationCallback&)); |
| |
| // For testing the concrete implementation. |
| void RequestConfirmationConcrete( |
| DownloadItem* download_item, |
| const base::FilePath& path, |
| DownloadConfirmationReason reason, |
| const DownloadTargetDeterminerDelegate::ConfirmationCallback& callback) { |
| ChromeDownloadManagerDelegate::RequestConfirmation(download_item, path, |
| reason, callback); |
| } |
| }; |
| |
| class ChromeDownloadManagerDelegateTest |
| : public ChromeRenderViewHostTestHarness { |
| public: |
| // Result of calling DetermineDownloadTarget. |
| ChromeDownloadManagerDelegateTest(); |
| |
| // ::testing::Test |
| void SetUp() override; |
| void TearDown() override; |
| |
| // Verifies and clears test expectations for |delegate_| and |
| // |download_manager_|. |
| void VerifyAndClearExpectations(); |
| |
| // Creates MockDownloadItem and sets up default expectations. |
| std::unique_ptr<content::MockDownloadItem> CreateActiveDownloadItem( |
| int32_t id); |
| |
| // Given the relative path |path|, returns the full path under the temporary |
| // downloads directory. |
| base::FilePath GetPathInDownloadDir(const char* path); |
| |
| // Set the kDownloadDefaultDirectory user preference to |path|. |
| void SetDefaultDownloadPath(const base::FilePath& path); |
| |
| void DetermineDownloadTarget(DownloadItem* download, |
| DetermineDownloadTargetResult* result); |
| |
| // Invokes ChromeDownloadManagerDelegate::CheckForFileExistence and waits for |
| // the asynchronous callback. The result passed into |
| // content::CheckForFileExistenceCallback is the return value from this |
| // method. |
| bool CheckForFileExistence(DownloadItem* download); |
| |
| const base::FilePath& default_download_path() const; |
| TestChromeDownloadManagerDelegate* delegate(); |
| content::MockDownloadManager* download_manager(); |
| DownloadPrefs* download_prefs(); |
| PrefService* pref_service(); |
| |
| const std::vector<uint32_t>& download_ids() const { return download_ids_; } |
| void GetNextId(uint32_t next_id) { download_ids_.emplace_back(next_id); } |
| |
| private: |
| sync_preferences::TestingPrefServiceSyncable* pref_service_; |
| base::ScopedTempDir test_download_dir_; |
| std::unique_ptr<content::MockDownloadManager> download_manager_; |
| std::unique_ptr<TestChromeDownloadManagerDelegate> delegate_; |
| MockWebContentsDelegate web_contents_delegate_; |
| std::vector<uint32_t> download_ids_; |
| }; |
| |
| ChromeDownloadManagerDelegateTest::ChromeDownloadManagerDelegateTest() |
| : download_manager_(new ::testing::NiceMock<content::MockDownloadManager>) { |
| } |
| |
| void ChromeDownloadManagerDelegateTest::SetUp() { |
| ChromeRenderViewHostTestHarness::SetUp(); |
| |
| CHECK(profile()); |
| delegate_ = |
| base::MakeUnique<::testing::NiceMock<TestChromeDownloadManagerDelegate>>( |
| profile()); |
| delegate_->SetDownloadManager(download_manager_.get()); |
| pref_service_ = profile()->GetTestingPrefService(); |
| web_contents()->SetDelegate(&web_contents_delegate_); |
| |
| ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir()); |
| SetDefaultDownloadPath(test_download_dir_.GetPath()); |
| } |
| |
| void ChromeDownloadManagerDelegateTest::TearDown() { |
| base::RunLoop().RunUntilIdle(); |
| delegate_->Shutdown(); |
| ChromeRenderViewHostTestHarness::TearDown(); |
| } |
| |
| void ChromeDownloadManagerDelegateTest::VerifyAndClearExpectations() { |
| ::testing::Mock::VerifyAndClearExpectations(delegate_.get()); |
| } |
| |
| std::unique_ptr<content::MockDownloadItem> |
| ChromeDownloadManagerDelegateTest::CreateActiveDownloadItem(int32_t id) { |
| std::unique_ptr<content::MockDownloadItem> item( |
| new ::testing::NiceMock<content::MockDownloadItem>()); |
| ON_CALL(*item, GetBrowserContext()) |
| .WillByDefault(Return(profile())); |
| ON_CALL(*item, GetDangerType()) |
| .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); |
| ON_CALL(*item, GetForcedFilePath()) |
| .WillByDefault(ReturnRefOfCopy(base::FilePath())); |
| ON_CALL(*item, GetFullPath()) |
| .WillByDefault(ReturnRefOfCopy(base::FilePath())); |
| ON_CALL(*item, GetHash()) |
| .WillByDefault(ReturnRefOfCopy(std::string())); |
| ON_CALL(*item, GetId()) |
| .WillByDefault(Return(id)); |
| ON_CALL(*item, GetLastReason()) |
| .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE)); |
| ON_CALL(*item, GetReferrerUrl()) |
| .WillByDefault(ReturnRefOfCopy(GURL())); |
| ON_CALL(*item, GetState()) |
| .WillByDefault(Return(DownloadItem::IN_PROGRESS)); |
| ON_CALL(*item, GetTargetFilePath()) |
| .WillByDefault(ReturnRefOfCopy(base::FilePath())); |
| ON_CALL(*item, GetTransitionType()) |
| .WillByDefault(Return(ui::PAGE_TRANSITION_LINK)); |
| ON_CALL(*item, GetWebContents()) |
| .WillByDefault(Return(web_contents())); |
| ON_CALL(*item, HasUserGesture()) |
| .WillByDefault(Return(false)); |
| ON_CALL(*item, IsDangerous()) |
| .WillByDefault(Return(false)); |
| ON_CALL(*item, IsTemporary()) |
| .WillByDefault(Return(false)); |
| EXPECT_CALL(*download_manager_, GetDownload(id)) |
| .WillRepeatedly(Return(item.get())); |
| return item; |
| } |
| |
| base::FilePath ChromeDownloadManagerDelegateTest::GetPathInDownloadDir( |
| const char* relative_path) { |
| base::FilePath full_path = |
| test_download_dir_.GetPath().AppendASCII(relative_path); |
| return full_path.NormalizePathSeparators(); |
| } |
| |
| void ChromeDownloadManagerDelegateTest::SetDefaultDownloadPath( |
| const base::FilePath& path) { |
| pref_service_->SetFilePath(prefs::kDownloadDefaultDirectory, path); |
| pref_service_->SetFilePath(prefs::kSaveFileDefaultDirectory, 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, |
| DetermineDownloadTargetResult* result) { |
| base::RunLoop loop_runner; |
| delegate()->DetermineDownloadTarget( |
| download_item, |
| base::Bind(&StoreDownloadTargetInfo, loop_runner.QuitClosure(), result)); |
| loop_runner.Run(); |
| } |
| |
| void StoreBoolAndRunClosure(const base::Closure& closure, |
| bool* result_storage, |
| bool result) { |
| *result_storage = result; |
| closure.Run(); |
| } |
| |
| bool ChromeDownloadManagerDelegateTest::CheckForFileExistence( |
| DownloadItem* download_item) { |
| base::RunLoop loop_runner; |
| bool result = false; |
| delegate()->CheckForFileExistence( |
| download_item, base::BindOnce(&StoreBoolAndRunClosure, |
| loop_runner.QuitClosure(), &result)); |
| loop_runner.Run(); |
| return result; |
| } |
| |
| const base::FilePath& ChromeDownloadManagerDelegateTest::default_download_path() |
| const { |
| return test_download_dir_.GetPath(); |
| } |
| |
| TestChromeDownloadManagerDelegate* |
| ChromeDownloadManagerDelegateTest::delegate() { |
| return delegate_.get(); |
| } |
| |
| content::MockDownloadManager* |
| ChromeDownloadManagerDelegateTest::download_manager() { |
| return download_manager_.get(); |
| } |
| |
| DownloadPrefs* ChromeDownloadManagerDelegateTest::download_prefs() { |
| return delegate_->download_prefs(); |
| } |
| |
| PrefService* ChromeDownloadManagerDelegateTest::pref_service() { |
| return pref_service_; |
| } |
| |
| } // namespace |
| |
| TEST_F(ChromeDownloadManagerDelegateTest, LastSavePath) { |
| GURL download_url("http://example.com/foo.txt"); |
| |
| std::unique_ptr<content::MockDownloadItem> save_as_download = |
| CreateActiveDownloadItem(0); |
| EXPECT_CALL(*save_as_download, GetURL()) |
| .Times(AnyNumber()) |
| .WillRepeatedly(ReturnRef(download_url)); |
| EXPECT_CALL(*save_as_download, GetTargetDisposition()) |
| .Times(AnyNumber()) |
| .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT)); |
| |
| std::unique_ptr<content::MockDownloadItem> automatic_download = |
| CreateActiveDownloadItem(1); |
| EXPECT_CALL(*automatic_download, GetURL()) |
| .Times(AnyNumber()) |
| .WillRepeatedly(ReturnRef(download_url)); |
| EXPECT_CALL(*automatic_download, GetTargetDisposition()) |
| .Times(AnyNumber()) |
| .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_OVERWRITE)); |
| |
| { |
| // When the prompt is displayed for the first download, the user selects a |
| // path in a different directory. |
| DetermineDownloadTargetResult result; |
| base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt")); |
| base::FilePath user_selected_path(GetPathInDownloadDir("bar/baz.txt")); |
| 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 directory |
| // from the previous download. |
| DetermineDownloadTargetResult result; |
| base::FilePath expected_prompt_path(GetPathInDownloadDir("bar/foo.txt")); |
| 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(); |
| } |
| |
| { |
| // Start an automatic download. This one should get the default download |
| // path since the last download path only affects Save As downloads. |
| DetermineDownloadTargetResult result; |
| base::FilePath expected_path(GetPathInDownloadDir("foo.txt")); |
| DetermineDownloadTarget(automatic_download.get(), &result); |
| EXPECT_EQ(expected_path, result.target_path); |
| VerifyAndClearExpectations(); |
| } |
| |
| { |
| // The prompt path for the next download should be the default. |
| download_prefs()->SetSaveFilePath(download_prefs()->DownloadPath()); |
| DetermineDownloadTargetResult result; |
| base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt")); |
| 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(); |
| } |
| } |
| |
| 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(DoAll(SetArgPointee<4>(PathValidationResult::CONFLICT), |
| 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 BUILDFLAG(ENABLE_PLUGINS) |
| content::PluginService::GetInstance()->Init(); |
| #endif |
| |
| GURL url("http://example.com/foo"); |
| |
| std::unique_ptr<content::MockDownloadItem> download_item = |
| CreateActiveDownloadItem(0); |
| EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(url)); |
| EXPECT_CALL(*download_item, GetTargetDisposition()) |
| .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_OVERWRITE)); |
| EXPECT_CALL(*delegate(), MockCheckDownloadUrl(_, _)) |
| .WillRepeatedly( |
| Return(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)); |
| |
| { |
| const std::string kDangerousContentDisposition( |
| "attachment; filename=\"foo.swf\""); |
| EXPECT_CALL(*download_item, GetContentDisposition()) |
| .WillRepeatedly(Return(kDangerousContentDisposition)); |
| 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, |
| result.danger_type); |
| } |
| |
| { |
| const std::string kSafeContentDisposition( |
| "attachment; filename=\"foo.txt\""); |
| EXPECT_CALL(*download_item, GetContentDisposition()) |
| .WillRepeatedly(Return(kSafeContentDisposition)); |
| 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, |
| result.danger_type); |
| } |
| |
| { |
| const std::string kModerateContentDisposition( |
| "attachment; filename=\"foo.crx\""); |
| EXPECT_CALL(*download_item, GetContentDisposition()) |
| .WillRepeatedly(Return(kModerateContentDisposition)); |
| 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, |
| result.danger_type); |
| } |
| } |
| |
| TEST_F(ChromeDownloadManagerDelegateTest, CheckForFileExistence) { |
| const char kData[] = "helloworld"; |
| const size_t kDataLength = sizeof(kData) - 1; |
| base::FilePath existing_path = default_download_path().AppendASCII("foo"); |
| base::FilePath non_existent_path = |
| default_download_path().AppendASCII("bar"); |
| base::WriteFile(existing_path, kData, kDataLength); |
| |
| std::unique_ptr<content::MockDownloadItem> download_item = |
| CreateActiveDownloadItem(1); |
| EXPECT_CALL(*download_item, GetTargetFilePath()) |
| .WillRepeatedly(ReturnRef(existing_path)); |
| EXPECT_TRUE(CheckForFileExistence(download_item.get())); |
| |
| download_item = CreateActiveDownloadItem(1); |
| EXPECT_CALL(*download_item, GetTargetFilePath()) |
| .WillRepeatedly(ReturnRef(non_existent_path)); |
| EXPECT_FALSE(CheckForFileExistence(download_item.get())); |
| } |
| |
| TEST_F(ChromeDownloadManagerDelegateTest, BlockedByPolicy) { |
| 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(DoAll(SetArgPointee<4>(PathValidationResult::CONFLICT), |
| ReturnArg<1>())); |
| EXPECT_CALL( |
| *delegate(), |
| RequestConfirmation(_, _, DownloadConfirmationReason::TARGET_CONFLICT, _)) |
| .WillOnce(WithArg<3>(ScheduleCallback2( |
| DownloadConfirmationResult::CONFIRMED, kExpectedPath))); |
| |
| pref_service()->SetInteger( |
| prefs::kDownloadRestrictions, |
| static_cast<int>(DownloadPrefs::DownloadRestriction::ALL_FILES)); |
| |
| DetermineDownloadTarget(download_item.get(), &result); |
| EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED, |
| result.interrupt_reason); |
| |
| VerifyAndClearExpectations(); |
| } |
| |
| TEST_F(ChromeDownloadManagerDelegateTest, WithoutHistoryDbNextId) { |
| content::DownloadIdCallback id_callback = base::Bind( |
| &ChromeDownloadManagerDelegateTest::GetNextId, base::Unretained(this)); |
| delegate()->GetNextId(id_callback); |
| delegate()->GetNextId(id_callback); |
| // When download database fails to initialize, id will be set to |
| // |content::DownloadItem::kInvalidId|. |
| delegate()->GetDownloadIdReceiverCallback().Run( |
| content::DownloadItem::kInvalidId); |
| std::vector<uint32_t> expected_ids = std::vector<uint32_t>{1u, 2u}; |
| EXPECT_EQ(expected_ids, download_ids()); |
| } |
| |
| TEST_F(ChromeDownloadManagerDelegateTest, WithHistoryDbNextId) { |
| content::DownloadIdCallback id_callback = base::Bind( |
| &ChromeDownloadManagerDelegateTest::GetNextId, base::Unretained(this)); |
| delegate()->GetNextId(id_callback); |
| delegate()->GetNextId(id_callback); |
| // Simulates a valid download database with no records. |
| delegate()->GetDownloadIdReceiverCallback().Run(1u); |
| std::vector<uint32_t> expected_ids = std::vector<uint32_t>{1u, 2u}; |
| EXPECT_EQ(expected_ids, download_ids()); |
| } |
| |
| #if defined(FULL_SAFE_BROWSING) |
| namespace { |
| |
| struct SafeBrowsingTestParameters { |
| content::DownloadDangerType initial_danger_type; |
| DownloadFileType::DangerLevel initial_danger_level; |
| safe_browsing::DownloadCheckResult verdict; |
| DownloadPrefs::DownloadRestriction download_restriction; |
| |
| content::DownloadDangerType expected_danger_type; |
| bool blocked; |
| }; |
| |
| class TestDownloadProtectionService |
| : public safe_browsing::DownloadProtectionService { |
| public: |
| TestDownloadProtectionService() : DownloadProtectionService(nullptr) {} |
| |
| void CheckClientDownload( |
| DownloadItem* download_item, |
| const safe_browsing::CheckDownloadCallback& callback) override { |
| callback.Run(MockCheckClientDownload()); |
| } |
| MOCK_METHOD0(MockCheckClientDownload, safe_browsing::DownloadCheckResult()); |
| }; |
| |
| class ChromeDownloadManagerDelegateTestWithSafeBrowsing |
| : public ChromeDownloadManagerDelegateTest, |
| public ::testing::WithParamInterface<SafeBrowsingTestParameters> { |
| public: |
| void SetUp() override; |
| void TearDown() override; |
| TestDownloadProtectionService* download_protection_service() { |
| return test_download_protection_service_.get(); |
| } |
| |
| private: |
| std::unique_ptr<TestDownloadProtectionService> |
| test_download_protection_service_; |
| }; |
| |
| void ChromeDownloadManagerDelegateTestWithSafeBrowsing::SetUp() { |
| ChromeDownloadManagerDelegateTest::SetUp(); |
| test_download_protection_service_.reset( |
| new ::testing::StrictMock<TestDownloadProtectionService>); |
| ON_CALL(*delegate(), GetDownloadProtectionService()) |
| .WillByDefault(Return(test_download_protection_service_.get())); |
| } |
| |
| void ChromeDownloadManagerDelegateTestWithSafeBrowsing::TearDown() { |
| test_download_protection_service_.reset(); |
| ChromeDownloadManagerDelegateTest::TearDown(); |
| } |
| |
| const SafeBrowsingTestParameters kSafeBrowsingTestCases[] = { |
| // SAFE verdict for a safe file. |
| {content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| DownloadFileType::NOT_DANGEROUS, safe_browsing::DownloadCheckResult::SAFE, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| /*blocked=*/false}, |
| |
| // UNKNOWN verdict for a safe file. |
| {content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| DownloadFileType::NOT_DANGEROUS, |
| safe_browsing::DownloadCheckResult::UNKNOWN, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| /*blocked=*/false}, |
| |
| // DANGEROUS verdict for a safe file. |
| {content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| DownloadFileType::NOT_DANGEROUS, |
| safe_browsing::DownloadCheckResult::DANGEROUS, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, |
| /*blocked=*/false}, |
| |
| // UNCOMMON verdict for a safe file. |
| {content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| DownloadFileType::NOT_DANGEROUS, |
| safe_browsing::DownloadCheckResult::UNCOMMON, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT, |
| /*blocked=*/false}, |
| |
| // POTENTIALLY_UNWANTED verdict for a safe file. |
| {content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| DownloadFileType::NOT_DANGEROUS, |
| safe_browsing::DownloadCheckResult::POTENTIALLY_UNWANTED, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, |
| /*blocked=*/false}, |
| |
| // SAFE verdict for a potentially dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::SAFE, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| /*blocked=*/false}, |
| |
| // UNKNOWN verdict for a potentially dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::UNKNOWN, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, |
| /*blocked=*/false}, |
| |
| // UNKNOWN verdict for a potentially dangerous file blocked by policy. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::UNKNOWN, |
| DownloadPrefs::DownloadRestriction::DANGEROUS_FILES, |
| |
| content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, |
| /*blocked=*/true}, |
| |
| // DANGEROUS verdict for a potentially dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::DANGEROUS, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, |
| /*blocked=*/false}, |
| |
| // UNCOMMON verdict for a potentially dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::UNCOMMON, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT, |
| /*blocked=*/false}, |
| |
| // POTENTIALLY_UNWANTED verdict for a potentially dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::POTENTIALLY_UNWANTED, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, |
| /*blocked=*/false}, |
| |
| // POTENTIALLY_UNWANTED verdict for a potentially dangerous file, blocked by |
| // policy. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::POTENTIALLY_UNWANTED, |
| DownloadPrefs::DownloadRestriction::POTENTIALLY_DANGEROUS_FILES, |
| |
| content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, |
| /*blocked=*/true}, |
| |
| // POTENTIALLY_UNWANTED verdict for a potentially dangerous file, not |
| // blocked by policy. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::ALLOW_ON_USER_GESTURE, |
| safe_browsing::DownloadCheckResult::POTENTIALLY_UNWANTED, |
| DownloadPrefs::DownloadRestriction::DANGEROUS_FILES, |
| |
| content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, |
| /*blocked=*/false}, |
| |
| // SAFE verdict for a dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::DANGEROUS, safe_browsing::DownloadCheckResult::SAFE, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, |
| /*blocked=*/false}, |
| |
| // UNKNOWN verdict for a dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::DANGEROUS, safe_browsing::DownloadCheckResult::UNKNOWN, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, |
| /*blocked=*/false}, |
| |
| // DANGEROUS verdict for a dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::DANGEROUS, safe_browsing::DownloadCheckResult::DANGEROUS, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, |
| /*blocked=*/false}, |
| |
| // UNCOMMON verdict for a dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::DANGEROUS, safe_browsing::DownloadCheckResult::UNCOMMON, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT, |
| /*blocked=*/false}, |
| |
| // POTENTIALLY_UNWANTED verdict for a dangerous file. |
| {content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, |
| DownloadFileType::DANGEROUS, |
| safe_browsing::DownloadCheckResult::POTENTIALLY_UNWANTED, |
| DownloadPrefs::DownloadRestriction::NONE, |
| |
| content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, |
| /*blocked=*/false}, |
| }; |
| |
| INSTANTIATE_TEST_CASE_P(_, |
| ChromeDownloadManagerDelegateTestWithSafeBrowsing, |
| ::testing::ValuesIn(kSafeBrowsingTestCases)); |
| |
| } // namespace |
| |
| TEST_P(ChromeDownloadManagerDelegateTestWithSafeBrowsing, CheckClientDownload) { |
| const SafeBrowsingTestParameters& kParameters = GetParam(); |
| |
| std::unique_ptr<content::MockDownloadItem> download_item = |
| CreateActiveDownloadItem(0); |
| EXPECT_CALL(*delegate(), GetDownloadProtectionService()); |
| EXPECT_CALL(*download_protection_service(), MockCheckClientDownload()) |
| .WillOnce(Return(kParameters.verdict)); |
| EXPECT_CALL(*download_item, GetDangerType()) |
| .WillRepeatedly(Return(kParameters.initial_danger_type)); |
| |
| if (kParameters.initial_danger_level != DownloadFileType::NOT_DANGEROUS) { |
| DownloadItemModel(download_item.get()) |
| .SetDangerLevel(kParameters.initial_danger_level); |
| } |
| |
| if (kParameters.expected_danger_type != |
| content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { |
| if (kParameters.blocked) { |
| EXPECT_CALL(*download_item, |
| OnContentCheckCompleted( |
| // Specifying a dangerous type here would take precendence |
| // over the blocking of the file. |
| content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED)); |
| } else { |
| EXPECT_CALL(*download_item, OnContentCheckCompleted( |
| kParameters.expected_danger_type, |
| content::DOWNLOAD_INTERRUPT_REASON_NONE)); |
| } |
| } else { |
| EXPECT_CALL(*download_item, OnContentCheckCompleted(_, _)).Times(0); |
| } |
| |
| pref_service()->SetInteger( |
| prefs::kDownloadRestrictions, |
| static_cast<int>(kParameters.download_restriction)); |
| |
| base::RunLoop run_loop; |
| ASSERT_FALSE(delegate()->ShouldCompleteDownload(download_item.get(), |
| run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing, |
| TrustedSourcesPolicyNotTrusted) { |
| GURL download_url("http://untrusted.com/best-download-ever.exe"); |
| pref_service()->SetBoolean(prefs::kSafeBrowsingForTrustedSourcesEnabled, |
| false); |
| std::unique_ptr<content::MockDownloadItem> download_item = |
| CreateActiveDownloadItem(0); |
| EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(download_url)); |
| |
| EXPECT_CALL(*delegate(), GetDownloadProtectionService()); |
| EXPECT_CALL(*download_protection_service(), MockCheckClientDownload()) |
| .WillOnce(Return(safe_browsing::DownloadCheckResult::SAFE)); |
| EXPECT_CALL(*download_item, GetDangerType()) |
| .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); |
| |
| base::RunLoop run_loop; |
| ASSERT_FALSE(delegate()->ShouldCompleteDownload(download_item.get(), |
| run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| #if !defined(OS_WIN) |
| // TODO(crbug.com/739204) Add a Windows version of this test. |
| TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing, |
| TrustedSourcesPolicyTrusted) { |
| base::CommandLine* command_line(base::CommandLine::ForCurrentProcess()); |
| DCHECK(command_line); |
| command_line->AppendSwitchASCII(switches::kTrustedDownloadSources, |
| "trusted.com"); |
| GURL download_url("http://trusted.com/best-download-ever.exe"); |
| pref_service()->SetBoolean(prefs::kSafeBrowsingForTrustedSourcesEnabled, |
| false); |
| std::unique_ptr<content::MockDownloadItem> download_item = |
| CreateActiveDownloadItem(0); |
| EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(download_url)); |
| EXPECT_CALL(*delegate(), GetDownloadProtectionService()).Times(0); |
| EXPECT_TRUE( |
| delegate()->ShouldCompleteDownload(download_item.get(), base::Closure())); |
| } |
| #endif // OS_WIN |
| #endif // FULL_SAFE_BROWSING |
| |
| #if defined(OS_ANDROID) |
| |
| 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() override { |
| infobar_service_->RemoveObserver(this); |
| } |
| |
| int CheckAndResetInfobarCount() { |
| int count = infobar_count_; |
| infobar_count_ = 0; |
| return count; |
| } |
| |
| private: |
| void OnInfoBarAdded(infobars::InfoBar* infobar) override { |
| if (infobar->delegate()->GetIdentifier() == |
| infobars::InfoBarDelegate::CHROME_DUPLICATE_DOWNLOAD_INFOBAR_DELEGATE) { |
| ++infobar_count_; |
| } |
| infobar->delegate()->InfoBarDismissed(); |
| infobar->RemoveSelf(); |
| } |
| |
| InfoBarService* infobar_service_; |
| int infobar_count_ = 0; |
| }; |
| |
| } // namespace |
| |
| TEST_F(ChromeDownloadManagerDelegateTest, RequestConfirmation_Android) { |
| enum class WebContents { AVAILABLE, NONE }; |
| enum class ExpectPath { FULL, EMPTY }; |
| enum class ExpectInfoBar { YES, NO }; |
| struct { |
| DownloadConfirmationReason confirmation_reason; |
| DownloadConfirmationResult expected_result; |
| WebContents web_contents; |
| ExpectInfoBar info_bar; |
| ExpectPath path; |
| } kTestCases[] = { |
| {DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE, |
| DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE, |
| ExpectInfoBar::NO, ExpectPath::EMPTY}, |
| |
| {DownloadConfirmationReason::NAME_TOO_LONG, |
| DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, |
| WebContents::AVAILABLE, ExpectInfoBar::NO, ExpectPath::FULL}, |
| |
| {DownloadConfirmationReason::TARGET_NO_SPACE, |
| DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, |
| WebContents::AVAILABLE, ExpectInfoBar::NO, ExpectPath::FULL}, |
| |
| {DownloadConfirmationReason::SAVE_AS, |
| DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, |
| WebContents::AVAILABLE, ExpectInfoBar::NO, ExpectPath::FULL}, |
| |
| {DownloadConfirmationReason::PREFERENCE, |
| DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION, |
| WebContents::AVAILABLE, ExpectInfoBar::NO, ExpectPath::FULL}, |
| |
| // 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, WebContents::AVAILABLE, |
| ExpectInfoBar::YES, ExpectPath::EMPTY}, |
| |
| {DownloadConfirmationReason::TARGET_CONFLICT, |
| DownloadConfirmationResult::CANCELED, WebContents::NONE, |
| ExpectInfoBar::NO, ExpectPath::EMPTY}, |
| |
| {DownloadConfirmationReason::UNEXPECTED, |
| DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE, |
| ExpectInfoBar::NO, ExpectPath::EMPTY}, |
| }; |
| |
| 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()); |
| |
| for (const auto& test_case : kTestCases) { |
| std::unique_ptr<content::MockDownloadItem> download_item = |
| CreateActiveDownloadItem(1); |
| EXPECT_CALL(*download_item, GetWebContents()) |
| .WillRepeatedly(Return(test_case.web_contents == WebContents::AVAILABLE |
| ? web_contents() |
| : nullptr)); |
| EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(url)); |
| infobar_counter.CheckAndResetInfobarCount(); |
| |
| base::RunLoop loop; |
| const auto callback = base::Bind( |
| [](const base::Closure& quit_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); |
| quit_closure.Run(); |
| }, |
| loop.QuitClosure(), test_case.expected_result, |
| test_case.path == ExpectPath::FULL ? fake_path : base::FilePath()); |
| delegate()->RequestConfirmation(download_item.get(), fake_path, |
| test_case.confirmation_reason, callback); |
| loop.Run(); |
| |
| EXPECT_EQ(test_case.info_bar == ExpectInfoBar::YES ? 1 : 0, |
| infobar_counter.CheckAndResetInfobarCount()); |
| } |
| } |
| #endif // OS_ANDROID |