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 |