- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / download / chrome_download_manager_delegate_unittest.cc
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.
4
5 #include "base/files/file_path.h"
6 #include "base/files/scoped_temp_dir.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/download/chrome_download_manager_delegate.h"
11 #include "chrome/browser/download/download_prefs.h"
12 #include "chrome/common/pref_names.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "chrome/test/base/testing_pref_service_syncable.h"
15 #include "chrome/test/base/testing_profile.h"
16 #include "content/public/browser/download_interrupt_reasons.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_contents_delegate.h"
19 #include "content/public/test/mock_download_item.h"
20 #include "content/public/test/mock_download_manager.h"
21 #include "content/public/test/test_browser_thread.h"
22 #include "content/public/test/test_renderer_host.h"
23 #include "content/public/test/web_contents_tester.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 using ::testing::AtMost;
28 using ::testing::Invoke;
29 using ::testing::Ref;
30 using ::testing::Return;
31 using ::testing::ReturnPointee;
32 using ::testing::ReturnRef;
33 using ::testing::ReturnRefOfCopy;
34 using ::testing::SetArgPointee;
35 using ::testing::WithArg;
36 using ::testing::_;
37 using content::DownloadItem;
38
39 namespace {
40
41 class MockWebContentsDelegate : public content::WebContentsDelegate {
42  public:
43   virtual ~MockWebContentsDelegate() {}
44 };
45
46 // Google Mock action that posts a task to the current message loop that invokes
47 // the first argument of the mocked method as a callback. Said argument must be
48 // a base::Callback<void(ParamType)>. |result| must be of |ParamType| and is
49 // bound as that parameter.
50 // Example:
51 //   class FooClass {
52 //    public:
53 //     virtual void Foo(base::Callback<void(bool)> callback);
54 //   };
55 //   ...
56 //   EXPECT_CALL(mock_fooclass_instance, Foo(callback))
57 //     .WillOnce(ScheduleCallback(false));
58 ACTION_P(ScheduleCallback, result) {
59   base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, result));
60 }
61
62 // Similar to ScheduleCallback, but binds 2 arguments.
63 ACTION_P2(ScheduleCallback2, result0, result1) {
64   base::MessageLoop::current()->PostTask(
65       FROM_HERE, base::Bind(arg0, result0, result1));
66 }
67
68 struct DownloadTarget {
69   base::FilePath target_path;
70   base::FilePath intermediate_path;
71   DownloadItem::TargetDisposition target_disposition;
72   content::DownloadDangerType danger_type;
73 };
74
75 // Subclass of the ChromeDownloadManagerDelegate that uses a mock
76 // DownloadProtectionService.
77 class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate {
78  public:
79   explicit TestChromeDownloadManagerDelegate(Profile* profile)
80       : ChromeDownloadManagerDelegate(profile) {
81   }
82
83   virtual safe_browsing::DownloadProtectionService*
84       GetDownloadProtectionService() OVERRIDE {
85     return NULL;
86   }
87
88   virtual void NotifyExtensions(
89       content::DownloadItem* download,
90       const base::FilePath& suggested_virtual_path,
91       const NotifyExtensionsCallback& callback) OVERRIDE {
92     callback.Run(base::FilePath(),
93                  DownloadPathReservationTracker::UNIQUIFY);
94   }
95
96   virtual void ReserveVirtualPath(
97       content::DownloadItem* download,
98       const base::FilePath& virtual_path,
99       bool create_directory,
100       DownloadPathReservationTracker::FilenameConflictAction conflict_action,
101       const DownloadPathReservationTracker::ReservedPathCallback& callback)
102       OVERRIDE {
103     // Pretend the path reservation succeeded without any change to
104     // |target_path|.
105     base::MessageLoop::current()->PostTask(
106         FROM_HERE, base::Bind(callback, virtual_path, true));
107   }
108
109   virtual void PromptUserForDownloadPath(
110       DownloadItem* download,
111       const base::FilePath& suggested_path,
112       const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback)
113       OVERRIDE {
114     base::FilePath return_path = MockPromptUserForDownloadPath(download,
115                                                                suggested_path,
116                                                                callback);
117     callback.Run(return_path);
118   }
119
120   MOCK_METHOD3(
121       MockPromptUserForDownloadPath,
122       base::FilePath(
123           content::DownloadItem*,
124           const base::FilePath&,
125           const DownloadTargetDeterminerDelegate::FileSelectedCallback&));
126
127  private:
128   ~TestChromeDownloadManagerDelegate() {}
129 };
130
131 class ChromeDownloadManagerDelegateTest :
132       public ChromeRenderViewHostTestHarness {
133  public:
134   ChromeDownloadManagerDelegateTest();
135
136   // ::testing::Test
137   virtual void SetUp() OVERRIDE;
138   virtual void TearDown() OVERRIDE;
139
140   // Verifies and clears test expectations for |delegate_| and
141   // |download_manager_|.
142   void VerifyAndClearExpectations();
143
144   // Creates MockDownloadItem and sets up default expectations.
145   content::MockDownloadItem* CreateActiveDownloadItem(int32 id);
146
147   // Given the relative path |path|, returns the full path under the temporary
148   // downloads directory.
149   base::FilePath GetPathInDownloadDir(const char* path);
150
151   // Set the kDownloadDefaultDirectory user preference to |path|.
152   void SetDefaultDownloadPath(const base::FilePath& path);
153
154   void DetermineDownloadTarget(DownloadItem* download,
155                                DownloadTarget* result);
156
157   const base::FilePath& default_download_path() const;
158   TestChromeDownloadManagerDelegate* delegate();
159   content::MockDownloadManager* download_manager();
160   DownloadPrefs* download_prefs();
161
162  private:
163   void OnDownloadTargetDone(DownloadTarget* result,
164                             const base::FilePath& target_path,
165                             DownloadItem::TargetDisposition disposition,
166                             content::DownloadDangerType danger_type,
167                             const base::FilePath& intermediate_path);
168
169   TestingPrefServiceSyncable* pref_service_;
170   base::ScopedTempDir test_download_dir_;
171   scoped_ptr<content::MockDownloadManager> download_manager_;
172   scoped_refptr<TestChromeDownloadManagerDelegate> delegate_;
173   MockWebContentsDelegate web_contents_delegate_;
174 };
175
176 ChromeDownloadManagerDelegateTest::ChromeDownloadManagerDelegateTest()
177     : download_manager_(new ::testing::NiceMock<content::MockDownloadManager>) {
178 }
179
180 void ChromeDownloadManagerDelegateTest::SetUp() {
181   ChromeRenderViewHostTestHarness::SetUp();
182
183   CHECK(profile());
184   delegate_ = new TestChromeDownloadManagerDelegate(profile());
185   delegate_->SetDownloadManager(download_manager_.get());
186   pref_service_ = profile()->GetTestingPrefService();
187   web_contents()->SetDelegate(&web_contents_delegate_);
188
189   ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
190   SetDefaultDownloadPath(test_download_dir_.path());
191 }
192
193 void ChromeDownloadManagerDelegateTest::TearDown() {
194   base::RunLoop().RunUntilIdle();
195   delegate_->Shutdown();
196   ChromeRenderViewHostTestHarness::TearDown();
197 }
198
199 void ChromeDownloadManagerDelegateTest::VerifyAndClearExpectations() {
200   ::testing::Mock::VerifyAndClearExpectations(delegate_.get());
201 }
202
203 content::MockDownloadItem*
204     ChromeDownloadManagerDelegateTest::CreateActiveDownloadItem(int32 id) {
205   content::MockDownloadItem* item =
206       new ::testing::NiceMock<content::MockDownloadItem>();
207   ON_CALL(*item, GetBrowserContext())
208       .WillByDefault(Return(profile()));
209   ON_CALL(*item, GetDangerType())
210       .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
211   ON_CALL(*item, GetForcedFilePath())
212       .WillByDefault(ReturnRefOfCopy(base::FilePath()));
213   ON_CALL(*item, GetFullPath())
214       .WillByDefault(ReturnRefOfCopy(base::FilePath()));
215   ON_CALL(*item, GetHash())
216       .WillByDefault(ReturnRefOfCopy(std::string()));
217   ON_CALL(*item, GetId())
218       .WillByDefault(Return(id));
219   ON_CALL(*item, GetLastReason())
220       .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE));
221   ON_CALL(*item, GetReferrerUrl())
222       .WillByDefault(ReturnRefOfCopy(GURL()));
223   ON_CALL(*item, GetState())
224       .WillByDefault(Return(DownloadItem::IN_PROGRESS));
225   ON_CALL(*item, GetTargetFilePath())
226       .WillByDefault(ReturnRefOfCopy(base::FilePath()));
227   ON_CALL(*item, GetTransitionType())
228       .WillByDefault(Return(content::PAGE_TRANSITION_LINK));
229   ON_CALL(*item, GetWebContents())
230       .WillByDefault(Return(web_contents()));
231   ON_CALL(*item, HasUserGesture())
232       .WillByDefault(Return(false));
233   ON_CALL(*item, IsDangerous())
234       .WillByDefault(Return(false));
235   ON_CALL(*item, IsTemporary())
236       .WillByDefault(Return(false));
237   EXPECT_CALL(*download_manager_, GetDownload(id))
238       .WillRepeatedly(Return(item));
239   return item;
240 }
241
242 base::FilePath ChromeDownloadManagerDelegateTest::GetPathInDownloadDir(
243     const char* relative_path) {
244   base::FilePath full_path =
245       test_download_dir_.path().AppendASCII(relative_path);
246   return full_path.NormalizePathSeparators();
247 }
248
249 void ChromeDownloadManagerDelegateTest::SetDefaultDownloadPath(
250     const base::FilePath& path) {
251   pref_service_->SetFilePath(prefs::kDownloadDefaultDirectory, path);
252   pref_service_->SetFilePath(prefs::kSaveFileDefaultDirectory, path);
253 }
254
255 void ChromeDownloadManagerDelegateTest::DetermineDownloadTarget(
256     DownloadItem* download_item,
257     DownloadTarget* result) {
258   base::WeakPtrFactory<ChromeDownloadManagerDelegateTest> factory(this);
259   delegate()->DetermineDownloadTarget(
260       download_item,
261       base::Bind(&ChromeDownloadManagerDelegateTest::OnDownloadTargetDone,
262                  factory.GetWeakPtr(), base::Unretained(result)));
263   base::RunLoop loop_runner;
264   loop_runner.RunUntilIdle();
265 }
266
267 void ChromeDownloadManagerDelegateTest::OnDownloadTargetDone(
268     DownloadTarget* result,
269     const base::FilePath& target_path,
270     DownloadItem::TargetDisposition target_disposition,
271     content::DownloadDangerType danger_type,
272     const base::FilePath& intermediate_path) {
273   result->target_path = target_path;
274   result->intermediate_path = intermediate_path;
275   result->target_disposition = target_disposition;
276   result->danger_type = danger_type;
277 }
278
279 const base::FilePath& ChromeDownloadManagerDelegateTest::default_download_path()
280     const {
281   return test_download_dir_.path();
282 }
283
284 TestChromeDownloadManagerDelegate*
285     ChromeDownloadManagerDelegateTest::delegate() {
286   return delegate_.get();
287 }
288
289 content::MockDownloadManager*
290     ChromeDownloadManagerDelegateTest::download_manager() {
291   return download_manager_.get();
292 }
293
294 DownloadPrefs* ChromeDownloadManagerDelegateTest::download_prefs() {
295   return delegate_->download_prefs();
296 }
297
298 }  // namespace
299
300 TEST_F(ChromeDownloadManagerDelegateTest, StartDownload_LastSavePath) {
301   GURL download_url("http://example.com/foo.txt");
302
303   scoped_ptr<content::MockDownloadItem> save_as_download(
304       CreateActiveDownloadItem(0));
305   EXPECT_CALL(*save_as_download, GetURL())
306       .Times(::testing::AnyNumber())
307       .WillRepeatedly(ReturnRef(download_url));
308   EXPECT_CALL(*save_as_download, GetTargetDisposition())
309       .Times(::testing::AnyNumber())
310       .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
311
312   scoped_ptr<content::MockDownloadItem> automatic_download(
313       CreateActiveDownloadItem(1));
314   EXPECT_CALL(*automatic_download, GetURL())
315       .Times(::testing::AnyNumber())
316       .WillRepeatedly(ReturnRef(download_url));
317   EXPECT_CALL(*automatic_download, GetTargetDisposition())
318       .Times(::testing::AnyNumber())
319       .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_OVERWRITE));
320
321   {
322     // When the prompt is displayed for the first download, the user selects a
323     // path in a different directory.
324     DownloadTarget result;
325     base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt"));
326     base::FilePath user_selected_path(GetPathInDownloadDir("bar/baz.txt"));
327     EXPECT_CALL(*delegate(),
328                 MockPromptUserForDownloadPath(save_as_download.get(),
329                                               expected_prompt_path, _))
330         .WillOnce(Return(user_selected_path));
331     DetermineDownloadTarget(save_as_download.get(), &result);
332     EXPECT_EQ(user_selected_path, result.target_path);
333     VerifyAndClearExpectations();
334   }
335
336   {
337     // The prompt path for the second download is the user selected directroy
338     // from the previous download.
339     DownloadTarget result;
340     base::FilePath expected_prompt_path(GetPathInDownloadDir("bar/foo.txt"));
341     EXPECT_CALL(*delegate(),
342                 MockPromptUserForDownloadPath(save_as_download.get(),
343                                               expected_prompt_path, _))
344         .WillOnce(Return(base::FilePath()));
345     DetermineDownloadTarget(save_as_download.get(), &result);
346     VerifyAndClearExpectations();
347   }
348
349   {
350     // Start an automatic download. This one should get the default download
351     // path since the last download path only affects Save As downloads.
352     DownloadTarget result;
353     base::FilePath expected_path(GetPathInDownloadDir("foo.txt"));
354     DetermineDownloadTarget(automatic_download.get(), &result);
355     EXPECT_EQ(expected_path, result.target_path);
356     VerifyAndClearExpectations();
357   }
358
359   {
360     // The prompt path for the next download should be the default.
361     download_prefs()->SetSaveFilePath(download_prefs()->DownloadPath());
362     DownloadTarget result;
363     base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt"));
364     EXPECT_CALL(*delegate(),
365                 MockPromptUserForDownloadPath(save_as_download.get(),
366                                               expected_prompt_path, _))
367         .WillOnce(Return(base::FilePath()));
368     DetermineDownloadTarget(save_as_download.get(), &result);
369     VerifyAndClearExpectations();
370   }
371 }