Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / download / download_item_impl_unittest.cc
blob86588ba2a2759c7299cc21126d716899464b48df
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"
26 using ::testing::_;
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");
37 namespace content {
39 namespace {
41 class MockDelegate : public DownloadItemImplDelegate {
42 public:
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();
74 private:
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 {
86 public:
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,
100 // new_path));
101 ACTION_P2(ScheduleRenameCallback, interrupt_reason, new_path) {
102 BrowserThread::PostTask(
103 BrowserThread::UI, FROM_HERE,
104 base::Bind(arg1, interrupt_reason, new_path));
107 } // namespace
109 class DownloadItemTest : public testing::Test {
110 public:
111 class MockObserver : public DownloadItem::Observer {
112 public:
113 explicit MockObserver(DownloadItem* item)
114 : item_(item),
115 last_state_(item->GetState()),
116 removed_(false),
117 destroyed_(false),
118 updated_(false),
119 interrupt_count_(0),
120 resume_count_(0) {
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);
131 removed_ = true;
134 virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
135 DVLOG(20) << " " << __FUNCTION__
136 << " download = " << download->DebugString(false);
137 updated_ = true;
138 DownloadItem::DownloadState new_state = download->GetState();
139 if (last_state_ == DownloadItem::IN_PROGRESS &&
140 new_state == DownloadItem::INTERRUPTED) {
141 interrupt_count_++;
143 if (last_state_ == DownloadItem::INTERRUPTED &&
144 new_state == DownloadItem::IN_PROGRESS) {
145 resume_count_++;
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);
158 destroyed_ = true;
159 item_->RemoveObserver(this);
160 item_ = NULL;
163 bool CheckRemoved() {
164 return removed_;
167 bool CheckDestroyed() {
168 return destroyed_;
171 bool CheckUpdated() {
172 bool was_updated = updated_;
173 updated_ = false;
174 return was_updated;
177 int GetInterruptCount() {
178 return interrupt_count_;
181 int GetResumeCount() {
182 return resume_count_;
185 private:
186 DownloadItem* item_;
187 DownloadItem::DownloadState last_state_;
188 bool removed_;
189 bool destroyed_;
190 bool updated_;
191 int interrupt_count_;
192 int resume_count_;
195 DownloadItemTest()
196 : ui_thread_(BrowserThread::UI, &loop_),
197 file_thread_(BrowserThread::FILE, &loop_),
198 delegate_() {
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
215 // called.
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);
233 return 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(_));
243 if (callback) {
244 // Save the callback.
245 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
246 .WillOnce(SaveArg<1>(callback));
247 } else {
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,
285 intermediate_path));
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());
301 item->Cancel(true);
302 loop_.RunUntilIdle();
306 // Destroy a previously created download item.
307 void DestroyDownloadItem(DownloadItem* item) {
308 allocated_downloads_.erase(item);
309 delete item;
312 void RunAllPendingInMessageLoops() {
313 loop_.RunUntilIdle();
316 MockDelegate* mock_delegate() {
317 return &delegate_;
320 void OnDownloadFileAcquired(base::FilePath* return_path,
321 const base::FilePath& path) {
322 *return_path = path;
325 private:
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
334 // observers.
335 // State changing functions not tested:
336 // void OpenDownload();
337 // void ShowDownloadInShell();
338 // void CompleteDelayedDownload();
339 // set_* mutators
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(_,_))
396 .Times(0);
398 item->DestinationObserverAsWeakPtr()->DestinationError(
399 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
400 ASSERT_TRUE(observer.CheckUpdated());
403 TEST_F(DownloadItemTest, NotificationAfterDestroyed) {
404 DownloadItemImpl* item = CreateDownloadItem();
405 MockObserver observer(item);
407 DestroyDownloadItem(item);
408 ASSERT_TRUE(observer.CheckDestroyed());
411 TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
412 base::CommandLine::ForCurrentProcess()->AppendSwitch(
413 switches::kEnableDownloadResumption);
415 DownloadItemImpl* item = CreateDownloadItem();
416 MockObserver observer(item);
417 DownloadItemImplDelegate::DownloadTargetCallback callback;
418 MockDownloadFile* download_file =
419 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
421 // Interrupt the download, using a continuable interrupt.
422 EXPECT_CALL(*download_file, FullPath())
423 .WillOnce(Return(base::FilePath()));
424 EXPECT_CALL(*download_file, Detach());
425 item->DestinationObserverAsWeakPtr()->DestinationError(
426 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR);
427 ASSERT_TRUE(observer.CheckUpdated());
428 // Should attempt to auto-resume. Because we don't have a mock WebContents,
429 // ResumeInterruptedDownload() will abort early, with another interrupt,
430 // which will be ignored.
431 ASSERT_EQ(1, observer.GetInterruptCount());
432 ASSERT_EQ(0, observer.GetResumeCount());
433 RunAllPendingInMessageLoops();
435 CleanupItem(item, download_file, DownloadItem::INTERRUPTED);
438 // Same as above, but with a non-continuable interrupt.
439 TEST_F(DownloadItemTest, RestartAfterInterrupted) {
440 base::CommandLine::ForCurrentProcess()->AppendSwitch(
441 switches::kEnableDownloadResumption);
443 DownloadItemImpl* item = CreateDownloadItem();
444 MockObserver observer(item);
445 DownloadItemImplDelegate::DownloadTargetCallback callback;
446 MockDownloadFile* download_file =
447 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
449 // Interrupt the download, using a restartable interrupt.
450 EXPECT_CALL(*download_file, Cancel());
451 item->DestinationObserverAsWeakPtr()->DestinationError(
452 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
453 ASSERT_TRUE(observer.CheckUpdated());
454 // Should not try to auto-resume.
455 ASSERT_EQ(1, observer.GetInterruptCount());
456 ASSERT_EQ(0, observer.GetResumeCount());
457 RunAllPendingInMessageLoops();
459 CleanupItem(item, download_file, DownloadItem::INTERRUPTED);
462 // Check we do correct cleanup for RESUME_MODE_INVALID interrupts.
463 TEST_F(DownloadItemTest, UnresumableInterrupt) {
464 base::CommandLine::ForCurrentProcess()->AppendSwitch(
465 switches::kEnableDownloadResumption);
467 DownloadItemImpl* item = CreateDownloadItem();
468 MockObserver observer(item);
469 DownloadItemImplDelegate::DownloadTargetCallback callback;
470 MockDownloadFile* download_file =
471 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
473 // Fail final rename with unresumable reason.
474 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
475 .WillOnce(Return(true));
476 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
477 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED,
478 base::FilePath(kDummyPath)));
479 EXPECT_CALL(*download_file, Cancel());
481 // Complete download to trigger final rename.
482 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
483 RunAllPendingInMessageLoops();
485 ASSERT_TRUE(observer.CheckUpdated());
486 // Should not try to auto-resume.
487 ASSERT_EQ(1, observer.GetInterruptCount());
488 ASSERT_EQ(0, observer.GetResumeCount());
490 CleanupItem(item, download_file, DownloadItem::INTERRUPTED);
493 TEST_F(DownloadItemTest, LimitRestartsAfterInterrupted) {
494 base::CommandLine::ForCurrentProcess()->AppendSwitch(
495 switches::kEnableDownloadResumption);
497 DownloadItemImpl* item = CreateDownloadItem();
498 base::WeakPtr<DownloadDestinationObserver> as_observer(
499 item->DestinationObserverAsWeakPtr());
500 MockObserver observer(item);
501 MockDownloadFile* mock_download_file(NULL);
502 scoped_ptr<DownloadFile> download_file;
503 MockRequestHandle* mock_request_handle(NULL);
504 scoped_ptr<DownloadRequestHandleInterface> request_handle;
505 DownloadItemImplDelegate::DownloadTargetCallback callback;
507 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
508 .WillRepeatedly(SaveArg<1>(&callback));
509 for (int i = 0; i < (DownloadItemImpl::kMaxAutoResumeAttempts + 1); ++i) {
510 DVLOG(20) << "Loop iteration " << i;
512 mock_download_file = new NiceMock<MockDownloadFile>;
513 download_file.reset(mock_download_file);
514 mock_request_handle = new NiceMock<MockRequestHandle>;
515 request_handle.reset(mock_request_handle);
517 ON_CALL(*mock_download_file, FullPath())
518 .WillByDefault(Return(base::FilePath()));
520 // It's too complicated to set up a WebContents instance that would cause
521 // the MockDownloadItemDelegate's ResumeInterruptedDownload() function
522 // to be callled, so we simply verify that GetWebContents() is called.
523 if (i < (DownloadItemImpl::kMaxAutoResumeAttempts - 1)) {
524 EXPECT_CALL(*mock_request_handle, GetWebContents())
525 .WillRepeatedly(Return(static_cast<WebContents*>(NULL)));
528 // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem
529 // to allow for holding onto the request handle.
530 item->Start(download_file.Pass(), request_handle.Pass());
531 RunAllPendingInMessageLoops();
532 if (i == 0) {
533 // Target determination is only done the first time through.
534 base::FilePath target_path(kDummyPath);
535 base::FilePath intermediate_path(
536 target_path.InsertBeforeExtensionASCII("x"));
537 EXPECT_CALL(*mock_download_file, RenameAndUniquify(intermediate_path, _))
538 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
539 intermediate_path));
540 callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
541 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
542 RunAllPendingInMessageLoops();
544 ASSERT_EQ(i, observer.GetResumeCount());
546 // Use a continuable interrupt.
547 item->DestinationObserverAsWeakPtr()->DestinationError(
548 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR);
550 ASSERT_EQ(i + 1, observer.GetInterruptCount());
551 ::testing::Mock::VerifyAndClearExpectations(mock_download_file);
554 CleanupItem(item, mock_download_file, DownloadItem::INTERRUPTED);
557 TEST_F(DownloadItemTest, NotificationAfterRemove) {
558 DownloadItemImpl* item = CreateDownloadItem();
559 MockDownloadFile* download_file = AddDownloadFileToDownloadItem(item, NULL);
560 EXPECT_CALL(*download_file, Cancel());
561 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
562 MockObserver observer(item);
564 item->Remove();
565 ASSERT_TRUE(observer.CheckUpdated());
566 ASSERT_TRUE(observer.CheckRemoved());
569 TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) {
570 // Setting to NOT_DANGEROUS does not trigger a notification.
571 DownloadItemImpl* safe_item = CreateDownloadItem();
572 MockObserver safe_observer(safe_item);
574 safe_item->OnAllDataSaved(std::string());
575 EXPECT_TRUE(safe_observer.CheckUpdated());
576 safe_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
577 EXPECT_TRUE(safe_observer.CheckUpdated());
579 // Setting to unsafe url or unsafe file should trigger a notification.
580 DownloadItemImpl* unsafeurl_item =
581 CreateDownloadItem();
582 MockObserver unsafeurl_observer(unsafeurl_item);
584 unsafeurl_item->OnAllDataSaved(std::string());
585 EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
586 unsafeurl_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
587 EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
589 unsafeurl_item->ValidateDangerousDownload();
590 EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
592 DownloadItemImpl* unsafefile_item =
593 CreateDownloadItem();
594 MockObserver unsafefile_observer(unsafefile_item);
596 unsafefile_item->OnAllDataSaved(std::string());
597 EXPECT_TRUE(unsafefile_observer.CheckUpdated());
598 unsafefile_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
599 EXPECT_TRUE(unsafefile_observer.CheckUpdated());
601 unsafefile_item->ValidateDangerousDownload();
602 EXPECT_TRUE(unsafefile_observer.CheckUpdated());
605 // DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
606 // DownloadFile::Rename(). Once the rename
607 // completes, DownloadItemImpl receives a notification with the new file
608 // name. Check that observers are updated when the new filename is available and
609 // not before.
610 TEST_F(DownloadItemTest, NotificationAfterOnDownloadTargetDetermined) {
611 DownloadItemImpl* item = CreateDownloadItem();
612 DownloadItemImplDelegate::DownloadTargetCallback callback;
613 MockDownloadFile* download_file =
614 AddDownloadFileToDownloadItem(item, &callback);
615 MockObserver observer(item);
616 base::FilePath target_path(kDummyPath);
617 base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
618 base::FilePath new_intermediate_path(
619 target_path.InsertBeforeExtensionASCII("y"));
620 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
621 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
622 new_intermediate_path));
624 // Currently, a notification would be generated if the danger type is anything
625 // other than NOT_DANGEROUS.
626 callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
627 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
628 EXPECT_FALSE(observer.CheckUpdated());
629 RunAllPendingInMessageLoops();
630 EXPECT_TRUE(observer.CheckUpdated());
631 EXPECT_EQ(new_intermediate_path, item->GetFullPath());
633 CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
636 TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
637 DownloadItemImpl* item = CreateDownloadItem();
638 MockObserver observer(item);
639 MockDownloadFile* mock_download_file(new MockDownloadFile);
640 scoped_ptr<DownloadFile> download_file(mock_download_file);
641 scoped_ptr<DownloadRequestHandleInterface> request_handle(
642 new NiceMock<MockRequestHandle>);
644 EXPECT_CALL(*mock_download_file, Initialize(_));
645 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _));
646 item->Start(download_file.Pass(), request_handle.Pass());
648 item->Pause();
649 ASSERT_TRUE(observer.CheckUpdated());
651 ASSERT_TRUE(item->IsPaused());
653 item->Resume();
654 ASSERT_TRUE(observer.CheckUpdated());
656 RunAllPendingInMessageLoops();
658 CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
661 TEST_F(DownloadItemTest, DisplayName) {
662 DownloadItemImpl* item = CreateDownloadItem();
663 DownloadItemImplDelegate::DownloadTargetCallback callback;
664 MockDownloadFile* download_file =
665 AddDownloadFileToDownloadItem(item, &callback);
666 base::FilePath target_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
667 base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
668 EXPECT_EQ(FILE_PATH_LITERAL(""),
669 item->GetFileNameToReportUser().value());
670 EXPECT_CALL(*download_file, RenameAndUniquify(_, _))
671 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
672 intermediate_path));
673 callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
674 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
675 RunAllPendingInMessageLoops();
676 EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
677 item->GetFileNameToReportUser().value());
678 item->SetDisplayName(base::FilePath(FILE_PATH_LITERAL("new.name")));
679 EXPECT_EQ(FILE_PATH_LITERAL("new.name"),
680 item->GetFileNameToReportUser().value());
681 CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
684 // Test to make sure that Start method calls DF initialize properly.
685 TEST_F(DownloadItemTest, Start) {
686 MockDownloadFile* mock_download_file(new MockDownloadFile);
687 scoped_ptr<DownloadFile> download_file(mock_download_file);
688 DownloadItemImpl* item = CreateDownloadItem();
689 EXPECT_CALL(*mock_download_file, Initialize(_));
690 scoped_ptr<DownloadRequestHandleInterface> request_handle(
691 new NiceMock<MockRequestHandle>);
692 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
693 item->Start(download_file.Pass(), request_handle.Pass());
694 RunAllPendingInMessageLoops();
696 CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
699 // Test that the delegate is invoked after the download file is renamed.
700 TEST_F(DownloadItemTest, CallbackAfterRename) {
701 DownloadItemImpl* item = CreateDownloadItem();
702 DownloadItemImplDelegate::DownloadTargetCallback callback;
703 MockDownloadFile* download_file =
704 AddDownloadFileToDownloadItem(item, &callback);
705 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
706 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
707 base::FilePath new_intermediate_path(
708 final_path.InsertBeforeExtensionASCII("y"));
709 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
710 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
711 new_intermediate_path));
713 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
714 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
715 RunAllPendingInMessageLoops();
716 // All the callbacks should have happened by now.
717 ::testing::Mock::VerifyAndClearExpectations(download_file);
718 mock_delegate()->VerifyAndClearExpectations();
720 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
721 .WillOnce(Return(true));
722 EXPECT_CALL(*download_file, RenameAndAnnotate(final_path, _))
723 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
724 final_path));
725 EXPECT_CALL(*download_file, FullPath())
726 .WillOnce(Return(base::FilePath()));
727 EXPECT_CALL(*download_file, Detach());
728 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
729 RunAllPendingInMessageLoops();
730 ::testing::Mock::VerifyAndClearExpectations(download_file);
731 mock_delegate()->VerifyAndClearExpectations();
734 // Test that the delegate is invoked after the download file is renamed and the
735 // download item is in an interrupted state.
736 TEST_F(DownloadItemTest, CallbackAfterInterruptedRename) {
737 DownloadItemImpl* item = CreateDownloadItem();
738 DownloadItemImplDelegate::DownloadTargetCallback callback;
739 MockDownloadFile* download_file =
740 AddDownloadFileToDownloadItem(item, &callback);
741 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
742 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
743 base::FilePath new_intermediate_path(
744 final_path.InsertBeforeExtensionASCII("y"));
745 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
746 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
747 new_intermediate_path));
748 EXPECT_CALL(*download_file, Cancel())
749 .Times(1);
751 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
752 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
753 RunAllPendingInMessageLoops();
754 // All the callbacks should have happened by now.
755 ::testing::Mock::VerifyAndClearExpectations(download_file);
756 mock_delegate()->VerifyAndClearExpectations();
759 TEST_F(DownloadItemTest, Interrupted) {
760 DownloadItemImpl* item = CreateDownloadItem();
761 MockDownloadFile* download_file =
762 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
764 const DownloadInterruptReason reason(
765 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
767 // Confirm interrupt sets state properly.
768 EXPECT_CALL(*download_file, Cancel());
769 item->DestinationObserverAsWeakPtr()->DestinationError(reason);
770 RunAllPendingInMessageLoops();
771 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
772 EXPECT_EQ(reason, item->GetLastReason());
774 // Cancel should kill it.
775 item->Cancel(true);
776 EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
777 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED, item->GetLastReason());
780 // Destination errors that occur before the intermediate rename shouldn't cause
781 // the download to be marked as interrupted until after the intermediate rename.
782 TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) {
783 DownloadItemImpl* item = CreateDownloadItem();
784 DownloadItemImplDelegate::DownloadTargetCallback callback;
785 MockDownloadFile* download_file =
786 AddDownloadFileToDownloadItem(item, &callback);
787 item->DestinationObserverAsWeakPtr()->DestinationError(
788 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
789 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
791 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
792 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
793 base::FilePath new_intermediate_path(
794 final_path.InsertBeforeExtensionASCII("y"));
795 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
796 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
797 new_intermediate_path));
798 EXPECT_CALL(*download_file, Cancel())
799 .Times(1);
801 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
802 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
803 RunAllPendingInMessageLoops();
804 // All the callbacks should have happened by now.
805 ::testing::Mock::VerifyAndClearExpectations(download_file);
806 mock_delegate()->VerifyAndClearExpectations();
807 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
808 EXPECT_TRUE(item->GetFullPath().empty());
809 EXPECT_EQ(final_path, item->GetTargetFilePath());
812 // As above. But if the download can be resumed by continuing, then the
813 // intermediate path should be retained when the download is interrupted after
814 // the intermediate rename succeeds.
815 TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
816 base::CommandLine::ForCurrentProcess()->AppendSwitch(
817 switches::kEnableDownloadResumption);
818 DownloadItemImpl* item = CreateDownloadItem();
819 DownloadItemImplDelegate::DownloadTargetCallback callback;
820 MockDownloadFile* download_file =
821 AddDownloadFileToDownloadItem(item, &callback);
822 item->DestinationObserverAsWeakPtr()->DestinationError(
823 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
824 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
826 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
827 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
828 base::FilePath new_intermediate_path(
829 final_path.InsertBeforeExtensionASCII("y"));
830 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
831 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
832 new_intermediate_path));
833 EXPECT_CALL(*download_file, FullPath())
834 .WillOnce(Return(base::FilePath(new_intermediate_path)));
835 EXPECT_CALL(*download_file, Detach());
837 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
838 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
839 RunAllPendingInMessageLoops();
840 // All the callbacks should have happened by now.
841 ::testing::Mock::VerifyAndClearExpectations(download_file);
842 mock_delegate()->VerifyAndClearExpectations();
843 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
844 EXPECT_EQ(new_intermediate_path, item->GetFullPath());
845 EXPECT_EQ(final_path, item->GetTargetFilePath());
848 // As above. If the intermediate rename fails, then the interrupt reason should
849 // be set to the destination error and the intermediate path should be empty.
850 TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) {
851 base::CommandLine::ForCurrentProcess()->AppendSwitch(
852 switches::kEnableDownloadResumption);
853 DownloadItemImpl* item = CreateDownloadItem();
854 DownloadItemImplDelegate::DownloadTargetCallback callback;
855 MockDownloadFile* download_file =
856 AddDownloadFileToDownloadItem(item, &callback);
857 item->DestinationObserverAsWeakPtr()->DestinationError(
858 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
859 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
861 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
862 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
863 base::FilePath new_intermediate_path(
864 final_path.InsertBeforeExtensionASCII("y"));
865 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
866 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
867 new_intermediate_path));
868 EXPECT_CALL(*download_file, Cancel())
869 .Times(1);
871 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
872 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
873 RunAllPendingInMessageLoops();
874 // All the callbacks should have happened by now.
875 ::testing::Mock::VerifyAndClearExpectations(download_file);
876 mock_delegate()->VerifyAndClearExpectations();
877 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
878 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item->GetLastReason());
879 EXPECT_TRUE(item->GetFullPath().empty());
880 EXPECT_EQ(final_path, item->GetTargetFilePath());
883 TEST_F(DownloadItemTest, Canceled) {
884 DownloadItemImpl* item = CreateDownloadItem();
885 MockDownloadFile* download_file = AddDownloadFileToDownloadItem(item, NULL);
887 // Confirm cancel sets state properly.
888 EXPECT_CALL(*download_file, Cancel());
889 item->Cancel(true);
890 EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
893 TEST_F(DownloadItemTest, FileRemoved) {
894 DownloadItemImpl* item = CreateDownloadItem();
896 EXPECT_FALSE(item->GetFileExternallyRemoved());
897 item->OnDownloadedFileRemoved();
898 EXPECT_TRUE(item->GetFileExternallyRemoved());
901 TEST_F(DownloadItemTest, DestinationUpdate) {
902 DownloadItemImpl* item = CreateDownloadItem();
903 base::WeakPtr<DownloadDestinationObserver> as_observer(
904 item->DestinationObserverAsWeakPtr());
905 MockObserver observer(item);
907 EXPECT_EQ(0l, item->CurrentSpeed());
908 EXPECT_EQ("", item->GetHashState());
909 EXPECT_EQ(0l, item->GetReceivedBytes());
910 EXPECT_EQ(0l, item->GetTotalBytes());
911 EXPECT_FALSE(observer.CheckUpdated());
912 item->SetTotalBytes(100l);
913 EXPECT_EQ(100l, item->GetTotalBytes());
915 as_observer->DestinationUpdate(10, 20, "deadbeef");
916 EXPECT_EQ(20l, item->CurrentSpeed());
917 EXPECT_EQ("deadbeef", item->GetHashState());
918 EXPECT_EQ(10l, item->GetReceivedBytes());
919 EXPECT_EQ(100l, item->GetTotalBytes());
920 EXPECT_TRUE(observer.CheckUpdated());
922 as_observer->DestinationUpdate(200, 20, "livebeef");
923 EXPECT_EQ(20l, item->CurrentSpeed());
924 EXPECT_EQ("livebeef", item->GetHashState());
925 EXPECT_EQ(200l, item->GetReceivedBytes());
926 EXPECT_EQ(0l, item->GetTotalBytes());
927 EXPECT_TRUE(observer.CheckUpdated());
930 TEST_F(DownloadItemTest, DestinationError) {
931 DownloadItemImpl* item = CreateDownloadItem();
932 MockDownloadFile* download_file =
933 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
934 base::WeakPtr<DownloadDestinationObserver> as_observer(
935 item->DestinationObserverAsWeakPtr());
936 MockObserver observer(item);
938 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
939 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, item->GetLastReason());
940 EXPECT_FALSE(observer.CheckUpdated());
942 EXPECT_CALL(*download_file, Cancel());
943 as_observer->DestinationError(
944 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
945 mock_delegate()->VerifyAndClearExpectations();
946 EXPECT_TRUE(observer.CheckUpdated());
947 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
948 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
949 item->GetLastReason());
952 TEST_F(DownloadItemTest, DestinationCompleted) {
953 DownloadItemImpl* item = CreateDownloadItem();
954 base::WeakPtr<DownloadDestinationObserver> as_observer(
955 item->DestinationObserverAsWeakPtr());
956 MockObserver observer(item);
958 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
959 EXPECT_EQ("", item->GetHash());
960 EXPECT_EQ("", item->GetHashState());
961 EXPECT_FALSE(item->AllDataSaved());
962 EXPECT_FALSE(observer.CheckUpdated());
964 as_observer->DestinationUpdate(10, 20, "deadbeef");
965 EXPECT_TRUE(observer.CheckUpdated());
966 EXPECT_FALSE(observer.CheckUpdated()); // Confirm reset.
967 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
968 EXPECT_EQ("", item->GetHash());
969 EXPECT_EQ("deadbeef", item->GetHashState());
970 EXPECT_FALSE(item->AllDataSaved());
972 as_observer->DestinationCompleted("livebeef");
973 mock_delegate()->VerifyAndClearExpectations();
974 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
975 EXPECT_TRUE(observer.CheckUpdated());
976 EXPECT_EQ("livebeef", item->GetHash());
977 EXPECT_EQ("", item->GetHashState());
978 EXPECT_TRUE(item->AllDataSaved());
981 TEST_F(DownloadItemTest, EnabledActionsForNormalDownload) {
982 DownloadItemImpl* item = CreateDownloadItem();
983 MockDownloadFile* download_file =
984 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
986 // InProgress
987 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
988 ASSERT_FALSE(item->GetTargetFilePath().empty());
989 EXPECT_TRUE(item->CanShowInFolder());
990 EXPECT_TRUE(item->CanOpenDownload());
992 // Complete
993 EXPECT_CALL(*download_file, RenameAndAnnotate(_, _))
994 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
995 base::FilePath(kDummyPath)));
996 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
997 .WillOnce(Return(true));
998 EXPECT_CALL(*download_file, FullPath())
999 .WillOnce(Return(base::FilePath()));
1000 EXPECT_CALL(*download_file, Detach());
1001 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1002 RunAllPendingInMessageLoops();
1004 ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
1005 EXPECT_TRUE(item->CanShowInFolder());
1006 EXPECT_TRUE(item->CanOpenDownload());
1009 TEST_F(DownloadItemTest, EnabledActionsForTemporaryDownload) {
1010 DownloadItemImpl* item = CreateDownloadItem();
1011 MockDownloadFile* download_file =
1012 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1013 item->SetIsTemporary(true);
1015 // InProgress Temporary
1016 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1017 ASSERT_FALSE(item->GetTargetFilePath().empty());
1018 ASSERT_TRUE(item->IsTemporary());
1019 EXPECT_FALSE(item->CanShowInFolder());
1020 EXPECT_FALSE(item->CanOpenDownload());
1022 // Complete Temporary
1023 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1024 .WillOnce(Return(true));
1025 EXPECT_CALL(*download_file, RenameAndAnnotate(_, _))
1026 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1027 base::FilePath(kDummyPath)));
1028 EXPECT_CALL(*download_file, FullPath())
1029 .WillOnce(Return(base::FilePath()));
1030 EXPECT_CALL(*download_file, Detach());
1031 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1032 RunAllPendingInMessageLoops();
1034 ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
1035 EXPECT_FALSE(item->CanShowInFolder());
1036 EXPECT_FALSE(item->CanOpenDownload());
1039 TEST_F(DownloadItemTest, EnabledActionsForInterruptedDownload) {
1040 DownloadItemImpl* item = CreateDownloadItem();
1041 MockDownloadFile* download_file =
1042 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1044 EXPECT_CALL(*download_file, Cancel());
1045 item->DestinationObserverAsWeakPtr()->DestinationError(
1046 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
1047 RunAllPendingInMessageLoops();
1049 ASSERT_EQ(DownloadItem::INTERRUPTED, item->GetState());
1050 ASSERT_FALSE(item->GetTargetFilePath().empty());
1051 EXPECT_FALSE(item->CanShowInFolder());
1052 EXPECT_FALSE(item->CanOpenDownload());
1055 TEST_F(DownloadItemTest, EnabledActionsForCancelledDownload) {
1056 DownloadItemImpl* item = CreateDownloadItem();
1057 MockDownloadFile* download_file =
1058 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1060 EXPECT_CALL(*download_file, Cancel());
1061 item->Cancel(true);
1062 RunAllPendingInMessageLoops();
1064 ASSERT_EQ(DownloadItem::CANCELLED, item->GetState());
1065 EXPECT_FALSE(item->CanShowInFolder());
1066 EXPECT_FALSE(item->CanOpenDownload());
1069 // Test various aspects of the delegate completion blocker.
1071 // Just allowing completion.
1072 TEST_F(DownloadItemTest, CompleteDelegate_ReturnTrue) {
1073 // Test to confirm that if we have a callback that returns true,
1074 // we complete immediately.
1075 DownloadItemImpl* item = CreateDownloadItem();
1076 MockDownloadFile* download_file =
1077 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1079 // Drive the delegate interaction.
1080 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1081 .WillOnce(Return(true));
1082 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1083 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1084 EXPECT_FALSE(item->IsDangerous());
1086 // Make sure the download can complete.
1087 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1088 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1089 base::FilePath(kDummyPath)));
1090 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1091 .WillOnce(Return(true));
1092 EXPECT_CALL(*download_file, FullPath())
1093 .WillOnce(Return(base::FilePath()));
1094 EXPECT_CALL(*download_file, Detach());
1095 RunAllPendingInMessageLoops();
1096 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1099 // Just delaying completion.
1100 TEST_F(DownloadItemTest, CompleteDelegate_BlockOnce) {
1101 // Test to confirm that if we have a callback that returns true,
1102 // we complete immediately.
1103 DownloadItemImpl* item = CreateDownloadItem();
1104 MockDownloadFile* download_file =
1105 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1107 // Drive the delegate interaction.
1108 base::Closure delegate_callback;
1109 base::Closure copy_delegate_callback;
1110 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1111 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1112 Return(false)))
1113 .WillOnce(Return(true));
1114 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1115 ASSERT_FALSE(delegate_callback.is_null());
1116 copy_delegate_callback = delegate_callback;
1117 delegate_callback.Reset();
1118 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1119 copy_delegate_callback.Run();
1120 ASSERT_TRUE(delegate_callback.is_null());
1121 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1122 EXPECT_FALSE(item->IsDangerous());
1124 // Make sure the download can complete.
1125 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1126 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1127 base::FilePath(kDummyPath)));
1128 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1129 .WillOnce(Return(true));
1130 EXPECT_CALL(*download_file, FullPath())
1131 .WillOnce(Return(base::FilePath()));
1132 EXPECT_CALL(*download_file, Detach());
1133 RunAllPendingInMessageLoops();
1134 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1137 // Delay and set danger.
1138 TEST_F(DownloadItemTest, CompleteDelegate_SetDanger) {
1139 // Test to confirm that if we have a callback that returns true,
1140 // we complete immediately.
1141 DownloadItemImpl* item = CreateDownloadItem();
1142 MockDownloadFile* download_file =
1143 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1145 // Drive the delegate interaction.
1146 base::Closure delegate_callback;
1147 base::Closure copy_delegate_callback;
1148 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1149 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1150 Return(false)))
1151 .WillOnce(Return(true));
1152 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1153 ASSERT_FALSE(delegate_callback.is_null());
1154 copy_delegate_callback = delegate_callback;
1155 delegate_callback.Reset();
1156 EXPECT_FALSE(item->IsDangerous());
1157 item->OnContentCheckCompleted(
1158 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1159 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1160 copy_delegate_callback.Run();
1161 ASSERT_TRUE(delegate_callback.is_null());
1162 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1163 EXPECT_TRUE(item->IsDangerous());
1165 // Make sure the download doesn't complete until we've validated it.
1166 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1167 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1168 base::FilePath(kDummyPath)));
1169 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1170 .WillOnce(Return(true));
1171 EXPECT_CALL(*download_file, FullPath())
1172 .WillOnce(Return(base::FilePath()));
1173 EXPECT_CALL(*download_file, Detach());
1174 RunAllPendingInMessageLoops();
1175 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1176 EXPECT_TRUE(item->IsDangerous());
1178 item->ValidateDangerousDownload();
1179 EXPECT_EQ(DOWNLOAD_DANGER_TYPE_USER_VALIDATED, item->GetDangerType());
1180 RunAllPendingInMessageLoops();
1181 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1184 // Just delaying completion twice.
1185 TEST_F(DownloadItemTest, CompleteDelegate_BlockTwice) {
1186 // Test to confirm that if we have a callback that returns true,
1187 // we complete immediately.
1188 DownloadItemImpl* item = CreateDownloadItem();
1189 MockDownloadFile* download_file =
1190 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1192 // Drive the delegate interaction.
1193 base::Closure delegate_callback;
1194 base::Closure copy_delegate_callback;
1195 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1196 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1197 Return(false)))
1198 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1199 Return(false)))
1200 .WillOnce(Return(true));
1201 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1202 ASSERT_FALSE(delegate_callback.is_null());
1203 copy_delegate_callback = delegate_callback;
1204 delegate_callback.Reset();
1205 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1206 copy_delegate_callback.Run();
1207 ASSERT_FALSE(delegate_callback.is_null());
1208 copy_delegate_callback = delegate_callback;
1209 delegate_callback.Reset();
1210 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1211 copy_delegate_callback.Run();
1212 ASSERT_TRUE(delegate_callback.is_null());
1213 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1214 EXPECT_FALSE(item->IsDangerous());
1216 // Make sure the download can complete.
1217 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1218 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1219 base::FilePath(kDummyPath)));
1220 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1221 .WillOnce(Return(true));
1222 EXPECT_CALL(*download_file, FullPath())
1223 .WillOnce(Return(base::FilePath()));
1224 EXPECT_CALL(*download_file, Detach());
1225 RunAllPendingInMessageLoops();
1226 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1229 TEST_F(DownloadItemTest, StealDangerousDownload) {
1230 DownloadItemImpl* item = CreateDownloadItem();
1231 MockDownloadFile* download_file =
1232 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1233 ASSERT_TRUE(item->IsDangerous());
1234 base::FilePath full_path(FILE_PATH_LITERAL("foo.txt"));
1235 base::FilePath returned_path;
1237 EXPECT_CALL(*download_file, FullPath())
1238 .WillOnce(Return(full_path));
1239 EXPECT_CALL(*download_file, Detach());
1240 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
1241 base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
1242 item->StealDangerousDownload(
1243 base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
1244 weak_ptr_factory.GetWeakPtr(),
1245 base::Unretained(&returned_path)));
1246 RunAllPendingInMessageLoops();
1247 EXPECT_EQ(full_path, returned_path);
1250 TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) {
1251 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1252 switches::kEnableDownloadResumption);
1253 base::FilePath returned_path;
1254 DownloadItemImpl* item = CreateDownloadItem();
1255 MockDownloadFile* download_file =
1256 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1257 base::FilePath full_path = item->GetFullPath();
1258 EXPECT_FALSE(full_path.empty());
1259 EXPECT_CALL(*download_file, FullPath())
1260 .WillOnce(Return(full_path));
1261 EXPECT_CALL(*download_file, Detach());
1262 item->DestinationObserverAsWeakPtr()->DestinationError(
1263 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
1264 ASSERT_TRUE(item->IsDangerous());
1266 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
1267 base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
1268 item->StealDangerousDownload(
1269 base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
1270 weak_ptr_factory.GetWeakPtr(),
1271 base::Unretained(&returned_path)));
1272 RunAllPendingInMessageLoops();
1273 EXPECT_EQ(full_path, returned_path);
1276 TEST_F(DownloadItemTest, StealInterruptedNonResumableDangerousDownload) {
1277 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1278 switches::kEnableDownloadResumption);
1279 base::FilePath returned_path;
1280 DownloadItemImpl* item = CreateDownloadItem();
1281 MockDownloadFile* download_file =
1282 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1283 EXPECT_CALL(*download_file, Cancel());
1284 item->DestinationObserverAsWeakPtr()->DestinationError(
1285 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
1286 ASSERT_TRUE(item->IsDangerous());
1288 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
1289 base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
1290 item->StealDangerousDownload(
1291 base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
1292 weak_ptr_factory.GetWeakPtr(),
1293 base::Unretained(&returned_path)));
1294 RunAllPendingInMessageLoops();
1295 EXPECT_TRUE(returned_path.empty());
1298 TEST(MockDownloadItem, Compiles) {
1299 MockDownloadItem mock_item;
1302 } // namespace content