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.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_id.h"
19 #include "content/public/browser/download_interrupt_reasons.h"
20 #include "content/public/browser/download_url_parameters.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/test/mock_download_item.h"
23 #include "content/public/test/test_browser_thread.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
28 using ::testing::NiceMock
;
29 using ::testing::Property
;
30 using ::testing::Return
;
31 using ::testing::SaveArg
;
32 using ::testing::StrictMock
;
36 const int kDownloadChunkSize
= 1000;
37 const int kDownloadSpeed
= 1000;
38 const int kDummyDBHandle
= 10;
39 const base::FilePath::CharType kDummyPath
[] = FILE_PATH_LITERAL("/testpath");
47 DownloadId::Domain kValidDownloadItemIdDomain
= "valid DownloadId::Domain";
49 class MockDelegate
: public DownloadItemImplDelegate
{
51 MockDelegate() : DownloadItemImplDelegate() {
52 SetDefaultExpectations();
55 MOCK_METHOD2(DetermineDownloadTarget
, void(
56 DownloadItemImpl
*, const DownloadTargetCallback
&));
57 MOCK_METHOD2(ShouldCompleteDownload
,
58 bool(DownloadItemImpl
*, const base::Closure
&));
59 MOCK_METHOD2(ShouldOpenDownload
,
60 bool(DownloadItemImpl
*, const ShouldOpenDownloadCallback
&));
61 MOCK_METHOD1(ShouldOpenFileBasedOnExtension
, bool(const base::FilePath
&));
62 MOCK_METHOD1(CheckForFileRemoval
, void(DownloadItemImpl
*));
64 virtual void ResumeInterruptedDownload(
65 scoped_ptr
<DownloadUrlParameters
> params
, DownloadId id
) OVERRIDE
{
66 MockResumeInterruptedDownload(params
.get(), id
);
68 MOCK_METHOD2(MockResumeInterruptedDownload
,
69 void(DownloadUrlParameters
* params
, DownloadId id
));
71 MOCK_CONST_METHOD0(GetBrowserContext
, BrowserContext
*());
72 MOCK_METHOD1(UpdatePersistence
, void(DownloadItemImpl
*));
73 MOCK_METHOD1(DownloadOpened
, void(DownloadItemImpl
*));
74 MOCK_METHOD1(DownloadRemoved
, void(DownloadItemImpl
*));
75 MOCK_CONST_METHOD1(AssertStateConsistent
, void(DownloadItemImpl
*));
77 void VerifyAndClearExpectations() {
78 ::testing::Mock::VerifyAndClearExpectations(this);
79 SetDefaultExpectations();
83 void SetDefaultExpectations() {
84 EXPECT_CALL(*this, AssertStateConsistent(_
))
85 .WillRepeatedly(Return());
86 EXPECT_CALL(*this, ShouldOpenFileBasedOnExtension(_
))
87 .WillRepeatedly(Return(false));
88 EXPECT_CALL(*this, ShouldOpenDownload(_
, _
))
89 .WillRepeatedly(Return(true));
93 class MockRequestHandle
: public DownloadRequestHandleInterface
{
95 MOCK_CONST_METHOD0(GetWebContents
, WebContents
*());
96 MOCK_CONST_METHOD0(GetDownloadManager
, DownloadManager
*());
97 MOCK_CONST_METHOD0(PauseRequest
, void());
98 MOCK_CONST_METHOD0(ResumeRequest
, void());
99 MOCK_CONST_METHOD0(CancelRequest
, void());
100 MOCK_CONST_METHOD0(DebugString
, std::string());
103 // Schedules a task to invoke the RenameCompletionCallback with |new_path| on
104 // the UI thread. Should only be used as the action for
105 // MockDownloadFile::Rename as follows:
106 // EXPECT_CALL(download_file, Rename*(_,_))
107 // .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
109 ACTION_P2(ScheduleRenameCallback
, interrupt_reason
, new_path
) {
110 BrowserThread::PostTask(
111 BrowserThread::UI
, FROM_HERE
,
112 base::Bind(arg1
, interrupt_reason
, new_path
));
117 class DownloadItemTest
: public testing::Test
{
119 class MockObserver
: public DownloadItem::Observer
{
121 explicit MockObserver(DownloadItem
* item
)
123 last_state_(item
->GetState()),
129 item_
->AddObserver(this);
132 virtual ~MockObserver() {
133 if (item_
) item_
->RemoveObserver(this);
136 virtual void OnDownloadRemoved(DownloadItem
* download
) OVERRIDE
{
137 DVLOG(20) << " " << __FUNCTION__
138 << " download = " << download
->DebugString(false);
142 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
{
143 DVLOG(20) << " " << __FUNCTION__
144 << " download = " << download
->DebugString(false);
146 DownloadItem::DownloadState new_state
= download
->GetState();
147 if (last_state_
== DownloadItem::IN_PROGRESS
&&
148 new_state
== DownloadItem::INTERRUPTED
) {
151 if (last_state_
== DownloadItem::INTERRUPTED
&&
152 new_state
== DownloadItem::IN_PROGRESS
) {
155 last_state_
= new_state
;
158 virtual void OnDownloadOpened(DownloadItem
* download
) OVERRIDE
{
159 DVLOG(20) << " " << __FUNCTION__
160 << " download = " << download
->DebugString(false);
163 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
{
164 DVLOG(20) << " " << __FUNCTION__
165 << " download = " << download
->DebugString(false);
167 item_
->RemoveObserver(this);
171 bool CheckRemoved() {
175 bool CheckDestroyed() {
179 bool CheckUpdated() {
180 bool was_updated
= updated_
;
185 int GetInterruptCount() {
186 return interrupt_count_
;
189 int GetResumeCount() {
190 return resume_count_
;
195 DownloadItem::DownloadState last_state_
;
199 int interrupt_count_
;
204 : ui_thread_(BrowserThread::UI
, &loop_
),
205 file_thread_(BrowserThread::FILE, &loop_
),
209 ~DownloadItemTest() {
212 virtual void SetUp() {
215 virtual void TearDown() {
216 ui_thread_
.DeprecatedGetThreadObject()->message_loop()->RunUntilIdle();
217 STLDeleteElements(&allocated_downloads_
);
218 allocated_downloads_
.clear();
221 // This class keeps ownership of the created download item; it will
222 // be torn down at the end of the test unless DestroyDownloadItem is
224 DownloadItemImpl
* CreateDownloadItem() {
225 // Normally, the download system takes ownership of info, and is
226 // responsible for deleting it. In these unit tests, however, we
227 // don't call the function that deletes it, so we do so ourselves.
228 scoped_ptr
<DownloadCreateInfo
> info_
;
230 info_
.reset(new DownloadCreateInfo());
231 static int next_id
= 0;
232 DownloadId
id(DownloadId(kValidDownloadItemIdDomain
, ++next_id
));
233 info_
->save_info
= scoped_ptr
<DownloadSaveInfo
>(new DownloadSaveInfo());
234 info_
->save_info
->prompt_for_save_location
= false;
235 info_
->url_chain
.push_back(GURL());
236 info_
->etag
= "SomethingToSatisfyResumption";
238 DownloadItemImpl
* download
=
239 new DownloadItemImpl(
240 &delegate_
, id
, *(info_
.get()), net::BoundNetLog());
241 allocated_downloads_
.insert(download
);
245 // Add DownloadFile to DownloadItem
246 MockDownloadFile
* AddDownloadFileToDownloadItem(
247 DownloadItemImpl
* item
,
248 DownloadItemImplDelegate::DownloadTargetCallback
*callback
) {
249 MockDownloadFile
* mock_download_file(new StrictMock
<MockDownloadFile
>);
250 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
251 EXPECT_CALL(*mock_download_file
, Initialize(_
));
253 // Save the callback.
254 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
255 .WillOnce(SaveArg
<1>(callback
));
257 // Drop it on the floor.
258 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
261 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
262 new NiceMock
<MockRequestHandle
>);
263 item
->Start(download_file
.Pass(), request_handle
.Pass());
264 loop_
.RunUntilIdle();
266 // So that we don't have a function writing to a stack variable
267 // lying around if the above failed.
268 mock_delegate()->VerifyAndClearExpectations();
269 EXPECT_CALL(*mock_delegate(), AssertStateConsistent(_
))
270 .WillRepeatedly(Return());
271 EXPECT_CALL(*mock_delegate(), ShouldOpenFileBasedOnExtension(_
))
272 .WillRepeatedly(Return(false));
273 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(_
, _
))
274 .WillRepeatedly(Return(true));
276 return mock_download_file
;
279 // Perform the intermediate rename for |item|. The target path for the
280 // download will be set to kDummyPath. Returns the MockDownloadFile* that was
281 // added to the DownloadItem.
282 MockDownloadFile
* DoIntermediateRename(DownloadItemImpl
* item
,
283 DownloadDangerType danger_type
) {
284 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
285 EXPECT_TRUE(item
->GetTargetFilePath().empty());
286 DownloadItemImplDelegate::DownloadTargetCallback callback
;
287 MockDownloadFile
* download_file
=
288 AddDownloadFileToDownloadItem(item
, &callback
);
289 base::FilePath
target_path(kDummyPath
);
290 base::FilePath
intermediate_path(
291 target_path
.InsertBeforeExtensionASCII("x"));
292 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
293 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
295 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
296 danger_type
, intermediate_path
);
297 RunAllPendingInMessageLoops();
298 return download_file
;
301 // Cleanup a download item (specifically get rid of the DownloadFile on it).
302 // The item must be in the expected state.
303 void CleanupItem(DownloadItemImpl
* item
,
304 MockDownloadFile
* download_file
,
305 DownloadItem::DownloadState expected_state
) {
306 EXPECT_EQ(expected_state
, item
->GetState());
308 if (expected_state
== DownloadItem::IN_PROGRESS
) {
309 EXPECT_CALL(*download_file
, Cancel());
311 loop_
.RunUntilIdle();
315 // Destroy a previously created download item.
316 void DestroyDownloadItem(DownloadItem
* item
) {
317 allocated_downloads_
.erase(item
);
321 void RunAllPendingInMessageLoops() {
322 loop_
.RunUntilIdle();
325 MockDelegate
* mock_delegate() {
329 void OnDownloadFileAcquired(base::FilePath
* return_path
,
330 const base::FilePath
& path
) {
335 base::MessageLoopForUI loop_
;
336 TestBrowserThread ui_thread_
; // UI thread
337 TestBrowserThread file_thread_
; // FILE thread
338 StrictMock
<MockDelegate
> delegate_
;
339 std::set
<DownloadItem
*> allocated_downloads_
;
342 // Tests to ensure calls that change a DownloadItem generate an update to
344 // State changing functions not tested:
345 // void OpenDownload();
346 // void ShowDownloadInShell();
347 // void CompleteDelayedDownload();
350 TEST_F(DownloadItemTest
, NotificationAfterUpdate
) {
351 DownloadItemImpl
* item
= CreateDownloadItem();
352 MockObserver
observer(item
);
354 item
->DestinationUpdate(kDownloadChunkSize
, kDownloadSpeed
, std::string());
355 ASSERT_TRUE(observer
.CheckUpdated());
356 EXPECT_EQ(kDownloadSpeed
, item
->CurrentSpeed());
359 TEST_F(DownloadItemTest
, NotificationAfterCancel
) {
360 DownloadItemImpl
* user_cancel
= CreateDownloadItem();
361 MockDownloadFile
* download_file
=
362 AddDownloadFileToDownloadItem(user_cancel
, NULL
);
363 EXPECT_CALL(*download_file
, Cancel());
364 MockObserver
observer1(user_cancel
);
366 user_cancel
->Cancel(true);
367 ASSERT_TRUE(observer1
.CheckUpdated());
369 DownloadItemImpl
* system_cancel
= CreateDownloadItem();
370 download_file
= AddDownloadFileToDownloadItem(system_cancel
, NULL
);
371 EXPECT_CALL(*download_file
, Cancel());
372 MockObserver
observer2(system_cancel
);
374 system_cancel
->Cancel(false);
375 ASSERT_TRUE(observer2
.CheckUpdated());
378 TEST_F(DownloadItemTest
, NotificationAfterComplete
) {
379 DownloadItemImpl
* item
= CreateDownloadItem();
380 MockObserver
observer(item
);
382 item
->OnAllDataSaved(DownloadItem::kEmptyFileHash
);
383 ASSERT_TRUE(observer
.CheckUpdated());
385 item
->MarkAsComplete();
386 ASSERT_TRUE(observer
.CheckUpdated());
389 TEST_F(DownloadItemTest
, NotificationAfterDownloadedFileRemoved
) {
390 DownloadItemImpl
* item
= CreateDownloadItem();
391 MockObserver
observer(item
);
393 item
->OnDownloadedFileRemoved();
394 ASSERT_TRUE(observer
.CheckUpdated());
397 TEST_F(DownloadItemTest
, NotificationAfterInterrupted
) {
398 DownloadItemImpl
* item
= CreateDownloadItem();
399 MockDownloadFile
* download_file
=
400 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
401 EXPECT_CALL(*download_file
, Cancel());
402 MockObserver
observer(item
);
404 EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_
,_
))
407 item
->DestinationObserverAsWeakPtr()->DestinationError(
408 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
409 ASSERT_TRUE(observer
.CheckUpdated());
412 TEST_F(DownloadItemTest
, NotificationAfterDestroyed
) {
413 DownloadItemImpl
* item
= CreateDownloadItem();
414 MockObserver
observer(item
);
416 DestroyDownloadItem(item
);
417 ASSERT_TRUE(observer
.CheckDestroyed());
420 TEST_F(DownloadItemTest
, ContinueAfterInterrupted
) {
421 CommandLine::ForCurrentProcess()->AppendSwitch(
422 switches::kEnableDownloadResumption
);
424 DownloadItemImpl
* item
= CreateDownloadItem();
425 MockObserver
observer(item
);
426 DownloadItemImplDelegate::DownloadTargetCallback callback
;
427 MockDownloadFile
* download_file
=
428 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
430 // Interrupt the download, using a continuable interrupt.
431 EXPECT_CALL(*download_file
, FullPath())
432 .WillOnce(Return(base::FilePath()));
433 EXPECT_CALL(*download_file
, Detach());
434 item
->DestinationObserverAsWeakPtr()->DestinationError(
435 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
436 ASSERT_TRUE(observer
.CheckUpdated());
437 // Should attempt to auto-resume. Because we don't have a mock WebContents,
438 // ResumeInterruptedDownload() will abort early, with another interrupt,
439 // which will be ignored.
440 ASSERT_EQ(1, observer
.GetInterruptCount());
441 ASSERT_EQ(0, observer
.GetResumeCount());
442 RunAllPendingInMessageLoops();
444 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
447 // Same as above, but with a non-continuable interrupt.
448 TEST_F(DownloadItemTest
, RestartAfterInterrupted
) {
449 CommandLine::ForCurrentProcess()->AppendSwitch(
450 switches::kEnableDownloadResumption
);
452 DownloadItemImpl
* item
= CreateDownloadItem();
453 MockObserver
observer(item
);
454 DownloadItemImplDelegate::DownloadTargetCallback callback
;
455 MockDownloadFile
* download_file
=
456 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
458 // Interrupt the download, using a restartable interrupt.
459 EXPECT_CALL(*download_file
, Cancel());
460 item
->DestinationObserverAsWeakPtr()->DestinationError(
461 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
462 ASSERT_TRUE(observer
.CheckUpdated());
463 // Should not try to auto-resume.
464 ASSERT_EQ(1, observer
.GetInterruptCount());
465 ASSERT_EQ(0, observer
.GetResumeCount());
466 RunAllPendingInMessageLoops();
468 CleanupItem(item
, download_file
, DownloadItem::INTERRUPTED
);
471 TEST_F(DownloadItemTest
, LimitRestartsAfterInterrupted
) {
472 CommandLine::ForCurrentProcess()->AppendSwitch(
473 switches::kEnableDownloadResumption
);
475 DownloadItemImpl
* item
= CreateDownloadItem();
476 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
477 item
->DestinationObserverAsWeakPtr());
478 MockObserver
observer(item
);
479 MockDownloadFile
* mock_download_file(NULL
);
480 scoped_ptr
<DownloadFile
> download_file
;
481 MockRequestHandle
* mock_request_handle(NULL
);
482 scoped_ptr
<DownloadRequestHandleInterface
> request_handle
;
483 DownloadItemImplDelegate::DownloadTargetCallback callback
;
485 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
))
486 .WillRepeatedly(SaveArg
<1>(&callback
));
487 for (int i
= 0; i
< (DownloadItemImpl::kMaxAutoResumeAttempts
+ 1); ++i
) {
488 DVLOG(20) << "Loop iteration " << i
;
490 mock_download_file
= new NiceMock
<MockDownloadFile
>;
491 download_file
.reset(mock_download_file
);
492 mock_request_handle
= new NiceMock
<MockRequestHandle
>;
493 request_handle
.reset(mock_request_handle
);
495 ON_CALL(*mock_download_file
, FullPath())
496 .WillByDefault(Return(base::FilePath()));
498 // It's too complicated to set up a WebContents instance that would cause
499 // the MockDownloadItemDelegate's ResumeInterruptedDownload() function
500 // to be callled, so we simply verify that GetWebContents() is called.
501 if (i
< (DownloadItemImpl::kMaxAutoResumeAttempts
- 1)) {
502 EXPECT_CALL(*mock_request_handle
, GetWebContents())
503 .WillOnce(Return(static_cast<WebContents
*>(NULL
)));
506 // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem
507 // to allow for holding onto the request handle.
508 item
->Start(download_file
.Pass(), request_handle
.Pass());
509 RunAllPendingInMessageLoops();
511 // Target determination is only done the first time through.
512 base::FilePath
target_path(kDummyPath
);
513 base::FilePath
intermediate_path(
514 target_path
.InsertBeforeExtensionASCII("x"));
515 EXPECT_CALL(*mock_download_file
, RenameAndUniquify(intermediate_path
, _
))
516 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
518 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
519 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
520 RunAllPendingInMessageLoops();
522 ASSERT_EQ(i
, observer
.GetResumeCount());
524 // Use a continuable interrupt.
525 item
->DestinationObserverAsWeakPtr()->DestinationError(
526 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
);
528 ASSERT_EQ(i
+ 1, observer
.GetInterruptCount());
529 ::testing::Mock::VerifyAndClearExpectations(mock_download_file
);
532 CleanupItem(item
, mock_download_file
, DownloadItem::INTERRUPTED
);
535 TEST_F(DownloadItemTest
, NotificationAfterRemove
) {
536 DownloadItemImpl
* item
= CreateDownloadItem();
537 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
538 EXPECT_CALL(*download_file
, Cancel());
539 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
540 MockObserver
observer(item
);
543 ASSERT_TRUE(observer
.CheckUpdated());
544 ASSERT_TRUE(observer
.CheckRemoved());
547 TEST_F(DownloadItemTest
, NotificationAfterOnContentCheckCompleted
) {
548 // Setting to NOT_DANGEROUS does not trigger a notification.
549 DownloadItemImpl
* safe_item
= CreateDownloadItem();
550 MockObserver
safe_observer(safe_item
);
552 safe_item
->OnAllDataSaved(std::string());
553 EXPECT_TRUE(safe_observer
.CheckUpdated());
554 safe_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
555 EXPECT_TRUE(safe_observer
.CheckUpdated());
557 // Setting to unsafe url or unsafe file should trigger a notification.
558 DownloadItemImpl
* unsafeurl_item
=
559 CreateDownloadItem();
560 MockObserver
unsafeurl_observer(unsafeurl_item
);
562 unsafeurl_item
->OnAllDataSaved(std::string());
563 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
564 unsafeurl_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL
);
565 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
567 unsafeurl_item
->ValidateDangerousDownload();
568 EXPECT_TRUE(unsafeurl_observer
.CheckUpdated());
570 DownloadItemImpl
* unsafefile_item
=
571 CreateDownloadItem();
572 MockObserver
unsafefile_observer(unsafefile_item
);
574 unsafefile_item
->OnAllDataSaved(std::string());
575 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
576 unsafefile_item
->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
577 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
579 unsafefile_item
->ValidateDangerousDownload();
580 EXPECT_TRUE(unsafefile_observer
.CheckUpdated());
583 // DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
584 // DownloadFile::Rename(). Once the rename
585 // completes, DownloadItemImpl receives a notification with the new file
586 // name. Check that observers are updated when the new filename is available and
588 TEST_F(DownloadItemTest
, NotificationAfterOnDownloadTargetDetermined
) {
589 DownloadItemImpl
* item
= CreateDownloadItem();
590 DownloadItemImplDelegate::DownloadTargetCallback callback
;
591 MockDownloadFile
* download_file
=
592 AddDownloadFileToDownloadItem(item
, &callback
);
593 MockObserver
observer(item
);
594 base::FilePath
target_path(kDummyPath
);
595 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
596 base::FilePath
new_intermediate_path(
597 target_path
.InsertBeforeExtensionASCII("y"));
598 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
599 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
600 new_intermediate_path
));
602 // Currently, a notification would be generated if the danger type is anything
603 // other than NOT_DANGEROUS.
604 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
605 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
606 EXPECT_FALSE(observer
.CheckUpdated());
607 RunAllPendingInMessageLoops();
608 EXPECT_TRUE(observer
.CheckUpdated());
609 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
611 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
614 TEST_F(DownloadItemTest
, NotificationAfterTogglePause
) {
615 DownloadItemImpl
* item
= CreateDownloadItem();
616 MockObserver
observer(item
);
617 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
618 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
619 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
620 new NiceMock
<MockRequestHandle
>);
622 EXPECT_CALL(*mock_download_file
, Initialize(_
));
623 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_
, _
));
624 item
->Start(download_file
.Pass(), request_handle
.Pass());
627 ASSERT_TRUE(observer
.CheckUpdated());
629 ASSERT_TRUE(item
->IsPaused());
632 ASSERT_TRUE(observer
.CheckUpdated());
634 RunAllPendingInMessageLoops();
636 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
639 TEST_F(DownloadItemTest
, DisplayName
) {
640 DownloadItemImpl
* item
= CreateDownloadItem();
641 DownloadItemImplDelegate::DownloadTargetCallback callback
;
642 MockDownloadFile
* download_file
=
643 AddDownloadFileToDownloadItem(item
, &callback
);
644 base::FilePath
target_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
645 base::FilePath
intermediate_path(target_path
.InsertBeforeExtensionASCII("x"));
646 EXPECT_EQ(FILE_PATH_LITERAL(""),
647 item
->GetFileNameToReportUser().value());
648 EXPECT_CALL(*download_file
, RenameAndUniquify(_
, _
))
649 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
651 callback
.Run(target_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
652 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
653 RunAllPendingInMessageLoops();
654 EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
655 item
->GetFileNameToReportUser().value());
656 item
->SetDisplayName(base::FilePath(FILE_PATH_LITERAL("new.name")));
657 EXPECT_EQ(FILE_PATH_LITERAL("new.name"),
658 item
->GetFileNameToReportUser().value());
659 CleanupItem(item
, download_file
, DownloadItem::IN_PROGRESS
);
662 // Test to make sure that Start method calls DF initialize properly.
663 TEST_F(DownloadItemTest
, Start
) {
664 MockDownloadFile
* mock_download_file(new MockDownloadFile
);
665 scoped_ptr
<DownloadFile
> download_file(mock_download_file
);
666 DownloadItemImpl
* item
= CreateDownloadItem();
667 EXPECT_CALL(*mock_download_file
, Initialize(_
));
668 scoped_ptr
<DownloadRequestHandleInterface
> request_handle(
669 new NiceMock
<MockRequestHandle
>);
670 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item
, _
));
671 item
->Start(download_file
.Pass(), request_handle
.Pass());
672 RunAllPendingInMessageLoops();
674 CleanupItem(item
, mock_download_file
, DownloadItem::IN_PROGRESS
);
677 // Test that the delegate is invoked after the download file is renamed.
678 TEST_F(DownloadItemTest
, CallbackAfterRename
) {
679 DownloadItemImpl
* item
= CreateDownloadItem();
680 DownloadItemImplDelegate::DownloadTargetCallback callback
;
681 MockDownloadFile
* download_file
=
682 AddDownloadFileToDownloadItem(item
, &callback
);
683 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
684 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
685 base::FilePath
new_intermediate_path(
686 final_path
.InsertBeforeExtensionASCII("y"));
687 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
688 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
689 new_intermediate_path
));
691 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
692 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
693 RunAllPendingInMessageLoops();
694 // All the callbacks should have happened by now.
695 ::testing::Mock::VerifyAndClearExpectations(download_file
);
696 mock_delegate()->VerifyAndClearExpectations();
698 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
699 .WillOnce(Return(true));
700 EXPECT_CALL(*download_file
, RenameAndAnnotate(final_path
, _
))
701 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
703 EXPECT_CALL(*download_file
, FullPath())
704 .WillOnce(Return(base::FilePath()));
705 EXPECT_CALL(*download_file
, Detach());
706 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
707 RunAllPendingInMessageLoops();
708 ::testing::Mock::VerifyAndClearExpectations(download_file
);
709 mock_delegate()->VerifyAndClearExpectations();
712 // Test that the delegate is invoked after the download file is renamed and the
713 // download item is in an interrupted state.
714 TEST_F(DownloadItemTest
, CallbackAfterInterruptedRename
) {
715 DownloadItemImpl
* item
= CreateDownloadItem();
716 DownloadItemImplDelegate::DownloadTargetCallback callback
;
717 MockDownloadFile
* download_file
=
718 AddDownloadFileToDownloadItem(item
, &callback
);
719 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
720 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
721 base::FilePath
new_intermediate_path(
722 final_path
.InsertBeforeExtensionASCII("y"));
723 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
724 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
725 new_intermediate_path
));
726 EXPECT_CALL(*download_file
, Cancel())
729 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
730 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
731 RunAllPendingInMessageLoops();
732 // All the callbacks should have happened by now.
733 ::testing::Mock::VerifyAndClearExpectations(download_file
);
734 mock_delegate()->VerifyAndClearExpectations();
737 TEST_F(DownloadItemTest
, Interrupted
) {
738 DownloadItemImpl
* item
= CreateDownloadItem();
739 MockDownloadFile
* download_file
=
740 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
742 const DownloadInterruptReason
reason(
743 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
745 // Confirm interrupt sets state properly.
746 EXPECT_CALL(*download_file
, Cancel());
747 item
->DestinationObserverAsWeakPtr()->DestinationError(reason
);
748 RunAllPendingInMessageLoops();
749 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
750 EXPECT_EQ(reason
, item
->GetLastReason());
752 // Cancel should kill it.
754 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
755 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
, item
->GetLastReason());
758 // Destination errors that occur before the intermediate rename shouldn't cause
759 // the download to be marked as interrupted until after the intermediate rename.
760 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Restart
) {
761 DownloadItemImpl
* item
= CreateDownloadItem();
762 DownloadItemImplDelegate::DownloadTargetCallback callback
;
763 MockDownloadFile
* download_file
=
764 AddDownloadFileToDownloadItem(item
, &callback
);
765 item
->DestinationObserverAsWeakPtr()->DestinationError(
766 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
767 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
769 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
770 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
771 base::FilePath
new_intermediate_path(
772 final_path
.InsertBeforeExtensionASCII("y"));
773 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
774 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
775 new_intermediate_path
));
776 EXPECT_CALL(*download_file
, Cancel())
779 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
780 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
781 RunAllPendingInMessageLoops();
782 // All the callbacks should have happened by now.
783 ::testing::Mock::VerifyAndClearExpectations(download_file
);
784 mock_delegate()->VerifyAndClearExpectations();
785 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
786 EXPECT_TRUE(item
->GetFullPath().empty());
787 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
790 // As above. But if the download can be resumed by continuing, then the
791 // intermediate path should be retained when the download is interrupted after
792 // the intermediate rename succeeds.
793 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Continue
) {
794 CommandLine::ForCurrentProcess()->AppendSwitch(
795 switches::kEnableDownloadResumption
);
796 DownloadItemImpl
* item
= CreateDownloadItem();
797 DownloadItemImplDelegate::DownloadTargetCallback callback
;
798 MockDownloadFile
* download_file
=
799 AddDownloadFileToDownloadItem(item
, &callback
);
800 item
->DestinationObserverAsWeakPtr()->DestinationError(
801 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
802 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
804 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
805 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
806 base::FilePath
new_intermediate_path(
807 final_path
.InsertBeforeExtensionASCII("y"));
808 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
809 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
810 new_intermediate_path
));
811 EXPECT_CALL(*download_file
, FullPath())
812 .WillOnce(Return(base::FilePath(new_intermediate_path
)));
813 EXPECT_CALL(*download_file
, Detach());
815 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
816 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
817 RunAllPendingInMessageLoops();
818 // All the callbacks should have happened by now.
819 ::testing::Mock::VerifyAndClearExpectations(download_file
);
820 mock_delegate()->VerifyAndClearExpectations();
821 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
822 EXPECT_EQ(new_intermediate_path
, item
->GetFullPath());
823 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
826 // As above. If the intermediate rename fails, then the interrupt reason should
827 // be set to the destination error and the intermediate path should be empty.
828 TEST_F(DownloadItemTest
, InterruptedBeforeIntermediateRename_Failed
) {
829 CommandLine::ForCurrentProcess()->AppendSwitch(
830 switches::kEnableDownloadResumption
);
831 DownloadItemImpl
* item
= CreateDownloadItem();
832 DownloadItemImplDelegate::DownloadTargetCallback callback
;
833 MockDownloadFile
* download_file
=
834 AddDownloadFileToDownloadItem(item
, &callback
);
835 item
->DestinationObserverAsWeakPtr()->DestinationError(
836 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
837 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
839 base::FilePath
final_path(base::FilePath(kDummyPath
).AppendASCII("foo.bar"));
840 base::FilePath
intermediate_path(final_path
.InsertBeforeExtensionASCII("x"));
841 base::FilePath
new_intermediate_path(
842 final_path
.InsertBeforeExtensionASCII("y"));
843 EXPECT_CALL(*download_file
, RenameAndUniquify(intermediate_path
, _
))
844 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
,
845 new_intermediate_path
));
846 EXPECT_CALL(*download_file
, Cancel())
849 callback
.Run(final_path
, DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
850 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
, intermediate_path
);
851 RunAllPendingInMessageLoops();
852 // All the callbacks should have happened by now.
853 ::testing::Mock::VerifyAndClearExpectations(download_file
);
854 mock_delegate()->VerifyAndClearExpectations();
855 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
856 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
, item
->GetLastReason());
857 EXPECT_TRUE(item
->GetFullPath().empty());
858 EXPECT_EQ(final_path
, item
->GetTargetFilePath());
861 TEST_F(DownloadItemTest
, Canceled
) {
862 DownloadItemImpl
* item
= CreateDownloadItem();
863 MockDownloadFile
* download_file
= AddDownloadFileToDownloadItem(item
, NULL
);
865 // Confirm cancel sets state properly.
866 EXPECT_CALL(*download_file
, Cancel());
868 EXPECT_EQ(DownloadItem::CANCELLED
, item
->GetState());
871 TEST_F(DownloadItemTest
, FileRemoved
) {
872 DownloadItemImpl
* item
= CreateDownloadItem();
874 EXPECT_FALSE(item
->GetFileExternallyRemoved());
875 item
->OnDownloadedFileRemoved();
876 EXPECT_TRUE(item
->GetFileExternallyRemoved());
879 TEST_F(DownloadItemTest
, DestinationUpdate
) {
880 DownloadItemImpl
* item
= CreateDownloadItem();
881 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
882 item
->DestinationObserverAsWeakPtr());
883 MockObserver
observer(item
);
885 EXPECT_EQ(0l, item
->CurrentSpeed());
886 EXPECT_EQ("", item
->GetHashState());
887 EXPECT_EQ(0l, item
->GetReceivedBytes());
888 EXPECT_EQ(0l, item
->GetTotalBytes());
889 EXPECT_FALSE(observer
.CheckUpdated());
890 item
->SetTotalBytes(100l);
891 EXPECT_EQ(100l, item
->GetTotalBytes());
893 as_observer
->DestinationUpdate(10, 20, "deadbeef");
894 EXPECT_EQ(20l, item
->CurrentSpeed());
895 EXPECT_EQ("deadbeef", item
->GetHashState());
896 EXPECT_EQ(10l, item
->GetReceivedBytes());
897 EXPECT_EQ(100l, item
->GetTotalBytes());
898 EXPECT_TRUE(observer
.CheckUpdated());
900 as_observer
->DestinationUpdate(200, 20, "livebeef");
901 EXPECT_EQ(20l, item
->CurrentSpeed());
902 EXPECT_EQ("livebeef", item
->GetHashState());
903 EXPECT_EQ(200l, item
->GetReceivedBytes());
904 EXPECT_EQ(0l, item
->GetTotalBytes());
905 EXPECT_TRUE(observer
.CheckUpdated());
908 TEST_F(DownloadItemTest
, DestinationError
) {
909 DownloadItemImpl
* item
= CreateDownloadItem();
910 MockDownloadFile
* download_file
=
911 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
912 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
913 item
->DestinationObserverAsWeakPtr());
914 MockObserver
observer(item
);
916 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
917 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE
, item
->GetLastReason());
918 EXPECT_FALSE(observer
.CheckUpdated());
920 EXPECT_CALL(*download_file
, Cancel());
921 as_observer
->DestinationError(
922 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
);
923 mock_delegate()->VerifyAndClearExpectations();
924 EXPECT_TRUE(observer
.CheckUpdated());
925 EXPECT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
926 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
,
927 item
->GetLastReason());
930 TEST_F(DownloadItemTest
, DestinationCompleted
) {
931 DownloadItemImpl
* item
= CreateDownloadItem();
932 base::WeakPtr
<DownloadDestinationObserver
> as_observer(
933 item
->DestinationObserverAsWeakPtr());
934 MockObserver
observer(item
);
936 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
937 EXPECT_EQ("", item
->GetHash());
938 EXPECT_EQ("", item
->GetHashState());
939 EXPECT_FALSE(item
->AllDataSaved());
940 EXPECT_FALSE(observer
.CheckUpdated());
942 as_observer
->DestinationUpdate(10, 20, "deadbeef");
943 EXPECT_TRUE(observer
.CheckUpdated());
944 EXPECT_FALSE(observer
.CheckUpdated()); // Confirm reset.
945 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
946 EXPECT_EQ("", item
->GetHash());
947 EXPECT_EQ("deadbeef", item
->GetHashState());
948 EXPECT_FALSE(item
->AllDataSaved());
950 as_observer
->DestinationCompleted("livebeef");
951 mock_delegate()->VerifyAndClearExpectations();
952 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
953 EXPECT_TRUE(observer
.CheckUpdated());
954 EXPECT_EQ("livebeef", item
->GetHash());
955 EXPECT_EQ("", item
->GetHashState());
956 EXPECT_TRUE(item
->AllDataSaved());
959 TEST_F(DownloadItemTest
, EnabledActionsForNormalDownload
) {
960 DownloadItemImpl
* item
= CreateDownloadItem();
961 MockDownloadFile
* download_file
=
962 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
965 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
966 ASSERT_FALSE(item
->GetTargetFilePath().empty());
967 EXPECT_TRUE(item
->CanShowInFolder());
968 EXPECT_TRUE(item
->CanOpenDownload());
971 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
972 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
973 base::FilePath(kDummyPath
)));
974 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
975 .WillOnce(Return(true));
976 EXPECT_CALL(*download_file
, FullPath())
977 .WillOnce(Return(base::FilePath()));
978 EXPECT_CALL(*download_file
, Detach());
979 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
980 RunAllPendingInMessageLoops();
982 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
983 EXPECT_TRUE(item
->CanShowInFolder());
984 EXPECT_TRUE(item
->CanOpenDownload());
987 TEST_F(DownloadItemTest
, EnabledActionsForTemporaryDownload
) {
988 DownloadItemImpl
* item
= CreateDownloadItem();
989 MockDownloadFile
* download_file
=
990 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
991 item
->SetIsTemporary(true);
993 // InProgress Temporary
994 ASSERT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
995 ASSERT_FALSE(item
->GetTargetFilePath().empty());
996 ASSERT_TRUE(item
->IsTemporary());
997 EXPECT_FALSE(item
->CanShowInFolder());
998 EXPECT_FALSE(item
->CanOpenDownload());
1000 // Complete Temporary
1001 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1002 .WillOnce(Return(true));
1003 EXPECT_CALL(*download_file
, RenameAndAnnotate(_
, _
))
1004 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1005 base::FilePath(kDummyPath
)));
1006 EXPECT_CALL(*download_file
, FullPath())
1007 .WillOnce(Return(base::FilePath()));
1008 EXPECT_CALL(*download_file
, Detach());
1009 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1010 RunAllPendingInMessageLoops();
1012 ASSERT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1013 EXPECT_FALSE(item
->CanShowInFolder());
1014 EXPECT_FALSE(item
->CanOpenDownload());
1017 TEST_F(DownloadItemTest
, EnabledActionsForInterruptedDownload
) {
1018 DownloadItemImpl
* item
= CreateDownloadItem();
1019 MockDownloadFile
* download_file
=
1020 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1022 EXPECT_CALL(*download_file
, Cancel());
1023 item
->DestinationObserverAsWeakPtr()->DestinationError(
1024 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1025 RunAllPendingInMessageLoops();
1027 ASSERT_EQ(DownloadItem::INTERRUPTED
, item
->GetState());
1028 ASSERT_FALSE(item
->GetTargetFilePath().empty());
1029 EXPECT_FALSE(item
->CanShowInFolder());
1030 EXPECT_FALSE(item
->CanOpenDownload());
1033 TEST_F(DownloadItemTest
, EnabledActionsForCancelledDownload
) {
1034 DownloadItemImpl
* item
= CreateDownloadItem();
1035 MockDownloadFile
* download_file
=
1036 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1038 EXPECT_CALL(*download_file
, Cancel());
1040 RunAllPendingInMessageLoops();
1042 ASSERT_EQ(DownloadItem::CANCELLED
, item
->GetState());
1043 EXPECT_FALSE(item
->CanShowInFolder());
1044 EXPECT_FALSE(item
->CanOpenDownload());
1047 // Test various aspects of the delegate completion blocker.
1049 // Just allowing completion.
1050 TEST_F(DownloadItemTest
, CompleteDelegate_ReturnTrue
) {
1051 // Test to confirm that if we have a callback that returns true,
1052 // we complete immediately.
1053 DownloadItemImpl
* item
= CreateDownloadItem();
1054 MockDownloadFile
* download_file
=
1055 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1057 // Drive the delegate interaction.
1058 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1059 .WillOnce(Return(true));
1060 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1061 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1062 EXPECT_FALSE(item
->IsDangerous());
1064 // Make sure the download can complete.
1065 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1066 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1067 base::FilePath(kDummyPath
)));
1068 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1069 .WillOnce(Return(true));
1070 EXPECT_CALL(*download_file
, FullPath())
1071 .WillOnce(Return(base::FilePath()));
1072 EXPECT_CALL(*download_file
, Detach());
1073 RunAllPendingInMessageLoops();
1074 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1077 // Just delaying completion.
1078 TEST_F(DownloadItemTest
, CompleteDelegate_BlockOnce
) {
1079 // Test to confirm that if we have a callback that returns true,
1080 // we complete immediately.
1081 DownloadItemImpl
* item
= CreateDownloadItem();
1082 MockDownloadFile
* download_file
=
1083 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1085 // Drive the delegate interaction.
1086 base::Closure delegate_callback
;
1087 base::Closure copy_delegate_callback
;
1088 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1089 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1091 .WillOnce(Return(true));
1092 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1093 ASSERT_FALSE(delegate_callback
.is_null());
1094 copy_delegate_callback
= delegate_callback
;
1095 delegate_callback
.Reset();
1096 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1097 copy_delegate_callback
.Run();
1098 ASSERT_TRUE(delegate_callback
.is_null());
1099 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1100 EXPECT_FALSE(item
->IsDangerous());
1102 // Make sure the download can complete.
1103 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1104 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1105 base::FilePath(kDummyPath
)));
1106 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1107 .WillOnce(Return(true));
1108 EXPECT_CALL(*download_file
, FullPath())
1109 .WillOnce(Return(base::FilePath()));
1110 EXPECT_CALL(*download_file
, Detach());
1111 RunAllPendingInMessageLoops();
1112 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1115 // Delay and set danger.
1116 TEST_F(DownloadItemTest
, CompleteDelegate_SetDanger
) {
1117 // Test to confirm that if we have a callback that returns true,
1118 // we complete immediately.
1119 DownloadItemImpl
* item
= CreateDownloadItem();
1120 MockDownloadFile
* download_file
=
1121 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1123 // Drive the delegate interaction.
1124 base::Closure delegate_callback
;
1125 base::Closure copy_delegate_callback
;
1126 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1127 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1129 .WillOnce(Return(true));
1130 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1131 ASSERT_FALSE(delegate_callback
.is_null());
1132 copy_delegate_callback
= delegate_callback
;
1133 delegate_callback
.Reset();
1134 EXPECT_FALSE(item
->IsDangerous());
1135 item
->OnContentCheckCompleted(
1136 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1137 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1138 copy_delegate_callback
.Run();
1139 ASSERT_TRUE(delegate_callback
.is_null());
1140 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1141 EXPECT_TRUE(item
->IsDangerous());
1143 // Make sure the download doesn't complete until we've validated it.
1144 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1145 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1146 base::FilePath(kDummyPath
)));
1147 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1148 .WillOnce(Return(true));
1149 EXPECT_CALL(*download_file
, FullPath())
1150 .WillOnce(Return(base::FilePath()));
1151 EXPECT_CALL(*download_file
, Detach());
1152 RunAllPendingInMessageLoops();
1153 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1154 EXPECT_TRUE(item
->IsDangerous());
1156 item
->ValidateDangerousDownload();
1157 EXPECT_EQ(DOWNLOAD_DANGER_TYPE_USER_VALIDATED
, item
->GetDangerType());
1158 RunAllPendingInMessageLoops();
1159 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1162 // Just delaying completion twice.
1163 TEST_F(DownloadItemTest
, CompleteDelegate_BlockTwice
) {
1164 // Test to confirm that if we have a callback that returns true,
1165 // we complete immediately.
1166 DownloadItemImpl
* item
= CreateDownloadItem();
1167 MockDownloadFile
* download_file
=
1168 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
);
1170 // Drive the delegate interaction.
1171 base::Closure delegate_callback
;
1172 base::Closure copy_delegate_callback
;
1173 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item
, _
))
1174 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1176 .WillOnce(DoAll(SaveArg
<1>(&delegate_callback
),
1178 .WillOnce(Return(true));
1179 item
->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1180 ASSERT_FALSE(delegate_callback
.is_null());
1181 copy_delegate_callback
= delegate_callback
;
1182 delegate_callback
.Reset();
1183 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1184 copy_delegate_callback
.Run();
1185 ASSERT_FALSE(delegate_callback
.is_null());
1186 copy_delegate_callback
= delegate_callback
;
1187 delegate_callback
.Reset();
1188 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1189 copy_delegate_callback
.Run();
1190 ASSERT_TRUE(delegate_callback
.is_null());
1191 EXPECT_EQ(DownloadItem::IN_PROGRESS
, item
->GetState());
1192 EXPECT_FALSE(item
->IsDangerous());
1194 // Make sure the download can complete.
1195 EXPECT_CALL(*download_file
, RenameAndAnnotate(base::FilePath(kDummyPath
), _
))
1196 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE
,
1197 base::FilePath(kDummyPath
)));
1198 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item
, _
))
1199 .WillOnce(Return(true));
1200 EXPECT_CALL(*download_file
, FullPath())
1201 .WillOnce(Return(base::FilePath()));
1202 EXPECT_CALL(*download_file
, Detach());
1203 RunAllPendingInMessageLoops();
1204 EXPECT_EQ(DownloadItem::COMPLETE
, item
->GetState());
1207 TEST_F(DownloadItemTest
, StealDangerousDownload
) {
1208 DownloadItemImpl
* item
= CreateDownloadItem();
1209 MockDownloadFile
* download_file
=
1210 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1211 ASSERT_TRUE(item
->IsDangerous());
1212 base::FilePath
full_path(FILE_PATH_LITERAL("foo.txt"));
1213 base::FilePath returned_path
;
1215 EXPECT_CALL(*download_file
, FullPath())
1216 .WillOnce(Return(full_path
));
1217 EXPECT_CALL(*download_file
, Detach());
1218 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1219 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1220 item
->StealDangerousDownload(
1221 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1222 weak_ptr_factory
.GetWeakPtr(),
1223 base::Unretained(&returned_path
)));
1224 RunAllPendingInMessageLoops();
1225 EXPECT_EQ(full_path
, returned_path
);
1228 TEST_F(DownloadItemTest
, StealInterruptedDangerousDownload
) {
1229 CommandLine::ForCurrentProcess()->AppendSwitch(
1230 switches::kEnableDownloadResumption
);
1231 base::FilePath returned_path
;
1232 DownloadItemImpl
* item
= CreateDownloadItem();
1233 MockDownloadFile
* download_file
=
1234 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1235 base::FilePath full_path
= item
->GetFullPath();
1236 EXPECT_FALSE(full_path
.empty());
1237 EXPECT_CALL(*download_file
, FullPath())
1238 .WillOnce(Return(full_path
));
1239 EXPECT_CALL(*download_file
, Detach());
1240 item
->DestinationObserverAsWeakPtr()->DestinationError(
1241 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
);
1242 ASSERT_TRUE(item
->IsDangerous());
1244 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1245 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1246 item
->StealDangerousDownload(
1247 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1248 weak_ptr_factory
.GetWeakPtr(),
1249 base::Unretained(&returned_path
)));
1250 RunAllPendingInMessageLoops();
1251 EXPECT_EQ(full_path
, returned_path
);
1254 TEST_F(DownloadItemTest
, StealInterruptedNonResumableDangerousDownload
) {
1255 CommandLine::ForCurrentProcess()->AppendSwitch(
1256 switches::kEnableDownloadResumption
);
1257 base::FilePath returned_path
;
1258 DownloadItemImpl
* item
= CreateDownloadItem();
1259 MockDownloadFile
* download_file
=
1260 DoIntermediateRename(item
, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
);
1261 EXPECT_CALL(*download_file
, Cancel());
1262 item
->DestinationObserverAsWeakPtr()->DestinationError(
1263 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
);
1264 ASSERT_TRUE(item
->IsDangerous());
1266 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_
));
1267 base::WeakPtrFactory
<DownloadItemTest
> weak_ptr_factory(this);
1268 item
->StealDangerousDownload(
1269 base::Bind(&DownloadItemTest::OnDownloadFileAcquired
,
1270 weak_ptr_factory
.GetWeakPtr(),
1271 base::Unretained(&returned_path
)));
1272 RunAllPendingInMessageLoops();
1273 EXPECT_TRUE(returned_path
.empty());
1276 TEST(MockDownloadItem
, Compiles
) {
1277 MockDownloadItem mock_item
;
1280 } // namespace content