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