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/at_exit.h"
6 #include "base/files/file_path.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/observer_list.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/run_loop.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_util.h"
14 #include "base/value_conversions.h"
15 #include "chrome/browser/download/chrome_download_manager_delegate.h"
16 #include "chrome/browser/download/download_extensions.h"
17 #include "chrome/browser/download/download_prefs.h"
18 #include "chrome/browser/download/download_target_determiner.h"
19 #include "chrome/browser/download/download_target_info.h"
20 #include "chrome/browser/history/history_service.h"
21 #include "chrome/browser/history/history_service_factory.h"
22 #include "chrome/browser/history/history_types.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/download_interrupt_reasons.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/browser/web_contents_delegate.h"
31 #include "content/public/test/mock_download_item.h"
32 #include "content/public/test/test_browser_thread.h"
33 #include "content/public/test/test_renderer_host.h"
34 #include "content/public/test/web_contents_tester.h"
35 #include "extensions/common/extension.h"
36 #include "net/base/mime_util.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39
40 #if defined(ENABLE_PLUGINS)
41 #include "chrome/browser/plugins/plugin_prefs.h"
42 #include "content/public/browser/plugin_service.h"
43 #include "content/public/common/webplugininfo.h"
44 #endif
45
46 using ::testing::AnyNumber;
47 using ::testing::Invoke;
48 using ::testing::Ref;
49 using ::testing::Return;
50 using ::testing::ReturnRef;
51 using ::testing::ReturnRefOfCopy;
52 using ::testing::Truly;
53 using ::testing::WithArg;
54 using ::testing::_;
55 using content::DownloadItem;
56
57 namespace {
58
59 // No-op delegate.
60 class NullWebContentsDelegate : public content::WebContentsDelegate {
61 public:
NullWebContentsDelegate()62 NullWebContentsDelegate() {}
~NullWebContentsDelegate()63 virtual ~NullWebContentsDelegate() {}
64 };
65
66 // Google Mock action that posts a task to the current message loop that invokes
67 // the first argument of the mocked method as a callback. Said argument must be
68 // a base::Callback<void(ParamType)>. |result| must be of |ParamType| and is
69 // bound as that parameter.
70 // Example:
71 // class FooClass {
72 // public:
73 // virtual void Foo(base::Callback<void(bool)> callback);
74 // };
75 // ...
76 // EXPECT_CALL(mock_fooclass_instance, Foo(callback))
77 // .WillOnce(ScheduleCallback(false));
ACTION_P(ScheduleCallback,result0)78 ACTION_P(ScheduleCallback, result0) {
79 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(arg0, result0));
80 }
81
82 // Similar to ScheduleCallback, but binds 2 arguments.
ACTION_P2(ScheduleCallback2,result0,result1)83 ACTION_P2(ScheduleCallback2, result0, result1) {
84 base::MessageLoop::current()->PostTask(
85 FROM_HERE, base::Bind(arg0, result0, result1));
86 }
87
88 // Used with DownloadTestCase. Indicates the type of test case. The expectations
89 // for the test is set based on the type.
90 enum TestCaseType {
91 SAVE_AS,
92 AUTOMATIC,
93 FORCED // Requires that forced_file_path be non-empty.
94 };
95
96 // Used with DownloadTestCase. Type of intermediate filename to expect.
97 enum TestCaseExpectIntermediate {
98 EXPECT_CRDOWNLOAD, // Expect path/to/target.crdownload.
99 EXPECT_UNCONFIRMED, // Expect path/to/Unconfirmed xxx.crdownload.
100 EXPECT_LOCAL_PATH, // Expect target path.
101 };
102
103 // Typical download test case. Used with
104 // DownloadTargetDeterminerTest::RunTestCase().
105 struct DownloadTestCase {
106 // Type of test.
107 TestCaseType test_type;
108
109 // Expected danger type. Verified at the end of target determination.
110 content::DownloadDangerType expected_danger_type;
111
112 // Value of DownloadItem::GetURL()
113 const char* url;
114
115 // Value of DownloadItem::GetMimeType()
116 const char* mime_type;
117
118 // Should be non-empty if |test_type| == FORCED. Value of GetForcedFilePath().
119 const base::FilePath::CharType* forced_file_path;
120
121 // Expected virtual path. Specified relative to the virtual download path. If
122 // empty, assumed to be the same as |expected_local_path|.
123 const base::FilePath::CharType* expected_virtual_path;
124
125 // Expected local path. Specified relative to the test download path.
126 const base::FilePath::CharType* expected_local_path;
127
128 // Expected target disposition. If this is TARGET_DISPOSITION_PROMPT, then the
129 // test run will expect ChromeDownloadManagerDelegate to prompt the user for a
130 // download location.
131 DownloadItem::TargetDisposition expected_disposition;
132
133 // Type of intermediate path to expect.
134 TestCaseExpectIntermediate expected_intermediate;
135 };
136
137 class MockDownloadTargetDeterminerDelegate
138 : public DownloadTargetDeterminerDelegate {
139 public:
140 MOCK_METHOD3(CheckDownloadUrl,
141 void(content::DownloadItem*, const base::FilePath&,
142 const CheckDownloadUrlCallback&));
143 MOCK_METHOD3(NotifyExtensions,
144 void(content::DownloadItem*, const base::FilePath&,
145 const NotifyExtensionsCallback&));
146 MOCK_METHOD3(PromptUserForDownloadPath,
147 void(content::DownloadItem*, const base::FilePath&,
148 const FileSelectedCallback&));
149 MOCK_METHOD3(DetermineLocalPath,
150 void(DownloadItem*, const base::FilePath&,
151 const LocalPathCallback&));
152 MOCK_METHOD5(ReserveVirtualPath,
153 void(DownloadItem*, const base::FilePath&, bool,
154 DownloadPathReservationTracker::FilenameConflictAction,
155 const ReservedPathCallback&));
156 MOCK_METHOD2(GetFileMimeType,
157 void(const base::FilePath&,
158 const GetFileMimeTypeCallback&));
159
SetupDefaults()160 void SetupDefaults() {
161 ON_CALL(*this, CheckDownloadUrl(_, _, _))
162 .WillByDefault(WithArg<2>(
163 ScheduleCallback(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)));
164 ON_CALL(*this, NotifyExtensions(_, _, _))
165 .WillByDefault(WithArg<2>(
166 ScheduleCallback2(base::FilePath(),
167 DownloadPathReservationTracker::UNIQUIFY)));
168 ON_CALL(*this, ReserveVirtualPath(_, _, _, _, _))
169 .WillByDefault(Invoke(
170 &MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath));
171 ON_CALL(*this, PromptUserForDownloadPath(_, _, _))
172 .WillByDefault(Invoke(
173 &MockDownloadTargetDeterminerDelegate::NullPromptUser));
174 ON_CALL(*this, DetermineLocalPath(_, _, _))
175 .WillByDefault(Invoke(
176 &MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath));
177 ON_CALL(*this, GetFileMimeType(_, _))
178 .WillByDefault(WithArg<1>(
179 ScheduleCallback("")));
180 }
181 private:
182 static void NullReserveVirtualPath(
183 DownloadItem* download,
184 const base::FilePath& virtual_path,
185 bool create_directory,
186 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
187 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback);
188 static void NullPromptUser(
189 DownloadItem* download, const base::FilePath& suggested_path,
190 const FileSelectedCallback& callback);
191 static void NullDetermineLocalPath(
192 DownloadItem* download, const base::FilePath& virtual_path,
193 const LocalPathCallback& callback);
194 };
195
196 class DownloadTargetDeterminerTest : public ChromeRenderViewHostTestHarness {
197 public:
198 // ::testing::Test
199 virtual void SetUp() OVERRIDE;
200 virtual void TearDown() OVERRIDE;
201
202 // Creates MockDownloadItem and sets up default expectations.
203 content::MockDownloadItem* CreateActiveDownloadItem(
204 int32 id,
205 const DownloadTestCase& test_case);
206
207 // Sets the AutoOpenBasedOnExtension user preference for |path|.
208 void EnableAutoOpenBasedOnExtension(const base::FilePath& path);
209
210 // Set the kDownloadDefaultDirectory managed preference to |path|.
211 void SetManagedDownloadPath(const base::FilePath& path);
212
213 // Set the kPromptForDownload user preference to |prompt|.
214 void SetPromptForDownload(bool prompt);
215
216 // Given the relative path |path|, returns the full path under the temporary
217 // downloads directory.
218 base::FilePath GetPathInDownloadDir(const base::FilePath::StringType& path);
219
220 // Run |test_case| using |item|.
221 void RunTestCase(const DownloadTestCase& test_case,
222 const base::FilePath& initial_virtual_path,
223 content::MockDownloadItem* item);
224
225 // Runs |test_case| with |item|. When the DownloadTargetDeterminer is done,
226 // returns the resulting DownloadTargetInfo.
227 scoped_ptr<DownloadTargetInfo> RunDownloadTargetDeterminer(
228 const base::FilePath& initial_virtual_path,
229 content::MockDownloadItem* item);
230
231 // Run through |test_case_count| tests in |test_cases|. A new MockDownloadItem
232 // will be created for each test case and destroyed when the test case is
233 // complete.
234 void RunTestCasesWithActiveItem(const DownloadTestCase test_cases[],
235 size_t test_case_count);
236
237 // Verifies that |target_path|, |disposition|, |expected_danger_type| and
238 // |intermediate_path| matches the expectations of |test_case|. Posts
239 // |closure| to the current message loop when done.
240 void VerifyDownloadTarget(const DownloadTestCase& test_case,
241 const DownloadTargetInfo* target_info);
242
test_download_dir() const243 const base::FilePath& test_download_dir() const {
244 return test_download_dir_.path();
245 }
246
test_virtual_dir() const247 const base::FilePath& test_virtual_dir() const {
248 return test_virtual_dir_;
249 }
250
delegate()251 MockDownloadTargetDeterminerDelegate* delegate() {
252 return &delegate_;
253 }
254
download_prefs()255 DownloadPrefs* download_prefs() {
256 return download_prefs_.get();
257 }
258
259 private:
260 scoped_ptr<DownloadPrefs> download_prefs_;
261 ::testing::NiceMock<MockDownloadTargetDeterminerDelegate> delegate_;
262 NullWebContentsDelegate web_contents_delegate_;
263 base::ScopedTempDir test_download_dir_;
264 base::FilePath test_virtual_dir_;
265 };
266
SetUp()267 void DownloadTargetDeterminerTest::SetUp() {
268 ChromeRenderViewHostTestHarness::SetUp();
269 CHECK(profile());
270 download_prefs_.reset(new DownloadPrefs(profile()));
271 web_contents()->SetDelegate(&web_contents_delegate_);
272 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
273 test_virtual_dir_ = test_download_dir().Append(FILE_PATH_LITERAL("virtual"));
274 download_prefs_->SetDownloadPath(test_download_dir());
275 delegate_.SetupDefaults();
276 }
277
TearDown()278 void DownloadTargetDeterminerTest::TearDown() {
279 download_prefs_.reset();
280 ChromeRenderViewHostTestHarness::TearDown();
281 }
282
283 content::MockDownloadItem*
CreateActiveDownloadItem(int32 id,const DownloadTestCase & test_case)284 DownloadTargetDeterminerTest::CreateActiveDownloadItem(
285 int32 id,
286 const DownloadTestCase& test_case) {
287 content::MockDownloadItem* item =
288 new ::testing::NiceMock<content::MockDownloadItem>();
289 GURL download_url(test_case.url);
290 std::vector<GURL> url_chain;
291 url_chain.push_back(download_url);
292 base::FilePath forced_file_path =
293 GetPathInDownloadDir(test_case.forced_file_path);
294 DownloadItem::TargetDisposition initial_disposition =
295 (test_case.test_type == SAVE_AS) ?
296 DownloadItem::TARGET_DISPOSITION_PROMPT :
297 DownloadItem::TARGET_DISPOSITION_OVERWRITE;
298 EXPECT_EQ(test_case.test_type == FORCED,
299 !forced_file_path.empty());
300
301 ON_CALL(*item, GetBrowserContext())
302 .WillByDefault(Return(profile()));
303 ON_CALL(*item, GetDangerType())
304 .WillByDefault(Return(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
305 ON_CALL(*item, GetForcedFilePath())
306 .WillByDefault(ReturnRefOfCopy(forced_file_path));
307 ON_CALL(*item, GetFullPath())
308 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
309 ON_CALL(*item, GetHash())
310 .WillByDefault(ReturnRefOfCopy(std::string()));
311 ON_CALL(*item, GetId())
312 .WillByDefault(Return(id));
313 ON_CALL(*item, GetLastReason())
314 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_NONE));
315 ON_CALL(*item, GetMimeType())
316 .WillByDefault(Return(test_case.mime_type));
317 ON_CALL(*item, GetReferrerUrl())
318 .WillByDefault(ReturnRefOfCopy(download_url));
319 ON_CALL(*item, GetState())
320 .WillByDefault(Return(DownloadItem::IN_PROGRESS));
321 ON_CALL(*item, GetTargetDisposition())
322 .WillByDefault(Return(initial_disposition));
323 ON_CALL(*item, GetTargetFilePath())
324 .WillByDefault(ReturnRefOfCopy(base::FilePath()));
325 ON_CALL(*item, GetTransitionType())
326 .WillByDefault(Return(content::PAGE_TRANSITION_LINK));
327 ON_CALL(*item, GetURL())
328 .WillByDefault(ReturnRefOfCopy(download_url));
329 ON_CALL(*item, GetUrlChain())
330 .WillByDefault(ReturnRefOfCopy(url_chain));
331 ON_CALL(*item, GetWebContents())
332 .WillByDefault(Return(web_contents()));
333 ON_CALL(*item, HasUserGesture())
334 .WillByDefault(Return(true));
335 ON_CALL(*item, IsDangerous())
336 .WillByDefault(Return(false));
337 ON_CALL(*item, IsTemporary())
338 .WillByDefault(Return(false));
339 return item;
340 }
341
EnableAutoOpenBasedOnExtension(const base::FilePath & path)342 void DownloadTargetDeterminerTest::EnableAutoOpenBasedOnExtension(
343 const base::FilePath& path) {
344 EXPECT_TRUE(download_prefs_->EnableAutoOpenBasedOnExtension(path));
345 }
346
SetManagedDownloadPath(const base::FilePath & path)347 void DownloadTargetDeterminerTest::SetManagedDownloadPath(
348 const base::FilePath& path) {
349 profile()->GetTestingPrefService()->
350 SetManagedPref(prefs::kDownloadDefaultDirectory,
351 base::CreateFilePathValue(path));
352 }
353
SetPromptForDownload(bool prompt)354 void DownloadTargetDeterminerTest::SetPromptForDownload(bool prompt) {
355 profile()->GetTestingPrefService()->
356 SetBoolean(prefs::kPromptForDownload, prompt);
357 }
358
GetPathInDownloadDir(const base::FilePath::StringType & relative_path)359 base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir(
360 const base::FilePath::StringType& relative_path) {
361 if (relative_path.empty())
362 return base::FilePath();
363 base::FilePath full_path(test_download_dir().Append(relative_path));
364 return full_path.NormalizePathSeparators();
365 }
366
RunTestCase(const DownloadTestCase & test_case,const base::FilePath & initial_virtual_path,content::MockDownloadItem * item)367 void DownloadTargetDeterminerTest::RunTestCase(
368 const DownloadTestCase& test_case,
369 const base::FilePath& initial_virtual_path,
370 content::MockDownloadItem* item) {
371 scoped_ptr<DownloadTargetInfo> target_info =
372 RunDownloadTargetDeterminer(initial_virtual_path, item);
373 VerifyDownloadTarget(test_case, target_info.get());
374 }
375
CompletionCallbackWrapper(const base::Closure & closure,scoped_ptr<DownloadTargetInfo> * target_info_receiver,scoped_ptr<DownloadTargetInfo> target_info)376 void CompletionCallbackWrapper(
377 const base::Closure& closure,
378 scoped_ptr<DownloadTargetInfo>* target_info_receiver,
379 scoped_ptr<DownloadTargetInfo> target_info) {
380 target_info_receiver->swap(target_info);
381 base::MessageLoop::current()->PostTask(FROM_HERE, closure);
382 }
383
384 scoped_ptr<DownloadTargetInfo>
RunDownloadTargetDeterminer(const base::FilePath & initial_virtual_path,content::MockDownloadItem * item)385 DownloadTargetDeterminerTest::RunDownloadTargetDeterminer(
386 const base::FilePath& initial_virtual_path,
387 content::MockDownloadItem* item) {
388 scoped_ptr<DownloadTargetInfo> target_info;
389 base::RunLoop run_loop;
390 DownloadTargetDeterminer::Start(
391 item, initial_virtual_path, download_prefs_.get(), delegate(),
392 base::Bind(&CompletionCallbackWrapper,
393 run_loop.QuitClosure(),
394 &target_info));
395 run_loop.Run();
396 ::testing::Mock::VerifyAndClearExpectations(delegate());
397 return target_info.Pass();
398 }
399
RunTestCasesWithActiveItem(const DownloadTestCase test_cases[],size_t test_case_count)400 void DownloadTargetDeterminerTest::RunTestCasesWithActiveItem(
401 const DownloadTestCase test_cases[],
402 size_t test_case_count) {
403 for (size_t i = 0; i < test_case_count; ++i) {
404 scoped_ptr<content::MockDownloadItem> item(
405 CreateActiveDownloadItem(i, test_cases[i]));
406 SCOPED_TRACE(testing::Message() << "Running test case " << i);
407 RunTestCase(test_cases[i], base::FilePath(), item.get());
408 }
409 }
410
VerifyDownloadTarget(const DownloadTestCase & test_case,const DownloadTargetInfo * target_info)411 void DownloadTargetDeterminerTest::VerifyDownloadTarget(
412 const DownloadTestCase& test_case,
413 const DownloadTargetInfo* target_info) {
414 base::FilePath expected_local_path(
415 GetPathInDownloadDir(test_case.expected_local_path));
416 EXPECT_EQ(expected_local_path.value(), target_info->target_path.value());
417 EXPECT_EQ(test_case.expected_disposition, target_info->target_disposition);
418 EXPECT_EQ(test_case.expected_danger_type, target_info->danger_type);
419
420 switch (test_case.expected_intermediate) {
421 case EXPECT_CRDOWNLOAD:
422 EXPECT_EQ(DownloadTargetDeterminer::GetCrDownloadPath(
423 target_info->target_path).value(),
424 target_info->intermediate_path.value());
425 break;
426
427 case EXPECT_UNCONFIRMED:
428 // The paths (in English) look like: /path/Unconfirmed xxx.crdownload.
429 // Of this, we only check that the path is:
430 // 1. Not "/path/target.crdownload",
431 // 2. Points to the same directory as the target.
432 // 3. Has extension ".crdownload".
433 // 4. Basename starts with "Unconfirmed ".
434 EXPECT_NE(DownloadTargetDeterminer::GetCrDownloadPath(expected_local_path)
435 .value(),
436 target_info->intermediate_path.value());
437 EXPECT_EQ(expected_local_path.DirName().value(),
438 target_info->intermediate_path.DirName().value());
439 EXPECT_TRUE(target_info->intermediate_path.MatchesExtension(
440 FILE_PATH_LITERAL(".crdownload")));
441 EXPECT_EQ(0u,
442 target_info->intermediate_path.BaseName().value().find(
443 FILE_PATH_LITERAL("Unconfirmed ")));
444 break;
445
446 case EXPECT_LOCAL_PATH:
447 EXPECT_EQ(expected_local_path.value(),
448 target_info->intermediate_path.value());
449 break;
450 }
451 }
452
453 // static
NullReserveVirtualPath(DownloadItem * download,const base::FilePath & virtual_path,bool create_directory,DownloadPathReservationTracker::FilenameConflictAction conflict_action,const DownloadTargetDeterminerDelegate::ReservedPathCallback & callback)454 void MockDownloadTargetDeterminerDelegate::NullReserveVirtualPath(
455 DownloadItem* download,
456 const base::FilePath& virtual_path,
457 bool create_directory,
458 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
459 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
460 callback.Run(virtual_path, true);
461 }
462
463 // static
NullPromptUser(DownloadItem * download,const base::FilePath & suggested_path,const FileSelectedCallback & callback)464 void MockDownloadTargetDeterminerDelegate::NullPromptUser(
465 DownloadItem* download, const base::FilePath& suggested_path,
466 const FileSelectedCallback& callback) {
467 callback.Run(suggested_path);
468 }
469
470 // static
NullDetermineLocalPath(DownloadItem * download,const base::FilePath & virtual_path,const LocalPathCallback & callback)471 void MockDownloadTargetDeterminerDelegate::NullDetermineLocalPath(
472 DownloadItem* download, const base::FilePath& virtual_path,
473 const LocalPathCallback& callback) {
474 callback.Run(virtual_path);
475 }
476
477 // NotifyExtensions implementation that overrides the path so that the target
478 // file is in a subdirectory called 'overridden'. If the extension is '.remove',
479 // the extension is removed.
NotifyExtensionsOverridePath(content::DownloadItem * download,const base::FilePath & path,const DownloadTargetDeterminerDelegate::NotifyExtensionsCallback & callback)480 void NotifyExtensionsOverridePath(
481 content::DownloadItem* download,
482 const base::FilePath& path,
483 const DownloadTargetDeterminerDelegate::NotifyExtensionsCallback&
484 callback) {
485 base::FilePath new_path =
486 base::FilePath()
487 .AppendASCII("overridden")
488 .Append(path.BaseName());
489 if (new_path.MatchesExtension(FILE_PATH_LITERAL(".remove")))
490 new_path = new_path.RemoveExtension();
491 callback.Run(new_path, DownloadPathReservationTracker::UNIQUIFY);
492 }
493
CheckDownloadUrlCheckExes(content::DownloadItem * download,const base::FilePath & path,const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback & callback)494 void CheckDownloadUrlCheckExes(
495 content::DownloadItem* download,
496 const base::FilePath& path,
497 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback&
498 callback) {
499 if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
500 callback.Run(content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT);
501 else
502 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
503 }
504
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_Basic)505 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_Basic) {
506 const DownloadTestCase kBasicTestCases[] = {
507 {
508 // 0: Automatic Safe
509 AUTOMATIC,
510 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
511 "http://example.com/foo.txt", "text/plain",
512 FILE_PATH_LITERAL(""),
513
514 FILE_PATH_LITERAL(""),
515 FILE_PATH_LITERAL("foo.txt"),
516 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
517
518 EXPECT_CRDOWNLOAD
519 },
520
521 {
522 // 1: Save_As Safe
523 SAVE_AS,
524 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
525 "http://example.com/foo.txt", "text/plain",
526 FILE_PATH_LITERAL(""),
527
528 FILE_PATH_LITERAL(""),
529 FILE_PATH_LITERAL("foo.txt"),
530 DownloadItem::TARGET_DISPOSITION_PROMPT,
531
532 EXPECT_CRDOWNLOAD
533 },
534
535 {
536 // 2: Automatic Dangerous
537 AUTOMATIC,
538 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
539 "http://example.com/foo.crx", "",
540 FILE_PATH_LITERAL(""),
541
542 FILE_PATH_LITERAL(""),
543 FILE_PATH_LITERAL("foo.crx"),
544 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
545
546 EXPECT_UNCONFIRMED
547 },
548
549 {
550 // 3: Forced Safe
551 FORCED,
552 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
553 "http://example.com/foo.txt", "",
554 FILE_PATH_LITERAL("forced-foo.txt"),
555
556 FILE_PATH_LITERAL(""),
557 FILE_PATH_LITERAL("forced-foo.txt"),
558 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
559
560 EXPECT_LOCAL_PATH
561 },
562 };
563
564 // The test assumes that .crx files have a danger level of
565 // ALLOW_ON_USER_GESTURE.
566 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
567 download_util::GetFileDangerLevel(
568 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
569 RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
570 }
571
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_CancelSaveAs)572 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_CancelSaveAs) {
573 const DownloadTestCase kCancelSaveAsTestCases[] = {
574 {
575 // 0: Save_As Safe, Cancelled.
576 SAVE_AS,
577 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
578 "http://example.com/foo.txt", "text/plain",
579 FILE_PATH_LITERAL(""),
580
581 FILE_PATH_LITERAL(""),
582 FILE_PATH_LITERAL(""),
583 DownloadItem::TARGET_DISPOSITION_PROMPT,
584
585 EXPECT_LOCAL_PATH
586 }
587 };
588 ON_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
589 .WillByDefault(WithArg<2>(ScheduleCallback(base::FilePath())));
590 RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
591 arraysize(kCancelSaveAsTestCases));
592 }
593
594 // The SafeBrowsing check is performed early. Make sure that a download item
595 // that has been marked as DANGEROUS_URL behaves correctly.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_DangerousUrl)596 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DangerousUrl) {
597 const DownloadTestCase kSafeBrowsingTestCases[] = {
598 {
599 // 0: Automatic Dangerous URL
600 AUTOMATIC,
601 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
602 "http://phishing.example.com/foo.txt", "",
603 FILE_PATH_LITERAL(""),
604
605 FILE_PATH_LITERAL(""),
606 FILE_PATH_LITERAL("foo.txt"),
607 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
608
609 EXPECT_UNCONFIRMED
610 },
611
612 {
613 // 1: Save As Dangerous URL
614 SAVE_AS,
615 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
616 "http://phishing.example.com/foo.txt", "",
617 FILE_PATH_LITERAL(""),
618
619 FILE_PATH_LITERAL(""),
620 FILE_PATH_LITERAL("foo.txt"),
621 DownloadItem::TARGET_DISPOSITION_PROMPT,
622
623 EXPECT_UNCONFIRMED
624 },
625
626 {
627 // 2: Forced Dangerous URL
628 FORCED,
629 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
630 "http://phishing.example.com/foo.txt", "",
631 FILE_PATH_LITERAL("forced-foo.txt"),
632
633 FILE_PATH_LITERAL(""),
634 FILE_PATH_LITERAL("forced-foo.txt"),
635 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
636
637 EXPECT_UNCONFIRMED
638 },
639
640 {
641 // 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes
642 // precendence.
643 AUTOMATIC,
644 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
645 "http://phishing.example.com/foo.html", "",
646 FILE_PATH_LITERAL(""),
647
648 FILE_PATH_LITERAL(""),
649 FILE_PATH_LITERAL("foo.html"),
650 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
651
652 EXPECT_UNCONFIRMED
653 },
654
655 {
656 // 4: Save As Dangerous URL + Dangerous file
657 SAVE_AS,
658 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
659 "http://phishing.example.com/foo.html", "",
660 FILE_PATH_LITERAL(""),
661
662 FILE_PATH_LITERAL(""),
663 FILE_PATH_LITERAL("foo.html"),
664 DownloadItem::TARGET_DISPOSITION_PROMPT,
665
666 EXPECT_UNCONFIRMED
667 },
668
669 {
670 // 5: Forced Dangerous URL + Dangerous file
671 FORCED,
672 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
673 "http://phishing.example.com/foo.html", "",
674 FILE_PATH_LITERAL("forced-foo.html"),
675
676 FILE_PATH_LITERAL(""),
677 FILE_PATH_LITERAL("forced-foo.html"),
678 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
679
680 EXPECT_UNCONFIRMED
681 },
682 };
683
684 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
685 .WillByDefault(WithArg<2>(ScheduleCallback(
686 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
687 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
688 arraysize(kSafeBrowsingTestCases));
689 }
690
691 // The SafeBrowsing check is performed early. Make sure that a download item
692 // that has been marked as MAYBE_DANGEROUS_CONTENT behaves correctly.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_MaybeDangerousContent)693 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_MaybeDangerousContent) {
694 const DownloadTestCase kSafeBrowsingTestCases[] = {
695 {
696 // 0: Automatic Maybe dangerous content
697 AUTOMATIC,
698 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
699 "http://phishing.example.com/foo.exe", "",
700 FILE_PATH_LITERAL(""),
701
702 FILE_PATH_LITERAL(""),
703 FILE_PATH_LITERAL("foo.exe"),
704 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
705
706 EXPECT_UNCONFIRMED
707 },
708
709 {
710 // 1: Save As Maybe dangerous content
711 SAVE_AS,
712 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
713 "http://phishing.example.com/foo.exe", "",
714 FILE_PATH_LITERAL(""),
715
716 FILE_PATH_LITERAL(""),
717 FILE_PATH_LITERAL("foo.exe"),
718 DownloadItem::TARGET_DISPOSITION_PROMPT,
719
720 EXPECT_UNCONFIRMED
721 },
722
723 {
724 // 2: Forced Maybe dangerous content
725 FORCED,
726 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
727 "http://phishing.example.com/foo.exe", "",
728 FILE_PATH_LITERAL("forced-foo.exe"),
729
730 FILE_PATH_LITERAL(""),
731 FILE_PATH_LITERAL("forced-foo.exe"),
732 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
733
734 EXPECT_UNCONFIRMED
735 },
736 };
737
738 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
739 .WillByDefault(WithArg<2>(ScheduleCallback(
740 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
741 RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
742 arraysize(kSafeBrowsingTestCases));
743 }
744
745 // Test whether the last saved directory is used for 'Save As' downloads.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_LastSavePath)746 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LastSavePath) {
747 const DownloadTestCase kLastSavePathTestCasesPre[] = {
748 {
749 // 0: If the last save path is empty, then the default download directory
750 // should be used.
751 SAVE_AS,
752 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
753 "http://example.com/foo.txt", "text/plain",
754 FILE_PATH_LITERAL(""),
755
756 FILE_PATH_LITERAL(""),
757 FILE_PATH_LITERAL("foo.txt"),
758 DownloadItem::TARGET_DISPOSITION_PROMPT,
759
760 EXPECT_CRDOWNLOAD
761 }
762 };
763
764 // These test cases are run with a last save path set to a non-emtpy local
765 // download directory.
766 const DownloadTestCase kLastSavePathTestCasesPost[] = {
767 {
768 // 0: This test case is run with the last download directory set to
769 // '<test_download_dir()>/foo'.
770 SAVE_AS,
771 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
772 "http://example.com/foo.txt", "text/plain",
773 FILE_PATH_LITERAL(""),
774
775 FILE_PATH_LITERAL(""),
776 FILE_PATH_LITERAL("foo/foo.txt"),
777 DownloadItem::TARGET_DISPOSITION_PROMPT,
778
779 EXPECT_CRDOWNLOAD
780 },
781
782 {
783 // 1: Start an automatic download. This should be saved to the user's
784 // default download directory and not the last used Save As directory.
785 AUTOMATIC,
786 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
787 "http://example.com/foo.txt", "text/plain",
788 FILE_PATH_LITERAL(""),
789
790 FILE_PATH_LITERAL(""),
791 FILE_PATH_LITERAL("foo.txt"),
792 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
793
794 EXPECT_CRDOWNLOAD
795 },
796 };
797
798 // This test case is run with the last save path set to a non-empty virtual
799 // directory.
800 const DownloadTestCase kLastSavePathTestCasesVirtual[] = {
801 {
802 SAVE_AS,
803 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
804 "http://example.com/foo.txt", "text/plain",
805 FILE_PATH_LITERAL(""),
806
807 FILE_PATH_LITERAL("virtual/foo/foo.txt"),
808 FILE_PATH_LITERAL("bar.txt"),
809 DownloadItem::TARGET_DISPOSITION_PROMPT,
810
811 EXPECT_LOCAL_PATH
812 },
813 };
814
815 {
816 SCOPED_TRACE(testing::Message()
817 << "Running with default download path");
818 base::FilePath prompt_path =
819 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
820 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
821 RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
822 arraysize(kLastSavePathTestCasesPre));
823 }
824
825 // Try with a non-empty last save path.
826 {
827 SCOPED_TRACE(testing::Message()
828 << "Running with local last_selected_directory");
829 download_prefs()->SetSaveFilePath(test_download_dir().AppendASCII("foo"));
830 base::FilePath prompt_path =
831 GetPathInDownloadDir(FILE_PATH_LITERAL("foo/foo.txt"));
832 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, prompt_path, _));
833 RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
834 arraysize(kLastSavePathTestCasesPost));
835 }
836
837 // And again, but this time use a virtual directory.
838 {
839 SCOPED_TRACE(testing::Message()
840 << "Running with virtual last_selected_directory");
841 base::FilePath last_selected_dir = test_virtual_dir().AppendASCII("foo");
842 base::FilePath virtual_path = last_selected_dir.AppendASCII("foo.txt");
843 download_prefs()->SetSaveFilePath(last_selected_dir);
844 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
845 _, last_selected_dir.AppendASCII("foo.txt"), _));
846 EXPECT_CALL(*delegate(), DetermineLocalPath(_, virtual_path, _))
847 .WillOnce(WithArg<2>(ScheduleCallback(
848 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")))));
849 RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
850 arraysize(kLastSavePathTestCasesVirtual));
851 }
852 }
853
854 // These tests are run with the default downloads folder set to a virtual
855 // directory.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_DefaultVirtual)856 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_DefaultVirtual) {
857 // The default download directory is the virutal path.
858 download_prefs()->SetDownloadPath(test_virtual_dir());
859
860 {
861 SCOPED_TRACE(testing::Message() << "Automatic Safe Download");
862 const DownloadTestCase kAutomaticDownloadToVirtualDir = {
863 AUTOMATIC,
864 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
865 "http://example.com/foo.txt", "text/plain",
866 FILE_PATH_LITERAL(""),
867
868 // Downloaded to default virtual directory.
869 FILE_PATH_LITERAL("virtual/foo.txt"),
870 FILE_PATH_LITERAL("foo-local.txt"),
871 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
872
873 EXPECT_LOCAL_PATH
874 };
875 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
876 .WillOnce(WithArg<2>(ScheduleCallback(
877 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
878 RunTestCasesWithActiveItem(&kAutomaticDownloadToVirtualDir, 1);
879 }
880
881 {
882 SCOPED_TRACE(testing::Message() << "Save As to virtual directory");
883 const DownloadTestCase kSaveAsToVirtualDir = {
884 SAVE_AS,
885 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
886 "http://example.com/bar.txt", "text/plain",
887 FILE_PATH_LITERAL(""),
888
889 // The response to the download prompt is to choose the 'prompted.txt'
890 // virtual path.
891 FILE_PATH_LITERAL("virtual/prompted.txt"),
892 FILE_PATH_LITERAL("foo-local.txt"),
893 DownloadItem::TARGET_DISPOSITION_PROMPT,
894
895 EXPECT_LOCAL_PATH
896 };
897 EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _))
898 .WillOnce(WithArg<2>(ScheduleCallback(
899 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt")))));
900 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
901 _, test_virtual_dir().AppendASCII("bar.txt"), _))
902 .WillOnce(WithArg<2>(ScheduleCallback(
903 test_virtual_dir().AppendASCII("prompted.txt"))));
904 RunTestCasesWithActiveItem(&kSaveAsToVirtualDir, 1);
905 }
906
907 {
908 SCOPED_TRACE(testing::Message() << "Save As to local directory");
909 const DownloadTestCase kSaveAsToLocalDir = {
910 SAVE_AS,
911 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
912 "http://example.com/bar.txt", "text/plain",
913 FILE_PATH_LITERAL(""),
914
915 // Response to the 'Save As' is to choose the local path for 'foo-x.txt'.
916 FILE_PATH_LITERAL(""),
917 FILE_PATH_LITERAL("foo-x.txt"),
918 DownloadItem::TARGET_DISPOSITION_PROMPT,
919
920 EXPECT_CRDOWNLOAD
921 };
922 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(
923 _, test_virtual_dir().AppendASCII("bar.txt"), _))
924 .WillOnce(WithArg<2>(ScheduleCallback(
925 GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")))));
926 RunTestCasesWithActiveItem(&kSaveAsToLocalDir, 1);
927 }
928
929 {
930 SCOPED_TRACE(testing::Message() << "Forced safe download");
931 const DownloadTestCase kForcedSafe = {
932 FORCED,
933 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
934 "http://example.com/foo.txt", "",
935 FILE_PATH_LITERAL("forced-foo.txt"),
936
937 // Forced paths should be left as-is.
938 FILE_PATH_LITERAL(""),
939 FILE_PATH_LITERAL("forced-foo.txt"),
940 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
941
942 EXPECT_LOCAL_PATH
943 };
944 RunTestCasesWithActiveItem(&kForcedSafe, 1);
945 }
946 }
947
948 // Test that an inactive download will still get a virtual or local download
949 // path.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_InactiveDownload)950 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_InactiveDownload) {
951 const DownloadTestCase kInactiveTestCases[] = {
952 {
953 AUTOMATIC,
954 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
955 "http://example.com/foo.txt", "text/plain",
956 FILE_PATH_LITERAL(""),
957
958 FILE_PATH_LITERAL("foo.txt"),
959 FILE_PATH_LITERAL(""),
960 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
961
962 EXPECT_LOCAL_PATH
963 },
964
965 {
966 SAVE_AS,
967 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
968 "http://example.com/foo.txt", "text/plain",
969 FILE_PATH_LITERAL(""),
970
971 FILE_PATH_LITERAL("foo.txt"),
972 FILE_PATH_LITERAL(""),
973 DownloadItem::TARGET_DISPOSITION_PROMPT,
974
975 EXPECT_LOCAL_PATH
976 }
977 };
978
979 for (size_t i = 0; i < arraysize(kInactiveTestCases); ++i) {
980 SCOPED_TRACE(testing::Message() << "Running test case " << i);
981 const DownloadTestCase& test_case = kInactiveTestCases[i];
982 scoped_ptr<content::MockDownloadItem> item(
983 CreateActiveDownloadItem(i, test_case));
984 EXPECT_CALL(*item.get(), GetState())
985 .WillRepeatedly(Return(content::DownloadItem::CANCELLED));
986 // Even though one is a SAVE_AS download, no prompt will be displayed to
987 // the user because the download is inactive.
988 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
989 .Times(0);
990 RunTestCase(test_case, base::FilePath(), item.get());
991 }
992 }
993
994 // If the reserved path could not be verified, then the user should see a
995 // prompt.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_ReservationFailed)996 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ReservationFailed) {
997 const DownloadTestCase kReservationFailedCases[] = {
998 {
999 // 0: Automatic download. Since the reservation fails, the disposition of
1000 // the target is to prompt, but the returned path is used.
1001 AUTOMATIC,
1002 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1003 "http://example.com/foo.txt", "text/plain",
1004 FILE_PATH_LITERAL(""),
1005
1006 FILE_PATH_LITERAL(""),
1007 FILE_PATH_LITERAL("bar.txt"),
1008 DownloadItem::TARGET_DISPOSITION_PROMPT,
1009
1010 EXPECT_CRDOWNLOAD
1011 },
1012 };
1013
1014 // Setup ReserveVirtualPath() to fail.
1015 ON_CALL(*delegate(), ReserveVirtualPath(_, _, _, _, _))
1016 .WillByDefault(WithArg<4>(ScheduleCallback2(
1017 GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")), false)));
1018 RunTestCasesWithActiveItem(kReservationFailedCases,
1019 arraysize(kReservationFailedCases));
1020 }
1021
1022 // If the local path could not be determined, the download should be cancelled.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_LocalPathFailed)1023 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_LocalPathFailed) {
1024 const DownloadTestCase kLocalPathFailedCases[] = {
1025 {
1026 // 0: Automatic download.
1027 AUTOMATIC,
1028 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1029 "http://example.com/foo.txt", "text/plain",
1030 FILE_PATH_LITERAL(""),
1031
1032 FILE_PATH_LITERAL(""),
1033 FILE_PATH_LITERAL(""),
1034 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1035
1036 EXPECT_LOCAL_PATH
1037 },
1038 };
1039
1040 base::FilePath expected_virtual_path(
1041 GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")));
1042 // The default download directory is the virtual path.
1043 download_prefs()->SetDownloadPath(test_virtual_dir());
1044 // Simulate failed call to DetermineLocalPath.
1045 EXPECT_CALL(*delegate(), DetermineLocalPath(
1046 _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
1047 .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
1048 RunTestCasesWithActiveItem(kLocalPathFailedCases,
1049 arraysize(kLocalPathFailedCases));
1050 }
1051
1052 // Downloads that have a danger level of ALLOW_ON_USER_GESTURE should be marked
1053 // as safe depending on whether there was a user gesture associated with the
1054 // download and whether the referrer was visited prior to today.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_VisitedReferrer)1055 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_VisitedReferrer) {
1056 const DownloadTestCase kVisitedReferrerCases[] = {
1057 // http://visited.example.com/ is added to the history as a visit that
1058 // happened prior to today.
1059 {
1060 // 0: Safe download due to visiting referrer before.
1061 AUTOMATIC,
1062 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1063 "http://visited.example.com/foo.crx", "application/xml",
1064 FILE_PATH_LITERAL(""),
1065
1066 FILE_PATH_LITERAL(""),
1067 FILE_PATH_LITERAL("foo.crx"),
1068 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1069
1070 EXPECT_CRDOWNLOAD
1071 },
1072
1073 {
1074 // 1: Dangerous due to not having visited referrer before.
1075 AUTOMATIC,
1076 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1077 "http://not-visited.example.com/foo.crx", "application/xml",
1078 FILE_PATH_LITERAL(""),
1079
1080 FILE_PATH_LITERAL(""),
1081 FILE_PATH_LITERAL("foo.crx"),
1082 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1083
1084 EXPECT_UNCONFIRMED
1085 },
1086
1087 {
1088 // 2: Safe because the user is being prompted.
1089 SAVE_AS,
1090 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1091 "http://not-visited.example.com/foo.crx", "application/xml",
1092 FILE_PATH_LITERAL(""),
1093
1094 FILE_PATH_LITERAL(""),
1095 FILE_PATH_LITERAL("foo.crx"),
1096 DownloadItem::TARGET_DISPOSITION_PROMPT,
1097
1098 EXPECT_CRDOWNLOAD
1099 },
1100
1101 {
1102 // 3: Safe because of forced path.
1103 FORCED,
1104 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1105 "http://not-visited.example.com/foo.crx", "application/xml",
1106 FILE_PATH_LITERAL("foo.crx"),
1107
1108 FILE_PATH_LITERAL(""),
1109 FILE_PATH_LITERAL("foo.crx"),
1110 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1111
1112 EXPECT_LOCAL_PATH
1113 },
1114 };
1115
1116 // This test assumes that the danger level of .crx files is
1117 // ALLOW_ON_USER_GESTURE.
1118 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1119 download_util::GetFileDangerLevel(
1120 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1121
1122 // First the history service must exist.
1123 ASSERT_TRUE(profile()->CreateHistoryService(false, false));
1124
1125 GURL url("http://visited.example.com/visited-link.html");
1126 // The time of visit is picked to be several seconds prior to the most recent
1127 // midnight.
1128 base::Time time_of_visit(
1129 base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(10));
1130 HistoryService* history_service =
1131 HistoryServiceFactory::GetForProfile(profile(), Profile::EXPLICIT_ACCESS);
1132 ASSERT_TRUE(history_service);
1133 history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
1134
1135 RunTestCasesWithActiveItem(kVisitedReferrerCases,
1136 arraysize(kVisitedReferrerCases));
1137 }
1138
1139 // These test cases are run with "Prompt for download" user preference set to
1140 // true.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_PromptAlways)1141 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways) {
1142 const DownloadTestCase kPromptingTestCases[] = {
1143 {
1144 // 0: Safe Automatic - Should prompt because of "Prompt for download"
1145 // preference setting.
1146 AUTOMATIC,
1147 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1148 "http://example.com/foo.txt", "text/plain",
1149 FILE_PATH_LITERAL(""),
1150
1151 FILE_PATH_LITERAL(""),
1152 FILE_PATH_LITERAL("foo.txt"),
1153 DownloadItem::TARGET_DISPOSITION_PROMPT,
1154
1155 EXPECT_CRDOWNLOAD
1156 },
1157
1158 {
1159 // 1: Safe Forced - Shouldn't prompt.
1160 FORCED,
1161 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1162 "http://example.com/foo.txt", "text/plain",
1163 FILE_PATH_LITERAL("foo.txt"),
1164
1165 FILE_PATH_LITERAL(""),
1166 FILE_PATH_LITERAL("foo.txt"),
1167 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1168
1169 EXPECT_LOCAL_PATH
1170 },
1171
1172 {
1173 // 2: Automatic - The filename extension is marked as one that we will
1174 // open automatically. Shouldn't prompt.
1175 AUTOMATIC,
1176 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1177 "http://example.com/foo.dummy", "",
1178 FILE_PATH_LITERAL(""),
1179
1180 FILE_PATH_LITERAL(""),
1181 FILE_PATH_LITERAL("foo.dummy"),
1182 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1183
1184 EXPECT_CRDOWNLOAD
1185 },
1186 };
1187
1188 SetPromptForDownload(true);
1189 EnableAutoOpenBasedOnExtension(
1190 base::FilePath(FILE_PATH_LITERAL("dummy.dummy")));
1191 RunTestCasesWithActiveItem(kPromptingTestCases,
1192 arraysize(kPromptingTestCases));
1193 }
1194
1195 #if !defined(OS_ANDROID)
1196 // These test cases are run with "Prompt for download" user preference set to
1197 // true. Automatic extension downloads shouldn't cause prompting.
1198 // Android doesn't support extensions.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_PromptAlways_Extension)1199 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_PromptAlways_Extension) {
1200 const DownloadTestCase kPromptingTestCases[] = {
1201 {
1202 // 0: Automatic Browser Extension download. - Shouldn't prompt for browser
1203 // extension downloads even if "Prompt for download" preference is set.
1204 AUTOMATIC,
1205 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1206 "http://example.com/foo.crx",
1207 extensions::Extension::kMimeType,
1208 FILE_PATH_LITERAL(""),
1209
1210 FILE_PATH_LITERAL(""),
1211 FILE_PATH_LITERAL("foo.crx"),
1212 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1213
1214 EXPECT_UNCONFIRMED
1215 },
1216
1217 #if defined(OS_WIN)
1218 {
1219 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1220 // even if "Prompt for download" preference is set. ".js" files are
1221 // considered dangerous on Windows.
1222 AUTOMATIC,
1223 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1224 "http://example.com/foo.user.js", "",
1225 FILE_PATH_LITERAL(""),
1226
1227 FILE_PATH_LITERAL(""),
1228 FILE_PATH_LITERAL("foo.user.js"),
1229 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1230
1231 EXPECT_UNCONFIRMED
1232 },
1233 #else
1234 {
1235 // 1: Automatic User Script - Shouldn't prompt for user script downloads
1236 // even if "Prompt for download" preference is set.
1237 AUTOMATIC,
1238 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1239 "http://example.com/foo.user.js", "",
1240 FILE_PATH_LITERAL(""),
1241
1242 FILE_PATH_LITERAL(""),
1243 FILE_PATH_LITERAL("foo.user.js"),
1244 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1245
1246 EXPECT_CRDOWNLOAD
1247 },
1248 #endif
1249 };
1250
1251 SetPromptForDownload(true);
1252 RunTestCasesWithActiveItem(kPromptingTestCases,
1253 arraysize(kPromptingTestCases));
1254 }
1255 #endif
1256
1257 // If the download path is managed, then we don't show any prompts.
1258 // Note that if the download path is managed, then PromptForDownload() is false.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_ManagedPath)1259 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ManagedPath) {
1260 const DownloadTestCase kManagedPathTestCases[] = {
1261 {
1262 // 0: Automatic Safe
1263 AUTOMATIC,
1264 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1265 "http://example.com/foo.txt", "text/plain",
1266 FILE_PATH_LITERAL(""),
1267
1268 FILE_PATH_LITERAL(""),
1269 FILE_PATH_LITERAL("foo.txt"),
1270 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1271
1272 EXPECT_CRDOWNLOAD
1273 },
1274
1275 {
1276 // 1: Save_As Safe
1277 SAVE_AS,
1278 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1279 "http://example.com/foo.txt", "text/plain",
1280 FILE_PATH_LITERAL(""),
1281
1282 FILE_PATH_LITERAL(""),
1283 FILE_PATH_LITERAL("foo.txt"),
1284 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1285
1286 EXPECT_CRDOWNLOAD
1287 },
1288 };
1289
1290 SetManagedDownloadPath(test_download_dir());
1291 ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
1292 RunTestCasesWithActiveItem(kManagedPathTestCases,
1293 arraysize(kManagedPathTestCases));
1294 }
1295
1296 // Test basic functionality supporting extensions that want to override download
1297 // filenames.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_NotifyExtensionsSafe)1298 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsSafe) {
1299 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1300 {
1301 // 0: Automatic Safe
1302 AUTOMATIC,
1303 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1304 "http://example.com/foo.txt", "text/plain",
1305 FILE_PATH_LITERAL(""),
1306
1307 FILE_PATH_LITERAL(""),
1308 FILE_PATH_LITERAL("overridden/foo.txt"),
1309 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1310
1311 EXPECT_CRDOWNLOAD
1312 },
1313
1314 {
1315 // 1: Save_As Safe
1316 SAVE_AS,
1317 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1318 "http://example.com/foo.txt", "text/plain",
1319 FILE_PATH_LITERAL(""),
1320
1321 FILE_PATH_LITERAL(""),
1322 FILE_PATH_LITERAL("overridden/foo.txt"),
1323 DownloadItem::TARGET_DISPOSITION_PROMPT,
1324
1325 EXPECT_CRDOWNLOAD
1326 },
1327
1328 {
1329 // 2: Automatic Dangerous
1330 AUTOMATIC,
1331 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1332 "http://example.com/foo.crx", "",
1333 FILE_PATH_LITERAL(""),
1334
1335 FILE_PATH_LITERAL(""),
1336 FILE_PATH_LITERAL("overridden/foo.crx"),
1337 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1338
1339 EXPECT_UNCONFIRMED
1340 },
1341
1342 {
1343 // 3: Forced Safe
1344 FORCED,
1345 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1346 "http://example.com/foo.txt", "",
1347 FILE_PATH_LITERAL("forced-foo.txt"),
1348
1349 FILE_PATH_LITERAL(""),
1350 FILE_PATH_LITERAL("forced-foo.txt"),
1351 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1352
1353 EXPECT_LOCAL_PATH
1354 },
1355 };
1356
1357 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1358 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1359 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1360 arraysize(kNotifyExtensionsTestCases));
1361 }
1362
1363 // Test that filenames provided by extensions are passed into SafeBrowsing
1364 // checks and dangerous download checks.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_NotifyExtensionsUnsafe)1365 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_NotifyExtensionsUnsafe) {
1366 const DownloadTestCase kNotifyExtensionsTestCases[] = {
1367 {
1368 // 0: Automatic Safe : Later overridden by a dangerous filetype.
1369 AUTOMATIC,
1370 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1371 "http://example.com/foo.crx.remove", "text/plain",
1372 FILE_PATH_LITERAL(""),
1373
1374 FILE_PATH_LITERAL(""),
1375 FILE_PATH_LITERAL("overridden/foo.crx"),
1376 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1377
1378 EXPECT_UNCONFIRMED
1379 },
1380
1381 {
1382 // 1: Automatic Safe : Later overridden by a potentially dangerous
1383 // filetype.
1384 AUTOMATIC,
1385 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
1386 "http://example.com/foo.exe.remove", "text/plain",
1387 FILE_PATH_LITERAL(""),
1388
1389 FILE_PATH_LITERAL(""),
1390 FILE_PATH_LITERAL("overridden/foo.exe"),
1391 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1392
1393 EXPECT_UNCONFIRMED
1394 },
1395 };
1396
1397 ON_CALL(*delegate(), NotifyExtensions(_, _, _))
1398 .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
1399 ON_CALL(*delegate(), CheckDownloadUrl(_, _, _))
1400 .WillByDefault(Invoke(&CheckDownloadUrlCheckExes));
1401 RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
1402 arraysize(kNotifyExtensionsTestCases));
1403 }
1404
1405 // Test that conflict actions set by extensions are passed correctly into
1406 // ReserveVirtualPath.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_NotifyExtensionsConflict)1407 TEST_F(DownloadTargetDeterminerTest,
1408 TargetDeterminer_NotifyExtensionsConflict) {
1409 const DownloadTestCase kNotifyExtensionsTestCase = {
1410 AUTOMATIC,
1411 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1412 "http://example.com/foo.txt", "text/plain",
1413 FILE_PATH_LITERAL(""),
1414
1415 FILE_PATH_LITERAL(""),
1416 FILE_PATH_LITERAL("overridden/foo.txt"),
1417 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1418
1419 EXPECT_CRDOWNLOAD
1420 };
1421
1422 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1423 scoped_ptr<content::MockDownloadItem> item(
1424 CreateActiveDownloadItem(0, test_case));
1425 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1426 base::FilePath full_overridden_path =
1427 GetPathInDownloadDir(overridden_path.value());
1428
1429 // First case: An extension sets the conflict_action to OVERWRITE.
1430 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1431 .WillOnce(WithArg<2>(
1432 ScheduleCallback2(overridden_path,
1433 DownloadPathReservationTracker::OVERWRITE)));
1434 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1435 _, full_overridden_path, true, DownloadPathReservationTracker::OVERWRITE,
1436 _)).WillOnce(WithArg<4>(
1437 ScheduleCallback2(full_overridden_path, true)));
1438
1439 RunTestCase(test_case, base::FilePath(), item.get());
1440
1441 // Second case: An extension sets the conflict_action to PROMPT.
1442 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1443 .WillOnce(WithArg<2>(
1444 ScheduleCallback2(overridden_path,
1445 DownloadPathReservationTracker::PROMPT)));
1446 EXPECT_CALL(*delegate(), ReserveVirtualPath(
1447 _, full_overridden_path, true, DownloadPathReservationTracker::PROMPT, _))
1448 .WillOnce(WithArg<4>(
1449 ScheduleCallback2(full_overridden_path, true)));
1450 RunTestCase(test_case, base::FilePath(), item.get());
1451 }
1452
1453 // Test that relative paths returned by extensions are always relative to the
1454 // default downloads path.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_NotifyExtensionsDefaultPath)1455 TEST_F(DownloadTargetDeterminerTest,
1456 TargetDeterminer_NotifyExtensionsDefaultPath) {
1457 const DownloadTestCase kNotifyExtensionsTestCase = {
1458 SAVE_AS,
1459 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1460 "http://example.com/foo.txt", "text/plain",
1461 FILE_PATH_LITERAL(""),
1462
1463 FILE_PATH_LITERAL(""),
1464 FILE_PATH_LITERAL("overridden/foo.txt"),
1465 DownloadItem::TARGET_DISPOSITION_PROMPT,
1466
1467 EXPECT_CRDOWNLOAD
1468 };
1469
1470 const DownloadTestCase& test_case = kNotifyExtensionsTestCase;
1471 scoped_ptr<content::MockDownloadItem> item(
1472 CreateActiveDownloadItem(0, test_case));
1473 base::FilePath overridden_path(FILE_PATH_LITERAL("overridden/foo.txt"));
1474 base::FilePath full_overridden_path =
1475 GetPathInDownloadDir(overridden_path.value());
1476
1477 download_prefs()->SetSaveFilePath(GetPathInDownloadDir(
1478 FILE_PATH_LITERAL("last_selected")));
1479
1480 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1481 .WillOnce(WithArg<2>(
1482 ScheduleCallback2(overridden_path,
1483 DownloadPathReservationTracker::UNIQUIFY)));
1484 EXPECT_CALL(*delegate(),
1485 PromptUserForDownloadPath(_, full_overridden_path, _))
1486 .WillOnce(WithArg<2>(
1487 ScheduleCallback(full_overridden_path)));
1488 RunTestCase(test_case, base::FilePath(), item.get());
1489 }
1490
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_InitialVirtualPathUnsafe)1491 TEST_F(DownloadTargetDeterminerTest,
1492 TargetDeterminer_InitialVirtualPathUnsafe) {
1493 const base::FilePath::CharType* kInitialPath =
1494 FILE_PATH_LITERAL("some_path/bar.html");
1495
1496 const DownloadTestCase kInitialPathTestCase = {
1497 // 0: Save As Save. The path generated based on the DownloadItem is safe,
1498 // but the initial path is unsafe. However, the download is not considered
1499 // dangerous since the user has been prompted.
1500 SAVE_AS,
1501 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1502 "http://example.com/foo.txt", "text/plain",
1503 FILE_PATH_LITERAL(""),
1504
1505 FILE_PATH_LITERAL(""),
1506 kInitialPath,
1507 DownloadItem::TARGET_DISPOSITION_PROMPT,
1508
1509 EXPECT_CRDOWNLOAD
1510 };
1511
1512 const DownloadTestCase& test_case = kInitialPathTestCase;
1513 scoped_ptr<content::MockDownloadItem> item(
1514 CreateActiveDownloadItem(1, test_case));
1515 EXPECT_CALL(*item, GetLastReason())
1516 .WillRepeatedly(Return(
1517 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1518 EXPECT_CALL(*item, GetTargetDisposition())
1519 .WillRepeatedly(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
1520 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1521 }
1522
1523 // Prompting behavior for resumed downloads is based on the last interrupt
1524 // reason. If the reason indicates that the target path may not be suitable for
1525 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1526 // prompted, and not otherwise. These test cases shouldn't result in prompting
1527 // since the error is set to NETWORK_FAILED.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_ResumedNoPrompt)1528 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedNoPrompt) {
1529 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1530 // path.
1531 const base::FilePath::CharType* kInitialPath =
1532 FILE_PATH_LITERAL("some_path/bar.txt");
1533
1534 const DownloadTestCase kResumedTestCases[] = {
1535 {
1536 // 0: Automatic Safe: Initial path is ignored since the user has not been
1537 // prompted before.
1538 AUTOMATIC,
1539 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1540 "http://example.com/foo.txt", "text/plain",
1541 FILE_PATH_LITERAL(""),
1542
1543 FILE_PATH_LITERAL(""),
1544 FILE_PATH_LITERAL("foo.txt"),
1545 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1546
1547 EXPECT_CRDOWNLOAD
1548 },
1549
1550 {
1551 // 1: Save_As Safe: Initial path used.
1552 SAVE_AS,
1553 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1554 "http://example.com/foo.txt", "text/plain",
1555 FILE_PATH_LITERAL(""),
1556
1557 FILE_PATH_LITERAL(""),
1558 kInitialPath,
1559 DownloadItem::TARGET_DISPOSITION_PROMPT,
1560
1561 EXPECT_CRDOWNLOAD
1562 },
1563
1564 {
1565 // 2: Automatic Dangerous: Initial path is ignored since the user hasn't
1566 // been prompted before.
1567 AUTOMATIC,
1568 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1569 "http://example.com/foo.crx", "",
1570 FILE_PATH_LITERAL(""),
1571
1572 FILE_PATH_LITERAL(""),
1573 FILE_PATH_LITERAL("foo.crx"),
1574 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1575
1576 EXPECT_UNCONFIRMED
1577 },
1578
1579 {
1580 // 3: Forced Safe: Initial path is ignored due to the forced path.
1581 FORCED,
1582 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1583 "http://example.com/foo.txt", "",
1584 FILE_PATH_LITERAL("forced-foo.txt"),
1585
1586 FILE_PATH_LITERAL(""),
1587 FILE_PATH_LITERAL("forced-foo.txt"),
1588 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1589
1590 EXPECT_LOCAL_PATH
1591 },
1592 };
1593
1594 // The test assumes that .crx files have a danger level of
1595 // ALLOW_ON_USER_GESTURE.
1596 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1597 download_util::GetFileDangerLevel(
1598 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1599 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1600 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1601 const DownloadTestCase& test_case = kResumedTestCases[i];
1602 scoped_ptr<content::MockDownloadItem> item(
1603 CreateActiveDownloadItem(i, test_case));
1604 base::FilePath expected_path =
1605 GetPathInDownloadDir(test_case.expected_local_path);
1606 ON_CALL(*item.get(), GetLastReason())
1607 .WillByDefault(Return(
1608 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1609 // Extensions should be notified if a new path is being generated and there
1610 // is no forced path. In the test cases above, this is true for tests with
1611 // type == AUTOMATIC.
1612 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1613 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1614 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1615 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _))
1616 .Times(0);
1617 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1618 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1619 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1620 }
1621
1622 }
1623
1624 // Test that a forced download doesn't prompt, even if the interrupt reason
1625 // suggests that the target path may not be suitable for downloads.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_ResumedForcedDownload)1626 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedForcedDownload) {
1627 const base::FilePath::CharType* kInitialPath =
1628 FILE_PATH_LITERAL("some_path/bar.txt");
1629 const DownloadTestCase kResumedForcedDownload = {
1630 // 3: Forced Safe
1631 FORCED,
1632 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1633 "http://example.com/foo.txt", "",
1634 FILE_PATH_LITERAL("forced-foo.txt"),
1635
1636 FILE_PATH_LITERAL(""),
1637 FILE_PATH_LITERAL("forced-foo.txt"),
1638 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1639
1640 EXPECT_LOCAL_PATH
1641 };
1642
1643 const DownloadTestCase& test_case = kResumedForcedDownload;
1644 base::FilePath expected_path =
1645 GetPathInDownloadDir(test_case.expected_local_path);
1646 scoped_ptr<content::MockDownloadItem> item(
1647 CreateActiveDownloadItem(0, test_case));
1648 ON_CALL(*item.get(), GetLastReason())
1649 .WillByDefault(Return(content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1650 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1651 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1652 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1653 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, _, _))
1654 .Times(0);
1655 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1656 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1657 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1658 }
1659
1660 // Prompting behavior for resumed downloads is based on the last interrupt
1661 // reason. If the reason indicates that the target path may not be suitable for
1662 // the download (ACCESS_DENIED, NO_SPACE, etc..), then the user should be
1663 // prompted, and not otherwise. These test cases result in prompting since the
1664 // error is set to NO_SPACE.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_ResumedWithPrompt)1665 TEST_F(DownloadTargetDeterminerTest, TargetDeterminer_ResumedWithPrompt) {
1666 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1667 // path.
1668 const base::FilePath::CharType* kInitialPath =
1669 FILE_PATH_LITERAL("some_path/bar.txt");
1670
1671 const DownloadTestCase kResumedTestCases[] = {
1672 {
1673 // 0: Automatic Safe
1674 AUTOMATIC,
1675 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1676 "http://example.com/foo.txt", "text/plain",
1677 FILE_PATH_LITERAL(""),
1678
1679 FILE_PATH_LITERAL(""),
1680 FILE_PATH_LITERAL("foo.txt"),
1681 DownloadItem::TARGET_DISPOSITION_PROMPT,
1682
1683 EXPECT_CRDOWNLOAD
1684 },
1685
1686 {
1687 // 1: Save_As Safe
1688 SAVE_AS,
1689 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1690 "http://example.com/foo.txt", "text/plain",
1691 FILE_PATH_LITERAL(""),
1692
1693 FILE_PATH_LITERAL(""),
1694 kInitialPath,
1695 DownloadItem::TARGET_DISPOSITION_PROMPT,
1696
1697 EXPECT_CRDOWNLOAD
1698 },
1699
1700 {
1701 // 2: Automatic Dangerous
1702 AUTOMATIC,
1703 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1704 "http://example.com/foo.crx", "",
1705 FILE_PATH_LITERAL(""),
1706
1707 FILE_PATH_LITERAL(""),
1708 FILE_PATH_LITERAL("foo.crx"),
1709 DownloadItem::TARGET_DISPOSITION_PROMPT,
1710
1711 EXPECT_CRDOWNLOAD
1712 },
1713 };
1714
1715 // The test assumes that .xml files have a danger level of
1716 // ALLOW_ON_USER_GESTURE.
1717 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1718 download_util::GetFileDangerLevel(
1719 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1720 for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
1721 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1722 download_prefs()->SetSaveFilePath(test_download_dir());
1723 const DownloadTestCase& test_case = kResumedTestCases[i];
1724 base::FilePath expected_path =
1725 GetPathInDownloadDir(test_case.expected_local_path);
1726 scoped_ptr<content::MockDownloadItem> item(
1727 CreateActiveDownloadItem(i, test_case));
1728 ON_CALL(*item.get(), GetLastReason())
1729 .WillByDefault(Return(
1730 content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
1731 EXPECT_CALL(*delegate(), NotifyExtensions(_, _, _))
1732 .Times(test_case.test_type == AUTOMATIC ? 1 : 0);
1733 EXPECT_CALL(*delegate(), ReserveVirtualPath(_, expected_path, false, _, _));
1734 EXPECT_CALL(*delegate(), PromptUserForDownloadPath(_, expected_path, _));
1735 EXPECT_CALL(*delegate(), DetermineLocalPath(_, expected_path, _));
1736 EXPECT_CALL(*delegate(), CheckDownloadUrl(_, expected_path, _));
1737 RunTestCase(test_case, GetPathInDownloadDir(kInitialPath), item.get());
1738 }
1739 }
1740
1741 // Test intermediate filename generation for resumed downloads.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_IntermediateNameForResumed)1742 TEST_F(DownloadTargetDeterminerTest,
1743 TargetDeterminer_IntermediateNameForResumed) {
1744 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1745 // path.
1746 const base::FilePath::CharType kInitialPath[] =
1747 FILE_PATH_LITERAL("some_path/bar.txt");
1748
1749 struct IntermediateNameTestCase {
1750 // General test case settings.
1751 DownloadTestCase general;
1752
1753 // Value of DownloadItem::GetFullPath() during test run, relative
1754 // to test download path.
1755 const base::FilePath::CharType* initial_intermediate_path;
1756
1757 // Expected intermediate path relatvie to the test download path. An exact
1758 // match is performed if this string is non-empty. Ignored otherwise.
1759 const base::FilePath::CharType* expected_intermediate_path;
1760 } kIntermediateNameTestCases[] = {
1761 {
1762 {
1763 // 0: Automatic Safe
1764 AUTOMATIC,
1765 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1766 "http://example.com/foo.txt", "text/plain",
1767 FILE_PATH_LITERAL(""),
1768
1769 FILE_PATH_LITERAL(""),
1770 FILE_PATH_LITERAL("foo.txt"),
1771 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1772
1773 EXPECT_CRDOWNLOAD
1774 },
1775 FILE_PATH_LITERAL("bar.txt.crdownload"),
1776 FILE_PATH_LITERAL("foo.txt.crdownload")
1777 },
1778
1779 {
1780 {
1781 // 1: Save_As Safe
1782 SAVE_AS,
1783 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1784 "http://example.com/foo.txt", "text/plain",
1785 FILE_PATH_LITERAL(""),
1786
1787 FILE_PATH_LITERAL(""),
1788 kInitialPath,
1789 DownloadItem::TARGET_DISPOSITION_PROMPT,
1790
1791 EXPECT_CRDOWNLOAD
1792 },
1793 FILE_PATH_LITERAL("foo.txt.crdownload"),
1794 FILE_PATH_LITERAL("some_path/bar.txt.crdownload")
1795 },
1796
1797 {
1798 {
1799 // 2: Automatic Dangerous
1800 AUTOMATIC,
1801 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1802 "http://example.com/foo.crx", "",
1803 FILE_PATH_LITERAL(""),
1804
1805 FILE_PATH_LITERAL(""),
1806 FILE_PATH_LITERAL("foo.crx"),
1807 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1808
1809 EXPECT_UNCONFIRMED
1810 },
1811 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload"),
1812 FILE_PATH_LITERAL("Unconfirmed abcd.crdownload")
1813 },
1814
1815 {
1816 {
1817 // 3: Automatic Dangerous
1818 AUTOMATIC,
1819 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
1820 "http://example.com/foo.crx", "",
1821 FILE_PATH_LITERAL(""),
1822
1823 FILE_PATH_LITERAL(""),
1824 FILE_PATH_LITERAL("foo.crx"),
1825 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1826
1827 EXPECT_UNCONFIRMED
1828 },
1829 FILE_PATH_LITERAL("other_path/Unconfirmed abcd.crdownload"),
1830 // Rely on the EXPECT_UNCONFIRMED check in the general test settings. A
1831 // new intermediate path of the form "Unconfirmed <number>.crdownload"
1832 // should be generated for this case since the initial intermediate path
1833 // is in the wrong directory.
1834 FILE_PATH_LITERAL("")
1835 },
1836
1837 {
1838 {
1839 // 3: Forced Safe: Initial path is ignored due to the forced path.
1840 FORCED,
1841 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1842 "http://example.com/foo.txt", "",
1843 FILE_PATH_LITERAL("forced-foo.txt"),
1844
1845 FILE_PATH_LITERAL(""),
1846 FILE_PATH_LITERAL("forced-foo.txt"),
1847 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1848
1849 EXPECT_LOCAL_PATH
1850 },
1851 FILE_PATH_LITERAL("forced-foo.txt"),
1852 FILE_PATH_LITERAL("forced-foo.txt")
1853 },
1854 };
1855
1856 // The test assumes that .crx files have a danger level of
1857 // ALLOW_ON_USER_GESTURE.
1858 ASSERT_EQ(download_util::ALLOW_ON_USER_GESTURE,
1859 download_util::GetFileDangerLevel(
1860 base::FilePath(FILE_PATH_LITERAL("foo.crx"))));
1861
1862 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kIntermediateNameTestCases); ++i) {
1863 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1864 const IntermediateNameTestCase& test_case = kIntermediateNameTestCases[i];
1865 scoped_ptr<content::MockDownloadItem> item(
1866 CreateActiveDownloadItem(i, test_case.general));
1867
1868 ON_CALL(*item.get(), GetLastReason())
1869 .WillByDefault(Return(
1870 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
1871 ON_CALL(*item.get(), GetFullPath())
1872 .WillByDefault(ReturnRefOfCopy(
1873 GetPathInDownloadDir(test_case.initial_intermediate_path)));
1874 ON_CALL(*item.get(), GetDangerType())
1875 .WillByDefault(Return(test_case.general.expected_danger_type));
1876
1877 scoped_ptr<DownloadTargetInfo> target_info =
1878 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1879 item.get());
1880 VerifyDownloadTarget(test_case.general, target_info.get());
1881 base::FilePath expected_intermediate_path =
1882 GetPathInDownloadDir(test_case.expected_intermediate_path);
1883 if (!expected_intermediate_path.empty())
1884 EXPECT_EQ(expected_intermediate_path, target_info->intermediate_path);
1885 }
1886 }
1887
1888 // Test MIME type determination based on the target filename.
TEST_F(DownloadTargetDeterminerTest,TargetDeterminer_MIMETypeDetermination)1889 TEST_F(DownloadTargetDeterminerTest,
1890 TargetDeterminer_MIMETypeDetermination) {
1891 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
1892 // path.
1893 const base::FilePath::CharType kInitialPath[] =
1894 FILE_PATH_LITERAL("some_path/bar.txt");
1895
1896 struct MIMETypeTestCase {
1897 // General test case settings.
1898 DownloadTestCase general;
1899
1900 // Expected MIME type for test case.
1901 const char* expected_mime_type;
1902 } kMIMETypeTestCases[] = {
1903 {
1904 {
1905 // 0:
1906 AUTOMATIC,
1907 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1908 "http://example.com/foo.png", "image/png",
1909 FILE_PATH_LITERAL(""),
1910
1911 FILE_PATH_LITERAL(""),
1912 FILE_PATH_LITERAL("foo.png"),
1913 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1914
1915 EXPECT_CRDOWNLOAD
1916 },
1917 "image/png"
1918 },
1919 {
1920 {
1921 // 1: Empty MIME type in response.
1922 AUTOMATIC,
1923 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1924 "http://example.com/foo.png", "",
1925 FILE_PATH_LITERAL(""),
1926
1927 FILE_PATH_LITERAL(""),
1928 FILE_PATH_LITERAL("foo.png"),
1929 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1930
1931 EXPECT_CRDOWNLOAD
1932 },
1933 "image/png"
1934 },
1935 {
1936 {
1937 // 2: Forced path.
1938 FORCED,
1939 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1940 "http://example.com/foo.abc", "",
1941 FILE_PATH_LITERAL("foo.png"),
1942
1943 FILE_PATH_LITERAL(""),
1944 FILE_PATH_LITERAL("foo.png"),
1945 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1946
1947 EXPECT_CRDOWNLOAD
1948 },
1949 "image/png"
1950 },
1951 {
1952 {
1953 // 3: Unknown file type.
1954 AUTOMATIC,
1955 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1956 "http://example.com/foo.notarealext", "",
1957 FILE_PATH_LITERAL(""),
1958
1959 FILE_PATH_LITERAL(""),
1960 FILE_PATH_LITERAL("foo.notarealext"),
1961 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1962
1963 EXPECT_CRDOWNLOAD
1964 },
1965 ""
1966 },
1967 {
1968 {
1969 // 4: Unknown file type.
1970 AUTOMATIC,
1971 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
1972 "http://example.com/foo.notarealext", "image/png",
1973 FILE_PATH_LITERAL(""),
1974
1975 FILE_PATH_LITERAL(""),
1976 FILE_PATH_LITERAL("foo.notarealext"),
1977 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
1978
1979 EXPECT_CRDOWNLOAD
1980 },
1981 ""
1982 },
1983 };
1984
1985 ON_CALL(*delegate(), GetFileMimeType(
1986 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.png")), _))
1987 .WillByDefault(WithArg<1>(
1988 ScheduleCallback("image/png")));
1989
1990 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kMIMETypeTestCases); ++i) {
1991 SCOPED_TRACE(testing::Message() << "Running test case " << i);
1992 const MIMETypeTestCase& test_case = kMIMETypeTestCases[i];
1993 scoped_ptr<content::MockDownloadItem> item(
1994 CreateActiveDownloadItem(i, test_case.general));
1995 scoped_ptr<DownloadTargetInfo> target_info =
1996 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
1997 item.get());
1998 EXPECT_EQ(test_case.expected_mime_type, target_info->mime_type);
1999 }
2000 }
2001
2002 #if defined(ENABLE_PLUGINS)
2003
DummyGetPluginsCallback(const base::Closure & closure,const std::vector<content::WebPluginInfo> & plugins)2004 void DummyGetPluginsCallback(
2005 const base::Closure& closure,
2006 const std::vector<content::WebPluginInfo>& plugins) {
2007 closure.Run();
2008 }
2009
ForceRefreshOfPlugins()2010 void ForceRefreshOfPlugins() {
2011 #if !defined(OS_WIN)
2012 // Prevent creation of a utility process for loading plugins. Doing so breaks
2013 // unit_tests since /proc/self/exe can't be run as a utility process.
2014 content::RenderProcessHost::SetRunRendererInProcess(true);
2015 #endif
2016 base::RunLoop run_loop;
2017 content::PluginService::GetInstance()->GetPlugins(
2018 base::Bind(&DummyGetPluginsCallback, run_loop.QuitClosure()));
2019 run_loop.Run();
2020 #if !defined(OS_WIN)
2021 content::RenderProcessHost::SetRunRendererInProcess(false);
2022 #endif
2023 }
2024
PluginEnabledCallback(const base::Closure & closure,bool result)2025 void PluginEnabledCallback(const base::Closure& closure,
2026 bool result) {
2027 EXPECT_TRUE(result);
2028 closure.Run();
2029 }
2030
EnablePlugin(bool enable,PluginPrefs * prefs,const base::FilePath & path)2031 void EnablePlugin(bool enable, PluginPrefs* prefs, const base::FilePath& path) {
2032 base::RunLoop run_loop;
2033 prefs->EnablePlugin(enable, path,
2034 base::Bind(&PluginEnabledCallback,
2035 run_loop.QuitClosure()));
2036 run_loop.Run();
2037 }
2038
2039 class ScopedRegisterInternalPlugin {
2040 public:
ScopedRegisterInternalPlugin(content::PluginService * plugin_service,content::WebPluginInfo::PluginType type,const base::FilePath & path,const char * mime_type,const char * extension)2041 ScopedRegisterInternalPlugin(content::PluginService* plugin_service,
2042 content::WebPluginInfo::PluginType type,
2043 const base::FilePath& path,
2044 const char* mime_type,
2045 const char* extension)
2046 : plugin_service_(plugin_service),
2047 plugin_path_(path) {
2048 content::WebPluginMimeType plugin_mime_type(mime_type,
2049 extension,
2050 "Test file");
2051 content::WebPluginInfo plugin_info(base::string16(),
2052 path,
2053 base::string16(),
2054 base::string16());
2055 plugin_info.mime_types.push_back(plugin_mime_type);
2056 plugin_info.type = type;
2057
2058 plugin_service->RegisterInternalPlugin(plugin_info, true);
2059 plugin_service->RefreshPlugins();
2060 ForceRefreshOfPlugins();
2061 }
2062
~ScopedRegisterInternalPlugin()2063 ~ScopedRegisterInternalPlugin() {
2064 plugin_service_->UnregisterInternalPlugin(plugin_path_);
2065 plugin_service_->RefreshPlugins();
2066 ForceRefreshOfPlugins();
2067 }
2068
path()2069 const base::FilePath& path() { return plugin_path_; }
2070
2071 private:
2072 content::PluginService* plugin_service_;
2073 base::FilePath plugin_path_;
2074 };
2075
2076 // We use a slightly different test fixture for tests that touch plugins. SetUp
2077 // needs to disable plugin discovery and we need to use a
2078 // ShadowingAtExitManager to discard the tainted PluginService. Unfortunately,
2079 // PluginService carries global state.
2080 class DownloadTargetDeterminerTestWithPlugin :
2081 public DownloadTargetDeterminerTest {
2082 public:
SetUp()2083 virtual void SetUp() OVERRIDE {
2084 content::PluginService::GetInstance()->Init();
2085 content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
2086 DownloadTargetDeterminerTest::SetUp();
2087 }
2088
2089 protected:
2090 // The ShadowingAtExitManager destroys the tainted PluginService instance.
2091 base::ShadowingAtExitManager at_exit_manager_;
2092 };
2093
2094 // Check if secure handling of filetypes is determined correctly for PPAPI
2095 // plugins.
TEST_F(DownloadTargetDeterminerTestWithPlugin,TargetDeterminer_CheckForSecureHandling_PPAPI)2096 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2097 TargetDeterminer_CheckForSecureHandling_PPAPI) {
2098 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2099 // path.
2100 const base::FilePath::CharType kInitialPath[] =
2101 FILE_PATH_LITERAL("some_path/bar.txt");
2102 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2103
2104 DownloadTestCase kSecureHandlingTestCase = {
2105 AUTOMATIC,
2106 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2107 "http://example.com/foo.fakeext", "",
2108 FILE_PATH_LITERAL(""),
2109
2110 FILE_PATH_LITERAL(""),
2111 FILE_PATH_LITERAL("foo.fakeext"),
2112 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2113
2114 EXPECT_CRDOWNLOAD
2115 };
2116
2117 content::PluginService* plugin_service =
2118 content::PluginService::GetInstance();
2119 // This creates a PluginPrefs for our TestingProfile.
2120 scoped_refptr<PluginPrefs> plugin_prefs =
2121 PluginPrefs::GetForTestingProfile(profile());
2122
2123 // Verify our test assumptions.
2124 {
2125 ForceRefreshOfPlugins();
2126 std::vector<content::WebPluginInfo> info;
2127 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2128 GURL(), kTestMIMEType, false, &info, NULL));
2129 ASSERT_EQ(0u, info.size())
2130 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2131 }
2132
2133 ON_CALL(*delegate(), GetFileMimeType(
2134 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2135 .WillByDefault(WithArg<1>(
2136 ScheduleCallback(kTestMIMEType)));
2137 scoped_ptr<content::MockDownloadItem> item(
2138 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2139 scoped_ptr<DownloadTargetInfo> target_info =
2140 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2141 item.get());
2142 EXPECT_FALSE(target_info->is_filetype_handled_securely);
2143
2144 // Register a PPAPI plugin. This should count as handling the filetype
2145 // securely.
2146 ScopedRegisterInternalPlugin ppapi_plugin(
2147 plugin_service,
2148 content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS,
2149 test_download_dir().AppendASCII("ppapi"),
2150 kTestMIMEType,
2151 "fakeext");
2152
2153 target_info = RunDownloadTargetDeterminer(
2154 GetPathInDownloadDir(kInitialPath), item.get());
2155 EXPECT_TRUE(target_info->is_filetype_handled_securely);
2156
2157 // Try disabling the plugin. Handling should no longer be considered secure.
2158 EnablePlugin(false, plugin_prefs, ppapi_plugin.path());
2159 target_info = RunDownloadTargetDeterminer(
2160 GetPathInDownloadDir(kInitialPath), item.get());
2161 EXPECT_FALSE(target_info->is_filetype_handled_securely);
2162
2163 // Now register an unsandboxed PPAPI plug-in. This plugin should not be
2164 // considered secure.
2165 ScopedRegisterInternalPlugin ppapi_unsandboxed_plugin(
2166 plugin_service,
2167 content::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED,
2168 test_download_dir().AppendASCII("ppapi-nosandbox"),
2169 kTestMIMEType,
2170 "fakeext");
2171
2172 target_info = RunDownloadTargetDeterminer(
2173 GetPathInDownloadDir(kInitialPath), item.get());
2174 EXPECT_FALSE(target_info->is_filetype_handled_securely);
2175 }
2176
2177 // Check if secure handling of filetypes is determined correctly for NPAPI
2178 // plugins.
TEST_F(DownloadTargetDeterminerTestWithPlugin,TargetDeterminer_CheckForSecureHandling_NPAPI)2179 TEST_F(DownloadTargetDeterminerTestWithPlugin,
2180 TargetDeterminer_CheckForSecureHandling_NPAPI) {
2181 // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital
2182 // path.
2183 const base::FilePath::CharType kInitialPath[] =
2184 FILE_PATH_LITERAL("some_path/bar.txt");
2185 const char kTestMIMEType[] = "application/x-example-should-not-exist";
2186
2187 DownloadTestCase kSecureHandlingTestCase = {
2188 AUTOMATIC,
2189 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
2190 "http://example.com/foo.fakeext", "",
2191 FILE_PATH_LITERAL(""),
2192
2193 FILE_PATH_LITERAL(""),
2194 FILE_PATH_LITERAL("foo.fakeext"),
2195 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
2196
2197 EXPECT_CRDOWNLOAD
2198 };
2199
2200 content::PluginService* plugin_service =
2201 content::PluginService::GetInstance();
2202
2203 // Can't run this test if NPAPI isn't supported.
2204 if (!plugin_service->NPAPIPluginsSupported())
2205 return;
2206
2207 // This creates a PluginPrefs for our TestingProfile.
2208 scoped_refptr<PluginPrefs> plugin_prefs =
2209 PluginPrefs::GetForTestingProfile(profile());
2210
2211 // Verify our test assumptions.
2212 {
2213 ForceRefreshOfPlugins();
2214 std::vector<content::WebPluginInfo> info;
2215 ASSERT_FALSE(plugin_service->GetPluginInfoArray(
2216 GURL(), kTestMIMEType, false, &info, NULL));
2217 ASSERT_EQ(0u, info.size())
2218 << "Name: " << info[0].name << ", Path: " << info[0].path.value();
2219 }
2220
2221 ON_CALL(*delegate(), GetFileMimeType(
2222 GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _))
2223 .WillByDefault(WithArg<1>(
2224 ScheduleCallback(kTestMIMEType)));
2225 scoped_ptr<content::MockDownloadItem> item(
2226 CreateActiveDownloadItem(1, kSecureHandlingTestCase));
2227 scoped_ptr<DownloadTargetInfo> target_info =
2228 RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath),
2229 item.get());
2230 EXPECT_FALSE(target_info->is_filetype_handled_securely);
2231
2232 // Register a NPAPI plugin. This should not count as handling the filetype
2233 // securely.
2234 ScopedRegisterInternalPlugin npapi_plugin(
2235 plugin_service,
2236 content::WebPluginInfo::PLUGIN_TYPE_NPAPI,
2237 test_download_dir().AppendASCII("npapi"),
2238 kTestMIMEType,
2239 "fakeext");
2240
2241 target_info = RunDownloadTargetDeterminer(
2242 GetPathInDownloadDir(kInitialPath), item.get());
2243 EXPECT_FALSE(target_info->is_filetype_handled_securely);
2244 }
2245 #endif // ENABLE_PLUGINS
2246
2247 } // namespace
2248