Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / download / download_item_impl_unittest.cc
blob786d90311049b1fac20367975848dbc48aed379b
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/callback.h"
6 #include "base/command_line.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/stl_util.h"
9 #include "base/threading/thread.h"
10 #include "content/browser/byte_stream.h"
11 #include "content/browser/download/download_create_info.h"
12 #include "content/browser/download/download_file_factory.h"
13 #include "content/browser/download/download_item_impl.h"
14 #include "content/browser/download/download_item_impl_delegate.h"
15 #include "content/browser/download/download_request_handle.h"
16 #include "content/browser/download/mock_download_file.h"
17 #include "content/public/browser/download_destination_observer.h"
18 #include "content/public/browser/download_interrupt_reasons.h"
19 #include "content/public/browser/download_url_parameters.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/test/mock_download_item.h"
22 #include "content/public/test/test_browser_thread.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using ::testing::_;
27 using ::testing::NiceMock;
28 using ::testing::Property;
29 using ::testing::Return;
30 using ::testing::SaveArg;
31 using ::testing::StrictMock;
33 const int kDownloadChunkSize = 1000;
34 const int kDownloadSpeed = 1000;
35 const base::FilePath::CharType kDummyPath[] = FILE_PATH_LITERAL("/testpath");
37 namespace content {
39 namespace {
41 class MockDelegate : public DownloadItemImplDelegate {
42 public:
43 MockDelegate() : DownloadItemImplDelegate() {
44 SetDefaultExpectations();
47 MOCK_METHOD2(DetermineDownloadTarget, void(
48 DownloadItemImpl*, const DownloadTargetCallback&));
49 MOCK_METHOD2(ShouldCompleteDownload,
50 bool(DownloadItemImpl*, const base::Closure&));
51 MOCK_METHOD2(ShouldOpenDownload,
52 bool(DownloadItemImpl*, const ShouldOpenDownloadCallback&));
53 MOCK_METHOD1(ShouldOpenFileBasedOnExtension, bool(const base::FilePath&));
54 MOCK_METHOD1(CheckForFileRemoval, void(DownloadItemImpl*));
56 void ResumeInterruptedDownload(
57 scoped_ptr<DownloadUrlParameters> params, uint32 id) override {
58 MockResumeInterruptedDownload(params.get(), id);
60 MOCK_METHOD2(MockResumeInterruptedDownload,
61 void(DownloadUrlParameters* params, uint32 id));
63 MOCK_CONST_METHOD0(GetBrowserContext, BrowserContext*());
64 MOCK_METHOD1(UpdatePersistence, void(DownloadItemImpl*));
65 MOCK_METHOD1(DownloadOpened, void(DownloadItemImpl*));
66 MOCK_METHOD1(DownloadRemoved, void(DownloadItemImpl*));
67 MOCK_CONST_METHOD1(AssertStateConsistent, void(DownloadItemImpl*));
69 void VerifyAndClearExpectations() {
70 ::testing::Mock::VerifyAndClearExpectations(this);
71 SetDefaultExpectations();
74 private:
75 void SetDefaultExpectations() {
76 EXPECT_CALL(*this, AssertStateConsistent(_))
77 .WillRepeatedly(Return());
78 EXPECT_CALL(*this, ShouldOpenFileBasedOnExtension(_))
79 .WillRepeatedly(Return(false));
80 EXPECT_CALL(*this, ShouldOpenDownload(_, _))
81 .WillRepeatedly(Return(true));
85 class MockRequestHandle : public DownloadRequestHandleInterface {
86 public:
87 MOCK_CONST_METHOD0(GetWebContents, WebContents*());
88 MOCK_CONST_METHOD0(GetDownloadManager, DownloadManager*());
89 MOCK_CONST_METHOD0(PauseRequest, void());
90 MOCK_CONST_METHOD0(ResumeRequest, void());
91 MOCK_CONST_METHOD0(CancelRequest, void());
92 MOCK_CONST_METHOD0(DebugString, std::string());
95 // Schedules a task to invoke the RenameCompletionCallback with |new_path| on
96 // the UI thread. Should only be used as the action for
97 // MockDownloadFile::Rename as follows:
98 // EXPECT_CALL(download_file, Rename*(_,_))
99 // .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
100 // new_path));
101 ACTION_P2(ScheduleRenameCallback, interrupt_reason, new_path) {
102 BrowserThread::PostTask(
103 BrowserThread::UI, FROM_HERE,
104 base::Bind(arg1, interrupt_reason, new_path));
107 } // namespace
109 class DownloadItemTest : public testing::Test {
110 public:
111 class MockObserver : public DownloadItem::Observer {
112 public:
113 explicit MockObserver(DownloadItem* item)
114 : item_(item),
115 last_state_(item->GetState()),
116 removed_(false),
117 destroyed_(false),
118 updated_(false),
119 interrupt_count_(0),
120 resume_count_(0) {
121 item_->AddObserver(this);
124 ~MockObserver() override {
125 if (item_) item_->RemoveObserver(this);
128 void OnDownloadRemoved(DownloadItem* download) override {
129 DVLOG(20) << " " << __FUNCTION__
130 << " download = " << download->DebugString(false);
131 removed_ = true;
134 void OnDownloadUpdated(DownloadItem* download) override {
135 DVLOG(20) << " " << __FUNCTION__
136 << " download = " << download->DebugString(false);
137 updated_ = true;
138 DownloadItem::DownloadState new_state = download->GetState();
139 if (last_state_ == DownloadItem::IN_PROGRESS &&
140 new_state == DownloadItem::INTERRUPTED) {
141 interrupt_count_++;
143 if (last_state_ == DownloadItem::INTERRUPTED &&
144 new_state == DownloadItem::IN_PROGRESS) {
145 resume_count_++;
147 last_state_ = new_state;
150 void OnDownloadOpened(DownloadItem* download) override {
151 DVLOG(20) << " " << __FUNCTION__
152 << " download = " << download->DebugString(false);
155 void OnDownloadDestroyed(DownloadItem* download) override {
156 DVLOG(20) << " " << __FUNCTION__
157 << " download = " << download->DebugString(false);
158 destroyed_ = true;
159 item_->RemoveObserver(this);
160 item_ = NULL;
163 bool CheckRemoved() {
164 return removed_;
167 bool CheckDestroyed() {
168 return destroyed_;
171 bool CheckUpdated() {
172 bool was_updated = updated_;
173 updated_ = false;
174 return was_updated;
177 int GetInterruptCount() {
178 return interrupt_count_;
181 int GetResumeCount() {
182 return resume_count_;
185 private:
186 DownloadItem* item_;
187 DownloadItem::DownloadState last_state_;
188 bool removed_;
189 bool destroyed_;
190 bool updated_;
191 int interrupt_count_;
192 int resume_count_;
195 DownloadItemTest()
196 : ui_thread_(BrowserThread::UI, &loop_),
197 file_thread_(BrowserThread::FILE, &loop_),
198 delegate_() {
201 ~DownloadItemTest() {
204 virtual void SetUp() {
207 virtual void TearDown() {
208 ui_thread_.DeprecatedGetThreadObject()->message_loop()->RunUntilIdle();
209 STLDeleteElements(&allocated_downloads_);
212 // This class keeps ownership of the created download item; it will
213 // be torn down at the end of the test unless DestroyDownloadItem is
214 // called.
215 DownloadItemImpl* CreateDownloadItem() {
216 // Normally, the download system takes ownership of info, and is
217 // responsible for deleting it. In these unit tests, however, we
218 // don't call the function that deletes it, so we do so ourselves.
219 scoped_ptr<DownloadCreateInfo> info_;
221 info_.reset(new DownloadCreateInfo());
222 static uint32 next_id = DownloadItem::kInvalidId + 1;
223 info_->save_info = scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo());
224 info_->save_info->prompt_for_save_location = false;
225 info_->url_chain.push_back(GURL());
226 info_->etag = "SomethingToSatisfyResumption";
228 DownloadItemImpl* download =
229 new DownloadItemImpl(
230 &delegate_, next_id++, *(info_.get()), net::BoundNetLog());
231 allocated_downloads_.insert(download);
232 return download;
235 // Add DownloadFile to DownloadItem
236 MockDownloadFile* AddDownloadFileToDownloadItem(
237 DownloadItemImpl* item,
238 DownloadItemImplDelegate::DownloadTargetCallback *callback) {
239 MockDownloadFile* mock_download_file(new StrictMock<MockDownloadFile>);
240 scoped_ptr<DownloadFile> download_file(mock_download_file);
241 EXPECT_CALL(*mock_download_file, Initialize(_));
242 if (callback) {
243 // Save the callback.
244 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
245 .WillOnce(SaveArg<1>(callback));
246 } else {
247 // Drop it on the floor.
248 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
251 scoped_ptr<DownloadRequestHandleInterface> request_handle(
252 new NiceMock<MockRequestHandle>);
253 item->Start(download_file.Pass(), request_handle.Pass());
254 loop_.RunUntilIdle();
256 // So that we don't have a function writing to a stack variable
257 // lying around if the above failed.
258 mock_delegate()->VerifyAndClearExpectations();
259 EXPECT_CALL(*mock_delegate(), AssertStateConsistent(_))
260 .WillRepeatedly(Return());
261 EXPECT_CALL(*mock_delegate(), ShouldOpenFileBasedOnExtension(_))
262 .WillRepeatedly(Return(false));
263 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(_, _))
264 .WillRepeatedly(Return(true));
266 return mock_download_file;
269 // Perform the intermediate rename for |item|. The target path for the
270 // download will be set to kDummyPath. Returns the MockDownloadFile* that was
271 // added to the DownloadItem.
272 MockDownloadFile* DoIntermediateRename(DownloadItemImpl* item,
273 DownloadDangerType danger_type) {
274 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
275 EXPECT_TRUE(item->GetTargetFilePath().empty());
276 DownloadItemImplDelegate::DownloadTargetCallback callback;
277 MockDownloadFile* download_file =
278 AddDownloadFileToDownloadItem(item, &callback);
279 base::FilePath target_path(kDummyPath);
280 base::FilePath intermediate_path(
281 target_path.InsertBeforeExtensionASCII("x"));
282 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
283 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
284 intermediate_path));
285 callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
286 danger_type, intermediate_path);
287 RunAllPendingInMessageLoops();
288 return download_file;
291 // Cleanup a download item (specifically get rid of the DownloadFile on it).
292 // The item must be in the expected state.
293 void CleanupItem(DownloadItemImpl* item,
294 MockDownloadFile* download_file,
295 DownloadItem::DownloadState expected_state) {
296 EXPECT_EQ(expected_state, item->GetState());
298 if (expected_state == DownloadItem::IN_PROGRESS) {
299 EXPECT_CALL(*download_file, Cancel());
300 item->Cancel(true);
301 loop_.RunUntilIdle();
305 // Destroy a previously created download item.
306 void DestroyDownloadItem(DownloadItem* item) {
307 allocated_downloads_.erase(item);
308 delete item;
311 void RunAllPendingInMessageLoops() {
312 loop_.RunUntilIdle();
315 MockDelegate* mock_delegate() {
316 return &delegate_;
319 void OnDownloadFileAcquired(base::FilePath* return_path,
320 const base::FilePath& path) {
321 *return_path = path;
324 private:
325 base::MessageLoopForUI loop_;
326 TestBrowserThread ui_thread_; // UI thread
327 TestBrowserThread file_thread_; // FILE thread
328 StrictMock<MockDelegate> delegate_;
329 std::set<DownloadItem*> allocated_downloads_;
332 // Tests to ensure calls that change a DownloadItem generate an update to
333 // observers.
334 // State changing functions not tested:
335 // void OpenDownload();
336 // void ShowDownloadInShell();
337 // void CompleteDelayedDownload();
338 // set_* mutators
340 TEST_F(DownloadItemTest, NotificationAfterUpdate) {
341 DownloadItemImpl* item = CreateDownloadItem();
342 MockObserver observer(item);
344 item->DestinationUpdate(kDownloadChunkSize, kDownloadSpeed, std::string());
345 ASSERT_TRUE(observer.CheckUpdated());
346 EXPECT_EQ(kDownloadSpeed, item->CurrentSpeed());
349 TEST_F(DownloadItemTest, NotificationAfterCancel) {
350 DownloadItemImpl* user_cancel = CreateDownloadItem();
351 MockDownloadFile* download_file =
352 AddDownloadFileToDownloadItem(user_cancel, NULL);
353 EXPECT_CALL(*download_file, Cancel());
354 MockObserver observer1(user_cancel);
356 user_cancel->Cancel(true);
357 ASSERT_TRUE(observer1.CheckUpdated());
359 DownloadItemImpl* system_cancel = CreateDownloadItem();
360 download_file = AddDownloadFileToDownloadItem(system_cancel, NULL);
361 EXPECT_CALL(*download_file, Cancel());
362 MockObserver observer2(system_cancel);
364 system_cancel->Cancel(false);
365 ASSERT_TRUE(observer2.CheckUpdated());
368 TEST_F(DownloadItemTest, NotificationAfterComplete) {
369 DownloadItemImpl* item = CreateDownloadItem();
370 MockObserver observer(item);
372 item->OnAllDataSaved(DownloadItem::kEmptyFileHash);
373 ASSERT_TRUE(observer.CheckUpdated());
375 item->MarkAsComplete();
376 ASSERT_TRUE(observer.CheckUpdated());
379 TEST_F(DownloadItemTest, NotificationAfterDownloadedFileRemoved) {
380 DownloadItemImpl* item = CreateDownloadItem();
381 MockObserver observer(item);
383 item->OnDownloadedFileRemoved();
384 ASSERT_TRUE(observer.CheckUpdated());
387 TEST_F(DownloadItemTest, NotificationAfterInterrupted) {
388 DownloadItemImpl* item = CreateDownloadItem();
389 MockDownloadFile* download_file =
390 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
391 EXPECT_CALL(*download_file, Cancel());
392 MockObserver observer(item);
394 EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_,_))
395 .Times(0);
397 item->DestinationObserverAsWeakPtr()->DestinationError(
398 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
399 ASSERT_TRUE(observer.CheckUpdated());
402 TEST_F(DownloadItemTest, NotificationAfterDestroyed) {
403 DownloadItemImpl* item = CreateDownloadItem();
404 MockObserver observer(item);
406 DestroyDownloadItem(item);
407 ASSERT_TRUE(observer.CheckDestroyed());
410 TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
411 base::CommandLine::ForCurrentProcess()->AppendSwitch(
412 switches::kEnableDownloadResumption);
414 DownloadItemImpl* item = CreateDownloadItem();
415 MockObserver observer(item);
416 DownloadItemImplDelegate::DownloadTargetCallback callback;
417 MockDownloadFile* download_file =
418 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
420 // Interrupt the download, using a continuable interrupt.
421 EXPECT_CALL(*download_file, FullPath())
422 .WillOnce(Return(base::FilePath()));
423 EXPECT_CALL(*download_file, Detach());
424 item->DestinationObserverAsWeakPtr()->DestinationError(
425 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR);
426 ASSERT_TRUE(observer.CheckUpdated());
427 // Should attempt to auto-resume. Because we don't have a mock WebContents,
428 // ResumeInterruptedDownload() will abort early, with another interrupt,
429 // which will be ignored.
430 ASSERT_EQ(1, observer.GetInterruptCount());
431 ASSERT_EQ(0, observer.GetResumeCount());
432 RunAllPendingInMessageLoops();
434 CleanupItem(item, download_file, DownloadItem::INTERRUPTED);
437 // Same as above, but with a non-continuable interrupt.
438 TEST_F(DownloadItemTest, RestartAfterInterrupted) {
439 base::CommandLine::ForCurrentProcess()->AppendSwitch(
440 switches::kEnableDownloadResumption);
442 DownloadItemImpl* item = CreateDownloadItem();
443 MockObserver observer(item);
444 DownloadItemImplDelegate::DownloadTargetCallback callback;
445 MockDownloadFile* download_file =
446 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
448 // Interrupt the download, using a restartable interrupt.
449 EXPECT_CALL(*download_file, Cancel());
450 item->DestinationObserverAsWeakPtr()->DestinationError(
451 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
452 ASSERT_TRUE(observer.CheckUpdated());
453 // Should not try to auto-resume.
454 ASSERT_EQ(1, observer.GetInterruptCount());
455 ASSERT_EQ(0, observer.GetResumeCount());
456 RunAllPendingInMessageLoops();
458 CleanupItem(item, download_file, DownloadItem::INTERRUPTED);
461 // Check we do correct cleanup for RESUME_MODE_INVALID interrupts.
462 TEST_F(DownloadItemTest, UnresumableInterrupt) {
463 base::CommandLine::ForCurrentProcess()->AppendSwitch(
464 switches::kEnableDownloadResumption);
466 DownloadItemImpl* item = CreateDownloadItem();
467 MockObserver observer(item);
468 DownloadItemImplDelegate::DownloadTargetCallback callback;
469 MockDownloadFile* download_file =
470 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
472 // Fail final rename with unresumable reason.
473 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
474 .WillOnce(Return(true));
475 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
476 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED,
477 base::FilePath(kDummyPath)));
478 EXPECT_CALL(*download_file, Cancel());
480 // Complete download to trigger final rename.
481 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
482 RunAllPendingInMessageLoops();
484 ASSERT_TRUE(observer.CheckUpdated());
485 // Should not try to auto-resume.
486 ASSERT_EQ(1, observer.GetInterruptCount());
487 ASSERT_EQ(0, observer.GetResumeCount());
489 CleanupItem(item, download_file, DownloadItem::INTERRUPTED);
492 TEST_F(DownloadItemTest, LimitRestartsAfterInterrupted) {
493 base::CommandLine::ForCurrentProcess()->AppendSwitch(
494 switches::kEnableDownloadResumption);
496 DownloadItemImpl* item = CreateDownloadItem();
497 base::WeakPtr<DownloadDestinationObserver> as_observer(
498 item->DestinationObserverAsWeakPtr());
499 MockObserver observer(item);
500 MockDownloadFile* mock_download_file(NULL);
501 scoped_ptr<DownloadFile> download_file;
502 MockRequestHandle* mock_request_handle(NULL);
503 scoped_ptr<DownloadRequestHandleInterface> request_handle;
504 DownloadItemImplDelegate::DownloadTargetCallback callback;
506 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
507 .WillRepeatedly(SaveArg<1>(&callback));
508 for (int i = 0; i < (DownloadItemImpl::kMaxAutoResumeAttempts + 1); ++i) {
509 DVLOG(20) << "Loop iteration " << i;
511 mock_download_file = new NiceMock<MockDownloadFile>;
512 download_file.reset(mock_download_file);
513 mock_request_handle = new NiceMock<MockRequestHandle>;
514 request_handle.reset(mock_request_handle);
516 ON_CALL(*mock_download_file, FullPath())
517 .WillByDefault(Return(base::FilePath()));
519 // It's too complicated to set up a WebContents instance that would cause
520 // the MockDownloadItemDelegate's ResumeInterruptedDownload() function
521 // to be callled, so we simply verify that GetWebContents() is called.
522 if (i < (DownloadItemImpl::kMaxAutoResumeAttempts - 1)) {
523 EXPECT_CALL(*mock_request_handle, GetWebContents())
524 .WillRepeatedly(Return(static_cast<WebContents*>(NULL)));
527 // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem
528 // to allow for holding onto the request handle.
529 item->Start(download_file.Pass(), request_handle.Pass());
530 RunAllPendingInMessageLoops();
531 if (i == 0) {
532 // Target determination is only done the first time through.
533 base::FilePath target_path(kDummyPath);
534 base::FilePath intermediate_path(
535 target_path.InsertBeforeExtensionASCII("x"));
536 EXPECT_CALL(*mock_download_file, RenameAndUniquify(intermediate_path, _))
537 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
538 intermediate_path));
539 callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
540 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
541 RunAllPendingInMessageLoops();
543 ASSERT_EQ(i, observer.GetResumeCount());
545 // Use a continuable interrupt.
546 item->DestinationObserverAsWeakPtr()->DestinationError(
547 DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR);
549 ASSERT_EQ(i + 1, observer.GetInterruptCount());
550 ::testing::Mock::VerifyAndClearExpectations(mock_download_file);
553 CleanupItem(item, mock_download_file, DownloadItem::INTERRUPTED);
556 TEST_F(DownloadItemTest, NotificationAfterRemove) {
557 DownloadItemImpl* item = CreateDownloadItem();
558 MockDownloadFile* download_file = AddDownloadFileToDownloadItem(item, NULL);
559 EXPECT_CALL(*download_file, Cancel());
560 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
561 MockObserver observer(item);
563 item->Remove();
564 ASSERT_TRUE(observer.CheckUpdated());
565 ASSERT_TRUE(observer.CheckRemoved());
568 TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) {
569 // Setting to NOT_DANGEROUS does not trigger a notification.
570 DownloadItemImpl* safe_item = CreateDownloadItem();
571 MockObserver safe_observer(safe_item);
573 safe_item->OnAllDataSaved(std::string());
574 EXPECT_TRUE(safe_observer.CheckUpdated());
575 safe_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
576 EXPECT_TRUE(safe_observer.CheckUpdated());
578 // Setting to unsafe url or unsafe file should trigger a notification.
579 DownloadItemImpl* unsafeurl_item =
580 CreateDownloadItem();
581 MockObserver unsafeurl_observer(unsafeurl_item);
583 unsafeurl_item->OnAllDataSaved(std::string());
584 EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
585 unsafeurl_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
586 EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
588 unsafeurl_item->ValidateDangerousDownload();
589 EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
591 DownloadItemImpl* unsafefile_item =
592 CreateDownloadItem();
593 MockObserver unsafefile_observer(unsafefile_item);
595 unsafefile_item->OnAllDataSaved(std::string());
596 EXPECT_TRUE(unsafefile_observer.CheckUpdated());
597 unsafefile_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
598 EXPECT_TRUE(unsafefile_observer.CheckUpdated());
600 unsafefile_item->ValidateDangerousDownload();
601 EXPECT_TRUE(unsafefile_observer.CheckUpdated());
604 // DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
605 // DownloadFile::Rename(). Once the rename
606 // completes, DownloadItemImpl receives a notification with the new file
607 // name. Check that observers are updated when the new filename is available and
608 // not before.
609 TEST_F(DownloadItemTest, NotificationAfterOnDownloadTargetDetermined) {
610 DownloadItemImpl* item = CreateDownloadItem();
611 DownloadItemImplDelegate::DownloadTargetCallback callback;
612 MockDownloadFile* download_file =
613 AddDownloadFileToDownloadItem(item, &callback);
614 MockObserver observer(item);
615 base::FilePath target_path(kDummyPath);
616 base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
617 base::FilePath new_intermediate_path(
618 target_path.InsertBeforeExtensionASCII("y"));
619 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
620 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
621 new_intermediate_path));
623 // Currently, a notification would be generated if the danger type is anything
624 // other than NOT_DANGEROUS.
625 callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
626 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
627 EXPECT_FALSE(observer.CheckUpdated());
628 RunAllPendingInMessageLoops();
629 EXPECT_TRUE(observer.CheckUpdated());
630 EXPECT_EQ(new_intermediate_path, item->GetFullPath());
632 CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
635 TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
636 DownloadItemImpl* item = CreateDownloadItem();
637 MockObserver observer(item);
638 MockDownloadFile* mock_download_file(new MockDownloadFile);
639 scoped_ptr<DownloadFile> download_file(mock_download_file);
640 scoped_ptr<DownloadRequestHandleInterface> request_handle(
641 new NiceMock<MockRequestHandle>);
643 EXPECT_CALL(*mock_download_file, Initialize(_));
644 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _));
645 item->Start(download_file.Pass(), request_handle.Pass());
647 item->Pause();
648 ASSERT_TRUE(observer.CheckUpdated());
650 ASSERT_TRUE(item->IsPaused());
652 item->Resume();
653 ASSERT_TRUE(observer.CheckUpdated());
655 RunAllPendingInMessageLoops();
657 CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
660 TEST_F(DownloadItemTest, DisplayName) {
661 DownloadItemImpl* item = CreateDownloadItem();
662 DownloadItemImplDelegate::DownloadTargetCallback callback;
663 MockDownloadFile* download_file =
664 AddDownloadFileToDownloadItem(item, &callback);
665 base::FilePath target_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
666 base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
667 EXPECT_EQ(FILE_PATH_LITERAL(""),
668 item->GetFileNameToReportUser().value());
669 EXPECT_CALL(*download_file, RenameAndUniquify(_, _))
670 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
671 intermediate_path));
672 callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
673 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
674 RunAllPendingInMessageLoops();
675 EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
676 item->GetFileNameToReportUser().value());
677 item->SetDisplayName(base::FilePath(FILE_PATH_LITERAL("new.name")));
678 EXPECT_EQ(FILE_PATH_LITERAL("new.name"),
679 item->GetFileNameToReportUser().value());
680 CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
683 // Test to make sure that Start method calls DF initialize properly.
684 TEST_F(DownloadItemTest, Start) {
685 MockDownloadFile* mock_download_file(new MockDownloadFile);
686 scoped_ptr<DownloadFile> download_file(mock_download_file);
687 DownloadItemImpl* item = CreateDownloadItem();
688 EXPECT_CALL(*mock_download_file, Initialize(_));
689 scoped_ptr<DownloadRequestHandleInterface> request_handle(
690 new NiceMock<MockRequestHandle>);
691 EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
692 item->Start(download_file.Pass(), request_handle.Pass());
693 RunAllPendingInMessageLoops();
695 CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
698 // Test that the delegate is invoked after the download file is renamed.
699 TEST_F(DownloadItemTest, CallbackAfterRename) {
700 DownloadItemImpl* item = CreateDownloadItem();
701 DownloadItemImplDelegate::DownloadTargetCallback callback;
702 MockDownloadFile* download_file =
703 AddDownloadFileToDownloadItem(item, &callback);
704 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
705 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
706 base::FilePath new_intermediate_path(
707 final_path.InsertBeforeExtensionASCII("y"));
708 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
709 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
710 new_intermediate_path));
712 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
713 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
714 RunAllPendingInMessageLoops();
715 // All the callbacks should have happened by now.
716 ::testing::Mock::VerifyAndClearExpectations(download_file);
717 mock_delegate()->VerifyAndClearExpectations();
719 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
720 .WillOnce(Return(true));
721 EXPECT_CALL(*download_file, RenameAndAnnotate(final_path, _))
722 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
723 final_path));
724 EXPECT_CALL(*download_file, FullPath())
725 .WillOnce(Return(base::FilePath()));
726 EXPECT_CALL(*download_file, Detach());
727 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
728 RunAllPendingInMessageLoops();
729 ::testing::Mock::VerifyAndClearExpectations(download_file);
730 mock_delegate()->VerifyAndClearExpectations();
733 // Test that the delegate is invoked after the download file is renamed and the
734 // download item is in an interrupted state.
735 TEST_F(DownloadItemTest, CallbackAfterInterruptedRename) {
736 DownloadItemImpl* item = CreateDownloadItem();
737 DownloadItemImplDelegate::DownloadTargetCallback callback;
738 MockDownloadFile* download_file =
739 AddDownloadFileToDownloadItem(item, &callback);
740 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
741 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
742 base::FilePath new_intermediate_path(
743 final_path.InsertBeforeExtensionASCII("y"));
744 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
745 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
746 new_intermediate_path));
747 EXPECT_CALL(*download_file, Cancel())
748 .Times(1);
750 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
751 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
752 RunAllPendingInMessageLoops();
753 // All the callbacks should have happened by now.
754 ::testing::Mock::VerifyAndClearExpectations(download_file);
755 mock_delegate()->VerifyAndClearExpectations();
758 TEST_F(DownloadItemTest, Interrupted) {
759 DownloadItemImpl* item = CreateDownloadItem();
760 MockDownloadFile* download_file =
761 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
763 const DownloadInterruptReason reason(
764 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
766 // Confirm interrupt sets state properly.
767 EXPECT_CALL(*download_file, Cancel());
768 item->DestinationObserverAsWeakPtr()->DestinationError(reason);
769 RunAllPendingInMessageLoops();
770 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
771 EXPECT_EQ(reason, item->GetLastReason());
773 // Cancel should kill it.
774 item->Cancel(true);
775 EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
776 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED, item->GetLastReason());
779 // Destination errors that occur before the intermediate rename shouldn't cause
780 // the download to be marked as interrupted until after the intermediate rename.
781 TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) {
782 DownloadItemImpl* item = CreateDownloadItem();
783 DownloadItemImplDelegate::DownloadTargetCallback callback;
784 MockDownloadFile* download_file =
785 AddDownloadFileToDownloadItem(item, &callback);
786 item->DestinationObserverAsWeakPtr()->DestinationError(
787 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
788 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
790 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
791 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
792 base::FilePath new_intermediate_path(
793 final_path.InsertBeforeExtensionASCII("y"));
794 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
795 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
796 new_intermediate_path));
797 EXPECT_CALL(*download_file, Cancel())
798 .Times(1);
800 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
801 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
802 RunAllPendingInMessageLoops();
803 // All the callbacks should have happened by now.
804 ::testing::Mock::VerifyAndClearExpectations(download_file);
805 mock_delegate()->VerifyAndClearExpectations();
806 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
807 EXPECT_TRUE(item->GetFullPath().empty());
808 EXPECT_EQ(final_path, item->GetTargetFilePath());
811 // As above. But if the download can be resumed by continuing, then the
812 // intermediate path should be retained when the download is interrupted after
813 // the intermediate rename succeeds.
814 TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
815 base::CommandLine::ForCurrentProcess()->AppendSwitch(
816 switches::kEnableDownloadResumption);
817 DownloadItemImpl* item = CreateDownloadItem();
818 DownloadItemImplDelegate::DownloadTargetCallback callback;
819 MockDownloadFile* download_file =
820 AddDownloadFileToDownloadItem(item, &callback);
821 item->DestinationObserverAsWeakPtr()->DestinationError(
822 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
823 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
825 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
826 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
827 base::FilePath new_intermediate_path(
828 final_path.InsertBeforeExtensionASCII("y"));
829 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
830 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
831 new_intermediate_path));
832 EXPECT_CALL(*download_file, FullPath())
833 .WillOnce(Return(base::FilePath(new_intermediate_path)));
834 EXPECT_CALL(*download_file, Detach());
836 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
837 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
838 RunAllPendingInMessageLoops();
839 // All the callbacks should have happened by now.
840 ::testing::Mock::VerifyAndClearExpectations(download_file);
841 mock_delegate()->VerifyAndClearExpectations();
842 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
843 EXPECT_EQ(new_intermediate_path, item->GetFullPath());
844 EXPECT_EQ(final_path, item->GetTargetFilePath());
847 // As above. If the intermediate rename fails, then the interrupt reason should
848 // be set to the destination error and the intermediate path should be empty.
849 TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) {
850 base::CommandLine::ForCurrentProcess()->AppendSwitch(
851 switches::kEnableDownloadResumption);
852 DownloadItemImpl* item = CreateDownloadItem();
853 DownloadItemImplDelegate::DownloadTargetCallback callback;
854 MockDownloadFile* download_file =
855 AddDownloadFileToDownloadItem(item, &callback);
856 item->DestinationObserverAsWeakPtr()->DestinationError(
857 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
858 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
860 base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
861 base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
862 base::FilePath new_intermediate_path(
863 final_path.InsertBeforeExtensionASCII("y"));
864 EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
865 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
866 new_intermediate_path));
867 EXPECT_CALL(*download_file, Cancel())
868 .Times(1);
870 callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
871 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
872 RunAllPendingInMessageLoops();
873 // All the callbacks should have happened by now.
874 ::testing::Mock::VerifyAndClearExpectations(download_file);
875 mock_delegate()->VerifyAndClearExpectations();
876 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
877 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item->GetLastReason());
878 EXPECT_TRUE(item->GetFullPath().empty());
879 EXPECT_EQ(final_path, item->GetTargetFilePath());
882 TEST_F(DownloadItemTest, Canceled) {
883 DownloadItemImpl* item = CreateDownloadItem();
884 MockDownloadFile* download_file = AddDownloadFileToDownloadItem(item, NULL);
886 // Confirm cancel sets state properly.
887 EXPECT_CALL(*download_file, Cancel());
888 item->Cancel(true);
889 EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
892 TEST_F(DownloadItemTest, FileRemoved) {
893 DownloadItemImpl* item = CreateDownloadItem();
895 EXPECT_FALSE(item->GetFileExternallyRemoved());
896 item->OnDownloadedFileRemoved();
897 EXPECT_TRUE(item->GetFileExternallyRemoved());
900 TEST_F(DownloadItemTest, DestinationUpdate) {
901 DownloadItemImpl* item = CreateDownloadItem();
902 base::WeakPtr<DownloadDestinationObserver> as_observer(
903 item->DestinationObserverAsWeakPtr());
904 MockObserver observer(item);
906 EXPECT_EQ(0l, item->CurrentSpeed());
907 EXPECT_EQ("", item->GetHashState());
908 EXPECT_EQ(0l, item->GetReceivedBytes());
909 EXPECT_EQ(0l, item->GetTotalBytes());
910 EXPECT_FALSE(observer.CheckUpdated());
911 item->SetTotalBytes(100l);
912 EXPECT_EQ(100l, item->GetTotalBytes());
914 as_observer->DestinationUpdate(10, 20, "deadbeef");
915 EXPECT_EQ(20l, item->CurrentSpeed());
916 EXPECT_EQ("deadbeef", item->GetHashState());
917 EXPECT_EQ(10l, item->GetReceivedBytes());
918 EXPECT_EQ(100l, item->GetTotalBytes());
919 EXPECT_TRUE(observer.CheckUpdated());
921 as_observer->DestinationUpdate(200, 20, "livebeef");
922 EXPECT_EQ(20l, item->CurrentSpeed());
923 EXPECT_EQ("livebeef", item->GetHashState());
924 EXPECT_EQ(200l, item->GetReceivedBytes());
925 EXPECT_EQ(0l, item->GetTotalBytes());
926 EXPECT_TRUE(observer.CheckUpdated());
929 TEST_F(DownloadItemTest, DestinationError) {
930 DownloadItemImpl* item = CreateDownloadItem();
931 MockDownloadFile* download_file =
932 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
933 base::WeakPtr<DownloadDestinationObserver> as_observer(
934 item->DestinationObserverAsWeakPtr());
935 MockObserver observer(item);
937 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
938 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, item->GetLastReason());
939 EXPECT_FALSE(observer.CheckUpdated());
941 EXPECT_CALL(*download_file, Cancel());
942 as_observer->DestinationError(
943 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
944 mock_delegate()->VerifyAndClearExpectations();
945 EXPECT_TRUE(observer.CheckUpdated());
946 EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
947 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
948 item->GetLastReason());
951 TEST_F(DownloadItemTest, DestinationCompleted) {
952 DownloadItemImpl* item = CreateDownloadItem();
953 base::WeakPtr<DownloadDestinationObserver> as_observer(
954 item->DestinationObserverAsWeakPtr());
955 MockObserver observer(item);
957 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
958 EXPECT_EQ("", item->GetHash());
959 EXPECT_EQ("", item->GetHashState());
960 EXPECT_FALSE(item->AllDataSaved());
961 EXPECT_FALSE(observer.CheckUpdated());
963 as_observer->DestinationUpdate(10, 20, "deadbeef");
964 EXPECT_TRUE(observer.CheckUpdated());
965 EXPECT_FALSE(observer.CheckUpdated()); // Confirm reset.
966 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
967 EXPECT_EQ("", item->GetHash());
968 EXPECT_EQ("deadbeef", item->GetHashState());
969 EXPECT_FALSE(item->AllDataSaved());
971 as_observer->DestinationCompleted("livebeef");
972 mock_delegate()->VerifyAndClearExpectations();
973 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
974 EXPECT_TRUE(observer.CheckUpdated());
975 EXPECT_EQ("livebeef", item->GetHash());
976 EXPECT_EQ("", item->GetHashState());
977 EXPECT_TRUE(item->AllDataSaved());
980 TEST_F(DownloadItemTest, EnabledActionsForNormalDownload) {
981 DownloadItemImpl* item = CreateDownloadItem();
982 MockDownloadFile* download_file =
983 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
985 // InProgress
986 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
987 ASSERT_FALSE(item->GetTargetFilePath().empty());
988 EXPECT_TRUE(item->CanShowInFolder());
989 EXPECT_TRUE(item->CanOpenDownload());
991 // Complete
992 EXPECT_CALL(*download_file, RenameAndAnnotate(_, _))
993 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
994 base::FilePath(kDummyPath)));
995 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
996 .WillOnce(Return(true));
997 EXPECT_CALL(*download_file, FullPath())
998 .WillOnce(Return(base::FilePath()));
999 EXPECT_CALL(*download_file, Detach());
1000 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1001 RunAllPendingInMessageLoops();
1003 ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
1004 EXPECT_TRUE(item->CanShowInFolder());
1005 EXPECT_TRUE(item->CanOpenDownload());
1008 TEST_F(DownloadItemTest, EnabledActionsForTemporaryDownload) {
1009 DownloadItemImpl* item = CreateDownloadItem();
1010 MockDownloadFile* download_file =
1011 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1012 item->SetIsTemporary(true);
1014 // InProgress Temporary
1015 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1016 ASSERT_FALSE(item->GetTargetFilePath().empty());
1017 ASSERT_TRUE(item->IsTemporary());
1018 EXPECT_FALSE(item->CanShowInFolder());
1019 EXPECT_FALSE(item->CanOpenDownload());
1021 // Complete Temporary
1022 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1023 .WillOnce(Return(true));
1024 EXPECT_CALL(*download_file, RenameAndAnnotate(_, _))
1025 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1026 base::FilePath(kDummyPath)));
1027 EXPECT_CALL(*download_file, FullPath())
1028 .WillOnce(Return(base::FilePath()));
1029 EXPECT_CALL(*download_file, Detach());
1030 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1031 RunAllPendingInMessageLoops();
1033 ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
1034 EXPECT_FALSE(item->CanShowInFolder());
1035 EXPECT_FALSE(item->CanOpenDownload());
1038 TEST_F(DownloadItemTest, EnabledActionsForInterruptedDownload) {
1039 DownloadItemImpl* item = CreateDownloadItem();
1040 MockDownloadFile* download_file =
1041 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1043 EXPECT_CALL(*download_file, Cancel());
1044 item->DestinationObserverAsWeakPtr()->DestinationError(
1045 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
1046 RunAllPendingInMessageLoops();
1048 ASSERT_EQ(DownloadItem::INTERRUPTED, item->GetState());
1049 ASSERT_FALSE(item->GetTargetFilePath().empty());
1050 EXPECT_FALSE(item->CanShowInFolder());
1051 EXPECT_FALSE(item->CanOpenDownload());
1054 TEST_F(DownloadItemTest, EnabledActionsForCancelledDownload) {
1055 DownloadItemImpl* item = CreateDownloadItem();
1056 MockDownloadFile* download_file =
1057 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1059 EXPECT_CALL(*download_file, Cancel());
1060 item->Cancel(true);
1061 RunAllPendingInMessageLoops();
1063 ASSERT_EQ(DownloadItem::CANCELLED, item->GetState());
1064 EXPECT_FALSE(item->CanShowInFolder());
1065 EXPECT_FALSE(item->CanOpenDownload());
1068 // Test various aspects of the delegate completion blocker.
1070 // Just allowing completion.
1071 TEST_F(DownloadItemTest, CompleteDelegate_ReturnTrue) {
1072 // Test to confirm that if we have a callback that returns true,
1073 // we complete immediately.
1074 DownloadItemImpl* item = CreateDownloadItem();
1075 MockDownloadFile* download_file =
1076 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1078 // Drive the delegate interaction.
1079 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1080 .WillOnce(Return(true));
1081 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1082 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1083 EXPECT_FALSE(item->IsDangerous());
1085 // Make sure the download can complete.
1086 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1087 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1088 base::FilePath(kDummyPath)));
1089 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1090 .WillOnce(Return(true));
1091 EXPECT_CALL(*download_file, FullPath())
1092 .WillOnce(Return(base::FilePath()));
1093 EXPECT_CALL(*download_file, Detach());
1094 RunAllPendingInMessageLoops();
1095 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1098 // Just delaying completion.
1099 TEST_F(DownloadItemTest, CompleteDelegate_BlockOnce) {
1100 // Test to confirm that if we have a callback that returns true,
1101 // we complete immediately.
1102 DownloadItemImpl* item = CreateDownloadItem();
1103 MockDownloadFile* download_file =
1104 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1106 // Drive the delegate interaction.
1107 base::Closure delegate_callback;
1108 base::Closure copy_delegate_callback;
1109 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1110 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1111 Return(false)))
1112 .WillOnce(Return(true));
1113 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1114 ASSERT_FALSE(delegate_callback.is_null());
1115 copy_delegate_callback = delegate_callback;
1116 delegate_callback.Reset();
1117 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1118 copy_delegate_callback.Run();
1119 ASSERT_TRUE(delegate_callback.is_null());
1120 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1121 EXPECT_FALSE(item->IsDangerous());
1123 // Make sure the download can complete.
1124 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1125 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1126 base::FilePath(kDummyPath)));
1127 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1128 .WillOnce(Return(true));
1129 EXPECT_CALL(*download_file, FullPath())
1130 .WillOnce(Return(base::FilePath()));
1131 EXPECT_CALL(*download_file, Detach());
1132 RunAllPendingInMessageLoops();
1133 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1136 // Delay and set danger.
1137 TEST_F(DownloadItemTest, CompleteDelegate_SetDanger) {
1138 // Test to confirm that if we have a callback that returns true,
1139 // we complete immediately.
1140 DownloadItemImpl* item = CreateDownloadItem();
1141 MockDownloadFile* download_file =
1142 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1144 // Drive the delegate interaction.
1145 base::Closure delegate_callback;
1146 base::Closure copy_delegate_callback;
1147 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1148 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1149 Return(false)))
1150 .WillOnce(Return(true));
1151 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1152 ASSERT_FALSE(delegate_callback.is_null());
1153 copy_delegate_callback = delegate_callback;
1154 delegate_callback.Reset();
1155 EXPECT_FALSE(item->IsDangerous());
1156 item->OnContentCheckCompleted(
1157 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1158 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1159 copy_delegate_callback.Run();
1160 ASSERT_TRUE(delegate_callback.is_null());
1161 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1162 EXPECT_TRUE(item->IsDangerous());
1164 // Make sure the download doesn't complete until we've validated it.
1165 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1166 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1167 base::FilePath(kDummyPath)));
1168 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1169 .WillOnce(Return(true));
1170 EXPECT_CALL(*download_file, FullPath())
1171 .WillOnce(Return(base::FilePath()));
1172 EXPECT_CALL(*download_file, Detach());
1173 RunAllPendingInMessageLoops();
1174 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1175 EXPECT_TRUE(item->IsDangerous());
1177 item->ValidateDangerousDownload();
1178 EXPECT_EQ(DOWNLOAD_DANGER_TYPE_USER_VALIDATED, item->GetDangerType());
1179 RunAllPendingInMessageLoops();
1180 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1183 // Just delaying completion twice.
1184 TEST_F(DownloadItemTest, CompleteDelegate_BlockTwice) {
1185 // Test to confirm that if we have a callback that returns true,
1186 // we complete immediately.
1187 DownloadItemImpl* item = CreateDownloadItem();
1188 MockDownloadFile* download_file =
1189 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
1191 // Drive the delegate interaction.
1192 base::Closure delegate_callback;
1193 base::Closure copy_delegate_callback;
1194 EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
1195 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1196 Return(false)))
1197 .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
1198 Return(false)))
1199 .WillOnce(Return(true));
1200 item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
1201 ASSERT_FALSE(delegate_callback.is_null());
1202 copy_delegate_callback = delegate_callback;
1203 delegate_callback.Reset();
1204 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1205 copy_delegate_callback.Run();
1206 ASSERT_FALSE(delegate_callback.is_null());
1207 copy_delegate_callback = delegate_callback;
1208 delegate_callback.Reset();
1209 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1210 copy_delegate_callback.Run();
1211 ASSERT_TRUE(delegate_callback.is_null());
1212 EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
1213 EXPECT_FALSE(item->IsDangerous());
1215 // Make sure the download can complete.
1216 EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
1217 .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
1218 base::FilePath(kDummyPath)));
1219 EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
1220 .WillOnce(Return(true));
1221 EXPECT_CALL(*download_file, FullPath())
1222 .WillOnce(Return(base::FilePath()));
1223 EXPECT_CALL(*download_file, Detach());
1224 RunAllPendingInMessageLoops();
1225 EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
1228 TEST_F(DownloadItemTest, StealDangerousDownload) {
1229 DownloadItemImpl* item = CreateDownloadItem();
1230 MockDownloadFile* download_file =
1231 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1232 ASSERT_TRUE(item->IsDangerous());
1233 base::FilePath full_path(FILE_PATH_LITERAL("foo.txt"));
1234 base::FilePath returned_path;
1236 EXPECT_CALL(*download_file, FullPath())
1237 .WillOnce(Return(full_path));
1238 EXPECT_CALL(*download_file, Detach());
1239 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
1240 base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
1241 item->StealDangerousDownload(
1242 base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
1243 weak_ptr_factory.GetWeakPtr(),
1244 base::Unretained(&returned_path)));
1245 RunAllPendingInMessageLoops();
1246 EXPECT_EQ(full_path, returned_path);
1249 TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) {
1250 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1251 switches::kEnableDownloadResumption);
1252 base::FilePath returned_path;
1253 DownloadItemImpl* item = CreateDownloadItem();
1254 MockDownloadFile* download_file =
1255 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1256 base::FilePath full_path = item->GetFullPath();
1257 EXPECT_FALSE(full_path.empty());
1258 EXPECT_CALL(*download_file, FullPath())
1259 .WillOnce(Return(full_path));
1260 EXPECT_CALL(*download_file, Detach());
1261 item->DestinationObserverAsWeakPtr()->DestinationError(
1262 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
1263 ASSERT_TRUE(item->IsDangerous());
1265 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
1266 base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
1267 item->StealDangerousDownload(
1268 base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
1269 weak_ptr_factory.GetWeakPtr(),
1270 base::Unretained(&returned_path)));
1271 RunAllPendingInMessageLoops();
1272 EXPECT_EQ(full_path, returned_path);
1275 TEST_F(DownloadItemTest, StealInterruptedNonResumableDangerousDownload) {
1276 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1277 switches::kEnableDownloadResumption);
1278 base::FilePath returned_path;
1279 DownloadItemImpl* item = CreateDownloadItem();
1280 MockDownloadFile* download_file =
1281 DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
1282 EXPECT_CALL(*download_file, Cancel());
1283 item->DestinationObserverAsWeakPtr()->DestinationError(
1284 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
1285 ASSERT_TRUE(item->IsDangerous());
1287 EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
1288 base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
1289 item->StealDangerousDownload(
1290 base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
1291 weak_ptr_factory.GetWeakPtr(),
1292 base::Unretained(&returned_path)));
1293 RunAllPendingInMessageLoops();
1294 EXPECT_TRUE(returned_path.empty());
1297 TEST(MockDownloadItem, Compiles) {
1298 MockDownloadItem mock_item;
1301 } // namespace content