blob: fef1de5c9f353798378df056c8a7651cd5e1f156 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include <string>
[email protected]f5920322011-03-24 20:34:166#include <set>
initial.commit09911bf2008-07-26 23:55:297
[email protected]a3094072011-10-10 17:14:058#include "base/bind.h"
[email protected]bf68a00b2011-04-07 17:28:269#include "base/file_util.h"
[email protected]9fc114672011-06-15 08:17:4810#include "base/i18n/number_formatting.h"
11#include "base/i18n/rtl.h"
[email protected]3b63f8f42011-03-28 01:54:1512#include "base/memory/scoped_ptr.h"
[email protected]7286e3fc2011-07-19 22:13:2413#include "base/stl_util.h"
[email protected]c2475df2011-09-07 23:52:2214#include "base/string16.h"
[email protected]eda58402011-09-21 19:32:0215#include "base/string_util.h"
[email protected]9fc114672011-06-15 08:17:4816#include "base/utf_string_conversions.h"
[email protected]047a03f2009-10-07 02:10:2017#include "build/build_config.h"
[email protected]aa9881c2011-08-15 18:01:1218#include "chrome/browser/download/chrome_download_manager_delegate.h"
[email protected]9fc114672011-06-15 08:17:4819#include "chrome/browser/download/download_item_model.h"
[email protected]e5dc4222010-08-30 22:16:3220#include "chrome/browser/download/download_prefs.h"
[email protected]594cd7d2010-07-21 03:23:5621#include "chrome/browser/download/download_util.h"
[email protected]37858e52010-08-26 00:22:0222#include "chrome/browser/prefs/pref_service.h"
[email protected]2941c2392010-07-15 22:54:3023#include "chrome/common/pref_names.h"
[email protected]a4ff9eae2011-08-01 19:58:1624#include "chrome/test/base/testing_profile.h"
[email protected]1bda97552011-03-01 20:11:5225#include "content/browser/browser_thread.h"
[email protected]2606e5a92011-10-21 00:09:5226#include "content/browser/download/download_buffer.h"
[email protected]71bf3f5e2011-08-15 21:05:2227#include "content/browser/download/download_create_info.h"
28#include "content/browser/download/download_file.h"
29#include "content/browser/download/download_file_manager.h"
30#include "content/browser/download/download_item.h"
31#include "content/browser/download/download_manager.h"
32#include "content/browser/download/download_status_updater.h"
[email protected]be76b7e2011-10-13 12:57:5733#include "content/browser/download/interrupt_reasons.h"
[email protected]71bf3f5e2011-08-15 21:05:2234#include "content/browser/download/mock_download_manager.h"
[email protected]9fc114672011-06-15 08:17:4835#include "grit/generated_resources.h"
[email protected]47a881b2011-08-29 22:59:2136#include "net/base/io_buffer.h"
37#include "net/base/mock_file_stream.h"
[email protected]594cd7d2010-07-21 03:23:5638#include "testing/gmock/include/gmock/gmock.h"
39#include "testing/gmock_mutant.h"
initial.commit09911bf2008-07-26 23:55:2940#include "testing/gtest/include/gtest/gtest.h"
[email protected]9fc114672011-06-15 08:17:4841#include "ui/base/l10n/l10n_util.h"
[email protected]7a3b2632011-06-22 20:40:2242#include "ui/base/text/bytes_formatting.h"
initial.commit09911bf2008-07-26 23:55:2943
[email protected]583844c2011-08-27 00:38:3544class DownloadManagerTest : public testing::Test {
initial.commit09911bf2008-07-26 23:55:2945 public:
[email protected]bf68a00b2011-04-07 17:28:2646 static const char* kTestData;
47 static const size_t kTestDataLen;
48
[email protected]2941c2392010-07-15 22:54:3049 DownloadManagerTest()
50 : profile_(new TestingProfile()),
[email protected]e7557f172011-08-19 23:42:0151 download_manager_delegate_(new ChromeDownloadManagerDelegate(
52 profile_.get())),
[email protected]da1a27b2011-07-29 23:16:3353 download_manager_(new MockDownloadManager(
[email protected]aa9881c2011-08-15 18:01:1254 download_manager_delegate_, &download_status_updater_)),
[email protected]f5920322011-03-24 20:34:1655 ui_thread_(BrowserThread::UI, &message_loop_),
[email protected]2606e5a92011-10-21 00:09:5256 file_thread_(BrowserThread::FILE, &message_loop_),
57 download_buffer_(new content::DownloadBuffer) {
[email protected]2941c2392010-07-15 22:54:3058 download_manager_->Init(profile_.get());
[email protected]2588ea9d2011-08-22 20:59:5359 download_manager_delegate_->SetDownloadManager(download_manager_);
[email protected]2941c2392010-07-15 22:54:3060 }
61
62 ~DownloadManagerTest() {
[email protected]326a6a92010-09-10 20:21:1363 download_manager_->Shutdown();
[email protected]2941c2392010-07-15 22:54:3064 // profile_ must outlive download_manager_, so we explicitly delete
65 // download_manager_ first.
[email protected]1b2f8da2010-07-22 08:29:2966 download_manager_ = NULL;
[email protected]e7557f172011-08-19 23:42:0167 download_manager_delegate_ = NULL;
[email protected]1b2f8da2010-07-22 08:29:2968 profile_.reset(NULL);
69 message_loop_.RunAllPending();
initial.commit09911bf2008-07-26 23:55:2970 }
71
[email protected]bf68a00b2011-04-07 17:28:2672 void AddDownloadToFileManager(int id, DownloadFile* download_file) {
[email protected]eda58402011-09-21 19:32:0273 file_manager()->downloads_[DownloadId(download_manager_.get(), id)] =
74 download_file;
[email protected]bf68a00b2011-04-07 17:28:2675 }
76
[email protected]47a881b2011-08-29 22:59:2177 void OnResponseCompleted(int32 download_id, int64 size,
78 const std::string& hash) {
79 download_manager_->OnResponseCompleted(download_id, size, hash);
[email protected]bf68a00b2011-04-07 17:28:2680 }
81
[email protected]99cb7f82011-07-28 17:27:2682 void FileSelected(const FilePath& path, void* params) {
83 download_manager_->FileSelected(path, params);
[email protected]bf68a00b2011-04-07 17:28:2684 }
85
[email protected]4cd82f72011-05-23 19:15:0186 void ContinueDownloadWithPath(DownloadItem* download, const FilePath& path) {
87 download_manager_->ContinueDownloadWithPath(download, path);
[email protected]bf68a00b2011-04-07 17:28:2688 }
89
[email protected]47a881b2011-08-29 22:59:2190 void UpdateData(int32 id, const char* data, size_t length) {
91 // We are passing ownership of this buffer to the download file manager.
92 net::IOBuffer* io_buffer = new net::IOBuffer(length);
93 // We need |AddRef()| because we do a |Release()| in |UpdateDownload()|.
94 io_buffer->AddRef();
95 memcpy(io_buffer->data(), data, length);
96
[email protected]2606e5a92011-10-21 00:09:5297 download_buffer_->AddData(io_buffer, length);
[email protected]47a881b2011-08-29 22:59:2198
99 BrowserThread::PostTask(
100 BrowserThread::FILE, FROM_HERE,
[email protected]a3094072011-10-10 17:14:05101 base::Bind(&DownloadFileManager::UpdateDownload, file_manager_.get(),
[email protected]2606e5a92011-10-21 00:09:52102 DownloadId(download_manager_.get(), id), download_buffer_));
[email protected]47a881b2011-08-29 22:59:21103
104 message_loop_.RunAllPending();
105 }
106
[email protected]be76b7e2011-10-13 12:57:57107 void OnDownloadInterrupted(int32 download_id, int64 size,
108 InterruptReason reason) {
109 download_manager_->OnDownloadInterrupted(download_id, size, reason);
[email protected]bf68a00b2011-04-07 17:28:26110 }
111
112 // Get the download item with ID |id|.
113 DownloadItem* GetActiveDownloadItem(int32 id) {
114 if (ContainsKey(download_manager_->active_downloads_, id))
115 return download_manager_->active_downloads_[id];
116 return NULL;
[email protected]594cd7d2010-07-21 03:23:56117 }
118
initial.commit09911bf2008-07-26 23:55:29119 protected:
[email protected]a3d2bc42010-10-06 14:08:49120 DownloadStatusUpdater download_status_updater_;
[email protected]2941c2392010-07-15 22:54:30121 scoped_ptr<TestingProfile> profile_;
[email protected]aa9881c2011-08-15 18:01:12122 scoped_refptr<ChromeDownloadManagerDelegate> download_manager_delegate_;
initial.commit09911bf2008-07-26 23:55:29123 scoped_refptr<DownloadManager> download_manager_;
[email protected]594cd7d2010-07-21 03:23:56124 scoped_refptr<DownloadFileManager> file_manager_;
[email protected]dd3eac22008-08-26 07:28:34125 MessageLoopForUI message_loop_;
[email protected]ca4b5fa32010-10-09 12:42:18126 BrowserThread ui_thread_;
[email protected]f5920322011-03-24 20:34:16127 BrowserThread file_thread_;
[email protected]2606e5a92011-10-21 00:09:52128 scoped_refptr<content::DownloadBuffer> download_buffer_;
initial.commit09911bf2008-07-26 23:55:29129
[email protected]594cd7d2010-07-21 03:23:56130 DownloadFileManager* file_manager() {
131 if (!file_manager_) {
132 file_manager_ = new DownloadFileManager(NULL);
133 download_manager_->file_manager_ = file_manager_;
134 }
135 return file_manager_;
136 }
137
[email protected]287b86b2011-02-26 00:11:35138 // Make sure download item |id| was set with correct safety state for
139 // given |is_dangerous_file| and |is_dangerous_url|.
140 bool VerifySafetyState(bool is_dangerous_file,
141 bool is_dangerous_url,
142 int id) {
143 DownloadItem::SafetyState safety_state =
144 download_manager_->GetDownloadItem(id)->safety_state();
145 return (is_dangerous_file || is_dangerous_url) ?
146 safety_state != DownloadItem::SAFE : safety_state == DownloadItem::SAFE;
147 }
148
[email protected]4d818fee2010-06-06 13:32:27149 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest);
initial.commit09911bf2008-07-26 23:55:29150};
151
[email protected]bf68a00b2011-04-07 17:28:26152const char* DownloadManagerTest::kTestData = "a;sdlfalsdfjalsdkfjad";
153const size_t DownloadManagerTest::kTestDataLen =
154 strlen(DownloadManagerTest::kTestData);
155
[email protected]47a881b2011-08-29 22:59:21156// A DownloadFile that we can inject errors into. Uses MockFileStream.
157// Note: This can't be in an anonymous namespace because it must be declared
158// as a friend of |DownloadFile| in order to access its private members.
159class DownloadFileWithMockStream : public DownloadFile {
160 public:
161 DownloadFileWithMockStream(DownloadCreateInfo* info,
162 DownloadManager* manager,
163 net::testing::MockFileStream* stream);
164
165 virtual ~DownloadFileWithMockStream() {}
166
167 void SetForcedError(int error);
168
169 protected:
170 // This version creates a |MockFileStream| instead of a |FileStream|.
171 virtual void CreateFileStream() OVERRIDE;
172};
173
174DownloadFileWithMockStream::DownloadFileWithMockStream(
175 DownloadCreateInfo* info,
176 DownloadManager* manager,
177 net::testing::MockFileStream* stream)
178 : DownloadFile(info, manager) {
179 DCHECK(file_stream_ == NULL);
180 file_stream_.reset(stream);
181}
182
183void DownloadFileWithMockStream::SetForcedError(int error)
184{
185 // |file_stream_| can only be set in the constructor and in
186 // CreateFileStream(), both of which insure that it is a |MockFileStream|.
187 net::testing::MockFileStream* mock_stream =
188 static_cast<net::testing::MockFileStream *>(file_stream_.get());
189 mock_stream->set_forced_error(error);
190}
191void DownloadFileWithMockStream::CreateFileStream() {
192 file_stream_.reset(new net::testing::MockFileStream);
193}
194
[email protected]763f946a2009-01-06 19:04:39195namespace {
196
197const struct {
[email protected]2941c2392010-07-15 22:54:30198 const char* url;
199 const char* mime_type;
200 bool save_as;
201 bool prompt_for_download;
202 bool expected_save_as;
203} kStartDownloadCases[] = {
204 { "http://www.foo.com/dont-open.html",
205 "text/html",
206 false,
207 false,
208 false, },
209 { "http://www.foo.com/save-as.html",
210 "text/html",
211 true,
212 false,
213 true, },
214 { "http://www.foo.com/always-prompt.html",
215 "text/html",
216 false,
217 true,
218 true, },
[email protected]bac4f4b2011-03-05 02:01:40219 { "http://www.foo.com/user-script-text-html-mimetype.user.js",
[email protected]2941c2392010-07-15 22:54:30220 "text/html",
221 false,
[email protected]bac4f4b2011-03-05 02:01:40222 false,
[email protected]2941c2392010-07-15 22:54:30223 false, },
224 { "http://www.foo.com/extensionless-extension",
225 "application/x-chrome-extension",
226 true,
227 false,
228 true, },
229 { "http://www.foo.com/save-as.pdf",
230 "application/pdf",
231 true,
232 false,
233 true, },
[email protected]2fc93852011-01-08 22:13:56234 { "http://www.foo.com/sometimes_prompt.pdf",
[email protected]2941c2392010-07-15 22:54:30235 "application/pdf",
236 false,
237 true,
[email protected]2fc93852011-01-08 22:13:56238 false, },
239 { "http://www.foo.com/always_prompt.jar",
240 "application/jar",
241 false,
242 true,
[email protected]3366aca62010-10-20 01:18:24243 true, },
[email protected]2941c2392010-07-15 22:54:30244};
245
[email protected]594cd7d2010-07-21 03:23:56246const struct {
247 FilePath::StringType suggested_path;
[email protected]287b86b2011-02-26 00:11:35248 bool is_dangerous_file;
249 bool is_dangerous_url;
[email protected]594cd7d2010-07-21 03:23:56250 bool finish_before_rename;
[email protected]594cd7d2010-07-21 03:23:56251 int expected_rename_count;
252} kDownloadRenameCases[] = {
[email protected]adb2f3d12011-01-23 16:24:54253 // Safe download, download finishes BEFORE file name determined.
254 // Renamed twice (linear path through UI). Crdownload file does not need
255 // to be deleted.
[email protected]88008002011-05-24 23:14:15256 { FILE_PATH_LITERAL("foo.zip"), false, false, true, 2, },
[email protected]287b86b2011-02-26 00:11:35257 // Dangerous download (file is dangerous or download URL is not safe or both),
258 // download finishes BEFORE file name determined. Needs to be renamed only
259 // once.
[email protected]88008002011-05-24 23:14:15260 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), true, false, true, 1, },
261 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), false, true, true, 1, },
262 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), true, true, true, 1, },
[email protected]adb2f3d12011-01-23 16:24:54263 // Safe download, download finishes AFTER file name determined.
[email protected]594cd7d2010-07-21 03:23:56264 // Needs to be renamed twice.
[email protected]88008002011-05-24 23:14:15265 { FILE_PATH_LITERAL("foo.zip"), false, false, false, 2, },
[email protected]adb2f3d12011-01-23 16:24:54266 // Dangerous download, download finishes AFTER file name determined.
[email protected]594cd7d2010-07-21 03:23:56267 // Needs to be renamed only once.
[email protected]88008002011-05-24 23:14:15268 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), true, false, false, 1, },
269 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), false, true, false, 1, },
270 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), true, true, false, 1, },
[email protected]594cd7d2010-07-21 03:23:56271};
272
273class MockDownloadFile : public DownloadFile {
274 public:
[email protected]f5920322011-03-24 20:34:16275 MockDownloadFile(DownloadCreateInfo* info, DownloadManager* manager)
276 : DownloadFile(info, manager), renamed_count_(0) { }
[email protected]594cd7d2010-07-21 03:23:56277 virtual ~MockDownloadFile() { Destructed(); }
[email protected]33c6d3f12011-09-04 00:00:54278 MOCK_METHOD1(Rename, net::Error(const FilePath&));
[email protected]594cd7d2010-07-21 03:23:56279 MOCK_METHOD0(Destructed, void());
280
[email protected]33c6d3f12011-09-04 00:00:54281 net::Error TestMultipleRename(
[email protected]d2310142011-02-18 17:02:55282 int expected_count, const FilePath& expected,
283 const FilePath& path) {
[email protected]594cd7d2010-07-21 03:23:56284 ++renamed_count_;
285 EXPECT_EQ(expected_count, renamed_count_);
[email protected]594cd7d2010-07-21 03:23:56286 EXPECT_EQ(expected.value(), path.value());
[email protected]33c6d3f12011-09-04 00:00:54287 return net::OK;
[email protected]594cd7d2010-07-21 03:23:56288 }
289
290 private:
291 int renamed_count_;
292};
293
[email protected]f5920322011-03-24 20:34:16294// This is an observer that records what download IDs have opened a select
295// file dialog.
296class SelectFileObserver : public DownloadManager::Observer {
297 public:
298 explicit SelectFileObserver(DownloadManager* download_manager)
299 : download_manager_(download_manager) {
[email protected]bf68a00b2011-04-07 17:28:26300 DCHECK(download_manager_.get());
[email protected]f5920322011-03-24 20:34:16301 download_manager_->AddObserver(this);
302 }
303
304 ~SelectFileObserver() {
305 download_manager_->RemoveObserver(this);
306 }
307
308 // Downloadmanager::Observer functions.
309 virtual void ModelChanged() {}
310 virtual void ManagerGoingDown() {}
[email protected]fed38252011-07-08 17:26:50311 virtual void SelectFileDialogDisplayed(int32 id) {
[email protected]f5920322011-03-24 20:34:16312 file_dialog_ids_.insert(id);
313 }
314
315 bool ShowedFileDialogForId(int32 id) {
316 return file_dialog_ids_.find(id) != file_dialog_ids_.end();
317 }
318
319 private:
320 std::set<int32> file_dialog_ids_;
[email protected]bf68a00b2011-04-07 17:28:26321 scoped_refptr<DownloadManager> download_manager_;
322};
323
324// This observer tracks the progress of |DownloadItem|s.
325class ItemObserver : public DownloadItem::Observer {
326 public:
327 explicit ItemObserver(DownloadItem* tracked)
328 : tracked_(tracked), states_hit_(0),
[email protected]48837962011-04-19 17:03:29329 was_updated_(false), was_opened_(false) {
[email protected]bf68a00b2011-04-07 17:28:26330 DCHECK(tracked_);
331 tracked_->AddObserver(this);
332 // Record the initial state.
333 OnDownloadUpdated(tracked_);
334 }
335 ~ItemObserver() {
336 tracked_->RemoveObserver(this);
337 }
338
339 bool hit_state(int state) const {
340 return (1 << state) & states_hit_;
341 }
342 bool was_updated() const { return was_updated_; }
[email protected]bf68a00b2011-04-07 17:28:26343 bool was_opened() const { return was_opened_; }
344
345 private:
346 // DownloadItem::Observer methods
347 virtual void OnDownloadUpdated(DownloadItem* download) {
348 DCHECK_EQ(tracked_, download);
349 states_hit_ |= (1 << download->state());
350 was_updated_ = true;
351 }
[email protected]bf68a00b2011-04-07 17:28:26352 virtual void OnDownloadOpened(DownloadItem* download) {
353 DCHECK_EQ(tracked_, download);
354 states_hit_ |= (1 << download->state());
355 was_opened_ = true;
356 }
357
358 DownloadItem* tracked_;
359 int states_hit_;
360 bool was_updated_;
[email protected]bf68a00b2011-04-07 17:28:26361 bool was_opened_;
[email protected]f5920322011-03-24 20:34:16362};
363
[email protected]594cd7d2010-07-21 03:23:56364} // namespace
365
[email protected]f5920322011-03-24 20:34:16366TEST_F(DownloadManagerTest, StartDownload) {
367 BrowserThread io_thread(BrowserThread::IO, &message_loop_);
368 PrefService* prefs = profile_->GetPrefs();
[email protected]fed38252011-07-08 17:26:50369 prefs->SetFilePath(prefs::kDownloadDefaultDirectory, FilePath());
[email protected]e7557f172011-08-19 23:42:01370 DownloadPrefs* download_prefs =
371 DownloadPrefs::FromDownloadManager(download_manager_);
372 download_prefs->EnableAutoOpenBasedOnExtension(
[email protected]f5920322011-03-24 20:34:16373 FilePath(FILE_PATH_LITERAL("example.pdf")));
374
375 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kStartDownloadCases); ++i) {
376 prefs->SetBoolean(prefs::kPromptForDownload,
377 kStartDownloadCases[i].prompt_for_download);
378
379 SelectFileObserver observer(download_manager_);
[email protected]c9994e02011-05-24 20:52:19380 // Normally, the download system takes ownership of info, and is
381 // responsible for deleting it. In these unit tests, however, we
382 // don't call the function that deletes it, so we do so ourselves.
383 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
[email protected]f5920322011-03-24 20:34:16384 info->download_id = static_cast<int>(i);
385 info->prompt_user_for_save_location = kStartDownloadCases[i].save_as;
[email protected]8799e542011-04-20 03:47:34386 info->url_chain.push_back(GURL(kStartDownloadCases[i].url));
[email protected]f5920322011-03-24 20:34:16387 info->mime_type = kStartDownloadCases[i].mime_type;
[email protected]c9994e02011-05-24 20:52:19388 download_manager_->CreateDownloadItem(info.get());
[email protected]f5920322011-03-24 20:34:16389
[email protected]c9994e02011-05-24 20:52:19390 DownloadFile* download_file(
391 new DownloadFile(info.get(), download_manager_));
[email protected]bf68a00b2011-04-07 17:28:26392 AddDownloadToFileManager(info->download_id, download_file);
393 download_file->Initialize(false);
[email protected]4cd82f72011-05-23 19:15:01394 download_manager_->StartDownload(info->download_id);
[email protected]f5920322011-03-24 20:34:16395 message_loop_.RunAllPending();
396
[email protected]c9994e02011-05-24 20:52:19397 // SelectFileObserver will have recorded any attempt to open the
[email protected]f5920322011-03-24 20:34:16398 // select file dialog.
[email protected]c9994e02011-05-24 20:52:19399 // Note that DownloadManager::FileSelectionCanceled() is never called.
[email protected]f5920322011-03-24 20:34:16400 EXPECT_EQ(kStartDownloadCases[i].expected_save_as,
401 observer.ShowedFileDialogForId(i));
[email protected]f5920322011-03-24 20:34:16402 }
403}
404
[email protected]594cd7d2010-07-21 03:23:56405TEST_F(DownloadManagerTest, DownloadRenameTest) {
406 using ::testing::_;
407 using ::testing::CreateFunctor;
408 using ::testing::Invoke;
409 using ::testing::Return;
410
[email protected]594cd7d2010-07-21 03:23:56411 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadRenameCases); ++i) {
[email protected]c9994e02011-05-24 20:52:19412 // Normally, the download system takes ownership of info, and is
413 // responsible for deleting it. In these unit tests, however, we
414 // don't call the function that deletes it, so we do so ourselves.
415 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
[email protected]594cd7d2010-07-21 03:23:56416 info->download_id = static_cast<int>(i);
417 info->prompt_user_for_save_location = false;
[email protected]30917cb2011-05-10 21:40:47418 info->url_chain.push_back(GURL());
[email protected]4cd82f72011-05-23 19:15:01419 const FilePath new_path(kDownloadRenameCases[i].suggested_path);
[email protected]594cd7d2010-07-21 03:23:56420
[email protected]bf68a00b2011-04-07 17:28:26421 MockDownloadFile* download_file(
[email protected]c9994e02011-05-24 20:52:19422 new MockDownloadFile(info.get(), download_manager_));
[email protected]bf68a00b2011-04-07 17:28:26423 AddDownloadToFileManager(info->download_id, download_file);
[email protected]594cd7d2010-07-21 03:23:56424
[email protected]bf68a00b2011-04-07 17:28:26425 // |download_file| is owned by DownloadFileManager.
426 ::testing::Mock::AllowLeak(download_file);
427 EXPECT_CALL(*download_file, Destructed()).Times(1);
[email protected]594cd7d2010-07-21 03:23:56428
429 if (kDownloadRenameCases[i].expected_rename_count == 1) {
[email protected]33c6d3f12011-09-04 00:00:54430 EXPECT_CALL(*download_file, Rename(new_path)).WillOnce(Return(net::OK));
[email protected]594cd7d2010-07-21 03:23:56431 } else {
432 ASSERT_EQ(2, kDownloadRenameCases[i].expected_rename_count);
433 FilePath crdownload(download_util::GetCrDownloadPath(new_path));
[email protected]bf68a00b2011-04-07 17:28:26434 EXPECT_CALL(*download_file, Rename(_))
[email protected]d2310142011-02-18 17:02:55435 .WillOnce(testing::WithArgs<0>(Invoke(CreateFunctor(
[email protected]bf68a00b2011-04-07 17:28:26436 download_file, &MockDownloadFile::TestMultipleRename,
[email protected]d2310142011-02-18 17:02:55437 1, crdownload))))
438 .WillOnce(testing::WithArgs<0>(Invoke(CreateFunctor(
[email protected]bf68a00b2011-04-07 17:28:26439 download_file, &MockDownloadFile::TestMultipleRename,
[email protected]d2310142011-02-18 17:02:55440 2, new_path))));
[email protected]594cd7d2010-07-21 03:23:56441 }
[email protected]c9994e02011-05-24 20:52:19442 download_manager_->CreateDownloadItem(info.get());
[email protected]88008002011-05-24 23:14:15443 DownloadItem* download = GetActiveDownloadItem(i);
444 ASSERT_TRUE(download != NULL);
445 if (kDownloadRenameCases[i].is_dangerous_file)
446 download->MarkFileDangerous();
447 if (kDownloadRenameCases[i].is_dangerous_url)
448 download->MarkUrlDangerous();
[email protected]c2e76012010-12-23 21:10:29449
[email protected]4cd82f72011-05-23 19:15:01450 int32* id_ptr = new int32;
451 *id_ptr = i; // Deleted in FileSelected().
[email protected]594cd7d2010-07-21 03:23:56452 if (kDownloadRenameCases[i].finish_before_rename) {
[email protected]47a881b2011-08-29 22:59:21453 OnResponseCompleted(i, 1024, std::string("fake_hash"));
[email protected]f5920322011-03-24 20:34:16454 message_loop_.RunAllPending();
[email protected]99cb7f82011-07-28 17:27:26455 FileSelected(new_path, id_ptr);
[email protected]594cd7d2010-07-21 03:23:56456 } else {
[email protected]99cb7f82011-07-28 17:27:26457 FileSelected(new_path, id_ptr);
[email protected]f5920322011-03-24 20:34:16458 message_loop_.RunAllPending();
[email protected]47a881b2011-08-29 22:59:21459 OnResponseCompleted(i, 1024, std::string("fake_hash"));
[email protected]594cd7d2010-07-21 03:23:56460 }
461
462 message_loop_.RunAllPending();
[email protected]287b86b2011-02-26 00:11:35463 EXPECT_TRUE(VerifySafetyState(kDownloadRenameCases[i].is_dangerous_file,
464 kDownloadRenameCases[i].is_dangerous_url,
465 i));
[email protected]594cd7d2010-07-21 03:23:56466 }
467}
[email protected]bf68a00b2011-04-07 17:28:26468
469TEST_F(DownloadManagerTest, DownloadInterruptTest) {
470 using ::testing::_;
471 using ::testing::CreateFunctor;
472 using ::testing::Invoke;
473 using ::testing::Return;
474
[email protected]c9994e02011-05-24 20:52:19475 // Normally, the download system takes ownership of info, and is
476 // responsible for deleting it. In these unit tests, however, we
477 // don't call the function that deletes it, so we do so ourselves.
478 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
[email protected]bf68a00b2011-04-07 17:28:26479 info->download_id = static_cast<int>(0);
480 info->prompt_user_for_save_location = false;
[email protected]30917cb2011-05-10 21:40:47481 info->url_chain.push_back(GURL());
[email protected]9fc114672011-06-15 08:17:48482 info->total_bytes = static_cast<int64>(kTestDataLen);
[email protected]bf68a00b2011-04-07 17:28:26483 const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
484 const FilePath cr_path(download_util::GetCrDownloadPath(new_path));
485
486 MockDownloadFile* download_file(
[email protected]c9994e02011-05-24 20:52:19487 new MockDownloadFile(info.get(), download_manager_));
[email protected]bf68a00b2011-04-07 17:28:26488 AddDownloadToFileManager(info->download_id, download_file);
489
490 // |download_file| is owned by DownloadFileManager.
491 ::testing::Mock::AllowLeak(download_file);
492 EXPECT_CALL(*download_file, Destructed()).Times(1);
493
[email protected]33c6d3f12011-09-04 00:00:54494 EXPECT_CALL(*download_file, Rename(cr_path)).WillOnce(Return(net::OK));
[email protected]bf68a00b2011-04-07 17:28:26495
[email protected]c9994e02011-05-24 20:52:19496 download_manager_->CreateDownloadItem(info.get());
[email protected]bf68a00b2011-04-07 17:28:26497
498 DownloadItem* download = GetActiveDownloadItem(0);
499 ASSERT_TRUE(download != NULL);
[email protected]9fc114672011-06-15 08:17:48500 scoped_ptr<DownloadItemModel> download_item_model(
501 new DownloadItemModel(download));
[email protected]bf68a00b2011-04-07 17:28:26502
503 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
[email protected]d8ca4d12011-04-07 22:05:13504 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
[email protected]bf68a00b2011-04-07 17:28:26505
506 download_file->AppendDataToFile(kTestData, kTestDataLen);
507
[email protected]4cd82f72011-05-23 19:15:01508 ContinueDownloadWithPath(download, new_path);
[email protected]bf68a00b2011-04-07 17:28:26509 message_loop_.RunAllPending();
510 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
511
[email protected]9fc114672011-06-15 08:17:48512 int64 error_size = 3;
[email protected]be76b7e2011-10-13 12:57:57513 OnDownloadInterrupted(0, error_size,
514 DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
[email protected]bf68a00b2011-04-07 17:28:26515 message_loop_.RunAllPending();
516
517 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
[email protected]bf68a00b2011-04-07 17:28:26518 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
519 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
520 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
521 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
522 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
523 EXPECT_TRUE(observer->was_updated());
[email protected]bf68a00b2011-04-07 17:28:26524 EXPECT_FALSE(observer->was_opened());
[email protected]9fc114672011-06-15 08:17:48525 EXPECT_FALSE(download->file_externally_removed());
526 EXPECT_EQ(DownloadItem::INTERRUPTED, download->state());
[email protected]7a3b2632011-06-22 20:40:22527 ui::DataUnits amount_units = ui::GetByteDisplayUnits(kTestDataLen);
528 string16 simple_size =
529 ui::FormatBytesWithUnits(error_size, amount_units, false);
[email protected]9fc114672011-06-15 08:17:48530 string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality(
[email protected]7a3b2632011-06-22 20:40:22531 ui::FormatBytesWithUnits(kTestDataLen, amount_units, true));
[email protected]9fc114672011-06-15 08:17:48532 EXPECT_EQ(download_item_model->GetStatusText(),
533 l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_INTERRUPTED,
534 simple_size,
535 simple_total));
[email protected]bf68a00b2011-04-07 17:28:26536
[email protected]93af2272011-09-21 18:29:17537 download->Cancel(true);
[email protected]bf68a00b2011-04-07 17:28:26538
[email protected]bf68a00b2011-04-07 17:28:26539 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
540 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
541 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
542 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
543 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
544 EXPECT_TRUE(observer->was_updated());
[email protected]bf68a00b2011-04-07 17:28:26545 EXPECT_FALSE(observer->was_opened());
[email protected]9fc114672011-06-15 08:17:48546 EXPECT_FALSE(download->file_externally_removed());
547 EXPECT_EQ(DownloadItem::INTERRUPTED, download->state());
548 EXPECT_EQ(download->received_bytes(), error_size);
549 EXPECT_EQ(download->total_bytes(), static_cast<int64>(kTestDataLen));
[email protected]bf68a00b2011-04-07 17:28:26550}
551
[email protected]47a881b2011-08-29 22:59:21552// Test the behavior of DownloadFileManager and DownloadManager in the event
553// of a file error while writing the download to disk.
554TEST_F(DownloadManagerTest, DownloadFileErrorTest) {
555 // Create a temporary file and a mock stream.
556 FilePath path;
557 ASSERT_TRUE(file_util::CreateTemporaryFile(&path));
558
559 // This file stream will be used, until the first rename occurs.
560 net::testing::MockFileStream* mock_stream = new net::testing::MockFileStream;
561 ASSERT_EQ(0, mock_stream->Open(
562 path,
563 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE));
564
565 // Normally, the download system takes ownership of info, and is
566 // responsible for deleting it. In these unit tests, however, we
567 // don't call the function that deletes it, so we do so ourselves.
568 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
569 int32 id = 0;
570 info->download_id = id;
571 info->prompt_user_for_save_location = false;
572 info->url_chain.push_back(GURL());
573 info->total_bytes = static_cast<int64>(kTestDataLen * 3);
574 info->save_info.file_path = path;
575
576 // Create a download file that we can insert errors into.
577 DownloadFileWithMockStream* download_file(new DownloadFileWithMockStream(
578 info.get(), download_manager_, mock_stream));
579 AddDownloadToFileManager(id, download_file);
580
581 // |download_file| is owned by DownloadFileManager.
582 download_manager_->CreateDownloadItem(info.get());
583
584 DownloadItem* download = GetActiveDownloadItem(0);
585 ASSERT_TRUE(download != NULL);
586 // This will keep track of what should be displayed on the shelf.
587 scoped_ptr<DownloadItemModel> download_item_model(
588 new DownloadItemModel(download));
589
590 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
591 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
592
593 // Add some data before finalizing the file name.
594 UpdateData(id, kTestData, kTestDataLen);
595
596 // Finalize the file name.
597 ContinueDownloadWithPath(download, path);
598 message_loop_.RunAllPending();
599 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
600
601 // Add more data.
602 UpdateData(id, kTestData, kTestDataLen);
603
604 // Add more data, but an error occurs.
605 download_file->SetForcedError(net::ERR_FAILED);
606 UpdateData(id, kTestData, kTestDataLen);
607
608 // Check the state. The download should have been interrupted.
609 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
610 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
611 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
612 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
613 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
614 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
615 EXPECT_TRUE(observer->was_updated());
616 EXPECT_FALSE(observer->was_opened());
617 EXPECT_FALSE(download->file_externally_removed());
618 EXPECT_EQ(DownloadItem::INTERRUPTED, download->state());
619
620 // Check the download shelf's information.
[email protected]e5e120f2011-09-23 23:08:15621 size_t error_size = kTestDataLen * 2;
622 size_t total_size = kTestDataLen * 3;
[email protected]47a881b2011-08-29 22:59:21623 ui::DataUnits amount_units = ui::GetByteDisplayUnits(kTestDataLen);
624 string16 simple_size =
625 ui::FormatBytesWithUnits(error_size, amount_units, false);
626 string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality(
[email protected]e5e120f2011-09-23 23:08:15627 ui::FormatBytesWithUnits(total_size, amount_units, true));
[email protected]47a881b2011-08-29 22:59:21628 EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_INTERRUPTED,
629 simple_size,
630 simple_total),
631 download_item_model->GetStatusText());
632
633 // Clean up.
[email protected]93af2272011-09-21 18:29:17634 download->Cancel(true);
[email protected]47a881b2011-08-29 22:59:21635 message_loop_.RunAllPending();
636}
637
[email protected]bf68a00b2011-04-07 17:28:26638TEST_F(DownloadManagerTest, DownloadCancelTest) {
639 using ::testing::_;
640 using ::testing::CreateFunctor;
641 using ::testing::Invoke;
642 using ::testing::Return;
643
[email protected]c9994e02011-05-24 20:52:19644 // Normally, the download system takes ownership of info, and is
645 // responsible for deleting it. In these unit tests, however, we
646 // don't call the function that deletes it, so we do so ourselves.
647 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
[email protected]bf68a00b2011-04-07 17:28:26648 info->download_id = static_cast<int>(0);
649 info->prompt_user_for_save_location = false;
[email protected]30917cb2011-05-10 21:40:47650 info->url_chain.push_back(GURL());
[email protected]bf68a00b2011-04-07 17:28:26651 const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
652 const FilePath cr_path(download_util::GetCrDownloadPath(new_path));
653
654 MockDownloadFile* download_file(
[email protected]c9994e02011-05-24 20:52:19655 new MockDownloadFile(info.get(), download_manager_));
[email protected]bf68a00b2011-04-07 17:28:26656 AddDownloadToFileManager(info->download_id, download_file);
657
658 // |download_file| is owned by DownloadFileManager.
659 ::testing::Mock::AllowLeak(download_file);
660 EXPECT_CALL(*download_file, Destructed()).Times(1);
661
[email protected]33c6d3f12011-09-04 00:00:54662 EXPECT_CALL(*download_file, Rename(cr_path)).WillOnce(Return(net::OK));
[email protected]bf68a00b2011-04-07 17:28:26663
[email protected]c9994e02011-05-24 20:52:19664 download_manager_->CreateDownloadItem(info.get());
[email protected]bf68a00b2011-04-07 17:28:26665
666 DownloadItem* download = GetActiveDownloadItem(0);
667 ASSERT_TRUE(download != NULL);
[email protected]9fc114672011-06-15 08:17:48668 scoped_ptr<DownloadItemModel> download_item_model(
669 new DownloadItemModel(download));
[email protected]bf68a00b2011-04-07 17:28:26670
671 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
[email protected]d8ca4d12011-04-07 22:05:13672 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
[email protected]bf68a00b2011-04-07 17:28:26673
[email protected]4cd82f72011-05-23 19:15:01674 ContinueDownloadWithPath(download, new_path);
[email protected]bf68a00b2011-04-07 17:28:26675 message_loop_.RunAllPending();
676 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
677
678 download_file->AppendDataToFile(kTestData, kTestDataLen);
679
[email protected]93af2272011-09-21 18:29:17680 download->Cancel(false);
[email protected]bf68a00b2011-04-07 17:28:26681 message_loop_.RunAllPending();
682
[email protected]93af2272011-09-21 18:29:17683 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
[email protected]bf68a00b2011-04-07 17:28:26684 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
685 EXPECT_TRUE(observer->hit_state(DownloadItem::CANCELLED));
686 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
687 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
688 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
689 EXPECT_TRUE(observer->was_updated());
[email protected]bf68a00b2011-04-07 17:28:26690 EXPECT_FALSE(observer->was_opened());
[email protected]9fc114672011-06-15 08:17:48691 EXPECT_FALSE(download->file_externally_removed());
692 EXPECT_EQ(DownloadItem::CANCELLED, download->state());
693 EXPECT_EQ(download_item_model->GetStatusText(),
694 l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELED));
[email protected]bf68a00b2011-04-07 17:28:26695
696 EXPECT_FALSE(file_util::PathExists(new_path));
697 EXPECT_FALSE(file_util::PathExists(cr_path));
698}
[email protected]8fa1eeb52011-04-13 14:18:02699
700TEST_F(DownloadManagerTest, DownloadOverwriteTest) {
701 using ::testing::_;
702 using ::testing::CreateFunctor;
703 using ::testing::Invoke;
704 using ::testing::Return;
705
706 // Create a temporary directory.
707 ScopedTempDir temp_dir_;
708 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
709
710 // File names we're using.
711 const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt"));
712 const FilePath cr_path(download_util::GetCrDownloadPath(new_path));
713 EXPECT_FALSE(file_util::PathExists(new_path));
714
715 // Create the file that we will overwrite. Will be automatically cleaned
716 // up when temp_dir_ is destroyed.
717 FILE* fp = file_util::OpenFile(new_path, "w");
718 file_util::CloseFile(fp);
719 EXPECT_TRUE(file_util::PathExists(new_path));
720
721 // Construct the unique file name that normally would be created, but
722 // which we will override.
[email protected]ec865262011-08-23 20:01:48723 int uniquifier = DownloadFile::GetUniquePathNumber(new_path);
[email protected]8fa1eeb52011-04-13 14:18:02724 FilePath unique_new_path = new_path;
725 EXPECT_NE(0, uniquifier);
[email protected]ec865262011-08-23 20:01:48726 DownloadFile::AppendNumberToPath(&unique_new_path, uniquifier);
[email protected]8fa1eeb52011-04-13 14:18:02727
[email protected]c9994e02011-05-24 20:52:19728 // Normally, the download system takes ownership of info, and is
729 // responsible for deleting it. In these unit tests, however, we
730 // don't call the function that deletes it, so we do so ourselves.
731 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
[email protected]8fa1eeb52011-04-13 14:18:02732 info->download_id = static_cast<int>(0);
733 info->prompt_user_for_save_location = true;
[email protected]30917cb2011-05-10 21:40:47734 info->url_chain.push_back(GURL());
[email protected]8fa1eeb52011-04-13 14:18:02735
[email protected]c9994e02011-05-24 20:52:19736 download_manager_->CreateDownloadItem(info.get());
[email protected]8fa1eeb52011-04-13 14:18:02737
738 DownloadItem* download = GetActiveDownloadItem(0);
739 ASSERT_TRUE(download != NULL);
[email protected]9fc114672011-06-15 08:17:48740 scoped_ptr<DownloadItemModel> download_item_model(
741 new DownloadItemModel(download));
[email protected]8fa1eeb52011-04-13 14:18:02742
743 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
744 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
745
746 // Create and initialize the download file. We're bypassing the first part
747 // of the download process and skipping to the part after the final file
748 // name has been chosen, so we need to initialize the download file
749 // properly.
750 DownloadFile* download_file(
[email protected]c9994e02011-05-24 20:52:19751 new DownloadFile(info.get(), download_manager_));
[email protected]8fa1eeb52011-04-13 14:18:02752 download_file->Rename(cr_path);
753 // This creates the .crdownload version of the file.
754 download_file->Initialize(false);
755 // |download_file| is owned by DownloadFileManager.
756 AddDownloadToFileManager(info->download_id, download_file);
757
[email protected]4cd82f72011-05-23 19:15:01758 ContinueDownloadWithPath(download, new_path);
[email protected]8fa1eeb52011-04-13 14:18:02759 message_loop_.RunAllPending();
760 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
761
762 download_file->AppendDataToFile(kTestData, kTestDataLen);
763
764 // Finish the download.
[email protected]47a881b2011-08-29 22:59:21765 OnResponseCompleted(0, kTestDataLen, "");
[email protected]8fa1eeb52011-04-13 14:18:02766 message_loop_.RunAllPending();
767
768 // Download is complete.
769 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
770 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
771 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
772 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
773 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
774 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
775 EXPECT_TRUE(observer->was_updated());
[email protected]8fa1eeb52011-04-13 14:18:02776 EXPECT_FALSE(observer->was_opened());
[email protected]9fc114672011-06-15 08:17:48777 EXPECT_FALSE(download->file_externally_removed());
[email protected]8fa1eeb52011-04-13 14:18:02778 EXPECT_EQ(DownloadItem::COMPLETE, download->state());
[email protected]9fc114672011-06-15 08:17:48779 EXPECT_EQ(download_item_model->GetStatusText(), ASCIIToUTF16(""));
[email protected]8fa1eeb52011-04-13 14:18:02780
781 EXPECT_TRUE(file_util::PathExists(new_path));
782 EXPECT_FALSE(file_util::PathExists(cr_path));
783 EXPECT_FALSE(file_util::PathExists(unique_new_path));
784 std::string file_contents;
785 EXPECT_TRUE(file_util::ReadFileToString(new_path, &file_contents));
786 EXPECT_EQ(std::string(kTestData), file_contents);
787}
[email protected]9fc114672011-06-15 08:17:48788
789TEST_F(DownloadManagerTest, DownloadRemoveTest) {
790 using ::testing::_;
791 using ::testing::CreateFunctor;
792 using ::testing::Invoke;
793 using ::testing::Return;
794
795 // Create a temporary directory.
796 ScopedTempDir temp_dir_;
797 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
798
799 // File names we're using.
800 const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt"));
801 const FilePath cr_path(download_util::GetCrDownloadPath(new_path));
802 EXPECT_FALSE(file_util::PathExists(new_path));
803
804 // Normally, the download system takes ownership of info, and is
805 // responsible for deleting it. In these unit tests, however, we
806 // don't call the function that deletes it, so we do so ourselves.
807 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
808 info->download_id = static_cast<int>(0);
809 info->prompt_user_for_save_location = true;
810 info->url_chain.push_back(GURL());
811
812 download_manager_->CreateDownloadItem(info.get());
813
814 DownloadItem* download = GetActiveDownloadItem(0);
815 ASSERT_TRUE(download != NULL);
816 scoped_ptr<DownloadItemModel> download_item_model(
817 new DownloadItemModel(download));
818
819 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state());
820 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
821
822 // Create and initialize the download file. We're bypassing the first part
823 // of the download process and skipping to the part after the final file
824 // name has been chosen, so we need to initialize the download file
825 // properly.
826 DownloadFile* download_file(
827 new DownloadFile(info.get(), download_manager_));
828 download_file->Rename(cr_path);
829 // This creates the .crdownload version of the file.
830 download_file->Initialize(false);
831 // |download_file| is owned by DownloadFileManager.
832 AddDownloadToFileManager(info->download_id, download_file);
833
834 ContinueDownloadWithPath(download, new_path);
835 message_loop_.RunAllPending();
836 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
837
838 download_file->AppendDataToFile(kTestData, kTestDataLen);
839
840 // Finish the download.
[email protected]47a881b2011-08-29 22:59:21841 OnResponseCompleted(0, kTestDataLen, "");
[email protected]9fc114672011-06-15 08:17:48842 message_loop_.RunAllPending();
843
844 // Download is complete.
845 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
846 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
847 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
848 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
849 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
850 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
851 EXPECT_TRUE(observer->was_updated());
852 EXPECT_FALSE(observer->was_opened());
853 EXPECT_FALSE(download->file_externally_removed());
854 EXPECT_EQ(DownloadItem::COMPLETE, download->state());
855 EXPECT_EQ(download_item_model->GetStatusText(), ASCIIToUTF16(""));
856
857 EXPECT_TRUE(file_util::PathExists(new_path));
858 EXPECT_FALSE(file_util::PathExists(cr_path));
859
860 // Remove the downloaded file.
861 ASSERT_TRUE(file_util::Delete(new_path, false));
862 download->OnDownloadedFileRemoved();
863 message_loop_.RunAllPending();
864
865 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL);
866 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
867 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
868 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
869 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
870 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
871 EXPECT_TRUE(observer->was_updated());
872 EXPECT_FALSE(observer->was_opened());
873 EXPECT_TRUE(download->file_externally_removed());
874 EXPECT_EQ(DownloadItem::COMPLETE, download->state());
875 EXPECT_EQ(download_item_model->GetStatusText(),
876 l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_REMOVED));
877
878 EXPECT_FALSE(file_util::PathExists(new_path));
879}