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 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 ~MockObserver() override
{
125 if (item_
) item_
->RemoveObserver(this);
128 void OnDownloadRemoved(DownloadItem
* download
) override
{
129 DVLOG(20) << " " << __FUNCTION__
130 << " download = " << download
->DebugString(false);
134 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 void OnDownloadOpened(DownloadItem
* download
) override
{
151 DVLOG(20) << " " << __FUNCTION__
152 << " download = " << download
->DebugString(false);
155 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_
);
212 // This class keeps ownership of the created download item; it will
213 // be torn down at the end of the test unless DestroyDownloadItem is
215 DownloadItemImpl
* CreateDownloadItem() {
216 // Normally, the download system takes ownership of info, and is
217 // responsible for deleting it. In these unit tests, however, we
218 // don't call the function that deletes it, so we do so ourselves.
219 scoped_ptr
<DownloadCreateInfo
> info_
;
221 info_
.reset(new DownloadCreateInfo());
222 static uint32 next_id
= DownloadItem::kInvalidId
+ 1;
223 info_
->save_info
= scoped_ptr
<DownloadSaveInfo
>(new DownloadSaveInfo());
224 info_
->save_info
->prompt_for_save_location
= false;
225 info_
->url_chain
.push_back(GURL());
226 info_
->etag
= "SomethingToSatisfyResumption";
228 DownloadItemImpl
* download
=
229 new DownloadItemImpl(
230 &delegate_
, next_id
++, *(info_
.get()), net::BoundNetLog());
231 allocated_downloads_
.insert(download
);
235 // Add DownloadFile to DownloadItem
236 MockDownloadFile
* AddDownloadFileToDownloadItem(
237 DownloadItemImpl
* item
,
238 DownloadItemImplDelegate::DownloadTargetCallback
*callback
) {
239 MockDownloadFile
* mock_download_file(new StrictMock
<MockDownloadFile
>);
240 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
241 EXPECT_CALL(*mock_download_file
, Initialize(_
));
243 // Save the callback.
244 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
245 .WillOnce(SaveArg
<1>(callback
));
247 // Drop it on the floor.
248 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
251 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
252 new NiceMock
<MockRequestHandle
>);
253 item
->Start(download_file
.Pass(), request_handle
.Pass());
254 loop_
.RunUntilIdle();
256 // So that we don't have a function writing to a stack variable
257 // lying around if the above failed.
258 mock_delegate()->VerifyAndClearExpectations();
259 EXPECT_CALL(*mock_delegate(), AssertStateConsistent(_
))
260 .WillRepeatedly(Return());
261 EXPECT_CALL(*mock_delegate(), ShouldOpenFileBasedOnExtension(_
))
262 .WillRepeatedly(Return(false));
263 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(_
, _
))
264 .WillRepeatedly(Return(true));
266 return mock_download_file
;
269 // Perform the intermediate rename for |item|. The target path for the
270 // download will be set to kDummyPath. Returns the MockDownloadFile* that was
271 // added to the DownloadItem.
272 MockDownloadFile
* DoIntermediateRename(DownloadItemImpl
* item
,
273 DownloadDangerType danger_type
) {
274 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
275 EXPECT_TRUE(item
->GetTargetFilePath().empty());
276 DownloadItemImplDelegate::DownloadTargetCallback callback
;
277 MockDownloadFile
* download_file
=
278 AddDownloadFileToDownloadItem(item
, &callback
);
279 base::FilePath
target_path(kDummyPath
);
280 base::FilePath
intermediate_path(
281 target_path
.InsertBeforeExtensionASCII("x"));
282 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
283 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
285 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
286 danger_type
, intermediate_path
);
287 RunAllPendingInMessageLoops();
288 return download_file
;
291 // Cleanup a download item (specifically get rid of the DownloadFile on it).
292 // The item must be in the expected state.
293 void CleanupItem(DownloadItemImpl
* item
,
294 MockDownloadFile
* download_file
,
295 DownloadItem::DownloadState expected_state
) {
296 EXPECT_EQ(expected_state
, item
->GetState());
298 if (expected_state
== DownloadItem::IN_PROGRESS
) {
299 EXPECT_CALL(*download_file
, Cancel());
301 loop_
.RunUntilIdle();
305 // Destroy a previously created download item.
306 void DestroyDownloadItem(DownloadItem
* item
) {
307 allocated_downloads_
.erase(item
);
311 void RunAllPendingInMessageLoops() {
312 loop_
.RunUntilIdle();
315 MockDelegate
* mock_delegate() {
319 void OnDownloadFileAcquired(base::FilePath
* return_path
,
320 const base::FilePath
& path
) {
325 base::MessageLoopForUI loop_
;
326 TestBrowserThread ui_thread_
; // UI thread
327 TestBrowserThread file_thread_
; // FILE thread
328 StrictMock
<MockDelegate
> delegate_
;
329 std::set
<DownloadItem
*> allocated_downloads_
;
332 // Tests to ensure calls that change a DownloadItem generate an update to
334 // State changing functions not tested:
335 // void OpenDownload();
336 // void ShowDownloadInShell();
337 // void CompleteDelayedDownload();
340 TEST_F(DownloadItemTest
, NotificationAfterUpdate
) {
341 DownloadItemImpl
* item
= CreateDownloadItem();
342 MockObserver
observer(item
);
344 item
->DestinationUpdate(kDownloadChunkSize
, kDownloadSpeed
, std::string());
345 ASSERT_TRUE(observer
.CheckUpdated());
346 EXPECT_EQ(kDownloadSpeed
, item
->CurrentSpeed());
349 TEST_F(DownloadItemTest
, NotificationAfterCancel
) {
350 DownloadItemImpl
* user_cancel
= CreateDownloadItem();
351 MockDownloadFile
* download_file
=
352 AddDownloadFileToDownloadItem(user_cancel
, NULL
);
353 EXPECT_CALL(*download_file
, Cancel());
354 MockObserver
observer1(user_cancel
);
356 user_cancel
->Cancel(true);
357 ASSERT_TRUE(observer1
.CheckUpdated());
359 DownloadItemImpl
* system_cancel
= CreateDownloadItem();
360 download_file
= AddDownloadFileToDownloadItem(system_cancel
, NULL
);
361 EXPECT_CALL(*download_file
, Cancel());
362 MockObserver
observer2(system_cancel
);
364 system_cancel
->Cancel(false);
365 ASSERT_TRUE(observer2
.CheckUpdated());
368 TEST_F(DownloadItemTest
, NotificationAfterComplete
) {
369 DownloadItemImpl
* item
= CreateDownloadItem();
370 MockObserver
observer(item
);
372 item
->OnAllDataSaved(DownloadItem::kEmptyFileHash
);
373 ASSERT_TRUE(observer
.CheckUpdated());
375 item
->MarkAsComplete();
376 ASSERT_TRUE(observer
.CheckUpdated());
379 TEST_F(DownloadItemTest
, NotificationAfterDownloadedFileRemoved
) {
380 DownloadItemImpl
* item
= CreateDownloadItem();
381 MockObserver
observer(item
);
383 item
->OnDownloadedFileRemoved();
384 ASSERT_TRUE(observer
.CheckUpdated());
387 TEST_F(DownloadItemTest
, NotificationAfterInterrupted
) {
388 DownloadItemImpl
* item
= CreateDownloadItem();
389 MockDownloadFile
* download_file
=
390 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
391 EXPECT_CALL(*download_file
, Cancel());
392 MockObserver
observer(item
);
394 EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_
,_
))
397 item
->DestinationObserverAsWeakPtr()->DestinationError(
398 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
399 ASSERT_TRUE(observer
.CheckUpdated());
402 TEST_F(DownloadItemTest
, NotificationAfterDestroyed
) {
403 DownloadItemImpl
* item
= CreateDownloadItem();
404 MockObserver
observer(item
);
406 DestroyDownloadItem(item
);
407 ASSERT_TRUE(observer
.CheckDestroyed());
410 TEST_F(DownloadItemTest
, ContinueAfterInterrupted
) {
411 base::CommandLine::ForCurrentProcess()->AppendSwitch(
412 switches::kEnableDownloadResumption
);
414 DownloadItemImpl
* item
= CreateDownloadItem();
415 MockObserver
observer(item
);
416 DownloadItemImplDelegate::DownloadTargetCallback callback
;
417 MockDownloadFile
* download_file
=
418 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
420 // Interrupt the download, using a continuable interrupt.
421 EXPECT_CALL(*download_file
, FullPath())
422 .WillOnce(Return(base::FilePath()));
423 EXPECT_CALL(*download_file
, Detach());
424 item
->DestinationObserverAsWeakPtr()->DestinationError(
425 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
426 ASSERT_TRUE(observer
.CheckUpdated());
427 // Should attempt to auto-resume. Because we don't have a mock WebContents,
428 // ResumeInterruptedDownload() will abort early, with another interrupt,
429 // which will be ignored.
430 ASSERT_EQ(1, observer
.GetInterruptCount());
431 ASSERT_EQ(0, observer
.GetResumeCount());
432 RunAllPendingInMessageLoops();
434 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
437 // Same as above, but with a non-continuable interrupt.
438 TEST_F(DownloadItemTest
, RestartAfterInterrupted
) {
439 base::CommandLine::ForCurrentProcess()->AppendSwitch(
440 switches::kEnableDownloadResumption
);
442 DownloadItemImpl
* item
= CreateDownloadItem();
443 MockObserver
observer(item
);
444 DownloadItemImplDelegate::DownloadTargetCallback callback
;
445 MockDownloadFile
* download_file
=
446 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
448 // Interrupt the download, using a restartable interrupt.
449 EXPECT_CALL(*download_file
, Cancel());
450 item
->DestinationObserverAsWeakPtr()->DestinationError(
451 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
452 ASSERT_TRUE(observer
.CheckUpdated());
453 // Should not try to auto-resume.
454 ASSERT_EQ(1, observer
.GetInterruptCount());
455 ASSERT_EQ(0, observer
.GetResumeCount());
456 RunAllPendingInMessageLoops();
458 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
461 // Check we do correct cleanup for RESUME_MODE_INVALID interrupts.
462 TEST_F(DownloadItemTest
, UnresumableInterrupt
) {
463 base::CommandLine::ForCurrentProcess()->AppendSwitch(
464 switches::kEnableDownloadResumption
);
466 DownloadItemImpl
* item
= CreateDownloadItem();
467 MockObserver
observer(item
);
468 DownloadItemImplDelegate::DownloadTargetCallback callback
;
469 MockDownloadFile
* download_file
=
470 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
472 // Fail final rename with unresumable reason.
473 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
474 .WillOnce(Return(true));
475 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
476 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED
,
477 base::FilePath(kDummyPath
)));
478 EXPECT_CALL(*download_file
, Cancel());
480 // Complete download to trigger final rename.
481 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
482 RunAllPendingInMessageLoops();
484 ASSERT_TRUE(observer
.CheckUpdated());
485 // Should not try to auto-resume.
486 ASSERT_EQ(1, observer
.GetInterruptCount());
487 ASSERT_EQ(0, observer
.GetResumeCount());
489 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
492 TEST_F(DownloadItemTest
, LimitRestartsAfterInterrupted
) {
493 base::CommandLine::ForCurrentProcess()->AppendSwitch(
494 switches::kEnableDownloadResumption
);
496 DownloadItemImpl
* item
= CreateDownloadItem();
497 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
498 item
->DestinationObserverAsWeakPtr());
499 MockObserver
observer(item
);
500 MockDownloadFile
* mock_download_file(NULL
);
501 scoped_ptr
<DownloadFile
> download_file
;
502 MockRequestHandle
* mock_request_handle(NULL
);
503 scoped_ptr
<DownloadRequestHandleInterface
> request_handle
;
504 DownloadItemImplDelegate::DownloadTargetCallback callback
;
506 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
507 .WillRepeatedly(SaveArg
<1>(&callback
));
508 for (int i
= 0; i
< (DownloadItemImpl::kMaxAutoResumeAttempts
+ 1); ++i
) {
509 DVLOG(20) << "Loop iteration " << i
;
511 mock_download_file
= new NiceMock
<MockDownloadFile
>;
512 download_file
.reset(mock_download_file
);
513 mock_request_handle
= new NiceMock
<MockRequestHandle
>;
514 request_handle
.reset(mock_request_handle
);
516 ON_CALL(*mock_download_file
, FullPath())
517 .WillByDefault(Return(base::FilePath()));
519 // It's too complicated to set up a WebContents instance that would cause
520 // the MockDownloadItemDelegate's ResumeInterruptedDownload() function
521 // to be callled, so we simply verify that GetWebContents() is called.
522 if (i
< (DownloadItemImpl::kMaxAutoResumeAttempts
- 1)) {
523 EXPECT_CALL(*mock_request_handle
, GetWebContents())
524 .WillRepeatedly(Return(static_cast<WebContents
*>(NULL
)));
527 // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem
528 // to allow for holding onto the request handle.
529 item
->Start(download_file
.Pass(), request_handle
.Pass());
530 RunAllPendingInMessageLoops();
532 // Target determination is only done the first time through.
533 base::FilePath
target_path(kDummyPath
);
534 base::FilePath
intermediate_path(
535 target_path
.InsertBeforeExtensionASCII("x"));
536 EXPECT_CALL(*mock_download_file
, RenameAndUniquify(intermediate_path
, _
))
537 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
539 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
540 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
541 RunAllPendingInMessageLoops();
543 ASSERT_EQ(i
, observer
.GetResumeCount());
545 // Use a continuable interrupt.
546 item
->DestinationObserverAsWeakPtr()->DestinationError(
547 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
549 ASSERT_EQ(i
+ 1, observer
.GetInterruptCount());
550 ::testing::Mock::VerifyAndClearExpectations(mock_download_file
);
553 CleanupItem(item
, mock_download_file
, DownloadItem::INTERRUPTED
);
556 TEST_F(DownloadItemTest
, NotificationAfterRemove
) {
557 DownloadItemImpl
* item
= CreateDownloadItem();
558 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
559 EXPECT_CALL(*download_file
, Cancel());
560 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
561 MockObserver
observer(item
);
564 ASSERT_TRUE(observer
.CheckUpdated());
565 ASSERT_TRUE(observer
.CheckRemoved());
568 TEST_F(DownloadItemTest
, NotificationAfterOnContentCheckCompleted
) {
569 // Setting to NOT_DANGEROUS does not trigger a notification.
570 DownloadItemImpl
* safe_item
= CreateDownloadItem();
571 MockObserver
safe_observer(safe_item
);
573 safe_item
->OnAllDataSaved(std::string());
574 EXPECT_TRUE(safe_observer
.CheckUpdated());
575 safe_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
576 EXPECT_TRUE(safe_observer
.CheckUpdated());
578 // Setting to unsafe url or unsafe file should trigger a notification.
579 DownloadItemImpl
* unsafeurl_item
=
580 CreateDownloadItem();
581 MockObserver
unsafeurl_observer(unsafeurl_item
);
583 unsafeurl_item
->OnAllDataSaved(std::string());
584 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
585 unsafeurl_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL
);
586 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
588 unsafeurl_item
->ValidateDangerousDownload();
589 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
591 DownloadItemImpl
* unsafefile_item
=
592 CreateDownloadItem();
593 MockObserver
unsafefile_observer(unsafefile_item
);
595 unsafefile_item
->OnAllDataSaved(std::string());
596 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
597 unsafefile_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
598 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
600 unsafefile_item
->ValidateDangerousDownload();
601 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
604 // DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
605 // DownloadFile::Rename(). Once the rename
606 // completes, DownloadItemImpl receives a notification with the new file
607 // name. Check that observers are updated when the new filename is available and
609 TEST_F(DownloadItemTest
, NotificationAfterOnDownloadTargetDetermined
) {
610 DownloadItemImpl
* item
= CreateDownloadItem();
611 DownloadItemImplDelegate::DownloadTargetCallback callback
;
612 MockDownloadFile
* download_file
=
613 AddDownloadFileToDownloadItem(item
, &callback
);
614 MockObserver
observer(item
);
615 base::FilePath
target_path(kDummyPath
);
616 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
617 base::FilePath
new_intermediate_path(
618 target_path
.InsertBeforeExtensionASCII("y"));
619 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
620 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
621 new_intermediate_path
));
623 // Currently, a notification would be generated if the danger type is anything
624 // other than NOT_DANGEROUS.
625 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
626 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
627 EXPECT_FALSE(observer
.CheckUpdated());
628 RunAllPendingInMessageLoops();
629 EXPECT_TRUE(observer
.CheckUpdated());
630 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
632 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
635 TEST_F(DownloadItemTest
, NotificationAfterTogglePause
) {
636 DownloadItemImpl
* item
= CreateDownloadItem();
637 MockObserver
observer(item
);
638 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
639 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
640 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
641 new NiceMock
<MockRequestHandle
>);
643 EXPECT_CALL(*mock_download_file
, Initialize(_
));
644 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_
, _
));
645 item
->Start(download_file
.Pass(), request_handle
.Pass());
648 ASSERT_TRUE(observer
.CheckUpdated());
650 ASSERT_TRUE(item
->IsPaused());
653 ASSERT_TRUE(observer
.CheckUpdated());
655 RunAllPendingInMessageLoops();
657 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
660 TEST_F(DownloadItemTest
, DisplayName
) {
661 DownloadItemImpl
* item
= CreateDownloadItem();
662 DownloadItemImplDelegate::DownloadTargetCallback callback
;
663 MockDownloadFile
* download_file
=
664 AddDownloadFileToDownloadItem(item
, &callback
);
665 base::FilePath
target_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
666 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
667 EXPECT_EQ(FILE_PATH_LITERAL(""),
668 item
->GetFileNameToReportUser().value());
669 EXPECT_CALL(*download_file
, RenameAndUniquify(_
, _
))
670 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
672 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
673 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
674 RunAllPendingInMessageLoops();
675 EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
676 item
->GetFileNameToReportUser().value());
677 item
->SetDisplayName(base::FilePath(FILE_PATH_LITERAL("new.name")));
678 EXPECT_EQ(FILE_PATH_LITERAL("new.name"),
679 item
->GetFileNameToReportUser().value());
680 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
683 // Test to make sure that Start method calls DF initialize properly.
684 TEST_F(DownloadItemTest
, Start
) {
685 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
686 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
687 DownloadItemImpl
* item
= CreateDownloadItem();
688 EXPECT_CALL(*mock_download_file
, Initialize(_
));
689 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
690 new NiceMock
<MockRequestHandle
>);
691 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
692 item
->Start(download_file
.Pass(), request_handle
.Pass());
693 RunAllPendingInMessageLoops();
695 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
698 // Test that the delegate is invoked after the download file is renamed.
699 TEST_F(DownloadItemTest
, CallbackAfterRename
) {
700 DownloadItemImpl
* item
= CreateDownloadItem();
701 DownloadItemImplDelegate::DownloadTargetCallback callback
;
702 MockDownloadFile
* download_file
=
703 AddDownloadFileToDownloadItem(item
, &callback
);
704 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
705 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
706 base::FilePath
new_intermediate_path(
707 final_path
.InsertBeforeExtensionASCII("y"));
708 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
709 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
710 new_intermediate_path
));
712 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
713 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
714 RunAllPendingInMessageLoops();
715 // All the callbacks should have happened by now.
716 ::testing::Mock::VerifyAndClearExpectations(download_file
);
717 mock_delegate()->VerifyAndClearExpectations();
719 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
720 .WillOnce(Return(true));
721 EXPECT_CALL(*download_file
, RenameAndAnnotate(final_path
, _
))
722 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
724 EXPECT_CALL(*download_file
, FullPath())
725 .WillOnce(Return(base::FilePath()));
726 EXPECT_CALL(*download_file
, Detach());
727 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
728 RunAllPendingInMessageLoops();
729 ::testing::Mock::VerifyAndClearExpectations(download_file
);
730 mock_delegate()->VerifyAndClearExpectations();
733 // Test that the delegate is invoked after the download file is renamed and the
734 // download item is in an interrupted state.
735 TEST_F(DownloadItemTest
, CallbackAfterInterruptedRename
) {
736 DownloadItemImpl
* item
= CreateDownloadItem();
737 DownloadItemImplDelegate::DownloadTargetCallback callback
;
738 MockDownloadFile
* download_file
=
739 AddDownloadFileToDownloadItem(item
, &callback
);
740 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
741 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
742 base::FilePath
new_intermediate_path(
743 final_path
.InsertBeforeExtensionASCII("y"));
744 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
745 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
746 new_intermediate_path
));
747 EXPECT_CALL(*download_file
, Cancel())
750 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
751 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
752 RunAllPendingInMessageLoops();
753 // All the callbacks should have happened by now.
754 ::testing::Mock::VerifyAndClearExpectations(download_file
);
755 mock_delegate()->VerifyAndClearExpectations();
758 TEST_F(DownloadItemTest
, Interrupted
) {
759 DownloadItemImpl
* item
= CreateDownloadItem();
760 MockDownloadFile
* download_file
=
761 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
763 const DownloadInterruptReason
reason(
764 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
766 // Confirm interrupt sets state properly.
767 EXPECT_CALL(*download_file
, Cancel());
768 item
->DestinationObserverAsWeakPtr()->DestinationError(reason
);
769 RunAllPendingInMessageLoops();
770 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
771 EXPECT_EQ(reason
, item
->GetLastReason());
773 // Cancel should kill it.
775 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
776 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
, item
->GetLastReason());
779 // Destination errors that occur before the intermediate rename shouldn't cause
780 // the download to be marked as interrupted until after the intermediate rename.
781 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Restart
) {
782 DownloadItemImpl
* item
= CreateDownloadItem();
783 DownloadItemImplDelegate::DownloadTargetCallback callback
;
784 MockDownloadFile
* download_file
=
785 AddDownloadFileToDownloadItem(item
, &callback
);
786 item
->DestinationObserverAsWeakPtr()->DestinationError(
787 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
788 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
790 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
791 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
792 base::FilePath
new_intermediate_path(
793 final_path
.InsertBeforeExtensionASCII("y"));
794 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
795 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
796 new_intermediate_path
));
797 EXPECT_CALL(*download_file
, Cancel())
800 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
801 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
802 RunAllPendingInMessageLoops();
803 // All the callbacks should have happened by now.
804 ::testing::Mock::VerifyAndClearExpectations(download_file
);
805 mock_delegate()->VerifyAndClearExpectations();
806 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
807 EXPECT_TRUE(item
->GetFullPath().empty());
808 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
811 // As above. But if the download can be resumed by continuing, then the
812 // intermediate path should be retained when the download is interrupted after
813 // the intermediate rename succeeds.
814 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Continue
) {
815 base::CommandLine::ForCurrentProcess()->AppendSwitch(
816 switches::kEnableDownloadResumption
);
817 DownloadItemImpl
* item
= CreateDownloadItem();
818 DownloadItemImplDelegate::DownloadTargetCallback callback
;
819 MockDownloadFile
* download_file
=
820 AddDownloadFileToDownloadItem(item
, &callback
);
821 item
->DestinationObserverAsWeakPtr()->DestinationError(
822 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
823 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
825 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
826 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
827 base::FilePath
new_intermediate_path(
828 final_path
.InsertBeforeExtensionASCII("y"));
829 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
830 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
831 new_intermediate_path
));
832 EXPECT_CALL(*download_file
, FullPath())
833 .WillOnce(Return(base::FilePath(new_intermediate_path
)));
834 EXPECT_CALL(*download_file
, Detach());
836 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
837 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
838 RunAllPendingInMessageLoops();
839 // All the callbacks should have happened by now.
840 ::testing::Mock::VerifyAndClearExpectations(download_file
);
841 mock_delegate()->VerifyAndClearExpectations();
842 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
843 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
844 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
847 // As above. If the intermediate rename fails, then the interrupt reason should
848 // be set to the destination error and the intermediate path should be empty.
849 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Failed
) {
850 base::CommandLine::ForCurrentProcess()->AppendSwitch(
851 switches::kEnableDownloadResumption
);
852 DownloadItemImpl
* item
= CreateDownloadItem();
853 DownloadItemImplDelegate::DownloadTargetCallback callback
;
854 MockDownloadFile
* download_file
=
855 AddDownloadFileToDownloadItem(item
, &callback
);
856 item
->DestinationObserverAsWeakPtr()->DestinationError(
857 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
858 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
860 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
861 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
862 base::FilePath
new_intermediate_path(
863 final_path
.InsertBeforeExtensionASCII("y"));
864 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
865 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
866 new_intermediate_path
));
867 EXPECT_CALL(*download_file
, Cancel())
870 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
871 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
872 RunAllPendingInMessageLoops();
873 // All the callbacks should have happened by now.
874 ::testing::Mock::VerifyAndClearExpectations(download_file
);
875 mock_delegate()->VerifyAndClearExpectations();
876 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
877 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
, item
->GetLastReason());
878 EXPECT_TRUE(item
->GetFullPath().empty());
879 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
882 TEST_F(DownloadItemTest
, Canceled
) {
883 DownloadItemImpl
* item
= CreateDownloadItem();
884 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
886 // Confirm cancel sets state properly.
887 EXPECT_CALL(*download_file
, Cancel());
889 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
892 TEST_F(DownloadItemTest
, FileRemoved
) {
893 DownloadItemImpl
* item
= CreateDownloadItem();
895 EXPECT_FALSE(item
->GetFileExternallyRemoved());
896 item
->OnDownloadedFileRemoved();
897 EXPECT_TRUE(item
->GetFileExternallyRemoved());
900 TEST_F(DownloadItemTest
, DestinationUpdate
) {
901 DownloadItemImpl
* item
= CreateDownloadItem();
902 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
903 item
->DestinationObserverAsWeakPtr());
904 MockObserver
observer(item
);
906 EXPECT_EQ(0l, item
->CurrentSpeed());
907 EXPECT_EQ("", item
->GetHashState());
908 EXPECT_EQ(0l, item
->GetReceivedBytes());
909 EXPECT_EQ(0l, item
->GetTotalBytes());
910 EXPECT_FALSE(observer
.CheckUpdated());
911 item
->SetTotalBytes(100l);
912 EXPECT_EQ(100l, item
->GetTotalBytes());
914 as_observer
->DestinationUpdate(10, 20, "deadbeef");
915 EXPECT_EQ(20l, item
->CurrentSpeed());
916 EXPECT_EQ("deadbeef", item
->GetHashState());
917 EXPECT_EQ(10l, item
->GetReceivedBytes());
918 EXPECT_EQ(100l, item
->GetTotalBytes());
919 EXPECT_TRUE(observer
.CheckUpdated());
921 as_observer
->DestinationUpdate(200, 20, "livebeef");
922 EXPECT_EQ(20l, item
->CurrentSpeed());
923 EXPECT_EQ("livebeef", item
->GetHashState());
924 EXPECT_EQ(200l, item
->GetReceivedBytes());
925 EXPECT_EQ(0l, item
->GetTotalBytes());
926 EXPECT_TRUE(observer
.CheckUpdated());
929 TEST_F(DownloadItemTest
, DestinationError
) {
930 DownloadItemImpl
* item
= CreateDownloadItem();
931 MockDownloadFile
* download_file
=
932 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
933 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
934 item
->DestinationObserverAsWeakPtr());
935 MockObserver
observer(item
);
937 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
938 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE
, item
->GetLastReason());
939 EXPECT_FALSE(observer
.CheckUpdated());
941 EXPECT_CALL(*download_file
, Cancel());
942 as_observer
->DestinationError(
943 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
944 mock_delegate()->VerifyAndClearExpectations();
945 EXPECT_TRUE(observer
.CheckUpdated());
946 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
947 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
,
948 item
->GetLastReason());
951 TEST_F(DownloadItemTest
, DestinationCompleted
) {
952 DownloadItemImpl
* item
= CreateDownloadItem();
953 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
954 item
->DestinationObserverAsWeakPtr());
955 MockObserver
observer(item
);
957 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
958 EXPECT_EQ("", item
->GetHash());
959 EXPECT_EQ("", item
->GetHashState());
960 EXPECT_FALSE(item
->AllDataSaved());
961 EXPECT_FALSE(observer
.CheckUpdated());
963 as_observer
->DestinationUpdate(10, 20, "deadbeef");
964 EXPECT_TRUE(observer
.CheckUpdated());
965 EXPECT_FALSE(observer
.CheckUpdated()); // Confirm reset.
966 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
967 EXPECT_EQ("", item
->GetHash());
968 EXPECT_EQ("deadbeef", item
->GetHashState());
969 EXPECT_FALSE(item
->AllDataSaved());
971 as_observer
->DestinationCompleted("livebeef");
972 mock_delegate()->VerifyAndClearExpectations();
973 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
974 EXPECT_TRUE(observer
.CheckUpdated());
975 EXPECT_EQ("livebeef", item
->GetHash());
976 EXPECT_EQ("", item
->GetHashState());
977 EXPECT_TRUE(item
->AllDataSaved());
980 TEST_F(DownloadItemTest
, EnabledActionsForNormalDownload
) {
981 DownloadItemImpl
* item
= CreateDownloadItem();
982 MockDownloadFile
* download_file
=
983 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
986 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
987 ASSERT_FALSE(item
->GetTargetFilePath().empty());
988 EXPECT_TRUE(item
->CanShowInFolder());
989 EXPECT_TRUE(item
->CanOpenDownload());
992 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
993 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
994 base::FilePath(kDummyPath
)));
995 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
996 .WillOnce(Return(true));
997 EXPECT_CALL(*download_file
, FullPath())
998 .WillOnce(Return(base::FilePath()));
999 EXPECT_CALL(*download_file
, Detach());
1000 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1001 RunAllPendingInMessageLoops();
1003 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1004 EXPECT_TRUE(item
->CanShowInFolder());
1005 EXPECT_TRUE(item
->CanOpenDownload());
1008 TEST_F(DownloadItemTest
, EnabledActionsForTemporaryDownload
) {
1009 DownloadItemImpl
* item
= CreateDownloadItem();
1010 MockDownloadFile
* download_file
=
1011 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1012 item
->SetIsTemporary(true);
1014 // InProgress Temporary
1015 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1016 ASSERT_FALSE(item
->GetTargetFilePath().empty());
1017 ASSERT_TRUE(item
->IsTemporary());
1018 EXPECT_FALSE(item
->CanShowInFolder());
1019 EXPECT_FALSE(item
->CanOpenDownload());
1021 // Complete Temporary
1022 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1023 .WillOnce(Return(true));
1024 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
1025 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1026 base::FilePath(kDummyPath
)));
1027 EXPECT_CALL(*download_file
, FullPath())
1028 .WillOnce(Return(base::FilePath()));
1029 EXPECT_CALL(*download_file
, Detach());
1030 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1031 RunAllPendingInMessageLoops();
1033 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1034 EXPECT_FALSE(item
->CanShowInFolder());
1035 EXPECT_FALSE(item
->CanOpenDownload());
1038 TEST_F(DownloadItemTest
, EnabledActionsForInterruptedDownload
) {
1039 DownloadItemImpl
* item
= CreateDownloadItem();
1040 MockDownloadFile
* download_file
=
1041 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1043 EXPECT_CALL(*download_file
, Cancel());
1044 item
->DestinationObserverAsWeakPtr()->DestinationError(
1045 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1046 RunAllPendingInMessageLoops();
1048 ASSERT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
1049 ASSERT_FALSE(item
->GetTargetFilePath().empty());
1050 EXPECT_FALSE(item
->CanShowInFolder());
1051 EXPECT_FALSE(item
->CanOpenDownload());
1054 TEST_F(DownloadItemTest
, EnabledActionsForCancelledDownload
) {
1055 DownloadItemImpl
* item
= CreateDownloadItem();
1056 MockDownloadFile
* download_file
=
1057 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1059 EXPECT_CALL(*download_file
, Cancel());
1061 RunAllPendingInMessageLoops();
1063 ASSERT_EQ(DownloadItem::CANCELLED
, item
->GetState());
1064 EXPECT_FALSE(item
->CanShowInFolder());
1065 EXPECT_FALSE(item
->CanOpenDownload());
1068 // Test various aspects of the delegate completion blocker.
1070 // Just allowing completion.
1071 TEST_F(DownloadItemTest
, CompleteDelegate_ReturnTrue
) {
1072 // Test to confirm that if we have a callback that returns true,
1073 // we complete immediately.
1074 DownloadItemImpl
* item
= CreateDownloadItem();
1075 MockDownloadFile
* download_file
=
1076 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1078 // Drive the delegate interaction.
1079 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1080 .WillOnce(Return(true));
1081 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1082 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1083 EXPECT_FALSE(item
->IsDangerous());
1085 // Make sure the download can complete.
1086 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1087 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1088 base::FilePath(kDummyPath
)));
1089 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1090 .WillOnce(Return(true));
1091 EXPECT_CALL(*download_file
, FullPath())
1092 .WillOnce(Return(base::FilePath()));
1093 EXPECT_CALL(*download_file
, Detach());
1094 RunAllPendingInMessageLoops();
1095 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1098 // Just delaying completion.
1099 TEST_F(DownloadItemTest
, CompleteDelegate_BlockOnce
) {
1100 // Test to confirm that if we have a callback that returns true,
1101 // we complete immediately.
1102 DownloadItemImpl
* item
= CreateDownloadItem();
1103 MockDownloadFile
* download_file
=
1104 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1106 // Drive the delegate interaction.
1107 base::Closure delegate_callback
;
1108 base::Closure copy_delegate_callback
;
1109 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1110 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1112 .WillOnce(Return(true));
1113 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1114 ASSERT_FALSE(delegate_callback
.is_null());
1115 copy_delegate_callback
= delegate_callback
;
1116 delegate_callback
.Reset();
1117 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1118 copy_delegate_callback
.Run();
1119 ASSERT_TRUE(delegate_callback
.is_null());
1120 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1121 EXPECT_FALSE(item
->IsDangerous());
1123 // Make sure the download can complete.
1124 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1125 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1126 base::FilePath(kDummyPath
)));
1127 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1128 .WillOnce(Return(true));
1129 EXPECT_CALL(*download_file
, FullPath())
1130 .WillOnce(Return(base::FilePath()));
1131 EXPECT_CALL(*download_file
, Detach());
1132 RunAllPendingInMessageLoops();
1133 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1136 // Delay and set danger.
1137 TEST_F(DownloadItemTest
, CompleteDelegate_SetDanger
) {
1138 // Test to confirm that if we have a callback that returns true,
1139 // we complete immediately.
1140 DownloadItemImpl
* item
= CreateDownloadItem();
1141 MockDownloadFile
* download_file
=
1142 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1144 // Drive the delegate interaction.
1145 base::Closure delegate_callback
;
1146 base::Closure copy_delegate_callback
;
1147 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1148 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1150 .WillOnce(Return(true));
1151 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1152 ASSERT_FALSE(delegate_callback
.is_null());
1153 copy_delegate_callback
= delegate_callback
;
1154 delegate_callback
.Reset();
1155 EXPECT_FALSE(item
->IsDangerous());
1156 item
->OnContentCheckCompleted(
1157 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1158 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1159 copy_delegate_callback
.Run();
1160 ASSERT_TRUE(delegate_callback
.is_null());
1161 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1162 EXPECT_TRUE(item
->IsDangerous());
1164 // Make sure the download doesn't complete until we've validated it.
1165 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1166 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1167 base::FilePath(kDummyPath
)));
1168 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1169 .WillOnce(Return(true));
1170 EXPECT_CALL(*download_file
, FullPath())
1171 .WillOnce(Return(base::FilePath()));
1172 EXPECT_CALL(*download_file
, Detach());
1173 RunAllPendingInMessageLoops();
1174 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1175 EXPECT_TRUE(item
->IsDangerous());
1177 item
->ValidateDangerousDownload();
1178 EXPECT_EQ(DOWNLOAD_DANGER_TYPE_USER_VALIDATED
, item
->GetDangerType());
1179 RunAllPendingInMessageLoops();
1180 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1183 // Just delaying completion twice.
1184 TEST_F(DownloadItemTest
, CompleteDelegate_BlockTwice
) {
1185 // Test to confirm that if we have a callback that returns true,
1186 // we complete immediately.
1187 DownloadItemImpl
* item
= CreateDownloadItem();
1188 MockDownloadFile
* download_file
=
1189 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1191 // Drive the delegate interaction.
1192 base::Closure delegate_callback
;
1193 base::Closure copy_delegate_callback
;
1194 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1195 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1197 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1199 .WillOnce(Return(true));
1200 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1201 ASSERT_FALSE(delegate_callback
.is_null());
1202 copy_delegate_callback
= delegate_callback
;
1203 delegate_callback
.Reset();
1204 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1205 copy_delegate_callback
.Run();
1206 ASSERT_FALSE(delegate_callback
.is_null());
1207 copy_delegate_callback
= delegate_callback
;
1208 delegate_callback
.Reset();
1209 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1210 copy_delegate_callback
.Run();
1211 ASSERT_TRUE(delegate_callback
.is_null());
1212 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1213 EXPECT_FALSE(item
->IsDangerous());
1215 // Make sure the download can complete.
1216 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1217 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1218 base::FilePath(kDummyPath
)));
1219 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1220 .WillOnce(Return(true));
1221 EXPECT_CALL(*download_file
, FullPath())
1222 .WillOnce(Return(base::FilePath()));
1223 EXPECT_CALL(*download_file
, Detach());
1224 RunAllPendingInMessageLoops();
1225 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1228 TEST_F(DownloadItemTest
, StealDangerousDownload
) {
1229 DownloadItemImpl
* item
= CreateDownloadItem();
1230 MockDownloadFile
* download_file
=
1231 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1232 ASSERT_TRUE(item
->IsDangerous());
1233 base::FilePath
full_path(FILE_PATH_LITERAL("foo.txt"));
1234 base::FilePath returned_path
;
1236 EXPECT_CALL(*download_file
, FullPath())
1237 .WillOnce(Return(full_path
));
1238 EXPECT_CALL(*download_file
, Detach());
1239 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1240 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1241 item
->StealDangerousDownload(
1242 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1243 weak_ptr_factory
.GetWeakPtr(),
1244 base::Unretained(&returned_path
)));
1245 RunAllPendingInMessageLoops();
1246 EXPECT_EQ(full_path
, returned_path
);
1249 TEST_F(DownloadItemTest
, StealInterruptedDangerousDownload
) {
1250 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1251 switches::kEnableDownloadResumption
);
1252 base::FilePath returned_path
;
1253 DownloadItemImpl
* item
= CreateDownloadItem();
1254 MockDownloadFile
* download_file
=
1255 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1256 base::FilePath full_path
= item
->GetFullPath();
1257 EXPECT_FALSE(full_path
.empty());
1258 EXPECT_CALL(*download_file
, FullPath())
1259 .WillOnce(Return(full_path
));
1260 EXPECT_CALL(*download_file
, Detach());
1261 item
->DestinationObserverAsWeakPtr()->DestinationError(
1262 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
1263 ASSERT_TRUE(item
->IsDangerous());
1265 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1266 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1267 item
->StealDangerousDownload(
1268 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1269 weak_ptr_factory
.GetWeakPtr(),
1270 base::Unretained(&returned_path
)));
1271 RunAllPendingInMessageLoops();
1272 EXPECT_EQ(full_path
, returned_path
);
1275 TEST_F(DownloadItemTest
, StealInterruptedNonResumableDangerousDownload
) {
1276 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1277 switches::kEnableDownloadResumption
);
1278 base::FilePath returned_path
;
1279 DownloadItemImpl
* item
= CreateDownloadItem();
1280 MockDownloadFile
* download_file
=
1281 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1282 EXPECT_CALL(*download_file
, Cancel());
1283 item
->DestinationObserverAsWeakPtr()->DestinationError(
1284 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1285 ASSERT_TRUE(item
->IsDangerous());
1287 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1288 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1289 item
->StealDangerousDownload(
1290 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1291 weak_ptr_factory
.GetWeakPtr(),
1292 base::Unretained(&returned_path
)));
1293 RunAllPendingInMessageLoops();
1294 EXPECT_TRUE(returned_path
.empty());
1297 TEST(MockDownloadItem
, Compiles
) {
1298 MockDownloadItem mock_item
;
1301 } // namespace content