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