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