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