- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / download / download_target_determiner_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/observer_list.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/run_loop.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_util.h"
13 #include "base/value_conversions.h"
14 #include "chrome/browser/download/chrome_download_manager_delegate.h"
15 #include "chrome/browser/download/download_extensions.h"
16 #include "chrome/browser/download/download_prefs.h"
17 #include "chrome/browser/download/download_target_determiner.h"
18 #include "chrome/browser/history/history_service.h"
19 #include "chrome/browser/history/history_service_factory.h"
20 #include "chrome/browser/history/history_types.h"
21 #include "chrome/common/extensions/extension.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
24 #include "chrome/test/base/testing_pref_service_syncable.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "content/public/browser/download_interrupt_reasons.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/browser/web_contents_delegate.h"
29 #include "content/public/test/mock_download_item.h"
30 #include "content/public/test/test_browser_thread.h"
31 #include "content/public/test/test_renderer_host.h"
32 #include "content/public/test/web_contents_tester.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35
36 using ::testing::AnyNumber;
37 using ::testing::Invoke;
38 using ::testing::Ref;
39 using ::testing::Return;
40 using ::testing::ReturnRef;
41 using ::testing::ReturnRefOfCopy;
42 using ::testing::Truly;
43 using ::testing::WithArg;
44 using ::testing::_;
45 using content::DownloadItem;
46
47 namespace {
48
49 // No-op delegate.
50 class NullWebContentsDelegate : public content::WebContentsDelegate {
51  public:
52   NullWebContentsDelegate() {}
53   virtual ~NullWebContentsDelegate() {}
54 };
55
56 // Google Mock action that posts a task to the current message loop that invokes
57 // the first argument of the mocked method as a callback. Said argument must be
58 // a base::Callback<void(ParamType)>. |result| must be of |ParamType| and is
59 // bound as that parameter.
60 // Example:
61 //   class FooClass {
62 //    public:
63 //     virtual void Foo(base::Callback<void(bool)> callback);
64 //   };
65 //   ...
66 //   EXPECT_CALL(mock_fooclass_instance, Foo(callback))
67 //     .WillOnce(ScheduleCallback(false));
68 ACTION_P(ScheduleCallback, result0) {
69   base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, result0));
70 }
71
72 // Similar to ScheduleCallback, but binds 2 arguments.
73 ACTION_P2(ScheduleCallback2, result0, result1) {
74   base::MessageLoop::current()->PostTask(
75       FROM_HERE, base::Bind(arg0, result0, result1));
76 }
77
78 // Used with DownloadTestCase. Indicates the type of test case. The expectations
79 // for the test is set based on the type.
80 enum TestCaseType {
81   SAVE_AS,
82   AUTOMATIC,
83   FORCED  // Requires that forced_file_path be non-empty.
84 };
85
86 // Used with DownloadTestCase. Type of intermediate filename to expect.
87 enum TestCaseExpectIntermediate {
88   EXPECT_CRDOWNLOAD,   // Expect path/to/target.crdownload.
89   EXPECT_UNCONFIRMED,  // Expect path/to/Unconfirmed xxx.crdownload.
90   EXPECT_LOCAL_PATH,   // Expect target path.
91 };
92
93 // Typical download test case. Used with
94 // DownloadTargetDeterminerTest::RunTestCase().
95 struct DownloadTestCase {
96   // Type of test.
97   TestCaseType test_type;
98
99   // Expected danger type. Verified at the end of target determination.
100   content::DownloadDangerType expected_danger_type;
101
102   // Value of DownloadItem::GetURL()
103   const char* url;
104
105   // Value of DownloadItem::GetMimeType()
106   const char* mime_type;
107
108   // Should be non-empty if |test_type| == FORCED. Value of GetForcedFilePath().
109   const base::FilePath::CharType* forced_file_path;
110
111   // Expected virtual path. Specified relative to the virtual download path. If
112   // empty, assumed to be the same as |expected_local_path|.
113   const base::FilePath::CharType* expected_virtual_path;
114
115   // Expected local path. Specified relative to the test download path.
116   const base::FilePath::CharType* expected_local_path;
117
118   // Expected target disposition. If this is TARGET_DISPOSITION_PROMPT, then the
119   // test run will expect ChromeDownloadManagerDelegate to prompt the user for a
120   // download location.
121   DownloadItem::TargetDisposition expected_disposition;
122
123   // Type of intermediate path to expect.
124   TestCaseExpectIntermediate expected_intermediate;
125 };
126
127 class MockDownloadTargetDeterminerDelegate
128     : public DownloadTargetDeterminerDelegate {
129  public:
130   MOCK_METHOD3(CheckDownloadUrl,
131                void(content::DownloadItem*, const base::FilePath&,
132                     const CheckDownloadUrlCallback&));
133   MOCK_METHOD3(NotifyExtensions,
134                void(content::DownloadItem*, const base::FilePath&,
135                     const NotifyExtensionsCallback&));
136   MOCK_METHOD3(PromptUserForDownloadPath,
137                void(content::DownloadItem*, const base::FilePath&,
138                     const FileSelectedCallback&));
139   MOCK_METHOD3(DetermineLocalPath,
140                void(DownloadItem*, const base::FilePath&,
141                     const LocalPathCallback&));
142   MOCK_METHOD5(ReserveVirtualPath,
143                void(DownloadItem*, const base::FilePath&, bool,
144                     DownloadPathReservationTracker::FilenameConflictAction,
145                     const ReservedPathCallback&));
146
147   void SetupDefaults() {
148     ON_CALL(*this, CheckDownloadUrl(_, _, _))
149         .WillByDefault(WithArg<2>(
150             ScheduleCallback(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)));
151     ON_CALL(*this, NotifyExtensions(_, _, _))
152         .WillByDefault(WithArg<2>(
153             ScheduleCallback2(base::FilePath(),
154                               DownloadPathReservationTracker::UNIQUIFY)));
155     ON_CALL(*this, ReserveVirtualPath(_, _, _, _, _))
156         .WillByDefault(Invoke(
157             &MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath));
158     ON_CALL(*this, PromptUserForDownloadPath(_, _, _))
159         .WillByDefault(Invoke(
160             &MockDownloadTargetDeterminerDelegate::NullPromptUser));
161     ON_CALL(*this, DetermineLocalPath(_, _, _))
162         .WillByDefault(Invoke(
163             &MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath));
164   }
165  private:
166   static void NullReserveVirtualPath(
167       DownloadItem* download,
168       const base::FilePath& virtual_path,
169       bool create_directory,
170       DownloadPathReservationTracker::FilenameConflictAction conflict_action,
171       const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback);
172   static void NullPromptUser(
173       DownloadItem* download, const base::FilePath& suggested_path,
174       const FileSelectedCallback& callback);
175   static void NullDetermineLocalPath(
176       DownloadItem* download, const base::FilePath& virtual_path,
177       const LocalPathCallback& callback);
178 };
179
180 class DownloadTargetDeterminerTest : public ChromeRenderViewHostTestHarness {
181  public:
182   // ::testing::Test
183   virtual void SetUp() OVERRIDE;
184   virtual void TearDown() OVERRIDE;
185
186   // Creates MockDownloadItem and sets up default expectations.
187   content::MockDownloadItem* CreateActiveDownloadItem(
188       int32 id,
189       const DownloadTestCase& test_case);
190
191   // Sets the AutoOpenBasedOnExtension user preference for |path|.
192   void EnableAutoOpenBasedOnExtension(const base::FilePath& path);
193
194   // Set the kDownloadDefaultDirectory managed preference to |path|.
195   void SetManagedDownloadPath(const base::FilePath& path);
196
197   // Set the kPromptForDownload user preference to |prompt|.
198   void SetPromptForDownload(bool prompt);
199
200   // Given the relative path |path|, returns the full path under the temporary
201   // downloads directory.
202   base::FilePath GetPathInDownloadDir(const base::FilePath::StringType& path);
203
204   // Run |test_case| using |item|.
205   void RunTestCase(const DownloadTestCase& test_case,
206                    const base::FilePath& initial_virtual_path,
207                    content::MockDownloadItem* item);
208
209   // Run through |test_case_count| tests in |test_cases|. A new MockDownloadItem
210   // will be created for each test case and destroyed when the test case is
211   // complete.
212   void RunTestCasesWithActiveItem(const DownloadTestCase test_cases[],
213                                   size_t test_case_count);
214
215   // Verifies that |target_path|, |disposition|, |expected_danger_type| and
216   // |intermediate_path| matches the expectations of |test_case|. Posts
217   // |closure| to the current message loop when done.
218   void DownloadTargetVerifier(const base::Closure& closure,
219                               const DownloadTestCase& test_case,
220                               const base::FilePath& local_path,
221                               DownloadItem::TargetDisposition disposition,
222                               content::DownloadDangerType danger_type,
223                               const base::FilePath& intermediate_path);
224
225   const base::FilePath& test_download_dir() const {
226     return test_download_dir_.path();
227   }
228
229   const base::FilePath& test_virtual_dir() const {
230     return test_virtual_dir_;
231   }
232
233   MockDownloadTargetDeterminerDelegate* delegate() {
234     return &delegate_;
235   }
236
237   DownloadPrefs* download_prefs() {
238     return download_prefs_.get();
239   }
240
241  private:
242   scoped_ptr<DownloadPrefs> download_prefs_;
243   ::testing::NiceMock<MockDownloadTargetDeterminerDelegate> delegate_;
244   NullWebContentsDelegate web_contents_delegate_;
245   base::ScopedTempDir test_download_dir_;
246   base::FilePath test_virtual_dir_;
247 };
248
249 void DownloadTargetDeterminerTest::SetUp() {
250   ChromeRenderViewHostTestHarness::SetUp();
251   CHECK(profile());
252   download_prefs_.reset(new DownloadPrefs(profile()));
253   web_contents()->SetDelegate(&web_contents_delegate_);
254   ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
255   test_virtual_dir_ = test_download_dir().Append(FILE_PATH_LITERAL("virtual"));
256   download_prefs_->SetDownloadPath(test_download_dir());
257   delegate_.SetupDefaults();
258 }
259
260 void DownloadTargetDeterminerTest::TearDown() {
261   download_prefs_.reset();
262   ChromeRenderViewHostTestHarness::TearDown();
263 }
264
265 content::MockDownloadItem*
266 DownloadTargetDeterminerTest::CreateActiveDownloadItem(
267     int32 id,
268     const DownloadTestCase& test_case) {
269   content::MockDownloadItem* item =
270       new ::testing::NiceMock<content::MockDownloadItem>();
271   GURL download_url(test_case.url);
272   std::vector<GURL> url_chain;
273   url_chain.push_back(download_url);
274   base::FilePath forced_file_path =
275       GetPathInDownloadDir(test_case.forced_file_path);
276   DownloadItem::TargetDisposition initial_disposition =
277       (test_case.test_type == SAVE_AS) ?
278       DownloadItem::TARGET_DISPOSITION_PROMPT :
279       DownloadItem::TARGET_DISPOSITION_OVERWRITE;
280   EXPECT_EQ(test_case.test_type == FORCED,
281             !forced_file_path.empty());
282
283   ON_CALL(*item, GetBrowserContext())
284       .WillByDefault(Return(profile()));
285   ON_CALL(*item, GetDangerType())
286       .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
287   ON_CALL(*item, GetForcedFilePath())
288       .WillByDefault(ReturnRefOfCopy(forced_file_path));
289   ON_CALL(*item, GetFullPath())
290       .WillByDefault(ReturnRefOfCopy(base::FilePath()));
291   ON_CALL(*item, GetHash())
292       .WillByDefault(ReturnRefOfCopy(std::string()));
293   ON_CALL(*item, GetId())
294       .WillByDefault(Return(id));
295   ON_CALL(*item, GetLastReason())
296       .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE));
297   ON_CALL(*item, GetMimeType())
298       .WillByDefault(Return(test_case.mime_type));
299   ON_CALL(*item, GetReferrerUrl())
300       .WillByDefault(ReturnRefOfCopy(download_url));
301   ON_CALL(*item, GetState())
302       .WillByDefault(Return(DownloadItem::IN_PROGRESS));
303   ON_CALL(*item, GetTargetDisposition())
304       .WillByDefault(Return(initial_disposition));
305   ON_CALL(*item, GetTargetFilePath())
306       .WillByDefault(ReturnRefOfCopy(base::FilePath()));
307   ON_CALL(*item, GetTransitionType())
308       .WillByDefault(Return(content::PAGE_TRANSITION_LINK));
309   ON_CALL(*item, GetURL())
310       .WillByDefault(ReturnRefOfCopy(download_url));
311   ON_CALL(*item, GetUrlChain())
312       .WillByDefault(ReturnRefOfCopy(url_chain));
313   ON_CALL(*item, GetWebContents())
314       .WillByDefault(Return(web_contents()));
315   ON_CALL(*item, HasUserGesture())
316       .WillByDefault(Return(true));
317   ON_CALL(*item, IsDangerous())
318       .WillByDefault(Return(false));
319   ON_CALL(*item, IsTemporary())
320       .WillByDefault(Return(false));
321   return item;
322 }
323
324 void DownloadTargetDeterminerTest::EnableAutoOpenBasedOnExtension(
325     const base::FilePath& path) {
326   EXPECT_TRUE(download_prefs_->EnableAutoOpenBasedOnExtension(path));
327 }
328
329 void DownloadTargetDeterminerTest::SetManagedDownloadPath(
330     const base::FilePath& path) {
331   profile()->GetTestingPrefService()->
332       SetManagedPref(prefs::kDownloadDefaultDirectory,
333                      base::CreateFilePathValue(path));
334 }
335
336 void DownloadTargetDeterminerTest::SetPromptForDownload(bool prompt) {
337   profile()->GetTestingPrefService()->
338       SetBoolean(prefs::kPromptForDownload, prompt);
339 }
340
341 base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir(
342     const base::FilePath::StringType& relative_path) {
343   if (relative_path.empty())
344     return base::FilePath();
345   base::FilePath full_path(test_download_dir().Append(relative_path));
346   return full_path.NormalizePathSeparators();
347 }
348
349 void DownloadTargetDeterminerTest::RunTestCase(
350     const DownloadTestCase& test_case,
351     const base::FilePath& initial_virtual_path,
352     content::MockDownloadItem* item) {
353   // Kick off the test.
354   base::WeakPtrFactory<DownloadTargetDeterminerTest> factory(this);
355   base::RunLoop run_loop;
356   DownloadTargetDeterminer::Start(
357       item, initial_virtual_path, download_prefs_.get(), delegate(),
358       base::Bind(&DownloadTargetDeterminerTest::DownloadTargetVerifier,
359                  factory.GetWeakPtr(), run_loop.QuitClosure(), test_case));
360   run_loop.Run();
361   ::testing::Mock::VerifyAndClearExpectations(delegate());
362 }
363
364 void DownloadTargetDeterminerTest::RunTestCasesWithActiveItem(
365     const DownloadTestCase test_cases[],
366     size_t test_case_count) {
367   for (size_t i = 0; i < test_case_count; ++i) {
368     scoped_ptr<content::MockDownloadItem> item(
369         CreateActiveDownloadItem(i, test_cases[i]));
370     SCOPED_TRACE(testing::Message() << "Running test case " << i);
371     RunTestCase(test_cases[i], base::FilePath(), item.get());
372   }
373 }
374
375 void DownloadTargetDeterminerTest::DownloadTargetVerifier(
376     const base::Closure& closure,
377     const DownloadTestCase& test_case,
378     const base::FilePath& local_path,
379     DownloadItem::TargetDisposition disposition,
380     content::DownloadDangerType danger_type,
381     const base::FilePath& intermediate_path) {
382   base::FilePath expected_local_path(
383       GetPathInDownloadDir(test_case.expected_local_path));
384   EXPECT_EQ(expected_local_path.value(), local_path.value());
385   EXPECT_EQ(test_case.expected_disposition, disposition);
386   EXPECT_EQ(test_case.expected_danger_type, danger_type);
387
388   switch (test_case.expected_intermediate) {
389     case EXPECT_CRDOWNLOAD:
390       EXPECT_EQ(DownloadTargetDeterminer::GetCrDownloadPath(local_path).value(),
391                 intermediate_path.value());
392       break;
393
394     case EXPECT_UNCONFIRMED:
395       // The paths (in English) look like: /path/Unconfirmed xxx.crdownload.
396       // Of this, we only check that the path is:
397       // 1. Not "/path/target.crdownload",
398       // 2. Points to the same directory as the target.
399       // 3. Has extension ".crdownload".
400       // 4. Basename starts with "Unconfirmed ".
401       EXPECT_NE(DownloadTargetDeterminer::GetCrDownloadPath(expected_local_path)
402                     .value(),
403                 intermediate_path.value());
404       EXPECT_EQ(expected_local_path.DirName().value(),
405                 intermediate_path.DirName().value());
406       EXPECT_TRUE(intermediate_path.MatchesExtension(
407           FILE_PATH_LITERAL(".crdownload")));
408       EXPECT_EQ(0u, intermediate_path.BaseName().value().find(
409           FILE_PATH_LITERAL("Unconfirmed ")));
410       break;
411
412     case EXPECT_LOCAL_PATH:
413       EXPECT_EQ(expected_local_path.value(), intermediate_path.value());
414       break;
415   }
416   base::MessageLoop::current()->PostTask(FROM_HERE, closure);
417 }
418
419 // static
420 void MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath(
421     DownloadItem* download,
422     const base::FilePath& virtual_path,
423     bool create_directory,
424     DownloadPathReservationTracker::FilenameConflictAction conflict_action,
425     const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
426   callback.Run(virtual_path, true);
427 }
428
429 // static
430 void MockDownloadTargetDeterminerDelegate::NullPromptUser(
431     DownloadItem* download, const base::FilePath& suggested_path,
432     const FileSelectedCallback& callback) {
433   callback.Run(suggested_path);
434 }
435
436 // static
437 void MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath(
438     DownloadItem* download, const base::FilePath& virtual_path,
439     const LocalPathCallback& callback) {
440   callback.Run(virtual_path);
441 }
442
443 // NotifyExtensions implementation that overrides the path so that the target
444 // file is in a subdirectory called 'overridden'. If the extension is '.remove',
445 // the extension is removed.
446 void NotifyExtensionsOverridePath(
447     content::DownloadItem* download,
448     const base::FilePath& path,
449     const DownloadTargetDeterminerDelegate::NotifyExtensionsCallback&
450         callback) {
451   base::FilePath new_path =
452       base::FilePath()
453       .AppendASCII("overridden")
454       .Append(path.BaseName());
455   if (new_path.MatchesExtension(FILE_PATH_LITERAL(".remove")))
456     new_path = new_path.RemoveExtension();
457   callback.Run(new_path, DownloadPathReservationTracker::UNIQUIFY);
458 }
459
460 void CheckDownloadUrlCheckExes(
461     content::DownloadItem* download,
462     const base::FilePath& path,
463     const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback&
464         callback) {
465   if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
466     callback.Run(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT);
467   else
468     callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
469 }
470
471 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_Basic) {
472   const DownloadTestCase kBasicTestCases[] = {
473     {
474       // 0: Automatic Safe
475       AUTOMATIC,
476       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
477       "http://example.com/foo.txt", "text/plain",
478       FILE_PATH_LITERAL(""),
479
480       FILE_PATH_LITERAL(""),
481       FILE_PATH_LITERAL("foo.txt"),
482       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
483
484       EXPECT_CRDOWNLOAD
485     },
486
487     {
488       // 1: Save_As Safe
489       SAVE_AS,
490       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
491       "http://example.com/foo.txt", "text/plain",
492       FILE_PATH_LITERAL(""),
493
494       FILE_PATH_LITERAL(""),
495       FILE_PATH_LITERAL("foo.txt"),
496       DownloadItem::TARGET_DISPOSITION_PROMPT,
497
498       EXPECT_CRDOWNLOAD
499     },
500
501     {
502       // 2: Automatic Dangerous
503       AUTOMATIC,
504       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
505       "http://example.com/foo.html", "",
506       FILE_PATH_LITERAL(""),
507
508       FILE_PATH_LITERAL(""),
509       FILE_PATH_LITERAL("foo.html"),
510       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
511
512       EXPECT_UNCONFIRMED
513     },
514
515     {
516       // 3: Forced Safe
517       FORCED,
518       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
519       "http://example.com/foo.txt", "",
520       FILE_PATH_LITERAL("forced-foo.txt"),
521
522       FILE_PATH_LITERAL(""),
523       FILE_PATH_LITERAL("forced-foo.txt"),
524       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
525
526       EXPECT_LOCAL_PATH
527     },
528   };
529
530   // The test assumes that .html files have a danger level of
531   // ALLOW_ON_USER_GESTURE.
532   ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
533             download_util::GetFileDangerLevel(
534                 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
535   RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
536 }
537
538 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_CancelSaveAs) {
539   const DownloadTestCase kCancelSaveAsTestCases[] = {
540     {
541       // 0: Save_As Safe, Cancelled.
542       SAVE_AS,
543       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
544       "http://example.com/foo.txt", "text/plain",
545       FILE_PATH_LITERAL(""),
546
547       FILE_PATH_LITERAL(""),
548       FILE_PATH_LITERAL(""),
549       DownloadItem::TARGET_DISPOSITION_PROMPT,
550
551       EXPECT_LOCAL_PATH
552     }
553   };
554   ON_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
555       .WillByDefault(WithArg<2>(ScheduleCallback(base::FilePath())));
556   RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
557                              arraysize(kCancelSaveAsTestCases));
558 }
559
560 // The SafeBrowsing check is performed early. Make sure that a download item
561 // that has been marked as DANGEROUS_URL behaves correctly.
562 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DangerousUrl) {
563   const DownloadTestCase kSafeBrowsingTestCases[] = {
564     {
565       // 0: Automatic Dangerous URL
566       AUTOMATIC,
567       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
568       "http://phishing.example.com/foo.txt", "",
569       FILE_PATH_LITERAL(""),
570
571       FILE_PATH_LITERAL(""),
572       FILE_PATH_LITERAL("foo.txt"),
573       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
574
575       EXPECT_UNCONFIRMED
576     },
577
578     {
579       // 1: Save As Dangerous URL
580       SAVE_AS,
581       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
582       "http://phishing.example.com/foo.txt", "",
583       FILE_PATH_LITERAL(""),
584
585       FILE_PATH_LITERAL(""),
586       FILE_PATH_LITERAL("foo.txt"),
587       DownloadItem::TARGET_DISPOSITION_PROMPT,
588
589       EXPECT_UNCONFIRMED
590     },
591
592     {
593       // 2: Forced Dangerous URL
594       FORCED,
595       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
596       "http://phishing.example.com/foo.txt", "",
597       FILE_PATH_LITERAL("forced-foo.txt"),
598
599       FILE_PATH_LITERAL(""),
600       FILE_PATH_LITERAL("forced-foo.txt"),
601       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
602
603       EXPECT_UNCONFIRMED
604     },
605
606     {
607       // 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes
608       // precendence.
609       AUTOMATIC,
610       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
611       "http://phishing.example.com/foo.html", "",
612       FILE_PATH_LITERAL(""),
613
614       FILE_PATH_LITERAL(""),
615       FILE_PATH_LITERAL("foo.html"),
616       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
617
618       EXPECT_UNCONFIRMED
619     },
620
621     {
622       // 4: Save As Dangerous URL + Dangerous file
623       SAVE_AS,
624       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
625       "http://phishing.example.com/foo.html", "",
626       FILE_PATH_LITERAL(""),
627
628       FILE_PATH_LITERAL(""),
629       FILE_PATH_LITERAL("foo.html"),
630       DownloadItem::TARGET_DISPOSITION_PROMPT,
631
632       EXPECT_UNCONFIRMED
633     },
634
635     {
636       // 5: Forced Dangerous URL + Dangerous file
637       FORCED,
638       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
639       "http://phishing.example.com/foo.html", "",
640       FILE_PATH_LITERAL("forced-foo.html"),
641
642       FILE_PATH_LITERAL(""),
643       FILE_PATH_LITERAL("forced-foo.html"),
644       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
645
646       EXPECT_UNCONFIRMED
647     },
648   };
649
650   ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
651       .WillByDefault(WithArg<2>(ScheduleCallback(
652           content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
653   RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
654                              arraysize(kSafeBrowsingTestCases));
655 }
656
657 // The SafeBrowsing check is performed early. Make sure that a download item
658 // that has been marked as MAYBE_DANGEROUS_CONTENT behaves correctly.
659 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_MaybeDangerousContent) {
660   const DownloadTestCase kSafeBrowsingTestCases[] = {
661     {
662       // 0: Automatic Maybe dangerous content
663       AUTOMATIC,
664       content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
665       "http://phishing.example.com/foo.exe", "",
666       FILE_PATH_LITERAL(""),
667
668       FILE_PATH_LITERAL(""),
669       FILE_PATH_LITERAL("foo.exe"),
670       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
671
672       EXPECT_UNCONFIRMED
673     },
674
675     {
676       // 1: Save As Maybe dangerous content
677       SAVE_AS,
678       content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
679       "http://phishing.example.com/foo.exe", "",
680       FILE_PATH_LITERAL(""),
681
682       FILE_PATH_LITERAL(""),
683       FILE_PATH_LITERAL("foo.exe"),
684       DownloadItem::TARGET_DISPOSITION_PROMPT,
685
686       EXPECT_UNCONFIRMED
687     },
688
689     {
690       // 2: Forced Maybe dangerous content
691       FORCED,
692       content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
693       "http://phishing.example.com/foo.exe", "",
694       FILE_PATH_LITERAL("forced-foo.exe"),
695
696       FILE_PATH_LITERAL(""),
697       FILE_PATH_LITERAL("forced-foo.exe"),
698       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
699
700       EXPECT_UNCONFIRMED
701     },
702   };
703
704   ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
705       .WillByDefault(WithArg<2>(ScheduleCallback(
706           content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
707   RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
708                              arraysize(kSafeBrowsingTestCases));
709 }
710
711 // Test whether the last saved directory is used for 'Save As' downloads.
712 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LastSavePath) {
713   const DownloadTestCase kLastSavePathTestCasesPre[] = {
714     {
715       // 0: If the last save path is empty, then the default download directory
716       //    should be used.
717       SAVE_AS,
718       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
719       "http://example.com/foo.txt", "text/plain",
720       FILE_PATH_LITERAL(""),
721
722       FILE_PATH_LITERAL(""),
723       FILE_PATH_LITERAL("foo.txt"),
724       DownloadItem::TARGET_DISPOSITION_PROMPT,
725
726       EXPECT_CRDOWNLOAD
727     }
728   };
729
730   // These test cases are run with a last save path set to a non-emtpy local
731   // download directory.
732   const DownloadTestCase kLastSavePathTestCasesPost[] = {
733     {
734       // 0: This test case is run with the last download directory set to
735       //    '<test_download_dir()>/foo'.
736       SAVE_AS,
737       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
738       "http://example.com/foo.txt", "text/plain",
739       FILE_PATH_LITERAL(""),
740
741       FILE_PATH_LITERAL(""),
742       FILE_PATH_LITERAL("foo/foo.txt"),
743       DownloadItem::TARGET_DISPOSITION_PROMPT,
744
745       EXPECT_CRDOWNLOAD
746     },
747
748     {
749       // 1: Start an automatic download. This should be saved to the user's
750       //    default download directory and not the last used Save As directory.
751       AUTOMATIC,
752       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
753       "http://example.com/foo.txt", "text/plain",
754       FILE_PATH_LITERAL(""),
755
756       FILE_PATH_LITERAL(""),
757       FILE_PATH_LITERAL("foo.txt"),
758       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
759
760       EXPECT_CRDOWNLOAD
761     },
762   };
763
764   // This test case is run with the last save path set to a non-empty virtual
765   // directory.
766   const DownloadTestCase kLastSavePathTestCasesVirtual[] = {
767     {
768       SAVE_AS,
769       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
770       "http://example.com/foo.txt", "text/plain",
771       FILE_PATH_LITERAL(""),
772
773       FILE_PATH_LITERAL("virtual/foo/foo.txt"),
774       FILE_PATH_LITERAL("bar.txt"),
775       DownloadItem::TARGET_DISPOSITION_PROMPT,
776
777       EXPECT_LOCAL_PATH
778     },
779   };
780
781   {
782     SCOPED_TRACE(testing::Message()
783                  << "Running with default download path");
784     base::FilePath prompt_path =
785         GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
786     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
787     RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
788                                arraysize(kLastSavePathTestCasesPre));
789   }
790
791   // Try with a non-empty last save path.
792   {
793     SCOPED_TRACE(testing::Message()
794                  << "Running with local last_selected_directory");
795     download_prefs()->SetSaveFilePath(test_download_dir().AppendASCII("foo"));
796     base::FilePath prompt_path =
797         GetPathInDownloadDir(FILE_PATH_LITERAL("foo/foo.txt"));
798     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
799     RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
800                                arraysize(kLastSavePathTestCasesPost));
801   }
802
803   // And again, but this time use a virtual directory.
804   {
805     SCOPED_TRACE(testing::Message()
806                  << "Running with virtual last_selected_directory");
807     base::FilePath last_selected_dir = test_virtual_dir().AppendASCII("foo");
808     base::FilePath virtual_path = last_selected_dir.AppendASCII("foo.txt");
809     download_prefs()->SetSaveFilePath(last_selected_dir);
810     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
811         _, last_selected_dir.AppendASCII("foo.txt"), _));
812     EXPECT_CALL(*delegate(), DetermineLocalPath(_, virtual_path, _))
813         .WillOnce(WithArg<2>(ScheduleCallback(
814             GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")))));
815     RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
816                                arraysize(kLastSavePathTestCasesVirtual));
817   }
818 }
819
820 // These tests are run with the default downloads folder set to a virtual
821 // directory.
822 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DefaultVirtual) {
823   // The default download directory is the virutal path.
824   download_prefs()->SetDownloadPath(test_virtual_dir());
825
826   {
827     SCOPED_TRACE(testing::Message() << "Automatic Safe Download");
828     const DownloadTestCase kAutomaticDownloadToVirtualDir = {
829       AUTOMATIC,
830       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
831       "http://example.com/foo.txt", "text/plain",
832       FILE_PATH_LITERAL(""),
833
834       // Downloaded to default virtual directory.
835       FILE_PATH_LITERAL("virtual/foo.txt"),
836       FILE_PATH_LITERAL("foo-local.txt"),
837       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
838
839       EXPECT_LOCAL_PATH
840     };
841     EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
842         .WillOnce(WithArg<2>(ScheduleCallback(
843             GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
844     RunTestCasesWithActiveItem(&kAutomaticDownloadToVirtualDir, 1);
845   }
846
847   {
848     SCOPED_TRACE(testing::Message() << "Save As to virtual directory");
849     const DownloadTestCase kSaveAsToVirtualDir = {
850       SAVE_AS,
851       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
852       "http://example.com/bar.txt", "text/plain",
853       FILE_PATH_LITERAL(""),
854
855       // The response to the download prompt is to choose the 'prompted.txt'
856       // virtual path.
857       FILE_PATH_LITERAL("virtual/prompted.txt"),
858       FILE_PATH_LITERAL("foo-local.txt"),
859       DownloadItem::TARGET_DISPOSITION_PROMPT,
860
861       EXPECT_LOCAL_PATH
862     };
863     EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
864         .WillOnce(WithArg<2>(ScheduleCallback(
865             GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
866     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
867         _, test_virtual_dir().AppendASCII("bar.txt"), _))
868         .WillOnce(WithArg<2>(ScheduleCallback(
869             test_virtual_dir().AppendASCII("prompted.txt"))));
870     RunTestCasesWithActiveItem(&kSaveAsToVirtualDir, 1);
871   }
872
873   {
874     SCOPED_TRACE(testing::Message() << "Save As to local directory");
875     const DownloadTestCase kSaveAsToLocalDir = {
876       SAVE_AS,
877       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
878       "http://example.com/bar.txt", "text/plain",
879       FILE_PATH_LITERAL(""),
880
881       // Response to the 'Save As' is to choose the local path for 'foo-x.txt'.
882       FILE_PATH_LITERAL(""),
883       FILE_PATH_LITERAL("foo-x.txt"),
884       DownloadItem::TARGET_DISPOSITION_PROMPT,
885
886       EXPECT_CRDOWNLOAD
887     };
888     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
889         _, test_virtual_dir().AppendASCII("bar.txt"), _))
890         .WillOnce(WithArg<2>(ScheduleCallback(
891             GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")))));
892     RunTestCasesWithActiveItem(&kSaveAsToLocalDir, 1);
893   }
894
895   {
896     SCOPED_TRACE(testing::Message() << "Forced safe download");
897     const DownloadTestCase kForcedSafe = {
898       FORCED,
899       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
900       "http://example.com/foo.txt", "",
901       FILE_PATH_LITERAL("forced-foo.txt"),
902
903       // Forced paths should be left as-is.
904       FILE_PATH_LITERAL(""),
905       FILE_PATH_LITERAL("forced-foo.txt"),
906       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
907
908       EXPECT_LOCAL_PATH
909     };
910     RunTestCasesWithActiveItem(&kForcedSafe, 1);
911   }
912 }
913
914 // Test that an inactive download will still get a virtual or local download
915 // path.
916 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_InactiveDownload) {
917   const DownloadTestCase kInactiveTestCases[] = {
918     {
919       AUTOMATIC,
920       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
921       "http://example.com/foo.txt", "text/plain",
922       FILE_PATH_LITERAL(""),
923
924       FILE_PATH_LITERAL("foo.txt"),
925       FILE_PATH_LITERAL(""),
926       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
927
928       EXPECT_LOCAL_PATH
929     },
930
931     {
932       SAVE_AS,
933       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
934       "http://example.com/foo.txt", "text/plain",
935       FILE_PATH_LITERAL(""),
936
937       FILE_PATH_LITERAL("foo.txt"),
938       FILE_PATH_LITERAL(""),
939       DownloadItem::TARGET_DISPOSITION_PROMPT,
940
941       EXPECT_LOCAL_PATH
942     }
943   };
944
945   for (size_t i = 0; i < arraysize(kInactiveTestCases); ++i) {
946     SCOPED_TRACE(testing::Message() << "Running test case " << i);
947     const DownloadTestCase& test_case = kInactiveTestCases[i];
948     scoped_ptr<content::MockDownloadItem> item(
949         CreateActiveDownloadItem(i, test_case));
950     EXPECT_CALL(*item.get(), GetState())
951         .WillRepeatedly(Return(content::DownloadItem::CANCELLED));
952     // Even though one is a SAVE_AS download, no prompt will be displayed to
953     // the user because the download is inactive.
954     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
955         .Times(0);
956     RunTestCase(test_case, base::FilePath(), item.get());
957   }
958 }
959
960 // If the reserved path could not be verified, then the user should see a
961 // prompt.
962 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ReservationFailed) {
963   const DownloadTestCase kReservationFailedCases[] = {
964     {
965       // 0: Automatic download. Since the reservation fails, the disposition of
966       // the target is to prompt, but the returned path is used.
967       AUTOMATIC,
968       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
969       "http://example.com/foo.txt", "text/plain",
970       FILE_PATH_LITERAL(""),
971
972       FILE_PATH_LITERAL(""),
973       FILE_PATH_LITERAL("bar.txt"),
974       DownloadItem::TARGET_DISPOSITION_PROMPT,
975
976       EXPECT_CRDOWNLOAD
977     },
978   };
979
980   // Setup ReserveVirtualPath() to fail.
981   ON_CALL(*delegate(), ReserveVirtualPath(_, _, _, _, _))
982       .WillByDefault(WithArg<4>(ScheduleCallback2(
983           GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")), false)));
984   RunTestCasesWithActiveItem(kReservationFailedCases,
985                              arraysize(kReservationFailedCases));
986 }
987
988 // If the local path could not be determined, the download should be cancelled.
989 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LocalPathFailed) {
990   const DownloadTestCase kLocalPathFailedCases[] = {
991     {
992       // 0: Automatic download.
993       AUTOMATIC,
994       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
995       "http://example.com/foo.txt", "text/plain",
996       FILE_PATH_LITERAL(""),
997
998       FILE_PATH_LITERAL(""),
999       FILE_PATH_LITERAL(""),
1000       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1001
1002       EXPECT_LOCAL_PATH
1003     },
1004   };
1005
1006   base::FilePath expected_virtual_path(
1007       GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")));
1008   // The default download directory is the virtual path.
1009   download_prefs()->SetDownloadPath(test_virtual_dir());
1010   // Simulate failed call to DetermineLocalPath.
1011   EXPECT_CALL(*delegate(), DetermineLocalPath(
1012       _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
1013       .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
1014   RunTestCasesWithActiveItem(kLocalPathFailedCases,
1015                              arraysize(kLocalPathFailedCases));
1016 }
1017
1018 // Downloads that have a danger level of ALLOW_ON_USER_GESTURE should be marked
1019 // as safe depending on whether there was a user gesture associated with the
1020 // download and whether the referrer was visited prior to today.
1021 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_VisitedReferrer) {
1022   const DownloadTestCase kVisitedReferrerCases[] = {
1023     // http://visited.example.com/ is added to the history as a visit that
1024     // happened prior to today.
1025     {
1026       // 0: Safe download due to visiting referrer before.
1027       AUTOMATIC,
1028       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1029       "http://visited.example.com/foo.html", "text/html",
1030       FILE_PATH_LITERAL(""),
1031
1032       FILE_PATH_LITERAL(""),
1033       FILE_PATH_LITERAL("foo.html"),
1034       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1035
1036       EXPECT_CRDOWNLOAD
1037     },
1038
1039     {
1040       // 1: Dangerous due to not having visited referrer before.
1041       AUTOMATIC,
1042       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1043       "http://not-visited.example.com/foo.html", "text/html",
1044       FILE_PATH_LITERAL(""),
1045
1046       FILE_PATH_LITERAL(""),
1047       FILE_PATH_LITERAL("foo.html"),
1048       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1049
1050       EXPECT_UNCONFIRMED
1051     },
1052
1053     {
1054       // 2: Safe because the user is being prompted.
1055       SAVE_AS,
1056       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1057       "http://not-visited.example.com/foo.html", "text/html",
1058       FILE_PATH_LITERAL(""),
1059
1060       FILE_PATH_LITERAL(""),
1061       FILE_PATH_LITERAL("foo.html"),
1062       DownloadItem::TARGET_DISPOSITION_PROMPT,
1063
1064       EXPECT_CRDOWNLOAD
1065     },
1066
1067     {
1068       // 3: Safe because of forced path.
1069       FORCED,
1070       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1071       "http://not-visited.example.com/foo.html", "text/html",
1072       FILE_PATH_LITERAL("foo.html"),
1073
1074       FILE_PATH_LITERAL(""),
1075       FILE_PATH_LITERAL("foo.html"),
1076       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1077
1078       EXPECT_LOCAL_PATH
1079     },
1080   };
1081
1082   // This test assumes that the danger level of .html files is
1083   // ALLOW_ON_USER_GESTURE.
1084   ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1085             download_util::GetFileDangerLevel(
1086                 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
1087
1088   // First the history service must exist.
1089   ASSERT_TRUE(profile()->CreateHistoryService(false, false));
1090
1091   GURL url("http://visited.example.com/visited-link.html");
1092   // The time of visit is picked to be several seconds prior to the most recent
1093   // midnight.
1094   base::Time time_of_visit(
1095       base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(10));
1096   HistoryService* history_service =
1097       HistoryServiceFactory::GetForProfile(profile(), Profile::EXPLICIT_ACCESS);
1098   ASSERT_TRUE(history_service);
1099   history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
1100
1101   RunTestCasesWithActiveItem(kVisitedReferrerCases,
1102                              arraysize(kVisitedReferrerCases));
1103 }
1104
1105 // These test cases are run with "Prompt for download" user preference set to
1106 // true.
1107 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways) {
1108   const DownloadTestCase kPromptingTestCases[] = {
1109     {
1110       // 0: Safe Automatic - Should prompt because of "Prompt for download"
1111       //    preference setting.
1112       AUTOMATIC,
1113       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1114       "http://example.com/foo.txt", "text/plain",
1115       FILE_PATH_LITERAL(""),
1116
1117       FILE_PATH_LITERAL(""),
1118       FILE_PATH_LITERAL("foo.txt"),
1119       DownloadItem::TARGET_DISPOSITION_PROMPT,
1120
1121       EXPECT_CRDOWNLOAD
1122     },
1123
1124     {
1125       // 1: Safe Forced - Shouldn't prompt.
1126       FORCED,
1127       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1128       "http://example.com/foo.txt", "text/plain",
1129       FILE_PATH_LITERAL("foo.txt"),
1130
1131       FILE_PATH_LITERAL(""),
1132       FILE_PATH_LITERAL("foo.txt"),
1133       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1134
1135       EXPECT_LOCAL_PATH
1136     },
1137
1138     {
1139       // 2: Automatic - The filename extension is marked as one that we will
1140       //    open automatically. Shouldn't prompt.
1141       AUTOMATIC,
1142       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1143       "http://example.com/foo.dummy", "",
1144       FILE_PATH_LITERAL(""),
1145
1146       FILE_PATH_LITERAL(""),
1147       FILE_PATH_LITERAL("foo.dummy"),
1148       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1149
1150       EXPECT_CRDOWNLOAD
1151     },
1152   };
1153
1154   SetPromptForDownload(true);
1155   EnableAutoOpenBasedOnExtension(
1156       base::FilePath(FILE_PATH_LITERAL("dummy.dummy")));
1157   RunTestCasesWithActiveItem(kPromptingTestCases,
1158                              arraysize(kPromptingTestCases));
1159 }
1160
1161 #if !defined(OS_ANDROID)
1162 // These test cases are run with "Prompt for download" user preference set to
1163 // true. Automatic extension downloads shouldn't cause prompting.
1164 // Android doesn't support extensions.
1165 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways_Extension) {
1166   const DownloadTestCase kPromptingTestCases[] = {
1167     {
1168       // 0: Automatic Browser Extension download. - Shouldn't prompt for browser
1169       //    extension downloads even if "Prompt for download" preference is set.
1170       AUTOMATIC,
1171       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1172       "http://example.com/foo.crx",
1173       extensions::Extension::kMimeType,
1174       FILE_PATH_LITERAL(""),
1175
1176       FILE_PATH_LITERAL(""),
1177       FILE_PATH_LITERAL("foo.crx"),
1178       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1179
1180       EXPECT_UNCONFIRMED
1181     },
1182
1183 #if defined(OS_WIN)
1184     {
1185       // 1: Automatic User Script - Shouldn't prompt for user script downloads
1186       //    even if "Prompt for download" preference is set. ".js" files are
1187       //    considered dangerous on Windows.
1188       AUTOMATIC,
1189       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1190       "http://example.com/foo.user.js", "",
1191       FILE_PATH_LITERAL(""),
1192
1193       FILE_PATH_LITERAL(""),
1194       FILE_PATH_LITERAL("foo.user.js"),
1195       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1196
1197       EXPECT_UNCONFIRMED
1198     },
1199 #else
1200     {
1201       // 1: Automatic User Script - Shouldn't prompt for user script downloads
1202       //    even if "Prompt for download" preference is set.
1203       AUTOMATIC,
1204       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1205       "http://example.com/foo.user.js", "",
1206       FILE_PATH_LITERAL(""),
1207
1208       FILE_PATH_LITERAL(""),
1209       FILE_PATH_LITERAL("foo.user.js"),
1210       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1211
1212       EXPECT_CRDOWNLOAD
1213     },
1214 #endif
1215   };
1216
1217   SetPromptForDownload(true);
1218   RunTestCasesWithActiveItem(kPromptingTestCases,
1219                              arraysize(kPromptingTestCases));
1220 }
1221 #endif
1222
1223 // If the download path is managed, then we don't show any prompts.
1224 // Note that if the download path is managed, then PromptForDownload() is false.
1225 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ManagedPath) {
1226   const DownloadTestCase kManagedPathTestCases[] = {
1227     {
1228       // 0: Automatic Safe
1229       AUTOMATIC,
1230       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1231       "http://example.com/foo.txt", "text/plain",
1232       FILE_PATH_LITERAL(""),
1233
1234       FILE_PATH_LITERAL(""),
1235       FILE_PATH_LITERAL("foo.txt"),
1236       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1237
1238       EXPECT_CRDOWNLOAD
1239     },
1240
1241     {
1242       // 1: Save_As Safe
1243       SAVE_AS,
1244       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1245       "http://example.com/foo.txt", "text/plain",
1246       FILE_PATH_LITERAL(""),
1247
1248       FILE_PATH_LITERAL(""),
1249       FILE_PATH_LITERAL("foo.txt"),
1250       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1251
1252       EXPECT_CRDOWNLOAD
1253     },
1254   };
1255
1256   SetManagedDownloadPath(test_download_dir());
1257   ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
1258   RunTestCasesWithActiveItem(kManagedPathTestCases,
1259                              arraysize(kManagedPathTestCases));
1260 }
1261
1262 // Test basic functionality supporting extensions that want to override download
1263 // filenames.
1264 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsSafe) {
1265   const DownloadTestCase kNotifyExtensionsTestCases[] = {
1266     {
1267       // 0: Automatic Safe
1268       AUTOMATIC,
1269       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1270       "http://example.com/foo.txt", "text/plain",
1271       FILE_PATH_LITERAL(""),
1272
1273       FILE_PATH_LITERAL(""),
1274       FILE_PATH_LITERAL("overridden/foo.txt"),
1275       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1276
1277       EXPECT_CRDOWNLOAD
1278     },
1279
1280     {
1281       // 1: Save_As Safe
1282       SAVE_AS,
1283       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1284       "http://example.com/foo.txt", "text/plain",
1285       FILE_PATH_LITERAL(""),
1286
1287       FILE_PATH_LITERAL(""),
1288       FILE_PATH_LITERAL("overridden/foo.txt"),
1289       DownloadItem::TARGET_DISPOSITION_PROMPT,
1290
1291       EXPECT_CRDOWNLOAD
1292     },
1293
1294     {
1295       // 2: Automatic Dangerous
1296       AUTOMATIC,
1297       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1298       "http://example.com/foo.html", "",
1299       FILE_PATH_LITERAL(""),
1300
1301       FILE_PATH_LITERAL(""),
1302       FILE_PATH_LITERAL("overridden/foo.html"),
1303       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1304
1305       EXPECT_UNCONFIRMED
1306     },
1307
1308     {
1309       // 3: Forced Safe
1310       FORCED,
1311       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1312       "http://example.com/foo.txt", "",
1313       FILE_PATH_LITERAL("forced-foo.txt"),
1314
1315       FILE_PATH_LITERAL(""),
1316       FILE_PATH_LITERAL("forced-foo.txt"),
1317       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1318
1319       EXPECT_LOCAL_PATH
1320     },
1321   };
1322
1323   ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1324       .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1325   RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1326                              arraysize(kNotifyExtensionsTestCases));
1327 }
1328
1329 // Test that filenames provided by extensions are passed into SafeBrowsing
1330 // checks and dangerous download checks.
1331 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsUnsafe) {
1332   const DownloadTestCase kNotifyExtensionsTestCases[] = {
1333     {
1334       // 0: Automatic Safe : Later overridden by a dangerous filetype.
1335       AUTOMATIC,
1336       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1337       "http://example.com/foo.html.remove", "text/plain",
1338       FILE_PATH_LITERAL(""),
1339
1340       FILE_PATH_LITERAL(""),
1341       FILE_PATH_LITERAL("overridden/foo.html"),
1342       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1343
1344       EXPECT_UNCONFIRMED
1345     },
1346
1347     {
1348       // 1: Automatic Safe : Later overridden by a potentially dangerous
1349       // filetype.
1350       AUTOMATIC,
1351       content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
1352       "http://example.com/foo.exe.remove", "text/plain",
1353       FILE_PATH_LITERAL(""),
1354
1355       FILE_PATH_LITERAL(""),
1356       FILE_PATH_LITERAL("overridden/foo.exe"),
1357       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1358
1359       EXPECT_UNCONFIRMED
1360     },
1361   };
1362
1363   ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1364       .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1365   ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
1366       .WillByDefault(Invoke(&CheckDownloadUrlCheckExes));
1367   RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1368                              arraysize(kNotifyExtensionsTestCases));
1369 }
1370
1371 // Test that conflict actions set by extensions are passed correctly into
1372 // ReserveVirtualPath.
1373 TEST_F(DownloadTargetDeterminerTest,
1374        TargetDeterminer_NotifyExtensionsConflict) {
1375   const DownloadTestCase kNotifyExtensionsTestCase = {
1376     AUTOMATIC,
1377     content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1378     "http://example.com/foo.txt", "text/plain",
1379     FILE_PATH_LITERAL(""),
1380
1381     FILE_PATH_LITERAL(""),
1382     FILE_PATH_LITERAL("overridden/foo.txt"),
1383     DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1384
1385     EXPECT_CRDOWNLOAD
1386   };
1387
1388   const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1389   scoped_ptr<content::MockDownloadItem> item(
1390       CreateActiveDownloadItem(0, test_case));
1391   base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1392   base::FilePath full_overridden_path =
1393       GetPathInDownloadDir(overridden_path.value());
1394
1395   // First case: An extension sets the conflict_action to OVERWRITE.
1396   EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1397       .WillOnce(WithArg<2>(
1398           ScheduleCallback2(overridden_path,
1399                             DownloadPathReservationTracker::OVERWRITE)));
1400   EXPECT_CALL(*delegate(), ReserveVirtualPath(
1401       _, full_overridden_path, true, DownloadPathReservationTracker::OVERWRITE,
1402       _)).WillOnce(WithArg<4>(
1403           ScheduleCallback2(full_overridden_path, true)));
1404
1405   RunTestCase(test_case, base::FilePath(), item.get());
1406
1407   // Second case: An extension sets the conflict_action to PROMPT.
1408   EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1409       .WillOnce(WithArg<2>(
1410           ScheduleCallback2(overridden_path,
1411                             DownloadPathReservationTracker::PROMPT)));
1412   EXPECT_CALL(*delegate(), ReserveVirtualPath(
1413       _, full_overridden_path, true, DownloadPathReservationTracker::PROMPT, _))
1414       .WillOnce(WithArg<4>(
1415           ScheduleCallback2(full_overridden_path, true)));
1416   RunTestCase(test_case, base::FilePath(), item.get());
1417 }
1418
1419 // Test that relative paths returned by extensions are always relative to the
1420 // default downloads path.
1421 TEST_F(DownloadTargetDeterminerTest,
1422        TargetDeterminer_NotifyExtensionsDefaultPath) {
1423   const DownloadTestCase kNotifyExtensionsTestCase = {
1424     SAVE_AS,
1425     content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1426     "http://example.com/foo.txt", "text/plain",
1427     FILE_PATH_LITERAL(""),
1428
1429     FILE_PATH_LITERAL(""),
1430     FILE_PATH_LITERAL("overridden/foo.txt"),
1431     DownloadItem::TARGET_DISPOSITION_PROMPT,
1432
1433     EXPECT_CRDOWNLOAD
1434   };
1435
1436   const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1437   scoped_ptr<content::MockDownloadItem> item(
1438       CreateActiveDownloadItem(0, test_case));
1439   base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1440   base::FilePath full_overridden_path =
1441       GetPathInDownloadDir(overridden_path.value());
1442
1443   download_prefs()->SetSaveFilePath(GetPathInDownloadDir(
1444       FILE_PATH_LITERAL("last_selected")));
1445
1446   EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1447       .WillOnce(WithArg<2>(
1448           ScheduleCallback2(overridden_path,
1449                             DownloadPathReservationTracker::UNIQUIFY)));
1450   EXPECT_CALL(*delegate(),
1451               PromptUserForDownloadPath(_, full_overridden_path, _))
1452       .WillOnce(WithArg<2>(
1453           ScheduleCallback(full_overridden_path)));
1454   RunTestCase(test_case, base::FilePath(), item.get());
1455 }
1456
1457 TEST_F(DownloadTargetDeterminerTest,
1458        TargetDeterminer_InitialVirtualPathUnsafe) {
1459   const base::FilePath::CharType* kInitialPath =
1460       FILE_PATH_LITERAL("some_path/bar.html");
1461
1462   const DownloadTestCase kInitialPathTestCase = {
1463     // 0: Save As Save. The path generated based on the DownloadItem is safe,
1464     // but the initial path is unsafe. However, the download is not considered
1465     // dangerous since the user has been prompted.
1466     SAVE_AS,
1467     content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1468     "http://example.com/foo.txt", "text/plain",
1469     FILE_PATH_LITERAL(""),
1470
1471     FILE_PATH_LITERAL(""),
1472     kInitialPath,
1473     DownloadItem::TARGET_DISPOSITION_PROMPT,
1474
1475     EXPECT_CRDOWNLOAD
1476   };
1477
1478   const DownloadTestCase& test_case = kInitialPathTestCase;
1479   scoped_ptr<content::MockDownloadItem> item(
1480       CreateActiveDownloadItem(1, test_case));
1481   EXPECT_CALL(*item, GetLastReason())
1482       .WillRepeatedly(Return(
1483           content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1484   EXPECT_CALL(*item, GetTargetDisposition())
1485       .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
1486   RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1487 }
1488
1489 // Prompting behavior for resumed downloads is based on the last interrupt
1490 // reason. If the reason indicates that the target path may not be suitable for
1491 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1492 // prompted, and not otherwise. These test cases shouldn't result in prompting
1493 // since the error is set to NETWORK_FAILED.
1494 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedNoPrompt) {
1495   // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1496   // path.
1497   const base::FilePath::CharType* kInitialPath =
1498       FILE_PATH_LITERAL("some_path/bar.txt");
1499
1500   const DownloadTestCase kResumedTestCases[] = {
1501     {
1502       // 0: Automatic Safe: Initial path is ignored since the user has not been
1503       // prompted before.
1504       AUTOMATIC,
1505       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1506       "http://example.com/foo.txt", "text/plain",
1507       FILE_PATH_LITERAL(""),
1508
1509       FILE_PATH_LITERAL(""),
1510       FILE_PATH_LITERAL("foo.txt"),
1511       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1512
1513       EXPECT_CRDOWNLOAD
1514     },
1515
1516     {
1517       // 1: Save_As Safe: Initial path used.
1518       SAVE_AS,
1519       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1520       "http://example.com/foo.txt", "text/plain",
1521       FILE_PATH_LITERAL(""),
1522
1523       FILE_PATH_LITERAL(""),
1524       kInitialPath,
1525       DownloadItem::TARGET_DISPOSITION_PROMPT,
1526
1527       EXPECT_CRDOWNLOAD
1528     },
1529
1530     {
1531       // 2: Automatic Dangerous: Initial path is ignored since the user hasn't
1532       // been prompted before.
1533       AUTOMATIC,
1534       content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1535       "http://example.com/foo.html", "",
1536       FILE_PATH_LITERAL(""),
1537
1538       FILE_PATH_LITERAL(""),
1539       FILE_PATH_LITERAL("foo.html"),
1540       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1541
1542       EXPECT_UNCONFIRMED
1543     },
1544
1545     {
1546       // 3: Forced Safe: Initial path is ignored due to the forced path.
1547       FORCED,
1548       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1549       "http://example.com/foo.txt", "",
1550       FILE_PATH_LITERAL("forced-foo.txt"),
1551
1552       FILE_PATH_LITERAL(""),
1553       FILE_PATH_LITERAL("forced-foo.txt"),
1554       DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1555
1556       EXPECT_LOCAL_PATH
1557     },
1558   };
1559
1560   // The test assumes that .html files have a danger level of
1561   // ALLOW_ON_USER_GESTURE.
1562   ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1563             download_util::GetFileDangerLevel(
1564                 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
1565   for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1566     SCOPED_TRACE(testing::Message() << "Running test case " << i);
1567     const DownloadTestCase& test_case = kResumedTestCases[i];
1568     scoped_ptr<content::MockDownloadItem> item(
1569         CreateActiveDownloadItem(i, test_case));
1570     base::FilePath expected_path =
1571         GetPathInDownloadDir(test_case.expected_local_path);
1572     ON_CALL(*item.get(), GetLastReason())
1573         .WillByDefault(Return(
1574             content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1575     // Extensions should be notified if a new path is being generated and there
1576     // is no forced path. In the test cases above, this is true for tests with
1577     // type == AUTOMATIC.
1578     EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1579         .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1580     EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1581     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _))
1582         .Times(0);
1583     EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1584     EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1585     RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1586   }
1587
1588 }
1589
1590 // Test that a forced download doesn't prompt, even if the interrupt reason
1591 // suggests that the target path may not be suitable for downloads.
1592 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedForcedDownload) {
1593   const base::FilePath::CharType* kInitialPath =
1594       FILE_PATH_LITERAL("some_path/bar.txt");
1595   const DownloadTestCase kResumedForcedDownload = {
1596     // 3: Forced Safe
1597     FORCED,
1598     content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1599     "http://example.com/foo.txt", "",
1600     FILE_PATH_LITERAL("forced-foo.txt"),
1601
1602     FILE_PATH_LITERAL(""),
1603     FILE_PATH_LITERAL("forced-foo.txt"),
1604     DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1605
1606     EXPECT_LOCAL_PATH
1607   };
1608
1609   const DownloadTestCase& test_case = kResumedForcedDownload;
1610   base::FilePath expected_path =
1611       GetPathInDownloadDir(test_case.expected_local_path);
1612   scoped_ptr<content::MockDownloadItem> item(
1613       CreateActiveDownloadItem(0, test_case));
1614   ON_CALL(*item.get(), GetLastReason())
1615       .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1616   EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1617       .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1618   EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1619   EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
1620       .Times(0);
1621   EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1622   EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1623   RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1624 }
1625
1626 // Prompting behavior for resumed downloads is based on the last interrupt
1627 // reason. If the reason indicates that the target path may not be suitable for
1628 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1629 // prompted, and not otherwise. These test cases result in prompting since the
1630 // error is set to NO_SPACE.
1631 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedWithPrompt) {
1632   // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1633   // path.
1634   const base::FilePath::CharType* kInitialPath =
1635       FILE_PATH_LITERAL("some_path/bar.txt");
1636
1637   const DownloadTestCase kResumedTestCases[] = {
1638     {
1639       // 0: Automatic Safe
1640       AUTOMATIC,
1641       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1642       "http://example.com/foo.txt", "text/plain",
1643       FILE_PATH_LITERAL(""),
1644
1645       FILE_PATH_LITERAL(""),
1646       FILE_PATH_LITERAL("foo.txt"),
1647       DownloadItem::TARGET_DISPOSITION_PROMPT,
1648
1649       EXPECT_CRDOWNLOAD
1650     },
1651
1652     {
1653       // 1: Save_As Safe
1654       SAVE_AS,
1655       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1656       "http://example.com/foo.txt", "text/plain",
1657       FILE_PATH_LITERAL(""),
1658
1659       FILE_PATH_LITERAL(""),
1660       kInitialPath,
1661       DownloadItem::TARGET_DISPOSITION_PROMPT,
1662
1663       EXPECT_CRDOWNLOAD
1664     },
1665
1666     {
1667       // 2: Automatic Dangerous
1668       AUTOMATIC,
1669       content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1670       "http://example.com/foo.html", "",
1671       FILE_PATH_LITERAL(""),
1672
1673       FILE_PATH_LITERAL(""),
1674       FILE_PATH_LITERAL("foo.html"),
1675       DownloadItem::TARGET_DISPOSITION_PROMPT,
1676
1677       EXPECT_CRDOWNLOAD
1678     },
1679   };
1680
1681   // The test assumes that .html files have a danger level of
1682   // ALLOW_ON_USER_GESTURE.
1683   ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1684             download_util::GetFileDangerLevel(
1685                 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
1686   for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1687     SCOPED_TRACE(testing::Message() << "Running test case " << i);
1688     download_prefs()->SetSaveFilePath(test_download_dir());
1689     const DownloadTestCase& test_case = kResumedTestCases[i];
1690     base::FilePath expected_path =
1691         GetPathInDownloadDir(test_case.expected_local_path);
1692     scoped_ptr<content::MockDownloadItem> item(
1693         CreateActiveDownloadItem(i, test_case));
1694     ON_CALL(*item.get(), GetLastReason())
1695         .WillByDefault(Return(
1696             content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1697     EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1698         .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1699     EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1700     EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _));
1701     EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1702     EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1703     RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1704   }
1705 }
1706
1707 // Used with TargetDeterminer_IntermediateNameForResumed test. Verifies that
1708 // |intermediate_path| == |expected_intermediate_path| if the latter is
1709 // non-empty.
1710 void IntermediatePathVerifier(
1711     const base::FilePath& expected_intermediate_path,
1712     const content::DownloadTargetCallback& callback,
1713     const base::FilePath& target_path,
1714     content::DownloadItem::TargetDisposition disposition,
1715     content::DownloadDangerType danger_type,
1716     const base::FilePath& intermediate_path) {
1717   if (!expected_intermediate_path.empty())
1718     EXPECT_EQ(expected_intermediate_path, intermediate_path);
1719   callback.Run(target_path, disposition, danger_type, intermediate_path);
1720 }
1721
1722 // Test intermediate filename generation for resumed downloads.
1723 TEST_F(DownloadTargetDeterminerTest,
1724        TargetDeterminer_IntermediateNameForResumed) {
1725   // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1726   // path.
1727   const base::FilePath::CharType kInitialPath[] =
1728       FILE_PATH_LITERAL("some_path/bar.txt");
1729
1730   struct IntermediateNameTestCase {
1731     // General test case settings.
1732     DownloadTestCase general;
1733
1734     // Value of DownloadItem::GetFullPath() during test run, relative
1735     // to test download path.
1736     const base::FilePath::CharType* initial_intermediate_path;
1737
1738     // Expected intermediate path relatvie to the test download path. An exact
1739     // match is performed if this string is non-empty. Ignored otherwise.
1740     const base::FilePath::CharType* expected_intermediate_path;
1741   } kIntermediateNameTestCases[] = {
1742     {
1743       {
1744         // 0: Automatic Safe
1745         AUTOMATIC,
1746         content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1747         "http://example.com/foo.txt", "text/plain",
1748         FILE_PATH_LITERAL(""),
1749
1750         FILE_PATH_LITERAL(""),
1751         FILE_PATH_LITERAL("foo.txt"),
1752         DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1753
1754         EXPECT_CRDOWNLOAD
1755       },
1756       FILE_PATH_LITERAL("bar.txt.crdownload"),
1757       FILE_PATH_LITERAL("foo.txt.crdownload")
1758     },
1759
1760     {
1761       {
1762         // 1: Save_As Safe
1763         SAVE_AS,
1764         content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1765         "http://example.com/foo.txt", "text/plain",
1766         FILE_PATH_LITERAL(""),
1767
1768         FILE_PATH_LITERAL(""),
1769         kInitialPath,
1770         DownloadItem::TARGET_DISPOSITION_PROMPT,
1771
1772         EXPECT_CRDOWNLOAD
1773       },
1774       FILE_PATH_LITERAL("foo.txt.crdownload"),
1775       FILE_PATH_LITERAL("some_path/bar.txt.crdownload")
1776     },
1777
1778     {
1779       {
1780         // 2: Automatic Dangerous
1781         AUTOMATIC,
1782         content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1783         "http://example.com/foo.html", "",
1784         FILE_PATH_LITERAL(""),
1785
1786         FILE_PATH_LITERAL(""),
1787         FILE_PATH_LITERAL("foo.html"),
1788         DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1789
1790         EXPECT_UNCONFIRMED
1791       },
1792       FILE_PATH_LITERAL("Unconfirmed abcd.crdownload"),
1793       FILE_PATH_LITERAL("Unconfirmed abcd.crdownload")
1794     },
1795
1796     {
1797       {
1798         // 3: Automatic Dangerous
1799         AUTOMATIC,
1800         content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1801         "http://example.com/foo.html", "",
1802         FILE_PATH_LITERAL(""),
1803
1804         FILE_PATH_LITERAL(""),
1805         FILE_PATH_LITERAL("foo.html"),
1806         DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1807
1808         EXPECT_UNCONFIRMED
1809       },
1810       FILE_PATH_LITERAL("other_path/Unconfirmed abcd.crdownload"),
1811       // Rely on the EXPECT_UNCONFIRMED check in the general test settings. A
1812       // new intermediate path of the form "Unconfirmed <number>.crdownload"
1813       // should be generated for this case since the initial intermediate path
1814       // is in the wrong directory.
1815       FILE_PATH_LITERAL("")
1816     },
1817
1818     {
1819       {
1820         // 3: Forced Safe: Initial path is ignored due to the forced path.
1821         FORCED,
1822         content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1823         "http://example.com/foo.txt", "",
1824         FILE_PATH_LITERAL("forced-foo.txt"),
1825
1826         FILE_PATH_LITERAL(""),
1827         FILE_PATH_LITERAL("forced-foo.txt"),
1828         DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1829
1830         EXPECT_LOCAL_PATH
1831       },
1832       FILE_PATH_LITERAL("forced-foo.txt"),
1833       FILE_PATH_LITERAL("forced-foo.txt")
1834     },
1835   };
1836
1837   // The test assumes that .html files have a danger level of
1838   // ALLOW_ON_USER_GESTURE.
1839   ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1840             download_util::GetFileDangerLevel(
1841                 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
1842
1843   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kIntermediateNameTestCases); ++i) {
1844     SCOPED_TRACE(testing::Message() << "Running test case " << i);
1845     const IntermediateNameTestCase& test_case = kIntermediateNameTestCases[i];
1846     scoped_ptr<content::MockDownloadItem> item(
1847         CreateActiveDownloadItem(i, test_case.general));
1848
1849     ON_CALL(*item.get(), GetLastReason())
1850         .WillByDefault(Return(
1851             content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1852     ON_CALL(*item.get(), GetFullPath())
1853         .WillByDefault(ReturnRefOfCopy(
1854             GetPathInDownloadDir(test_case.initial_intermediate_path)));
1855     ON_CALL(*item.get(), GetDangerType())
1856         .WillByDefault(Return(test_case.general.expected_danger_type));
1857
1858     base::WeakPtrFactory<DownloadTargetDeterminerTest> factory(this);
1859     base::RunLoop run_loop;
1860     content::DownloadTargetCallback verifier_callback =
1861         base::Bind(&DownloadTargetDeterminerTest::DownloadTargetVerifier,
1862                    factory.GetWeakPtr(),
1863                    run_loop.QuitClosure(),
1864                    test_case.general);
1865     content::DownloadTargetCallback test_callback =
1866         base::Bind(&IntermediatePathVerifier,
1867                    GetPathInDownloadDir(test_case.expected_intermediate_path),
1868                    verifier_callback);
1869     DownloadTargetDeterminer::Start(item.get(),
1870                                     GetPathInDownloadDir(kInitialPath),
1871                                     download_prefs(),
1872                                     delegate(),
1873                                     test_callback);
1874     run_loop.Run();
1875     ::testing::Mock::VerifyAndClearExpectations(delegate());
1876   }
1877 }
1878
1879 }  // namespace