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
;
35 const int kDownloadChunkSize
= 1000;
36 const int kDownloadSpeed
= 1000;
37 const int kDummyDBHandle
= 10;
38 const base::FilePath::CharType kDummyPath
[] = FILE_PATH_LITERAL("/testpath");
46 class MockDelegate
: public DownloadItemImplDelegate
{
48 MockDelegate() : DownloadItemImplDelegate() {
49 SetDefaultExpectations();
52 MOCK_METHOD2(DetermineDownloadTarget
, void(
53 DownloadItemImpl
*, const DownloadTargetCallback
&));
54 MOCK_METHOD2(ShouldCompleteDownload
,
55 bool(DownloadItemImpl
*, const base::Closure
&));
56 MOCK_METHOD2(ShouldOpenDownload
,
57 bool(DownloadItemImpl
*, const ShouldOpenDownloadCallback
&));
58 MOCK_METHOD1(ShouldOpenFileBasedOnExtension
, bool(const base::FilePath
&));
59 MOCK_METHOD1(CheckForFileRemoval
, void(DownloadItemImpl
*));
61 virtual void ResumeInterruptedDownload(
62 scoped_ptr
<DownloadUrlParameters
> params
, uint32 id
) OVERRIDE
{
63 MockResumeInterruptedDownload(params
.get(), id
);
65 MOCK_METHOD2(MockResumeInterruptedDownload
,
66 void(DownloadUrlParameters
* params
, uint32 id
));
68 MOCK_CONST_METHOD0(GetBrowserContext
, BrowserContext
*());
69 MOCK_METHOD1(UpdatePersistence
, void(DownloadItemImpl
*));
70 MOCK_METHOD1(DownloadOpened
, void(DownloadItemImpl
*));
71 MOCK_METHOD1(DownloadRemoved
, void(DownloadItemImpl
*));
72 MOCK_CONST_METHOD1(AssertStateConsistent
, void(DownloadItemImpl
*));
74 void VerifyAndClearExpectations() {
75 ::testing::Mock::VerifyAndClearExpectations(this);
76 SetDefaultExpectations();
80 void SetDefaultExpectations() {
81 EXPECT_CALL(*this, AssertStateConsistent(_
))
82 .WillRepeatedly(Return());
83 EXPECT_CALL(*this, ShouldOpenFileBasedOnExtension(_
))
84 .WillRepeatedly(Return(false));
85 EXPECT_CALL(*this, ShouldOpenDownload(_
, _
))
86 .WillRepeatedly(Return(true));
90 class MockRequestHandle
: public DownloadRequestHandleInterface
{
92 MOCK_CONST_METHOD0(GetWebContents
, WebContents
*());
93 MOCK_CONST_METHOD0(GetDownloadManager
, DownloadManager
*());
94 MOCK_CONST_METHOD0(PauseRequest
, void());
95 MOCK_CONST_METHOD0(ResumeRequest
, void());
96 MOCK_CONST_METHOD0(CancelRequest
, void());
97 MOCK_CONST_METHOD0(DebugString
, std::string());
100 // Schedules a task to invoke the RenameCompletionCallback with |new_path| on
101 // the UI thread. Should only be used as the action for
102 // MockDownloadFile::Rename as follows:
103 // EXPECT_CALL(download_file, Rename*(_,_))
104 // .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
106 ACTION_P2(ScheduleRenameCallback
, interrupt_reason
, new_path
) {
107 BrowserThread::PostTask(
108 BrowserThread::UI
, FROM_HERE
,
109 base::Bind(arg1
, interrupt_reason
, new_path
));
114 class DownloadItemTest
: public testing::Test
{
116 class MockObserver
: public DownloadItem::Observer
{
118 explicit MockObserver(DownloadItem
* item
)
120 last_state_(item
->GetState()),
126 item_
->AddObserver(this);
129 virtual ~MockObserver() {
130 if (item_
) item_
->RemoveObserver(this);
133 virtual void OnDownloadRemoved(DownloadItem
* download
) OVERRIDE
{
134 DVLOG(20) << " " << __FUNCTION__
135 << " download = " << download
->DebugString(false);
139 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
{
140 DVLOG(20) << " " << __FUNCTION__
141 << " download = " << download
->DebugString(false);
143 DownloadItem::DownloadState new_state
= download
->GetState();
144 if (last_state_
== DownloadItem::IN_PROGRESS
&&
145 new_state
== DownloadItem::INTERRUPTED
) {
148 if (last_state_
== DownloadItem::INTERRUPTED
&&
149 new_state
== DownloadItem::IN_PROGRESS
) {
152 last_state_
= new_state
;
155 virtual void OnDownloadOpened(DownloadItem
* download
) OVERRIDE
{
156 DVLOG(20) << " " << __FUNCTION__
157 << " download = " << download
->DebugString(false);
160 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
{
161 DVLOG(20) << " " << __FUNCTION__
162 << " download = " << download
->DebugString(false);
164 item_
->RemoveObserver(this);
168 bool CheckRemoved() {
172 bool CheckDestroyed() {
176 bool CheckUpdated() {
177 bool was_updated
= updated_
;
182 int GetInterruptCount() {
183 return interrupt_count_
;
186 int GetResumeCount() {
187 return resume_count_
;
192 DownloadItem::DownloadState last_state_
;
196 int interrupt_count_
;
201 : ui_thread_(BrowserThread::UI
, &loop_
),
202 file_thread_(BrowserThread::FILE, &loop_
),
206 ~DownloadItemTest() {
209 virtual void SetUp() {
212 virtual void TearDown() {
213 ui_thread_
.DeprecatedGetThreadObject()->message_loop()->RunUntilIdle();
214 STLDeleteElements(&allocated_downloads_
);
215 allocated_downloads_
.clear();
218 // This class keeps ownership of the created download item; it will
219 // be torn down at the end of the test unless DestroyDownloadItem is
221 DownloadItemImpl
* CreateDownloadItem() {
222 // Normally, the download system takes ownership of info, and is
223 // responsible for deleting it. In these unit tests, however, we
224 // don't call the function that deletes it, so we do so ourselves.
225 scoped_ptr
<DownloadCreateInfo
> info_
;
227 info_
.reset(new DownloadCreateInfo());
228 static uint32 next_id
= DownloadItem::kInvalidId
+ 1;
229 info_
->save_info
= scoped_ptr
<DownloadSaveInfo
>(new DownloadSaveInfo());
230 info_
->save_info
->prompt_for_save_location
= false;
231 info_
->url_chain
.push_back(GURL());
232 info_
->etag
= "SomethingToSatisfyResumption";
234 DownloadItemImpl
* download
=
235 new DownloadItemImpl(
236 &delegate_
, next_id
++, *(info_
.get()), net::BoundNetLog());
237 allocated_downloads_
.insert(download
);
241 // Add DownloadFile to DownloadItem
242 MockDownloadFile
* AddDownloadFileToDownloadItem(
243 DownloadItemImpl
* item
,
244 DownloadItemImplDelegate::DownloadTargetCallback
*callback
) {
245 MockDownloadFile
* mock_download_file(new StrictMock
<MockDownloadFile
>);
246 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
247 EXPECT_CALL(*mock_download_file
, Initialize(_
));
249 // Save the callback.
250 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
251 .WillOnce(SaveArg
<1>(callback
));
253 // Drop it on the floor.
254 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
257 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
258 new NiceMock
<MockRequestHandle
>);
259 item
->Start(download_file
.Pass(), request_handle
.Pass());
260 loop_
.RunUntilIdle();
262 // So that we don't have a function writing to a stack variable
263 // lying around if the above failed.
264 mock_delegate()->VerifyAndClearExpectations();
265 EXPECT_CALL(*mock_delegate(), AssertStateConsistent(_
))
266 .WillRepeatedly(Return());
267 EXPECT_CALL(*mock_delegate(), ShouldOpenFileBasedOnExtension(_
))
268 .WillRepeatedly(Return(false));
269 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(_
, _
))
270 .WillRepeatedly(Return(true));
272 return mock_download_file
;
275 // Perform the intermediate rename for |item|. The target path for the
276 // download will be set to kDummyPath. Returns the MockDownloadFile* that was
277 // added to the DownloadItem.
278 MockDownloadFile
* DoIntermediateRename(DownloadItemImpl
* item
,
279 DownloadDangerType danger_type
) {
280 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
281 EXPECT_TRUE(item
->GetTargetFilePath().empty());
282 DownloadItemImplDelegate::DownloadTargetCallback callback
;
283 MockDownloadFile
* download_file
=
284 AddDownloadFileToDownloadItem(item
, &callback
);
285 base::FilePath
target_path(kDummyPath
);
286 base::FilePath
intermediate_path(
287 target_path
.InsertBeforeExtensionASCII("x"));
288 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
289 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
291 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
292 danger_type
, intermediate_path
);
293 RunAllPendingInMessageLoops();
294 return download_file
;
297 // Cleanup a download item (specifically get rid of the DownloadFile on it).
298 // The item must be in the expected state.
299 void CleanupItem(DownloadItemImpl
* item
,
300 MockDownloadFile
* download_file
,
301 DownloadItem::DownloadState expected_state
) {
302 EXPECT_EQ(expected_state
, item
->GetState());
304 if (expected_state
== DownloadItem::IN_PROGRESS
) {
305 EXPECT_CALL(*download_file
, Cancel());
307 loop_
.RunUntilIdle();
311 // Destroy a previously created download item.
312 void DestroyDownloadItem(DownloadItem
* item
) {
313 allocated_downloads_
.erase(item
);
317 void RunAllPendingInMessageLoops() {
318 loop_
.RunUntilIdle();
321 MockDelegate
* mock_delegate() {
325 void OnDownloadFileAcquired(base::FilePath
* return_path
,
326 const base::FilePath
& path
) {
331 base::MessageLoopForUI loop_
;
332 TestBrowserThread ui_thread_
; // UI thread
333 TestBrowserThread file_thread_
; // FILE thread
334 StrictMock
<MockDelegate
> delegate_
;
335 std::set
<DownloadItem
*> allocated_downloads_
;
338 // Tests to ensure calls that change a DownloadItem generate an update to
340 // State changing functions not tested:
341 // void OpenDownload();
342 // void ShowDownloadInShell();
343 // void CompleteDelayedDownload();
346 TEST_F(DownloadItemTest
, NotificationAfterUpdate
) {
347 DownloadItemImpl
* item
= CreateDownloadItem();
348 MockObserver
observer(item
);
350 item
->DestinationUpdate(kDownloadChunkSize
, kDownloadSpeed
, std::string());
351 ASSERT_TRUE(observer
.CheckUpdated());
352 EXPECT_EQ(kDownloadSpeed
, item
->CurrentSpeed());
355 TEST_F(DownloadItemTest
, NotificationAfterCancel
) {
356 DownloadItemImpl
* user_cancel
= CreateDownloadItem();
357 MockDownloadFile
* download_file
=
358 AddDownloadFileToDownloadItem(user_cancel
, NULL
);
359 EXPECT_CALL(*download_file
, Cancel());
360 MockObserver
observer1(user_cancel
);
362 user_cancel
->Cancel(true);
363 ASSERT_TRUE(observer1
.CheckUpdated());
365 DownloadItemImpl
* system_cancel
= CreateDownloadItem();
366 download_file
= AddDownloadFileToDownloadItem(system_cancel
, NULL
);
367 EXPECT_CALL(*download_file
, Cancel());
368 MockObserver
observer2(system_cancel
);
370 system_cancel
->Cancel(false);
371 ASSERT_TRUE(observer2
.CheckUpdated());
374 TEST_F(DownloadItemTest
, NotificationAfterComplete
) {
375 DownloadItemImpl
* item
= CreateDownloadItem();
376 MockObserver
observer(item
);
378 item
->OnAllDataSaved(DownloadItem::kEmptyFileHash
);
379 ASSERT_TRUE(observer
.CheckUpdated());
381 item
->MarkAsComplete();
382 ASSERT_TRUE(observer
.CheckUpdated());
385 TEST_F(DownloadItemTest
, NotificationAfterDownloadedFileRemoved
) {
386 DownloadItemImpl
* item
= CreateDownloadItem();
387 MockObserver
observer(item
);
389 item
->OnDownloadedFileRemoved();
390 ASSERT_TRUE(observer
.CheckUpdated());
393 TEST_F(DownloadItemTest
, NotificationAfterInterrupted
) {
394 DownloadItemImpl
* item
= CreateDownloadItem();
395 MockDownloadFile
* download_file
=
396 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
397 EXPECT_CALL(*download_file
, Cancel());
398 MockObserver
observer(item
);
400 EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_
,_
))
403 item
->DestinationObserverAsWeakPtr()->DestinationError(
404 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
405 ASSERT_TRUE(observer
.CheckUpdated());
408 TEST_F(DownloadItemTest
, NotificationAfterDestroyed
) {
409 DownloadItemImpl
* item
= CreateDownloadItem();
410 MockObserver
observer(item
);
412 DestroyDownloadItem(item
);
413 ASSERT_TRUE(observer
.CheckDestroyed());
416 TEST_F(DownloadItemTest
, ContinueAfterInterrupted
) {
417 CommandLine::ForCurrentProcess()->AppendSwitch(
418 switches::kEnableDownloadResumption
);
420 DownloadItemImpl
* item
= CreateDownloadItem();
421 MockObserver
observer(item
);
422 DownloadItemImplDelegate::DownloadTargetCallback callback
;
423 MockDownloadFile
* download_file
=
424 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
426 // Interrupt the download, using a continuable interrupt.
427 EXPECT_CALL(*download_file
, FullPath())
428 .WillOnce(Return(base::FilePath()));
429 EXPECT_CALL(*download_file
, Detach());
430 item
->DestinationObserverAsWeakPtr()->DestinationError(
431 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
432 ASSERT_TRUE(observer
.CheckUpdated());
433 // Should attempt to auto-resume. Because we don't have a mock WebContents,
434 // ResumeInterruptedDownload() will abort early, with another interrupt,
435 // which will be ignored.
436 ASSERT_EQ(1, observer
.GetInterruptCount());
437 ASSERT_EQ(0, observer
.GetResumeCount());
438 RunAllPendingInMessageLoops();
440 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
443 // Same as above, but with a non-continuable interrupt.
444 TEST_F(DownloadItemTest
, RestartAfterInterrupted
) {
445 CommandLine::ForCurrentProcess()->AppendSwitch(
446 switches::kEnableDownloadResumption
);
448 DownloadItemImpl
* item
= CreateDownloadItem();
449 MockObserver
observer(item
);
450 DownloadItemImplDelegate::DownloadTargetCallback callback
;
451 MockDownloadFile
* download_file
=
452 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
454 // Interrupt the download, using a restartable interrupt.
455 EXPECT_CALL(*download_file
, Cancel());
456 item
->DestinationObserverAsWeakPtr()->DestinationError(
457 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
458 ASSERT_TRUE(observer
.CheckUpdated());
459 // Should not try to auto-resume.
460 ASSERT_EQ(1, observer
.GetInterruptCount());
461 ASSERT_EQ(0, observer
.GetResumeCount());
462 RunAllPendingInMessageLoops();
464 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
467 TEST_F(DownloadItemTest
, LimitRestartsAfterInterrupted
) {
468 CommandLine::ForCurrentProcess()->AppendSwitch(
469 switches::kEnableDownloadResumption
);
471 DownloadItemImpl
* item
= CreateDownloadItem();
472 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
473 item
->DestinationObserverAsWeakPtr());
474 MockObserver
observer(item
);
475 MockDownloadFile
* mock_download_file(NULL
);
476 scoped_ptr
<DownloadFile
> download_file
;
477 MockRequestHandle
* mock_request_handle(NULL
);
478 scoped_ptr
<DownloadRequestHandleInterface
> request_handle
;
479 DownloadItemImplDelegate::DownloadTargetCallback callback
;
481 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
482 .WillRepeatedly(SaveArg
<1>(&callback
));
483 for (int i
= 0; i
< (DownloadItemImpl::kMaxAutoResumeAttempts
+ 1); ++i
) {
484 DVLOG(20) << "Loop iteration " << i
;
486 mock_download_file
= new NiceMock
<MockDownloadFile
>;
487 download_file
.reset(mock_download_file
);
488 mock_request_handle
= new NiceMock
<MockRequestHandle
>;
489 request_handle
.reset(mock_request_handle
);
491 ON_CALL(*mock_download_file
, FullPath())
492 .WillByDefault(Return(base::FilePath()));
494 // It's too complicated to set up a WebContents instance that would cause
495 // the MockDownloadItemDelegate's ResumeInterruptedDownload() function
496 // to be callled, so we simply verify that GetWebContents() is called.
497 if (i
< (DownloadItemImpl::kMaxAutoResumeAttempts
- 1)) {
498 EXPECT_CALL(*mock_request_handle
, GetWebContents())
499 .WillRepeatedly(Return(static_cast<WebContents
*>(NULL
)));
502 // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem
503 // to allow for holding onto the request handle.
504 item
->Start(download_file
.Pass(), request_handle
.Pass());
505 RunAllPendingInMessageLoops();
507 // Target determination is only done the first time through.
508 base::FilePath
target_path(kDummyPath
);
509 base::FilePath
intermediate_path(
510 target_path
.InsertBeforeExtensionASCII("x"));
511 EXPECT_CALL(*mock_download_file
, RenameAndUniquify(intermediate_path
, _
))
512 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
514 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
515 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
516 RunAllPendingInMessageLoops();
518 ASSERT_EQ(i
, observer
.GetResumeCount());
520 // Use a continuable interrupt.
521 item
->DestinationObserverAsWeakPtr()->DestinationError(
522 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
524 ASSERT_EQ(i
+ 1, observer
.GetInterruptCount());
525 ::testing::Mock::VerifyAndClearExpectations(mock_download_file
);
528 CleanupItem(item
, mock_download_file
, DownloadItem::INTERRUPTED
);
531 TEST_F(DownloadItemTest
, NotificationAfterRemove
) {
532 DownloadItemImpl
* item
= CreateDownloadItem();
533 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
534 EXPECT_CALL(*download_file
, Cancel());
535 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
536 MockObserver
observer(item
);
539 ASSERT_TRUE(observer
.CheckUpdated());
540 ASSERT_TRUE(observer
.CheckRemoved());
543 TEST_F(DownloadItemTest
, NotificationAfterOnContentCheckCompleted
) {
544 // Setting to NOT_DANGEROUS does not trigger a notification.
545 DownloadItemImpl
* safe_item
= CreateDownloadItem();
546 MockObserver
safe_observer(safe_item
);
548 safe_item
->OnAllDataSaved(std::string());
549 EXPECT_TRUE(safe_observer
.CheckUpdated());
550 safe_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
551 EXPECT_TRUE(safe_observer
.CheckUpdated());
553 // Setting to unsafe url or unsafe file should trigger a notification.
554 DownloadItemImpl
* unsafeurl_item
=
555 CreateDownloadItem();
556 MockObserver
unsafeurl_observer(unsafeurl_item
);
558 unsafeurl_item
->OnAllDataSaved(std::string());
559 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
560 unsafeurl_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL
);
561 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
563 unsafeurl_item
->ValidateDangerousDownload();
564 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
566 DownloadItemImpl
* unsafefile_item
=
567 CreateDownloadItem();
568 MockObserver
unsafefile_observer(unsafefile_item
);
570 unsafefile_item
->OnAllDataSaved(std::string());
571 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
572 unsafefile_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
573 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
575 unsafefile_item
->ValidateDangerousDownload();
576 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
579 // DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
580 // DownloadFile::Rename(). Once the rename
581 // completes, DownloadItemImpl receives a notification with the new file
582 // name. Check that observers are updated when the new filename is available and
584 TEST_F(DownloadItemTest
, NotificationAfterOnDownloadTargetDetermined
) {
585 DownloadItemImpl
* item
= CreateDownloadItem();
586 DownloadItemImplDelegate::DownloadTargetCallback callback
;
587 MockDownloadFile
* download_file
=
588 AddDownloadFileToDownloadItem(item
, &callback
);
589 MockObserver
observer(item
);
590 base::FilePath
target_path(kDummyPath
);
591 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
592 base::FilePath
new_intermediate_path(
593 target_path
.InsertBeforeExtensionASCII("y"));
594 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
595 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
596 new_intermediate_path
));
598 // Currently, a notification would be generated if the danger type is anything
599 // other than NOT_DANGEROUS.
600 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
601 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
602 EXPECT_FALSE(observer
.CheckUpdated());
603 RunAllPendingInMessageLoops();
604 EXPECT_TRUE(observer
.CheckUpdated());
605 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
607 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
610 TEST_F(DownloadItemTest
, NotificationAfterTogglePause
) {
611 DownloadItemImpl
* item
= CreateDownloadItem();
612 MockObserver
observer(item
);
613 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
614 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
615 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
616 new NiceMock
<MockRequestHandle
>);
618 EXPECT_CALL(*mock_download_file
, Initialize(_
));
619 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_
, _
));
620 item
->Start(download_file
.Pass(), request_handle
.Pass());
623 ASSERT_TRUE(observer
.CheckUpdated());
625 ASSERT_TRUE(item
->IsPaused());
628 ASSERT_TRUE(observer
.CheckUpdated());
630 RunAllPendingInMessageLoops();
632 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
635 TEST_F(DownloadItemTest
, DisplayName
) {
636 DownloadItemImpl
* item
= CreateDownloadItem();
637 DownloadItemImplDelegate::DownloadTargetCallback callback
;
638 MockDownloadFile
* download_file
=
639 AddDownloadFileToDownloadItem(item
, &callback
);
640 base::FilePath
target_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
641 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
642 EXPECT_EQ(FILE_PATH_LITERAL(""),
643 item
->GetFileNameToReportUser().value());
644 EXPECT_CALL(*download_file
, RenameAndUniquify(_
, _
))
645 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
647 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
648 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
649 RunAllPendingInMessageLoops();
650 EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
651 item
->GetFileNameToReportUser().value());
652 item
->SetDisplayName(base::FilePath(FILE_PATH_LITERAL("new.name")));
653 EXPECT_EQ(FILE_PATH_LITERAL("new.name"),
654 item
->GetFileNameToReportUser().value());
655 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
658 // Test to make sure that Start method calls DF initialize properly.
659 TEST_F(DownloadItemTest
, Start
) {
660 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
661 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
662 DownloadItemImpl
* item
= CreateDownloadItem();
663 EXPECT_CALL(*mock_download_file
, Initialize(_
));
664 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
665 new NiceMock
<MockRequestHandle
>);
666 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
667 item
->Start(download_file
.Pass(), request_handle
.Pass());
668 RunAllPendingInMessageLoops();
670 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
673 // Test that the delegate is invoked after the download file is renamed.
674 TEST_F(DownloadItemTest
, CallbackAfterRename
) {
675 DownloadItemImpl
* item
= CreateDownloadItem();
676 DownloadItemImplDelegate::DownloadTargetCallback callback
;
677 MockDownloadFile
* download_file
=
678 AddDownloadFileToDownloadItem(item
, &callback
);
679 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
680 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
681 base::FilePath
new_intermediate_path(
682 final_path
.InsertBeforeExtensionASCII("y"));
683 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
684 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
685 new_intermediate_path
));
687 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
688 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
689 RunAllPendingInMessageLoops();
690 // All the callbacks should have happened by now.
691 ::testing::Mock::VerifyAndClearExpectations(download_file
);
692 mock_delegate()->VerifyAndClearExpectations();
694 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
695 .WillOnce(Return(true));
696 EXPECT_CALL(*download_file
, RenameAndAnnotate(final_path
, _
))
697 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
699 EXPECT_CALL(*download_file
, FullPath())
700 .WillOnce(Return(base::FilePath()));
701 EXPECT_CALL(*download_file
, Detach());
702 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
703 RunAllPendingInMessageLoops();
704 ::testing::Mock::VerifyAndClearExpectations(download_file
);
705 mock_delegate()->VerifyAndClearExpectations();
708 // Test that the delegate is invoked after the download file is renamed and the
709 // download item is in an interrupted state.
710 TEST_F(DownloadItemTest
, CallbackAfterInterruptedRename
) {
711 DownloadItemImpl
* item
= CreateDownloadItem();
712 DownloadItemImplDelegate::DownloadTargetCallback callback
;
713 MockDownloadFile
* download_file
=
714 AddDownloadFileToDownloadItem(item
, &callback
);
715 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
716 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
717 base::FilePath
new_intermediate_path(
718 final_path
.InsertBeforeExtensionASCII("y"));
719 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
720 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
721 new_intermediate_path
));
722 EXPECT_CALL(*download_file
, Cancel())
725 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
726 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
727 RunAllPendingInMessageLoops();
728 // All the callbacks should have happened by now.
729 ::testing::Mock::VerifyAndClearExpectations(download_file
);
730 mock_delegate()->VerifyAndClearExpectations();
733 TEST_F(DownloadItemTest
, Interrupted
) {
734 DownloadItemImpl
* item
= CreateDownloadItem();
735 MockDownloadFile
* download_file
=
736 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
738 const DownloadInterruptReason
reason(
739 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
741 // Confirm interrupt sets state properly.
742 EXPECT_CALL(*download_file
, Cancel());
743 item
->DestinationObserverAsWeakPtr()->DestinationError(reason
);
744 RunAllPendingInMessageLoops();
745 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
746 EXPECT_EQ(reason
, item
->GetLastReason());
748 // Cancel should kill it.
750 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
751 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
, item
->GetLastReason());
754 // Destination errors that occur before the intermediate rename shouldn't cause
755 // the download to be marked as interrupted until after the intermediate rename.
756 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Restart
) {
757 DownloadItemImpl
* item
= CreateDownloadItem();
758 DownloadItemImplDelegate::DownloadTargetCallback callback
;
759 MockDownloadFile
* download_file
=
760 AddDownloadFileToDownloadItem(item
, &callback
);
761 item
->DestinationObserverAsWeakPtr()->DestinationError(
762 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
763 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
765 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
766 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
767 base::FilePath
new_intermediate_path(
768 final_path
.InsertBeforeExtensionASCII("y"));
769 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
770 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
771 new_intermediate_path
));
772 EXPECT_CALL(*download_file
, Cancel())
775 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
776 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
777 RunAllPendingInMessageLoops();
778 // All the callbacks should have happened by now.
779 ::testing::Mock::VerifyAndClearExpectations(download_file
);
780 mock_delegate()->VerifyAndClearExpectations();
781 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
782 EXPECT_TRUE(item
->GetFullPath().empty());
783 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
786 // As above. But if the download can be resumed by continuing, then the
787 // intermediate path should be retained when the download is interrupted after
788 // the intermediate rename succeeds.
789 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Continue
) {
790 CommandLine::ForCurrentProcess()->AppendSwitch(
791 switches::kEnableDownloadResumption
);
792 DownloadItemImpl
* item
= CreateDownloadItem();
793 DownloadItemImplDelegate::DownloadTargetCallback callback
;
794 MockDownloadFile
* download_file
=
795 AddDownloadFileToDownloadItem(item
, &callback
);
796 item
->DestinationObserverAsWeakPtr()->DestinationError(
797 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
798 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
800 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
801 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
802 base::FilePath
new_intermediate_path(
803 final_path
.InsertBeforeExtensionASCII("y"));
804 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
805 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
806 new_intermediate_path
));
807 EXPECT_CALL(*download_file
, FullPath())
808 .WillOnce(Return(base::FilePath(new_intermediate_path
)));
809 EXPECT_CALL(*download_file
, Detach());
811 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
812 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
813 RunAllPendingInMessageLoops();
814 // All the callbacks should have happened by now.
815 ::testing::Mock::VerifyAndClearExpectations(download_file
);
816 mock_delegate()->VerifyAndClearExpectations();
817 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
818 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
819 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
822 // As above. If the intermediate rename fails, then the interrupt reason should
823 // be set to the destination error and the intermediate path should be empty.
824 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Failed
) {
825 CommandLine::ForCurrentProcess()->AppendSwitch(
826 switches::kEnableDownloadResumption
);
827 DownloadItemImpl
* item
= CreateDownloadItem();
828 DownloadItemImplDelegate::DownloadTargetCallback callback
;
829 MockDownloadFile
* download_file
=
830 AddDownloadFileToDownloadItem(item
, &callback
);
831 item
->DestinationObserverAsWeakPtr()->DestinationError(
832 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
833 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
835 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
836 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
837 base::FilePath
new_intermediate_path(
838 final_path
.InsertBeforeExtensionASCII("y"));
839 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
840 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
841 new_intermediate_path
));
842 EXPECT_CALL(*download_file
, Cancel())
845 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
846 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
847 RunAllPendingInMessageLoops();
848 // All the callbacks should have happened by now.
849 ::testing::Mock::VerifyAndClearExpectations(download_file
);
850 mock_delegate()->VerifyAndClearExpectations();
851 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
852 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
, item
->GetLastReason());
853 EXPECT_TRUE(item
->GetFullPath().empty());
854 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
857 TEST_F(DownloadItemTest
, Canceled
) {
858 DownloadItemImpl
* item
= CreateDownloadItem();
859 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
861 // Confirm cancel sets state properly.
862 EXPECT_CALL(*download_file
, Cancel());
864 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
867 TEST_F(DownloadItemTest
, FileRemoved
) {
868 DownloadItemImpl
* item
= CreateDownloadItem();
870 EXPECT_FALSE(item
->GetFileExternallyRemoved());
871 item
->OnDownloadedFileRemoved();
872 EXPECT_TRUE(item
->GetFileExternallyRemoved());
875 TEST_F(DownloadItemTest
, DestinationUpdate
) {
876 DownloadItemImpl
* item
= CreateDownloadItem();
877 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
878 item
->DestinationObserverAsWeakPtr());
879 MockObserver
observer(item
);
881 EXPECT_EQ(0l, item
->CurrentSpeed());
882 EXPECT_EQ("", item
->GetHashState());
883 EXPECT_EQ(0l, item
->GetReceivedBytes());
884 EXPECT_EQ(0l, item
->GetTotalBytes());
885 EXPECT_FALSE(observer
.CheckUpdated());
886 item
->SetTotalBytes(100l);
887 EXPECT_EQ(100l, item
->GetTotalBytes());
889 as_observer
->DestinationUpdate(10, 20, "deadbeef");
890 EXPECT_EQ(20l, item
->CurrentSpeed());
891 EXPECT_EQ("deadbeef", item
->GetHashState());
892 EXPECT_EQ(10l, item
->GetReceivedBytes());
893 EXPECT_EQ(100l, item
->GetTotalBytes());
894 EXPECT_TRUE(observer
.CheckUpdated());
896 as_observer
->DestinationUpdate(200, 20, "livebeef");
897 EXPECT_EQ(20l, item
->CurrentSpeed());
898 EXPECT_EQ("livebeef", item
->GetHashState());
899 EXPECT_EQ(200l, item
->GetReceivedBytes());
900 EXPECT_EQ(0l, item
->GetTotalBytes());
901 EXPECT_TRUE(observer
.CheckUpdated());
904 TEST_F(DownloadItemTest
, DestinationError
) {
905 DownloadItemImpl
* item
= CreateDownloadItem();
906 MockDownloadFile
* download_file
=
907 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
908 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
909 item
->DestinationObserverAsWeakPtr());
910 MockObserver
observer(item
);
912 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
913 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE
, item
->GetLastReason());
914 EXPECT_FALSE(observer
.CheckUpdated());
916 EXPECT_CALL(*download_file
, Cancel());
917 as_observer
->DestinationError(
918 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
919 mock_delegate()->VerifyAndClearExpectations();
920 EXPECT_TRUE(observer
.CheckUpdated());
921 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
922 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
,
923 item
->GetLastReason());
926 TEST_F(DownloadItemTest
, DestinationCompleted
) {
927 DownloadItemImpl
* item
= CreateDownloadItem();
928 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
929 item
->DestinationObserverAsWeakPtr());
930 MockObserver
observer(item
);
932 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
933 EXPECT_EQ("", item
->GetHash());
934 EXPECT_EQ("", item
->GetHashState());
935 EXPECT_FALSE(item
->AllDataSaved());
936 EXPECT_FALSE(observer
.CheckUpdated());
938 as_observer
->DestinationUpdate(10, 20, "deadbeef");
939 EXPECT_TRUE(observer
.CheckUpdated());
940 EXPECT_FALSE(observer
.CheckUpdated()); // Confirm reset.
941 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
942 EXPECT_EQ("", item
->GetHash());
943 EXPECT_EQ("deadbeef", item
->GetHashState());
944 EXPECT_FALSE(item
->AllDataSaved());
946 as_observer
->DestinationCompleted("livebeef");
947 mock_delegate()->VerifyAndClearExpectations();
948 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
949 EXPECT_TRUE(observer
.CheckUpdated());
950 EXPECT_EQ("livebeef", item
->GetHash());
951 EXPECT_EQ("", item
->GetHashState());
952 EXPECT_TRUE(item
->AllDataSaved());
955 TEST_F(DownloadItemTest
, EnabledActionsForNormalDownload
) {
956 DownloadItemImpl
* item
= CreateDownloadItem();
957 MockDownloadFile
* download_file
=
958 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
961 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
962 ASSERT_FALSE(item
->GetTargetFilePath().empty());
963 EXPECT_TRUE(item
->CanShowInFolder());
964 EXPECT_TRUE(item
->CanOpenDownload());
967 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
968 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
969 base::FilePath(kDummyPath
)));
970 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
971 .WillOnce(Return(true));
972 EXPECT_CALL(*download_file
, FullPath())
973 .WillOnce(Return(base::FilePath()));
974 EXPECT_CALL(*download_file
, Detach());
975 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
976 RunAllPendingInMessageLoops();
978 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
979 EXPECT_TRUE(item
->CanShowInFolder());
980 EXPECT_TRUE(item
->CanOpenDownload());
983 TEST_F(DownloadItemTest
, EnabledActionsForTemporaryDownload
) {
984 DownloadItemImpl
* item
= CreateDownloadItem();
985 MockDownloadFile
* download_file
=
986 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
987 item
->SetIsTemporary(true);
989 // InProgress Temporary
990 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
991 ASSERT_FALSE(item
->GetTargetFilePath().empty());
992 ASSERT_TRUE(item
->IsTemporary());
993 EXPECT_FALSE(item
->CanShowInFolder());
994 EXPECT_FALSE(item
->CanOpenDownload());
996 // Complete Temporary
997 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
998 .WillOnce(Return(true));
999 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
1000 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1001 base::FilePath(kDummyPath
)));
1002 EXPECT_CALL(*download_file
, FullPath())
1003 .WillOnce(Return(base::FilePath()));
1004 EXPECT_CALL(*download_file
, Detach());
1005 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1006 RunAllPendingInMessageLoops();
1008 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1009 EXPECT_FALSE(item
->CanShowInFolder());
1010 EXPECT_FALSE(item
->CanOpenDownload());
1013 TEST_F(DownloadItemTest
, EnabledActionsForInterruptedDownload
) {
1014 DownloadItemImpl
* item
= CreateDownloadItem();
1015 MockDownloadFile
* download_file
=
1016 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1018 EXPECT_CALL(*download_file
, Cancel());
1019 item
->DestinationObserverAsWeakPtr()->DestinationError(
1020 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1021 RunAllPendingInMessageLoops();
1023 ASSERT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
1024 ASSERT_FALSE(item
->GetTargetFilePath().empty());
1025 EXPECT_FALSE(item
->CanShowInFolder());
1026 EXPECT_FALSE(item
->CanOpenDownload());
1029 TEST_F(DownloadItemTest
, EnabledActionsForCancelledDownload
) {
1030 DownloadItemImpl
* item
= CreateDownloadItem();
1031 MockDownloadFile
* download_file
=
1032 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1034 EXPECT_CALL(*download_file
, Cancel());
1036 RunAllPendingInMessageLoops();
1038 ASSERT_EQ(DownloadItem::CANCELLED
, item
->GetState());
1039 EXPECT_FALSE(item
->CanShowInFolder());
1040 EXPECT_FALSE(item
->CanOpenDownload());
1043 // Test various aspects of the delegate completion blocker.
1045 // Just allowing completion.
1046 TEST_F(DownloadItemTest
, CompleteDelegate_ReturnTrue
) {
1047 // Test to confirm that if we have a callback that returns true,
1048 // we complete immediately.
1049 DownloadItemImpl
* item
= CreateDownloadItem();
1050 MockDownloadFile
* download_file
=
1051 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1053 // Drive the delegate interaction.
1054 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1055 .WillOnce(Return(true));
1056 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1057 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1058 EXPECT_FALSE(item
->IsDangerous());
1060 // Make sure the download can complete.
1061 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1062 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1063 base::FilePath(kDummyPath
)));
1064 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1065 .WillOnce(Return(true));
1066 EXPECT_CALL(*download_file
, FullPath())
1067 .WillOnce(Return(base::FilePath()));
1068 EXPECT_CALL(*download_file
, Detach());
1069 RunAllPendingInMessageLoops();
1070 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1073 // Just delaying completion.
1074 TEST_F(DownloadItemTest
, CompleteDelegate_BlockOnce
) {
1075 // Test to confirm that if we have a callback that returns true,
1076 // we complete immediately.
1077 DownloadItemImpl
* item
= CreateDownloadItem();
1078 MockDownloadFile
* download_file
=
1079 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1081 // Drive the delegate interaction.
1082 base::Closure delegate_callback
;
1083 base::Closure copy_delegate_callback
;
1084 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1085 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1087 .WillOnce(Return(true));
1088 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1089 ASSERT_FALSE(delegate_callback
.is_null());
1090 copy_delegate_callback
= delegate_callback
;
1091 delegate_callback
.Reset();
1092 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1093 copy_delegate_callback
.Run();
1094 ASSERT_TRUE(delegate_callback
.is_null());
1095 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1096 EXPECT_FALSE(item
->IsDangerous());
1098 // Make sure the download can complete.
1099 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1100 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1101 base::FilePath(kDummyPath
)));
1102 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1103 .WillOnce(Return(true));
1104 EXPECT_CALL(*download_file
, FullPath())
1105 .WillOnce(Return(base::FilePath()));
1106 EXPECT_CALL(*download_file
, Detach());
1107 RunAllPendingInMessageLoops();
1108 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1111 // Delay and set danger.
1112 TEST_F(DownloadItemTest
, CompleteDelegate_SetDanger
) {
1113 // Test to confirm that if we have a callback that returns true,
1114 // we complete immediately.
1115 DownloadItemImpl
* item
= CreateDownloadItem();
1116 MockDownloadFile
* download_file
=
1117 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1119 // Drive the delegate interaction.
1120 base::Closure delegate_callback
;
1121 base::Closure copy_delegate_callback
;
1122 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1123 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1125 .WillOnce(Return(true));
1126 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1127 ASSERT_FALSE(delegate_callback
.is_null());
1128 copy_delegate_callback
= delegate_callback
;
1129 delegate_callback
.Reset();
1130 EXPECT_FALSE(item
->IsDangerous());
1131 item
->OnContentCheckCompleted(
1132 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1133 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1134 copy_delegate_callback
.Run();
1135 ASSERT_TRUE(delegate_callback
.is_null());
1136 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1137 EXPECT_TRUE(item
->IsDangerous());
1139 // Make sure the download doesn't complete until we've validated it.
1140 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1141 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1142 base::FilePath(kDummyPath
)));
1143 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1144 .WillOnce(Return(true));
1145 EXPECT_CALL(*download_file
, FullPath())
1146 .WillOnce(Return(base::FilePath()));
1147 EXPECT_CALL(*download_file
, Detach());
1148 RunAllPendingInMessageLoops();
1149 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1150 EXPECT_TRUE(item
->IsDangerous());
1152 item
->ValidateDangerousDownload();
1153 EXPECT_EQ(DOWNLOAD_DANGER_TYPE_USER_VALIDATED
, item
->GetDangerType());
1154 RunAllPendingInMessageLoops();
1155 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1158 // Just delaying completion twice.
1159 TEST_F(DownloadItemTest
, CompleteDelegate_BlockTwice
) {
1160 // Test to confirm that if we have a callback that returns true,
1161 // we complete immediately.
1162 DownloadItemImpl
* item
= CreateDownloadItem();
1163 MockDownloadFile
* download_file
=
1164 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1166 // Drive the delegate interaction.
1167 base::Closure delegate_callback
;
1168 base::Closure copy_delegate_callback
;
1169 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1170 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1172 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1174 .WillOnce(Return(true));
1175 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1176 ASSERT_FALSE(delegate_callback
.is_null());
1177 copy_delegate_callback
= delegate_callback
;
1178 delegate_callback
.Reset();
1179 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1180 copy_delegate_callback
.Run();
1181 ASSERT_FALSE(delegate_callback
.is_null());
1182 copy_delegate_callback
= delegate_callback
;
1183 delegate_callback
.Reset();
1184 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1185 copy_delegate_callback
.Run();
1186 ASSERT_TRUE(delegate_callback
.is_null());
1187 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1188 EXPECT_FALSE(item
->IsDangerous());
1190 // Make sure the download can complete.
1191 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1192 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1193 base::FilePath(kDummyPath
)));
1194 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1195 .WillOnce(Return(true));
1196 EXPECT_CALL(*download_file
, FullPath())
1197 .WillOnce(Return(base::FilePath()));
1198 EXPECT_CALL(*download_file
, Detach());
1199 RunAllPendingInMessageLoops();
1200 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1203 TEST_F(DownloadItemTest
, StealDangerousDownload
) {
1204 DownloadItemImpl
* item
= CreateDownloadItem();
1205 MockDownloadFile
* download_file
=
1206 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1207 ASSERT_TRUE(item
->IsDangerous());
1208 base::FilePath
full_path(FILE_PATH_LITERAL("foo.txt"));
1209 base::FilePath returned_path
;
1211 EXPECT_CALL(*download_file
, FullPath())
1212 .WillOnce(Return(full_path
));
1213 EXPECT_CALL(*download_file
, Detach());
1214 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1215 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1216 item
->StealDangerousDownload(
1217 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1218 weak_ptr_factory
.GetWeakPtr(),
1219 base::Unretained(&returned_path
)));
1220 RunAllPendingInMessageLoops();
1221 EXPECT_EQ(full_path
, returned_path
);
1224 TEST_F(DownloadItemTest
, StealInterruptedDangerousDownload
) {
1225 CommandLine::ForCurrentProcess()->AppendSwitch(
1226 switches::kEnableDownloadResumption
);
1227 base::FilePath returned_path
;
1228 DownloadItemImpl
* item
= CreateDownloadItem();
1229 MockDownloadFile
* download_file
=
1230 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1231 base::FilePath full_path
= item
->GetFullPath();
1232 EXPECT_FALSE(full_path
.empty());
1233 EXPECT_CALL(*download_file
, FullPath())
1234 .WillOnce(Return(full_path
));
1235 EXPECT_CALL(*download_file
, Detach());
1236 item
->DestinationObserverAsWeakPtr()->DestinationError(
1237 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
1238 ASSERT_TRUE(item
->IsDangerous());
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
, StealInterruptedNonResumableDangerousDownload
) {
1251 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 EXPECT_CALL(*download_file
, Cancel());
1258 item
->DestinationObserverAsWeakPtr()->DestinationError(
1259 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1260 ASSERT_TRUE(item
->IsDangerous());
1262 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1263 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1264 item
->StealDangerousDownload(
1265 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1266 weak_ptr_factory
.GetWeakPtr(),
1267 base::Unretained(&returned_path
)));
1268 RunAllPendingInMessageLoops();
1269 EXPECT_TRUE(returned_path
.empty());
1272 TEST(MockDownloadItem
, Compiles
) {
1273 MockDownloadItem mock_item
;
1276 } // namespace content