Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / download / download_target_determiner_unittest.cc
blobfc673c10ee685a97f6ff22589ab676710dc24e17
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.
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"
40 #if defined(ENABLE_PLUGINS)
41 #include "content/public/browser/plugin_service.h"
42 #include "content/public/browser/plugin_service_filter.h"
43 #include "content/public/common/webplugininfo.h"
44 #endif
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;
57 namespace {
59 // No-op delegate.
60 class NullWebContentsDelegate : public content::WebContentsDelegate {
61 public:
62 NullWebContentsDelegate() {}
63 virtual ~NullWebContentsDelegate() {}
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));
78 ACTION_P(ScheduleCallback, result0) {
79 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, result0));
82 // Similar to ScheduleCallback, but binds 2 arguments.
83 ACTION_P2(ScheduleCallback2, result0, result1) {
84 base::MessageLoop::current()->PostTask(
85 FROM_HERE, base::Bind(arg0, result0, result1));
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.
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.
103 // Typical download test case. Used with
104 // DownloadTargetDeterminerTest::RunTestCase().
105 struct DownloadTestCase {
106 // Type of test.
107 TestCaseType test_type;
109 // Expected danger type. Verified at the end of target determination.
110 content::DownloadDangerType expected_danger_type;
112 // Value of DownloadItem::GetURL()
113 const char* url;
115 // Value of DownloadItem::GetMimeType()
116 const char* mime_type;
118 // Should be non-empty if |test_type| == FORCED. Value of GetForcedFilePath().
119 const base::FilePath::CharType* forced_file_path;
121 // Expected local path. Specified relative to the test download path.
122 const base::FilePath::CharType* expected_local_path;
124 // Expected target disposition. If this is TARGET_DISPOSITION_PROMPT, then the
125 // test run will expect ChromeDownloadManagerDelegate to prompt the user for a
126 // download location.
127 DownloadItem::TargetDisposition expected_disposition;
129 // Type of intermediate path to expect.
130 TestCaseExpectIntermediate expected_intermediate;
133 class MockDownloadTargetDeterminerDelegate
134 : public DownloadTargetDeterminerDelegate {
135 public:
136 MOCK_METHOD3(CheckDownloadUrl,
137 void(content::DownloadItem*, const base::FilePath&,
138 const CheckDownloadUrlCallback&));
139 MOCK_METHOD3(NotifyExtensions,
140 void(content::DownloadItem*, const base::FilePath&,
141 const NotifyExtensionsCallback&));
142 MOCK_METHOD3(PromptUserForDownloadPath,
143 void(content::DownloadItem*, const base::FilePath&,
144 const FileSelectedCallback&));
145 MOCK_METHOD3(DetermineLocalPath,
146 void(DownloadItem*, const base::FilePath&,
147 const LocalPathCallback&));
148 MOCK_METHOD5(ReserveVirtualPath,
149 void(DownloadItem*, const base::FilePath&, bool,
150 DownloadPathReservationTracker::FilenameConflictAction,
151 const ReservedPathCallback&));
152 MOCK_METHOD2(GetFileMimeType,
153 void(const base::FilePath&,
154 const GetFileMimeTypeCallback&));
156 void SetupDefaults() {
157 ON_CALL(*this, CheckDownloadUrl(_, _, _))
158 .WillByDefault(WithArg<2>(
159 ScheduleCallback(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)));
160 ON_CALL(*this, NotifyExtensions(_, _, _))
161 .WillByDefault(WithArg<2>(
162 ScheduleCallback2(base::FilePath(),
163 DownloadPathReservationTracker::UNIQUIFY)));
164 ON_CALL(*this, ReserveVirtualPath(_, _, _, _, _))
165 .WillByDefault(Invoke(
166 &MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath));
167 ON_CALL(*this, PromptUserForDownloadPath(_, _, _))
168 .WillByDefault(Invoke(
169 &MockDownloadTargetDeterminerDelegate::NullPromptUser));
170 ON_CALL(*this, DetermineLocalPath(_, _, _))
171 .WillByDefault(Invoke(
172 &MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath));
173 ON_CALL(*this, GetFileMimeType(_, _))
174 .WillByDefault(WithArg<1>(
175 ScheduleCallback("")));
177 private:
178 static void NullReserveVirtualPath(
179 DownloadItem* download,
180 const base::FilePath& virtual_path,
181 bool create_directory,
182 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
183 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback);
184 static void NullPromptUser(
185 DownloadItem* download, const base::FilePath& suggested_path,
186 const FileSelectedCallback& callback);
187 static void NullDetermineLocalPath(
188 DownloadItem* download, const base::FilePath& virtual_path,
189 const LocalPathCallback& callback);
192 class DownloadTargetDeterminerTest : public ChromeRenderViewHostTestHarness {
193 public:
194 // ::testing::Test
195 virtual void SetUp() OVERRIDE;
196 virtual void TearDown() OVERRIDE;
198 // Creates MockDownloadItem and sets up default expectations.
199 content::MockDownloadItem* CreateActiveDownloadItem(
200 int32 id,
201 const DownloadTestCase& test_case);
203 // Sets the AutoOpenBasedOnExtension user preference for |path|.
204 void EnableAutoOpenBasedOnExtension(const base::FilePath& path);
206 // Set the kDownloadDefaultDirectory managed preference to |path|.
207 void SetManagedDownloadPath(const base::FilePath& path);
209 // Set the kPromptForDownload user preference to |prompt|.
210 void SetPromptForDownload(bool prompt);
212 // Given the relative path |path|, returns the full path under the temporary
213 // downloads directory.
214 base::FilePath GetPathInDownloadDir(const base::FilePath::StringType& path);
216 // Run |test_case| using |item|.
217 void RunTestCase(const DownloadTestCase& test_case,
218 const base::FilePath& initial_virtual_path,
219 content::MockDownloadItem* item);
221 // Runs |test_case| with |item|. When the DownloadTargetDeterminer is done,
222 // returns the resulting DownloadTargetInfo.
223 scoped_ptr<DownloadTargetInfo> RunDownloadTargetDeterminer(
224 const base::FilePath& initial_virtual_path,
225 content::MockDownloadItem* item);
227 // Run through |test_case_count| tests in |test_cases|. A new MockDownloadItem
228 // will be created for each test case and destroyed when the test case is
229 // complete.
230 void RunTestCasesWithActiveItem(const DownloadTestCase test_cases[],
231 size_t test_case_count);
233 // Verifies that |target_path|, |disposition|, |expected_danger_type| and
234 // |intermediate_path| matches the expectations of |test_case|. Posts
235 // |closure| to the current message loop when done.
236 void VerifyDownloadTarget(const DownloadTestCase& test_case,
237 const DownloadTargetInfo* target_info);
239 const base::FilePath& test_download_dir() const {
240 return test_download_dir_.path();
243 const base::FilePath& test_virtual_dir() const {
244 return test_virtual_dir_;
247 MockDownloadTargetDeterminerDelegate* delegate() {
248 return &delegate_;
251 DownloadPrefs* download_prefs() {
252 return download_prefs_.get();
255 private:
256 scoped_ptr<DownloadPrefs> download_prefs_;
257 ::testing::NiceMock<MockDownloadTargetDeterminerDelegate> delegate_;
258 NullWebContentsDelegate web_contents_delegate_;
259 base::ScopedTempDir test_download_dir_;
260 base::FilePath test_virtual_dir_;
263 void DownloadTargetDeterminerTest::SetUp() {
264 ChromeRenderViewHostTestHarness::SetUp();
265 CHECK(profile());
266 download_prefs_.reset(new DownloadPrefs(profile()));
267 web_contents()->SetDelegate(&web_contents_delegate_);
268 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
269 test_virtual_dir_ = test_download_dir().Append(FILE_PATH_LITERAL("virtual"));
270 download_prefs_->SetDownloadPath(test_download_dir());
271 delegate_.SetupDefaults();
274 void DownloadTargetDeterminerTest::TearDown() {
275 download_prefs_.reset();
276 ChromeRenderViewHostTestHarness::TearDown();
279 content::MockDownloadItem*
280 DownloadTargetDeterminerTest::CreateActiveDownloadItem(
281 int32 id,
282 const DownloadTestCase& test_case) {
283 content::MockDownloadItem* item =
284 new ::testing::NiceMock<content::MockDownloadItem>();
285 GURL download_url(test_case.url);
286 std::vector<GURL> url_chain;
287 url_chain.push_back(download_url);
288 base::FilePath forced_file_path =
289 GetPathInDownloadDir(test_case.forced_file_path);
290 DownloadItem::TargetDisposition initial_disposition =
291 (test_case.test_type == SAVE_AS) ?
292 DownloadItem::TARGET_DISPOSITION_PROMPT :
293 DownloadItem::TARGET_DISPOSITION_OVERWRITE;
294 EXPECT_EQ(test_case.test_type == FORCED,
295 !forced_file_path.empty());
297 ON_CALL(*item, GetBrowserContext())
298 .WillByDefault(Return(profile()));
299 ON_CALL(*item, GetDangerType())
300 .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
301 ON_CALL(*item, GetForcedFilePath())
302 .WillByDefault(ReturnRefOfCopy(forced_file_path));
303 ON_CALL(*item, GetFullPath())
304 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
305 ON_CALL(*item, GetHash())
306 .WillByDefault(ReturnRefOfCopy(std::string()));
307 ON_CALL(*item, GetId())
308 .WillByDefault(Return(id));
309 ON_CALL(*item, GetLastReason())
310 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE));
311 ON_CALL(*item, GetMimeType())
312 .WillByDefault(Return(test_case.mime_type));
313 ON_CALL(*item, GetReferrerUrl())
314 .WillByDefault(ReturnRefOfCopy(download_url));
315 ON_CALL(*item, GetState())
316 .WillByDefault(Return(DownloadItem::IN_PROGRESS));
317 ON_CALL(*item, GetTargetDisposition())
318 .WillByDefault(Return(initial_disposition));
319 ON_CALL(*item, GetTargetFilePath())
320 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
321 ON_CALL(*item, GetTransitionType())
322 .WillByDefault(Return(content::PAGE_TRANSITION_LINK));
323 ON_CALL(*item, GetURL())
324 .WillByDefault(ReturnRefOfCopy(download_url));
325 ON_CALL(*item, GetUrlChain())
326 .WillByDefault(ReturnRefOfCopy(url_chain));
327 ON_CALL(*item, GetWebContents())
328 .WillByDefault(Return(web_contents()));
329 ON_CALL(*item, HasUserGesture())
330 .WillByDefault(Return(true));
331 ON_CALL(*item, IsDangerous())
332 .WillByDefault(Return(false));
333 ON_CALL(*item, IsTemporary())
334 .WillByDefault(Return(false));
335 return item;
338 void DownloadTargetDeterminerTest::EnableAutoOpenBasedOnExtension(
339 const base::FilePath& path) {
340 EXPECT_TRUE(download_prefs_->EnableAutoOpenBasedOnExtension(path));
343 void DownloadTargetDeterminerTest::SetManagedDownloadPath(
344 const base::FilePath& path) {
345 profile()->GetTestingPrefService()->
346 SetManagedPref(prefs::kDownloadDefaultDirectory,
347 base::CreateFilePathValue(path));
350 void DownloadTargetDeterminerTest::SetPromptForDownload(bool prompt) {
351 profile()->GetTestingPrefService()->
352 SetBoolean(prefs::kPromptForDownload, prompt);
355 base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir(
356 const base::FilePath::StringType& relative_path) {
357 if (relative_path.empty())
358 return base::FilePath();
359 base::FilePath full_path(test_download_dir().Append(relative_path));
360 return full_path.NormalizePathSeparators();
363 void DownloadTargetDeterminerTest::RunTestCase(
364 const DownloadTestCase& test_case,
365 const base::FilePath& initial_virtual_path,
366 content::MockDownloadItem* item) {
367 scoped_ptr<DownloadTargetInfo> target_info =
368 RunDownloadTargetDeterminer(initial_virtual_path, item);
369 VerifyDownloadTarget(test_case, target_info.get());
372 void CompletionCallbackWrapper(
373 const base::Closure& closure,
374 scoped_ptr<DownloadTargetInfo>* target_info_receiver,
375 scoped_ptr<DownloadTargetInfo> target_info) {
376 target_info_receiver->swap(target_info);
377 base::MessageLoop::current()->PostTask(FROM_HERE, closure);
380 scoped_ptr<DownloadTargetInfo>
381 DownloadTargetDeterminerTest::RunDownloadTargetDeterminer(
382 const base::FilePath& initial_virtual_path,
383 content::MockDownloadItem* item) {
384 scoped_ptr<DownloadTargetInfo> target_info;
385 base::RunLoop run_loop;
386 DownloadTargetDeterminer::Start(
387 item, initial_virtual_path, download_prefs_.get(), delegate(),
388 base::Bind(&CompletionCallbackWrapper,
389 run_loop.QuitClosure(),
390 &target_info));
391 run_loop.Run();
392 ::testing::Mock::VerifyAndClearExpectations(delegate());
393 return target_info.Pass();
396 void DownloadTargetDeterminerTest::RunTestCasesWithActiveItem(
397 const DownloadTestCase test_cases[],
398 size_t test_case_count) {
399 for (size_t i = 0; i < test_case_count; ++i) {
400 scoped_ptr<content::MockDownloadItem> item(
401 CreateActiveDownloadItem(i, test_cases[i]));
402 SCOPED_TRACE(testing::Message() << "Running test case " << i);
403 RunTestCase(test_cases[i], base::FilePath(), item.get());
407 void DownloadTargetDeterminerTest::VerifyDownloadTarget(
408 const DownloadTestCase& test_case,
409 const DownloadTargetInfo* target_info) {
410 base::FilePath expected_local_path(
411 GetPathInDownloadDir(test_case.expected_local_path));
412 EXPECT_EQ(expected_local_path.value(), target_info->target_path.value());
413 EXPECT_EQ(test_case.expected_disposition, target_info->target_disposition);
414 EXPECT_EQ(test_case.expected_danger_type, target_info->danger_type);
416 switch (test_case.expected_intermediate) {
417 case EXPECT_CRDOWNLOAD:
418 EXPECT_EQ(DownloadTargetDeterminer::GetCrDownloadPath(
419 target_info->target_path).value(),
420 target_info->intermediate_path.value());
421 break;
423 case EXPECT_UNCONFIRMED:
424 // The paths (in English) look like: /path/Unconfirmed xxx.crdownload.
425 // Of this, we only check that the path is:
426 // 1. Not "/path/target.crdownload",
427 // 2. Points to the same directory as the target.
428 // 3. Has extension ".crdownload".
429 // 4. Basename starts with "Unconfirmed ".
430 EXPECT_NE(DownloadTargetDeterminer::GetCrDownloadPath(expected_local_path)
431 .value(),
432 target_info->intermediate_path.value());
433 EXPECT_EQ(expected_local_path.DirName().value(),
434 target_info->intermediate_path.DirName().value());
435 EXPECT_TRUE(target_info->intermediate_path.MatchesExtension(
436 FILE_PATH_LITERAL(".crdownload")));
437 EXPECT_EQ(0u,
438 target_info->intermediate_path.BaseName().value().find(
439 FILE_PATH_LITERAL("Unconfirmed ")));
440 break;
442 case EXPECT_LOCAL_PATH:
443 EXPECT_EQ(expected_local_path.value(),
444 target_info->intermediate_path.value());
445 break;
449 // static
450 void MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath(
451 DownloadItem* download,
452 const base::FilePath& virtual_path,
453 bool create_directory,
454 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
455 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
456 callback.Run(virtual_path, true);
459 // static
460 void MockDownloadTargetDeterminerDelegate::NullPromptUser(
461 DownloadItem* download, const base::FilePath& suggested_path,
462 const FileSelectedCallback& callback) {
463 callback.Run(suggested_path);
466 // static
467 void MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath(
468 DownloadItem* download, const base::FilePath& virtual_path,
469 const LocalPathCallback& callback) {
470 callback.Run(virtual_path);
473 // NotifyExtensions implementation that overrides the path so that the target
474 // file is in a subdirectory called 'overridden'. If the extension is '.remove',
475 // the extension is removed.
476 void NotifyExtensionsOverridePath(
477 content::DownloadItem* download,
478 const base::FilePath& path,
479 const DownloadTargetDeterminerDelegate::NotifyExtensionsCallback&
480 callback) {
481 base::FilePath new_path =
482 base::FilePath()
483 .AppendASCII("overridden")
484 .Append(path.BaseName());
485 if (new_path.MatchesExtension(FILE_PATH_LITERAL(".remove")))
486 new_path = new_path.RemoveExtension();
487 callback.Run(new_path, DownloadPathReservationTracker::UNIQUIFY);
490 void CheckDownloadUrlCheckExes(
491 content::DownloadItem* download,
492 const base::FilePath& path,
493 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback&
494 callback) {
495 if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
496 callback.Run(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT);
497 else
498 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
501 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_Basic) {
502 const DownloadTestCase kBasicTestCases[] = {
504 // 0: Automatic Safe
505 AUTOMATIC,
506 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
507 "http://example.com/foo.txt", "text/plain",
508 FILE_PATH_LITERAL(""),
510 FILE_PATH_LITERAL("foo.txt"),
511 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
513 EXPECT_CRDOWNLOAD
517 // 1: Save_As Safe
518 SAVE_AS,
519 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
520 "http://example.com/foo.txt", "text/plain",
521 FILE_PATH_LITERAL(""),
523 FILE_PATH_LITERAL("foo.txt"),
524 DownloadItem::TARGET_DISPOSITION_PROMPT,
526 EXPECT_CRDOWNLOAD
530 // 2: Automatic Dangerous
531 AUTOMATIC,
532 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
533 "http://example.com/foo.crx", "",
534 FILE_PATH_LITERAL(""),
536 FILE_PATH_LITERAL("foo.crx"),
537 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
539 EXPECT_UNCONFIRMED
543 // 3: Forced Safe
544 FORCED,
545 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
546 "http://example.com/foo.txt", "",
547 FILE_PATH_LITERAL("forced-foo.txt"),
549 FILE_PATH_LITERAL("forced-foo.txt"),
550 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
552 EXPECT_LOCAL_PATH
556 // The test assumes that .crx files have a danger level of
557 // ALLOW_ON_USER_GESTURE.
558 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
559 download_util::GetFileDangerLevel(
560 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
561 RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
564 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_CancelSaveAs) {
565 const DownloadTestCase kCancelSaveAsTestCases[] = {
567 // 0: Save_As Safe, Cancelled.
568 SAVE_AS,
569 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
570 "http://example.com/foo.txt", "text/plain",
571 FILE_PATH_LITERAL(""),
573 FILE_PATH_LITERAL(""),
574 DownloadItem::TARGET_DISPOSITION_PROMPT,
576 EXPECT_LOCAL_PATH
579 ON_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
580 .WillByDefault(WithArg<2>(ScheduleCallback(base::FilePath())));
581 RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
582 arraysize(kCancelSaveAsTestCases));
585 // The SafeBrowsing check is performed early. Make sure that a download item
586 // that has been marked as DANGEROUS_URL behaves correctly.
587 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DangerousUrl) {
588 const DownloadTestCase kSafeBrowsingTestCases[] = {
590 // 0: Automatic Dangerous URL
591 AUTOMATIC,
592 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
593 "http://phishing.example.com/foo.txt", "",
594 FILE_PATH_LITERAL(""),
596 FILE_PATH_LITERAL("foo.txt"),
597 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
599 EXPECT_UNCONFIRMED
603 // 1: Save As Dangerous URL
604 SAVE_AS,
605 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
606 "http://phishing.example.com/foo.txt", "",
607 FILE_PATH_LITERAL(""),
609 FILE_PATH_LITERAL("foo.txt"),
610 DownloadItem::TARGET_DISPOSITION_PROMPT,
612 EXPECT_UNCONFIRMED
616 // 2: Forced Dangerous URL
617 FORCED,
618 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
619 "http://phishing.example.com/foo.txt", "",
620 FILE_PATH_LITERAL("forced-foo.txt"),
622 FILE_PATH_LITERAL("forced-foo.txt"),
623 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
625 EXPECT_UNCONFIRMED
629 // 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes
630 // precendence.
631 AUTOMATIC,
632 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
633 "http://phishing.example.com/foo.html", "",
634 FILE_PATH_LITERAL(""),
636 FILE_PATH_LITERAL("foo.html"),
637 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
639 EXPECT_UNCONFIRMED
643 // 4: Save As Dangerous URL + Dangerous file
644 SAVE_AS,
645 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
646 "http://phishing.example.com/foo.html", "",
647 FILE_PATH_LITERAL(""),
649 FILE_PATH_LITERAL("foo.html"),
650 DownloadItem::TARGET_DISPOSITION_PROMPT,
652 EXPECT_UNCONFIRMED
656 // 5: Forced Dangerous URL + Dangerous file
657 FORCED,
658 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
659 "http://phishing.example.com/foo.html", "",
660 FILE_PATH_LITERAL("forced-foo.html"),
662 FILE_PATH_LITERAL("forced-foo.html"),
663 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
665 EXPECT_UNCONFIRMED
669 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
670 .WillByDefault(WithArg<2>(ScheduleCallback(
671 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
672 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
673 arraysize(kSafeBrowsingTestCases));
676 // The SafeBrowsing check is performed early. Make sure that a download item
677 // that has been marked as MAYBE_DANGEROUS_CONTENT behaves correctly.
678 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_MaybeDangerousContent) {
679 const DownloadTestCase kSafeBrowsingTestCases[] = {
681 // 0: Automatic Maybe dangerous content
682 AUTOMATIC,
683 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
684 "http://phishing.example.com/foo.exe", "",
685 FILE_PATH_LITERAL(""),
687 FILE_PATH_LITERAL("foo.exe"),
688 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
690 EXPECT_UNCONFIRMED
694 // 1: Save As Maybe dangerous content
695 SAVE_AS,
696 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
697 "http://phishing.example.com/foo.exe", "",
698 FILE_PATH_LITERAL(""),
700 FILE_PATH_LITERAL("foo.exe"),
701 DownloadItem::TARGET_DISPOSITION_PROMPT,
703 EXPECT_UNCONFIRMED
707 // 2: Forced Maybe dangerous content
708 FORCED,
709 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
710 "http://phishing.example.com/foo.exe", "",
711 FILE_PATH_LITERAL("forced-foo.exe"),
713 FILE_PATH_LITERAL("forced-foo.exe"),
714 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
716 EXPECT_UNCONFIRMED
720 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
721 .WillByDefault(WithArg<2>(ScheduleCallback(
722 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
723 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
724 arraysize(kSafeBrowsingTestCases));
727 // Test whether the last saved directory is used for 'Save As' downloads.
728 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LastSavePath) {
729 const DownloadTestCase kLastSavePathTestCasesPre[] = {
731 // 0: If the last save path is empty, then the default download directory
732 // should be used.
733 SAVE_AS,
734 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
735 "http://example.com/foo.txt", "text/plain",
736 FILE_PATH_LITERAL(""),
738 FILE_PATH_LITERAL("foo.txt"),
739 DownloadItem::TARGET_DISPOSITION_PROMPT,
741 EXPECT_CRDOWNLOAD
745 // These test cases are run with a last save path set to a non-emtpy local
746 // download directory.
747 const DownloadTestCase kLastSavePathTestCasesPost[] = {
749 // 0: This test case is run with the last download directory set to
750 // '<test_download_dir()>/foo'.
751 SAVE_AS,
752 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
753 "http://example.com/foo.txt", "text/plain",
754 FILE_PATH_LITERAL(""),
756 FILE_PATH_LITERAL("foo/foo.txt"),
757 DownloadItem::TARGET_DISPOSITION_PROMPT,
759 EXPECT_CRDOWNLOAD
763 // 1: Start an automatic download. This should be saved to the user's
764 // default download directory and not the last used Save As directory.
765 AUTOMATIC,
766 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
767 "http://example.com/foo.txt", "text/plain",
768 FILE_PATH_LITERAL(""),
770 FILE_PATH_LITERAL("foo.txt"),
771 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
773 EXPECT_CRDOWNLOAD
777 // This test case is run with the last save path set to a non-empty virtual
778 // directory.
779 const DownloadTestCase kLastSavePathTestCasesVirtual[] = {
781 SAVE_AS,
782 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
783 "http://example.com/foo.txt", "text/plain",
784 FILE_PATH_LITERAL(""),
786 FILE_PATH_LITERAL("bar.txt"),
787 DownloadItem::TARGET_DISPOSITION_PROMPT,
789 EXPECT_LOCAL_PATH
794 SCOPED_TRACE(testing::Message()
795 << "Running with default download path");
796 base::FilePath prompt_path =
797 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
798 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
799 RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
800 arraysize(kLastSavePathTestCasesPre));
803 // Try with a non-empty last save path.
805 SCOPED_TRACE(testing::Message()
806 << "Running with local last_selected_directory");
807 download_prefs()->SetSaveFilePath(test_download_dir().AppendASCII("foo"));
808 base::FilePath prompt_path =
809 GetPathInDownloadDir(FILE_PATH_LITERAL("foo/foo.txt"));
810 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
811 RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
812 arraysize(kLastSavePathTestCasesPost));
815 // And again, but this time use a virtual directory.
817 SCOPED_TRACE(testing::Message()
818 << "Running with virtual last_selected_directory");
819 base::FilePath last_selected_dir = test_virtual_dir().AppendASCII("foo");
820 base::FilePath virtual_path = last_selected_dir.AppendASCII("foo.txt");
821 download_prefs()->SetSaveFilePath(last_selected_dir);
822 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
823 _, last_selected_dir.AppendASCII("foo.txt"), _));
824 EXPECT_CALL(*delegate(), DetermineLocalPath(_, virtual_path, _))
825 .WillOnce(WithArg<2>(ScheduleCallback(
826 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")))));
827 RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
828 arraysize(kLastSavePathTestCasesVirtual));
832 // These tests are run with the default downloads folder set to a virtual
833 // directory.
834 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DefaultVirtual) {
835 // The default download directory is the virutal path.
836 download_prefs()->SetDownloadPath(test_virtual_dir());
839 SCOPED_TRACE(testing::Message() << "Automatic Safe Download");
840 const DownloadTestCase kAutomaticDownloadToVirtualDir = {
841 AUTOMATIC,
842 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
843 "http://example.com/foo.txt", "text/plain",
844 FILE_PATH_LITERAL(""),
846 FILE_PATH_LITERAL("foo-local.txt"),
847 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
849 EXPECT_LOCAL_PATH
851 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
852 .WillOnce(WithArg<2>(ScheduleCallback(
853 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
854 RunTestCasesWithActiveItem(&kAutomaticDownloadToVirtualDir, 1);
858 SCOPED_TRACE(testing::Message() << "Save As to virtual directory");
859 const DownloadTestCase kSaveAsToVirtualDir = {
860 SAVE_AS,
861 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
862 "http://example.com/bar.txt", "text/plain",
863 FILE_PATH_LITERAL(""),
865 FILE_PATH_LITERAL("foo-local.txt"),
866 DownloadItem::TARGET_DISPOSITION_PROMPT,
868 EXPECT_LOCAL_PATH
870 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
871 .WillOnce(WithArg<2>(ScheduleCallback(
872 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
873 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
874 _, test_virtual_dir().AppendASCII("bar.txt"), _))
875 .WillOnce(WithArg<2>(ScheduleCallback(
876 test_virtual_dir().AppendASCII("prompted.txt"))));
877 RunTestCasesWithActiveItem(&kSaveAsToVirtualDir, 1);
881 SCOPED_TRACE(testing::Message() << "Save As to local directory");
882 const DownloadTestCase kSaveAsToLocalDir = {
883 SAVE_AS,
884 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
885 "http://example.com/bar.txt", "text/plain",
886 FILE_PATH_LITERAL(""),
888 FILE_PATH_LITERAL("foo-x.txt"),
889 DownloadItem::TARGET_DISPOSITION_PROMPT,
891 EXPECT_CRDOWNLOAD
893 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
894 _, test_virtual_dir().AppendASCII("bar.txt"), _))
895 .WillOnce(WithArg<2>(ScheduleCallback(
896 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")))));
897 RunTestCasesWithActiveItem(&kSaveAsToLocalDir, 1);
901 SCOPED_TRACE(testing::Message() << "Forced safe download");
902 const DownloadTestCase kForcedSafe = {
903 FORCED,
904 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
905 "http://example.com/foo.txt", "",
906 FILE_PATH_LITERAL("forced-foo.txt"),
908 FILE_PATH_LITERAL("forced-foo.txt"),
909 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
911 EXPECT_LOCAL_PATH
913 RunTestCasesWithActiveItem(&kForcedSafe, 1);
917 // Test that an inactive download will still get a virtual or local download
918 // path.
919 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_InactiveDownload) {
920 const DownloadTestCase kInactiveTestCases[] = {
922 AUTOMATIC,
923 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
924 "http://example.com/foo.txt", "text/plain",
925 FILE_PATH_LITERAL(""),
927 FILE_PATH_LITERAL(""),
928 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
930 EXPECT_LOCAL_PATH
934 SAVE_AS,
935 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
936 "http://example.com/foo.txt", "text/plain",
937 FILE_PATH_LITERAL(""),
939 FILE_PATH_LITERAL(""),
940 DownloadItem::TARGET_DISPOSITION_PROMPT,
942 EXPECT_LOCAL_PATH
946 for (size_t i = 0; i < arraysize(kInactiveTestCases); ++i) {
947 SCOPED_TRACE(testing::Message() << "Running test case " << i);
948 const DownloadTestCase& test_case = kInactiveTestCases[i];
949 scoped_ptr<content::MockDownloadItem> item(
950 CreateActiveDownloadItem(i, test_case));
951 EXPECT_CALL(*item.get(), GetState())
952 .WillRepeatedly(Return(content::DownloadItem::CANCELLED));
953 // Even though one is a SAVE_AS download, no prompt will be displayed to
954 // the user because the download is inactive.
955 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
956 .Times(0);
957 RunTestCase(test_case, base::FilePath(), item.get());
961 // If the reserved path could not be verified, then the user should see a
962 // prompt.
963 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ReservationFailed) {
964 const DownloadTestCase kReservationFailedCases[] = {
966 // 0: Automatic download. Since the reservation fails, the disposition of
967 // the target is to prompt, but the returned path is used.
968 AUTOMATIC,
969 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
970 "http://example.com/foo.txt", "text/plain",
971 FILE_PATH_LITERAL(""),
973 FILE_PATH_LITERAL("bar.txt"),
974 DownloadItem::TARGET_DISPOSITION_PROMPT,
976 EXPECT_CRDOWNLOAD
980 // Setup ReserveVirtualPath() to fail.
981 ON_CALL(*delegate(), ReserveVirtualPath(_, _, _, _, _))
982 .WillByDefault(WithArg<4>(ScheduleCallback2(
983 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")), false)));
984 RunTestCasesWithActiveItem(kReservationFailedCases,
985 arraysize(kReservationFailedCases));
988 // If the local path could not be determined, the download should be cancelled.
989 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LocalPathFailed) {
990 const DownloadTestCase kLocalPathFailedCases[] = {
992 // 0: Automatic download.
993 AUTOMATIC,
994 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
995 "http://example.com/foo.txt", "text/plain",
996 FILE_PATH_LITERAL(""),
998 FILE_PATH_LITERAL(""),
999 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1001 EXPECT_LOCAL_PATH
1005 // The default download directory is the virtual path.
1006 download_prefs()->SetDownloadPath(test_virtual_dir());
1007 // Simulate failed call to DetermineLocalPath.
1008 EXPECT_CALL(*delegate(), DetermineLocalPath(
1009 _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
1010 .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
1011 RunTestCasesWithActiveItem(kLocalPathFailedCases,
1012 arraysize(kLocalPathFailedCases));
1015 // Downloads that have a danger level of ALLOW_ON_USER_GESTURE should be marked
1016 // as safe depending on whether there was a user gesture associated with the
1017 // download and whether the referrer was visited prior to today.
1018 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_VisitedReferrer) {
1019 const DownloadTestCase kVisitedReferrerCases[] = {
1020 // http://visited.example.com/ is added to the history as a visit that
1021 // happened prior to today.
1023 // 0: Safe download due to visiting referrer before.
1024 AUTOMATIC,
1025 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1026 "http://visited.example.com/foo.crx", "application/xml",
1027 FILE_PATH_LITERAL(""),
1029 FILE_PATH_LITERAL("foo.crx"),
1030 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1032 EXPECT_CRDOWNLOAD
1036 // 1: Dangerous due to not having visited referrer before.
1037 AUTOMATIC,
1038 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1039 "http://not-visited.example.com/foo.crx", "application/xml",
1040 FILE_PATH_LITERAL(""),
1042 FILE_PATH_LITERAL("foo.crx"),
1043 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1045 EXPECT_UNCONFIRMED
1049 // 2: Safe because the user is being prompted.
1050 SAVE_AS,
1051 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1052 "http://not-visited.example.com/foo.crx", "application/xml",
1053 FILE_PATH_LITERAL(""),
1055 FILE_PATH_LITERAL("foo.crx"),
1056 DownloadItem::TARGET_DISPOSITION_PROMPT,
1058 EXPECT_CRDOWNLOAD
1062 // 3: Safe because of forced path.
1063 FORCED,
1064 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1065 "http://not-visited.example.com/foo.crx", "application/xml",
1066 FILE_PATH_LITERAL("foo.crx"),
1068 FILE_PATH_LITERAL("foo.crx"),
1069 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1071 EXPECT_LOCAL_PATH
1075 // This test assumes that the danger level of .crx files is
1076 // ALLOW_ON_USER_GESTURE.
1077 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1078 download_util::GetFileDangerLevel(
1079 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1081 // First the history service must exist.
1082 ASSERT_TRUE(profile()->CreateHistoryService(false, false));
1084 GURL url("http://visited.example.com/visited-link.html");
1085 // The time of visit is picked to be several seconds prior to the most recent
1086 // midnight.
1087 base::Time time_of_visit(
1088 base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(10));
1089 HistoryService* history_service =
1090 HistoryServiceFactory::GetForProfile(profile(), Profile::EXPLICIT_ACCESS);
1091 ASSERT_TRUE(history_service);
1092 history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
1094 RunTestCasesWithActiveItem(kVisitedReferrerCases,
1095 arraysize(kVisitedReferrerCases));
1098 // These test cases are run with "Prompt for download" user preference set to
1099 // true.
1100 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways) {
1101 const DownloadTestCase kPromptingTestCases[] = {
1103 // 0: Safe Automatic - Should prompt because of "Prompt for download"
1104 // preference setting.
1105 AUTOMATIC,
1106 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1107 "http://example.com/foo.txt", "text/plain",
1108 FILE_PATH_LITERAL(""),
1110 FILE_PATH_LITERAL("foo.txt"),
1111 DownloadItem::TARGET_DISPOSITION_PROMPT,
1113 EXPECT_CRDOWNLOAD
1117 // 1: Safe Forced - Shouldn't prompt.
1118 FORCED,
1119 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1120 "http://example.com/foo.txt", "text/plain",
1121 FILE_PATH_LITERAL("foo.txt"),
1123 FILE_PATH_LITERAL("foo.txt"),
1124 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1126 EXPECT_LOCAL_PATH
1130 // 2: Automatic - The filename extension is marked as one that we will
1131 // open automatically. Shouldn't prompt.
1132 AUTOMATIC,
1133 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1134 "http://example.com/foo.dummy", "",
1135 FILE_PATH_LITERAL(""),
1137 FILE_PATH_LITERAL("foo.dummy"),
1138 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1140 EXPECT_CRDOWNLOAD
1144 SetPromptForDownload(true);
1145 EnableAutoOpenBasedOnExtension(
1146 base::FilePath(FILE_PATH_LITERAL("dummy.dummy")));
1147 RunTestCasesWithActiveItem(kPromptingTestCases,
1148 arraysize(kPromptingTestCases));
1151 #if !defined(OS_ANDROID)
1152 // These test cases are run with "Prompt for download" user preference set to
1153 // true. Automatic extension downloads shouldn't cause prompting.
1154 // Android doesn't support extensions.
1155 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways_Extension) {
1156 const DownloadTestCase kPromptingTestCases[] = {
1158 // 0: Automatic Browser Extension download. - Shouldn't prompt for browser
1159 // extension downloads even if "Prompt for download" preference is set.
1160 AUTOMATIC,
1161 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1162 "http://example.com/foo.crx",
1163 extensions::Extension::kMimeType,
1164 FILE_PATH_LITERAL(""),
1166 FILE_PATH_LITERAL("foo.crx"),
1167 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1169 EXPECT_UNCONFIRMED
1172 #if defined(OS_WIN)
1174 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1175 // even if "Prompt for download" preference is set. ".js" files are
1176 // considered dangerous on Windows.
1177 AUTOMATIC,
1178 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1179 "http://example.com/foo.user.js", "",
1180 FILE_PATH_LITERAL(""),
1182 FILE_PATH_LITERAL("foo.user.js"),
1183 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1185 EXPECT_UNCONFIRMED
1187 #else
1189 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1190 // even if "Prompt for download" preference is set.
1191 AUTOMATIC,
1192 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1193 "http://example.com/foo.user.js", "",
1194 FILE_PATH_LITERAL(""),
1196 FILE_PATH_LITERAL("foo.user.js"),
1197 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1199 EXPECT_CRDOWNLOAD
1201 #endif
1204 SetPromptForDownload(true);
1205 RunTestCasesWithActiveItem(kPromptingTestCases,
1206 arraysize(kPromptingTestCases));
1208 #endif
1210 // If the download path is managed, then we don't show any prompts.
1211 // Note that if the download path is managed, then PromptForDownload() is false.
1212 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ManagedPath) {
1213 const DownloadTestCase kManagedPathTestCases[] = {
1215 // 0: Automatic Safe
1216 AUTOMATIC,
1217 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1218 "http://example.com/foo.txt", "text/plain",
1219 FILE_PATH_LITERAL(""),
1221 FILE_PATH_LITERAL("foo.txt"),
1222 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1224 EXPECT_CRDOWNLOAD
1228 // 1: Save_As Safe
1229 SAVE_AS,
1230 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1231 "http://example.com/foo.txt", "text/plain",
1232 FILE_PATH_LITERAL(""),
1234 FILE_PATH_LITERAL("foo.txt"),
1235 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1237 EXPECT_CRDOWNLOAD
1241 SetManagedDownloadPath(test_download_dir());
1242 ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
1243 RunTestCasesWithActiveItem(kManagedPathTestCases,
1244 arraysize(kManagedPathTestCases));
1247 // Test basic functionality supporting extensions that want to override download
1248 // filenames.
1249 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsSafe) {
1250 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1252 // 0: Automatic Safe
1253 AUTOMATIC,
1254 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1255 "http://example.com/foo.txt", "text/plain",
1256 FILE_PATH_LITERAL(""),
1258 FILE_PATH_LITERAL("overridden/foo.txt"),
1259 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1261 EXPECT_CRDOWNLOAD
1265 // 1: Save_As Safe
1266 SAVE_AS,
1267 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1268 "http://example.com/foo.txt", "text/plain",
1269 FILE_PATH_LITERAL(""),
1271 FILE_PATH_LITERAL("overridden/foo.txt"),
1272 DownloadItem::TARGET_DISPOSITION_PROMPT,
1274 EXPECT_CRDOWNLOAD
1278 // 2: Automatic Dangerous
1279 AUTOMATIC,
1280 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1281 "http://example.com/foo.crx", "",
1282 FILE_PATH_LITERAL(""),
1284 FILE_PATH_LITERAL("overridden/foo.crx"),
1285 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1287 EXPECT_UNCONFIRMED
1291 // 3: Forced Safe
1292 FORCED,
1293 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1294 "http://example.com/foo.txt", "",
1295 FILE_PATH_LITERAL("forced-foo.txt"),
1297 FILE_PATH_LITERAL("forced-foo.txt"),
1298 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1300 EXPECT_LOCAL_PATH
1304 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1305 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1306 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1307 arraysize(kNotifyExtensionsTestCases));
1310 // Test that filenames provided by extensions are passed into SafeBrowsing
1311 // checks and dangerous download checks.
1312 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsUnsafe) {
1313 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1315 // 0: Automatic Safe : Later overridden by a dangerous filetype.
1316 AUTOMATIC,
1317 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1318 "http://example.com/foo.crx.remove", "text/plain",
1319 FILE_PATH_LITERAL(""),
1321 FILE_PATH_LITERAL("overridden/foo.crx"),
1322 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1324 EXPECT_UNCONFIRMED
1328 // 1: Automatic Safe : Later overridden by a potentially dangerous
1329 // filetype.
1330 AUTOMATIC,
1331 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
1332 "http://example.com/foo.exe.remove", "text/plain",
1333 FILE_PATH_LITERAL(""),
1335 FILE_PATH_LITERAL("overridden/foo.exe"),
1336 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1338 EXPECT_UNCONFIRMED
1342 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1343 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1344 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
1345 .WillByDefault(Invoke(&CheckDownloadUrlCheckExes));
1346 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1347 arraysize(kNotifyExtensionsTestCases));
1350 // Test that conflict actions set by extensions are passed correctly into
1351 // ReserveVirtualPath.
1352 TEST_F(DownloadTargetDeterminerTest,
1353 TargetDeterminer_NotifyExtensionsConflict) {
1354 const DownloadTestCase kNotifyExtensionsTestCase = {
1355 AUTOMATIC,
1356 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1357 "http://example.com/foo.txt", "text/plain",
1358 FILE_PATH_LITERAL(""),
1360 FILE_PATH_LITERAL("overridden/foo.txt"),
1361 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1363 EXPECT_CRDOWNLOAD
1366 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1367 scoped_ptr<content::MockDownloadItem> item(
1368 CreateActiveDownloadItem(0, test_case));
1369 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1370 base::FilePath full_overridden_path =
1371 GetPathInDownloadDir(overridden_path.value());
1373 // First case: An extension sets the conflict_action to OVERWRITE.
1374 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1375 .WillOnce(WithArg<2>(
1376 ScheduleCallback2(overridden_path,
1377 DownloadPathReservationTracker::OVERWRITE)));
1378 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1379 _, full_overridden_path, true, DownloadPathReservationTracker::OVERWRITE,
1380 _)).WillOnce(WithArg<4>(
1381 ScheduleCallback2(full_overridden_path, true)));
1383 RunTestCase(test_case, base::FilePath(), item.get());
1385 // Second case: An extension sets the conflict_action to PROMPT.
1386 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1387 .WillOnce(WithArg<2>(
1388 ScheduleCallback2(overridden_path,
1389 DownloadPathReservationTracker::PROMPT)));
1390 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1391 _, full_overridden_path, true, DownloadPathReservationTracker::PROMPT, _))
1392 .WillOnce(WithArg<4>(
1393 ScheduleCallback2(full_overridden_path, true)));
1394 RunTestCase(test_case, base::FilePath(), item.get());
1397 // Test that relative paths returned by extensions are always relative to the
1398 // default downloads path.
1399 TEST_F(DownloadTargetDeterminerTest,
1400 TargetDeterminer_NotifyExtensionsDefaultPath) {
1401 const DownloadTestCase kNotifyExtensionsTestCase = {
1402 SAVE_AS,
1403 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1404 "http://example.com/foo.txt", "text/plain",
1405 FILE_PATH_LITERAL(""),
1407 FILE_PATH_LITERAL("overridden/foo.txt"),
1408 DownloadItem::TARGET_DISPOSITION_PROMPT,
1410 EXPECT_CRDOWNLOAD
1413 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1414 scoped_ptr<content::MockDownloadItem> item(
1415 CreateActiveDownloadItem(0, test_case));
1416 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1417 base::FilePath full_overridden_path =
1418 GetPathInDownloadDir(overridden_path.value());
1420 download_prefs()->SetSaveFilePath(GetPathInDownloadDir(
1421 FILE_PATH_LITERAL("last_selected")));
1423 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1424 .WillOnce(WithArg<2>(
1425 ScheduleCallback2(overridden_path,
1426 DownloadPathReservationTracker::UNIQUIFY)));
1427 EXPECT_CALL(*delegate(),
1428 PromptUserForDownloadPath(_, full_overridden_path, _))
1429 .WillOnce(WithArg<2>(
1430 ScheduleCallback(full_overridden_path)));
1431 RunTestCase(test_case, base::FilePath(), item.get());
1434 TEST_F(DownloadTargetDeterminerTest,
1435 TargetDeterminer_InitialVirtualPathUnsafe) {
1436 const base::FilePath::CharType* kInitialPath =
1437 FILE_PATH_LITERAL("some_path/bar.html");
1439 const DownloadTestCase kInitialPathTestCase = {
1440 // 0: Save As Save. The path generated based on the DownloadItem is safe,
1441 // but the initial path is unsafe. However, the download is not considered
1442 // dangerous since the user has been prompted.
1443 SAVE_AS,
1444 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1445 "http://example.com/foo.txt", "text/plain",
1446 FILE_PATH_LITERAL(""),
1448 kInitialPath,
1449 DownloadItem::TARGET_DISPOSITION_PROMPT,
1451 EXPECT_CRDOWNLOAD
1454 const DownloadTestCase& test_case = kInitialPathTestCase;
1455 scoped_ptr<content::MockDownloadItem> item(
1456 CreateActiveDownloadItem(1, test_case));
1457 EXPECT_CALL(*item, GetLastReason())
1458 .WillRepeatedly(Return(
1459 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1460 EXPECT_CALL(*item, GetTargetDisposition())
1461 .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
1462 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1465 // Prompting behavior for resumed downloads is based on the last interrupt
1466 // reason. If the reason indicates that the target path may not be suitable for
1467 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1468 // prompted, and not otherwise. These test cases shouldn't result in prompting
1469 // since the error is set to NETWORK_FAILED.
1470 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedNoPrompt) {
1471 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1472 // path.
1473 const base::FilePath::CharType* kInitialPath =
1474 FILE_PATH_LITERAL("some_path/bar.txt");
1476 const DownloadTestCase kResumedTestCases[] = {
1478 // 0: Automatic Safe: Initial path is ignored since the user has not been
1479 // prompted before.
1480 AUTOMATIC,
1481 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1482 "http://example.com/foo.txt", "text/plain",
1483 FILE_PATH_LITERAL(""),
1485 FILE_PATH_LITERAL("foo.txt"),
1486 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1488 EXPECT_CRDOWNLOAD
1492 // 1: Save_As Safe: Initial path used.
1493 SAVE_AS,
1494 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1495 "http://example.com/foo.txt", "text/plain",
1496 FILE_PATH_LITERAL(""),
1498 kInitialPath,
1499 DownloadItem::TARGET_DISPOSITION_PROMPT,
1501 EXPECT_CRDOWNLOAD
1505 // 2: Automatic Dangerous: Initial path is ignored since the user hasn't
1506 // been prompted before.
1507 AUTOMATIC,
1508 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1509 "http://example.com/foo.crx", "",
1510 FILE_PATH_LITERAL(""),
1512 FILE_PATH_LITERAL("foo.crx"),
1513 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1515 EXPECT_UNCONFIRMED
1519 // 3: Forced Safe: Initial path is ignored due to the forced path.
1520 FORCED,
1521 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1522 "http://example.com/foo.txt", "",
1523 FILE_PATH_LITERAL("forced-foo.txt"),
1525 FILE_PATH_LITERAL("forced-foo.txt"),
1526 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1528 EXPECT_LOCAL_PATH
1532 // The test assumes that .crx files have a danger level of
1533 // ALLOW_ON_USER_GESTURE.
1534 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1535 download_util::GetFileDangerLevel(
1536 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1537 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1538 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1539 const DownloadTestCase& test_case = kResumedTestCases[i];
1540 scoped_ptr<content::MockDownloadItem> item(
1541 CreateActiveDownloadItem(i, test_case));
1542 base::FilePath expected_path =
1543 GetPathInDownloadDir(test_case.expected_local_path);
1544 ON_CALL(*item.get(), GetLastReason())
1545 .WillByDefault(Return(
1546 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1547 // Extensions should be notified if a new path is being generated and there
1548 // is no forced path. In the test cases above, this is true for tests with
1549 // type == AUTOMATIC.
1550 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1551 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1552 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1553 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _))
1554 .Times(0);
1555 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1556 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1557 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1562 // Test that a forced download doesn't prompt, even if the interrupt reason
1563 // suggests that the target path may not be suitable for downloads.
1564 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedForcedDownload) {
1565 const base::FilePath::CharType* kInitialPath =
1566 FILE_PATH_LITERAL("some_path/bar.txt");
1567 const DownloadTestCase kResumedForcedDownload = {
1568 // 3: Forced Safe
1569 FORCED,
1570 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1571 "http://example.com/foo.txt", "",
1572 FILE_PATH_LITERAL("forced-foo.txt"),
1574 FILE_PATH_LITERAL("forced-foo.txt"),
1575 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1577 EXPECT_LOCAL_PATH
1580 const DownloadTestCase& test_case = kResumedForcedDownload;
1581 base::FilePath expected_path =
1582 GetPathInDownloadDir(test_case.expected_local_path);
1583 scoped_ptr<content::MockDownloadItem> item(
1584 CreateActiveDownloadItem(0, test_case));
1585 ON_CALL(*item.get(), GetLastReason())
1586 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1587 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1588 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1589 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1590 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
1591 .Times(0);
1592 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1593 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1594 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1597 // Prompting behavior for resumed downloads is based on the last interrupt
1598 // reason. If the reason indicates that the target path may not be suitable for
1599 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1600 // prompted, and not otherwise. These test cases result in prompting since the
1601 // error is set to NO_SPACE.
1602 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedWithPrompt) {
1603 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1604 // path.
1605 const base::FilePath::CharType* kInitialPath =
1606 FILE_PATH_LITERAL("some_path/bar.txt");
1608 const DownloadTestCase kResumedTestCases[] = {
1610 // 0: Automatic Safe
1611 AUTOMATIC,
1612 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1613 "http://example.com/foo.txt", "text/plain",
1614 FILE_PATH_LITERAL(""),
1616 FILE_PATH_LITERAL("foo.txt"),
1617 DownloadItem::TARGET_DISPOSITION_PROMPT,
1619 EXPECT_CRDOWNLOAD
1623 // 1: Save_As Safe
1624 SAVE_AS,
1625 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1626 "http://example.com/foo.txt", "text/plain",
1627 FILE_PATH_LITERAL(""),
1629 kInitialPath,
1630 DownloadItem::TARGET_DISPOSITION_PROMPT,
1632 EXPECT_CRDOWNLOAD
1636 // 2: Automatic Dangerous
1637 AUTOMATIC,
1638 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1639 "http://example.com/foo.crx", "",
1640 FILE_PATH_LITERAL(""),
1642 FILE_PATH_LITERAL("foo.crx"),
1643 DownloadItem::TARGET_DISPOSITION_PROMPT,
1645 EXPECT_CRDOWNLOAD
1649 // The test assumes that .xml files have a danger level of
1650 // ALLOW_ON_USER_GESTURE.
1651 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1652 download_util::GetFileDangerLevel(
1653 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1654 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1655 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1656 download_prefs()->SetSaveFilePath(test_download_dir());
1657 const DownloadTestCase& test_case = kResumedTestCases[i];
1658 base::FilePath expected_path =
1659 GetPathInDownloadDir(test_case.expected_local_path);
1660 scoped_ptr<content::MockDownloadItem> item(
1661 CreateActiveDownloadItem(i, test_case));
1662 ON_CALL(*item.get(), GetLastReason())
1663 .WillByDefault(Return(
1664 content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1665 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1666 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1667 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1668 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _));
1669 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1670 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1671 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1675 // Test intermediate filename generation for resumed downloads.
1676 TEST_F(DownloadTargetDeterminerTest,
1677 TargetDeterminer_IntermediateNameForResumed) {
1678 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1679 // path.
1680 const base::FilePath::CharType kInitialPath[] =
1681 FILE_PATH_LITERAL("some_path/bar.txt");
1683 struct IntermediateNameTestCase {
1684 // General test case settings.
1685 DownloadTestCase general;
1687 // Value of DownloadItem::GetFullPath() during test run, relative
1688 // to test download path.
1689 const base::FilePath::CharType* initial_intermediate_path;
1691 // Expected intermediate path relatvie to the test download path. An exact
1692 // match is performed if this string is non-empty. Ignored otherwise.
1693 const base::FilePath::CharType* expected_intermediate_path;
1694 } kIntermediateNameTestCases[] = {
1697 // 0: Automatic Safe
1698 AUTOMATIC,
1699 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1700 "http://example.com/foo.txt", "text/plain",
1701 FILE_PATH_LITERAL(""),
1703 FILE_PATH_LITERAL("foo.txt"),
1704 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1706 EXPECT_CRDOWNLOAD
1708 FILE_PATH_LITERAL("bar.txt.crdownload"),
1709 FILE_PATH_LITERAL("foo.txt.crdownload")
1714 // 1: Save_As Safe
1715 SAVE_AS,
1716 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1717 "http://example.com/foo.txt", "text/plain",
1718 FILE_PATH_LITERAL(""),
1720 kInitialPath,
1721 DownloadItem::TARGET_DISPOSITION_PROMPT,
1723 EXPECT_CRDOWNLOAD
1725 FILE_PATH_LITERAL("foo.txt.crdownload"),
1726 FILE_PATH_LITERAL("some_path/bar.txt.crdownload")
1731 // 2: Automatic Dangerous
1732 AUTOMATIC,
1733 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1734 "http://example.com/foo.crx", "",
1735 FILE_PATH_LITERAL(""),
1737 FILE_PATH_LITERAL("foo.crx"),
1738 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1740 EXPECT_UNCONFIRMED
1742 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload"),
1743 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload")
1748 // 3: Automatic Dangerous
1749 AUTOMATIC,
1750 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1751 "http://example.com/foo.crx", "",
1752 FILE_PATH_LITERAL(""),
1754 FILE_PATH_LITERAL("foo.crx"),
1755 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1757 EXPECT_UNCONFIRMED
1759 FILE_PATH_LITERAL("other_path/Unconfirmed abcd.crdownload"),
1760 // Rely on the EXPECT_UNCONFIRMED check in the general test settings. A
1761 // new intermediate path of the form "Unconfirmed <number>.crdownload"
1762 // should be generated for this case since the initial intermediate path
1763 // is in the wrong directory.
1764 FILE_PATH_LITERAL("")
1769 // 3: Forced Safe: Initial path is ignored due to the forced path.
1770 FORCED,
1771 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1772 "http://example.com/foo.txt", "",
1773 FILE_PATH_LITERAL("forced-foo.txt"),
1775 FILE_PATH_LITERAL("forced-foo.txt"),
1776 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1778 EXPECT_LOCAL_PATH
1780 FILE_PATH_LITERAL("forced-foo.txt"),
1781 FILE_PATH_LITERAL("forced-foo.txt")
1785 // The test assumes that .crx files have a danger level of
1786 // ALLOW_ON_USER_GESTURE.
1787 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1788 download_util::GetFileDangerLevel(
1789 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1791 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kIntermediateNameTestCases); ++i) {
1792 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1793 const IntermediateNameTestCase& test_case = kIntermediateNameTestCases[i];
1794 scoped_ptr<content::MockDownloadItem> item(
1795 CreateActiveDownloadItem(i, test_case.general));
1797 ON_CALL(*item.get(), GetLastReason())
1798 .WillByDefault(Return(
1799 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1800 ON_CALL(*item.get(), GetFullPath())
1801 .WillByDefault(ReturnRefOfCopy(
1802 GetPathInDownloadDir(test_case.initial_intermediate_path)));
1803 ON_CALL(*item.get(), GetDangerType())
1804 .WillByDefault(Return(test_case.general.expected_danger_type));
1806 scoped_ptr<DownloadTargetInfo> target_info =
1807 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1808 item.get());
1809 VerifyDownloadTarget(test_case.general, target_info.get());
1810 base::FilePath expected_intermediate_path =
1811 GetPathInDownloadDir(test_case.expected_intermediate_path);
1812 if (!expected_intermediate_path.empty())
1813 EXPECT_EQ(expected_intermediate_path, target_info->intermediate_path);
1817 // Test MIME type determination based on the target filename.
1818 TEST_F(DownloadTargetDeterminerTest,
1819 TargetDeterminer_MIMETypeDetermination) {
1820 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1821 // path.
1822 const base::FilePath::CharType kInitialPath[] =
1823 FILE_PATH_LITERAL("some_path/bar.txt");
1825 struct MIMETypeTestCase {
1826 // General test case settings.
1827 DownloadTestCase general;
1829 // Expected MIME type for test case.
1830 const char* expected_mime_type;
1831 } kMIMETypeTestCases[] = {
1834 // 0:
1835 AUTOMATIC,
1836 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1837 "http://example.com/foo.png", "image/png",
1838 FILE_PATH_LITERAL(""),
1840 FILE_PATH_LITERAL("foo.png"),
1841 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1843 EXPECT_CRDOWNLOAD
1845 "image/png"
1849 // 1: Empty MIME type in response.
1850 AUTOMATIC,
1851 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1852 "http://example.com/foo.png", "",
1853 FILE_PATH_LITERAL(""),
1855 FILE_PATH_LITERAL("foo.png"),
1856 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1858 EXPECT_CRDOWNLOAD
1860 "image/png"
1864 // 2: Forced path.
1865 FORCED,
1866 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1867 "http://example.com/foo.abc", "",
1868 FILE_PATH_LITERAL("foo.png"),
1870 FILE_PATH_LITERAL("foo.png"),
1871 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1873 EXPECT_CRDOWNLOAD
1875 "image/png"
1879 // 3: Unknown file type.
1880 AUTOMATIC,
1881 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1882 "http://example.com/foo.notarealext", "",
1883 FILE_PATH_LITERAL(""),
1885 FILE_PATH_LITERAL("foo.notarealext"),
1886 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1888 EXPECT_CRDOWNLOAD
1894 // 4: Unknown file type.
1895 AUTOMATIC,
1896 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1897 "http://example.com/foo.notarealext", "image/png",
1898 FILE_PATH_LITERAL(""),
1900 FILE_PATH_LITERAL("foo.notarealext"),
1901 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1903 EXPECT_CRDOWNLOAD
1909 ON_CALL(*delegate(), GetFileMimeType(
1910 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.png")), _))
1911 .WillByDefault(WithArg<1>(
1912 ScheduleCallback("image/png")));
1914 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kMIMETypeTestCases); ++i) {
1915 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1916 const MIMETypeTestCase& test_case = kMIMETypeTestCases[i];
1917 scoped_ptr<content::MockDownloadItem> item(
1918 CreateActiveDownloadItem(i, test_case.general));
1919 scoped_ptr<DownloadTargetInfo> target_info =
1920 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1921 item.get());
1922 EXPECT_EQ(test_case.expected_mime_type, target_info->mime_type);
1926 #if defined(ENABLE_PLUGINS)
1928 void DummyGetPluginsCallback(
1929 const base::Closure& closure,
1930 const std::vector<content::WebPluginInfo>& plugins) {
1931 closure.Run();
1934 void ForceRefreshOfPlugins() {
1935 #if !defined(OS_WIN)
1936 // Prevent creation of a utility process for loading plugins. Doing so breaks
1937 // unit_tests since /proc/self/exe can't be run as a utility process.
1938 content::RenderProcessHost::SetRunRendererInProcess(true);
1939 #endif
1940 base::RunLoop run_loop;
1941 content::PluginService::GetInstance()->GetPlugins(
1942 base::Bind(&DummyGetPluginsCallback, run_loop.QuitClosure()));
1943 run_loop.Run();
1944 #if !defined(OS_WIN)
1945 content::RenderProcessHost::SetRunRendererInProcess(false);
1946 #endif
1949 class MockPluginServiceFilter : public content::PluginServiceFilter {
1950 public:
1951 MOCK_METHOD1(MockPluginAvailable, bool(const base::FilePath&));
1953 virtual bool IsPluginAvailable(int render_process_id,
1954 int render_view_id,
1955 const void* context,
1956 const GURL& url,
1957 const GURL& policy_url,
1958 content::WebPluginInfo* plugin) OVERRIDE {
1959 return MockPluginAvailable(plugin->path);
1962 virtual bool CanLoadPlugin(int render_process_id,
1963 const base::FilePath& path) OVERRIDE {
1964 return true;
1968 class ScopedRegisterInternalPlugin {
1969 public:
1970 ScopedRegisterInternalPlugin(content::PluginService* plugin_service,
1971 content::WebPluginInfo::PluginType type,
1972 const base::FilePath& path,
1973 const char* mime_type,
1974 const char* extension)
1975 : plugin_service_(plugin_service),
1976 plugin_path_(path) {
1977 content::WebPluginMimeType plugin_mime_type(mime_type,
1978 extension,
1979 "Test file");
1980 content::WebPluginInfo plugin_info(base::string16(),
1981 path,
1982 base::string16(),
1983 base::string16());
1984 plugin_info.mime_types.push_back(plugin_mime_type);
1985 plugin_info.type = type;
1987 plugin_service->RegisterInternalPlugin(plugin_info, true);
1988 plugin_service->RefreshPlugins();
1989 ForceRefreshOfPlugins();
1992 ~ScopedRegisterInternalPlugin() {
1993 plugin_service_->UnregisterInternalPlugin(plugin_path_);
1994 plugin_service_->RefreshPlugins();
1995 ForceRefreshOfPlugins();
1998 const base::FilePath& path() { return plugin_path_; }
2000 private:
2001 content::PluginService* plugin_service_;
2002 base::FilePath plugin_path_;
2005 // We use a slightly different test fixture for tests that touch plugins. SetUp
2006 // needs to disable plugin discovery and we need to use a
2007 // ShadowingAtExitManager to discard the tainted PluginService. Unfortunately,
2008 // PluginService carries global state.
2009 class DownloadTargetDeterminerTestWithPlugin :
2010 public DownloadTargetDeterminerTest {
2011 public:
2012 DownloadTargetDeterminerTestWithPlugin()
2013 : old_plugin_service_filter_(NULL) {}
2015 virtual void SetUp() OVERRIDE {
2016 content::PluginService* plugin_service =
2017 content::PluginService::GetInstance();
2018 plugin_service->Init();
2019 plugin_service->DisablePluginsDiscoveryForTesting();
2020 old_plugin_service_filter_ = plugin_service->GetFilter();
2021 plugin_service->SetFilter(&mock_plugin_filter_);
2022 DownloadTargetDeterminerTest::SetUp();
2025 virtual void TearDown() OVERRIDE {
2026 content::PluginService::GetInstance()->SetFilter(
2027 old_plugin_service_filter_);
2028 DownloadTargetDeterminerTest::TearDown();
2031 protected:
2032 content::PluginServiceFilter* old_plugin_service_filter_;
2033 testing::StrictMock<MockPluginServiceFilter> mock_plugin_filter_;
2034 // The ShadowingAtExitManager destroys the tainted PluginService instance.
2035 base::ShadowingAtExitManager at_exit_manager_;
2038 // Check if secure handling of filetypes is determined correctly for PPAPI
2039 // plugins.
2040 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2041 TargetDeterminer_CheckForSecureHandling_PPAPI) {
2042 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2043 // path.
2044 const base::FilePath::CharType kInitialPath[] =
2045 FILE_PATH_LITERAL("some_path/bar.txt");
2046 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2048 DownloadTestCase kSecureHandlingTestCase = {
2049 AUTOMATIC,
2050 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2051 "http://example.com/foo.fakeext", "",
2052 FILE_PATH_LITERAL(""),
2054 FILE_PATH_LITERAL("foo.fakeext"),
2055 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2057 EXPECT_CRDOWNLOAD
2060 content::PluginService* plugin_service =
2061 content::PluginService::GetInstance();
2063 // Verify our test assumptions.
2065 ForceRefreshOfPlugins();
2066 std::vector<content::WebPluginInfo> info;
2067 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2068 GURL(), kTestMIMEType, false, &info, NULL));
2069 ASSERT_EQ(0u, info.size())
2070 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2073 ON_CALL(*delegate(), GetFileMimeType(
2074 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2075 .WillByDefault(WithArg<1>(
2076 ScheduleCallback(kTestMIMEType)));
2077 scoped_ptr<content::MockDownloadItem> item(
2078 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2079 scoped_ptr<DownloadTargetInfo> target_info =
2080 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2081 item.get());
2082 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2084 // Register a PPAPI plugin. This should count as handling the filetype
2085 // securely.
2086 ScopedRegisterInternalPlugin ppapi_plugin(
2087 plugin_service,
2088 content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS,
2089 test_download_dir().AppendASCII("ppapi"),
2090 kTestMIMEType,
2091 "fakeext");
2092 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(ppapi_plugin.path()))
2093 .WillRepeatedly(Return(true));
2095 target_info = RunDownloadTargetDeterminer(
2096 GetPathInDownloadDir(kInitialPath), item.get());
2097 EXPECT_TRUE(target_info->is_filetype_handled_safely);
2099 // Try disabling the plugin. Handling should no longer be considered secure.
2100 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(ppapi_plugin.path()))
2101 .WillRepeatedly(Return(false));
2102 target_info = RunDownloadTargetDeterminer(
2103 GetPathInDownloadDir(kInitialPath), item.get());
2104 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2106 // Now register an unsandboxed PPAPI plug-in. This plugin should not be
2107 // considered secure.
2108 ScopedRegisterInternalPlugin ppapi_unsandboxed_plugin(
2109 plugin_service,
2110 content::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED,
2111 test_download_dir().AppendASCII("ppapi-nosandbox"),
2112 kTestMIMEType,
2113 "fakeext");
2114 EXPECT_CALL(mock_plugin_filter_,
2115 MockPluginAvailable(ppapi_unsandboxed_plugin.path()))
2116 .WillRepeatedly(Return(true));
2118 target_info = RunDownloadTargetDeterminer(
2119 GetPathInDownloadDir(kInitialPath), item.get());
2120 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2123 // Check if secure handling of filetypes is determined correctly for NPAPI
2124 // plugins.
2125 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2126 TargetDeterminer_CheckForSecureHandling_NPAPI) {
2127 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2128 // path.
2129 const base::FilePath::CharType kInitialPath[] =
2130 FILE_PATH_LITERAL("some_path/bar.txt");
2131 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2133 DownloadTestCase kSecureHandlingTestCase = {
2134 AUTOMATIC,
2135 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2136 "http://example.com/foo.fakeext", "",
2137 FILE_PATH_LITERAL(""),
2139 FILE_PATH_LITERAL("foo.fakeext"),
2140 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2142 EXPECT_CRDOWNLOAD
2145 content::PluginService* plugin_service =
2146 content::PluginService::GetInstance();
2148 // Can't run this test if NPAPI isn't supported.
2149 if (!plugin_service->NPAPIPluginsSupported())
2150 return;
2152 // Verify our test assumptions.
2154 ForceRefreshOfPlugins();
2155 std::vector<content::WebPluginInfo> info;
2156 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2157 GURL(), kTestMIMEType, false, &info, NULL));
2158 ASSERT_EQ(0u, info.size())
2159 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2162 ON_CALL(*delegate(), GetFileMimeType(
2163 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2164 .WillByDefault(WithArg<1>(
2165 ScheduleCallback(kTestMIMEType)));
2166 scoped_ptr<content::MockDownloadItem> item(
2167 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2168 scoped_ptr<DownloadTargetInfo> target_info =
2169 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2170 item.get());
2171 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2173 // Register a NPAPI plugin. This should not count as handling the filetype
2174 // securely.
2175 ScopedRegisterInternalPlugin npapi_plugin(
2176 plugin_service,
2177 content::WebPluginInfo::PLUGIN_TYPE_NPAPI,
2178 test_download_dir().AppendASCII("npapi"),
2179 kTestMIMEType,
2180 "fakeext");
2181 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(npapi_plugin.path()))
2182 .WillRepeatedly(Return(true));
2184 target_info = RunDownloadTargetDeterminer(
2185 GetPathInDownloadDir(kInitialPath), item.get());
2186 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2188 #endif // ENABLE_PLUGINS
2190 } // namespace