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