1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/callback.h"
6 #include "base/command_line.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/stl_util.h"
9 #include "base/threading/thread.h"
10 #include "content/browser/byte_stream.h"
11 #include "content/browser/download/download_create_info.h"
12 #include "content/browser/download/download_file_factory.h"
13 #include "content/browser/download/download_item_impl.h"
14 #include "content/browser/download/download_item_impl_delegate.h"
15 #include "content/browser/download/download_request_handle.h"
16 #include "content/browser/download/mock_download_file.h"
17 #include "content/public/browser/download_destination_observer.h"
18 #include "content/public/browser/download_interrupt_reasons.h"
19 #include "content/public/browser/download_url_parameters.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/test/mock_download_item.h"
22 #include "content/public/test/test_browser_thread.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
27 using ::testing::NiceMock
;
28 using ::testing::Property
;
29 using ::testing::Return
;
30 using ::testing::SaveArg
;
31 using ::testing::StrictMock
;
33 const int kDownloadChunkSize
= 1000;
34 const int kDownloadSpeed
= 1000;
35 const base::FilePath::CharType kDummyPath
[] = FILE_PATH_LITERAL("/testpath");
41 class MockDelegate
: public DownloadItemImplDelegate
{
43 MockDelegate() : DownloadItemImplDelegate() {
44 SetDefaultExpectations();
47 MOCK_METHOD2(DetermineDownloadTarget
, void(
48 DownloadItemImpl
*, const DownloadTargetCallback
&));
49 MOCK_METHOD2(ShouldCompleteDownload
,
50 bool(DownloadItemImpl
*, const base::Closure
&));
51 MOCK_METHOD2(ShouldOpenDownload
,
52 bool(DownloadItemImpl
*, const ShouldOpenDownloadCallback
&));
53 MOCK_METHOD1(ShouldOpenFileBasedOnExtension
, bool(const base::FilePath
&));
54 MOCK_METHOD1(CheckForFileRemoval
, void(DownloadItemImpl
*));
56 virtual void ResumeInterruptedDownload(
57 scoped_ptr
<DownloadUrlParameters
> params
, uint32 id
) OVERRIDE
{
58 MockResumeInterruptedDownload(params
.get(), id
);
60 MOCK_METHOD2(MockResumeInterruptedDownload
,
61 void(DownloadUrlParameters
* params
, uint32 id
));
63 MOCK_CONST_METHOD0(GetBrowserContext
, BrowserContext
*());
64 MOCK_METHOD1(UpdatePersistence
, void(DownloadItemImpl
*));
65 MOCK_METHOD1(DownloadOpened
, void(DownloadItemImpl
*));
66 MOCK_METHOD1(DownloadRemoved
, void(DownloadItemImpl
*));
67 MOCK_CONST_METHOD1(AssertStateConsistent
, void(DownloadItemImpl
*));
69 void VerifyAndClearExpectations() {
70 ::testing::Mock::VerifyAndClearExpectations(this);
71 SetDefaultExpectations();
75 void SetDefaultExpectations() {
76 EXPECT_CALL(*this, AssertStateConsistent(_
))
77 .WillRepeatedly(Return());
78 EXPECT_CALL(*this, ShouldOpenFileBasedOnExtension(_
))
79 .WillRepeatedly(Return(false));
80 EXPECT_CALL(*this, ShouldOpenDownload(_
, _
))
81 .WillRepeatedly(Return(true));
85 class MockRequestHandle
: public DownloadRequestHandleInterface
{
87 MOCK_CONST_METHOD0(GetWebContents
, WebContents
*());
88 MOCK_CONST_METHOD0(GetDownloadManager
, DownloadManager
*());
89 MOCK_CONST_METHOD0(PauseRequest
, void());
90 MOCK_CONST_METHOD0(ResumeRequest
, void());
91 MOCK_CONST_METHOD0(CancelRequest
, void());
92 MOCK_CONST_METHOD0(DebugString
, std::string());
95 // Schedules a task to invoke the RenameCompletionCallback with |new_path| on
96 // the UI thread. Should only be used as the action for
97 // MockDownloadFile::Rename as follows:
98 // EXPECT_CALL(download_file, Rename*(_,_))
99 // .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
101 ACTION_P2(ScheduleRenameCallback
, interrupt_reason
, new_path
) {
102 BrowserThread::PostTask(
103 BrowserThread::UI
, FROM_HERE
,
104 base::Bind(arg1
, interrupt_reason
, new_path
));
109 class DownloadItemTest
: public testing::Test
{
111 class MockObserver
: public DownloadItem::Observer
{
113 explicit MockObserver(DownloadItem
* item
)
115 last_state_(item
->GetState()),
121 item_
->AddObserver(this);
124 virtual ~MockObserver() {
125 if (item_
) item_
->RemoveObserver(this);
128 virtual void OnDownloadRemoved(DownloadItem
* download
) OVERRIDE
{
129 DVLOG(20) << " " << __FUNCTION__
130 << " download = " << download
->DebugString(false);
134 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
{
135 DVLOG(20) << " " << __FUNCTION__
136 << " download = " << download
->DebugString(false);
138 DownloadItem::DownloadState new_state
= download
->GetState();
139 if (last_state_
== DownloadItem::IN_PROGRESS
&&
140 new_state
== DownloadItem::INTERRUPTED
) {
143 if (last_state_
== DownloadItem::INTERRUPTED
&&
144 new_state
== DownloadItem::IN_PROGRESS
) {
147 last_state_
= new_state
;
150 virtual void OnDownloadOpened(DownloadItem
* download
) OVERRIDE
{
151 DVLOG(20) << " " << __FUNCTION__
152 << " download = " << download
->DebugString(false);
155 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
{
156 DVLOG(20) << " " << __FUNCTION__
157 << " download = " << download
->DebugString(false);
159 item_
->RemoveObserver(this);
163 bool CheckRemoved() {
167 bool CheckDestroyed() {
171 bool CheckUpdated() {
172 bool was_updated
= updated_
;
177 int GetInterruptCount() {
178 return interrupt_count_
;
181 int GetResumeCount() {
182 return resume_count_
;
187 DownloadItem::DownloadState last_state_
;
191 int interrupt_count_
;
196 : ui_thread_(BrowserThread::UI
, &loop_
),
197 file_thread_(BrowserThread::FILE, &loop_
),
201 ~DownloadItemTest() {
204 virtual void SetUp() {
207 virtual void TearDown() {
208 ui_thread_
.DeprecatedGetThreadObject()->message_loop()->RunUntilIdle();
209 STLDeleteElements(&allocated_downloads_
);
210 allocated_downloads_
.clear();
213 // This class keeps ownership of the created download item; it will
214 // be torn down at the end of the test unless DestroyDownloadItem is
216 DownloadItemImpl
* CreateDownloadItem() {
217 // Normally, the download system takes ownership of info, and is
218 // responsible for deleting it. In these unit tests, however, we
219 // don't call the function that deletes it, so we do so ourselves.
220 scoped_ptr
<DownloadCreateInfo
> info_
;
222 info_
.reset(new DownloadCreateInfo());
223 static uint32 next_id
= DownloadItem::kInvalidId
+ 1;
224 info_
->save_info
= scoped_ptr
<DownloadSaveInfo
>(new DownloadSaveInfo());
225 info_
->save_info
->prompt_for_save_location
= false;
226 info_
->url_chain
.push_back(GURL());
227 info_
->etag
= "SomethingToSatisfyResumption";
229 DownloadItemImpl
* download
=
230 new DownloadItemImpl(
231 &delegate_
, next_id
++, *(info_
.get()), net::BoundNetLog());
232 allocated_downloads_
.insert(download
);
236 // Add DownloadFile to DownloadItem
237 MockDownloadFile
* AddDownloadFileToDownloadItem(
238 DownloadItemImpl
* item
,
239 DownloadItemImplDelegate::DownloadTargetCallback
*callback
) {
240 MockDownloadFile
* mock_download_file(new StrictMock
<MockDownloadFile
>);
241 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
242 EXPECT_CALL(*mock_download_file
, Initialize(_
));
244 // Save the callback.
245 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
246 .WillOnce(SaveArg
<1>(callback
));
248 // Drop it on the floor.
249 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
252 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
253 new NiceMock
<MockRequestHandle
>);
254 item
->Start(download_file
.Pass(), request_handle
.Pass());
255 loop_
.RunUntilIdle();
257 // So that we don't have a function writing to a stack variable
258 // lying around if the above failed.
259 mock_delegate()->VerifyAndClearExpectations();
260 EXPECT_CALL(*mock_delegate(), AssertStateConsistent(_
))
261 .WillRepeatedly(Return());
262 EXPECT_CALL(*mock_delegate(), ShouldOpenFileBasedOnExtension(_
))
263 .WillRepeatedly(Return(false));
264 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(_
, _
))
265 .WillRepeatedly(Return(true));
267 return mock_download_file
;
270 // Perform the intermediate rename for |item|. The target path for the
271 // download will be set to kDummyPath. Returns the MockDownloadFile* that was
272 // added to the DownloadItem.
273 MockDownloadFile
* DoIntermediateRename(DownloadItemImpl
* item
,
274 DownloadDangerType danger_type
) {
275 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
276 EXPECT_TRUE(item
->GetTargetFilePath().empty());
277 DownloadItemImplDelegate::DownloadTargetCallback callback
;
278 MockDownloadFile
* download_file
=
279 AddDownloadFileToDownloadItem(item
, &callback
);
280 base::FilePath
target_path(kDummyPath
);
281 base::FilePath
intermediate_path(
282 target_path
.InsertBeforeExtensionASCII("x"));
283 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
284 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
286 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
287 danger_type
, intermediate_path
);
288 RunAllPendingInMessageLoops();
289 return download_file
;
292 // Cleanup a download item (specifically get rid of the DownloadFile on it).
293 // The item must be in the expected state.
294 void CleanupItem(DownloadItemImpl
* item
,
295 MockDownloadFile
* download_file
,
296 DownloadItem::DownloadState expected_state
) {
297 EXPECT_EQ(expected_state
, item
->GetState());
299 if (expected_state
== DownloadItem::IN_PROGRESS
) {
300 EXPECT_CALL(*download_file
, Cancel());
302 loop_
.RunUntilIdle();
306 // Destroy a previously created download item.
307 void DestroyDownloadItem(DownloadItem
* item
) {
308 allocated_downloads_
.erase(item
);
312 void RunAllPendingInMessageLoops() {
313 loop_
.RunUntilIdle();
316 MockDelegate
* mock_delegate() {
320 void OnDownloadFileAcquired(base::FilePath
* return_path
,
321 const base::FilePath
& path
) {
326 base::MessageLoopForUI loop_
;
327 TestBrowserThread ui_thread_
; // UI thread
328 TestBrowserThread file_thread_
; // FILE thread
329 StrictMock
<MockDelegate
> delegate_
;
330 std::set
<DownloadItem
*> allocated_downloads_
;
333 // Tests to ensure calls that change a DownloadItem generate an update to
335 // State changing functions not tested:
336 // void OpenDownload();
337 // void ShowDownloadInShell();
338 // void CompleteDelayedDownload();
341 TEST_F(DownloadItemTest
, NotificationAfterUpdate
) {
342 DownloadItemImpl
* item
= CreateDownloadItem();
343 MockObserver
observer(item
);
345 item
->DestinationUpdate(kDownloadChunkSize
, kDownloadSpeed
, std::string());
346 ASSERT_TRUE(observer
.CheckUpdated());
347 EXPECT_EQ(kDownloadSpeed
, item
->CurrentSpeed());
350 TEST_F(DownloadItemTest
, NotificationAfterCancel
) {
351 DownloadItemImpl
* user_cancel
= CreateDownloadItem();
352 MockDownloadFile
* download_file
=
353 AddDownloadFileToDownloadItem(user_cancel
, NULL
);
354 EXPECT_CALL(*download_file
, Cancel());
355 MockObserver
observer1(user_cancel
);
357 user_cancel
->Cancel(true);
358 ASSERT_TRUE(observer1
.CheckUpdated());
360 DownloadItemImpl
* system_cancel
= CreateDownloadItem();
361 download_file
= AddDownloadFileToDownloadItem(system_cancel
, NULL
);
362 EXPECT_CALL(*download_file
, Cancel());
363 MockObserver
observer2(system_cancel
);
365 system_cancel
->Cancel(false);
366 ASSERT_TRUE(observer2
.CheckUpdated());
369 TEST_F(DownloadItemTest
, NotificationAfterComplete
) {
370 DownloadItemImpl
* item
= CreateDownloadItem();
371 MockObserver
observer(item
);
373 item
->OnAllDataSaved(DownloadItem::kEmptyFileHash
);
374 ASSERT_TRUE(observer
.CheckUpdated());
376 item
->MarkAsComplete();
377 ASSERT_TRUE(observer
.CheckUpdated());
380 TEST_F(DownloadItemTest
, NotificationAfterDownloadedFileRemoved
) {
381 DownloadItemImpl
* item
= CreateDownloadItem();
382 MockObserver
observer(item
);
384 item
->OnDownloadedFileRemoved();
385 ASSERT_TRUE(observer
.CheckUpdated());
388 TEST_F(DownloadItemTest
, NotificationAfterInterrupted
) {
389 DownloadItemImpl
* item
= CreateDownloadItem();
390 MockDownloadFile
* download_file
=
391 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
392 EXPECT_CALL(*download_file
, Cancel());
393 MockObserver
observer(item
);
395 EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_
,_
))
398 item
->DestinationObserverAsWeakPtr()->DestinationError(
399 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
400 ASSERT_TRUE(observer
.CheckUpdated());
403 TEST_F(DownloadItemTest
, NotificationAfterDestroyed
) {
404 DownloadItemImpl
* item
= CreateDownloadItem();
405 MockObserver
observer(item
);
407 DestroyDownloadItem(item
);
408 ASSERT_TRUE(observer
.CheckDestroyed());
411 TEST_F(DownloadItemTest
, ContinueAfterInterrupted
) {
412 base::CommandLine::ForCurrentProcess()->AppendSwitch(
413 switches::kEnableDownloadResumption
);
415 DownloadItemImpl
* item
= CreateDownloadItem();
416 MockObserver
observer(item
);
417 DownloadItemImplDelegate::DownloadTargetCallback callback
;
418 MockDownloadFile
* download_file
=
419 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
421 // Interrupt the download, using a continuable interrupt.
422 EXPECT_CALL(*download_file
, FullPath())
423 .WillOnce(Return(base::FilePath()));
424 EXPECT_CALL(*download_file
, Detach());
425 item
->DestinationObserverAsWeakPtr()->DestinationError(
426 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
427 ASSERT_TRUE(observer
.CheckUpdated());
428 // Should attempt to auto-resume. Because we don't have a mock WebContents,
429 // ResumeInterruptedDownload() will abort early, with another interrupt,
430 // which will be ignored.
431 ASSERT_EQ(1, observer
.GetInterruptCount());
432 ASSERT_EQ(0, observer
.GetResumeCount());
433 RunAllPendingInMessageLoops();
435 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
438 // Same as above, but with a non-continuable interrupt.
439 TEST_F(DownloadItemTest
, RestartAfterInterrupted
) {
440 base::CommandLine::ForCurrentProcess()->AppendSwitch(
441 switches::kEnableDownloadResumption
);
443 DownloadItemImpl
* item
= CreateDownloadItem();
444 MockObserver
observer(item
);
445 DownloadItemImplDelegate::DownloadTargetCallback callback
;
446 MockDownloadFile
* download_file
=
447 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
449 // Interrupt the download, using a restartable interrupt.
450 EXPECT_CALL(*download_file
, Cancel());
451 item
->DestinationObserverAsWeakPtr()->DestinationError(
452 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
453 ASSERT_TRUE(observer
.CheckUpdated());
454 // Should not try to auto-resume.
455 ASSERT_EQ(1, observer
.GetInterruptCount());
456 ASSERT_EQ(0, observer
.GetResumeCount());
457 RunAllPendingInMessageLoops();
459 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
462 // Check we do correct cleanup for RESUME_MODE_INVALID interrupts.
463 TEST_F(DownloadItemTest
, UnresumableInterrupt
) {
464 base::CommandLine::ForCurrentProcess()->AppendSwitch(
465 switches::kEnableDownloadResumption
);
467 DownloadItemImpl
* item
= CreateDownloadItem();
468 MockObserver
observer(item
);
469 DownloadItemImplDelegate::DownloadTargetCallback callback
;
470 MockDownloadFile
* download_file
=
471 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
473 // Fail final rename with unresumable reason.
474 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
475 .WillOnce(Return(true));
476 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
477 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED
,
478 base::FilePath(kDummyPath
)));
479 EXPECT_CALL(*download_file
, Cancel());
481 // Complete download to trigger final rename.
482 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
483 RunAllPendingInMessageLoops();
485 ASSERT_TRUE(observer
.CheckUpdated());
486 // Should not try to auto-resume.
487 ASSERT_EQ(1, observer
.GetInterruptCount());
488 ASSERT_EQ(0, observer
.GetResumeCount());
490 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
493 TEST_F(DownloadItemTest
, LimitRestartsAfterInterrupted
) {
494 base::CommandLine::ForCurrentProcess()->AppendSwitch(
495 switches::kEnableDownloadResumption
);
497 DownloadItemImpl
* item
= CreateDownloadItem();
498 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
499 item
->DestinationObserverAsWeakPtr());
500 MockObserver
observer(item
);
501 MockDownloadFile
* mock_download_file(NULL
);
502 scoped_ptr
<DownloadFile
> download_file
;
503 MockRequestHandle
* mock_request_handle(NULL
);
504 scoped_ptr
<DownloadRequestHandleInterface
> request_handle
;
505 DownloadItemImplDelegate::DownloadTargetCallback callback
;
507 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
508 .WillRepeatedly(SaveArg
<1>(&callback
));
509 for (int i
= 0; i
< (DownloadItemImpl::kMaxAutoResumeAttempts
+ 1); ++i
) {
510 DVLOG(20) << "Loop iteration " << i
;
512 mock_download_file
= new NiceMock
<MockDownloadFile
>;
513 download_file
.reset(mock_download_file
);
514 mock_request_handle
= new NiceMock
<MockRequestHandle
>;
515 request_handle
.reset(mock_request_handle
);
517 ON_CALL(*mock_download_file
, FullPath())
518 .WillByDefault(Return(base::FilePath()));
520 // It's too complicated to set up a WebContents instance that would cause
521 // the MockDownloadItemDelegate's ResumeInterruptedDownload() function
522 // to be callled, so we simply verify that GetWebContents() is called.
523 if (i
< (DownloadItemImpl::kMaxAutoResumeAttempts
- 1)) {
524 EXPECT_CALL(*mock_request_handle
, GetWebContents())
525 .WillRepeatedly(Return(static_cast<WebContents
*>(NULL
)));
528 // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem
529 // to allow for holding onto the request handle.
530 item
->Start(download_file
.Pass(), request_handle
.Pass());
531 RunAllPendingInMessageLoops();
533 // Target determination is only done the first time through.
534 base::FilePath
target_path(kDummyPath
);
535 base::FilePath
intermediate_path(
536 target_path
.InsertBeforeExtensionASCII("x"));
537 EXPECT_CALL(*mock_download_file
, RenameAndUniquify(intermediate_path
, _
))
538 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
540 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
541 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
542 RunAllPendingInMessageLoops();
544 ASSERT_EQ(i
, observer
.GetResumeCount());
546 // Use a continuable interrupt.
547 item
->DestinationObserverAsWeakPtr()->DestinationError(
548 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
550 ASSERT_EQ(i
+ 1, observer
.GetInterruptCount());
551 ::testing::Mock::VerifyAndClearExpectations(mock_download_file
);
554 CleanupItem(item
, mock_download_file
, DownloadItem::INTERRUPTED
);
557 TEST_F(DownloadItemTest
, NotificationAfterRemove
) {
558 DownloadItemImpl
* item
= CreateDownloadItem();
559 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
560 EXPECT_CALL(*download_file
, Cancel());
561 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
562 MockObserver
observer(item
);
565 ASSERT_TRUE(observer
.CheckUpdated());
566 ASSERT_TRUE(observer
.CheckRemoved());
569 TEST_F(DownloadItemTest
, NotificationAfterOnContentCheckCompleted
) {
570 // Setting to NOT_DANGEROUS does not trigger a notification.
571 DownloadItemImpl
* safe_item
= CreateDownloadItem();
572 MockObserver
safe_observer(safe_item
);
574 safe_item
->OnAllDataSaved(std::string());
575 EXPECT_TRUE(safe_observer
.CheckUpdated());
576 safe_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
577 EXPECT_TRUE(safe_observer
.CheckUpdated());
579 // Setting to unsafe url or unsafe file should trigger a notification.
580 DownloadItemImpl
* unsafeurl_item
=
581 CreateDownloadItem();
582 MockObserver
unsafeurl_observer(unsafeurl_item
);
584 unsafeurl_item
->OnAllDataSaved(std::string());
585 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
586 unsafeurl_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL
);
587 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
589 unsafeurl_item
->ValidateDangerousDownload();
590 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
592 DownloadItemImpl
* unsafefile_item
=
593 CreateDownloadItem();
594 MockObserver
unsafefile_observer(unsafefile_item
);
596 unsafefile_item
->OnAllDataSaved(std::string());
597 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
598 unsafefile_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
599 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
601 unsafefile_item
->ValidateDangerousDownload();
602 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
605 // DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
606 // DownloadFile::Rename(). Once the rename
607 // completes, DownloadItemImpl receives a notification with the new file
608 // name. Check that observers are updated when the new filename is available and
610 TEST_F(DownloadItemTest
, NotificationAfterOnDownloadTargetDetermined
) {
611 DownloadItemImpl
* item
= CreateDownloadItem();
612 DownloadItemImplDelegate::DownloadTargetCallback callback
;
613 MockDownloadFile
* download_file
=
614 AddDownloadFileToDownloadItem(item
, &callback
);
615 MockObserver
observer(item
);
616 base::FilePath
target_path(kDummyPath
);
617 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
618 base::FilePath
new_intermediate_path(
619 target_path
.InsertBeforeExtensionASCII("y"));
620 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
621 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
622 new_intermediate_path
));
624 // Currently, a notification would be generated if the danger type is anything
625 // other than NOT_DANGEROUS.
626 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
627 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
628 EXPECT_FALSE(observer
.CheckUpdated());
629 RunAllPendingInMessageLoops();
630 EXPECT_TRUE(observer
.CheckUpdated());
631 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
633 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
636 TEST_F(DownloadItemTest
, NotificationAfterTogglePause
) {
637 DownloadItemImpl
* item
= CreateDownloadItem();
638 MockObserver
observer(item
);
639 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
640 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
641 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
642 new NiceMock
<MockRequestHandle
>);
644 EXPECT_CALL(*mock_download_file
, Initialize(_
));
645 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_
, _
));
646 item
->Start(download_file
.Pass(), request_handle
.Pass());
649 ASSERT_TRUE(observer
.CheckUpdated());
651 ASSERT_TRUE(item
->IsPaused());
654 ASSERT_TRUE(observer
.CheckUpdated());
656 RunAllPendingInMessageLoops();
658 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
661 TEST_F(DownloadItemTest
, DisplayName
) {
662 DownloadItemImpl
* item
= CreateDownloadItem();
663 DownloadItemImplDelegate::DownloadTargetCallback callback
;
664 MockDownloadFile
* download_file
=
665 AddDownloadFileToDownloadItem(item
, &callback
);
666 base::FilePath
target_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
667 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
668 EXPECT_EQ(FILE_PATH_LITERAL(""),
669 item
->GetFileNameToReportUser().value());
670 EXPECT_CALL(*download_file
, RenameAndUniquify(_
, _
))
671 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
673 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
674 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
675 RunAllPendingInMessageLoops();
676 EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
677 item
->GetFileNameToReportUser().value());
678 item
->SetDisplayName(base::FilePath(FILE_PATH_LITERAL("new.name")));
679 EXPECT_EQ(FILE_PATH_LITERAL("new.name"),
680 item
->GetFileNameToReportUser().value());
681 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
684 // Test to make sure that Start method calls DF initialize properly.
685 TEST_F(DownloadItemTest
, Start
) {
686 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
687 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
688 DownloadItemImpl
* item
= CreateDownloadItem();
689 EXPECT_CALL(*mock_download_file
, Initialize(_
));
690 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
691 new NiceMock
<MockRequestHandle
>);
692 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
693 item
->Start(download_file
.Pass(), request_handle
.Pass());
694 RunAllPendingInMessageLoops();
696 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
699 // Test that the delegate is invoked after the download file is renamed.
700 TEST_F(DownloadItemTest
, CallbackAfterRename
) {
701 DownloadItemImpl
* item
= CreateDownloadItem();
702 DownloadItemImplDelegate::DownloadTargetCallback callback
;
703 MockDownloadFile
* download_file
=
704 AddDownloadFileToDownloadItem(item
, &callback
);
705 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
706 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
707 base::FilePath
new_intermediate_path(
708 final_path
.InsertBeforeExtensionASCII("y"));
709 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
710 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
711 new_intermediate_path
));
713 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
714 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
715 RunAllPendingInMessageLoops();
716 // All the callbacks should have happened by now.
717 ::testing::Mock::VerifyAndClearExpectations(download_file
);
718 mock_delegate()->VerifyAndClearExpectations();
720 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
721 .WillOnce(Return(true));
722 EXPECT_CALL(*download_file
, RenameAndAnnotate(final_path
, _
))
723 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
725 EXPECT_CALL(*download_file
, FullPath())
726 .WillOnce(Return(base::FilePath()));
727 EXPECT_CALL(*download_file
, Detach());
728 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
729 RunAllPendingInMessageLoops();
730 ::testing::Mock::VerifyAndClearExpectations(download_file
);
731 mock_delegate()->VerifyAndClearExpectations();
734 // Test that the delegate is invoked after the download file is renamed and the
735 // download item is in an interrupted state.
736 TEST_F(DownloadItemTest
, CallbackAfterInterruptedRename
) {
737 DownloadItemImpl
* item
= CreateDownloadItem();
738 DownloadItemImplDelegate::DownloadTargetCallback callback
;
739 MockDownloadFile
* download_file
=
740 AddDownloadFileToDownloadItem(item
, &callback
);
741 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
742 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
743 base::FilePath
new_intermediate_path(
744 final_path
.InsertBeforeExtensionASCII("y"));
745 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
746 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
747 new_intermediate_path
));
748 EXPECT_CALL(*download_file
, Cancel())
751 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
752 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
753 RunAllPendingInMessageLoops();
754 // All the callbacks should have happened by now.
755 ::testing::Mock::VerifyAndClearExpectations(download_file
);
756 mock_delegate()->VerifyAndClearExpectations();
759 TEST_F(DownloadItemTest
, Interrupted
) {
760 DownloadItemImpl
* item
= CreateDownloadItem();
761 MockDownloadFile
* download_file
=
762 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
764 const DownloadInterruptReason
reason(
765 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
767 // Confirm interrupt sets state properly.
768 EXPECT_CALL(*download_file
, Cancel());
769 item
->DestinationObserverAsWeakPtr()->DestinationError(reason
);
770 RunAllPendingInMessageLoops();
771 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
772 EXPECT_EQ(reason
, item
->GetLastReason());
774 // Cancel should kill it.
776 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
777 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
, item
->GetLastReason());
780 // Destination errors that occur before the intermediate rename shouldn't cause
781 // the download to be marked as interrupted until after the intermediate rename.
782 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Restart
) {
783 DownloadItemImpl
* item
= CreateDownloadItem();
784 DownloadItemImplDelegate::DownloadTargetCallback callback
;
785 MockDownloadFile
* download_file
=
786 AddDownloadFileToDownloadItem(item
, &callback
);
787 item
->DestinationObserverAsWeakPtr()->DestinationError(
788 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
789 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
791 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
792 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
793 base::FilePath
new_intermediate_path(
794 final_path
.InsertBeforeExtensionASCII("y"));
795 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
796 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
797 new_intermediate_path
));
798 EXPECT_CALL(*download_file
, Cancel())
801 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
802 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
803 RunAllPendingInMessageLoops();
804 // All the callbacks should have happened by now.
805 ::testing::Mock::VerifyAndClearExpectations(download_file
);
806 mock_delegate()->VerifyAndClearExpectations();
807 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
808 EXPECT_TRUE(item
->GetFullPath().empty());
809 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
812 // As above. But if the download can be resumed by continuing, then the
813 // intermediate path should be retained when the download is interrupted after
814 // the intermediate rename succeeds.
815 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Continue
) {
816 base::CommandLine::ForCurrentProcess()->AppendSwitch(
817 switches::kEnableDownloadResumption
);
818 DownloadItemImpl
* item
= CreateDownloadItem();
819 DownloadItemImplDelegate::DownloadTargetCallback callback
;
820 MockDownloadFile
* download_file
=
821 AddDownloadFileToDownloadItem(item
, &callback
);
822 item
->DestinationObserverAsWeakPtr()->DestinationError(
823 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
824 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
826 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
827 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
828 base::FilePath
new_intermediate_path(
829 final_path
.InsertBeforeExtensionASCII("y"));
830 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
831 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
832 new_intermediate_path
));
833 EXPECT_CALL(*download_file
, FullPath())
834 .WillOnce(Return(base::FilePath(new_intermediate_path
)));
835 EXPECT_CALL(*download_file
, Detach());
837 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
838 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
839 RunAllPendingInMessageLoops();
840 // All the callbacks should have happened by now.
841 ::testing::Mock::VerifyAndClearExpectations(download_file
);
842 mock_delegate()->VerifyAndClearExpectations();
843 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
844 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
845 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
848 // As above. If the intermediate rename fails, then the interrupt reason should
849 // be set to the destination error and the intermediate path should be empty.
850 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Failed
) {
851 base::CommandLine::ForCurrentProcess()->AppendSwitch(
852 switches::kEnableDownloadResumption
);
853 DownloadItemImpl
* item
= CreateDownloadItem();
854 DownloadItemImplDelegate::DownloadTargetCallback callback
;
855 MockDownloadFile
* download_file
=
856 AddDownloadFileToDownloadItem(item
, &callback
);
857 item
->DestinationObserverAsWeakPtr()->DestinationError(
858 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
859 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
861 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
862 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
863 base::FilePath
new_intermediate_path(
864 final_path
.InsertBeforeExtensionASCII("y"));
865 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
866 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
867 new_intermediate_path
));
868 EXPECT_CALL(*download_file
, Cancel())
871 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
872 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
873 RunAllPendingInMessageLoops();
874 // All the callbacks should have happened by now.
875 ::testing::Mock::VerifyAndClearExpectations(download_file
);
876 mock_delegate()->VerifyAndClearExpectations();
877 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
878 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
, item
->GetLastReason());
879 EXPECT_TRUE(item
->GetFullPath().empty());
880 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
883 TEST_F(DownloadItemTest
, Canceled
) {
884 DownloadItemImpl
* item
= CreateDownloadItem();
885 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
887 // Confirm cancel sets state properly.
888 EXPECT_CALL(*download_file
, Cancel());
890 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
893 TEST_F(DownloadItemTest
, FileRemoved
) {
894 DownloadItemImpl
* item
= CreateDownloadItem();
896 EXPECT_FALSE(item
->GetFileExternallyRemoved());
897 item
->OnDownloadedFileRemoved();
898 EXPECT_TRUE(item
->GetFileExternallyRemoved());
901 TEST_F(DownloadItemTest
, DestinationUpdate
) {
902 DownloadItemImpl
* item
= CreateDownloadItem();
903 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
904 item
->DestinationObserverAsWeakPtr());
905 MockObserver
observer(item
);
907 EXPECT_EQ(0l, item
->CurrentSpeed());
908 EXPECT_EQ("", item
->GetHashState());
909 EXPECT_EQ(0l, item
->GetReceivedBytes());
910 EXPECT_EQ(0l, item
->GetTotalBytes());
911 EXPECT_FALSE(observer
.CheckUpdated());
912 item
->SetTotalBytes(100l);
913 EXPECT_EQ(100l, item
->GetTotalBytes());
915 as_observer
->DestinationUpdate(10, 20, "deadbeef");
916 EXPECT_EQ(20l, item
->CurrentSpeed());
917 EXPECT_EQ("deadbeef", item
->GetHashState());
918 EXPECT_EQ(10l, item
->GetReceivedBytes());
919 EXPECT_EQ(100l, item
->GetTotalBytes());
920 EXPECT_TRUE(observer
.CheckUpdated());
922 as_observer
->DestinationUpdate(200, 20, "livebeef");
923 EXPECT_EQ(20l, item
->CurrentSpeed());
924 EXPECT_EQ("livebeef", item
->GetHashState());
925 EXPECT_EQ(200l, item
->GetReceivedBytes());
926 EXPECT_EQ(0l, item
->GetTotalBytes());
927 EXPECT_TRUE(observer
.CheckUpdated());
930 TEST_F(DownloadItemTest
, DestinationError
) {
931 DownloadItemImpl
* item
= CreateDownloadItem();
932 MockDownloadFile
* download_file
=
933 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
934 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
935 item
->DestinationObserverAsWeakPtr());
936 MockObserver
observer(item
);
938 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
939 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE
, item
->GetLastReason());
940 EXPECT_FALSE(observer
.CheckUpdated());
942 EXPECT_CALL(*download_file
, Cancel());
943 as_observer
->DestinationError(
944 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
945 mock_delegate()->VerifyAndClearExpectations();
946 EXPECT_TRUE(observer
.CheckUpdated());
947 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
948 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
,
949 item
->GetLastReason());
952 TEST_F(DownloadItemTest
, DestinationCompleted
) {
953 DownloadItemImpl
* item
= CreateDownloadItem();
954 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
955 item
->DestinationObserverAsWeakPtr());
956 MockObserver
observer(item
);
958 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
959 EXPECT_EQ("", item
->GetHash());
960 EXPECT_EQ("", item
->GetHashState());
961 EXPECT_FALSE(item
->AllDataSaved());
962 EXPECT_FALSE(observer
.CheckUpdated());
964 as_observer
->DestinationUpdate(10, 20, "deadbeef");
965 EXPECT_TRUE(observer
.CheckUpdated());
966 EXPECT_FALSE(observer
.CheckUpdated()); // Confirm reset.
967 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
968 EXPECT_EQ("", item
->GetHash());
969 EXPECT_EQ("deadbeef", item
->GetHashState());
970 EXPECT_FALSE(item
->AllDataSaved());
972 as_observer
->DestinationCompleted("livebeef");
973 mock_delegate()->VerifyAndClearExpectations();
974 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
975 EXPECT_TRUE(observer
.CheckUpdated());
976 EXPECT_EQ("livebeef", item
->GetHash());
977 EXPECT_EQ("", item
->GetHashState());
978 EXPECT_TRUE(item
->AllDataSaved());
981 TEST_F(DownloadItemTest
, EnabledActionsForNormalDownload
) {
982 DownloadItemImpl
* item
= CreateDownloadItem();
983 MockDownloadFile
* download_file
=
984 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
987 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
988 ASSERT_FALSE(item
->GetTargetFilePath().empty());
989 EXPECT_TRUE(item
->CanShowInFolder());
990 EXPECT_TRUE(item
->CanOpenDownload());
993 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
994 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
995 base::FilePath(kDummyPath
)));
996 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
997 .WillOnce(Return(true));
998 EXPECT_CALL(*download_file
, FullPath())
999 .WillOnce(Return(base::FilePath()));
1000 EXPECT_CALL(*download_file
, Detach());
1001 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1002 RunAllPendingInMessageLoops();
1004 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1005 EXPECT_TRUE(item
->CanShowInFolder());
1006 EXPECT_TRUE(item
->CanOpenDownload());
1009 TEST_F(DownloadItemTest
, EnabledActionsForTemporaryDownload
) {
1010 DownloadItemImpl
* item
= CreateDownloadItem();
1011 MockDownloadFile
* download_file
=
1012 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1013 item
->SetIsTemporary(true);
1015 // InProgress Temporary
1016 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1017 ASSERT_FALSE(item
->GetTargetFilePath().empty());
1018 ASSERT_TRUE(item
->IsTemporary());
1019 EXPECT_FALSE(item
->CanShowInFolder());
1020 EXPECT_FALSE(item
->CanOpenDownload());
1022 // Complete Temporary
1023 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1024 .WillOnce(Return(true));
1025 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
1026 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1027 base::FilePath(kDummyPath
)));
1028 EXPECT_CALL(*download_file
, FullPath())
1029 .WillOnce(Return(base::FilePath()));
1030 EXPECT_CALL(*download_file
, Detach());
1031 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1032 RunAllPendingInMessageLoops();
1034 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1035 EXPECT_FALSE(item
->CanShowInFolder());
1036 EXPECT_FALSE(item
->CanOpenDownload());
1039 TEST_F(DownloadItemTest
, EnabledActionsForInterruptedDownload
) {
1040 DownloadItemImpl
* item
= CreateDownloadItem();
1041 MockDownloadFile
* download_file
=
1042 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1044 EXPECT_CALL(*download_file
, Cancel());
1045 item
->DestinationObserverAsWeakPtr()->DestinationError(
1046 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1047 RunAllPendingInMessageLoops();
1049 ASSERT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
1050 ASSERT_FALSE(item
->GetTargetFilePath().empty());
1051 EXPECT_FALSE(item
->CanShowInFolder());
1052 EXPECT_FALSE(item
->CanOpenDownload());
1055 TEST_F(DownloadItemTest
, EnabledActionsForCancelledDownload
) {
1056 DownloadItemImpl
* item
= CreateDownloadItem();
1057 MockDownloadFile
* download_file
=
1058 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1060 EXPECT_CALL(*download_file
, Cancel());
1062 RunAllPendingInMessageLoops();
1064 ASSERT_EQ(DownloadItem::CANCELLED
, item
->GetState());
1065 EXPECT_FALSE(item
->CanShowInFolder());
1066 EXPECT_FALSE(item
->CanOpenDownload());
1069 // Test various aspects of the delegate completion blocker.
1071 // Just allowing completion.
1072 TEST_F(DownloadItemTest
, CompleteDelegate_ReturnTrue
) {
1073 // Test to confirm that if we have a callback that returns true,
1074 // we complete immediately.
1075 DownloadItemImpl
* item
= CreateDownloadItem();
1076 MockDownloadFile
* download_file
=
1077 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1079 // Drive the delegate interaction.
1080 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1081 .WillOnce(Return(true));
1082 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1083 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1084 EXPECT_FALSE(item
->IsDangerous());
1086 // Make sure the download can complete.
1087 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1088 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1089 base::FilePath(kDummyPath
)));
1090 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1091 .WillOnce(Return(true));
1092 EXPECT_CALL(*download_file
, FullPath())
1093 .WillOnce(Return(base::FilePath()));
1094 EXPECT_CALL(*download_file
, Detach());
1095 RunAllPendingInMessageLoops();
1096 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1099 // Just delaying completion.
1100 TEST_F(DownloadItemTest
, CompleteDelegate_BlockOnce
) {
1101 // Test to confirm that if we have a callback that returns true,
1102 // we complete immediately.
1103 DownloadItemImpl
* item
= CreateDownloadItem();
1104 MockDownloadFile
* download_file
=
1105 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1107 // Drive the delegate interaction.
1108 base::Closure delegate_callback
;
1109 base::Closure copy_delegate_callback
;
1110 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1111 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1113 .WillOnce(Return(true));
1114 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1115 ASSERT_FALSE(delegate_callback
.is_null());
1116 copy_delegate_callback
= delegate_callback
;
1117 delegate_callback
.Reset();
1118 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1119 copy_delegate_callback
.Run();
1120 ASSERT_TRUE(delegate_callback
.is_null());
1121 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1122 EXPECT_FALSE(item
->IsDangerous());
1124 // Make sure the download can complete.
1125 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1126 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1127 base::FilePath(kDummyPath
)));
1128 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1129 .WillOnce(Return(true));
1130 EXPECT_CALL(*download_file
, FullPath())
1131 .WillOnce(Return(base::FilePath()));
1132 EXPECT_CALL(*download_file
, Detach());
1133 RunAllPendingInMessageLoops();
1134 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1137 // Delay and set danger.
1138 TEST_F(DownloadItemTest
, CompleteDelegate_SetDanger
) {
1139 // Test to confirm that if we have a callback that returns true,
1140 // we complete immediately.
1141 DownloadItemImpl
* item
= CreateDownloadItem();
1142 MockDownloadFile
* download_file
=
1143 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1145 // Drive the delegate interaction.
1146 base::Closure delegate_callback
;
1147 base::Closure copy_delegate_callback
;
1148 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1149 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1151 .WillOnce(Return(true));
1152 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1153 ASSERT_FALSE(delegate_callback
.is_null());
1154 copy_delegate_callback
= delegate_callback
;
1155 delegate_callback
.Reset();
1156 EXPECT_FALSE(item
->IsDangerous());
1157 item
->OnContentCheckCompleted(
1158 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1159 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1160 copy_delegate_callback
.Run();
1161 ASSERT_TRUE(delegate_callback
.is_null());
1162 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1163 EXPECT_TRUE(item
->IsDangerous());
1165 // Make sure the download doesn't complete until we've validated it.
1166 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1167 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1168 base::FilePath(kDummyPath
)));
1169 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1170 .WillOnce(Return(true));
1171 EXPECT_CALL(*download_file
, FullPath())
1172 .WillOnce(Return(base::FilePath()));
1173 EXPECT_CALL(*download_file
, Detach());
1174 RunAllPendingInMessageLoops();
1175 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1176 EXPECT_TRUE(item
->IsDangerous());
1178 item
->ValidateDangerousDownload();
1179 EXPECT_EQ(DOWNLOAD_DANGER_TYPE_USER_VALIDATED
, item
->GetDangerType());
1180 RunAllPendingInMessageLoops();
1181 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1184 // Just delaying completion twice.
1185 TEST_F(DownloadItemTest
, CompleteDelegate_BlockTwice
) {
1186 // Test to confirm that if we have a callback that returns true,
1187 // we complete immediately.
1188 DownloadItemImpl
* item
= CreateDownloadItem();
1189 MockDownloadFile
* download_file
=
1190 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1192 // Drive the delegate interaction.
1193 base::Closure delegate_callback
;
1194 base::Closure copy_delegate_callback
;
1195 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1196 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1198 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1200 .WillOnce(Return(true));
1201 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1202 ASSERT_FALSE(delegate_callback
.is_null());
1203 copy_delegate_callback
= delegate_callback
;
1204 delegate_callback
.Reset();
1205 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1206 copy_delegate_callback
.Run();
1207 ASSERT_FALSE(delegate_callback
.is_null());
1208 copy_delegate_callback
= delegate_callback
;
1209 delegate_callback
.Reset();
1210 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1211 copy_delegate_callback
.Run();
1212 ASSERT_TRUE(delegate_callback
.is_null());
1213 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1214 EXPECT_FALSE(item
->IsDangerous());
1216 // Make sure the download can complete.
1217 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1218 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1219 base::FilePath(kDummyPath
)));
1220 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1221 .WillOnce(Return(true));
1222 EXPECT_CALL(*download_file
, FullPath())
1223 .WillOnce(Return(base::FilePath()));
1224 EXPECT_CALL(*download_file
, Detach());
1225 RunAllPendingInMessageLoops();
1226 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1229 TEST_F(DownloadItemTest
, StealDangerousDownload
) {
1230 DownloadItemImpl
* item
= CreateDownloadItem();
1231 MockDownloadFile
* download_file
=
1232 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1233 ASSERT_TRUE(item
->IsDangerous());
1234 base::FilePath
full_path(FILE_PATH_LITERAL("foo.txt"));
1235 base::FilePath returned_path
;
1237 EXPECT_CALL(*download_file
, FullPath())
1238 .WillOnce(Return(full_path
));
1239 EXPECT_CALL(*download_file
, Detach());
1240 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1241 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1242 item
->StealDangerousDownload(
1243 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1244 weak_ptr_factory
.GetWeakPtr(),
1245 base::Unretained(&returned_path
)));
1246 RunAllPendingInMessageLoops();
1247 EXPECT_EQ(full_path
, returned_path
);
1250 TEST_F(DownloadItemTest
, StealInterruptedDangerousDownload
) {
1251 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1252 switches::kEnableDownloadResumption
);
1253 base::FilePath returned_path
;
1254 DownloadItemImpl
* item
= CreateDownloadItem();
1255 MockDownloadFile
* download_file
=
1256 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1257 base::FilePath full_path
= item
->GetFullPath();
1258 EXPECT_FALSE(full_path
.empty());
1259 EXPECT_CALL(*download_file
, FullPath())
1260 .WillOnce(Return(full_path
));
1261 EXPECT_CALL(*download_file
, Detach());
1262 item
->DestinationObserverAsWeakPtr()->DestinationError(
1263 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
1264 ASSERT_TRUE(item
->IsDangerous());
1266 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1267 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1268 item
->StealDangerousDownload(
1269 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1270 weak_ptr_factory
.GetWeakPtr(),
1271 base::Unretained(&returned_path
)));
1272 RunAllPendingInMessageLoops();
1273 EXPECT_EQ(full_path
, returned_path
);
1276 TEST_F(DownloadItemTest
, StealInterruptedNonResumableDangerousDownload
) {
1277 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1278 switches::kEnableDownloadResumption
);
1279 base::FilePath returned_path
;
1280 DownloadItemImpl
* item
= CreateDownloadItem();
1281 MockDownloadFile
* download_file
=
1282 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1283 EXPECT_CALL(*download_file
, Cancel());
1284 item
->DestinationObserverAsWeakPtr()->DestinationError(
1285 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1286 ASSERT_TRUE(item
->IsDangerous());
1288 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1289 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1290 item
->StealDangerousDownload(
1291 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1292 weak_ptr_factory
.GetWeakPtr(),
1293 base::Unretained(&returned_path
)));
1294 RunAllPendingInMessageLoops();
1295 EXPECT_TRUE(returned_path
.empty());
1298 TEST(MockDownloadItem
, Compiles
) {
1299 MockDownloadItem mock_item
;
1302 } // namespace content