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

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: Address comments. 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/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 // 4. Basename starts with "Unconfirmed ".
447 EXPECT_NE(download_util::GetCrDownloadPath(expected_local_path).value(),
448 intermediate_path.value());
449 EXPECT_EQ(expected_local_path.DirName().value(),
450 intermediate_path.DirName().value());
451 EXPECT_TRUE(intermediate_path.MatchesExtension(
452 FILE_PATH_LITERAL(".crdownload")));
453 EXPECT_EQ(0u, intermediate_path.BaseName().value().find(
454 FILE_PATH_LITERAL("Unconfirmed ")));
455 break;
456
457 case EXPECT_LOCAL_PATH:
458 EXPECT_EQ(expected_local_path.value(), intermediate_path.value());
459 break;
460 }
461 }
462
463 // static
464 void MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath(
465 DownloadItem* download,
466 const base::FilePath& virtual_path,
467 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
468 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
469 callback.Run(virtual_path, true);
470 }
471
472 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_Basic) {
473 const DownloadTestCase kBasicTestCases[] = {
474 {
475 // 0: Automatic Safe
476 AUTOMATIC,
477 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
478 "http://example.com/foo.txt", "text/plain",
479 FILE_PATH_LITERAL(""),
480
481 FILE_PATH_LITERAL(""),
482 FILE_PATH_LITERAL("foo.txt"),
483 FILE_PATH_LITERAL("foo.txt"),
484 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
485
486 EXPECT_CRDOWNLOAD
487 },
488
489 {
490 // 1: Save_As Safe
491 SAVE_AS,
492 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
493 "http://example.com/foo.txt", "text/plain",
494 FILE_PATH_LITERAL(""),
495
496 FILE_PATH_LITERAL(""),
497 FILE_PATH_LITERAL("foo.txt"),
498 FILE_PATH_LITERAL("foo.txt"),
499 DownloadItem::TARGET_DISPOSITION_PROMPT,
500
501 EXPECT_CRDOWNLOAD
502 },
503
504 {
505 // 2: Automatic Dangerous
506 AUTOMATIC,
507 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
508 "http://example.com/foo.html", "",
509 FILE_PATH_LITERAL(""),
510
511 FILE_PATH_LITERAL(""),
512 FILE_PATH_LITERAL("foo.html"),
513 FILE_PATH_LITERAL("foo.html"),
514 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
515
516 EXPECT_UNCONFIRMED
517 },
518
519 {
520 // 3: Forced Safe
521 FORCED,
522 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
523 "http://example.com/foo.txt", "",
524 FILE_PATH_LITERAL("forced-foo.txt"),
525
526 FILE_PATH_LITERAL(""),
527 FILE_PATH_LITERAL("forced-foo.txt"),
528 FILE_PATH_LITERAL("forced-foo.txt"),
529 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
530
531 EXPECT_LOCAL_PATH
532 },
533 };
534
535 // The test assumes that .html files have a danger level of
536 // AllowOnUserGesture.
537 ASSERT_EQ(download_util::AllowOnUserGesture,
538 download_util::GetFileDangerLevel(
539 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
540 RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
541 }
542
543 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_CancelSaveAs) {
544 const DownloadTestCase kCancelSaveAsTestCases[] = {
545 {
546 // 0: Save_As Safe, Cancelled.
547 SAVE_AS,
548 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
549 "http://example.com/foo.txt", "text/plain",
550 FILE_PATH_LITERAL(""),
551
552 FILE_PATH_LITERAL(""),
553 FILE_PATH_LITERAL(""),
554 FILE_PATH_LITERAL("foo.txt"),
555 DownloadItem::TARGET_DISPOSITION_PROMPT,
556
557 EXPECT_LOCAL_PATH
558 }
559 };
560 RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
561 arraysize(kCancelSaveAsTestCases));
562 }
563
564 // The SafeBrowsing check is performed early. Make sure that a download item
565 // that has been marked as DANGEROUS_URL behaves correctly.
566 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DangerousUrl) {
567 const DownloadTestCase kSafeBrowsingTestCases[] = {
568 {
569 // 0: Automatic Dangerous URL
570 AUTOMATIC,
571 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
572 "http://phishing.example.com/foo.txt", "",
573 FILE_PATH_LITERAL(""),
574
575 FILE_PATH_LITERAL(""),
576 FILE_PATH_LITERAL("foo.txt"),
577 FILE_PATH_LITERAL("foo.txt"),
578 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
579
580 EXPECT_UNCONFIRMED
581 },
582
583 {
584 // 1: Save As Dangerous URL
585 SAVE_AS,
586 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
587 "http://phishing.example.com/foo.txt", "",
588 FILE_PATH_LITERAL(""),
589
590 FILE_PATH_LITERAL(""),
591 FILE_PATH_LITERAL("foo.txt"),
592 FILE_PATH_LITERAL("foo.txt"),
593 DownloadItem::TARGET_DISPOSITION_PROMPT,
594
595 EXPECT_UNCONFIRMED
596 },
597
598 {
599 // 2: Forced Dangerous URL
600 FORCED,
601 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
602 "http://phishing.example.com/foo.txt", "",
603 FILE_PATH_LITERAL("forced-foo.txt"),
604
605 FILE_PATH_LITERAL(""),
606 FILE_PATH_LITERAL("forced-foo.txt"),
607 FILE_PATH_LITERAL("forced-foo.txt"),
608 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
609
610 EXPECT_UNCONFIRMED
611 },
612
613 {
614 // 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes
615 // precendence.
616 AUTOMATIC,
617 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
618 "http://phishing.example.com/foo.html", "",
619 FILE_PATH_LITERAL(""),
620
621 FILE_PATH_LITERAL(""),
622 FILE_PATH_LITERAL("foo.html"),
623 FILE_PATH_LITERAL("foo.html"),
624 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
625
626 EXPECT_UNCONFIRMED
627 },
628
629 {
630 // 4: Save As Dangerous URL + Dangerous file
631 SAVE_AS,
632 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
633 "http://phishing.example.com/foo.html", "",
634 FILE_PATH_LITERAL(""),
635
636 FILE_PATH_LITERAL(""),
637 FILE_PATH_LITERAL("foo.html"),
638 FILE_PATH_LITERAL("foo.html"),
639 DownloadItem::TARGET_DISPOSITION_PROMPT,
640
641 EXPECT_UNCONFIRMED
642 },
643
644 {
645 // 5: Forced Dangerous URL + Dangerous file
646 FORCED,
647 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
648 "http://phishing.example.com/foo.html", "",
649 FILE_PATH_LITERAL("forced-foo.html"),
650
651 FILE_PATH_LITERAL(""),
652 FILE_PATH_LITERAL("forced-foo.html"),
653 FILE_PATH_LITERAL("forced-foo.html"),
654 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
655
656 EXPECT_UNCONFIRMED
657 },
658 };
659
660 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
661 .WillByDefault(WithArg<2>(ScheduleCallback(
662 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
663 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
664 arraysize(kSafeBrowsingTestCases));
665 }
666
667 // The SafeBrowsing check is performed early. Make sure that a download item
668 // that has been marked as MAYBE_DANGEROUS_CONTENT behaves correctly.
669 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_MaybeDangerousContent) {
670 const DownloadTestCase kSafeBrowsingTestCases[] = {
671 {
672 // 0: Automatic Maybe dangerous content
673 AUTOMATIC,
674 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
675 "http://phishing.example.com/foo.exe", "",
676 FILE_PATH_LITERAL(""),
677
678 FILE_PATH_LITERAL(""),
679 FILE_PATH_LITERAL("foo.exe"),
680 FILE_PATH_LITERAL("foo.exe"),
681 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
682
683 EXPECT_UNCONFIRMED
684 },
685
686 {
687 // 1: Save As Maybe dangerous content
688 SAVE_AS,
689 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
690 "http://phishing.example.com/foo.exe", "",
691 FILE_PATH_LITERAL(""),
692
693 FILE_PATH_LITERAL(""),
694 FILE_PATH_LITERAL("foo.exe"),
695 FILE_PATH_LITERAL("foo.exe"),
696 DownloadItem::TARGET_DISPOSITION_PROMPT,
697
698 EXPECT_UNCONFIRMED
699 },
700
701 {
702 // 2: Forced Maybe dangerous content
703 FORCED,
704 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
705 "http://phishing.example.com/foo.exe", "",
706 FILE_PATH_LITERAL("forced-foo.exe"),
707
708 FILE_PATH_LITERAL(""),
709 FILE_PATH_LITERAL("forced-foo.exe"),
710 FILE_PATH_LITERAL("forced-foo.exe"),
711 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
712
713 EXPECT_UNCONFIRMED
714 },
715 };
716
717 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
718 .WillByDefault(WithArg<2>(ScheduleCallback(
719 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
720 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
721 arraysize(kSafeBrowsingTestCases));
722 }
723
724 // Test whether the last saved directory is used for 'Save As' downloads.
725 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LastSavePath) {
726 const DownloadTestCase kLastSavePathTestCasesPre[] = {
727 {
728 // 0: If the last save path is empty, then the default download directory
729 // should be used.
730 SAVE_AS,
731 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
732 "http://example.com/foo.txt", "text/plain",
733 FILE_PATH_LITERAL(""),
734
735 FILE_PATH_LITERAL(""),
736 FILE_PATH_LITERAL("bar.txt"),
737 FILE_PATH_LITERAL("foo.txt"),
738 DownloadItem::TARGET_DISPOSITION_PROMPT,
739
740 EXPECT_CRDOWNLOAD
741 }
742 };
743
744 // These test cases are run with a last save path set to a non-emtpy local
745 // download directory.
746 const DownloadTestCase kLastSavePathTestCasesPost[] = {
747 {
748 // 0: This test case is run with the last download directory set to
749 // '<test_download_dir()>/foo'.
750 SAVE_AS,
751 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
752 "http://example.com/foo.txt", "text/plain",
753 FILE_PATH_LITERAL(""),
754
755 FILE_PATH_LITERAL(""),
756 FILE_PATH_LITERAL("foo/bar.txt"),
757 FILE_PATH_LITERAL("foo/foo.txt"),
758 DownloadItem::TARGET_DISPOSITION_PROMPT,
759
760 EXPECT_CRDOWNLOAD
761 },
762
763 {
764 // 1: Start an automatic download. This should be saved to the user's
765 // default download directory and not the last used Save As directory.
766 AUTOMATIC,
767 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
768 "http://example.com/foo.txt", "text/plain",
769 FILE_PATH_LITERAL(""),
770
771 FILE_PATH_LITERAL(""),
772 FILE_PATH_LITERAL("foo.txt"),
773 FILE_PATH_LITERAL("foo.txt"),
774 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
775
776 EXPECT_CRDOWNLOAD
777 },
778 };
779
780 // This test case is run with the last save path set to a non-empty virtual
781 // directory.
782 const DownloadTestCase kLastSavePathTestCasesVirtual[] = {
783 {
784 SAVE_AS,
785 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
786 "http://example.com/foo.txt", "text/plain",
787 FILE_PATH_LITERAL(""),
788
789 FILE_PATH_LITERAL("virtual/foo/foo.txt"),
790 FILE_PATH_LITERAL("foo/bar.txt"),
791 FILE_PATH_LITERAL("virtual/foo/foo.txt"),
792 DownloadItem::TARGET_DISPOSITION_PROMPT,
793
794 EXPECT_LOCAL_PATH
795 },
796 };
797
798 {
799 SCOPED_TRACE(testing::Message()
800 << "Running with empty last_selected_directory");
801 RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
802 arraysize(kLastSavePathTestCasesPre));
803 }
804
805 // Try with a non-empty last save path.
806 {
807 SCOPED_TRACE(testing::Message()
808 << "Running with local last_selected_directory");
809 set_last_selected_directory(test_download_dir().AppendASCII("foo"));
810 RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
811 arraysize(kLastSavePathTestCasesPost));
812 }
813
814 // And again, but this time use a virtual directory.
815 {
816 SCOPED_TRACE(testing::Message()
817 << "Running with virtual last_selected_directory");
818 set_last_selected_directory(test_virtual_dir().AppendASCII("foo"));
819 RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
820 arraysize(kLastSavePathTestCasesVirtual));
821 }
822 }
823
824 // These tests are run with the default downloads folder set to a virtual
825 // directory.
826 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DefaultVirtual) {
827 const DownloadTestCase kDefaultVirtualTestCases[] = {
828 {
829 // 0: Automatic Safe
830 AUTOMATIC,
831 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
832 "http://example.com/foo.txt", "text/plain",
833 FILE_PATH_LITERAL(""),
834
835 FILE_PATH_LITERAL("virtual/foo.txt"),
836 FILE_PATH_LITERAL("foo-local.txt"),
837 FILE_PATH_LITERAL("virtual/foo.txt"),
838 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
839
840 EXPECT_LOCAL_PATH
841 },
842
843 {
844 // 1: Save_As Safe.
845 SAVE_AS,
846 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
847 "http://example.com/foo.txt", "text/plain",
848 FILE_PATH_LITERAL(""),
849
850 // The response to the download prompt is to choose the 'foo.txt' virtual
851 // path. However, the virtual path shouldn't be passed through
852 // DetermineLocalPath(). So the 'foo-x.txt' local path should make it
853 // through without being modified.
854 FILE_PATH_LITERAL("virtual/foo.txt"),
855 FILE_PATH_LITERAL("foo-x.txt"),
856
857 // The last selected download path is empty. So 'Save As' should default
858 // to using the virtual path for the suggested path.
859 FILE_PATH_LITERAL("virtual/foo.txt"),
860
861 DownloadItem::TARGET_DISPOSITION_PROMPT,
862
863 EXPECT_LOCAL_PATH
864 },
865
866 {
867 // 2: Save_As Safe.
868 SAVE_AS,
869 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
870 "http://example.com/foo.txt", "text/plain",
871 FILE_PATH_LITERAL(""),
872
873 // Response to the 'Save As' is to choose the local path for 'foo-x.txt'.
874 FILE_PATH_LITERAL(""),
875 FILE_PATH_LITERAL("foo-x.txt"),
876
877 // The last selected download path is empty. So 'Save As' should default
878 // to using the virtual path for the suggested path.
879 FILE_PATH_LITERAL("virtual/foo.txt"),
880
881 DownloadItem::TARGET_DISPOSITION_PROMPT,
882
883 EXPECT_CRDOWNLOAD
884 },
885
886 {
887 // 3: Forced Safe. Doesn't override forced paths.
888 FORCED,
889 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
890 "http://example.com/foo.txt", "",
891 FILE_PATH_LITERAL("forced-foo.txt"),
892
893 FILE_PATH_LITERAL(""),
894 FILE_PATH_LITERAL("forced-foo.txt"),
895 FILE_PATH_LITERAL("forced-foo.txt"),
896 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
897
898 EXPECT_LOCAL_PATH
899 },
900 };
901
902 // The default download directory is the virutal path.
903 SetDefaultDownloadPath(test_virtual_dir());
904
905 RunTestCasesWithActiveItem(kDefaultVirtualTestCases,
906 arraysize(kDefaultVirtualTestCases));
907 }
908
909 // Test that an inactive download will still get a virtual or local download
910 // path.
911 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_InactiveDownload) {
912 const DownloadTestCase kInactiveTestCases[] = {
913 {
914 AUTOMATIC,
915 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
916 "http://example.com/foo.txt", "text/plain",
917 FILE_PATH_LITERAL(""),
918
919 FILE_PATH_LITERAL("foo.txt"),
920 FILE_PATH_LITERAL(""),
921 FILE_PATH_LITERAL(""),
922 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
923
924 EXPECT_LOCAL_PATH
925 },
926
927 {
928 SAVE_AS,
929 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
930 "http://example.com/foo.txt", "text/plain",
931 FILE_PATH_LITERAL(""),
932
933 FILE_PATH_LITERAL("foo.txt"),
934 FILE_PATH_LITERAL(""),
935 // Even though this is a SAVE_AS download, no prompt will be displayed to
936 // the user because the download is inactive.
937 FILE_PATH_LITERAL(""),
938 DownloadItem::TARGET_DISPOSITION_PROMPT,
939
940 EXPECT_LOCAL_PATH
941 }
942 };
943
944 for (size_t i = 0; i < arraysize(kInactiveTestCases); ++i) {
945 SCOPED_TRACE(testing::Message() << "Running test case " << i);
946 const DownloadTestCase& test_case = kInactiveTestCases[i];
947 scoped_ptr<content::MockDownloadItem> item(
948 CreateActiveDownloadItem(i, test_case));
949 EXPECT_CALL(*item.get(), IsInProgress())
950 .WillRepeatedly(Return(false));
951 SetUpDelegateExpectationsForInactiveItem();
952 RunTestCase(kInactiveTestCases[i], item.get());
953 }
954 }
955
956 // If the reserved path could not be verified, then the user should see a
957 // prompt.
958 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ReservationFailed) {
959 const DownloadTestCase kReservationFailedCases[] = {
960 {
961 // 0: Automatic download. Since the reservation fails, the disposition of
962 // the target is to prompt. Also the returned reserved path is ignored.
963 AUTOMATIC,
964 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
965 "http://example.com/foo.txt", "text/plain",
966 FILE_PATH_LITERAL(""),
967
968 FILE_PATH_LITERAL(""),
969 FILE_PATH_LITERAL("foo.txt"),
970 FILE_PATH_LITERAL("foo.txt"),
971 DownloadItem::TARGET_DISPOSITION_PROMPT,
972
973 EXPECT_CRDOWNLOAD
974 },
975 };
976
977 // Setup ReserveVirtualPath() to fail.
978 ON_CALL(*delegate(), ReserveVirtualPath(_, _, _, _))
979 .WillByDefault(WithArg<3>(ScheduleCallback2(
980 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")), false)));
981 RunTestCasesWithActiveItem(kReservationFailedCases,
982 arraysize(kReservationFailedCases));
983 }
984
985 // If the local path could not be determined, the download should be cancelled.
986 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LocalPathFailed) {
987 const DownloadTestCase kLocalPathFailedCases[] = {
988 {
989 // 0: Automatic download.
990 AUTOMATIC,
991 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
992 "http://example.com/foo.txt", "text/plain",
993 FILE_PATH_LITERAL(""),
994
995 FILE_PATH_LITERAL(""),
996 FILE_PATH_LITERAL(""),
997 FILE_PATH_LITERAL("virtual/foo.txt"),
998 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
999
1000 EXPECT_LOCAL_PATH
1001 },
1002 };
1003
1004 base::FilePath expected_virtual_path(
1005 GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")));
1006 // The default download directory is the virtual path.
1007 SetDefaultDownloadPath(test_virtual_dir());
1008 // Simulate failed call to DetermineLocalPath.
1009 EXPECT_CALL(*delegate(), DetermineLocalPath(
1010 _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
1011 .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
1012 RunTestCasesWithActiveItem(kLocalPathFailedCases,
1013 arraysize(kLocalPathFailedCases));
1014 }
1015
1016 // Downloads that have a danger level of AllowOnUserGesture should be marked as
1017 // safe depending on whether there was a user gesture associated with the
1018 // download and whether the referrer was visited prior to today.
1019 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_VisitedReferrer) {
1020 const DownloadTestCase kVisitedReferrerCases[] = {
1021 // http://visited.example.com/ is added to the history as a visit that
1022 // happened prior to today.
1023 {
1024 // 0: Safe download due to visiting referrer before.
1025 AUTOMATIC,
1026 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1027 "http://visited.example.com/foo.html", "text/html",
1028 FILE_PATH_LITERAL(""),
1029
1030 FILE_PATH_LITERAL(""),
1031 FILE_PATH_LITERAL("foo.html"),
1032 FILE_PATH_LITERAL("foo.html"),
1033 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1034
1035 EXPECT_CRDOWNLOAD
1036 },
1037
1038 {
1039 // 1: Dangerous due to not having visited referrer before.
1040 AUTOMATIC,
1041 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1042 "http://not-visited.example.com/foo.html", "text/html",
1043 FILE_PATH_LITERAL(""),
1044
1045 FILE_PATH_LITERAL(""),
1046 FILE_PATH_LITERAL("foo.html"),
1047 FILE_PATH_LITERAL("foo.html"),
1048 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1049
1050 EXPECT_UNCONFIRMED
1051 },
1052
1053 {
1054 // 2: Safe because the user is being prompted.
1055 SAVE_AS,
1056 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1057 "http://not-visited.example.com/foo.html", "text/html",
1058 FILE_PATH_LITERAL(""),
1059
1060 FILE_PATH_LITERAL(""),
1061 FILE_PATH_LITERAL("foo.html"),
1062 FILE_PATH_LITERAL("foo.html"),
1063 DownloadItem::TARGET_DISPOSITION_PROMPT,
1064
1065 EXPECT_CRDOWNLOAD
1066 },
1067
1068 {
1069 // 3: Safe because of forced path.
1070 FORCED,
1071 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1072 "http://not-visited.example.com/foo.html", "text/html",
1073 FILE_PATH_LITERAL("foo.html"),
1074
1075 FILE_PATH_LITERAL(""),
1076 FILE_PATH_LITERAL("foo.html"),
1077 FILE_PATH_LITERAL("foo.html"),
1078 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1079
1080 EXPECT_LOCAL_PATH
1081 },
1082 };
1083
1084 // This test assumes that the danger level of .html files is
1085 // AllowOnUserGesture.
1086 ASSERT_EQ(download_util::AllowOnUserGesture,
1087 download_util::GetFileDangerLevel(
1088 base::FilePath(FILE_PATH_LITERAL("foo.html"))));
1089
1090 // First the history service must exist.
1091 profile()->CreateHistoryService(false, false);
1092
1093 GURL url("http://visited.example.com/visited-link.html");
1094 // The time of visit is picked to be several seconds prior to the most recent
1095 // midnight.
1096 base::Time time_of_visit(
1097 base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(10));
1098 HistoryService* history_service =
1099 HistoryServiceFactory::GetForProfile(profile(), Profile::EXPLICIT_ACCESS);
1100 ASSERT_TRUE(history_service);
1101 history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
1102
1103 RunTestCasesWithActiveItem(kVisitedReferrerCases,
1104 arraysize(kVisitedReferrerCases));
1105 }
1106
1107 // These test cases are run with "Prompt for download" user preference set to
1108 // true. Even with the preference set, some of these downloads should not cause
1109 // a prompt to appear.
1110 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways) {
1111 const DownloadTestCase kPromptingTestCases[] = {
1112 {
1113 // 0: Safe Automatic - Should prompt because of "Prompt for download"
1114 // preference setting.
1115 AUTOMATIC,
1116 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1117 "http://example.com/foo.txt", "text/plain",
1118 FILE_PATH_LITERAL(""),
1119
1120 FILE_PATH_LITERAL(""),
1121 FILE_PATH_LITERAL("foo.txt"),
1122 FILE_PATH_LITERAL("foo.txt"),
1123 DownloadItem::TARGET_DISPOSITION_PROMPT,
1124
1125 EXPECT_CRDOWNLOAD
1126 },
1127
1128 {
1129 // 1: Automatic Browser Extension download. - Shouldn't prompt for browser
1130 // extension downloads even if "Prompt for download" preference is set.
1131 AUTOMATIC,
1132 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1133 "http://example.com/foo.crx",
1134 extensions::Extension::kMimeType,
1135 FILE_PATH_LITERAL(""),
1136
1137 FILE_PATH_LITERAL(""),
1138 FILE_PATH_LITERAL("foo.crx"),
1139 FILE_PATH_LITERAL("foo.crx"),
1140 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1141
1142 EXPECT_UNCONFIRMED
1143 },
1144
1145 {
1146 // 2: 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 FILE_PATH_LITERAL("foo.txt"),
1155 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1156
1157 EXPECT_LOCAL_PATH
1158 },
1159
1160 {
1161 // 3: Automatic User Script - Shouldn't prompt for user script downloads
1162 // even if "Prompt for download" preference is set.
1163 AUTOMATIC,
1164 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1165 "http://example.com/foo.user.js", "",
1166 FILE_PATH_LITERAL(""),
1167
1168 FILE_PATH_LITERAL(""),
1169 FILE_PATH_LITERAL("foo.user.js"),
1170 FILE_PATH_LITERAL("foo.user.js"),
1171 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1172
1173 EXPECT_CRDOWNLOAD
1174 },
1175
1176 {
1177 // 4: Automatic - The filename extension is marked as one that we will
1178 // open automatically. Shouldn't prompt.
1179 AUTOMATIC,
1180 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1181 "http://example.com/foo.dummy", "",
1182 FILE_PATH_LITERAL(""),
1183
1184 FILE_PATH_LITERAL(""),
1185 FILE_PATH_LITERAL("foo.dummy"),
1186 FILE_PATH_LITERAL("foo.dummy"),
1187 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1188
1189 EXPECT_CRDOWNLOAD
1190 },
1191 };
1192
1193 SetPromptForDownload(true);
1194 EnableAutoOpenBasedOnExtension(
1195 base::FilePath(FILE_PATH_LITERAL("dummy.dummy")));
1196 RunTestCasesWithActiveItem(kPromptingTestCases,
1197 arraysize(kPromptingTestCases));
1198 }
1199
1200 // If the download path is managed, then we don't show any prompts.
1201 // Note that if the download path is managed, then PromptForDownload() is false.
1202 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ManagedPath) {
1203 const DownloadTestCase kManagedPathTestCases[] = {
1204 {
1205 // 0: Automatic Safe
1206 AUTOMATIC,
1207 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1208 "http://example.com/foo.txt", "text/plain",
1209 FILE_PATH_LITERAL(""),
1210
1211 FILE_PATH_LITERAL(""),
1212 FILE_PATH_LITERAL("foo.txt"),
1213 FILE_PATH_LITERAL("foo.txt"),
1214 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1215
1216 EXPECT_CRDOWNLOAD
1217 },
1218
1219 {
1220 // 1: Save_As Safe
1221 SAVE_AS,
1222 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1223 "http://example.com/foo.txt", "text/plain",
1224 FILE_PATH_LITERAL(""),
1225
1226 FILE_PATH_LITERAL(""),
1227 FILE_PATH_LITERAL("foo.txt"),
1228 FILE_PATH_LITERAL("foo.txt"),
1229 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1230
1231 EXPECT_CRDOWNLOAD
1232 },
1233 };
1234
1235 SetManagedDownloadPath(test_download_dir());
1236 ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
1237 RunTestCasesWithActiveItem(kManagedPathTestCases,
1238 arraysize(kManagedPathTestCases));
1239 }
1240
1241 // Test basic functionality supporting extensions that want to override download
1242 // filenames.
1243 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsSafe) {
1244 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1245 {
1246 // 0: Automatic Safe
1247 AUTOMATIC,
1248 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1249 "http://example.com/foo.txt", "text/plain",
1250 FILE_PATH_LITERAL(""),
1251
1252 FILE_PATH_LITERAL(""),
1253 FILE_PATH_LITERAL("overridden/foo.txt"),
1254 FILE_PATH_LITERAL("foo.txt"),
1255 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1256
1257 EXPECT_CRDOWNLOAD
1258 },
1259
1260 {
1261 // 1: Save_As Safe
1262 SAVE_AS,
1263 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1264 "http://example.com/foo.txt", "text/plain",
1265 FILE_PATH_LITERAL(""),
1266
1267 FILE_PATH_LITERAL(""),
1268 FILE_PATH_LITERAL("overridden/foo.txt"),
1269 FILE_PATH_LITERAL("foo.txt"),
1270 DownloadItem::TARGET_DISPOSITION_PROMPT,
1271
1272 EXPECT_CRDOWNLOAD
1273 },
1274
1275 {
1276 // 2: Automatic Dangerous
1277 AUTOMATIC,
1278 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1279 "http://example.com/foo.html", "",
1280 FILE_PATH_LITERAL(""),
1281
1282 FILE_PATH_LITERAL(""),
1283 FILE_PATH_LITERAL("overridden/foo.html"),
1284 FILE_PATH_LITERAL("foo.html"),
1285 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1286
1287 EXPECT_UNCONFIRMED
1288 },
1289
1290 {
1291 // 3: Forced Safe
1292 FORCED,
1293 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1294 "http://example.com/foo.txt", "",
1295 FILE_PATH_LITERAL("forced-foo.txt"),
1296
1297 FILE_PATH_LITERAL(""),
1298 FILE_PATH_LITERAL("forced-foo.txt"),
1299 FILE_PATH_LITERAL("forced-foo.txt"),
1300 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1301
1302 EXPECT_LOCAL_PATH
1303 },
1304 };
1305
1306 for (size_t i = 0; i < arraysize(kNotifyExtensionsTestCases); ++i) {
1307 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1308 const DownloadTestCase& test_case = kNotifyExtensionsTestCases[i];
1309 scoped_ptr<content::MockDownloadItem> item(
1310 CreateActiveDownloadItem(i, test_case));
1311 SetUpDelegateExpectationsForActiveItem(test_case, item.get());
1312
1313 // Set up expectations so that the extension overrides the target directory,
1314 // but not the filename.
1315 base::FilePath generated_path(test_case.expected_generated_path);
1316
1317 // Override with "overridden/foo.txt".
1318 base::FilePath overridden_path =
1319 base::FilePath(FILE_PATH_LITERAL("overridden"))
1320 .Append(generated_path.BaseName());
1321
1322 if (test_case.test_type == FORCED) {
1323 // Don't notify extensions for forced downloads.
1324 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1325 .Times(0);
1326 } else {
1327 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1328 .WillOnce(WithArg<2>(
1329 ScheduleCallback2(overridden_path,
1330 DownloadPathReservationTracker::UNIQUIFY)));
1331 }
1332 base::FilePath full_overridden_path =
1333 GetPathInDownloadDir(overridden_path.value());
1334 EXPECT_CALL(*delegate(),
1335 PromptUserForDownloadPath(_, full_overridden_path, _))
1336 .WillRepeatedly(WithArg<2>(
1337 ScheduleCallback(full_overridden_path)));
1338
1339 RunTestCase(test_case, item.get());
1340 }
1341 }
1342
1343 // Test that filenames provided by extensions are passed into SafeBrowsing
1344 // checks and dangerous download checks.
1345 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsUnsafe) {
1346 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1347 {
1348 // 0: Automatic Safe : Later overridden by a dangerous filetype.
1349 AUTOMATIC,
1350 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1351 "http://example.com/foo.txt", "text/plain",
1352 FILE_PATH_LITERAL(""),
1353
1354 FILE_PATH_LITERAL(""),
1355 FILE_PATH_LITERAL("overridden/foo.html"),
1356 FILE_PATH_LITERAL("foo.txt"),
1357 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1358
1359 EXPECT_UNCONFIRMED
1360 },
1361
1362 {
1363 // 1: Automatic Safe : Later overridden by a potentially dangerous
1364 // filetype.
1365 AUTOMATIC,
1366 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
1367 "http://example.com/foo.txt", "text/plain",
1368 FILE_PATH_LITERAL(""),
1369
1370 FILE_PATH_LITERAL(""),
1371 FILE_PATH_LITERAL("overridden/foo.exe"),
1372 FILE_PATH_LITERAL("foo.png"),
1373 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1374
1375 EXPECT_UNCONFIRMED
1376 },
1377 };
1378
1379 for (size_t i = 0; i < arraysize(kNotifyExtensionsTestCases); ++i) {
1380 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1381 const DownloadTestCase& test_case = kNotifyExtensionsTestCases[i];
1382 scoped_ptr<content::MockDownloadItem> item(
1383 CreateActiveDownloadItem(i, test_case));
1384 SetUpDelegateExpectationsForActiveItem(test_case, item.get());
1385 base::FilePath generated_path(test_case.expected_generated_path);
1386
1387 // The extension overrides the path and filename:
1388 // "foo.txt" => "overridden/foo.html"
1389 // "foo.png" => "overridden/foo.exe"
1390 base::FilePath::StringType new_extension =
1391 (generated_path.MatchesExtension(FILE_PATH_LITERAL(".txt")) ?
1392 FILE_PATH_LITERAL("html") : FILE_PATH_LITERAL("exe"));
1393 base::FilePath overridden_path =
1394 base::FilePath(FILE_PATH_LITERAL("overridden"))
1395 .Append(generated_path.BaseName().ReplaceExtension(new_extension));
1396
1397 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1398 .WillOnce(WithArg<2>(
1399 ScheduleCallback2(overridden_path,
1400 DownloadPathReservationTracker::UNIQUIFY)));
1401
1402 // ".exe" files are considered MAYBE_DANGEROUS.
1403 content::DownloadDangerType danger_type =
1404 overridden_path.MatchesExtension(FILE_PATH_LITERAL(".exe")) ?
1405 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT :
1406 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
1407 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, _, _))
1408 .WillOnce(WithArg<2>(
1409 ScheduleCallback(danger_type)));
1410
1411 RunTestCase(test_case, item.get());
1412 }
1413 }
1414
1415 // Test that conflict actions set by extensions are passed correctly into
1416 // ReserveVirtualPath.
1417 TEST_F(DownloadTargetDeterminerTest,
1418 TargetDeterminer_NotifyExtensionsConflict) {
1419 const DownloadTestCase kNotifyExtensionsTestCase = {
1420 AUTOMATIC,
1421 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1422 "http://example.com/foo.txt", "text/plain",
1423 FILE_PATH_LITERAL(""),
1424
1425 FILE_PATH_LITERAL(""),
1426 FILE_PATH_LITERAL("overridden/foo.txt"),
1427 FILE_PATH_LITERAL("foo.txt"),
1428 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1429
1430 EXPECT_CRDOWNLOAD
1431 };
1432
1433 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1434 scoped_ptr<content::MockDownloadItem> item(
1435 CreateActiveDownloadItem(0, test_case));
1436 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1437 base::FilePath full_overridden_path =
1438 GetPathInDownloadDir(overridden_path.value());
1439
1440 // First case: An extension sets the conflict_action to OVERWRITE.
1441 SetUpDelegateExpectationsForActiveItem(test_case, item.get());
1442 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1443 .WillOnce(WithArg<2>(
1444 ScheduleCallback2(overridden_path,
1445 DownloadPathReservationTracker::OVERWRITE)));
1446 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1447 _, full_overridden_path, DownloadPathReservationTracker::OVERWRITE, _))
1448 .WillOnce(WithArg<3>(
1449 ScheduleCallback2(full_overridden_path, true)));
1450
1451 RunTestCase(test_case, item.get());
1452
1453 // Second case: An extension sets the conflict_action to PROMPT.
1454 SetUpDelegateExpectationsForActiveItem(test_case, item.get());
1455 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1456 .WillOnce(WithArg<2>(
1457 ScheduleCallback2(overridden_path,
1458 DownloadPathReservationTracker::PROMPT)));
1459 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1460 _, full_overridden_path, DownloadPathReservationTracker::PROMPT, _))
1461 .WillOnce(WithArg<3>(
1462 ScheduleCallback2(full_overridden_path, true)));
1463 RunTestCase(test_case, item.get());
1464 }
1465
1466 // Test that relative paths returned by extensions are always relative to the
1467 // default downloads path.
1468 TEST_F(DownloadTargetDeterminerTest,
1469 TargetDeterminer_NotifyExtensionsDefaultPath) {
1470 const DownloadTestCase kNotifyExtensionsTestCase = {
1471 SAVE_AS,
1472 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1473 "http://example.com/foo.txt", "text/plain",
1474 FILE_PATH_LITERAL(""),
1475
1476 FILE_PATH_LITERAL(""),
1477 FILE_PATH_LITERAL("overridden/foo.txt"),
1478 FILE_PATH_LITERAL("last_selected/foo.txt"),
1479 DownloadItem::TARGET_DISPOSITION_PROMPT,
1480
1481 EXPECT_CRDOWNLOAD
1482 };
1483
1484 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1485 scoped_ptr<content::MockDownloadItem> item(
1486 CreateActiveDownloadItem(0, test_case));
1487 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1488 base::FilePath full_overridden_path =
1489 GetPathInDownloadDir(overridden_path.value());
1490
1491 // The last selected directory is this one. Since the test case is a SAVE_AS
1492 // download, it should use this directory for the generated path.
1493 set_last_selected_directory(GetPathInDownloadDir("last_selected"));
1494
1495 SetUpDelegateExpectationsForActiveItem(test_case, item.get());
1496 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1497 .WillOnce(WithArg<2>(
1498 ScheduleCallback2(overridden_path,
1499 DownloadPathReservationTracker::UNIQUIFY)));
1500 EXPECT_CALL(*delegate(),
1501 PromptUserForDownloadPath(_, full_overridden_path, _))
1502 .WillOnce(WithArg<2>(
1503 ScheduleCallback(full_overridden_path)));
1504 RunTestCase(test_case, item.get());
1505 }
1506 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698