Home | History | Annotate | Download | only in download
      1 // Copyright (c) 2011 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 <string>
      6 #include <set>
      7 
      8 #include "base/file_util.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/stl_util-inl.h"
     11 #include "base/string_util.h"
     12 #include "build/build_config.h"
     13 #include "chrome/browser/download/download_file.h"
     14 #include "chrome/browser/download/download_file_manager.h"
     15 #include "chrome/browser/download/download_item.h"
     16 #include "chrome/browser/download/download_manager.h"
     17 #include "chrome/browser/download/download_prefs.h"
     18 #include "chrome/browser/download/download_status_updater.h"
     19 #include "chrome/browser/download/download_util.h"
     20 #include "chrome/browser/download/mock_download_manager.h"
     21 #include "chrome/browser/history/download_create_info.h"
     22 #include "chrome/browser/prefs/pref_service.h"
     23 #include "chrome/common/pref_names.h"
     24 #include "chrome/test/testing_profile.h"
     25 #include "content/browser/browser_thread.h"
     26 #include "testing/gmock/include/gmock/gmock.h"
     27 #include "testing/gmock_mutant.h"
     28 #include "testing/gtest/include/gtest/gtest.h"
     29 
     30 class DownloadManagerTest : public testing::Test {
     31  public:
     32   static const char* kTestData;
     33   static const size_t kTestDataLen;
     34 
     35   DownloadManagerTest()
     36       : profile_(new TestingProfile()),
     37         download_manager_(new MockDownloadManager(&download_status_updater_)),
     38         ui_thread_(BrowserThread::UI, &message_loop_),
     39         file_thread_(BrowserThread::FILE, &message_loop_) {
     40     download_manager_->Init(profile_.get());
     41   }
     42 
     43   ~DownloadManagerTest() {
     44     download_manager_->Shutdown();
     45     // profile_ must outlive download_manager_, so we explicitly delete
     46     // download_manager_ first.
     47     download_manager_ = NULL;
     48     profile_.reset(NULL);
     49     message_loop_.RunAllPending();
     50   }
     51 
     52   void AddDownloadToFileManager(int id, DownloadFile* download_file) {
     53     file_manager()->downloads_[id] = download_file;
     54   }
     55 
     56   void OnAllDataSaved(int32 download_id, int64 size, const std::string& hash) {
     57     download_manager_->OnAllDataSaved(download_id, size, hash);
     58   }
     59 
     60   void FileSelected(const FilePath& path, int index, void* params) {
     61     download_manager_->FileSelected(path, index, params);
     62   }
     63 
     64   void AttachDownloadItem(DownloadCreateInfo* info) {
     65     download_manager_->AttachDownloadItem(info);
     66   }
     67 
     68   void OnDownloadError(int32 download_id, int64 size, int os_error) {
     69     download_manager_->OnDownloadError(download_id, size, os_error);
     70   }
     71 
     72   // Get the download item with ID |id|.
     73   DownloadItem* GetActiveDownloadItem(int32 id) {
     74     if (ContainsKey(download_manager_->active_downloads_, id))
     75       return download_manager_->active_downloads_[id];
     76     return NULL;
     77   }
     78 
     79  protected:
     80   DownloadStatusUpdater download_status_updater_;
     81   scoped_ptr<TestingProfile> profile_;
     82   scoped_refptr<DownloadManager> download_manager_;
     83   scoped_refptr<DownloadFileManager> file_manager_;
     84   MessageLoopForUI message_loop_;
     85   BrowserThread ui_thread_;
     86   BrowserThread file_thread_;
     87 
     88   DownloadFileManager* file_manager() {
     89     if (!file_manager_) {
     90       file_manager_ = new DownloadFileManager(NULL);
     91       download_manager_->file_manager_ = file_manager_;
     92     }
     93     return file_manager_;
     94   }
     95 
     96   // Make sure download item |id| was set with correct safety state for
     97   // given |is_dangerous_file| and |is_dangerous_url|.
     98   bool VerifySafetyState(bool is_dangerous_file,
     99                          bool is_dangerous_url,
    100                          int id) {
    101     DownloadItem::SafetyState safety_state =
    102         download_manager_->GetDownloadItem(id)->safety_state();
    103     return (is_dangerous_file || is_dangerous_url) ?
    104         safety_state != DownloadItem::SAFE : safety_state == DownloadItem::SAFE;
    105   }
    106 
    107   DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest);
    108 };
    109 
    110 const char* DownloadManagerTest::kTestData = "a;sdlfalsdfjalsdkfjad";
    111 const size_t DownloadManagerTest::kTestDataLen =
    112     strlen(DownloadManagerTest::kTestData);
    113 
    114 namespace {
    115 
    116 const struct {
    117   const char* url;
    118   const char* mime_type;
    119   bool save_as;
    120   bool prompt_for_download;
    121   bool expected_save_as;
    122 } kStartDownloadCases[] = {
    123   { "http://www.foo.com/dont-open.html",
    124     "text/html",
    125     false,
    126     false,
    127     false, },
    128   { "http://www.foo.com/save-as.html",
    129     "text/html",
    130     true,
    131     false,
    132     true, },
    133   { "http://www.foo.com/always-prompt.html",
    134     "text/html",
    135     false,
    136     true,
    137     true, },
    138   { "http://www.foo.com/user-script-text-html-mimetype.user.js",
    139     "text/html",
    140     false,
    141     false,
    142     false, },
    143   { "http://www.foo.com/extensionless-extension",
    144     "application/x-chrome-extension",
    145     true,
    146     false,
    147     true, },
    148   { "http://www.foo.com/save-as.pdf",
    149     "application/pdf",
    150     true,
    151     false,
    152     true, },
    153   { "http://www.foo.com/sometimes_prompt.pdf",
    154     "application/pdf",
    155     false,
    156     true,
    157     false, },
    158   { "http://www.foo.com/always_prompt.jar",
    159     "application/jar",
    160     false,
    161     true,
    162     true, },
    163 };
    164 
    165 const struct {
    166   FilePath::StringType suggested_path;
    167   bool is_dangerous_file;
    168   bool is_dangerous_url;
    169   bool finish_before_rename;
    170   int expected_rename_count;
    171 } kDownloadRenameCases[] = {
    172   // Safe download, download finishes BEFORE file name determined.
    173   // Renamed twice (linear path through UI).  Crdownload file does not need
    174   // to be deleted.
    175   { FILE_PATH_LITERAL("foo.zip"),
    176     false, false, true, 2, },
    177   // Dangerous download (file is dangerous or download URL is not safe or both),
    178   // download finishes BEFORE file name determined. Needs to be renamed only
    179   // once.
    180   { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
    181     true, false, true, 1, },
    182   { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
    183     false, true, true, 1, },
    184   { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
    185     true, true, true, 1, },
    186   // Safe download, download finishes AFTER file name determined.
    187   // Needs to be renamed twice.
    188   { FILE_PATH_LITERAL("foo.zip"),
    189     false, false, false, 2, },
    190   // Dangerous download, download finishes AFTER file name determined.
    191   // Needs to be renamed only once.
    192   { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
    193     true, false, false, 1, },
    194   { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
    195     false, true, false, 1, },
    196   { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"),
    197     true, true, false, 1, },
    198 };
    199 
    200 class MockDownloadFile : public DownloadFile {
    201  public:
    202   MockDownloadFile(DownloadCreateInfo* info, DownloadManager* manager)
    203       : DownloadFile(info, manager), renamed_count_(0) { }
    204   virtual ~MockDownloadFile() { Destructed(); }
    205   MOCK_METHOD1(Rename, bool(const FilePath&));
    206   MOCK_METHOD0(Destructed, void());
    207 
    208   bool TestMultipleRename(
    209       int expected_count, const FilePath& expected,
    210       const FilePath& path) {
    211     ++renamed_count_;
    212     EXPECT_EQ(expected_count, renamed_count_);
    213     EXPECT_EQ(expected.value(), path.value());
    214     return true;
    215   }
    216 
    217  private:
    218   int renamed_count_;
    219 };
    220 
    221 // This is an observer that records what download IDs have opened a select
    222 // file dialog.
    223 class SelectFileObserver : public DownloadManager::Observer {
    224  public:
    225   explicit SelectFileObserver(DownloadManager* download_manager)
    226       : download_manager_(download_manager) {
    227     DCHECK(download_manager_.get());
    228     download_manager_->AddObserver(this);
    229   }
    230 
    231   ~SelectFileObserver() {
    232     download_manager_->RemoveObserver(this);
    233   }
    234 
    235   // Downloadmanager::Observer functions.
    236   virtual void ModelChanged() {}
    237   virtual void ManagerGoingDown() {}
    238   virtual void SelectFileDialogDisplayed(int32 id) {
    239     file_dialog_ids_.insert(id);
    240   }
    241 
    242   bool ShowedFileDialogForId(int32 id) {
    243     return file_dialog_ids_.find(id) != file_dialog_ids_.end();
    244   }
    245 
    246  private:
    247   std::set<int32> file_dialog_ids_;
    248   scoped_refptr<DownloadManager> download_manager_;
    249 };
    250 
    251 // This observer tracks the progress of |DownloadItem|s.
    252 class ItemObserver : public DownloadItem::Observer {
    253  public:
    254   explicit ItemObserver(DownloadItem* tracked)
    255       : tracked_(tracked), states_hit_(0),
    256         was_updated_(false), was_opened_(false) {
    257     DCHECK(tracked_);
    258     tracked_->AddObserver(this);
    259     // Record the initial state.
    260     OnDownloadUpdated(tracked_);
    261   }
    262   ~ItemObserver() {
    263     tracked_->RemoveObserver(this);
    264   }
    265 
    266   bool hit_state(int state) const {
    267     return (1 << state) & states_hit_;
    268   }
    269   bool was_updated() const { return was_updated_; }
    270   bool was_opened() const { return was_opened_; }
    271 
    272  private:
    273   // DownloadItem::Observer methods
    274   virtual void OnDownloadUpdated(DownloadItem* download) {
    275     DCHECK_EQ(tracked_, download);
    276     states_hit_ |= (1 << download->state());
    277     was_updated_ = true;
    278   }
    279   virtual void OnDownloadOpened(DownloadItem* download) {
    280     DCHECK_EQ(tracked_, download);
    281     states_hit_ |= (1 << download->state());
    282     was_opened_ = true;
    283   }
    284 
    285   DownloadItem* tracked_;
    286   int states_hit_;
    287   bool was_updated_;
    288   bool was_opened_;
    289 };
    290 
    291 }  // namespace
    292 
    293 #if !defined(OS_CHROMEOS)
    294 
    295 TEST_F(DownloadManagerTest, StartDownload) {
    296   BrowserThread io_thread(BrowserThread::IO, &message_loop_);
    297   PrefService* prefs = profile_->GetPrefs();
    298   prefs->SetFilePath(prefs::kDownloadDefaultDirectory, FilePath());
    299   download_manager_->download_prefs()->EnableAutoOpenBasedOnExtension(
    300       FilePath(FILE_PATH_LITERAL("example.pdf")));
    301 
    302   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kStartDownloadCases); ++i) {
    303     prefs->SetBoolean(prefs::kPromptForDownload,
    304                       kStartDownloadCases[i].prompt_for_download);
    305 
    306     SelectFileObserver observer(download_manager_);
    307     DownloadCreateInfo* info = new DownloadCreateInfo;
    308     info->download_id = static_cast<int>(i);
    309     info->prompt_user_for_save_location = kStartDownloadCases[i].save_as;
    310     info->url_chain.push_back(GURL(kStartDownloadCases[i].url));
    311     info->mime_type = kStartDownloadCases[i].mime_type;
    312     download_manager_->CreateDownloadItem(info);
    313 
    314     DownloadFile* download_file(new DownloadFile(info, download_manager_));
    315     AddDownloadToFileManager(info->download_id, download_file);
    316     download_file->Initialize(false);
    317     download_manager_->StartDownload(info);
    318     message_loop_.RunAllPending();
    319 
    320     // NOTE: At this point, |AttachDownloadItem| will have been run if we don't
    321     // need to prompt the user, so |info| could have been destructed.
    322     // This means that we can't check any of its values.
    323     // However, SelectFileObserver will have recorded any attempt to open the
    324     // select file dialog.
    325     EXPECT_EQ(kStartDownloadCases[i].expected_save_as,
    326               observer.ShowedFileDialogForId(i));
    327 
    328     // If the Save As dialog pops up, it never reached
    329     // DownloadManager::AttachDownloadItem(), and never deleted info or
    330     // completed.  This cleans up info.
    331     // Note that DownloadManager::FileSelectionCanceled() is never called.
    332     if (observer.ShowedFileDialogForId(i)) {
    333       delete info;
    334     }
    335   }
    336 }
    337 
    338 #endif // !defined(OS_CHROMEOS)
    339 
    340 TEST_F(DownloadManagerTest, DownloadRenameTest) {
    341   using ::testing::_;
    342   using ::testing::CreateFunctor;
    343   using ::testing::Invoke;
    344   using ::testing::Return;
    345 
    346   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadRenameCases); ++i) {
    347     // |info| will be destroyed in download_manager_.
    348     DownloadCreateInfo* info(new DownloadCreateInfo);
    349     info->download_id = static_cast<int>(i);
    350     info->prompt_user_for_save_location = false;
    351     info->url_chain.push_back(GURL());
    352     info->is_dangerous_file = kDownloadRenameCases[i].is_dangerous_file;
    353     info->is_dangerous_url = kDownloadRenameCases[i].is_dangerous_url;
    354     FilePath new_path(kDownloadRenameCases[i].suggested_path);
    355 
    356     MockDownloadFile* download_file(
    357         new MockDownloadFile(info, download_manager_));
    358     AddDownloadToFileManager(info->download_id, download_file);
    359 
    360     // |download_file| is owned by DownloadFileManager.
    361     ::testing::Mock::AllowLeak(download_file);
    362     EXPECT_CALL(*download_file, Destructed()).Times(1);
    363 
    364     if (kDownloadRenameCases[i].expected_rename_count == 1) {
    365       EXPECT_CALL(*download_file, Rename(new_path)).WillOnce(Return(true));
    366     } else {
    367       ASSERT_EQ(2, kDownloadRenameCases[i].expected_rename_count);
    368       FilePath crdownload(download_util::GetCrDownloadPath(new_path));
    369       EXPECT_CALL(*download_file, Rename(_))
    370           .WillOnce(testing::WithArgs<0>(Invoke(CreateFunctor(
    371               download_file, &MockDownloadFile::TestMultipleRename,
    372               1, crdownload))))
    373           .WillOnce(testing::WithArgs<0>(Invoke(CreateFunctor(
    374               download_file, &MockDownloadFile::TestMultipleRename,
    375               2, new_path))));
    376     }
    377     download_manager_->CreateDownloadItem(info);
    378 
    379     if (kDownloadRenameCases[i].finish_before_rename) {
    380       OnAllDataSaved(i, 1024, std::string("fake_hash"));
    381       message_loop_.RunAllPending();
    382       FileSelected(new_path, i, info);
    383     } else {
    384       FileSelected(new_path, i, info);
    385       message_loop_.RunAllPending();
    386       OnAllDataSaved(i, 1024, std::string("fake_hash"));
    387     }
    388 
    389     message_loop_.RunAllPending();
    390     EXPECT_TRUE(VerifySafetyState(kDownloadRenameCases[i].is_dangerous_file,
    391                                   kDownloadRenameCases[i].is_dangerous_url,
    392                                   i));
    393   }
    394 }
    395 
    396 TEST_F(DownloadManagerTest, DownloadInterruptTest) {
    397   using ::testing::_;
    398   using ::testing::CreateFunctor;
    399   using ::testing::Invoke;
    400   using ::testing::Return;
    401 
    402   // |info| will be destroyed in download_manager_.
    403   DownloadCreateInfo* info(new DownloadCreateInfo);
    404   info->download_id = static_cast<int>(0);
    405   info->prompt_user_for_save_location = false;
    406   info->url_chain.push_back(GURL());
    407   info->is_dangerous_file = false;
    408   info->is_dangerous_url = false;
    409   const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
    410   const FilePath cr_path(download_util::GetCrDownloadPath(new_path));
    411 
    412   MockDownloadFile* download_file(
    413       new MockDownloadFile(info, download_manager_));
    414   AddDownloadToFileManager(info->download_id, download_file);
    415 
    416   // |download_file| is owned by DownloadFileManager.
    417   ::testing::Mock::AllowLeak(download_file);
    418   EXPECT_CALL(*download_file, Destructed()).Times(1);
    419 
    420   EXPECT_CALL(*download_file, Rename(cr_path)).WillOnce(Return(true));
    421 
    422   download_manager_->CreateDownloadItem(info);
    423 
    424   DownloadItem* download = GetActiveDownloadItem(0);
    425   ASSERT_TRUE(download != NULL);
    426 
    427   EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
    428   scoped_ptr<ItemObserver> observer(new ItemObserver(download));
    429 
    430   download_file->AppendDataToFile(kTestData, kTestDataLen);
    431 
    432   info->path = new_path;
    433   AttachDownloadItem(info);
    434   message_loop_.RunAllPending();
    435   EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
    436 
    437   OnDownloadError(0, 1024, -6);
    438   message_loop_.RunAllPending();
    439 
    440   EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
    441   EXPECT_EQ(DownloadItem::INTERRUPTED, download->state());
    442   EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
    443   EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
    444   EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
    445   EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
    446   EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
    447   EXPECT_TRUE(observer->was_updated());
    448   EXPECT_FALSE(observer->was_opened());
    449 
    450   download->Cancel(true);
    451 
    452   EXPECT_EQ(DownloadItem::INTERRUPTED, download->state());
    453   EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
    454   EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
    455   EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
    456   EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
    457   EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
    458   EXPECT_TRUE(observer->was_updated());
    459   EXPECT_FALSE(observer->was_opened());
    460 }
    461 
    462 TEST_F(DownloadManagerTest, DownloadCancelTest) {
    463   using ::testing::_;
    464   using ::testing::CreateFunctor;
    465   using ::testing::Invoke;
    466   using ::testing::Return;
    467 
    468   // |info| will be destroyed in download_manager_.
    469   DownloadCreateInfo* info(new DownloadCreateInfo);
    470   info->download_id = static_cast<int>(0);
    471   info->prompt_user_for_save_location = false;
    472   info->url_chain.push_back(GURL());
    473   info->is_dangerous_file = false;
    474   info->is_dangerous_url = false;
    475   const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
    476   const FilePath cr_path(download_util::GetCrDownloadPath(new_path));
    477 
    478   MockDownloadFile* download_file(
    479       new MockDownloadFile(info, download_manager_));
    480   AddDownloadToFileManager(info->download_id, download_file);
    481 
    482   // |download_file| is owned by DownloadFileManager.
    483   ::testing::Mock::AllowLeak(download_file);
    484   EXPECT_CALL(*download_file, Destructed()).Times(1);
    485 
    486   EXPECT_CALL(*download_file, Rename(cr_path)).WillOnce(Return(true));
    487 
    488   download_manager_->CreateDownloadItem(info);
    489 
    490   DownloadItem* download = GetActiveDownloadItem(0);
    491   ASSERT_TRUE(download != NULL);
    492 
    493   EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
    494   scoped_ptr<ItemObserver> observer(new ItemObserver(download));
    495 
    496   info->path = new_path;
    497   AttachDownloadItem(info);
    498   message_loop_.RunAllPending();
    499   EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
    500 
    501   download_file->AppendDataToFile(kTestData, kTestDataLen);
    502 
    503   download->Cancel(false);
    504   message_loop_.RunAllPending();
    505 
    506   EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
    507   EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
    508   EXPECT_TRUE(observer->hit_state(DownloadItem::CANCELLED));
    509   EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
    510   EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
    511   EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
    512   EXPECT_TRUE(observer->was_updated());
    513   EXPECT_FALSE(observer->was_opened());
    514 
    515   EXPECT_FALSE(file_util::PathExists(new_path));
    516   EXPECT_FALSE(file_util::PathExists(cr_path));
    517 }
    518 
    519 TEST_F(DownloadManagerTest, DownloadOverwriteTest) {
    520   using ::testing::_;
    521   using ::testing::CreateFunctor;
    522   using ::testing::Invoke;
    523   using ::testing::Return;
    524 
    525   // Create a temporary directory.
    526   ScopedTempDir temp_dir_;
    527   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    528 
    529   // File names we're using.
    530   const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt"));
    531   const FilePath cr_path(download_util::GetCrDownloadPath(new_path));
    532   EXPECT_FALSE(file_util::PathExists(new_path));
    533 
    534   // Create the file that we will overwrite.  Will be automatically cleaned
    535   // up when temp_dir_ is destroyed.
    536   FILE* fp = file_util::OpenFile(new_path, "w");
    537   file_util::CloseFile(fp);
    538   EXPECT_TRUE(file_util::PathExists(new_path));
    539 
    540   // Construct the unique file name that normally would be created, but
    541   // which we will override.
    542   int uniquifier = download_util::GetUniquePathNumber(new_path);
    543   FilePath unique_new_path = new_path;
    544   EXPECT_NE(0, uniquifier);
    545   download_util::AppendNumberToPath(&unique_new_path, uniquifier);
    546 
    547   // |info| will be destroyed in download_manager_.
    548   DownloadCreateInfo* info(new DownloadCreateInfo);
    549   info->download_id = static_cast<int>(0);
    550   info->prompt_user_for_save_location = true;
    551   info->url_chain.push_back(GURL());
    552   info->is_dangerous_file = false;
    553   info->is_dangerous_url = false;
    554 
    555   download_manager_->CreateDownloadItem(info);
    556 
    557   DownloadItem* download = GetActiveDownloadItem(0);
    558   ASSERT_TRUE(download != NULL);
    559 
    560   EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
    561   scoped_ptr<ItemObserver> observer(new ItemObserver(download));
    562 
    563   // Create and initialize the download file.  We're bypassing the first part
    564   // of the download process and skipping to the part after the final file
    565   // name has been chosen, so we need to initialize the download file
    566   // properly.
    567   DownloadFile* download_file(
    568       new DownloadFile(info, download_manager_));
    569   download_file->Rename(cr_path);
    570   // This creates the .crdownload version of the file.
    571   download_file->Initialize(false);
    572   // |download_file| is owned by DownloadFileManager.
    573   AddDownloadToFileManager(info->download_id, download_file);
    574 
    575   info->path = new_path;
    576   AttachDownloadItem(info);
    577   message_loop_.RunAllPending();
    578   EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
    579 
    580   download_file->AppendDataToFile(kTestData, kTestDataLen);
    581 
    582   // Finish the download.
    583   OnAllDataSaved(0, kTestDataLen, "");
    584   message_loop_.RunAllPending();
    585 
    586   // Download is complete.
    587   EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
    588   EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
    589   EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
    590   EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
    591   EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
    592   EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
    593   EXPECT_TRUE(observer->was_updated());
    594   EXPECT_FALSE(observer->was_opened());
    595   EXPECT_EQ(DownloadItem::COMPLETE, download->state());
    596 
    597   EXPECT_TRUE(file_util::PathExists(new_path));
    598   EXPECT_FALSE(file_util::PathExists(cr_path));
    599   EXPECT_FALSE(file_util::PathExists(unique_new_path));
    600   std::string file_contents;
    601   EXPECT_TRUE(file_util::ReadFileToString(new_path, &file_contents));
    602   EXPECT_EQ(std::string(kTestData), file_contents);
    603 }
    604