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

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

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

Powered by Google App Engine
This is Rietveld 408576698