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