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