Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / download / download_target_determiner_unittest.cc
blob53812ab44cd80554c8380d329f82789700d6c961
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/location.h"
9 #include "base/observer_list.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/value_conversions.h"
17 #include "chrome/browser/download/chrome_download_manager_delegate.h"
18 #include "chrome/browser/download/download_extensions.h"
19 #include "chrome/browser/download/download_prefs.h"
20 #include "chrome/browser/download/download_target_determiner.h"
21 #include "chrome/browser/download/download_target_info.h"
22 #include "chrome/browser/history/history_service_factory.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 "components/history/core/browser/history_service.h"
28 #include "components/history/core/browser/history_types.h"
29 #include "content/public/browser/download_interrupt_reasons.h"
30 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/web_contents.h"
32 #include "content/public/browser/web_contents_delegate.h"
33 #include "content/public/test/mock_download_item.h"
34 #include "content/public/test/test_renderer_host.h"
35 #include "content/public/test/web_contents_tester.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 #if defined(ENABLE_EXTENSIONS)
47 #include "extensions/common/extension.h"
48 #endif
50 using ::testing::AnyNumber;
51 using ::testing::Invoke;
52 using ::testing::Ref;
53 using ::testing::Return;
54 using ::testing::ReturnRef;
55 using ::testing::ReturnRefOfCopy;
56 using ::testing::Truly;
57 using ::testing::WithArg;
58 using ::testing::_;
59 using content::DownloadItem;
61 namespace {
63 // No-op delegate.
64 class NullWebContentsDelegate : public content::WebContentsDelegate {
65 public:
66 NullWebContentsDelegate() {}
67 ~NullWebContentsDelegate() override {}
70 // Google Mock action that posts a task to the current message loop that invokes
71 // the first argument of the mocked method as a callback. Said argument must be
72 // a base::Callback<void(ParamType)>. |result| must be of |ParamType| and is
73 // bound as that parameter.
74 // Example:
75 // class FooClass {
76 // public:
77 // virtual void Foo(base::Callback<void(bool)> callback);
78 // };
79 // ...
80 // EXPECT_CALL(mock_fooclass_instance, Foo(callback))
81 // .WillOnce(ScheduleCallback(false));
82 ACTION_P(ScheduleCallback, result0) {
83 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
84 base::Bind(arg0, result0));
87 // Similar to ScheduleCallback, but binds 2 arguments.
88 ACTION_P2(ScheduleCallback2, result0, result1) {
89 base::ThreadTaskRunnerHandle::Get()->PostTask(
90 FROM_HERE, base::Bind(arg0, result0, result1));
93 // Used with DownloadTestCase. Indicates the type of test case. The expectations
94 // for the test is set based on the type.
95 enum TestCaseType {
96 SAVE_AS,
97 AUTOMATIC,
98 FORCED // Requires that forced_file_path be non-empty.
101 // Used with DownloadTestCase. Type of intermediate filename to expect.
102 enum TestCaseExpectIntermediate {
103 EXPECT_CRDOWNLOAD, // Expect path/to/target.crdownload.
104 EXPECT_UNCONFIRMED, // Expect path/to/Unconfirmed xxx.crdownload.
105 EXPECT_LOCAL_PATH, // Expect target path.
108 // Typical download test case. Used with
109 // DownloadTargetDeterminerTest::RunTestCase().
110 struct DownloadTestCase {
111 // Type of test.
112 TestCaseType test_type;
114 // Expected danger type. Verified at the end of target determination.
115 content::DownloadDangerType expected_danger_type;
117 // Value of DownloadItem::GetURL()
118 const char* url;
120 // Value of DownloadItem::GetMimeType()
121 const char* mime_type;
123 // Should be non-empty if |test_type| == FORCED. Value of GetForcedFilePath().
124 const base::FilePath::CharType* forced_file_path;
126 // Expected local path. Specified relative to the test download path.
127 const base::FilePath::CharType* expected_local_path;
129 // Expected target disposition. If this is TARGET_DISPOSITION_PROMPT, then the
130 // test run will expect ChromeDownloadManagerDelegate to prompt the user for a
131 // download location.
132 DownloadItem::TargetDisposition expected_disposition;
134 // Type of intermediate path to expect.
135 TestCaseExpectIntermediate expected_intermediate;
138 class MockDownloadTargetDeterminerDelegate
139 : public DownloadTargetDeterminerDelegate {
140 public:
141 MOCK_METHOD3(CheckDownloadUrl,
142 void(content::DownloadItem*, const base::FilePath&,
143 const CheckDownloadUrlCallback&));
144 MOCK_METHOD3(NotifyExtensions,
145 void(content::DownloadItem*, const base::FilePath&,
146 const NotifyExtensionsCallback&));
147 MOCK_METHOD3(PromptUserForDownloadPath,
148 void(content::DownloadItem*, const base::FilePath&,
149 const FileSelectedCallback&));
150 MOCK_METHOD3(DetermineLocalPath,
151 void(DownloadItem*, const base::FilePath&,
152 const LocalPathCallback&));
153 MOCK_METHOD5(ReserveVirtualPath,
154 void(DownloadItem*, const base::FilePath&, bool,
155 DownloadPathReservationTracker::FilenameConflictAction,
156 const ReservedPathCallback&));
157 MOCK_METHOD2(GetFileMimeType,
158 void(const base::FilePath&,
159 const GetFileMimeTypeCallback&));
161 void SetupDefaults() {
162 ON_CALL(*this, CheckDownloadUrl(_, _, _))
163 .WillByDefault(WithArg<2>(
164 ScheduleCallback(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)));
165 ON_CALL(*this, NotifyExtensions(_, _, _))
166 .WillByDefault(WithArg<2>(
167 ScheduleCallback2(base::FilePath(),
168 DownloadPathReservationTracker::UNIQUIFY)));
169 ON_CALL(*this, ReserveVirtualPath(_, _, _, _, _))
170 .WillByDefault(Invoke(
171 &MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath));
172 ON_CALL(*this, PromptUserForDownloadPath(_, _, _))
173 .WillByDefault(Invoke(
174 &MockDownloadTargetDeterminerDelegate::NullPromptUser));
175 ON_CALL(*this, DetermineLocalPath(_, _, _))
176 .WillByDefault(Invoke(
177 &MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath));
178 ON_CALL(*this, GetFileMimeType(_, _))
179 .WillByDefault(WithArg<1>(
180 ScheduleCallback("")));
182 private:
183 static void NullReserveVirtualPath(
184 DownloadItem* download,
185 const base::FilePath& virtual_path,
186 bool create_directory,
187 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
188 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback);
189 static void NullPromptUser(
190 DownloadItem* download, const base::FilePath& suggested_path,
191 const FileSelectedCallback& callback);
192 static void NullDetermineLocalPath(
193 DownloadItem* download, const base::FilePath& virtual_path,
194 const LocalPathCallback& callback);
197 class DownloadTargetDeterminerTest : public ChromeRenderViewHostTestHarness {
198 public:
199 // ::testing::Test
200 void SetUp() override;
201 void TearDown() override;
203 // Creates MockDownloadItem and sets up default expectations.
204 content::MockDownloadItem* CreateActiveDownloadItem(
205 int32 id,
206 const DownloadTestCase& test_case);
208 // Sets the AutoOpenBasedOnExtension user preference for |path|.
209 void EnableAutoOpenBasedOnExtension(const base::FilePath& path);
211 // Set the kDownloadDefaultDirectory managed preference to |path|.
212 void SetManagedDownloadPath(const base::FilePath& path);
214 // Set the kPromptForDownload user preference to |prompt|.
215 void SetPromptForDownload(bool prompt);
217 // Given the relative path |path|, returns the full path under the temporary
218 // downloads directory.
219 base::FilePath GetPathInDownloadDir(const base::FilePath::StringType& path);
221 // Run |test_case| using |item|.
222 void RunTestCase(const DownloadTestCase& test_case,
223 const base::FilePath& initial_virtual_path,
224 content::MockDownloadItem* item);
226 // Runs |test_case| with |item|. When the DownloadTargetDeterminer is done,
227 // returns the resulting DownloadTargetInfo.
228 scoped_ptr<DownloadTargetInfo> RunDownloadTargetDeterminer(
229 const base::FilePath& initial_virtual_path,
230 content::MockDownloadItem* item);
232 // Run through |test_case_count| tests in |test_cases|. A new MockDownloadItem
233 // will be created for each test case and destroyed when the test case is
234 // complete.
235 void RunTestCasesWithActiveItem(const DownloadTestCase test_cases[],
236 size_t test_case_count);
238 // Verifies that |target_path|, |disposition|, |expected_danger_type| and
239 // |intermediate_path| matches the expectations of |test_case|. Posts
240 // |closure| to the current message loop when done.
241 void VerifyDownloadTarget(const DownloadTestCase& test_case,
242 const DownloadTargetInfo* target_info);
244 const base::FilePath& test_download_dir() const {
245 return test_download_dir_.path();
248 const base::FilePath& test_virtual_dir() const {
249 return test_virtual_dir_;
252 MockDownloadTargetDeterminerDelegate* delegate() {
253 return &delegate_;
256 DownloadPrefs* download_prefs() {
257 return download_prefs_.get();
260 private:
261 scoped_ptr<DownloadPrefs> download_prefs_;
262 ::testing::NiceMock<MockDownloadTargetDeterminerDelegate> delegate_;
263 NullWebContentsDelegate web_contents_delegate_;
264 base::ScopedTempDir test_download_dir_;
265 base::FilePath test_virtual_dir_;
268 void DownloadTargetDeterminerTest::SetUp() {
269 ChromeRenderViewHostTestHarness::SetUp();
270 CHECK(profile());
271 download_prefs_.reset(new DownloadPrefs(profile()));
272 web_contents()->SetDelegate(&web_contents_delegate_);
273 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
274 test_virtual_dir_ = test_download_dir().Append(FILE_PATH_LITERAL("virtual"));
275 download_prefs_->SetDownloadPath(test_download_dir());
276 delegate_.SetupDefaults();
279 void DownloadTargetDeterminerTest::TearDown() {
280 download_prefs_.reset();
281 ChromeRenderViewHostTestHarness::TearDown();
284 content::MockDownloadItem*
285 DownloadTargetDeterminerTest::CreateActiveDownloadItem(
286 int32 id,
287 const DownloadTestCase& test_case) {
288 content::MockDownloadItem* item =
289 new ::testing::NiceMock<content::MockDownloadItem>();
290 GURL download_url(test_case.url);
291 std::vector<GURL> url_chain;
292 url_chain.push_back(download_url);
293 base::FilePath forced_file_path =
294 GetPathInDownloadDir(test_case.forced_file_path);
295 DownloadItem::TargetDisposition initial_disposition =
296 (test_case.test_type == SAVE_AS) ?
297 DownloadItem::TARGET_DISPOSITION_PROMPT :
298 DownloadItem::TARGET_DISPOSITION_OVERWRITE;
299 EXPECT_EQ(test_case.test_type == FORCED,
300 !forced_file_path.empty());
302 ON_CALL(*item, GetBrowserContext())
303 .WillByDefault(Return(profile()));
304 ON_CALL(*item, GetDangerType())
305 .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
306 ON_CALL(*item, GetForcedFilePath())
307 .WillByDefault(ReturnRefOfCopy(forced_file_path));
308 ON_CALL(*item, GetFullPath())
309 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
310 ON_CALL(*item, GetHash())
311 .WillByDefault(ReturnRefOfCopy(std::string()));
312 ON_CALL(*item, GetId())
313 .WillByDefault(Return(id));
314 ON_CALL(*item, GetLastReason())
315 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE));
316 ON_CALL(*item, GetMimeType())
317 .WillByDefault(Return(test_case.mime_type));
318 ON_CALL(*item, GetReferrerUrl())
319 .WillByDefault(ReturnRefOfCopy(download_url));
320 ON_CALL(*item, GetState())
321 .WillByDefault(Return(DownloadItem::IN_PROGRESS));
322 ON_CALL(*item, GetTargetDisposition())
323 .WillByDefault(Return(initial_disposition));
324 ON_CALL(*item, GetTargetFilePath())
325 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
326 ON_CALL(*item, GetTransitionType())
327 .WillByDefault(Return(ui::PAGE_TRANSITION_LINK));
328 ON_CALL(*item, GetURL())
329 .WillByDefault(ReturnRefOfCopy(download_url));
330 ON_CALL(*item, GetUrlChain())
331 .WillByDefault(ReturnRefOfCopy(url_chain));
332 ON_CALL(*item, GetWebContents())
333 .WillByDefault(Return(web_contents()));
334 ON_CALL(*item, HasUserGesture())
335 .WillByDefault(Return(true));
336 ON_CALL(*item, IsDangerous())
337 .WillByDefault(Return(false));
338 ON_CALL(*item, IsTemporary())
339 .WillByDefault(Return(false));
340 return item;
343 void DownloadTargetDeterminerTest::EnableAutoOpenBasedOnExtension(
344 const base::FilePath& path) {
345 EXPECT_TRUE(download_prefs_->EnableAutoOpenBasedOnExtension(path));
348 void DownloadTargetDeterminerTest::SetManagedDownloadPath(
349 const base::FilePath& path) {
350 profile()->GetTestingPrefService()->
351 SetManagedPref(prefs::kDownloadDefaultDirectory,
352 base::CreateFilePathValue(path));
355 void DownloadTargetDeterminerTest::SetPromptForDownload(bool prompt) {
356 profile()->GetTestingPrefService()->
357 SetBoolean(prefs::kPromptForDownload, prompt);
360 base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir(
361 const base::FilePath::StringType& relative_path) {
362 if (relative_path.empty())
363 return base::FilePath();
364 base::FilePath full_path(test_download_dir().Append(relative_path));
365 return full_path.NormalizePathSeparators();
368 void DownloadTargetDeterminerTest::RunTestCase(
369 const DownloadTestCase& test_case,
370 const base::FilePath& initial_virtual_path,
371 content::MockDownloadItem* item) {
372 scoped_ptr<DownloadTargetInfo> target_info =
373 RunDownloadTargetDeterminer(initial_virtual_path, item);
374 VerifyDownloadTarget(test_case, target_info.get());
377 void CompletionCallbackWrapper(
378 const base::Closure& closure,
379 scoped_ptr<DownloadTargetInfo>* target_info_receiver,
380 scoped_ptr<DownloadTargetInfo> target_info) {
381 target_info_receiver->swap(target_info);
382 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure);
385 scoped_ptr<DownloadTargetInfo>
386 DownloadTargetDeterminerTest::RunDownloadTargetDeterminer(
387 const base::FilePath& initial_virtual_path,
388 content::MockDownloadItem* item) {
389 scoped_ptr<DownloadTargetInfo> target_info;
390 base::RunLoop run_loop;
391 DownloadTargetDeterminer::Start(
392 item, initial_virtual_path, download_prefs_.get(), delegate(),
393 base::Bind(&CompletionCallbackWrapper,
394 run_loop.QuitClosure(),
395 &target_info));
396 run_loop.Run();
397 ::testing::Mock::VerifyAndClearExpectations(delegate());
398 return target_info.Pass();
401 void DownloadTargetDeterminerTest::RunTestCasesWithActiveItem(
402 const DownloadTestCase test_cases[],
403 size_t test_case_count) {
404 for (size_t i = 0; i < test_case_count; ++i) {
405 scoped_ptr<content::MockDownloadItem> item(
406 CreateActiveDownloadItem(i, test_cases[i]));
407 SCOPED_TRACE(testing::Message() << "Running test case " << i);
408 RunTestCase(test_cases[i], base::FilePath(), item.get());
412 void DownloadTargetDeterminerTest::VerifyDownloadTarget(
413 const DownloadTestCase& test_case,
414 const DownloadTargetInfo* target_info) {
415 base::FilePath expected_local_path(
416 GetPathInDownloadDir(test_case.expected_local_path));
417 EXPECT_EQ(expected_local_path.value(), target_info->target_path.value());
418 EXPECT_EQ(test_case.expected_disposition, target_info->target_disposition);
419 EXPECT_EQ(test_case.expected_danger_type, target_info->danger_type);
421 switch (test_case.expected_intermediate) {
422 case EXPECT_CRDOWNLOAD:
423 EXPECT_EQ(DownloadTargetDeterminer::GetCrDownloadPath(
424 target_info->target_path).value(),
425 target_info->intermediate_path.value());
426 break;
428 case EXPECT_UNCONFIRMED:
429 // The paths (in English) look like: /path/Unconfirmed xxx.crdownload.
430 // Of this, we only check that the path is:
431 // 1. Not "/path/target.crdownload",
432 // 2. Points to the same directory as the target.
433 // 3. Has extension ".crdownload".
434 // 4. Basename starts with "Unconfirmed ".
435 EXPECT_NE(DownloadTargetDeterminer::GetCrDownloadPath(expected_local_path)
436 .value(),
437 target_info->intermediate_path.value());
438 EXPECT_EQ(expected_local_path.DirName().value(),
439 target_info->intermediate_path.DirName().value());
440 EXPECT_TRUE(target_info->intermediate_path.MatchesExtension(
441 FILE_PATH_LITERAL(".crdownload")));
442 EXPECT_EQ(0u,
443 target_info->intermediate_path.BaseName().value().find(
444 FILE_PATH_LITERAL("Unconfirmed ")));
445 break;
447 case EXPECT_LOCAL_PATH:
448 EXPECT_EQ(expected_local_path.value(),
449 target_info->intermediate_path.value());
450 break;
454 // static
455 void MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath(
456 DownloadItem* download,
457 const base::FilePath& virtual_path,
458 bool create_directory,
459 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
460 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
461 callback.Run(virtual_path, true);
464 // static
465 void MockDownloadTargetDeterminerDelegate::NullPromptUser(
466 DownloadItem* download, const base::FilePath& suggested_path,
467 const FileSelectedCallback& callback) {
468 callback.Run(suggested_path);
471 // static
472 void MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath(
473 DownloadItem* download, const base::FilePath& virtual_path,
474 const LocalPathCallback& callback) {
475 callback.Run(virtual_path);
478 // NotifyExtensions implementation that overrides the path so that the target
479 // file is in a subdirectory called 'overridden'. If the extension is '.remove',
480 // the extension is removed.
481 void NotifyExtensionsOverridePath(
482 content::DownloadItem* download,
483 const base::FilePath& path,
484 const DownloadTargetDeterminerDelegate::NotifyExtensionsCallback&
485 callback) {
486 base::FilePath new_path =
487 base::FilePath()
488 .AppendASCII("overridden")
489 .Append(path.BaseName());
490 if (new_path.MatchesExtension(FILE_PATH_LITERAL(".remove")))
491 new_path = new_path.RemoveExtension();
492 callback.Run(new_path, DownloadPathReservationTracker::UNIQUIFY);
495 void CheckDownloadUrlCheckExes(
496 content::DownloadItem* download,
497 const base::FilePath& path,
498 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback&
499 callback) {
500 if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
501 callback.Run(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT);
502 else
503 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
506 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_Basic) {
507 const DownloadTestCase kBasicTestCases[] = {
509 // 0: Automatic Safe
510 AUTOMATIC,
511 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
512 "http://example.com/foo.txt", "text/plain",
513 FILE_PATH_LITERAL(""),
515 FILE_PATH_LITERAL("foo.txt"),
516 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
518 EXPECT_CRDOWNLOAD
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(""),
528 FILE_PATH_LITERAL("foo.txt"),
529 DownloadItem::TARGET_DISPOSITION_PROMPT,
531 EXPECT_CRDOWNLOAD
535 // 2: Automatic Dangerous
536 AUTOMATIC,
537 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
538 "http://example.com/foo.crx", "",
539 FILE_PATH_LITERAL(""),
541 FILE_PATH_LITERAL("foo.crx"),
542 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
544 EXPECT_UNCONFIRMED
548 // 3: Forced Safe
549 FORCED,
550 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
551 "http://example.com/foo.txt", "",
552 FILE_PATH_LITERAL("forced-foo.txt"),
554 FILE_PATH_LITERAL("forced-foo.txt"),
555 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
557 EXPECT_LOCAL_PATH
561 // The test assumes that .crx files have a danger level of
562 // ALLOW_ON_USER_GESTURE.
563 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
564 download_util::GetFileDangerLevel(
565 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
566 RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
569 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_CancelSaveAs) {
570 const DownloadTestCase kCancelSaveAsTestCases[] = {
572 // 0: Save_As Safe, Cancelled.
573 SAVE_AS,
574 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
575 "http://example.com/foo.txt", "text/plain",
576 FILE_PATH_LITERAL(""),
578 FILE_PATH_LITERAL(""),
579 DownloadItem::TARGET_DISPOSITION_PROMPT,
581 EXPECT_LOCAL_PATH
584 ON_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
585 .WillByDefault(WithArg<2>(ScheduleCallback(base::FilePath())));
586 RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
587 arraysize(kCancelSaveAsTestCases));
590 // The SafeBrowsing check is performed early. Make sure that a download item
591 // that has been marked as DANGEROUS_URL behaves correctly.
592 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DangerousUrl) {
593 const DownloadTestCase kSafeBrowsingTestCases[] = {
595 // 0: Automatic Dangerous URL
596 AUTOMATIC,
597 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
598 "http://phishing.example.com/foo.txt", "",
599 FILE_PATH_LITERAL(""),
601 FILE_PATH_LITERAL("foo.txt"),
602 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
604 EXPECT_UNCONFIRMED
608 // 1: Save As Dangerous URL
609 SAVE_AS,
610 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
611 "http://phishing.example.com/foo.txt", "",
612 FILE_PATH_LITERAL(""),
614 FILE_PATH_LITERAL("foo.txt"),
615 DownloadItem::TARGET_DISPOSITION_PROMPT,
617 EXPECT_UNCONFIRMED
621 // 2: Forced Dangerous URL
622 FORCED,
623 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
624 "http://phishing.example.com/foo.txt", "",
625 FILE_PATH_LITERAL("forced-foo.txt"),
627 FILE_PATH_LITERAL("forced-foo.txt"),
628 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
630 EXPECT_UNCONFIRMED
634 // 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes
635 // precedence.
636 AUTOMATIC,
637 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
638 "http://phishing.example.com/foo.html", "",
639 FILE_PATH_LITERAL(""),
641 FILE_PATH_LITERAL("foo.html"),
642 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
644 EXPECT_UNCONFIRMED
648 // 4: Save As Dangerous URL + Dangerous file
649 SAVE_AS,
650 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
651 "http://phishing.example.com/foo.html", "",
652 FILE_PATH_LITERAL(""),
654 FILE_PATH_LITERAL("foo.html"),
655 DownloadItem::TARGET_DISPOSITION_PROMPT,
657 EXPECT_UNCONFIRMED
661 // 5: Forced Dangerous URL + Dangerous file
662 FORCED,
663 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
664 "http://phishing.example.com/foo.html", "",
665 FILE_PATH_LITERAL("forced-foo.html"),
667 FILE_PATH_LITERAL("forced-foo.html"),
668 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
670 EXPECT_UNCONFIRMED
674 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
675 .WillByDefault(WithArg<2>(ScheduleCallback(
676 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
677 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
678 arraysize(kSafeBrowsingTestCases));
681 // The SafeBrowsing check is performed early. Make sure that a download item
682 // that has been marked as MAYBE_DANGEROUS_CONTENT behaves correctly.
683 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_MaybeDangerousContent) {
684 const DownloadTestCase kSafeBrowsingTestCases[] = {
686 // 0: Automatic Maybe dangerous content
687 AUTOMATIC,
688 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
689 "http://phishing.example.com/foo.exe", "",
690 FILE_PATH_LITERAL(""),
692 FILE_PATH_LITERAL("foo.exe"),
693 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
695 EXPECT_UNCONFIRMED
699 // 1: Save As Maybe dangerous content
700 SAVE_AS,
701 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
702 "http://phishing.example.com/foo.exe", "",
703 FILE_PATH_LITERAL(""),
705 FILE_PATH_LITERAL("foo.exe"),
706 DownloadItem::TARGET_DISPOSITION_PROMPT,
708 EXPECT_UNCONFIRMED
712 // 2: Forced Maybe dangerous content
713 FORCED,
714 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
715 "http://phishing.example.com/foo.exe", "",
716 FILE_PATH_LITERAL("forced-foo.exe"),
718 FILE_PATH_LITERAL("forced-foo.exe"),
719 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
721 EXPECT_UNCONFIRMED
725 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
726 .WillByDefault(WithArg<2>(ScheduleCallback(
727 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
728 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
729 arraysize(kSafeBrowsingTestCases));
732 // Test whether the last saved directory is used for 'Save As' downloads.
733 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LastSavePath) {
734 const DownloadTestCase kLastSavePathTestCasesPre[] = {
736 // 0: If the last save path is empty, then the default download directory
737 // should be used.
738 SAVE_AS,
739 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
740 "http://example.com/foo.txt", "text/plain",
741 FILE_PATH_LITERAL(""),
743 FILE_PATH_LITERAL("foo.txt"),
744 DownloadItem::TARGET_DISPOSITION_PROMPT,
746 EXPECT_CRDOWNLOAD
750 // These test cases are run with a last save path set to a non-emtpy local
751 // download directory.
752 const DownloadTestCase kLastSavePathTestCasesPost[] = {
754 // 0: This test case is run with the last download directory set to
755 // '<test_download_dir()>/foo'.
756 SAVE_AS,
757 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
758 "http://example.com/foo.txt", "text/plain",
759 FILE_PATH_LITERAL(""),
761 FILE_PATH_LITERAL("foo/foo.txt"),
762 DownloadItem::TARGET_DISPOSITION_PROMPT,
764 EXPECT_CRDOWNLOAD
768 // 1: Start an automatic download. This should be saved to the user's
769 // default download directory and not the last used Save As directory.
770 AUTOMATIC,
771 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
772 "http://example.com/foo.txt", "text/plain",
773 FILE_PATH_LITERAL(""),
775 FILE_PATH_LITERAL("foo.txt"),
776 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
778 EXPECT_CRDOWNLOAD
782 // This test case is run with the last save path set to a non-empty virtual
783 // directory.
784 const DownloadTestCase kLastSavePathTestCasesVirtual[] = {
786 SAVE_AS,
787 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
788 "http://example.com/foo.txt", "text/plain",
789 FILE_PATH_LITERAL(""),
791 FILE_PATH_LITERAL("bar.txt"),
792 DownloadItem::TARGET_DISPOSITION_PROMPT,
794 EXPECT_LOCAL_PATH
799 SCOPED_TRACE(testing::Message()
800 << "Running with default download path");
801 base::FilePath prompt_path =
802 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
803 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
804 RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
805 arraysize(kLastSavePathTestCasesPre));
808 // Try with a non-empty last save path.
810 SCOPED_TRACE(testing::Message()
811 << "Running with local last_selected_directory");
812 download_prefs()->SetSaveFilePath(test_download_dir().AppendASCII("foo"));
813 base::FilePath prompt_path =
814 GetPathInDownloadDir(FILE_PATH_LITERAL("foo/foo.txt"));
815 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
816 RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
817 arraysize(kLastSavePathTestCasesPost));
820 // And again, but this time use a virtual directory.
822 SCOPED_TRACE(testing::Message()
823 << "Running with virtual last_selected_directory");
824 base::FilePath last_selected_dir = test_virtual_dir().AppendASCII("foo");
825 base::FilePath virtual_path = last_selected_dir.AppendASCII("foo.txt");
826 download_prefs()->SetSaveFilePath(last_selected_dir);
827 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
828 _, last_selected_dir.AppendASCII("foo.txt"), _));
829 EXPECT_CALL(*delegate(), DetermineLocalPath(_, virtual_path, _))
830 .WillOnce(WithArg<2>(ScheduleCallback(
831 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")))));
832 RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
833 arraysize(kLastSavePathTestCasesVirtual));
837 // These tests are run with the default downloads folder set to a virtual
838 // directory.
839 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DefaultVirtual) {
840 // The default download directory is the virutal path.
841 download_prefs()->SetDownloadPath(test_virtual_dir());
844 SCOPED_TRACE(testing::Message() << "Automatic Safe Download");
845 const DownloadTestCase kAutomaticDownloadToVirtualDir = {
846 AUTOMATIC,
847 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
848 "http://example.com/foo.txt", "text/plain",
849 FILE_PATH_LITERAL(""),
851 FILE_PATH_LITERAL("foo-local.txt"),
852 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
854 EXPECT_LOCAL_PATH
856 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
857 .WillOnce(WithArg<2>(ScheduleCallback(
858 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
859 RunTestCasesWithActiveItem(&kAutomaticDownloadToVirtualDir, 1);
863 SCOPED_TRACE(testing::Message() << "Save As to virtual directory");
864 const DownloadTestCase kSaveAsToVirtualDir = {
865 SAVE_AS,
866 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
867 "http://example.com/bar.txt", "text/plain",
868 FILE_PATH_LITERAL(""),
870 FILE_PATH_LITERAL("foo-local.txt"),
871 DownloadItem::TARGET_DISPOSITION_PROMPT,
873 EXPECT_LOCAL_PATH
875 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
876 .WillOnce(WithArg<2>(ScheduleCallback(
877 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
878 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
879 _, test_virtual_dir().AppendASCII("bar.txt"), _))
880 .WillOnce(WithArg<2>(ScheduleCallback(
881 test_virtual_dir().AppendASCII("prompted.txt"))));
882 RunTestCasesWithActiveItem(&kSaveAsToVirtualDir, 1);
886 SCOPED_TRACE(testing::Message() << "Save As to local directory");
887 const DownloadTestCase kSaveAsToLocalDir = {
888 SAVE_AS,
889 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
890 "http://example.com/bar.txt", "text/plain",
891 FILE_PATH_LITERAL(""),
893 FILE_PATH_LITERAL("foo-x.txt"),
894 DownloadItem::TARGET_DISPOSITION_PROMPT,
896 EXPECT_CRDOWNLOAD
898 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
899 _, test_virtual_dir().AppendASCII("bar.txt"), _))
900 .WillOnce(WithArg<2>(ScheduleCallback(
901 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")))));
902 RunTestCasesWithActiveItem(&kSaveAsToLocalDir, 1);
906 SCOPED_TRACE(testing::Message() << "Forced safe download");
907 const DownloadTestCase kForcedSafe = {
908 FORCED,
909 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
910 "http://example.com/foo.txt", "",
911 FILE_PATH_LITERAL("forced-foo.txt"),
913 FILE_PATH_LITERAL("forced-foo.txt"),
914 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
916 EXPECT_LOCAL_PATH
918 RunTestCasesWithActiveItem(&kForcedSafe, 1);
922 // Test that an inactive download will still get a virtual or local download
923 // path.
924 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_InactiveDownload) {
925 const DownloadTestCase kInactiveTestCases[] = {
927 AUTOMATIC,
928 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
929 "http://example.com/foo.txt", "text/plain",
930 FILE_PATH_LITERAL(""),
932 FILE_PATH_LITERAL(""),
933 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
935 EXPECT_LOCAL_PATH
939 SAVE_AS,
940 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
941 "http://example.com/foo.txt", "text/plain",
942 FILE_PATH_LITERAL(""),
944 FILE_PATH_LITERAL(""),
945 DownloadItem::TARGET_DISPOSITION_PROMPT,
947 EXPECT_LOCAL_PATH
951 for (size_t i = 0; i < arraysize(kInactiveTestCases); ++i) {
952 SCOPED_TRACE(testing::Message() << "Running test case " << i);
953 const DownloadTestCase& test_case = kInactiveTestCases[i];
954 scoped_ptr<content::MockDownloadItem> item(
955 CreateActiveDownloadItem(i, test_case));
956 EXPECT_CALL(*item.get(), GetState())
957 .WillRepeatedly(Return(content::DownloadItem::CANCELLED));
958 // Even though one is a SAVE_AS download, no prompt will be displayed to
959 // the user because the download is inactive.
960 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
961 .Times(0);
962 RunTestCase(test_case, base::FilePath(), item.get());
966 // If the reserved path could not be verified, then the user should see a
967 // prompt.
968 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ReservationFailed) {
969 const DownloadTestCase kReservationFailedCases[] = {
971 // 0: Automatic download. Since the reservation fails, the disposition of
972 // the target is to prompt, but the returned path is used.
973 AUTOMATIC,
974 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
975 "http://example.com/foo.txt", "text/plain",
976 FILE_PATH_LITERAL(""),
978 FILE_PATH_LITERAL("bar.txt"),
979 DownloadItem::TARGET_DISPOSITION_PROMPT,
981 EXPECT_CRDOWNLOAD
985 // Setup ReserveVirtualPath() to fail.
986 ON_CALL(*delegate(), ReserveVirtualPath(_, _, _, _, _))
987 .WillByDefault(WithArg<4>(ScheduleCallback2(
988 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")), false)));
989 RunTestCasesWithActiveItem(kReservationFailedCases,
990 arraysize(kReservationFailedCases));
993 // If the local path could not be determined, the download should be cancelled.
994 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LocalPathFailed) {
995 const DownloadTestCase kLocalPathFailedCases[] = {
997 // 0: Automatic download.
998 AUTOMATIC,
999 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1000 "http://example.com/foo.txt", "text/plain",
1001 FILE_PATH_LITERAL(""),
1003 FILE_PATH_LITERAL(""),
1004 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1006 EXPECT_LOCAL_PATH
1010 // The default download directory is the virtual path.
1011 download_prefs()->SetDownloadPath(test_virtual_dir());
1012 // Simulate failed call to DetermineLocalPath.
1013 EXPECT_CALL(*delegate(), DetermineLocalPath(
1014 _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
1015 .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
1016 RunTestCasesWithActiveItem(kLocalPathFailedCases,
1017 arraysize(kLocalPathFailedCases));
1020 // Downloads that have a danger level of ALLOW_ON_USER_GESTURE should be marked
1021 // as safe depending on whether there was a user gesture associated with the
1022 // download and whether the referrer was visited prior to today.
1023 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_VisitedReferrer) {
1024 const DownloadTestCase kVisitedReferrerCases[] = {
1025 // http://visited.example.com/ is added to the history as a visit that
1026 // happened prior to today.
1028 // 0: Safe download due to visiting referrer before.
1029 AUTOMATIC,
1030 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1031 "http://visited.example.com/foo.crx", "application/xml",
1032 FILE_PATH_LITERAL(""),
1034 FILE_PATH_LITERAL("foo.crx"),
1035 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1037 EXPECT_CRDOWNLOAD
1041 // 1: Dangerous due to not having visited referrer before.
1042 AUTOMATIC,
1043 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1044 "http://not-visited.example.com/foo.crx", "application/xml",
1045 FILE_PATH_LITERAL(""),
1047 FILE_PATH_LITERAL("foo.crx"),
1048 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1050 EXPECT_UNCONFIRMED
1054 // 2: Safe because the user is being prompted.
1055 SAVE_AS,
1056 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1057 "http://not-visited.example.com/foo.crx", "application/xml",
1058 FILE_PATH_LITERAL(""),
1060 FILE_PATH_LITERAL("foo.crx"),
1061 DownloadItem::TARGET_DISPOSITION_PROMPT,
1063 EXPECT_CRDOWNLOAD
1067 // 3: Safe because of forced path.
1068 FORCED,
1069 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1070 "http://not-visited.example.com/foo.crx", "application/xml",
1071 FILE_PATH_LITERAL("foo.crx"),
1073 FILE_PATH_LITERAL("foo.crx"),
1074 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1076 EXPECT_LOCAL_PATH
1080 // This test assumes that the danger level of .crx files is
1081 // ALLOW_ON_USER_GESTURE.
1082 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1083 download_util::GetFileDangerLevel(
1084 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1086 // First the history service must exist.
1087 ASSERT_TRUE(profile()->CreateHistoryService(false, false));
1089 GURL url("http://visited.example.com/visited-link.html");
1090 // The time of visit is picked to be several seconds prior to the most recent
1091 // midnight.
1092 base::Time time_of_visit(
1093 base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(10));
1094 history::HistoryService* history_service =
1095 HistoryServiceFactory::GetForProfile(profile(),
1096 ServiceAccessType::EXPLICIT_ACCESS);
1097 ASSERT_TRUE(history_service);
1098 history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
1100 RunTestCasesWithActiveItem(kVisitedReferrerCases,
1101 arraysize(kVisitedReferrerCases));
1104 // These test cases are run with "Prompt for download" user preference set to
1105 // true.
1106 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways) {
1107 const DownloadTestCase kPromptingTestCases[] = {
1109 // 0: Safe Automatic - Should prompt because of "Prompt for download"
1110 // preference setting.
1111 AUTOMATIC,
1112 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1113 "http://example.com/foo.txt", "text/plain",
1114 FILE_PATH_LITERAL(""),
1116 FILE_PATH_LITERAL("foo.txt"),
1117 DownloadItem::TARGET_DISPOSITION_PROMPT,
1119 EXPECT_CRDOWNLOAD
1123 // 1: Safe Forced - Shouldn't prompt.
1124 FORCED,
1125 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1126 "http://example.com/foo.txt", "text/plain",
1127 FILE_PATH_LITERAL("foo.txt"),
1129 FILE_PATH_LITERAL("foo.txt"),
1130 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1132 EXPECT_LOCAL_PATH
1136 // 2: Automatic - The filename extension is marked as one that we will
1137 // open automatically. Shouldn't prompt.
1138 AUTOMATIC,
1139 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1140 "http://example.com/foo.dummy", "",
1141 FILE_PATH_LITERAL(""),
1143 FILE_PATH_LITERAL("foo.dummy"),
1144 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1146 EXPECT_CRDOWNLOAD
1150 SetPromptForDownload(true);
1151 EnableAutoOpenBasedOnExtension(
1152 base::FilePath(FILE_PATH_LITERAL("dummy.dummy")));
1153 RunTestCasesWithActiveItem(kPromptingTestCases,
1154 arraysize(kPromptingTestCases));
1157 #if defined(ENABLE_EXTENSIONS)
1158 // These test cases are run with "Prompt for download" user preference set to
1159 // true. Automatic extension downloads shouldn't cause prompting.
1160 // Android doesn't support extensions.
1161 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways_Extension) {
1162 const DownloadTestCase kPromptingTestCases[] = {
1164 // 0: Automatic Browser Extension download. - Shouldn't prompt for browser
1165 // extension downloads even if "Prompt for download" preference is set.
1166 AUTOMATIC,
1167 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1168 "http://example.com/foo.crx",
1169 extensions::Extension::kMimeType,
1170 FILE_PATH_LITERAL(""),
1172 FILE_PATH_LITERAL("foo.crx"),
1173 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1175 EXPECT_UNCONFIRMED
1178 #if defined(OS_WIN)
1180 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1181 // even if "Prompt for download" preference is set. ".js" files are
1182 // considered dangerous on Windows.
1183 AUTOMATIC,
1184 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1185 "http://example.com/foo.user.js", "",
1186 FILE_PATH_LITERAL(""),
1188 FILE_PATH_LITERAL("foo.user.js"),
1189 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1191 EXPECT_UNCONFIRMED
1193 #else
1195 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1196 // even if "Prompt for download" preference is set.
1197 AUTOMATIC,
1198 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1199 "http://example.com/foo.user.js", "",
1200 FILE_PATH_LITERAL(""),
1202 FILE_PATH_LITERAL("foo.user.js"),
1203 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1205 EXPECT_CRDOWNLOAD
1207 #endif
1210 SetPromptForDownload(true);
1211 RunTestCasesWithActiveItem(kPromptingTestCases,
1212 arraysize(kPromptingTestCases));
1214 #endif // defined(ENABLE_EXTENSIONS)
1216 // If the download path is managed, then we don't show any prompts.
1217 // Note that if the download path is managed, then PromptForDownload() is false.
1218 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ManagedPath) {
1219 const DownloadTestCase kManagedPathTestCases[] = {
1221 // 0: Automatic Safe
1222 AUTOMATIC,
1223 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1224 "http://example.com/foo.txt", "text/plain",
1225 FILE_PATH_LITERAL(""),
1227 FILE_PATH_LITERAL("foo.txt"),
1228 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1230 EXPECT_CRDOWNLOAD
1234 // 1: Save_As Safe
1235 SAVE_AS,
1236 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1237 "http://example.com/foo.txt", "text/plain",
1238 FILE_PATH_LITERAL(""),
1240 FILE_PATH_LITERAL("foo.txt"),
1241 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1243 EXPECT_CRDOWNLOAD
1247 SetManagedDownloadPath(test_download_dir());
1248 ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
1249 RunTestCasesWithActiveItem(kManagedPathTestCases,
1250 arraysize(kManagedPathTestCases));
1253 // Test basic functionality supporting extensions that want to override download
1254 // filenames.
1255 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsSafe) {
1256 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1258 // 0: Automatic Safe
1259 AUTOMATIC,
1260 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1261 "http://example.com/foo.txt", "text/plain",
1262 FILE_PATH_LITERAL(""),
1264 FILE_PATH_LITERAL("overridden/foo.txt"),
1265 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1267 EXPECT_CRDOWNLOAD
1271 // 1: Save_As Safe
1272 SAVE_AS,
1273 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1274 "http://example.com/foo.txt", "text/plain",
1275 FILE_PATH_LITERAL(""),
1277 FILE_PATH_LITERAL("overridden/foo.txt"),
1278 DownloadItem::TARGET_DISPOSITION_PROMPT,
1280 EXPECT_CRDOWNLOAD
1284 // 2: Automatic Dangerous
1285 AUTOMATIC,
1286 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1287 "http://example.com/foo.crx", "",
1288 FILE_PATH_LITERAL(""),
1290 FILE_PATH_LITERAL("overridden/foo.crx"),
1291 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1293 EXPECT_UNCONFIRMED
1297 // 3: Forced Safe
1298 FORCED,
1299 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1300 "http://example.com/foo.txt", "",
1301 FILE_PATH_LITERAL("forced-foo.txt"),
1303 FILE_PATH_LITERAL("forced-foo.txt"),
1304 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1306 EXPECT_LOCAL_PATH
1310 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1311 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1312 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1313 arraysize(kNotifyExtensionsTestCases));
1316 // Test that filenames provided by extensions are passed into SafeBrowsing
1317 // checks and dangerous download checks.
1318 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsUnsafe) {
1319 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1321 // 0: Automatic Safe : Later overridden by a dangerous filetype.
1322 AUTOMATIC,
1323 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1324 "http://example.com/foo.crx.remove", "text/plain",
1325 FILE_PATH_LITERAL(""),
1327 FILE_PATH_LITERAL("overridden/foo.crx"),
1328 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1330 EXPECT_UNCONFIRMED
1334 // 1: Automatic Safe : Later overridden by a potentially dangerous
1335 // filetype.
1336 AUTOMATIC,
1337 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
1338 "http://example.com/foo.exe.remove", "text/plain",
1339 FILE_PATH_LITERAL(""),
1341 FILE_PATH_LITERAL("overridden/foo.exe"),
1342 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1344 EXPECT_UNCONFIRMED
1348 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1349 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1350 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
1351 .WillByDefault(Invoke(&CheckDownloadUrlCheckExes));
1352 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1353 arraysize(kNotifyExtensionsTestCases));
1356 // Test that conflict actions set by extensions are passed correctly into
1357 // ReserveVirtualPath.
1358 TEST_F(DownloadTargetDeterminerTest,
1359 TargetDeterminer_NotifyExtensionsConflict) {
1360 const DownloadTestCase kNotifyExtensionsTestCase = {
1361 AUTOMATIC,
1362 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1363 "http://example.com/foo.txt", "text/plain",
1364 FILE_PATH_LITERAL(""),
1366 FILE_PATH_LITERAL("overridden/foo.txt"),
1367 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1369 EXPECT_CRDOWNLOAD
1372 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1373 scoped_ptr<content::MockDownloadItem> item(
1374 CreateActiveDownloadItem(0, test_case));
1375 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1376 base::FilePath full_overridden_path =
1377 GetPathInDownloadDir(overridden_path.value());
1379 // First case: An extension sets the conflict_action to OVERWRITE.
1380 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1381 .WillOnce(WithArg<2>(
1382 ScheduleCallback2(overridden_path,
1383 DownloadPathReservationTracker::OVERWRITE)));
1384 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1385 _, full_overridden_path, true, DownloadPathReservationTracker::OVERWRITE,
1386 _)).WillOnce(WithArg<4>(
1387 ScheduleCallback2(full_overridden_path, true)));
1389 RunTestCase(test_case, base::FilePath(), item.get());
1391 // Second case: An extension sets the conflict_action to PROMPT.
1392 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1393 .WillOnce(WithArg<2>(
1394 ScheduleCallback2(overridden_path,
1395 DownloadPathReservationTracker::PROMPT)));
1396 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1397 _, full_overridden_path, true, DownloadPathReservationTracker::PROMPT, _))
1398 .WillOnce(WithArg<4>(
1399 ScheduleCallback2(full_overridden_path, true)));
1400 RunTestCase(test_case, base::FilePath(), item.get());
1403 // Test that relative paths returned by extensions are always relative to the
1404 // default downloads path.
1405 TEST_F(DownloadTargetDeterminerTest,
1406 TargetDeterminer_NotifyExtensionsDefaultPath) {
1407 const DownloadTestCase kNotifyExtensionsTestCase = {
1408 SAVE_AS,
1409 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1410 "http://example.com/foo.txt", "text/plain",
1411 FILE_PATH_LITERAL(""),
1413 FILE_PATH_LITERAL("overridden/foo.txt"),
1414 DownloadItem::TARGET_DISPOSITION_PROMPT,
1416 EXPECT_CRDOWNLOAD
1419 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1420 scoped_ptr<content::MockDownloadItem> item(
1421 CreateActiveDownloadItem(0, test_case));
1422 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1423 base::FilePath full_overridden_path =
1424 GetPathInDownloadDir(overridden_path.value());
1426 download_prefs()->SetSaveFilePath(GetPathInDownloadDir(
1427 FILE_PATH_LITERAL("last_selected")));
1429 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1430 .WillOnce(WithArg<2>(
1431 ScheduleCallback2(overridden_path,
1432 DownloadPathReservationTracker::UNIQUIFY)));
1433 EXPECT_CALL(*delegate(),
1434 PromptUserForDownloadPath(_, full_overridden_path, _))
1435 .WillOnce(WithArg<2>(
1436 ScheduleCallback(full_overridden_path)));
1437 RunTestCase(test_case, base::FilePath(), item.get());
1440 TEST_F(DownloadTargetDeterminerTest,
1441 TargetDeterminer_InitialVirtualPathUnsafe) {
1442 const base::FilePath::CharType* kInitialPath =
1443 FILE_PATH_LITERAL("some_path/bar.html");
1445 const DownloadTestCase kInitialPathTestCase = {
1446 // 0: Save As Save. The path generated based on the DownloadItem is safe,
1447 // but the initial path is unsafe. However, the download is not considered
1448 // dangerous since the user has been prompted.
1449 SAVE_AS,
1450 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1451 "http://example.com/foo.txt", "text/plain",
1452 FILE_PATH_LITERAL(""),
1454 kInitialPath,
1455 DownloadItem::TARGET_DISPOSITION_PROMPT,
1457 EXPECT_CRDOWNLOAD
1460 const DownloadTestCase& test_case = kInitialPathTestCase;
1461 scoped_ptr<content::MockDownloadItem> item(
1462 CreateActiveDownloadItem(1, test_case));
1463 EXPECT_CALL(*item, GetLastReason())
1464 .WillRepeatedly(Return(
1465 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1466 EXPECT_CALL(*item, GetTargetDisposition())
1467 .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
1468 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1471 // Prompting behavior for resumed downloads is based on the last interrupt
1472 // reason. If the reason indicates that the target path may not be suitable for
1473 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1474 // prompted, and not otherwise. These test cases shouldn't result in prompting
1475 // since the error is set to NETWORK_FAILED.
1476 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedNoPrompt) {
1477 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1478 // path.
1479 const base::FilePath::CharType* kInitialPath =
1480 FILE_PATH_LITERAL("some_path/bar.txt");
1482 const DownloadTestCase kResumedTestCases[] = {
1484 // 0: Automatic Safe: Initial path is ignored since the user has not been
1485 // prompted before.
1486 AUTOMATIC,
1487 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1488 "http://example.com/foo.txt", "text/plain",
1489 FILE_PATH_LITERAL(""),
1491 FILE_PATH_LITERAL("foo.txt"),
1492 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1494 EXPECT_CRDOWNLOAD
1498 // 1: Save_As Safe: Initial path used.
1499 SAVE_AS,
1500 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1501 "http://example.com/foo.txt", "text/plain",
1502 FILE_PATH_LITERAL(""),
1504 kInitialPath,
1505 DownloadItem::TARGET_DISPOSITION_PROMPT,
1507 EXPECT_CRDOWNLOAD
1511 // 2: Automatic Dangerous: Initial path is ignored since the user hasn't
1512 // been prompted before.
1513 AUTOMATIC,
1514 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1515 "http://example.com/foo.crx", "",
1516 FILE_PATH_LITERAL(""),
1518 FILE_PATH_LITERAL("foo.crx"),
1519 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1521 EXPECT_UNCONFIRMED
1525 // 3: Forced Safe: Initial path is ignored due to the forced path.
1526 FORCED,
1527 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1528 "http://example.com/foo.txt", "",
1529 FILE_PATH_LITERAL("forced-foo.txt"),
1531 FILE_PATH_LITERAL("forced-foo.txt"),
1532 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1534 EXPECT_LOCAL_PATH
1538 // The test assumes that .crx files have a danger level of
1539 // ALLOW_ON_USER_GESTURE.
1540 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1541 download_util::GetFileDangerLevel(
1542 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1543 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1544 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1545 const DownloadTestCase& test_case = kResumedTestCases[i];
1546 scoped_ptr<content::MockDownloadItem> item(
1547 CreateActiveDownloadItem(i, test_case));
1548 base::FilePath expected_path =
1549 GetPathInDownloadDir(test_case.expected_local_path);
1550 ON_CALL(*item.get(), GetLastReason())
1551 .WillByDefault(Return(
1552 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1553 // Extensions should be notified if a new path is being generated and there
1554 // is no forced path. In the test cases above, this is true for tests with
1555 // type == AUTOMATIC.
1556 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1557 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1558 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1559 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _))
1560 .Times(0);
1561 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1562 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1563 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1567 // Test that a forced download doesn't prompt, even if the interrupt reason
1568 // suggests that the target path may not be suitable for downloads.
1569 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedForcedDownload) {
1570 const base::FilePath::CharType* kInitialPath =
1571 FILE_PATH_LITERAL("some_path/bar.txt");
1572 const DownloadTestCase kResumedForcedDownload = {
1573 // 3: Forced Safe
1574 FORCED,
1575 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1576 "http://example.com/foo.txt", "",
1577 FILE_PATH_LITERAL("forced-foo.txt"),
1579 FILE_PATH_LITERAL("forced-foo.txt"),
1580 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1582 EXPECT_LOCAL_PATH
1585 const DownloadTestCase& test_case = kResumedForcedDownload;
1586 base::FilePath expected_path =
1587 GetPathInDownloadDir(test_case.expected_local_path);
1588 scoped_ptr<content::MockDownloadItem> item(
1589 CreateActiveDownloadItem(0, test_case));
1590 ON_CALL(*item.get(), GetLastReason())
1591 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1592 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1593 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1594 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1595 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
1596 .Times(0);
1597 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1598 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1599 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1602 // Prompting behavior for resumed downloads is based on the last interrupt
1603 // reason. If the reason indicates that the target path may not be suitable for
1604 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1605 // prompted, and not otherwise. These test cases result in prompting since the
1606 // error is set to NO_SPACE.
1607 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedWithPrompt) {
1608 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1609 // path.
1610 const base::FilePath::CharType* kInitialPath =
1611 FILE_PATH_LITERAL("some_path/bar.txt");
1613 const DownloadTestCase kResumedTestCases[] = {
1615 // 0: Automatic Safe
1616 AUTOMATIC,
1617 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1618 "http://example.com/foo.txt", "text/plain",
1619 FILE_PATH_LITERAL(""),
1621 FILE_PATH_LITERAL("foo.txt"),
1622 DownloadItem::TARGET_DISPOSITION_PROMPT,
1624 EXPECT_CRDOWNLOAD
1628 // 1: Save_As Safe
1629 SAVE_AS,
1630 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1631 "http://example.com/foo.txt", "text/plain",
1632 FILE_PATH_LITERAL(""),
1634 kInitialPath,
1635 DownloadItem::TARGET_DISPOSITION_PROMPT,
1637 EXPECT_CRDOWNLOAD
1641 // 2: Automatic Dangerous
1642 AUTOMATIC,
1643 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1644 "http://example.com/foo.crx", "",
1645 FILE_PATH_LITERAL(""),
1647 FILE_PATH_LITERAL("foo.crx"),
1648 DownloadItem::TARGET_DISPOSITION_PROMPT,
1650 EXPECT_CRDOWNLOAD
1654 // The test assumes that .xml files have a danger level of
1655 // ALLOW_ON_USER_GESTURE.
1656 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1657 download_util::GetFileDangerLevel(
1658 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1659 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1660 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1661 download_prefs()->SetSaveFilePath(test_download_dir());
1662 const DownloadTestCase& test_case = kResumedTestCases[i];
1663 base::FilePath expected_path =
1664 GetPathInDownloadDir(test_case.expected_local_path);
1665 scoped_ptr<content::MockDownloadItem> item(
1666 CreateActiveDownloadItem(i, test_case));
1667 ON_CALL(*item.get(), GetLastReason())
1668 .WillByDefault(Return(
1669 content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1670 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1671 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1672 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1673 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _));
1674 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1675 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1676 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1680 // Test intermediate filename generation for resumed downloads.
1681 TEST_F(DownloadTargetDeterminerTest,
1682 TargetDeterminer_IntermediateNameForResumed) {
1683 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1684 // path.
1685 const base::FilePath::CharType kInitialPath[] =
1686 FILE_PATH_LITERAL("some_path/bar.txt");
1688 struct IntermediateNameTestCase {
1689 // General test case settings.
1690 DownloadTestCase general;
1692 // Value of DownloadItem::GetFullPath() during test run, relative
1693 // to test download path.
1694 const base::FilePath::CharType* initial_intermediate_path;
1696 // Expected intermediate path relatvie to the test download path. An exact
1697 // match is performed if this string is non-empty. Ignored otherwise.
1698 const base::FilePath::CharType* expected_intermediate_path;
1699 } kIntermediateNameTestCases[] = {
1702 // 0: Automatic Safe
1703 AUTOMATIC,
1704 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1705 "http://example.com/foo.txt", "text/plain",
1706 FILE_PATH_LITERAL(""),
1708 FILE_PATH_LITERAL("foo.txt"),
1709 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1711 EXPECT_CRDOWNLOAD
1713 FILE_PATH_LITERAL("bar.txt.crdownload"),
1714 FILE_PATH_LITERAL("foo.txt.crdownload")
1719 // 1: Save_As Safe
1720 SAVE_AS,
1721 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1722 "http://example.com/foo.txt", "text/plain",
1723 FILE_PATH_LITERAL(""),
1725 kInitialPath,
1726 DownloadItem::TARGET_DISPOSITION_PROMPT,
1728 EXPECT_CRDOWNLOAD
1730 FILE_PATH_LITERAL("foo.txt.crdownload"),
1731 FILE_PATH_LITERAL("some_path/bar.txt.crdownload")
1736 // 2: Automatic Dangerous
1737 AUTOMATIC,
1738 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1739 "http://example.com/foo.crx", "",
1740 FILE_PATH_LITERAL(""),
1742 FILE_PATH_LITERAL("foo.crx"),
1743 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1745 EXPECT_UNCONFIRMED
1747 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload"),
1748 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload")
1753 // 3: Automatic Dangerous
1754 AUTOMATIC,
1755 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1756 "http://example.com/foo.crx", "",
1757 FILE_PATH_LITERAL(""),
1759 FILE_PATH_LITERAL("foo.crx"),
1760 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1762 EXPECT_UNCONFIRMED
1764 FILE_PATH_LITERAL("other_path/Unconfirmed abcd.crdownload"),
1765 // Rely on the EXPECT_UNCONFIRMED check in the general test settings. A
1766 // new intermediate path of the form "Unconfirmed <number>.crdownload"
1767 // should be generated for this case since the initial intermediate path
1768 // is in the wrong directory.
1769 FILE_PATH_LITERAL("")
1774 // 3: Forced Safe: Initial path is ignored due to the forced path.
1775 FORCED,
1776 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1777 "http://example.com/foo.txt", "",
1778 FILE_PATH_LITERAL("forced-foo.txt"),
1780 FILE_PATH_LITERAL("forced-foo.txt"),
1781 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1783 EXPECT_LOCAL_PATH
1785 FILE_PATH_LITERAL("forced-foo.txt"),
1786 FILE_PATH_LITERAL("forced-foo.txt")
1790 // The test assumes that .crx files have a danger level of
1791 // ALLOW_ON_USER_GESTURE.
1792 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1793 download_util::GetFileDangerLevel(
1794 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1796 for (size_t i = 0; i < arraysize(kIntermediateNameTestCases); ++i) {
1797 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1798 const IntermediateNameTestCase& test_case = kIntermediateNameTestCases[i];
1799 scoped_ptr<content::MockDownloadItem> item(
1800 CreateActiveDownloadItem(i, test_case.general));
1802 ON_CALL(*item.get(), GetLastReason())
1803 .WillByDefault(Return(
1804 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1805 ON_CALL(*item.get(), GetFullPath())
1806 .WillByDefault(ReturnRefOfCopy(
1807 GetPathInDownloadDir(test_case.initial_intermediate_path)));
1808 ON_CALL(*item.get(), GetDangerType())
1809 .WillByDefault(Return(test_case.general.expected_danger_type));
1811 scoped_ptr<DownloadTargetInfo> target_info =
1812 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1813 item.get());
1814 VerifyDownloadTarget(test_case.general, target_info.get());
1815 base::FilePath expected_intermediate_path =
1816 GetPathInDownloadDir(test_case.expected_intermediate_path);
1817 if (!expected_intermediate_path.empty())
1818 EXPECT_EQ(expected_intermediate_path, target_info->intermediate_path);
1822 // Test MIME type determination based on the target filename.
1823 TEST_F(DownloadTargetDeterminerTest,
1824 TargetDeterminer_MIMETypeDetermination) {
1825 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1826 // path.
1827 const base::FilePath::CharType kInitialPath[] =
1828 FILE_PATH_LITERAL("some_path/bar.txt");
1830 struct MIMETypeTestCase {
1831 // General test case settings.
1832 DownloadTestCase general;
1834 // Expected MIME type for test case.
1835 const char* expected_mime_type;
1836 } kMIMETypeTestCases[] = {
1839 // 0:
1840 AUTOMATIC,
1841 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1842 "http://example.com/foo.png", "image/png",
1843 FILE_PATH_LITERAL(""),
1845 FILE_PATH_LITERAL("foo.png"),
1846 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1848 EXPECT_CRDOWNLOAD
1850 "image/png"
1854 // 1: Empty MIME type in response.
1855 AUTOMATIC,
1856 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1857 "http://example.com/foo.png", "",
1858 FILE_PATH_LITERAL(""),
1860 FILE_PATH_LITERAL("foo.png"),
1861 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1863 EXPECT_CRDOWNLOAD
1865 "image/png"
1869 // 2: Forced path.
1870 FORCED,
1871 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1872 "http://example.com/foo.abc", "",
1873 FILE_PATH_LITERAL("foo.png"),
1875 FILE_PATH_LITERAL("foo.png"),
1876 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1878 EXPECT_CRDOWNLOAD
1880 "image/png"
1884 // 3: Unknown file type.
1885 AUTOMATIC,
1886 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1887 "http://example.com/foo.notarealext", "",
1888 FILE_PATH_LITERAL(""),
1890 FILE_PATH_LITERAL("foo.notarealext"),
1891 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1893 EXPECT_CRDOWNLOAD
1899 // 4: Unknown file type.
1900 AUTOMATIC,
1901 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1902 "http://example.com/foo.notarealext", "image/png",
1903 FILE_PATH_LITERAL(""),
1905 FILE_PATH_LITERAL("foo.notarealext"),
1906 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1908 EXPECT_CRDOWNLOAD
1914 ON_CALL(*delegate(), GetFileMimeType(
1915 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.png")), _))
1916 .WillByDefault(WithArg<1>(
1917 ScheduleCallback("image/png")));
1919 for (size_t i = 0; i < arraysize(kMIMETypeTestCases); ++i) {
1920 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1921 const MIMETypeTestCase& test_case = kMIMETypeTestCases[i];
1922 scoped_ptr<content::MockDownloadItem> item(
1923 CreateActiveDownloadItem(i, test_case.general));
1924 scoped_ptr<DownloadTargetInfo> target_info =
1925 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1926 item.get());
1927 EXPECT_EQ(test_case.expected_mime_type, target_info->mime_type);
1931 #if defined(ENABLE_PLUGINS)
1933 void DummyGetPluginsCallback(
1934 const base::Closure& closure,
1935 const std::vector<content::WebPluginInfo>& plugins) {
1936 closure.Run();
1939 void ForceRefreshOfPlugins() {
1940 #if !defined(OS_WIN)
1941 // Prevent creation of a utility process for loading plugins. Doing so breaks
1942 // unit_tests since /proc/self/exe can't be run as a utility process.
1943 content::RenderProcessHost::SetRunRendererInProcess(true);
1944 #endif
1945 base::RunLoop run_loop;
1946 content::PluginService::GetInstance()->GetPlugins(
1947 base::Bind(&DummyGetPluginsCallback, run_loop.QuitClosure()));
1948 run_loop.Run();
1949 #if !defined(OS_WIN)
1950 content::RenderProcessHost::SetRunRendererInProcess(false);
1951 #endif
1954 class MockPluginServiceFilter : public content::PluginServiceFilter {
1955 public:
1956 MOCK_METHOD1(MockPluginAvailable, bool(const base::FilePath&));
1958 bool IsPluginAvailable(int render_process_id,
1959 int render_view_id,
1960 const void* context,
1961 const GURL& url,
1962 const GURL& policy_url,
1963 content::WebPluginInfo* plugin) override {
1964 return MockPluginAvailable(plugin->path);
1967 bool CanLoadPlugin(int render_process_id,
1968 const base::FilePath& path) override {
1969 return true;
1973 class ScopedRegisterInternalPlugin {
1974 public:
1975 ScopedRegisterInternalPlugin(content::PluginService* plugin_service,
1976 content::WebPluginInfo::PluginType type,
1977 const base::FilePath& path,
1978 const char* mime_type,
1979 const char* extension)
1980 : plugin_service_(plugin_service),
1981 plugin_path_(path) {
1982 content::WebPluginMimeType plugin_mime_type(mime_type,
1983 extension,
1984 "Test file");
1985 content::WebPluginInfo plugin_info(base::string16(),
1986 path,
1987 base::string16(),
1988 base::string16());
1989 plugin_info.mime_types.push_back(plugin_mime_type);
1990 plugin_info.type = type;
1992 plugin_service->RegisterInternalPlugin(plugin_info, true);
1993 plugin_service->RefreshPlugins();
1994 ForceRefreshOfPlugins();
1997 ~ScopedRegisterInternalPlugin() {
1998 plugin_service_->UnregisterInternalPlugin(plugin_path_);
1999 plugin_service_->RefreshPlugins();
2000 ForceRefreshOfPlugins();
2003 const base::FilePath& path() { return plugin_path_; }
2005 private:
2006 content::PluginService* plugin_service_;
2007 base::FilePath plugin_path_;
2010 // We use a slightly different test fixture for tests that touch plugins. SetUp
2011 // needs to disable plugin discovery and we need to use a
2012 // ShadowingAtExitManager to discard the tainted PluginService. Unfortunately,
2013 // PluginService carries global state.
2014 class DownloadTargetDeterminerTestWithPlugin
2015 : public DownloadTargetDeterminerTest {
2016 public:
2017 DownloadTargetDeterminerTestWithPlugin()
2018 : old_plugin_service_filter_(NULL) {}
2020 void SetUp() override {
2021 DownloadTargetDeterminerTest::SetUp();
2022 content::PluginService* plugin_service =
2023 content::PluginService::GetInstance();
2024 plugin_service->Init();
2025 plugin_service->DisablePluginsDiscoveryForTesting();
2026 old_plugin_service_filter_ = plugin_service->GetFilter();
2027 plugin_service->SetFilter(&mock_plugin_filter_);
2030 void TearDown() override {
2031 content::PluginService::GetInstance()->SetFilter(
2032 old_plugin_service_filter_);
2033 DownloadTargetDeterminerTest::TearDown();
2036 protected:
2037 content::PluginServiceFilter* old_plugin_service_filter_;
2038 testing::StrictMock<MockPluginServiceFilter> mock_plugin_filter_;
2039 // The ShadowingAtExitManager destroys the tainted PluginService instance.
2040 base::ShadowingAtExitManager at_exit_manager_;
2043 // Check if secure handling of filetypes is determined correctly for PPAPI
2044 // plugins.
2045 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2046 TargetDeterminer_CheckForSecureHandling_PPAPI) {
2047 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2048 // path.
2049 const base::FilePath::CharType kInitialPath[] =
2050 FILE_PATH_LITERAL("some_path/bar.txt");
2051 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2053 DownloadTestCase kSecureHandlingTestCase = {
2054 AUTOMATIC,
2055 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2056 "http://example.com/foo.fakeext", "",
2057 FILE_PATH_LITERAL(""),
2059 FILE_PATH_LITERAL("foo.fakeext"),
2060 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2062 EXPECT_CRDOWNLOAD
2065 content::PluginService* plugin_service =
2066 content::PluginService::GetInstance();
2068 // Verify our test assumptions.
2070 ForceRefreshOfPlugins();
2071 std::vector<content::WebPluginInfo> info;
2072 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2073 GURL(), kTestMIMEType, false, &info, NULL));
2074 ASSERT_EQ(0u, info.size())
2075 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2078 ON_CALL(*delegate(), GetFileMimeType(
2079 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2080 .WillByDefault(WithArg<1>(
2081 ScheduleCallback(kTestMIMEType)));
2082 scoped_ptr<content::MockDownloadItem> item(
2083 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2084 scoped_ptr<DownloadTargetInfo> target_info =
2085 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2086 item.get());
2087 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2089 // Register a PPAPI plugin. This should count as handling the filetype
2090 // securely.
2091 ScopedRegisterInternalPlugin ppapi_plugin(
2092 plugin_service,
2093 content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS,
2094 test_download_dir().AppendASCII("ppapi"),
2095 kTestMIMEType,
2096 "fakeext");
2097 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(ppapi_plugin.path()))
2098 .WillRepeatedly(Return(true));
2100 target_info = RunDownloadTargetDeterminer(
2101 GetPathInDownloadDir(kInitialPath), item.get());
2102 EXPECT_TRUE(target_info->is_filetype_handled_safely);
2104 // Try disabling the plugin. Handling should no longer be considered secure.
2105 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(ppapi_plugin.path()))
2106 .WillRepeatedly(Return(false));
2107 target_info = RunDownloadTargetDeterminer(
2108 GetPathInDownloadDir(kInitialPath), item.get());
2109 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2112 // Check if secure handling of filetypes is determined correctly for
2113 // BrowserPlugins.
2114 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2115 TargetDeterminer_CheckForSecureHandling_BrowserPlugin) {
2116 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2117 // path.
2118 const base::FilePath::CharType kInitialPath[] =
2119 FILE_PATH_LITERAL("some_path/bar.txt");
2120 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2122 DownloadTestCase kSecureHandlingTestCase = {
2123 AUTOMATIC,
2124 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2125 "http://example.com/foo.fakeext", "",
2126 FILE_PATH_LITERAL(""),
2128 FILE_PATH_LITERAL("foo.fakeext"),
2129 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2131 EXPECT_CRDOWNLOAD
2134 content::PluginService* plugin_service =
2135 content::PluginService::GetInstance();
2137 // Verify our test assumptions.
2139 ForceRefreshOfPlugins();
2140 std::vector<content::WebPluginInfo> info;
2141 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2142 GURL(), kTestMIMEType, false, &info, NULL));
2143 ASSERT_EQ(0u, info.size())
2144 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2147 ON_CALL(*delegate(), GetFileMimeType(
2148 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2149 .WillByDefault(WithArg<1>(
2150 ScheduleCallback(kTestMIMEType)));
2151 scoped_ptr<content::MockDownloadItem> item(
2152 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2153 scoped_ptr<DownloadTargetInfo> target_info =
2154 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2155 item.get());
2156 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2158 // Register a BrowserPlugin. This should count as handling the filetype
2159 // securely.
2160 ScopedRegisterInternalPlugin browser_plugin(
2161 plugin_service,
2162 content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN,
2163 test_download_dir().AppendASCII("browser_plugin"),
2164 kTestMIMEType,
2165 "fakeext");
2166 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(browser_plugin.path()))
2167 .WillRepeatedly(Return(true));
2169 target_info = RunDownloadTargetDeterminer(
2170 GetPathInDownloadDir(kInitialPath), item.get());
2171 EXPECT_TRUE(target_info->is_filetype_handled_safely);
2173 // Try disabling the plugin. Handling should no longer be considered secure.
2174 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(browser_plugin.path()))
2175 .WillRepeatedly(Return(false));
2176 target_info = RunDownloadTargetDeterminer(
2177 GetPathInDownloadDir(kInitialPath), item.get());
2178 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2181 // Check if secure handling of filetypes is determined correctly for NPAPI
2182 // plugins.
2183 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2184 TargetDeterminer_CheckForSecureHandling_NPAPI) {
2185 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2186 // path.
2187 const base::FilePath::CharType kInitialPath[] =
2188 FILE_PATH_LITERAL("some_path/bar.txt");
2189 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2191 DownloadTestCase kSecureHandlingTestCase = {
2192 AUTOMATIC,
2193 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2194 "http://example.com/foo.fakeext", "",
2195 FILE_PATH_LITERAL(""),
2197 FILE_PATH_LITERAL("foo.fakeext"),
2198 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2200 EXPECT_CRDOWNLOAD
2203 content::PluginService* plugin_service =
2204 content::PluginService::GetInstance();
2206 // Can't run this test if NPAPI isn't supported.
2207 if (!plugin_service->NPAPIPluginsSupported())
2208 return;
2210 // Verify our test assumptions.
2212 ForceRefreshOfPlugins();
2213 std::vector<content::WebPluginInfo> info;
2214 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2215 GURL(), kTestMIMEType, false, &info, NULL));
2216 ASSERT_EQ(0u, info.size())
2217 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2220 ON_CALL(*delegate(), GetFileMimeType(
2221 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2222 .WillByDefault(WithArg<1>(
2223 ScheduleCallback(kTestMIMEType)));
2224 scoped_ptr<content::MockDownloadItem> item(
2225 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2226 scoped_ptr<DownloadTargetInfo> target_info =
2227 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2228 item.get());
2229 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2231 // Register a NPAPI plugin. This should not count as handling the filetype
2232 // securely.
2233 ScopedRegisterInternalPlugin npapi_plugin(
2234 plugin_service,
2235 content::WebPluginInfo::PLUGIN_TYPE_NPAPI,
2236 test_download_dir().AppendASCII("npapi"),
2237 kTestMIMEType,
2238 "fakeext");
2239 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(npapi_plugin.path()))
2240 .WillRepeatedly(Return(true));
2242 target_info = RunDownloadTargetDeterminer(
2243 GetPathInDownloadDir(kInitialPath), item.get());
2244 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2246 #endif // defined(ENABLE_PLUGINS)
2248 } // namespace