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
DownloadManagerTest()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
~DownloadManagerTest()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
AddDownloadToFileManager(int id,DownloadFile * download_file)52 void AddDownloadToFileManager(int id, DownloadFile* download_file) {
53 file_manager()->downloads_[id] = download_file;
54 }
55
OnAllDataSaved(int32 download_id,int64 size,const std::string & hash)56 void OnAllDataSaved(int32 download_id, int64 size, const std::string& hash) {
57 download_manager_->OnAllDataSaved(download_id, size, hash);
58 }
59
FileSelected(const FilePath & path,int index,void * params)60 void FileSelected(const FilePath& path, int index, void* params) {
61 download_manager_->FileSelected(path, index, params);
62 }
63
AttachDownloadItem(DownloadCreateInfo * info)64 void AttachDownloadItem(DownloadCreateInfo* info) {
65 download_manager_->AttachDownloadItem(info);
66 }
67
OnDownloadError(int32 download_id,int64 size,int os_error)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|.
GetActiveDownloadItem(int32 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
file_manager()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|.
VerifySafetyState(bool is_dangerous_file,bool is_dangerous_url,int id)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:
MockDownloadFile(DownloadCreateInfo * info,DownloadManager * manager)202 MockDownloadFile(DownloadCreateInfo* info, DownloadManager* manager)
203 : DownloadFile(info, manager), renamed_count_(0) { }
~MockDownloadFile()204 virtual ~MockDownloadFile() { Destructed(); }
205 MOCK_METHOD1(Rename, bool(const FilePath&));
206 MOCK_METHOD0(Destructed, void());
207
TestMultipleRename(int expected_count,const FilePath & expected,const FilePath & path)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:
SelectFileObserver(DownloadManager * download_manager)225 explicit SelectFileObserver(DownloadManager* download_manager)
226 : download_manager_(download_manager) {
227 DCHECK(download_manager_.get());
228 download_manager_->AddObserver(this);
229 }
230
~SelectFileObserver()231 ~SelectFileObserver() {
232 download_manager_->RemoveObserver(this);
233 }
234
235 // Downloadmanager::Observer functions.
ModelChanged()236 virtual void ModelChanged() {}
ManagerGoingDown()237 virtual void ManagerGoingDown() {}
SelectFileDialogDisplayed(int32 id)238 virtual void SelectFileDialogDisplayed(int32 id) {
239 file_dialog_ids_.insert(id);
240 }
241
ShowedFileDialogForId(int32 id)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:
ItemObserver(DownloadItem * tracked)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 }
~ItemObserver()262 ~ItemObserver() {
263 tracked_->RemoveObserver(this);
264 }
265
hit_state(int state) const266 bool hit_state(int state) const {
267 return (1 << state) & states_hit_;
268 }
was_updated() const269 bool was_updated() const { return was_updated_; }
was_opened() const270 bool was_opened() const { return was_opened_; }
271
272 private:
273 // DownloadItem::Observer methods
OnDownloadUpdated(DownloadItem * download)274 virtual void OnDownloadUpdated(DownloadItem* download) {
275 DCHECK_EQ(tracked_, download);
276 states_hit_ |= (1 << download->state());
277 was_updated_ = true;
278 }
OnDownloadOpened(DownloadItem * download)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
TEST_F(DownloadManagerTest,StartDownload)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
TEST_F(DownloadManagerTest,DownloadRenameTest)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
TEST_F(DownloadManagerTest,DownloadInterruptTest)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
TEST_F(DownloadManagerTest,DownloadCancelTest)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
TEST_F(DownloadManagerTest,DownloadOverwriteTest)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