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