Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: chrome/browser/download/download_target_determiner_unittest.cc

Issue 14773004: Move download filename determination into a separate class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/file_util.h"
6 #include "base/files/file_path.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/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/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_util.h"
20 #include "chrome/browser/history/history_service.h"
21 #include "chrome/browser/history/history_service_factory.h"
22 #include "chrome/browser/history/history_types.h"
23 #include "chrome/common/extensions/extension.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
26 #include "chrome/test/base/testing_pref_service_syncable.h"
27 #include "chrome/test/base/testing_profile.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_contents_delegate.h"
30 #include "content/public/test/mock_download_item.h"
31 #include "content/public/test/test_browser_thread.h"
32 #include "content/public/test/test_renderer_host.h"
33 #include "content/public/test/web_contents_tester.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 using ::testing::AnyNumber;
38 using ::testing::Invoke;
39 using ::testing::Ref;
40 using ::testing::Return;
41 using ::testing::ReturnRef;
42 using ::testing::ReturnRefOfCopy;
43 using ::testing::Truly;
44 using ::testing::WithArg;
45 using ::testing::_;
46 using content::DownloadItem;
47
48 namespace {
49
50 // No-op delegate.
51 class NullWebContentsDelegate : public content::WebContentsDelegate {
52 public:
53 NullWebContentsDelegate() {}
54 virtual ~NullWebContentsDelegate() {}
55 };
56
57 // Google Mock action that posts a task to the current message loop that invokes
58 // the first argument of the mocked method as a callback. Said argument must be
59 // a base::Callback<void(ParamType)>. |result| must be of |ParamType| and is
60 // bound as that parameter.
61 // Example:
62 // class FooClass {
63 // public:
64 // virtual void Foo(base::Callback<void(bool)> callback);
65 // };
66 // ...
67 // EXPECT_CALL(mock_fooclass_instance, Foo(callback))
68 // .WillOnce(ScheduleCallback(false));
69 ACTION_P(ScheduleCallback, result0) {
70 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, result0));
71 }
72
73 // Similar to ScheduleCallback, but binds 2 arguments.
74 ACTION_P2(ScheduleCallback2, result0, result1) {
75 base::MessageLoop::current()->PostTask(
76 FROM_HERE, base::Bind(arg0, result0, result1));
77 }
78
79 // Used with DownloadTestCase. Indicates the type of test case. The expectations
80 // for the test is set based on the type.
81 enum TestCaseType {
82 SAVE_AS,
83 AUTOMATIC,
84 FORCED // Requires that forced_file_path be non-empty.
85 };
86
87 // Used with DownloadTestCase. Type of intermediate filename to expect.
88 enum TestCaseExpectIntermediate {
89 EXPECT_CRDOWNLOAD, // Expect path/to/target.crdownload.
90 EXPECT_UNCONFIRMED, // Expect path/to/Unconfirmed xxx.crdownload.
91 EXPECT_LOCAL_PATH, // Expect target path.
92 };
93
94 // Typical download test case. Used with
95 // DownloadTargetDeterminerTest::RunTestCase().
96 struct DownloadTestCase {
97 // Type of test.
98 TestCaseType test_type;
99
100 // Expected danger type. Verified at the end of target determination.
101 content::DownloadDangerType expected_danger_type;
102
103 // Value of DownloadItem::GetURL()
104 const char* url;
105
106 // Value of DownloadItem::GetMimeType()
107 const char* mime_type;
108
109 // Should be non-empty if |test_type| == FORCED. Value of GetForcedFilePath().
110 const base::FilePath::CharType* forced_file_path;
111
112 // Expected virtual path. Specified relative to the virtual download path. If
113 // empty, assumed to be the same as |expected_local_path|.
114 const base::FilePath::CharType* expected_virtual_path;
Nico 2014/01/15 18:01:07 This appears unused. I'll send out a CL to remove
115
116 // Expected local path. Specified relative to the test download path.
117 const base::FilePath::CharType* expected_local_path;
118
119 // Expected target disposition. If this is TARGET_DISPOSITION_PROMPT, then the
120 // test run will expect ChromeDownloadManagerDelegate to prompt the user for a
121 // download location.
122 DownloadItem::TargetDisposition expected_disposition;
123
124 // Type of intermediate path to expect.
125 TestCaseExpectIntermediate expected_intermediate;
126 };
127
128 class MockDownloadTargetDeterminerDelegate :
129 public DownloadTargetDeterminerDelegate {
130 public:
131 MOCK_METHOD3(CheckDownloadUrl,
132 void(content::DownloadItem*, const base::FilePath&,
133 const CheckDownloadUrlCallback&));
134 MOCK_METHOD3(NotifyExtensions,
135 void(content::DownloadItem*, const base::FilePath&,
136 const NotifyExtensionsCallback&));
137 MOCK_METHOD3(PromptUserForDownloadPath,
138 void(content::DownloadItem*, const base::FilePath&,
139 const FileSelectedCallback&));
140 MOCK_METHOD3(DetermineLocalPath,
141 void(DownloadItem*, const base::FilePath&,
142 const LocalPathCallback&));
143 MOCK_METHOD4(ReserveVirtualPath,
144 void(DownloadItem*, const base::FilePath&,
145 DownloadPathReservationTracker::FilenameConflictAction,
146 const ReservedPathCallback&));
147
148 void SetupDefaults() {
149 ON_CALL(*this, CheckDownloadUrl(_, _, _))
150 .WillByDefault(WithArg<2>(
151 ScheduleCallback(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)));
152 ON_CALL(*this, NotifyExtensions(_, _, _))
153 .WillByDefault(WithArg<2>(
154 ScheduleCallback2(base::FilePath(),
155 DownloadPathReservationTracker::UNIQUIFY)));
156 ON_CALL(*this, ReserveVirtualPath(_, _, _, _))
157 .WillByDefault(Invoke(
158 &MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath));
159 ON_CALL(*this, PromptUserForDownloadPath(_, _, _))
160 .WillByDefault(Invoke(
161 &MockDownloadTargetDeterminerDelegate::NullPromptUser));
162 ON_CALL(*this, DetermineLocalPath(_, _, _))
163 .WillByDefault(Invoke(
164 &MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath));
165 }
166 private:
167 static void NullReserveVirtualPath(
168 DownloadItem* download,
169 const base::FilePath& virtual_path,
170 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
171 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback);
172 static void NullPromptUser(
173 DownloadItem* download, const base::FilePath& suggested_path,
174 const FileSelectedCallback& callback);
175 static void NullDetermineLocalPath(
176 DownloadItem* download, const base::FilePath& virtual_path,
177 const LocalPathCallback& callback);
178 };
179
180 class DownloadTargetDeterminerTest : public ChromeRenderViewHostTestHarness {
181 public:
182 DownloadTargetDeterminerTest();
183
184 // ::testing::Test
185 virtual void SetUp() OVERRIDE;
186 virtual void TearDown() OVERRIDE;
187
188 // Creates MockDownloadItem and sets up default expectations.
189 content::MockDownloadItem* CreateActiveDownloadItem(
190 int32 id,
191 const DownloadTestCase& test_case);
192
193 // Sets the AutoOpenBasedOnExtension user preference for |path|.
194 void EnableAutoOpenBasedOnExtension(const base::FilePath& path);
195
196 // Set the kDownloadDefaultDirectory user preference to |path|.
197 void SetDefaultDownloadPath(const base::FilePath& path);
198
199 // Set the kDownloadDefaultDirectory managed preference to |path|.
200 void SetManagedDownloadPath(const base::FilePath& path);
201
202 // Set the kPromptForDownload user preference to |prompt|.
203 void SetPromptForDownload(bool prompt);
204
205 // Given the relative path |path|, returns the full path under the temporary
206 // downloads directory.
207 base::FilePath GetPathInDownloadDir(const base::FilePath::StringType& path);
208
209 // Run |test_case| using |item|.
210 void RunTestCase(const DownloadTestCase& test_case,
211 content::MockDownloadItem* item);
212
213 // Run through |test_case_count| tests in |test_cases|. A new MockDownloadItem
214 // will be created for each test case and destroyed when the test case is
215 // complete.
216 void RunTestCasesWithActiveItem(const DownloadTestCase test_cases[],
217 size_t test_case_count);
218
219 const base::FilePath& test_download_dir() const {
220 return test_download_dir_.path();
221 }
222
223 const base::FilePath& test_virtual_dir() const {
224 return test_virtual_dir_;
225 }
226
227 MockDownloadTargetDeterminerDelegate* delegate() {
228 return &delegate_;
229 }
230
231 DownloadPrefs* download_prefs() {
232 return download_prefs_.get();
233 }
234
235 void set_last_selected_directory(const base::FilePath& path) {
236 last_selected_directory_ = path;
237 }
238
239 private:
240 // Verifies that |target_path|, |disposition|, |expected_danger_type| and
241 // |intermediate_path| matches the expectations of |test_case|. Posts
242 // |closure| to the current message loop when done.
243 void DownloadTargetVerifier(const base::Closure& closure,
244 const DownloadTestCase& test_case,
245 const base::FilePath& local_path,
246 DownloadItem::TargetDisposition disposition,
247 content::DownloadDangerType danger_type,
248 const base::FilePath& intermediate_path);
249
250 scoped_ptr<DownloadPrefs> download_prefs_;
251 ::testing::NiceMock<MockDownloadTargetDeterminerDelegate> delegate_;
252 NullWebContentsDelegate web_contents_delegate_;
253 base::ScopedTempDir test_download_dir_;
254 base::FilePath test_virtual_dir_;
255 base::FilePath last_selected_directory_;
256 content::TestBrowserThread ui_thread_;
257 content::TestBrowserThread file_thread_;
258 };
259
260 DownloadTargetDeterminerTest::DownloadTargetDeterminerTest()
261 : ChromeRenderViewHostTestHarness(),
262 ui_thread_(content::BrowserThread::UI, &message_loop_),
263 file_thread_(content::BrowserThread::FILE, &message_loop_) {
264 }
265
266 void DownloadTargetDeterminerTest::SetUp() {
267 ChromeRenderViewHostTestHarness::SetUp();
268 CHECK(profile());
269 download_prefs_.reset(new DownloadPrefs(profile()));
270 web_contents()->SetDelegate(&web_contents_delegate_);
271 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
272 test_virtual_dir_ = test_download_dir().Append(FILE_PATH_LITERAL("virtual"));
273 SetDefaultDownloadPath(test_download_dir());
274 delegate_.SetupDefaults();
275 }
276
277 void DownloadTargetDeterminerTest::TearDown() {
278 download_prefs_.reset();
279 message_loop_.RunUntilIdle();
280 ChromeRenderViewHostTestHarness::TearDown();
281 }
282
283 content::MockDownloadItem*
284 DownloadTargetDeterminerTest::CreateActiveDownloadItem(
285 int32 id,
286 const DownloadTestCase& test_case) {
287 content::MockDownloadItem* item =
288 new ::testing::NiceMock<content::MockDownloadItem>();
289 GURL download_url(test_case.url);
290 std::vector<GURL> url_chain;
291 url_chain.push_back(download_url);
292 base::FilePath forced_file_path =
293 GetPathInDownloadDir(test_case.forced_file_path);
294 DownloadItem::TargetDisposition initial_disposition =
295 (test_case.test_type == SAVE_AS) ?
296 DownloadItem::TARGET_DISPOSITION_PROMPT :
297 DownloadItem::TARGET_DISPOSITION_OVERWRITE;
298 EXPECT_EQ(test_case.test_type == FORCED,
299 !forced_file_path.empty());
300
301 ON_CALL(*item, GetBrowserContext())
302 .WillByDefault(Return(profile()));
303 ON_CALL(*item, GetDangerType())
304 .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
305 ON_CALL(*item, GetForcedFilePath())
306 .WillByDefault(ReturnRefOfCopy(forced_file_path));
307 ON_CALL(*item, GetFullPath())
308 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
309 ON_CALL(*item, GetHash())
310 .WillByDefault(ReturnRefOfCopy(std::string()));
311 ON_CALL(*item, GetId())
312 .WillByDefault(Return(id));
313 ON_CALL(*item, 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(content::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, IsInProgress())
336 .WillByDefault(Return(true));
337 ON_CALL(*item, IsTemporary())
338 .WillByDefault(Return(false));
339 return item;
340 }
341
342 void DownloadTargetDeterminerTest::EnableAutoOpenBasedOnExtension(
343 const base::FilePath& path) {
344 EXPECT_TRUE(download_prefs_->EnableAutoOpenBasedOnExtension(path));
345 }
346
347 void DownloadTargetDeterminerTest::SetDefaultDownloadPath(
348 const base::FilePath& path) {
349 profile()->GetTestingPrefService()->
350 SetFilePath(prefs::kDownloadDefaultDirectory, path);
351 }
352
353 void DownloadTargetDeterminerTest::SetManagedDownloadPath(
354 const base::FilePath& path) {
355 profile()->GetTestingPrefService()->
356 SetManagedPref(prefs::kDownloadDefaultDirectory,
357 base::CreateFilePathValue(path));
358 }
359
360 void DownloadTargetDeterminerTest::SetPromptForDownload(bool prompt) {
361 profile()->GetTestingPrefService()->
362 SetBoolean(prefs::kPromptForDownload, prompt);
363 }
364
365 base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir(
366 const base::FilePath::StringType& relative_path) {
367 if (relative_path.empty())
368 return base::FilePath();
369 base::FilePath full_path(test_download_dir().Append(relative_path));
370 return full_path.NormalizePathSeparators();
371 }
372
373 void DownloadTargetDeterminerTest::RunTestCase(
374 const DownloadTestCase& test_case,
375 content::MockDownloadItem* item) {
376 // Kick off the test.
377 base::WeakPtrFactory<DownloadTargetDeterminerTest> factory(this);
378 base::RunLoop run_loop;
379 DownloadTargetDeterminer::Start(
380 item, download_prefs_.get(), last_selected_directory_, delegate(),
381 base::Bind(&DownloadTargetDeterminerTest::DownloadTargetVerifier,
382 factory.GetWeakPtr(), run_loop.QuitClosure(), test_case));
383 run_loop.Run();
384 ::testing::Mock::VerifyAndClearExpectations(delegate());
385 }
386
387 void DownloadTargetDeterminerTest::RunTestCasesWithActiveItem(
388 const DownloadTestCase test_cases[],
389 size_t test_case_count) {
390 for (size_t i = 0; i < test_case_count; ++i) {
391 scoped_ptr<content::MockDownloadItem> item(
392 CreateActiveDownloadItem(i, test_cases[i]));
393 SCOPED_TRACE(testing::Message() << "Running test case " << i);
394 RunTestCase(test_cases[i], item.get());
395 }
396 }
397
398 void DownloadTargetDeterminerTest::DownloadTargetVerifier(
399 const base::Closure& closure,
400 const DownloadTestCase& test_case,
401 const base::FilePath& local_path,
402 DownloadItem::TargetDisposition disposition,
403 content::DownloadDangerType danger_type,
404 const base::FilePath& intermediate_path) {
405 base::FilePath expected_local_path(
406 GetPathInDownloadDir(test_case.expected_local_path));
407 EXPECT_EQ(expected_local_path.value(), local_path.value());
408 EXPECT_EQ(test_case.expected_disposition, disposition);
409 EXPECT_EQ(test_case.expected_danger_type, danger_type);
410
411 switch (test_case.expected_intermediate) {
412 case EXPECT_CRDOWNLOAD:
413 EXPECT_EQ(download_util::GetCrDownloadPath(local_path).value(),
414 intermediate_path.value());
415 break;
416
417 case EXPECT_UNCONFIRMED:
418 // The paths (in English) look like: /path/Unconfirmed xxx.crdownload.
419 // Of this, we only check that the path is:
420 // 1. Not "/path/target.crdownload",
421 // 2. Points to the same directory as the target.
422 // 3. Has extension ".crdownload".
423 // 4. Basename starts with "Unconfirmed ".
424 EXPECT_NE(download_util::GetCrDownloadPath(expected_local_path).value(),
425 intermediate_path.value());
426 EXPECT_EQ(expected_local_path.DirName().value(),
427 intermediate_path.DirName().value());
428 EXPECT_TRUE(intermediate_path.MatchesExtension(
429 FILE_PATH_LITERAL(".crdownload")));
430 EXPECT_EQ(0u, intermediate_path.BaseName().value().find(
431 FILE_PATH_LITERAL("Unconfirmed ")));
432 break;
433
434 case EXPECT_LOCAL_PATH:
435 EXPECT_EQ(expected_local_path.value(), intermediate_path.value());
436 break;
437 }
438 base::MessageLoop::current()->PostTask(FROM_HERE, closure);
439 }
440
441 // static
442 void MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath(
443 DownloadItem* download,
444 const base::FilePath& virtual_path,
445 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
446 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
447 callback.Run(virtual_path, true);
448 }
449
450 // static
451 void MockDownloadTargetDeterminerDelegate::NullPromptUser(
452 DownloadItem* download, const base::FilePath& suggested_path,
453 const FileSelectedCallback& callback) {
454 callback.Run(suggested_path);
455 }
456
457 // static
458 void MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath(
459 DownloadItem* download, const base::FilePath& virtual_path,
460 const LocalPathCallback& callback) {
461 callback.Run(virtual_path);
462 }
463
464 // NotifyExtensions implementation that overrides the path so that the target
465 // file is in a subdirectory called 'overridden'. If the extension is '.remove',
466 // the extension is removed.
467 void NotifyExtensionsOverridePath(
468 content::DownloadItem* download,
469 const base::FilePath& path,
470 const DownloadTargetDeterminerDelegate::NotifyExtensionsCallback&
471 callback) {
472 base::FilePath new_path =
473 base::FilePath()
474 .AppendASCII("overridden")
475 .Append(path.BaseName());
476 if (new_path.MatchesExtension(FILE_PATH_LITERAL(".remove")))
477 new_path = new_path.RemoveExtension();
478 callback.Run(new_path, DownloadPathReservationTracker::UNIQUIFY);
479 }
480
481 void CheckDownloadUrlCheckExes(
482 content::DownloadItem* download,
483 const base::FilePath& path,
484 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback&
485 callback) {
486 if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
487 callback.Run(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT);
488 else
489 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
490 }
491
492 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_Basic) {
493 const DownloadTestCase kBasicTestCases[] = {
494 {
495 // 0: Automatic Safe
496 AUTOMATIC,
497 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
498 "http://example.com/foo.txt", "text/plain",
499 FILE_PATH_LITERAL(""),
500
501 FILE_PATH_LITERAL(""),
502 FILE_PATH_LITERAL("foo.txt"),
503 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
504
505 EXPECT_CRDOWNLOAD
506 },
507
508 {
509 // 1: Save_As Safe
510 SAVE_AS,
511 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
512 "http://example.com/foo.txt", "text/plain",
513 FILE_PATH_LITERAL(""),
514
515 FILE_PATH_LITERAL(""),
516 FILE_PATH_LITERAL("foo.txt"),
517 DownloadItem::TARGET_DISPOSITION_PROMPT,
518
519 EXPECT_CRDOWNLOAD
520 },
521
522 {
523 // 2: Automatic Dangerous
524 AUTOMATIC,
525 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
526 "http://example.com/foo.html", "",
527 FILE_PATH_LITERAL(""),
528
529 FILE_PATH_LITERAL(""),
530 FILE_PATH_LITERAL("foo.html"),
531 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
532
533 EXPECT_UNCONFIRMED
534 },
535
536 {
537 // 3: Forced Safe
538 FORCED,
539 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
540 "http://example.com/foo.txt", "",
541 FILE_PATH_LITERAL("forced-foo.txt"),
542
543 FILE_PATH_LITERAL(""),
544 FILE_PATH_LITERAL("forced-foo.txt"),
545 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
546
547 EXPECT_LOCAL_PATH
548 },
549 };
550
551 // The test assumes that .html files have a danger level of
552 // AllowOnUserGesture.
553 ASSERT_EQ(download_util::AllowOnUserGesture,
554 download_util::GetFileDangerLevel(
555 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
556 RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
557 }
558
559 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_CancelSaveAs) {
560 const DownloadTestCase kCancelSaveAsTestCases[] = {
561 {
562 // 0: Save_As Safe, Cancelled.
563 SAVE_AS,
564 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
565 "http://example.com/foo.txt", "text/plain",
566 FILE_PATH_LITERAL(""),
567
568 FILE_PATH_LITERAL(""),
569 FILE_PATH_LITERAL(""),
570 DownloadItem::TARGET_DISPOSITION_PROMPT,
571
572 EXPECT_LOCAL_PATH
573 }
574 };
575 ON_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
576 .WillByDefault(WithArg<2>(ScheduleCallback(base::FilePath())));
577 RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
578 arraysize(kCancelSaveAsTestCases));
579 }
580
581 // The SafeBrowsing check is performed early. Make sure that a download item
582 // that has been marked as DANGEROUS_URL behaves correctly.
583 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DangerousUrl) {
584 const DownloadTestCase kSafeBrowsingTestCases[] = {
585 {
586 // 0: Automatic Dangerous URL
587 AUTOMATIC,
588 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
589 "http://phishing.example.com/foo.txt", "",
590 FILE_PATH_LITERAL(""),
591
592 FILE_PATH_LITERAL(""),
593 FILE_PATH_LITERAL("foo.txt"),
594 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
595
596 EXPECT_UNCONFIRMED
597 },
598
599 {
600 // 1: Save As Dangerous URL
601 SAVE_AS,
602 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
603 "http://phishing.example.com/foo.txt", "",
604 FILE_PATH_LITERAL(""),
605
606 FILE_PATH_LITERAL(""),
607 FILE_PATH_LITERAL("foo.txt"),
608 DownloadItem::TARGET_DISPOSITION_PROMPT,
609
610 EXPECT_UNCONFIRMED
611 },
612
613 {
614 // 2: Forced Dangerous URL
615 FORCED,
616 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
617 "http://phishing.example.com/foo.txt", "",
618 FILE_PATH_LITERAL("forced-foo.txt"),
619
620 FILE_PATH_LITERAL(""),
621 FILE_PATH_LITERAL("forced-foo.txt"),
622 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
623
624 EXPECT_UNCONFIRMED
625 },
626
627 {
628 // 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes
629 // precendence.
630 AUTOMATIC,
631 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
632 "http://phishing.example.com/foo.html", "",
633 FILE_PATH_LITERAL(""),
634
635 FILE_PATH_LITERAL(""),
636 FILE_PATH_LITERAL("foo.html"),
637 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
638
639 EXPECT_UNCONFIRMED
640 },
641
642 {
643 // 4: Save As Dangerous URL + Dangerous file
644 SAVE_AS,
645 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
646 "http://phishing.example.com/foo.html", "",
647 FILE_PATH_LITERAL(""),
648
649 FILE_PATH_LITERAL(""),
650 FILE_PATH_LITERAL("foo.html"),
651 DownloadItem::TARGET_DISPOSITION_PROMPT,
652
653 EXPECT_UNCONFIRMED
654 },
655
656 {
657 // 5: Forced Dangerous URL + Dangerous file
658 FORCED,
659 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
660 "http://phishing.example.com/foo.html", "",
661 FILE_PATH_LITERAL("forced-foo.html"),
662
663 FILE_PATH_LITERAL(""),
664 FILE_PATH_LITERAL("forced-foo.html"),
665 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
666
667 EXPECT_UNCONFIRMED
668 },
669 };
670
671 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
672 .WillByDefault(WithArg<2>(ScheduleCallback(
673 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
674 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
675 arraysize(kSafeBrowsingTestCases));
676 }
677
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[] = {
682 {
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(""),
688
689 FILE_PATH_LITERAL(""),
690 FILE_PATH_LITERAL("foo.exe"),
691 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
692
693 EXPECT_UNCONFIRMED
694 },
695
696 {
697 // 1: Save As Maybe dangerous content
698 SAVE_AS,
699 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
700 "http://phishing.example.com/foo.exe", "",
701 FILE_PATH_LITERAL(""),
702
703 FILE_PATH_LITERAL(""),
704 FILE_PATH_LITERAL("foo.exe"),
705 DownloadItem::TARGET_DISPOSITION_PROMPT,
706
707 EXPECT_UNCONFIRMED
708 },
709
710 {
711 // 2: Forced Maybe dangerous content
712 FORCED,
713 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
714 "http://phishing.example.com/foo.exe", "",
715 FILE_PATH_LITERAL("forced-foo.exe"),
716
717 FILE_PATH_LITERAL(""),
718 FILE_PATH_LITERAL("forced-foo.exe"),
719 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
720
721 EXPECT_UNCONFIRMED
722 },
723 };
724
725 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
726 .WillByDefault(WithArg<2>(ScheduleCallback(
727 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
728 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
729 arraysize(kSafeBrowsingTestCases));
730 }
731
732 // Test whether the last saved directory is used for 'Save As' downloads.
733 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LastSavePath) {
734 const DownloadTestCase kLastSavePathTestCasesPre[] = {
735 {
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(""),
742
743 FILE_PATH_LITERAL(""),
744 FILE_PATH_LITERAL("foo.txt"),
745 DownloadItem::TARGET_DISPOSITION_PROMPT,
746
747 EXPECT_CRDOWNLOAD
748 }
749 };
750
751 // These test cases are run with a last save path set to a non-emtpy local
752 // download directory.
753 const DownloadTestCase kLastSavePathTestCasesPost[] = {
754 {
755 // 0: This test case is run with the last download directory set to
756 // '<test_download_dir()>/foo'.
757 SAVE_AS,
758 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
759 "http://example.com/foo.txt", "text/plain",
760 FILE_PATH_LITERAL(""),
761
762 FILE_PATH_LITERAL(""),
763 FILE_PATH_LITERAL("foo/foo.txt"),
764 DownloadItem::TARGET_DISPOSITION_PROMPT,
765
766 EXPECT_CRDOWNLOAD
767 },
768
769 {
770 // 1: Start an automatic download. This should be saved to the user's
771 // default download directory and not the last used Save As directory.
772 AUTOMATIC,
773 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
774 "http://example.com/foo.txt", "text/plain",
775 FILE_PATH_LITERAL(""),
776
777 FILE_PATH_LITERAL(""),
778 FILE_PATH_LITERAL("foo.txt"),
779 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
780
781 EXPECT_CRDOWNLOAD
782 },
783 };
784
785 // This test case is run with the last save path set to a non-empty virtual
786 // directory.
787 const DownloadTestCase kLastSavePathTestCasesVirtual[] = {
788 {
789 SAVE_AS,
790 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
791 "http://example.com/foo.txt", "text/plain",
792 FILE_PATH_LITERAL(""),
793
794 FILE_PATH_LITERAL("virtual/foo/foo.txt"),
795 FILE_PATH_LITERAL("bar.txt"),
796 DownloadItem::TARGET_DISPOSITION_PROMPT,
797
798 EXPECT_LOCAL_PATH
799 },
800 };
801
802 {
803 SCOPED_TRACE(testing::Message()
804 << "Running with empty last_selected_directory");
805 base::FilePath prompt_path =
806 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
807 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
808 RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
809 arraysize(kLastSavePathTestCasesPre));
810 }
811
812 // Try with a non-empty last save path.
813 {
814 SCOPED_TRACE(testing::Message()
815 << "Running with local last_selected_directory");
816 set_last_selected_directory(test_download_dir().AppendASCII("foo"));
817 base::FilePath prompt_path =
818 GetPathInDownloadDir(FILE_PATH_LITERAL("foo/foo.txt"));
819 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
820 RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
821 arraysize(kLastSavePathTestCasesPost));
822 }
823
824 // And again, but this time use a virtual directory.
825 {
826 SCOPED_TRACE(testing::Message()
827 << "Running with virtual last_selected_directory");
828 base::FilePath last_selected_dir = test_virtual_dir().AppendASCII("foo");
829 base::FilePath virtual_path = last_selected_dir.AppendASCII("foo.txt");
830 set_last_selected_directory(last_selected_dir);
831 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
832 _, last_selected_dir.AppendASCII("foo.txt"), _));
833 EXPECT_CALL(*delegate(), DetermineLocalPath(_, virtual_path, _))
834 .WillOnce(WithArg<2>(ScheduleCallback(
835 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")))));
836 RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
837 arraysize(kLastSavePathTestCasesVirtual));
838 }
839 }
840
841 // These tests are run with the default downloads folder set to a virtual
842 // directory.
843 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DefaultVirtual) {
844 // The default download directory is the virutal path.
845 SetDefaultDownloadPath(test_virtual_dir());
846
847 {
848 SCOPED_TRACE(testing::Message() << "Automatic Safe Download");
849 const DownloadTestCase kAutomaticDownloadToVirtualDir = {
850 AUTOMATIC,
851 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
852 "http://example.com/foo.txt", "text/plain",
853 FILE_PATH_LITERAL(""),
854
855 // Downloaded to default virtual directory.
856 FILE_PATH_LITERAL("virtual/foo.txt"),
857 FILE_PATH_LITERAL("foo-local.txt"),
858 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
859
860 EXPECT_LOCAL_PATH
861 };
862 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
863 .WillOnce(WithArg<2>(ScheduleCallback(
864 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
865 RunTestCasesWithActiveItem(&kAutomaticDownloadToVirtualDir, 1);
866 }
867
868 {
869 SCOPED_TRACE(testing::Message() << "Save As to virtual directory");
870 const DownloadTestCase kSaveAsToVirtualDir = {
871 SAVE_AS,
872 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
873 "http://example.com/bar.txt", "text/plain",
874 FILE_PATH_LITERAL(""),
875
876 // The response to the download prompt is to choose the 'prompted.txt'
877 // virtual path.
878 FILE_PATH_LITERAL("virtual/prompted.txt"),
879 FILE_PATH_LITERAL("foo-local.txt"),
880 DownloadItem::TARGET_DISPOSITION_PROMPT,
881
882 EXPECT_LOCAL_PATH
883 };
884 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
885 .WillOnce(WithArg<2>(ScheduleCallback(
886 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
887 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
888 _, test_virtual_dir().AppendASCII("bar.txt"), _))
889 .WillOnce(WithArg<2>(ScheduleCallback(
890 test_virtual_dir().AppendASCII("prompted.txt"))));
891 RunTestCasesWithActiveItem(&kSaveAsToVirtualDir, 1);
892 }
893
894 {
895 SCOPED_TRACE(testing::Message() << "Save As to local directory");
896 const DownloadTestCase kSaveAsToLocalDir = {
897 SAVE_AS,
898 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
899 "http://example.com/bar.txt", "text/plain",
900 FILE_PATH_LITERAL(""),
901
902 // Response to the 'Save As' is to choose the local path for 'foo-x.txt'.
903 FILE_PATH_LITERAL(""),
904 FILE_PATH_LITERAL("foo-x.txt"),
905 DownloadItem::TARGET_DISPOSITION_PROMPT,
906
907 EXPECT_CRDOWNLOAD
908 };
909 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
910 _, test_virtual_dir().AppendASCII("bar.txt"), _))
911 .WillOnce(WithArg<2>(ScheduleCallback(
912 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")))));
913 RunTestCasesWithActiveItem(&kSaveAsToLocalDir, 1);
914 }
915
916 {
917 SCOPED_TRACE(testing::Message() << "Forced safe download");
918 const DownloadTestCase kForcedSafe = {
919 FORCED,
920 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
921 "http://example.com/foo.txt", "",
922 FILE_PATH_LITERAL("forced-foo.txt"),
923
924 // Forced paths should be left as-is.
925 FILE_PATH_LITERAL(""),
926 FILE_PATH_LITERAL("forced-foo.txt"),
927 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
928
929 EXPECT_LOCAL_PATH
930 };
931 RunTestCasesWithActiveItem(&kForcedSafe, 1);
932 }
933 }
934
935 // Test that an inactive download will still get a virtual or local download
936 // path.
937 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_InactiveDownload) {
938 const DownloadTestCase kInactiveTestCases[] = {
939 {
940 AUTOMATIC,
941 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
942 "http://example.com/foo.txt", "text/plain",
943 FILE_PATH_LITERAL(""),
944
945 FILE_PATH_LITERAL("foo.txt"),
946 FILE_PATH_LITERAL(""),
947 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
948
949 EXPECT_LOCAL_PATH
950 },
951
952 {
953 SAVE_AS,
954 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
955 "http://example.com/foo.txt", "text/plain",
956 FILE_PATH_LITERAL(""),
957
958 FILE_PATH_LITERAL("foo.txt"),
959 FILE_PATH_LITERAL(""),
960 DownloadItem::TARGET_DISPOSITION_PROMPT,
961
962 EXPECT_LOCAL_PATH
963 }
964 };
965
966 for (size_t i = 0; i < arraysize(kInactiveTestCases); ++i) {
967 SCOPED_TRACE(testing::Message() << "Running test case " << i);
968 const DownloadTestCase& test_case = kInactiveTestCases[i];
969 scoped_ptr<content::MockDownloadItem> item(
970 CreateActiveDownloadItem(i, test_case));
971 EXPECT_CALL(*item.get(), IsInProgress())
972 .WillRepeatedly(Return(false));
973 // Even though one is a SAVE_AS download, no prompt will be displayed to
974 // the user because the download is inactive.
975 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
976 .Times(0);
977 RunTestCase(kInactiveTestCases[i], item.get());
978 }
979 }
980
981 // If the reserved path could not be verified, then the user should see a
982 // prompt.
983 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ReservationFailed) {
984 const DownloadTestCase kReservationFailedCases[] = {
985 {
986 // 0: Automatic download. Since the reservation fails, the disposition of
987 // the target is to prompt, but the returned path is used.
988 AUTOMATIC,
989 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
990 "http://example.com/foo.txt", "text/plain",
991 FILE_PATH_LITERAL(""),
992
993 FILE_PATH_LITERAL(""),
994 FILE_PATH_LITERAL("bar.txt"),
995 DownloadItem::TARGET_DISPOSITION_PROMPT,
996
997 EXPECT_CRDOWNLOAD
998 },
999 };
1000
1001 // Setup ReserveVirtualPath() to fail.
1002 ON_CALL(*delegate(), ReserveVirtualPath(_, _, _, _))
1003 .WillByDefault(WithArg<3>(ScheduleCallback2(
1004 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")), false)));
1005 RunTestCasesWithActiveItem(kReservationFailedCases,
1006 arraysize(kReservationFailedCases));
1007 }
1008
1009 // If the local path could not be determined, the download should be cancelled.
1010 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LocalPathFailed) {
1011 const DownloadTestCase kLocalPathFailedCases[] = {
1012 {
1013 // 0: Automatic download.
1014 AUTOMATIC,
1015 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1016 "http://example.com/foo.txt", "text/plain",
1017 FILE_PATH_LITERAL(""),
1018
1019 FILE_PATH_LITERAL(""),
1020 FILE_PATH_LITERAL(""),
1021 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1022
1023 EXPECT_LOCAL_PATH
1024 },
1025 };
1026
1027 base::FilePath expected_virtual_path(
1028 GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")));
1029 // The default download directory is the virtual path.
1030 SetDefaultDownloadPath(test_virtual_dir());
1031 // Simulate failed call to DetermineLocalPath.
1032 EXPECT_CALL(*delegate(), DetermineLocalPath(
1033 _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
1034 .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
1035 RunTestCasesWithActiveItem(kLocalPathFailedCases,
1036 arraysize(kLocalPathFailedCases));
1037 }
1038
1039 // Downloads that have a danger level of AllowOnUserGesture should be marked as
1040 // safe depending on whether there was a user gesture associated with the
1041 // download and whether the referrer was visited prior to today.
1042 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_VisitedReferrer) {
1043 const DownloadTestCase kVisitedReferrerCases[] = {
1044 // http://visited.example.com/ is added to the history as a visit that
1045 // happened prior to today.
1046 {
1047 // 0: Safe download due to visiting referrer before.
1048 AUTOMATIC,
1049 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1050 "http://visited.example.com/foo.html", "text/html",
1051 FILE_PATH_LITERAL(""),
1052
1053 FILE_PATH_LITERAL(""),
1054 FILE_PATH_LITERAL("foo.html"),
1055 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1056
1057 EXPECT_CRDOWNLOAD
1058 },
1059
1060 {
1061 // 1: Dangerous due to not having visited referrer before.
1062 AUTOMATIC,
1063 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1064 "http://not-visited.example.com/foo.html", "text/html",
1065 FILE_PATH_LITERAL(""),
1066
1067 FILE_PATH_LITERAL(""),
1068 FILE_PATH_LITERAL("foo.html"),
1069 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1070
1071 EXPECT_UNCONFIRMED
1072 },
1073
1074 {
1075 // 2: Safe because the user is being prompted.
1076 SAVE_AS,
1077 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1078 "http://not-visited.example.com/foo.html", "text/html",
1079 FILE_PATH_LITERAL(""),
1080
1081 FILE_PATH_LITERAL(""),
1082 FILE_PATH_LITERAL("foo.html"),
1083 DownloadItem::TARGET_DISPOSITION_PROMPT,
1084
1085 EXPECT_CRDOWNLOAD
1086 },
1087
1088 {
1089 // 3: Safe because of forced path.
1090 FORCED,
1091 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1092 "http://not-visited.example.com/foo.html", "text/html",
1093 FILE_PATH_LITERAL("foo.html"),
1094
1095 FILE_PATH_LITERAL(""),
1096 FILE_PATH_LITERAL("foo.html"),
1097 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1098
1099 EXPECT_LOCAL_PATH
1100 },
1101 };
1102
1103 // This test assumes that the danger level of .html files is
1104 // AllowOnUserGesture.
1105 ASSERT_EQ(download_util::AllowOnUserGesture,
1106 download_util::GetFileDangerLevel(
1107 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
1108
1109 // First the history service must exist.
1110 profile()->CreateHistoryService(false, false);
1111
1112 GURL url("http://visited.example.com/visited-link.html");
1113 // The time of visit is picked to be several seconds prior to the most recent
1114 // midnight.
1115 base::Time time_of_visit(
1116 base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(10));
1117 HistoryService* history_service =
1118 HistoryServiceFactory::GetForProfile(profile(), Profile::EXPLICIT_ACCESS);
1119 ASSERT_TRUE(history_service);
1120 history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
1121
1122 RunTestCasesWithActiveItem(kVisitedReferrerCases,
1123 arraysize(kVisitedReferrerCases));
1124 }
1125
1126 // These test cases are run with "Prompt for download" user preference set to
1127 // true.
1128 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways) {
1129 const DownloadTestCase kPromptingTestCases[] = {
1130 {
1131 // 0: Safe Automatic - Should prompt because of "Prompt for download"
1132 // preference setting.
1133 AUTOMATIC,
1134 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1135 "http://example.com/foo.txt", "text/plain",
1136 FILE_PATH_LITERAL(""),
1137
1138 FILE_PATH_LITERAL(""),
1139 FILE_PATH_LITERAL("foo.txt"),
1140 DownloadItem::TARGET_DISPOSITION_PROMPT,
1141
1142 EXPECT_CRDOWNLOAD
1143 },
1144
1145 {
1146 // 1: Safe Forced - Shouldn't prompt.
1147 FORCED,
1148 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1149 "http://example.com/foo.txt", "text/plain",
1150 FILE_PATH_LITERAL("foo.txt"),
1151
1152 FILE_PATH_LITERAL(""),
1153 FILE_PATH_LITERAL("foo.txt"),
1154 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1155
1156 EXPECT_LOCAL_PATH
1157 },
1158
1159 {
1160 // 2: Automatic - The filename extension is marked as one that we will
1161 // open automatically. Shouldn't prompt.
1162 AUTOMATIC,
1163 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1164 "http://example.com/foo.dummy", "",
1165 FILE_PATH_LITERAL(""),
1166
1167 FILE_PATH_LITERAL(""),
1168 FILE_PATH_LITERAL("foo.dummy"),
1169 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1170
1171 EXPECT_CRDOWNLOAD
1172 },
1173 };
1174
1175 SetPromptForDownload(true);
1176 EnableAutoOpenBasedOnExtension(
1177 base::FilePath(FILE_PATH_LITERAL("dummy.dummy")));
1178 RunTestCasesWithActiveItem(kPromptingTestCases,
1179 arraysize(kPromptingTestCases));
1180 }
1181
1182 #if !defined(OS_ANDROID)
1183 // These test cases are run with "Prompt for download" user preference set to
1184 // true. Automatic extension downloads shouldn't cause prompting.
1185 // Android doesn't support extensions.
1186 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways_Extension) {
1187 const DownloadTestCase kPromptingTestCases[] = {
1188 {
1189 // 0: Automatic Browser Extension download. - Shouldn't prompt for browser
1190 // extension downloads even if "Prompt for download" preference is set.
1191 AUTOMATIC,
1192 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1193 "http://example.com/foo.crx",
1194 extensions::Extension::kMimeType,
1195 FILE_PATH_LITERAL(""),
1196
1197 FILE_PATH_LITERAL(""),
1198 FILE_PATH_LITERAL("foo.crx"),
1199 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1200
1201 EXPECT_UNCONFIRMED
1202 },
1203
1204 #if defined(OS_WIN)
1205 {
1206 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1207 // even if "Prompt for download" preference is set. ".js" files are
1208 // considered dangerous on Windows.
1209 AUTOMATIC,
1210 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1211 "http://example.com/foo.user.js", "",
1212 FILE_PATH_LITERAL(""),
1213
1214 FILE_PATH_LITERAL(""),
1215 FILE_PATH_LITERAL("foo.user.js"),
1216 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1217
1218 EXPECT_UNCONFIRMED
1219 },
1220 #else
1221 {
1222 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1223 // even if "Prompt for download" preference is set.
1224 AUTOMATIC,
1225 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1226 "http://example.com/foo.user.js", "",
1227 FILE_PATH_LITERAL(""),
1228
1229 FILE_PATH_LITERAL(""),
1230 FILE_PATH_LITERAL("foo.user.js"),
1231 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1232
1233 EXPECT_CRDOWNLOAD
1234 },
1235 #endif
1236 };
1237
1238 SetPromptForDownload(true);
1239 RunTestCasesWithActiveItem(kPromptingTestCases,
1240 arraysize(kPromptingTestCases));
1241 }
1242 #endif
1243
1244 // If the download path is managed, then we don't show any prompts.
1245 // Note that if the download path is managed, then PromptForDownload() is false.
1246 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ManagedPath) {
1247 const DownloadTestCase kManagedPathTestCases[] = {
1248 {
1249 // 0: Automatic Safe
1250 AUTOMATIC,
1251 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1252 "http://example.com/foo.txt", "text/plain",
1253 FILE_PATH_LITERAL(""),
1254
1255 FILE_PATH_LITERAL(""),
1256 FILE_PATH_LITERAL("foo.txt"),
1257 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1258
1259 EXPECT_CRDOWNLOAD
1260 },
1261
1262 {
1263 // 1: Save_As Safe
1264 SAVE_AS,
1265 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1266 "http://example.com/foo.txt", "text/plain",
1267 FILE_PATH_LITERAL(""),
1268
1269 FILE_PATH_LITERAL(""),
1270 FILE_PATH_LITERAL("foo.txt"),
1271 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1272
1273 EXPECT_CRDOWNLOAD
1274 },
1275 };
1276
1277 SetManagedDownloadPath(test_download_dir());
1278 ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
1279 RunTestCasesWithActiveItem(kManagedPathTestCases,
1280 arraysize(kManagedPathTestCases));
1281 }
1282
1283 // Test basic functionality supporting extensions that want to override download
1284 // filenames.
1285 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsSafe) {
1286 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1287 {
1288 // 0: Automatic Safe
1289 AUTOMATIC,
1290 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1291 "http://example.com/foo.txt", "text/plain",
1292 FILE_PATH_LITERAL(""),
1293
1294 FILE_PATH_LITERAL(""),
1295 FILE_PATH_LITERAL("overridden/foo.txt"),
1296 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1297
1298 EXPECT_CRDOWNLOAD
1299 },
1300
1301 {
1302 // 1: Save_As Safe
1303 SAVE_AS,
1304 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1305 "http://example.com/foo.txt", "text/plain",
1306 FILE_PATH_LITERAL(""),
1307
1308 FILE_PATH_LITERAL(""),
1309 FILE_PATH_LITERAL("overridden/foo.txt"),
1310 DownloadItem::TARGET_DISPOSITION_PROMPT,
1311
1312 EXPECT_CRDOWNLOAD
1313 },
1314
1315 {
1316 // 2: Automatic Dangerous
1317 AUTOMATIC,
1318 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1319 "http://example.com/foo.html", "",
1320 FILE_PATH_LITERAL(""),
1321
1322 FILE_PATH_LITERAL(""),
1323 FILE_PATH_LITERAL("overridden/foo.html"),
1324 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1325
1326 EXPECT_UNCONFIRMED
1327 },
1328
1329 {
1330 // 3: Forced Safe
1331 FORCED,
1332 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1333 "http://example.com/foo.txt", "",
1334 FILE_PATH_LITERAL("forced-foo.txt"),
1335
1336 FILE_PATH_LITERAL(""),
1337 FILE_PATH_LITERAL("forced-foo.txt"),
1338 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1339
1340 EXPECT_LOCAL_PATH
1341 },
1342 };
1343
1344 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1345 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1346 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1347 arraysize(kNotifyExtensionsTestCases));
1348 }
1349
1350 // Test that filenames provided by extensions are passed into SafeBrowsing
1351 // checks and dangerous download checks.
1352 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsUnsafe) {
1353 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1354 {
1355 // 0: Automatic Safe : Later overridden by a dangerous filetype.
1356 AUTOMATIC,
1357 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1358 "http://example.com/foo.html.remove", "text/plain",
1359 FILE_PATH_LITERAL(""),
1360
1361 FILE_PATH_LITERAL(""),
1362 FILE_PATH_LITERAL("overridden/foo.html"),
1363 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1364
1365 EXPECT_UNCONFIRMED
1366 },
1367
1368 {
1369 // 1: Automatic Safe : Later overridden by a potentially dangerous
1370 // filetype.
1371 AUTOMATIC,
1372 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
1373 "http://example.com/foo.exe.remove", "text/plain",
1374 FILE_PATH_LITERAL(""),
1375
1376 FILE_PATH_LITERAL(""),
1377 FILE_PATH_LITERAL("overridden/foo.exe"),
1378 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1379
1380 EXPECT_UNCONFIRMED
1381 },
1382 };
1383
1384 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1385 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1386 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
1387 .WillByDefault(Invoke(&CheckDownloadUrlCheckExes));
1388 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1389 arraysize(kNotifyExtensionsTestCases));
1390 }
1391
1392 // Test that conflict actions set by extensions are passed correctly into
1393 // ReserveVirtualPath.
1394 TEST_F(DownloadTargetDeterminerTest,
1395 TargetDeterminer_NotifyExtensionsConflict) {
1396 const DownloadTestCase kNotifyExtensionsTestCase = {
1397 AUTOMATIC,
1398 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1399 "http://example.com/foo.txt", "text/plain",
1400 FILE_PATH_LITERAL(""),
1401
1402 FILE_PATH_LITERAL(""),
1403 FILE_PATH_LITERAL("overridden/foo.txt"),
1404 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1405
1406 EXPECT_CRDOWNLOAD
1407 };
1408
1409 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1410 scoped_ptr<content::MockDownloadItem> item(
1411 CreateActiveDownloadItem(0, test_case));
1412 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1413 base::FilePath full_overridden_path =
1414 GetPathInDownloadDir(overridden_path.value());
1415
1416 // First case: An extension sets the conflict_action to OVERWRITE.
1417 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1418 .WillOnce(WithArg<2>(
1419 ScheduleCallback2(overridden_path,
1420 DownloadPathReservationTracker::OVERWRITE)));
1421 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1422 _, full_overridden_path, DownloadPathReservationTracker::OVERWRITE, _))
1423 .WillOnce(WithArg<3>(
1424 ScheduleCallback2(full_overridden_path, true)));
1425
1426 RunTestCase(test_case, item.get());
1427
1428 // Second case: An extension sets the conflict_action to PROMPT.
1429 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1430 .WillOnce(WithArg<2>(
1431 ScheduleCallback2(overridden_path,
1432 DownloadPathReservationTracker::PROMPT)));
1433 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1434 _, full_overridden_path, DownloadPathReservationTracker::PROMPT, _))
1435 .WillOnce(WithArg<3>(
1436 ScheduleCallback2(full_overridden_path, true)));
1437 RunTestCase(test_case, item.get());
1438 }
1439
1440 // Test that relative paths returned by extensions are always relative to the
1441 // default downloads path.
1442 TEST_F(DownloadTargetDeterminerTest,
1443 TargetDeterminer_NotifyExtensionsDefaultPath) {
1444 const DownloadTestCase kNotifyExtensionsTestCase = {
1445 SAVE_AS,
1446 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1447 "http://example.com/foo.txt", "text/plain",
1448 FILE_PATH_LITERAL(""),
1449
1450 FILE_PATH_LITERAL(""),
1451 FILE_PATH_LITERAL("overridden/foo.txt"),
1452 DownloadItem::TARGET_DISPOSITION_PROMPT,
1453
1454 EXPECT_CRDOWNLOAD
1455 };
1456
1457 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1458 scoped_ptr<content::MockDownloadItem> item(
1459 CreateActiveDownloadItem(0, test_case));
1460 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1461 base::FilePath full_overridden_path =
1462 GetPathInDownloadDir(overridden_path.value());
1463
1464 // The last selected directory is this one. Since the test case is a SAVE_AS
1465 // download, it should use this directory for the generated path.
1466 set_last_selected_directory(GetPathInDownloadDir(
1467 FILE_PATH_LITERAL("last_selected")));
1468
1469 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1470 .WillOnce(WithArg<2>(
1471 ScheduleCallback2(overridden_path,
1472 DownloadPathReservationTracker::UNIQUIFY)));
1473 EXPECT_CALL(*delegate(),
1474 PromptUserForDownloadPath(_, full_overridden_path, _))
1475 .WillOnce(WithArg<2>(
1476 ScheduleCallback(full_overridden_path)));
1477 RunTestCase(test_case, item.get());
1478 }
1479 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698