Give names to all utility processes.
[chromium-blink-merge.git] / chrome / browser / download / download_target_determiner_unittest.cc
blob0418af8a10e9d8795d40daebc57dfa36c6b6409a
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_factory.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
23 #include "chrome/test/base/testing_pref_service_syncable.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "components/history/core/browser/history_service.h"
26 #include "components/history/core/browser/history_types.h"
27 #include "content/public/browser/download_interrupt_reasons.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/browser/web_contents_delegate.h"
31 #include "content/public/test/mock_download_item.h"
32 #include "content/public/test/test_renderer_host.h"
33 #include "content/public/test/web_contents_tester.h"
34 #include "net/base/mime_util.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "testing/gtest/include/gtest/gtest.h"
38 #if defined(ENABLE_PLUGINS)
39 #include "content/public/browser/plugin_service.h"
40 #include "content/public/browser/plugin_service_filter.h"
41 #include "content/public/common/webplugininfo.h"
42 #endif
44 #if defined(ENABLE_EXTENSIONS)
45 #include "extensions/common/extension.h"
46 #endif
48 using ::testing::AnyNumber;
49 using ::testing::Invoke;
50 using ::testing::Ref;
51 using ::testing::Return;
52 using ::testing::ReturnRef;
53 using ::testing::ReturnRefOfCopy;
54 using ::testing::Truly;
55 using ::testing::WithArg;
56 using ::testing::_;
57 using content::DownloadItem;
59 namespace {
61 // No-op delegate.
62 class NullWebContentsDelegate : public content::WebContentsDelegate {
63 public:
64 NullWebContentsDelegate() {}
65 ~NullWebContentsDelegate() override {}
68 // Google Mock action that posts a task to the current message loop that invokes
69 // the first argument of the mocked method as a callback. Said argument must be
70 // a base::Callback<void(ParamType)>. |result| must be of |ParamType| and is
71 // bound as that parameter.
72 // Example:
73 // class FooClass {
74 // public:
75 // virtual void Foo(base::Callback<void(bool)> callback);
76 // };
77 // ...
78 // EXPECT_CALL(mock_fooclass_instance, Foo(callback))
79 // .WillOnce(ScheduleCallback(false));
80 ACTION_P(ScheduleCallback, result0) {
81 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, result0));
84 // Similar to ScheduleCallback, but binds 2 arguments.
85 ACTION_P2(ScheduleCallback2, result0, result1) {
86 base::MessageLoop::current()->PostTask(
87 FROM_HERE, base::Bind(arg0, result0, result1));
90 // Used with DownloadTestCase. Indicates the type of test case. The expectations
91 // for the test is set based on the type.
92 enum TestCaseType {
93 SAVE_AS,
94 AUTOMATIC,
95 FORCED // Requires that forced_file_path be non-empty.
98 // Used with DownloadTestCase. Type of intermediate filename to expect.
99 enum TestCaseExpectIntermediate {
100 EXPECT_CRDOWNLOAD, // Expect path/to/target.crdownload.
101 EXPECT_UNCONFIRMED, // Expect path/to/Unconfirmed xxx.crdownload.
102 EXPECT_LOCAL_PATH, // Expect target path.
105 // Typical download test case. Used with
106 // DownloadTargetDeterminerTest::RunTestCase().
107 struct DownloadTestCase {
108 // Type of test.
109 TestCaseType test_type;
111 // Expected danger type. Verified at the end of target determination.
112 content::DownloadDangerType expected_danger_type;
114 // Value of DownloadItem::GetURL()
115 const char* url;
117 // Value of DownloadItem::GetMimeType()
118 const char* mime_type;
120 // Should be non-empty if |test_type| == FORCED. Value of GetForcedFilePath().
121 const base::FilePath::CharType* forced_file_path;
123 // Expected local path. Specified relative to the test download path.
124 const base::FilePath::CharType* expected_local_path;
126 // Expected target disposition. If this is TARGET_DISPOSITION_PROMPT, then the
127 // test run will expect ChromeDownloadManagerDelegate to prompt the user for a
128 // download location.
129 DownloadItem::TargetDisposition expected_disposition;
131 // Type of intermediate path to expect.
132 TestCaseExpectIntermediate expected_intermediate;
135 class MockDownloadTargetDeterminerDelegate
136 : public DownloadTargetDeterminerDelegate {
137 public:
138 MOCK_METHOD3(CheckDownloadUrl,
139 void(content::DownloadItem*, const base::FilePath&,
140 const CheckDownloadUrlCallback&));
141 MOCK_METHOD3(NotifyExtensions,
142 void(content::DownloadItem*, const base::FilePath&,
143 const NotifyExtensionsCallback&));
144 MOCK_METHOD3(PromptUserForDownloadPath,
145 void(content::DownloadItem*, const base::FilePath&,
146 const FileSelectedCallback&));
147 MOCK_METHOD3(DetermineLocalPath,
148 void(DownloadItem*, const base::FilePath&,
149 const LocalPathCallback&));
150 MOCK_METHOD5(ReserveVirtualPath,
151 void(DownloadItem*, const base::FilePath&, bool,
152 DownloadPathReservationTracker::FilenameConflictAction,
153 const ReservedPathCallback&));
154 MOCK_METHOD2(GetFileMimeType,
155 void(const base::FilePath&,
156 const GetFileMimeTypeCallback&));
158 void SetupDefaults() {
159 ON_CALL(*this, CheckDownloadUrl(_, _, _))
160 .WillByDefault(WithArg<2>(
161 ScheduleCallback(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)));
162 ON_CALL(*this, NotifyExtensions(_, _, _))
163 .WillByDefault(WithArg<2>(
164 ScheduleCallback2(base::FilePath(),
165 DownloadPathReservationTracker::UNIQUIFY)));
166 ON_CALL(*this, ReserveVirtualPath(_, _, _, _, _))
167 .WillByDefault(Invoke(
168 &MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath));
169 ON_CALL(*this, PromptUserForDownloadPath(_, _, _))
170 .WillByDefault(Invoke(
171 &MockDownloadTargetDeterminerDelegate::NullPromptUser));
172 ON_CALL(*this, DetermineLocalPath(_, _, _))
173 .WillByDefault(Invoke(
174 &MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath));
175 ON_CALL(*this, GetFileMimeType(_, _))
176 .WillByDefault(WithArg<1>(
177 ScheduleCallback("")));
179 private:
180 static void NullReserveVirtualPath(
181 DownloadItem* download,
182 const base::FilePath& virtual_path,
183 bool create_directory,
184 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
185 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback);
186 static void NullPromptUser(
187 DownloadItem* download, const base::FilePath& suggested_path,
188 const FileSelectedCallback& callback);
189 static void NullDetermineLocalPath(
190 DownloadItem* download, const base::FilePath& virtual_path,
191 const LocalPathCallback& callback);
194 class DownloadTargetDeterminerTest : public ChromeRenderViewHostTestHarness {
195 public:
196 // ::testing::Test
197 virtual void SetUp() override;
198 virtual void TearDown() override;
200 // Creates MockDownloadItem and sets up default expectations.
201 content::MockDownloadItem* CreateActiveDownloadItem(
202 int32 id,
203 const DownloadTestCase& test_case);
205 // Sets the AutoOpenBasedOnExtension user preference for |path|.
206 void EnableAutoOpenBasedOnExtension(const base::FilePath& path);
208 // Set the kDownloadDefaultDirectory managed preference to |path|.
209 void SetManagedDownloadPath(const base::FilePath& path);
211 // Set the kPromptForDownload user preference to |prompt|.
212 void SetPromptForDownload(bool prompt);
214 // Given the relative path |path|, returns the full path under the temporary
215 // downloads directory.
216 base::FilePath GetPathInDownloadDir(const base::FilePath::StringType& path);
218 // Run |test_case| using |item|.
219 void RunTestCase(const DownloadTestCase& test_case,
220 const base::FilePath& initial_virtual_path,
221 content::MockDownloadItem* item);
223 // Runs |test_case| with |item|. When the DownloadTargetDeterminer is done,
224 // returns the resulting DownloadTargetInfo.
225 scoped_ptr<DownloadTargetInfo> RunDownloadTargetDeterminer(
226 const base::FilePath& initial_virtual_path,
227 content::MockDownloadItem* item);
229 // Run through |test_case_count| tests in |test_cases|. A new MockDownloadItem
230 // will be created for each test case and destroyed when the test case is
231 // complete.
232 void RunTestCasesWithActiveItem(const DownloadTestCase test_cases[],
233 size_t test_case_count);
235 // Verifies that |target_path|, |disposition|, |expected_danger_type| and
236 // |intermediate_path| matches the expectations of |test_case|. Posts
237 // |closure| to the current message loop when done.
238 void VerifyDownloadTarget(const DownloadTestCase& test_case,
239 const DownloadTargetInfo* target_info);
241 const base::FilePath& test_download_dir() const {
242 return test_download_dir_.path();
245 const base::FilePath& test_virtual_dir() const {
246 return test_virtual_dir_;
249 MockDownloadTargetDeterminerDelegate* delegate() {
250 return &delegate_;
253 DownloadPrefs* download_prefs() {
254 return download_prefs_.get();
257 private:
258 scoped_ptr<DownloadPrefs> download_prefs_;
259 ::testing::NiceMock<MockDownloadTargetDeterminerDelegate> delegate_;
260 NullWebContentsDelegate web_contents_delegate_;
261 base::ScopedTempDir test_download_dir_;
262 base::FilePath test_virtual_dir_;
265 void DownloadTargetDeterminerTest::SetUp() {
266 ChromeRenderViewHostTestHarness::SetUp();
267 CHECK(profile());
268 download_prefs_.reset(new DownloadPrefs(profile()));
269 web_contents()->SetDelegate(&web_contents_delegate_);
270 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
271 test_virtual_dir_ = test_download_dir().Append(FILE_PATH_LITERAL("virtual"));
272 download_prefs_->SetDownloadPath(test_download_dir());
273 delegate_.SetupDefaults();
276 void DownloadTargetDeterminerTest::TearDown() {
277 download_prefs_.reset();
278 ChromeRenderViewHostTestHarness::TearDown();
281 content::MockDownloadItem*
282 DownloadTargetDeterminerTest::CreateActiveDownloadItem(
283 int32 id,
284 const DownloadTestCase& test_case) {
285 content::MockDownloadItem* item =
286 new ::testing::NiceMock<content::MockDownloadItem>();
287 GURL download_url(test_case.url);
288 std::vector<GURL> url_chain;
289 url_chain.push_back(download_url);
290 base::FilePath forced_file_path =
291 GetPathInDownloadDir(test_case.forced_file_path);
292 DownloadItem::TargetDisposition initial_disposition =
293 (test_case.test_type == SAVE_AS) ?
294 DownloadItem::TARGET_DISPOSITION_PROMPT :
295 DownloadItem::TARGET_DISPOSITION_OVERWRITE;
296 EXPECT_EQ(test_case.test_type == FORCED,
297 !forced_file_path.empty());
299 ON_CALL(*item, GetBrowserContext())
300 .WillByDefault(Return(profile()));
301 ON_CALL(*item, GetDangerType())
302 .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
303 ON_CALL(*item, GetForcedFilePath())
304 .WillByDefault(ReturnRefOfCopy(forced_file_path));
305 ON_CALL(*item, GetFullPath())
306 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
307 ON_CALL(*item, GetHash())
308 .WillByDefault(ReturnRefOfCopy(std::string()));
309 ON_CALL(*item, GetId())
310 .WillByDefault(Return(id));
311 ON_CALL(*item, GetLastReason())
312 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE));
313 ON_CALL(*item, GetMimeType())
314 .WillByDefault(Return(test_case.mime_type));
315 ON_CALL(*item, GetReferrerUrl())
316 .WillByDefault(ReturnRefOfCopy(download_url));
317 ON_CALL(*item, GetState())
318 .WillByDefault(Return(DownloadItem::IN_PROGRESS));
319 ON_CALL(*item, GetTargetDisposition())
320 .WillByDefault(Return(initial_disposition));
321 ON_CALL(*item, GetTargetFilePath())
322 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
323 ON_CALL(*item, GetTransitionType())
324 .WillByDefault(Return(ui::PAGE_TRANSITION_LINK));
325 ON_CALL(*item, GetURL())
326 .WillByDefault(ReturnRefOfCopy(download_url));
327 ON_CALL(*item, GetUrlChain())
328 .WillByDefault(ReturnRefOfCopy(url_chain));
329 ON_CALL(*item, GetWebContents())
330 .WillByDefault(Return(web_contents()));
331 ON_CALL(*item, HasUserGesture())
332 .WillByDefault(Return(true));
333 ON_CALL(*item, IsDangerous())
334 .WillByDefault(Return(false));
335 ON_CALL(*item, IsTemporary())
336 .WillByDefault(Return(false));
337 return item;
340 void DownloadTargetDeterminerTest::EnableAutoOpenBasedOnExtension(
341 const base::FilePath& path) {
342 EXPECT_TRUE(download_prefs_->EnableAutoOpenBasedOnExtension(path));
345 void DownloadTargetDeterminerTest::SetManagedDownloadPath(
346 const base::FilePath& path) {
347 profile()->GetTestingPrefService()->
348 SetManagedPref(prefs::kDownloadDefaultDirectory,
349 base::CreateFilePathValue(path));
352 void DownloadTargetDeterminerTest::SetPromptForDownload(bool prompt) {
353 profile()->GetTestingPrefService()->
354 SetBoolean(prefs::kPromptForDownload, prompt);
357 base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir(
358 const base::FilePath::StringType& relative_path) {
359 if (relative_path.empty())
360 return base::FilePath();
361 base::FilePath full_path(test_download_dir().Append(relative_path));
362 return full_path.NormalizePathSeparators();
365 void DownloadTargetDeterminerTest::RunTestCase(
366 const DownloadTestCase& test_case,
367 const base::FilePath& initial_virtual_path,
368 content::MockDownloadItem* item) {
369 scoped_ptr<DownloadTargetInfo> target_info =
370 RunDownloadTargetDeterminer(initial_virtual_path, item);
371 VerifyDownloadTarget(test_case, target_info.get());
374 void CompletionCallbackWrapper(
375 const base::Closure& closure,
376 scoped_ptr<DownloadTargetInfo>* target_info_receiver,
377 scoped_ptr<DownloadTargetInfo> target_info) {
378 target_info_receiver->swap(target_info);
379 base::MessageLoop::current()->PostTask(FROM_HERE, closure);
382 scoped_ptr<DownloadTargetInfo>
383 DownloadTargetDeterminerTest::RunDownloadTargetDeterminer(
384 const base::FilePath& initial_virtual_path,
385 content::MockDownloadItem* item) {
386 scoped_ptr<DownloadTargetInfo> target_info;
387 base::RunLoop run_loop;
388 DownloadTargetDeterminer::Start(
389 item, initial_virtual_path, download_prefs_.get(), delegate(),
390 base::Bind(&CompletionCallbackWrapper,
391 run_loop.QuitClosure(),
392 &target_info));
393 run_loop.Run();
394 ::testing::Mock::VerifyAndClearExpectations(delegate());
395 return target_info.Pass();
398 void DownloadTargetDeterminerTest::RunTestCasesWithActiveItem(
399 const DownloadTestCase test_cases[],
400 size_t test_case_count) {
401 for (size_t i = 0; i < test_case_count; ++i) {
402 scoped_ptr<content::MockDownloadItem> item(
403 CreateActiveDownloadItem(i, test_cases[i]));
404 SCOPED_TRACE(testing::Message() << "Running test case " << i);
405 RunTestCase(test_cases[i], base::FilePath(), item.get());
409 void DownloadTargetDeterminerTest::VerifyDownloadTarget(
410 const DownloadTestCase& test_case,
411 const DownloadTargetInfo* target_info) {
412 base::FilePath expected_local_path(
413 GetPathInDownloadDir(test_case.expected_local_path));
414 EXPECT_EQ(expected_local_path.value(), target_info->target_path.value());
415 EXPECT_EQ(test_case.expected_disposition, target_info->target_disposition);
416 EXPECT_EQ(test_case.expected_danger_type, target_info->danger_type);
418 switch (test_case.expected_intermediate) {
419 case EXPECT_CRDOWNLOAD:
420 EXPECT_EQ(DownloadTargetDeterminer::GetCrDownloadPath(
421 target_info->target_path).value(),
422 target_info->intermediate_path.value());
423 break;
425 case EXPECT_UNCONFIRMED:
426 // The paths (in English) look like: /path/Unconfirmed xxx.crdownload.
427 // Of this, we only check that the path is:
428 // 1. Not "/path/target.crdownload",
429 // 2. Points to the same directory as the target.
430 // 3. Has extension ".crdownload".
431 // 4. Basename starts with "Unconfirmed ".
432 EXPECT_NE(DownloadTargetDeterminer::GetCrDownloadPath(expected_local_path)
433 .value(),
434 target_info->intermediate_path.value());
435 EXPECT_EQ(expected_local_path.DirName().value(),
436 target_info->intermediate_path.DirName().value());
437 EXPECT_TRUE(target_info->intermediate_path.MatchesExtension(
438 FILE_PATH_LITERAL(".crdownload")));
439 EXPECT_EQ(0u,
440 target_info->intermediate_path.BaseName().value().find(
441 FILE_PATH_LITERAL("Unconfirmed ")));
442 break;
444 case EXPECT_LOCAL_PATH:
445 EXPECT_EQ(expected_local_path.value(),
446 target_info->intermediate_path.value());
447 break;
451 // static
452 void MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath(
453 DownloadItem* download,
454 const base::FilePath& virtual_path,
455 bool create_directory,
456 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
457 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
458 callback.Run(virtual_path, true);
461 // static
462 void MockDownloadTargetDeterminerDelegate::NullPromptUser(
463 DownloadItem* download, const base::FilePath& suggested_path,
464 const FileSelectedCallback& callback) {
465 callback.Run(suggested_path);
468 // static
469 void MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath(
470 DownloadItem* download, const base::FilePath& virtual_path,
471 const LocalPathCallback& callback) {
472 callback.Run(virtual_path);
475 // NotifyExtensions implementation that overrides the path so that the target
476 // file is in a subdirectory called 'overridden'. If the extension is '.remove',
477 // the extension is removed.
478 void NotifyExtensionsOverridePath(
479 content::DownloadItem* download,
480 const base::FilePath& path,
481 const DownloadTargetDeterminerDelegate::NotifyExtensionsCallback&
482 callback) {
483 base::FilePath new_path =
484 base::FilePath()
485 .AppendASCII("overridden")
486 .Append(path.BaseName());
487 if (new_path.MatchesExtension(FILE_PATH_LITERAL(".remove")))
488 new_path = new_path.RemoveExtension();
489 callback.Run(new_path, DownloadPathReservationTracker::UNIQUIFY);
492 void CheckDownloadUrlCheckExes(
493 content::DownloadItem* download,
494 const base::FilePath& path,
495 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback&
496 callback) {
497 if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
498 callback.Run(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT);
499 else
500 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
503 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_Basic) {
504 const DownloadTestCase kBasicTestCases[] = {
506 // 0: Automatic Safe
507 AUTOMATIC,
508 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
509 "http://example.com/foo.txt", "text/plain",
510 FILE_PATH_LITERAL(""),
512 FILE_PATH_LITERAL("foo.txt"),
513 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
515 EXPECT_CRDOWNLOAD
519 // 1: Save_As Safe
520 SAVE_AS,
521 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
522 "http://example.com/foo.txt", "text/plain",
523 FILE_PATH_LITERAL(""),
525 FILE_PATH_LITERAL("foo.txt"),
526 DownloadItem::TARGET_DISPOSITION_PROMPT,
528 EXPECT_CRDOWNLOAD
532 // 2: Automatic Dangerous
533 AUTOMATIC,
534 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
535 "http://example.com/foo.crx", "",
536 FILE_PATH_LITERAL(""),
538 FILE_PATH_LITERAL("foo.crx"),
539 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
541 EXPECT_UNCONFIRMED
545 // 3: Forced Safe
546 FORCED,
547 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
548 "http://example.com/foo.txt", "",
549 FILE_PATH_LITERAL("forced-foo.txt"),
551 FILE_PATH_LITERAL("forced-foo.txt"),
552 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
554 EXPECT_LOCAL_PATH
558 // The test assumes that .crx files have a danger level of
559 // ALLOW_ON_USER_GESTURE.
560 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
561 download_util::GetFileDangerLevel(
562 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
563 RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
566 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_CancelSaveAs) {
567 const DownloadTestCase kCancelSaveAsTestCases[] = {
569 // 0: Save_As Safe, Cancelled.
570 SAVE_AS,
571 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
572 "http://example.com/foo.txt", "text/plain",
573 FILE_PATH_LITERAL(""),
575 FILE_PATH_LITERAL(""),
576 DownloadItem::TARGET_DISPOSITION_PROMPT,
578 EXPECT_LOCAL_PATH
581 ON_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
582 .WillByDefault(WithArg<2>(ScheduleCallback(base::FilePath())));
583 RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
584 arraysize(kCancelSaveAsTestCases));
587 // The SafeBrowsing check is performed early. Make sure that a download item
588 // that has been marked as DANGEROUS_URL behaves correctly.
589 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DangerousUrl) {
590 const DownloadTestCase kSafeBrowsingTestCases[] = {
592 // 0: Automatic Dangerous URL
593 AUTOMATIC,
594 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
595 "http://phishing.example.com/foo.txt", "",
596 FILE_PATH_LITERAL(""),
598 FILE_PATH_LITERAL("foo.txt"),
599 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
601 EXPECT_UNCONFIRMED
605 // 1: Save As Dangerous URL
606 SAVE_AS,
607 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
608 "http://phishing.example.com/foo.txt", "",
609 FILE_PATH_LITERAL(""),
611 FILE_PATH_LITERAL("foo.txt"),
612 DownloadItem::TARGET_DISPOSITION_PROMPT,
614 EXPECT_UNCONFIRMED
618 // 2: Forced Dangerous URL
619 FORCED,
620 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
621 "http://phishing.example.com/foo.txt", "",
622 FILE_PATH_LITERAL("forced-foo.txt"),
624 FILE_PATH_LITERAL("forced-foo.txt"),
625 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
627 EXPECT_UNCONFIRMED
631 // 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes
632 // precedence.
633 AUTOMATIC,
634 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
635 "http://phishing.example.com/foo.html", "",
636 FILE_PATH_LITERAL(""),
638 FILE_PATH_LITERAL("foo.html"),
639 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
641 EXPECT_UNCONFIRMED
645 // 4: Save As Dangerous URL + Dangerous file
646 SAVE_AS,
647 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
648 "http://phishing.example.com/foo.html", "",
649 FILE_PATH_LITERAL(""),
651 FILE_PATH_LITERAL("foo.html"),
652 DownloadItem::TARGET_DISPOSITION_PROMPT,
654 EXPECT_UNCONFIRMED
658 // 5: Forced Dangerous URL + Dangerous file
659 FORCED,
660 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
661 "http://phishing.example.com/foo.html", "",
662 FILE_PATH_LITERAL("forced-foo.html"),
664 FILE_PATH_LITERAL("forced-foo.html"),
665 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
667 EXPECT_UNCONFIRMED
671 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
672 .WillByDefault(WithArg<2>(ScheduleCallback(
673 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
674 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
675 arraysize(kSafeBrowsingTestCases));
678 // The SafeBrowsing check is performed early. Make sure that a download item
679 // that has been marked as MAYBE_DANGEROUS_CONTENT behaves correctly.
680 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_MaybeDangerousContent) {
681 const DownloadTestCase kSafeBrowsingTestCases[] = {
683 // 0: Automatic Maybe dangerous content
684 AUTOMATIC,
685 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
686 "http://phishing.example.com/foo.exe", "",
687 FILE_PATH_LITERAL(""),
689 FILE_PATH_LITERAL("foo.exe"),
690 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
692 EXPECT_UNCONFIRMED
696 // 1: Save As Maybe dangerous content
697 SAVE_AS,
698 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
699 "http://phishing.example.com/foo.exe", "",
700 FILE_PATH_LITERAL(""),
702 FILE_PATH_LITERAL("foo.exe"),
703 DownloadItem::TARGET_DISPOSITION_PROMPT,
705 EXPECT_UNCONFIRMED
709 // 2: Forced Maybe dangerous content
710 FORCED,
711 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
712 "http://phishing.example.com/foo.exe", "",
713 FILE_PATH_LITERAL("forced-foo.exe"),
715 FILE_PATH_LITERAL("forced-foo.exe"),
716 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
718 EXPECT_UNCONFIRMED
722 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
723 .WillByDefault(WithArg<2>(ScheduleCallback(
724 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
725 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
726 arraysize(kSafeBrowsingTestCases));
729 // Test whether the last saved directory is used for 'Save As' downloads.
730 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LastSavePath) {
731 const DownloadTestCase kLastSavePathTestCasesPre[] = {
733 // 0: If the last save path is empty, then the default download directory
734 // should be used.
735 SAVE_AS,
736 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
737 "http://example.com/foo.txt", "text/plain",
738 FILE_PATH_LITERAL(""),
740 FILE_PATH_LITERAL("foo.txt"),
741 DownloadItem::TARGET_DISPOSITION_PROMPT,
743 EXPECT_CRDOWNLOAD
747 // These test cases are run with a last save path set to a non-emtpy local
748 // download directory.
749 const DownloadTestCase kLastSavePathTestCasesPost[] = {
751 // 0: This test case is run with the last download directory set to
752 // '<test_download_dir()>/foo'.
753 SAVE_AS,
754 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
755 "http://example.com/foo.txt", "text/plain",
756 FILE_PATH_LITERAL(""),
758 FILE_PATH_LITERAL("foo/foo.txt"),
759 DownloadItem::TARGET_DISPOSITION_PROMPT,
761 EXPECT_CRDOWNLOAD
765 // 1: Start an automatic download. This should be saved to the user's
766 // default download directory and not the last used Save As directory.
767 AUTOMATIC,
768 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
769 "http://example.com/foo.txt", "text/plain",
770 FILE_PATH_LITERAL(""),
772 FILE_PATH_LITERAL("foo.txt"),
773 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
775 EXPECT_CRDOWNLOAD
779 // This test case is run with the last save path set to a non-empty virtual
780 // directory.
781 const DownloadTestCase kLastSavePathTestCasesVirtual[] = {
783 SAVE_AS,
784 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
785 "http://example.com/foo.txt", "text/plain",
786 FILE_PATH_LITERAL(""),
788 FILE_PATH_LITERAL("bar.txt"),
789 DownloadItem::TARGET_DISPOSITION_PROMPT,
791 EXPECT_LOCAL_PATH
796 SCOPED_TRACE(testing::Message()
797 << "Running with default download path");
798 base::FilePath prompt_path =
799 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
800 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
801 RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
802 arraysize(kLastSavePathTestCasesPre));
805 // Try with a non-empty last save path.
807 SCOPED_TRACE(testing::Message()
808 << "Running with local last_selected_directory");
809 download_prefs()->SetSaveFilePath(test_download_dir().AppendASCII("foo"));
810 base::FilePath prompt_path =
811 GetPathInDownloadDir(FILE_PATH_LITERAL("foo/foo.txt"));
812 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
813 RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
814 arraysize(kLastSavePathTestCasesPost));
817 // And again, but this time use a virtual directory.
819 SCOPED_TRACE(testing::Message()
820 << "Running with virtual last_selected_directory");
821 base::FilePath last_selected_dir = test_virtual_dir().AppendASCII("foo");
822 base::FilePath virtual_path = last_selected_dir.AppendASCII("foo.txt");
823 download_prefs()->SetSaveFilePath(last_selected_dir);
824 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
825 _, last_selected_dir.AppendASCII("foo.txt"), _));
826 EXPECT_CALL(*delegate(), DetermineLocalPath(_, virtual_path, _))
827 .WillOnce(WithArg<2>(ScheduleCallback(
828 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")))));
829 RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
830 arraysize(kLastSavePathTestCasesVirtual));
834 // These tests are run with the default downloads folder set to a virtual
835 // directory.
836 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DefaultVirtual) {
837 // The default download directory is the virutal path.
838 download_prefs()->SetDownloadPath(test_virtual_dir());
841 SCOPED_TRACE(testing::Message() << "Automatic Safe Download");
842 const DownloadTestCase kAutomaticDownloadToVirtualDir = {
843 AUTOMATIC,
844 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
845 "http://example.com/foo.txt", "text/plain",
846 FILE_PATH_LITERAL(""),
848 FILE_PATH_LITERAL("foo-local.txt"),
849 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
851 EXPECT_LOCAL_PATH
853 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
854 .WillOnce(WithArg<2>(ScheduleCallback(
855 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
856 RunTestCasesWithActiveItem(&kAutomaticDownloadToVirtualDir, 1);
860 SCOPED_TRACE(testing::Message() << "Save As to virtual directory");
861 const DownloadTestCase kSaveAsToVirtualDir = {
862 SAVE_AS,
863 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
864 "http://example.com/bar.txt", "text/plain",
865 FILE_PATH_LITERAL(""),
867 FILE_PATH_LITERAL("foo-local.txt"),
868 DownloadItem::TARGET_DISPOSITION_PROMPT,
870 EXPECT_LOCAL_PATH
872 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
873 .WillOnce(WithArg<2>(ScheduleCallback(
874 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
875 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
876 _, test_virtual_dir().AppendASCII("bar.txt"), _))
877 .WillOnce(WithArg<2>(ScheduleCallback(
878 test_virtual_dir().AppendASCII("prompted.txt"))));
879 RunTestCasesWithActiveItem(&kSaveAsToVirtualDir, 1);
883 SCOPED_TRACE(testing::Message() << "Save As to local directory");
884 const DownloadTestCase kSaveAsToLocalDir = {
885 SAVE_AS,
886 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
887 "http://example.com/bar.txt", "text/plain",
888 FILE_PATH_LITERAL(""),
890 FILE_PATH_LITERAL("foo-x.txt"),
891 DownloadItem::TARGET_DISPOSITION_PROMPT,
893 EXPECT_CRDOWNLOAD
895 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
896 _, test_virtual_dir().AppendASCII("bar.txt"), _))
897 .WillOnce(WithArg<2>(ScheduleCallback(
898 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")))));
899 RunTestCasesWithActiveItem(&kSaveAsToLocalDir, 1);
903 SCOPED_TRACE(testing::Message() << "Forced safe download");
904 const DownloadTestCase kForcedSafe = {
905 FORCED,
906 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
907 "http://example.com/foo.txt", "",
908 FILE_PATH_LITERAL("forced-foo.txt"),
910 FILE_PATH_LITERAL("forced-foo.txt"),
911 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
913 EXPECT_LOCAL_PATH
915 RunTestCasesWithActiveItem(&kForcedSafe, 1);
919 // Test that an inactive download will still get a virtual or local download
920 // path.
921 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_InactiveDownload) {
922 const DownloadTestCase kInactiveTestCases[] = {
924 AUTOMATIC,
925 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
926 "http://example.com/foo.txt", "text/plain",
927 FILE_PATH_LITERAL(""),
929 FILE_PATH_LITERAL(""),
930 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
932 EXPECT_LOCAL_PATH
936 SAVE_AS,
937 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
938 "http://example.com/foo.txt", "text/plain",
939 FILE_PATH_LITERAL(""),
941 FILE_PATH_LITERAL(""),
942 DownloadItem::TARGET_DISPOSITION_PROMPT,
944 EXPECT_LOCAL_PATH
948 for (size_t i = 0; i < arraysize(kInactiveTestCases); ++i) {
949 SCOPED_TRACE(testing::Message() << "Running test case " << i);
950 const DownloadTestCase& test_case = kInactiveTestCases[i];
951 scoped_ptr<content::MockDownloadItem> item(
952 CreateActiveDownloadItem(i, test_case));
953 EXPECT_CALL(*item.get(), GetState())
954 .WillRepeatedly(Return(content::DownloadItem::CANCELLED));
955 // Even though one is a SAVE_AS download, no prompt will be displayed to
956 // the user because the download is inactive.
957 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
958 .Times(0);
959 RunTestCase(test_case, base::FilePath(), item.get());
963 // If the reserved path could not be verified, then the user should see a
964 // prompt.
965 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ReservationFailed) {
966 const DownloadTestCase kReservationFailedCases[] = {
968 // 0: Automatic download. Since the reservation fails, the disposition of
969 // the target is to prompt, but the returned path is used.
970 AUTOMATIC,
971 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
972 "http://example.com/foo.txt", "text/plain",
973 FILE_PATH_LITERAL(""),
975 FILE_PATH_LITERAL("bar.txt"),
976 DownloadItem::TARGET_DISPOSITION_PROMPT,
978 EXPECT_CRDOWNLOAD
982 // Setup ReserveVirtualPath() to fail.
983 ON_CALL(*delegate(), ReserveVirtualPath(_, _, _, _, _))
984 .WillByDefault(WithArg<4>(ScheduleCallback2(
985 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")), false)));
986 RunTestCasesWithActiveItem(kReservationFailedCases,
987 arraysize(kReservationFailedCases));
990 // If the local path could not be determined, the download should be cancelled.
991 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LocalPathFailed) {
992 const DownloadTestCase kLocalPathFailedCases[] = {
994 // 0: Automatic download.
995 AUTOMATIC,
996 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
997 "http://example.com/foo.txt", "text/plain",
998 FILE_PATH_LITERAL(""),
1000 FILE_PATH_LITERAL(""),
1001 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1003 EXPECT_LOCAL_PATH
1007 // The default download directory is the virtual path.
1008 download_prefs()->SetDownloadPath(test_virtual_dir());
1009 // Simulate failed call to DetermineLocalPath.
1010 EXPECT_CALL(*delegate(), DetermineLocalPath(
1011 _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
1012 .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
1013 RunTestCasesWithActiveItem(kLocalPathFailedCases,
1014 arraysize(kLocalPathFailedCases));
1017 // Downloads that have a danger level of ALLOW_ON_USER_GESTURE should be marked
1018 // as safe depending on whether there was a user gesture associated with the
1019 // download and whether the referrer was visited prior to today.
1020 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_VisitedReferrer) {
1021 const DownloadTestCase kVisitedReferrerCases[] = {
1022 // http://visited.example.com/ is added to the history as a visit that
1023 // happened prior to today.
1025 // 0: Safe download due to visiting referrer before.
1026 AUTOMATIC,
1027 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1028 "http://visited.example.com/foo.crx", "application/xml",
1029 FILE_PATH_LITERAL(""),
1031 FILE_PATH_LITERAL("foo.crx"),
1032 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1034 EXPECT_CRDOWNLOAD
1038 // 1: Dangerous due to not having visited referrer before.
1039 AUTOMATIC,
1040 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1041 "http://not-visited.example.com/foo.crx", "application/xml",
1042 FILE_PATH_LITERAL(""),
1044 FILE_PATH_LITERAL("foo.crx"),
1045 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1047 EXPECT_UNCONFIRMED
1051 // 2: Safe because the user is being prompted.
1052 SAVE_AS,
1053 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1054 "http://not-visited.example.com/foo.crx", "application/xml",
1055 FILE_PATH_LITERAL(""),
1057 FILE_PATH_LITERAL("foo.crx"),
1058 DownloadItem::TARGET_DISPOSITION_PROMPT,
1060 EXPECT_CRDOWNLOAD
1064 // 3: Safe because of forced path.
1065 FORCED,
1066 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1067 "http://not-visited.example.com/foo.crx", "application/xml",
1068 FILE_PATH_LITERAL("foo.crx"),
1070 FILE_PATH_LITERAL("foo.crx"),
1071 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1073 EXPECT_LOCAL_PATH
1077 // This test assumes that the danger level of .crx files is
1078 // ALLOW_ON_USER_GESTURE.
1079 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1080 download_util::GetFileDangerLevel(
1081 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1083 // First the history service must exist.
1084 ASSERT_TRUE(profile()->CreateHistoryService(false, false));
1086 GURL url("http://visited.example.com/visited-link.html");
1087 // The time of visit is picked to be several seconds prior to the most recent
1088 // midnight.
1089 base::Time time_of_visit(
1090 base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(10));
1091 history::HistoryService* history_service =
1092 HistoryServiceFactory::GetForProfile(profile(),
1093 ServiceAccessType::EXPLICIT_ACCESS);
1094 ASSERT_TRUE(history_service);
1095 history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
1097 RunTestCasesWithActiveItem(kVisitedReferrerCases,
1098 arraysize(kVisitedReferrerCases));
1101 // These test cases are run with "Prompt for download" user preference set to
1102 // true.
1103 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways) {
1104 const DownloadTestCase kPromptingTestCases[] = {
1106 // 0: Safe Automatic - Should prompt because of "Prompt for download"
1107 // preference setting.
1108 AUTOMATIC,
1109 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1110 "http://example.com/foo.txt", "text/plain",
1111 FILE_PATH_LITERAL(""),
1113 FILE_PATH_LITERAL("foo.txt"),
1114 DownloadItem::TARGET_DISPOSITION_PROMPT,
1116 EXPECT_CRDOWNLOAD
1120 // 1: Safe Forced - Shouldn't prompt.
1121 FORCED,
1122 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1123 "http://example.com/foo.txt", "text/plain",
1124 FILE_PATH_LITERAL("foo.txt"),
1126 FILE_PATH_LITERAL("foo.txt"),
1127 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1129 EXPECT_LOCAL_PATH
1133 // 2: Automatic - The filename extension is marked as one that we will
1134 // open automatically. Shouldn't prompt.
1135 AUTOMATIC,
1136 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1137 "http://example.com/foo.dummy", "",
1138 FILE_PATH_LITERAL(""),
1140 FILE_PATH_LITERAL("foo.dummy"),
1141 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1143 EXPECT_CRDOWNLOAD
1147 SetPromptForDownload(true);
1148 EnableAutoOpenBasedOnExtension(
1149 base::FilePath(FILE_PATH_LITERAL("dummy.dummy")));
1150 RunTestCasesWithActiveItem(kPromptingTestCases,
1151 arraysize(kPromptingTestCases));
1154 #if defined(ENABLE_EXTENSIONS)
1155 // These test cases are run with "Prompt for download" user preference set to
1156 // true. Automatic extension downloads shouldn't cause prompting.
1157 // Android doesn't support extensions.
1158 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways_Extension) {
1159 const DownloadTestCase kPromptingTestCases[] = {
1161 // 0: Automatic Browser Extension download. - Shouldn't prompt for browser
1162 // extension downloads even if "Prompt for download" preference is set.
1163 AUTOMATIC,
1164 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1165 "http://example.com/foo.crx",
1166 extensions::Extension::kMimeType,
1167 FILE_PATH_LITERAL(""),
1169 FILE_PATH_LITERAL("foo.crx"),
1170 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1172 EXPECT_UNCONFIRMED
1175 #if defined(OS_WIN)
1177 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1178 // even if "Prompt for download" preference is set. ".js" files are
1179 // considered dangerous on Windows.
1180 AUTOMATIC,
1181 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1182 "http://example.com/foo.user.js", "",
1183 FILE_PATH_LITERAL(""),
1185 FILE_PATH_LITERAL("foo.user.js"),
1186 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1188 EXPECT_UNCONFIRMED
1190 #else
1192 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1193 // even if "Prompt for download" preference is set.
1194 AUTOMATIC,
1195 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1196 "http://example.com/foo.user.js", "",
1197 FILE_PATH_LITERAL(""),
1199 FILE_PATH_LITERAL("foo.user.js"),
1200 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1202 EXPECT_CRDOWNLOAD
1204 #endif
1207 SetPromptForDownload(true);
1208 RunTestCasesWithActiveItem(kPromptingTestCases,
1209 arraysize(kPromptingTestCases));
1211 #endif // defined(ENABLE_EXTENSIONS)
1213 // If the download path is managed, then we don't show any prompts.
1214 // Note that if the download path is managed, then PromptForDownload() is false.
1215 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ManagedPath) {
1216 const DownloadTestCase kManagedPathTestCases[] = {
1218 // 0: Automatic Safe
1219 AUTOMATIC,
1220 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1221 "http://example.com/foo.txt", "text/plain",
1222 FILE_PATH_LITERAL(""),
1224 FILE_PATH_LITERAL("foo.txt"),
1225 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1227 EXPECT_CRDOWNLOAD
1231 // 1: Save_As Safe
1232 SAVE_AS,
1233 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1234 "http://example.com/foo.txt", "text/plain",
1235 FILE_PATH_LITERAL(""),
1237 FILE_PATH_LITERAL("foo.txt"),
1238 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1240 EXPECT_CRDOWNLOAD
1244 SetManagedDownloadPath(test_download_dir());
1245 ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
1246 RunTestCasesWithActiveItem(kManagedPathTestCases,
1247 arraysize(kManagedPathTestCases));
1250 // Test basic functionality supporting extensions that want to override download
1251 // filenames.
1252 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsSafe) {
1253 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1255 // 0: Automatic Safe
1256 AUTOMATIC,
1257 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1258 "http://example.com/foo.txt", "text/plain",
1259 FILE_PATH_LITERAL(""),
1261 FILE_PATH_LITERAL("overridden/foo.txt"),
1262 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1264 EXPECT_CRDOWNLOAD
1268 // 1: Save_As Safe
1269 SAVE_AS,
1270 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1271 "http://example.com/foo.txt", "text/plain",
1272 FILE_PATH_LITERAL(""),
1274 FILE_PATH_LITERAL("overridden/foo.txt"),
1275 DownloadItem::TARGET_DISPOSITION_PROMPT,
1277 EXPECT_CRDOWNLOAD
1281 // 2: Automatic Dangerous
1282 AUTOMATIC,
1283 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1284 "http://example.com/foo.crx", "",
1285 FILE_PATH_LITERAL(""),
1287 FILE_PATH_LITERAL("overridden/foo.crx"),
1288 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1290 EXPECT_UNCONFIRMED
1294 // 3: Forced Safe
1295 FORCED,
1296 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1297 "http://example.com/foo.txt", "",
1298 FILE_PATH_LITERAL("forced-foo.txt"),
1300 FILE_PATH_LITERAL("forced-foo.txt"),
1301 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1303 EXPECT_LOCAL_PATH
1307 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1308 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1309 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1310 arraysize(kNotifyExtensionsTestCases));
1313 // Test that filenames provided by extensions are passed into SafeBrowsing
1314 // checks and dangerous download checks.
1315 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsUnsafe) {
1316 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1318 // 0: Automatic Safe : Later overridden by a dangerous filetype.
1319 AUTOMATIC,
1320 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1321 "http://example.com/foo.crx.remove", "text/plain",
1322 FILE_PATH_LITERAL(""),
1324 FILE_PATH_LITERAL("overridden/foo.crx"),
1325 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1327 EXPECT_UNCONFIRMED
1331 // 1: Automatic Safe : Later overridden by a potentially dangerous
1332 // filetype.
1333 AUTOMATIC,
1334 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
1335 "http://example.com/foo.exe.remove", "text/plain",
1336 FILE_PATH_LITERAL(""),
1338 FILE_PATH_LITERAL("overridden/foo.exe"),
1339 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1341 EXPECT_UNCONFIRMED
1345 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1346 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1347 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
1348 .WillByDefault(Invoke(&CheckDownloadUrlCheckExes));
1349 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1350 arraysize(kNotifyExtensionsTestCases));
1353 // Test that conflict actions set by extensions are passed correctly into
1354 // ReserveVirtualPath.
1355 TEST_F(DownloadTargetDeterminerTest,
1356 TargetDeterminer_NotifyExtensionsConflict) {
1357 const DownloadTestCase kNotifyExtensionsTestCase = {
1358 AUTOMATIC,
1359 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1360 "http://example.com/foo.txt", "text/plain",
1361 FILE_PATH_LITERAL(""),
1363 FILE_PATH_LITERAL("overridden/foo.txt"),
1364 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1366 EXPECT_CRDOWNLOAD
1369 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1370 scoped_ptr<content::MockDownloadItem> item(
1371 CreateActiveDownloadItem(0, test_case));
1372 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1373 base::FilePath full_overridden_path =
1374 GetPathInDownloadDir(overridden_path.value());
1376 // First case: An extension sets the conflict_action to OVERWRITE.
1377 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1378 .WillOnce(WithArg<2>(
1379 ScheduleCallback2(overridden_path,
1380 DownloadPathReservationTracker::OVERWRITE)));
1381 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1382 _, full_overridden_path, true, DownloadPathReservationTracker::OVERWRITE,
1383 _)).WillOnce(WithArg<4>(
1384 ScheduleCallback2(full_overridden_path, true)));
1386 RunTestCase(test_case, base::FilePath(), item.get());
1388 // Second case: An extension sets the conflict_action to PROMPT.
1389 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1390 .WillOnce(WithArg<2>(
1391 ScheduleCallback2(overridden_path,
1392 DownloadPathReservationTracker::PROMPT)));
1393 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1394 _, full_overridden_path, true, DownloadPathReservationTracker::PROMPT, _))
1395 .WillOnce(WithArg<4>(
1396 ScheduleCallback2(full_overridden_path, true)));
1397 RunTestCase(test_case, base::FilePath(), item.get());
1400 // Test that relative paths returned by extensions are always relative to the
1401 // default downloads path.
1402 TEST_F(DownloadTargetDeterminerTest,
1403 TargetDeterminer_NotifyExtensionsDefaultPath) {
1404 const DownloadTestCase kNotifyExtensionsTestCase = {
1405 SAVE_AS,
1406 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1407 "http://example.com/foo.txt", "text/plain",
1408 FILE_PATH_LITERAL(""),
1410 FILE_PATH_LITERAL("overridden/foo.txt"),
1411 DownloadItem::TARGET_DISPOSITION_PROMPT,
1413 EXPECT_CRDOWNLOAD
1416 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1417 scoped_ptr<content::MockDownloadItem> item(
1418 CreateActiveDownloadItem(0, test_case));
1419 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1420 base::FilePath full_overridden_path =
1421 GetPathInDownloadDir(overridden_path.value());
1423 download_prefs()->SetSaveFilePath(GetPathInDownloadDir(
1424 FILE_PATH_LITERAL("last_selected")));
1426 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1427 .WillOnce(WithArg<2>(
1428 ScheduleCallback2(overridden_path,
1429 DownloadPathReservationTracker::UNIQUIFY)));
1430 EXPECT_CALL(*delegate(),
1431 PromptUserForDownloadPath(_, full_overridden_path, _))
1432 .WillOnce(WithArg<2>(
1433 ScheduleCallback(full_overridden_path)));
1434 RunTestCase(test_case, base::FilePath(), item.get());
1437 TEST_F(DownloadTargetDeterminerTest,
1438 TargetDeterminer_InitialVirtualPathUnsafe) {
1439 const base::FilePath::CharType* kInitialPath =
1440 FILE_PATH_LITERAL("some_path/bar.html");
1442 const DownloadTestCase kInitialPathTestCase = {
1443 // 0: Save As Save. The path generated based on the DownloadItem is safe,
1444 // but the initial path is unsafe. However, the download is not considered
1445 // dangerous since the user has been prompted.
1446 SAVE_AS,
1447 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1448 "http://example.com/foo.txt", "text/plain",
1449 FILE_PATH_LITERAL(""),
1451 kInitialPath,
1452 DownloadItem::TARGET_DISPOSITION_PROMPT,
1454 EXPECT_CRDOWNLOAD
1457 const DownloadTestCase& test_case = kInitialPathTestCase;
1458 scoped_ptr<content::MockDownloadItem> item(
1459 CreateActiveDownloadItem(1, test_case));
1460 EXPECT_CALL(*item, GetLastReason())
1461 .WillRepeatedly(Return(
1462 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1463 EXPECT_CALL(*item, GetTargetDisposition())
1464 .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
1465 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1468 // Prompting behavior for resumed downloads is based on the last interrupt
1469 // reason. If the reason indicates that the target path may not be suitable for
1470 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1471 // prompted, and not otherwise. These test cases shouldn't result in prompting
1472 // since the error is set to NETWORK_FAILED.
1473 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedNoPrompt) {
1474 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1475 // path.
1476 const base::FilePath::CharType* kInitialPath =
1477 FILE_PATH_LITERAL("some_path/bar.txt");
1479 const DownloadTestCase kResumedTestCases[] = {
1481 // 0: Automatic Safe: Initial path is ignored since the user has not been
1482 // prompted before.
1483 AUTOMATIC,
1484 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1485 "http://example.com/foo.txt", "text/plain",
1486 FILE_PATH_LITERAL(""),
1488 FILE_PATH_LITERAL("foo.txt"),
1489 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1491 EXPECT_CRDOWNLOAD
1495 // 1: Save_As Safe: Initial path used.
1496 SAVE_AS,
1497 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1498 "http://example.com/foo.txt", "text/plain",
1499 FILE_PATH_LITERAL(""),
1501 kInitialPath,
1502 DownloadItem::TARGET_DISPOSITION_PROMPT,
1504 EXPECT_CRDOWNLOAD
1508 // 2: Automatic Dangerous: Initial path is ignored since the user hasn't
1509 // been prompted before.
1510 AUTOMATIC,
1511 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1512 "http://example.com/foo.crx", "",
1513 FILE_PATH_LITERAL(""),
1515 FILE_PATH_LITERAL("foo.crx"),
1516 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1518 EXPECT_UNCONFIRMED
1522 // 3: Forced Safe: Initial path is ignored due to the forced path.
1523 FORCED,
1524 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1525 "http://example.com/foo.txt", "",
1526 FILE_PATH_LITERAL("forced-foo.txt"),
1528 FILE_PATH_LITERAL("forced-foo.txt"),
1529 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1531 EXPECT_LOCAL_PATH
1535 // The test assumes that .crx files have a danger level of
1536 // ALLOW_ON_USER_GESTURE.
1537 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1538 download_util::GetFileDangerLevel(
1539 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1540 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1541 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1542 const DownloadTestCase& test_case = kResumedTestCases[i];
1543 scoped_ptr<content::MockDownloadItem> item(
1544 CreateActiveDownloadItem(i, test_case));
1545 base::FilePath expected_path =
1546 GetPathInDownloadDir(test_case.expected_local_path);
1547 ON_CALL(*item.get(), GetLastReason())
1548 .WillByDefault(Return(
1549 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1550 // Extensions should be notified if a new path is being generated and there
1551 // is no forced path. In the test cases above, this is true for tests with
1552 // type == AUTOMATIC.
1553 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1554 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1555 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1556 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _))
1557 .Times(0);
1558 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1559 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1560 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1564 // Test that a forced download doesn't prompt, even if the interrupt reason
1565 // suggests that the target path may not be suitable for downloads.
1566 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedForcedDownload) {
1567 const base::FilePath::CharType* kInitialPath =
1568 FILE_PATH_LITERAL("some_path/bar.txt");
1569 const DownloadTestCase kResumedForcedDownload = {
1570 // 3: Forced Safe
1571 FORCED,
1572 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1573 "http://example.com/foo.txt", "",
1574 FILE_PATH_LITERAL("forced-foo.txt"),
1576 FILE_PATH_LITERAL("forced-foo.txt"),
1577 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1579 EXPECT_LOCAL_PATH
1582 const DownloadTestCase& test_case = kResumedForcedDownload;
1583 base::FilePath expected_path =
1584 GetPathInDownloadDir(test_case.expected_local_path);
1585 scoped_ptr<content::MockDownloadItem> item(
1586 CreateActiveDownloadItem(0, test_case));
1587 ON_CALL(*item.get(), GetLastReason())
1588 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1589 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1590 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1591 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1592 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
1593 .Times(0);
1594 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1595 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1596 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1599 // Prompting behavior for resumed downloads is based on the last interrupt
1600 // reason. If the reason indicates that the target path may not be suitable for
1601 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1602 // prompted, and not otherwise. These test cases result in prompting since the
1603 // error is set to NO_SPACE.
1604 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedWithPrompt) {
1605 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1606 // path.
1607 const base::FilePath::CharType* kInitialPath =
1608 FILE_PATH_LITERAL("some_path/bar.txt");
1610 const DownloadTestCase kResumedTestCases[] = {
1612 // 0: Automatic Safe
1613 AUTOMATIC,
1614 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1615 "http://example.com/foo.txt", "text/plain",
1616 FILE_PATH_LITERAL(""),
1618 FILE_PATH_LITERAL("foo.txt"),
1619 DownloadItem::TARGET_DISPOSITION_PROMPT,
1621 EXPECT_CRDOWNLOAD
1625 // 1: Save_As Safe
1626 SAVE_AS,
1627 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1628 "http://example.com/foo.txt", "text/plain",
1629 FILE_PATH_LITERAL(""),
1631 kInitialPath,
1632 DownloadItem::TARGET_DISPOSITION_PROMPT,
1634 EXPECT_CRDOWNLOAD
1638 // 2: Automatic Dangerous
1639 AUTOMATIC,
1640 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1641 "http://example.com/foo.crx", "",
1642 FILE_PATH_LITERAL(""),
1644 FILE_PATH_LITERAL("foo.crx"),
1645 DownloadItem::TARGET_DISPOSITION_PROMPT,
1647 EXPECT_CRDOWNLOAD
1651 // The test assumes that .xml files have a danger level of
1652 // ALLOW_ON_USER_GESTURE.
1653 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1654 download_util::GetFileDangerLevel(
1655 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1656 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1657 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1658 download_prefs()->SetSaveFilePath(test_download_dir());
1659 const DownloadTestCase& test_case = kResumedTestCases[i];
1660 base::FilePath expected_path =
1661 GetPathInDownloadDir(test_case.expected_local_path);
1662 scoped_ptr<content::MockDownloadItem> item(
1663 CreateActiveDownloadItem(i, test_case));
1664 ON_CALL(*item.get(), GetLastReason())
1665 .WillByDefault(Return(
1666 content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1667 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1668 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1669 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1670 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _));
1671 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1672 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1673 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1677 // Test intermediate filename generation for resumed downloads.
1678 TEST_F(DownloadTargetDeterminerTest,
1679 TargetDeterminer_IntermediateNameForResumed) {
1680 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1681 // path.
1682 const base::FilePath::CharType kInitialPath[] =
1683 FILE_PATH_LITERAL("some_path/bar.txt");
1685 struct IntermediateNameTestCase {
1686 // General test case settings.
1687 DownloadTestCase general;
1689 // Value of DownloadItem::GetFullPath() during test run, relative
1690 // to test download path.
1691 const base::FilePath::CharType* initial_intermediate_path;
1693 // Expected intermediate path relatvie to the test download path. An exact
1694 // match is performed if this string is non-empty. Ignored otherwise.
1695 const base::FilePath::CharType* expected_intermediate_path;
1696 } kIntermediateNameTestCases[] = {
1699 // 0: Automatic Safe
1700 AUTOMATIC,
1701 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1702 "http://example.com/foo.txt", "text/plain",
1703 FILE_PATH_LITERAL(""),
1705 FILE_PATH_LITERAL("foo.txt"),
1706 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1708 EXPECT_CRDOWNLOAD
1710 FILE_PATH_LITERAL("bar.txt.crdownload"),
1711 FILE_PATH_LITERAL("foo.txt.crdownload")
1716 // 1: Save_As Safe
1717 SAVE_AS,
1718 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1719 "http://example.com/foo.txt", "text/plain",
1720 FILE_PATH_LITERAL(""),
1722 kInitialPath,
1723 DownloadItem::TARGET_DISPOSITION_PROMPT,
1725 EXPECT_CRDOWNLOAD
1727 FILE_PATH_LITERAL("foo.txt.crdownload"),
1728 FILE_PATH_LITERAL("some_path/bar.txt.crdownload")
1733 // 2: Automatic Dangerous
1734 AUTOMATIC,
1735 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1736 "http://example.com/foo.crx", "",
1737 FILE_PATH_LITERAL(""),
1739 FILE_PATH_LITERAL("foo.crx"),
1740 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1742 EXPECT_UNCONFIRMED
1744 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload"),
1745 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload")
1750 // 3: Automatic Dangerous
1751 AUTOMATIC,
1752 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1753 "http://example.com/foo.crx", "",
1754 FILE_PATH_LITERAL(""),
1756 FILE_PATH_LITERAL("foo.crx"),
1757 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1759 EXPECT_UNCONFIRMED
1761 FILE_PATH_LITERAL("other_path/Unconfirmed abcd.crdownload"),
1762 // Rely on the EXPECT_UNCONFIRMED check in the general test settings. A
1763 // new intermediate path of the form "Unconfirmed <number>.crdownload"
1764 // should be generated for this case since the initial intermediate path
1765 // is in the wrong directory.
1766 FILE_PATH_LITERAL("")
1771 // 3: Forced Safe: Initial path is ignored due to the forced path.
1772 FORCED,
1773 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1774 "http://example.com/foo.txt", "",
1775 FILE_PATH_LITERAL("forced-foo.txt"),
1777 FILE_PATH_LITERAL("forced-foo.txt"),
1778 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1780 EXPECT_LOCAL_PATH
1782 FILE_PATH_LITERAL("forced-foo.txt"),
1783 FILE_PATH_LITERAL("forced-foo.txt")
1787 // The test assumes that .crx files have a danger level of
1788 // ALLOW_ON_USER_GESTURE.
1789 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1790 download_util::GetFileDangerLevel(
1791 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1793 for (size_t i = 0; i < arraysize(kIntermediateNameTestCases); ++i) {
1794 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1795 const IntermediateNameTestCase& test_case = kIntermediateNameTestCases[i];
1796 scoped_ptr<content::MockDownloadItem> item(
1797 CreateActiveDownloadItem(i, test_case.general));
1799 ON_CALL(*item.get(), GetLastReason())
1800 .WillByDefault(Return(
1801 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1802 ON_CALL(*item.get(), GetFullPath())
1803 .WillByDefault(ReturnRefOfCopy(
1804 GetPathInDownloadDir(test_case.initial_intermediate_path)));
1805 ON_CALL(*item.get(), GetDangerType())
1806 .WillByDefault(Return(test_case.general.expected_danger_type));
1808 scoped_ptr<DownloadTargetInfo> target_info =
1809 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1810 item.get());
1811 VerifyDownloadTarget(test_case.general, target_info.get());
1812 base::FilePath expected_intermediate_path =
1813 GetPathInDownloadDir(test_case.expected_intermediate_path);
1814 if (!expected_intermediate_path.empty())
1815 EXPECT_EQ(expected_intermediate_path, target_info->intermediate_path);
1819 // Test MIME type determination based on the target filename.
1820 TEST_F(DownloadTargetDeterminerTest,
1821 TargetDeterminer_MIMETypeDetermination) {
1822 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1823 // path.
1824 const base::FilePath::CharType kInitialPath[] =
1825 FILE_PATH_LITERAL("some_path/bar.txt");
1827 struct MIMETypeTestCase {
1828 // General test case settings.
1829 DownloadTestCase general;
1831 // Expected MIME type for test case.
1832 const char* expected_mime_type;
1833 } kMIMETypeTestCases[] = {
1836 // 0:
1837 AUTOMATIC,
1838 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1839 "http://example.com/foo.png", "image/png",
1840 FILE_PATH_LITERAL(""),
1842 FILE_PATH_LITERAL("foo.png"),
1843 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1845 EXPECT_CRDOWNLOAD
1847 "image/png"
1851 // 1: Empty MIME type in response.
1852 AUTOMATIC,
1853 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1854 "http://example.com/foo.png", "",
1855 FILE_PATH_LITERAL(""),
1857 FILE_PATH_LITERAL("foo.png"),
1858 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1860 EXPECT_CRDOWNLOAD
1862 "image/png"
1866 // 2: Forced path.
1867 FORCED,
1868 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1869 "http://example.com/foo.abc", "",
1870 FILE_PATH_LITERAL("foo.png"),
1872 FILE_PATH_LITERAL("foo.png"),
1873 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1875 EXPECT_CRDOWNLOAD
1877 "image/png"
1881 // 3: Unknown file type.
1882 AUTOMATIC,
1883 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1884 "http://example.com/foo.notarealext", "",
1885 FILE_PATH_LITERAL(""),
1887 FILE_PATH_LITERAL("foo.notarealext"),
1888 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1890 EXPECT_CRDOWNLOAD
1896 // 4: Unknown file type.
1897 AUTOMATIC,
1898 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1899 "http://example.com/foo.notarealext", "image/png",
1900 FILE_PATH_LITERAL(""),
1902 FILE_PATH_LITERAL("foo.notarealext"),
1903 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1905 EXPECT_CRDOWNLOAD
1911 ON_CALL(*delegate(), GetFileMimeType(
1912 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.png")), _))
1913 .WillByDefault(WithArg<1>(
1914 ScheduleCallback("image/png")));
1916 for (size_t i = 0; i < arraysize(kMIMETypeTestCases); ++i) {
1917 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1918 const MIMETypeTestCase& test_case = kMIMETypeTestCases[i];
1919 scoped_ptr<content::MockDownloadItem> item(
1920 CreateActiveDownloadItem(i, test_case.general));
1921 scoped_ptr<DownloadTargetInfo> target_info =
1922 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1923 item.get());
1924 EXPECT_EQ(test_case.expected_mime_type, target_info->mime_type);
1928 #if defined(ENABLE_PLUGINS)
1930 void DummyGetPluginsCallback(
1931 const base::Closure& closure,
1932 const std::vector<content::WebPluginInfo>& plugins) {
1933 closure.Run();
1936 void ForceRefreshOfPlugins() {
1937 #if !defined(OS_WIN)
1938 // Prevent creation of a utility process for loading plugins. Doing so breaks
1939 // unit_tests since /proc/self/exe can't be run as a utility process.
1940 content::RenderProcessHost::SetRunRendererInProcess(true);
1941 #endif
1942 base::RunLoop run_loop;
1943 content::PluginService::GetInstance()->GetPlugins(
1944 base::Bind(&DummyGetPluginsCallback, run_loop.QuitClosure()));
1945 run_loop.Run();
1946 #if !defined(OS_WIN)
1947 content::RenderProcessHost::SetRunRendererInProcess(false);
1948 #endif
1951 class MockPluginServiceFilter : public content::PluginServiceFilter {
1952 public:
1953 MOCK_METHOD1(MockPluginAvailable, bool(const base::FilePath&));
1955 virtual bool IsPluginAvailable(int render_process_id,
1956 int render_view_id,
1957 const void* context,
1958 const GURL& url,
1959 const GURL& policy_url,
1960 content::WebPluginInfo* plugin) override {
1961 return MockPluginAvailable(plugin->path);
1964 virtual bool CanLoadPlugin(int render_process_id,
1965 const base::FilePath& path) override {
1966 return true;
1970 class ScopedRegisterInternalPlugin {
1971 public:
1972 ScopedRegisterInternalPlugin(content::PluginService* plugin_service,
1973 content::WebPluginInfo::PluginType type,
1974 const base::FilePath& path,
1975 const char* mime_type,
1976 const char* extension)
1977 : plugin_service_(plugin_service),
1978 plugin_path_(path) {
1979 content::WebPluginMimeType plugin_mime_type(mime_type,
1980 extension,
1981 "Test file");
1982 content::WebPluginInfo plugin_info(base::string16(),
1983 path,
1984 base::string16(),
1985 base::string16());
1986 plugin_info.mime_types.push_back(plugin_mime_type);
1987 plugin_info.type = type;
1989 plugin_service->RegisterInternalPlugin(plugin_info, true);
1990 plugin_service->RefreshPlugins();
1991 ForceRefreshOfPlugins();
1994 ~ScopedRegisterInternalPlugin() {
1995 plugin_service_->UnregisterInternalPlugin(plugin_path_);
1996 plugin_service_->RefreshPlugins();
1997 ForceRefreshOfPlugins();
2000 const base::FilePath& path() { return plugin_path_; }
2002 private:
2003 content::PluginService* plugin_service_;
2004 base::FilePath plugin_path_;
2007 // We use a slightly different test fixture for tests that touch plugins. SetUp
2008 // needs to disable plugin discovery and we need to use a
2009 // ShadowingAtExitManager to discard the tainted PluginService. Unfortunately,
2010 // PluginService carries global state.
2011 class DownloadTargetDeterminerTestWithPlugin
2012 : public DownloadTargetDeterminerTest {
2013 public:
2014 DownloadTargetDeterminerTestWithPlugin()
2015 : old_plugin_service_filter_(NULL) {}
2017 virtual void SetUp() override {
2018 content::PluginService* plugin_service =
2019 content::PluginService::GetInstance();
2020 plugin_service->Init();
2021 plugin_service->DisablePluginsDiscoveryForTesting();
2022 old_plugin_service_filter_ = plugin_service->GetFilter();
2023 plugin_service->SetFilter(&mock_plugin_filter_);
2024 DownloadTargetDeterminerTest::SetUp();
2027 virtual void TearDown() override {
2028 content::PluginService::GetInstance()->SetFilter(
2029 old_plugin_service_filter_);
2030 DownloadTargetDeterminerTest::TearDown();
2033 protected:
2034 content::PluginServiceFilter* old_plugin_service_filter_;
2035 testing::StrictMock<MockPluginServiceFilter> mock_plugin_filter_;
2036 // The ShadowingAtExitManager destroys the tainted PluginService instance.
2037 base::ShadowingAtExitManager at_exit_manager_;
2040 // Check if secure handling of filetypes is determined correctly for PPAPI
2041 // plugins.
2042 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2043 TargetDeterminer_CheckForSecureHandling_PPAPI) {
2044 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2045 // path.
2046 const base::FilePath::CharType kInitialPath[] =
2047 FILE_PATH_LITERAL("some_path/bar.txt");
2048 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2050 DownloadTestCase kSecureHandlingTestCase = {
2051 AUTOMATIC,
2052 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2053 "http://example.com/foo.fakeext", "",
2054 FILE_PATH_LITERAL(""),
2056 FILE_PATH_LITERAL("foo.fakeext"),
2057 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2059 EXPECT_CRDOWNLOAD
2062 content::PluginService* plugin_service =
2063 content::PluginService::GetInstance();
2065 // Verify our test assumptions.
2067 ForceRefreshOfPlugins();
2068 std::vector<content::WebPluginInfo> info;
2069 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2070 GURL(), kTestMIMEType, false, &info, NULL));
2071 ASSERT_EQ(0u, info.size())
2072 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2075 ON_CALL(*delegate(), GetFileMimeType(
2076 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2077 .WillByDefault(WithArg<1>(
2078 ScheduleCallback(kTestMIMEType)));
2079 scoped_ptr<content::MockDownloadItem> item(
2080 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2081 scoped_ptr<DownloadTargetInfo> target_info =
2082 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2083 item.get());
2084 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2086 // Register a PPAPI plugin. This should count as handling the filetype
2087 // securely.
2088 ScopedRegisterInternalPlugin ppapi_plugin(
2089 plugin_service,
2090 content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS,
2091 test_download_dir().AppendASCII("ppapi"),
2092 kTestMIMEType,
2093 "fakeext");
2094 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(ppapi_plugin.path()))
2095 .WillRepeatedly(Return(true));
2097 target_info = RunDownloadTargetDeterminer(
2098 GetPathInDownloadDir(kInitialPath), item.get());
2099 EXPECT_TRUE(target_info->is_filetype_handled_safely);
2101 // Try disabling the plugin. Handling should no longer be considered secure.
2102 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(ppapi_plugin.path()))
2103 .WillRepeatedly(Return(false));
2104 target_info = RunDownloadTargetDeterminer(
2105 GetPathInDownloadDir(kInitialPath), item.get());
2106 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2108 // Now register an unsandboxed PPAPI plugin. This plugin should not be
2109 // considered secure.
2110 ScopedRegisterInternalPlugin ppapi_unsandboxed_plugin(
2111 plugin_service,
2112 content::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED,
2113 test_download_dir().AppendASCII("ppapi-nosandbox"),
2114 kTestMIMEType,
2115 "fakeext");
2116 EXPECT_CALL(mock_plugin_filter_,
2117 MockPluginAvailable(ppapi_unsandboxed_plugin.path()))
2118 .WillRepeatedly(Return(true));
2120 target_info = RunDownloadTargetDeterminer(
2121 GetPathInDownloadDir(kInitialPath), item.get());
2122 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2125 // Check if secure handling of filetypes is determined correctly for NPAPI
2126 // plugins.
2127 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2128 TargetDeterminer_CheckForSecureHandling_NPAPI) {
2129 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2130 // path.
2131 const base::FilePath::CharType kInitialPath[] =
2132 FILE_PATH_LITERAL("some_path/bar.txt");
2133 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2135 DownloadTestCase kSecureHandlingTestCase = {
2136 AUTOMATIC,
2137 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2138 "http://example.com/foo.fakeext", "",
2139 FILE_PATH_LITERAL(""),
2141 FILE_PATH_LITERAL("foo.fakeext"),
2142 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2144 EXPECT_CRDOWNLOAD
2147 content::PluginService* plugin_service =
2148 content::PluginService::GetInstance();
2150 // Can't run this test if NPAPI isn't supported.
2151 if (!plugin_service->NPAPIPluginsSupported())
2152 return;
2154 // Verify our test assumptions.
2156 ForceRefreshOfPlugins();
2157 std::vector<content::WebPluginInfo> info;
2158 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2159 GURL(), kTestMIMEType, false, &info, NULL));
2160 ASSERT_EQ(0u, info.size())
2161 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2164 ON_CALL(*delegate(), GetFileMimeType(
2165 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2166 .WillByDefault(WithArg<1>(
2167 ScheduleCallback(kTestMIMEType)));
2168 scoped_ptr<content::MockDownloadItem> item(
2169 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2170 scoped_ptr<DownloadTargetInfo> target_info =
2171 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2172 item.get());
2173 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2175 // Register a NPAPI plugin. This should not count as handling the filetype
2176 // securely.
2177 ScopedRegisterInternalPlugin npapi_plugin(
2178 plugin_service,
2179 content::WebPluginInfo::PLUGIN_TYPE_NPAPI,
2180 test_download_dir().AppendASCII("npapi"),
2181 kTestMIMEType,
2182 "fakeext");
2183 EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(npapi_plugin.path()))
2184 .WillRepeatedly(Return(true));
2186 target_info = RunDownloadTargetDeterminer(
2187 GetPathInDownloadDir(kInitialPath), item.get());
2188 EXPECT_FALSE(target_info->is_filetype_handled_safely);
2190 #endif // defined(ENABLE_PLUGINS)
2192 } // namespace