No dual_mode on Win10+ shortcuts.
[chromium-blink-merge.git] / chrome / browser / download / chrome_download_manager_delegate_unittest.cc
blob210773079dfd10f3b861062f8741391f5689cbb0
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/files/file_path.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "chrome/browser/download/chrome_download_manager_delegate.h"
15 #include "chrome/browser/download/download_prefs.h"
16 #include "chrome/browser/download/download_target_info.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
19 #include "chrome/test/base/testing_pref_service_syncable.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "content/public/browser/download_interrupt_reasons.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_delegate.h"
24 #include "content/public/test/mock_download_item.h"
25 #include "content/public/test/mock_download_manager.h"
26 #include "content/public/test/test_renderer_host.h"
27 #include "content/public/test/web_contents_tester.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 using ::testing::AtMost;
32 using ::testing::Invoke;
33 using ::testing::Ref;
34 using ::testing::Return;
35 using ::testing::ReturnPointee;
36 using ::testing::ReturnRef;
37 using ::testing::ReturnRefOfCopy;
38 using ::testing::SetArgPointee;
39 using ::testing::WithArg;
40 using ::testing::_;
41 using content::DownloadItem;
43 namespace {
45 class MockWebContentsDelegate : public content::WebContentsDelegate {
46 public:
47 ~MockWebContentsDelegate() override {}
50 // Google Mock action that posts a task to the current message loop that invokes
51 // the first argument of the mocked method as a callback. Said argument must be
52 // a base::Callback<void(ParamType)>. |result| must be of |ParamType| and is
53 // bound as that parameter.
54 // Example:
55 // class FooClass {
56 // public:
57 // virtual void Foo(base::Callback<void(bool)> callback);
58 // };
59 // ...
60 // EXPECT_CALL(mock_fooclass_instance, Foo(callback))
61 // .WillOnce(ScheduleCallback(false));
62 ACTION_P(ScheduleCallback, result) {
63 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, result));
66 // Similar to ScheduleCallback, but binds 2 arguments.
67 ACTION_P2(ScheduleCallback2, result0, result1) {
68 base::MessageLoop::current()->PostTask(
69 FROM_HERE, base::Bind(arg0, result0, result1));
72 // Subclass of the ChromeDownloadManagerDelegate that uses a mock
73 // DownloadProtectionService.
74 class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate {
75 public:
76 explicit TestChromeDownloadManagerDelegate(Profile* profile)
77 : ChromeDownloadManagerDelegate(profile) {
80 ~TestChromeDownloadManagerDelegate() override {}
82 safe_browsing::DownloadProtectionService*
83 GetDownloadProtectionService() override {
84 return NULL;
87 void NotifyExtensions(content::DownloadItem* download,
88 const base::FilePath& suggested_virtual_path,
89 const NotifyExtensionsCallback& callback) override {
90 callback.Run(base::FilePath(),
91 DownloadPathReservationTracker::UNIQUIFY);
94 void ReserveVirtualPath(
95 content::DownloadItem* download,
96 const base::FilePath& virtual_path,
97 bool create_directory,
98 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
99 const DownloadPathReservationTracker::ReservedPathCallback& callback)
100 override {
101 // Pretend the path reservation succeeded without any change to
102 // |target_path|.
103 base::ThreadTaskRunnerHandle::Get()->PostTask(
104 FROM_HERE, base::Bind(callback, virtual_path, true));
107 void PromptUserForDownloadPath(
108 DownloadItem* download,
109 const base::FilePath& suggested_path,
110 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback)
111 override {
112 base::FilePath return_path = MockPromptUserForDownloadPath(download,
113 suggested_path,
114 callback);
115 callback.Run(return_path);
118 MOCK_METHOD3(
119 MockPromptUserForDownloadPath,
120 base::FilePath(
121 content::DownloadItem*,
122 const base::FilePath&,
123 const DownloadTargetDeterminerDelegate::FileSelectedCallback&));
126 class ChromeDownloadManagerDelegateTest
127 : public ChromeRenderViewHostTestHarness {
128 public:
129 ChromeDownloadManagerDelegateTest();
131 // ::testing::Test
132 void SetUp() override;
133 void TearDown() override;
135 // Verifies and clears test expectations for |delegate_| and
136 // |download_manager_|.
137 void VerifyAndClearExpectations();
139 // Creates MockDownloadItem and sets up default expectations.
140 content::MockDownloadItem* CreateActiveDownloadItem(int32 id);
142 // Given the relative path |path|, returns the full path under the temporary
143 // downloads directory.
144 base::FilePath GetPathInDownloadDir(const char* path);
146 // Set the kDownloadDefaultDirectory user preference to |path|.
147 void SetDefaultDownloadPath(const base::FilePath& path);
149 void DetermineDownloadTarget(DownloadItem* download,
150 DownloadTargetInfo* result);
152 // Invokes ChromeDownloadManagerDelegate::CheckForFileExistence and waits for
153 // the asynchronous callback. The result passed into
154 // content::CheckForFileExistenceCallback is the return value from this
155 // method.
156 bool CheckForFileExistence(DownloadItem* download);
158 const base::FilePath& default_download_path() const;
159 TestChromeDownloadManagerDelegate* delegate();
160 content::MockDownloadManager* download_manager();
161 DownloadPrefs* download_prefs();
163 private:
164 TestingPrefServiceSyncable* pref_service_;
165 base::ScopedTempDir test_download_dir_;
166 scoped_ptr<content::MockDownloadManager> download_manager_;
167 scoped_ptr<TestChromeDownloadManagerDelegate> delegate_;
168 MockWebContentsDelegate web_contents_delegate_;
172 ChromeDownloadManagerDelegateTest::ChromeDownloadManagerDelegateTest()
173 : download_manager_(new ::testing::NiceMock<content::MockDownloadManager>) {
176 void ChromeDownloadManagerDelegateTest::SetUp() {
177 ChromeRenderViewHostTestHarness::SetUp();
179 CHECK(profile());
180 delegate_.reset(new TestChromeDownloadManagerDelegate(profile()));
181 delegate_->SetDownloadManager(download_manager_.get());
182 pref_service_ = profile()->GetTestingPrefService();
183 web_contents()->SetDelegate(&web_contents_delegate_);
185 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
186 SetDefaultDownloadPath(test_download_dir_.path());
189 void ChromeDownloadManagerDelegateTest::TearDown() {
190 base::RunLoop().RunUntilIdle();
191 delegate_->Shutdown();
192 ChromeRenderViewHostTestHarness::TearDown();
195 void ChromeDownloadManagerDelegateTest::VerifyAndClearExpectations() {
196 ::testing::Mock::VerifyAndClearExpectations(delegate_.get());
199 content::MockDownloadItem*
200 ChromeDownloadManagerDelegateTest::CreateActiveDownloadItem(int32 id) {
201 content::MockDownloadItem* item =
202 new ::testing::NiceMock<content::MockDownloadItem>();
203 ON_CALL(*item, GetBrowserContext())
204 .WillByDefault(Return(profile()));
205 ON_CALL(*item, GetDangerType())
206 .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
207 ON_CALL(*item, GetForcedFilePath())
208 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
209 ON_CALL(*item, GetFullPath())
210 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
211 ON_CALL(*item, GetHash())
212 .WillByDefault(ReturnRefOfCopy(std::string()));
213 ON_CALL(*item, GetId())
214 .WillByDefault(Return(id));
215 ON_CALL(*item, GetLastReason())
216 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE));
217 ON_CALL(*item, GetReferrerUrl())
218 .WillByDefault(ReturnRefOfCopy(GURL()));
219 ON_CALL(*item, GetState())
220 .WillByDefault(Return(DownloadItem::IN_PROGRESS));
221 ON_CALL(*item, GetTargetFilePath())
222 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
223 ON_CALL(*item, GetTransitionType())
224 .WillByDefault(Return(ui::PAGE_TRANSITION_LINK));
225 ON_CALL(*item, GetWebContents())
226 .WillByDefault(Return(web_contents()));
227 ON_CALL(*item, HasUserGesture())
228 .WillByDefault(Return(false));
229 ON_CALL(*item, IsDangerous())
230 .WillByDefault(Return(false));
231 ON_CALL(*item, IsTemporary())
232 .WillByDefault(Return(false));
233 EXPECT_CALL(*download_manager_, GetDownload(id))
234 .WillRepeatedly(Return(item));
235 return item;
238 base::FilePath ChromeDownloadManagerDelegateTest::GetPathInDownloadDir(
239 const char* relative_path) {
240 base::FilePath full_path =
241 test_download_dir_.path().AppendASCII(relative_path);
242 return full_path.NormalizePathSeparators();
245 void ChromeDownloadManagerDelegateTest::SetDefaultDownloadPath(
246 const base::FilePath& path) {
247 pref_service_->SetFilePath(prefs::kDownloadDefaultDirectory, path);
248 pref_service_->SetFilePath(prefs::kSaveFileDefaultDirectory, path);
251 void StoreDownloadTargetInfo(const base::Closure& closure,
252 DownloadTargetInfo* target_info,
253 const base::FilePath& target_path,
254 DownloadItem::TargetDisposition target_disposition,
255 content::DownloadDangerType danger_type,
256 const base::FilePath& intermediate_path) {
257 target_info->target_path = target_path;
258 target_info->target_disposition = target_disposition;
259 target_info->danger_type = danger_type;
260 target_info->intermediate_path = intermediate_path;
261 closure.Run();
264 void ChromeDownloadManagerDelegateTest::DetermineDownloadTarget(
265 DownloadItem* download_item,
266 DownloadTargetInfo* result) {
267 base::RunLoop loop_runner;
268 delegate()->DetermineDownloadTarget(
269 download_item,
270 base::Bind(&StoreDownloadTargetInfo, loop_runner.QuitClosure(), result));
271 loop_runner.Run();
274 void StoreBoolAndRunClosure(const base::Closure& closure,
275 bool* result_storage,
276 bool result) {
277 *result_storage = result;
278 closure.Run();
281 bool ChromeDownloadManagerDelegateTest::CheckForFileExistence(
282 DownloadItem* download_item) {
283 base::RunLoop loop_runner;
284 bool result = false;
285 delegate()->CheckForFileExistence(
286 download_item,
287 base::Bind(&StoreBoolAndRunClosure, loop_runner.QuitClosure(), &result));
288 loop_runner.Run();
289 return result;
292 const base::FilePath& ChromeDownloadManagerDelegateTest::default_download_path()
293 const {
294 return test_download_dir_.path();
297 TestChromeDownloadManagerDelegate*
298 ChromeDownloadManagerDelegateTest::delegate() {
299 return delegate_.get();
302 content::MockDownloadManager*
303 ChromeDownloadManagerDelegateTest::download_manager() {
304 return download_manager_.get();
307 DownloadPrefs* ChromeDownloadManagerDelegateTest::download_prefs() {
308 return delegate_->download_prefs();
311 } // namespace
313 TEST_F(ChromeDownloadManagerDelegateTest, StartDownload_LastSavePath) {
314 GURL download_url("http://example.com/foo.txt");
316 scoped_ptr<content::MockDownloadItem> save_as_download(
317 CreateActiveDownloadItem(0));
318 EXPECT_CALL(*save_as_download, GetURL())
319 .Times(::testing::AnyNumber())
320 .WillRepeatedly(ReturnRef(download_url));
321 EXPECT_CALL(*save_as_download, GetTargetDisposition())
322 .Times(::testing::AnyNumber())
323 .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
325 scoped_ptr<content::MockDownloadItem> automatic_download(
326 CreateActiveDownloadItem(1));
327 EXPECT_CALL(*automatic_download, GetURL())
328 .Times(::testing::AnyNumber())
329 .WillRepeatedly(ReturnRef(download_url));
330 EXPECT_CALL(*automatic_download, GetTargetDisposition())
331 .Times(::testing::AnyNumber())
332 .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_OVERWRITE));
335 // When the prompt is displayed for the first download, the user selects a
336 // path in a different directory.
337 DownloadTargetInfo result;
338 base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt"));
339 base::FilePath user_selected_path(GetPathInDownloadDir("bar/baz.txt"));
340 EXPECT_CALL(*delegate(),
341 MockPromptUserForDownloadPath(save_as_download.get(),
342 expected_prompt_path, _))
343 .WillOnce(Return(user_selected_path));
344 DetermineDownloadTarget(save_as_download.get(), &result);
345 EXPECT_EQ(user_selected_path, result.target_path);
346 VerifyAndClearExpectations();
350 // The prompt path for the second download is the user selected directroy
351 // from the previous download.
352 DownloadTargetInfo result;
353 base::FilePath expected_prompt_path(GetPathInDownloadDir("bar/foo.txt"));
354 EXPECT_CALL(*delegate(),
355 MockPromptUserForDownloadPath(save_as_download.get(),
356 expected_prompt_path, _))
357 .WillOnce(Return(base::FilePath()));
358 DetermineDownloadTarget(save_as_download.get(), &result);
359 VerifyAndClearExpectations();
363 // Start an automatic download. This one should get the default download
364 // path since the last download path only affects Save As downloads.
365 DownloadTargetInfo result;
366 base::FilePath expected_path(GetPathInDownloadDir("foo.txt"));
367 DetermineDownloadTarget(automatic_download.get(), &result);
368 EXPECT_EQ(expected_path, result.target_path);
369 VerifyAndClearExpectations();
373 // The prompt path for the next download should be the default.
374 download_prefs()->SetSaveFilePath(download_prefs()->DownloadPath());
375 DownloadTargetInfo result;
376 base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt"));
377 EXPECT_CALL(*delegate(),
378 MockPromptUserForDownloadPath(save_as_download.get(),
379 expected_prompt_path, _))
380 .WillOnce(Return(base::FilePath()));
381 DetermineDownloadTarget(save_as_download.get(), &result);
382 VerifyAndClearExpectations();
386 TEST_F(ChromeDownloadManagerDelegateTest, CheckForFileExistence) {
387 const char kData[] = "helloworld";
388 const size_t kDataLength = sizeof(kData) - 1;
389 base::FilePath existing_path = default_download_path().AppendASCII("foo");
390 base::FilePath non_existent_path =
391 default_download_path().AppendASCII("bar");
392 base::WriteFile(existing_path, kData, kDataLength);
394 scoped_ptr<content::MockDownloadItem> download_item(
395 CreateActiveDownloadItem(1));
396 EXPECT_CALL(*download_item, GetTargetFilePath())
397 .WillRepeatedly(ReturnRef(existing_path));
398 EXPECT_TRUE(CheckForFileExistence(download_item.get()));
400 download_item.reset(CreateActiveDownloadItem(1));
401 EXPECT_CALL(*download_item, GetTargetFilePath())
402 .WillRepeatedly(ReturnRef(non_existent_path));
403 EXPECT_FALSE(CheckForFileExistence(download_item.get()));