Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: content/browser/download/download_manager_impl_unittest.cc

Issue 10344024: Rewrite download manager unit to be actual unit tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync'd to LKGR. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/download/download_manager_impl.cc ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <set> 5 #include <set>
6 #include <string> 6 #include <string>
7 7
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop.h" 12 #include "base/message_loop.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/scoped_temp_dir.h" 13 #include "base/scoped_temp_dir.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/string16.h" 15 #include "base/string16.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "content/browser/download/byte_stream.h"
19 #include "content/browser/download/download_create_info.h" 20 #include "content/browser/download/download_create_info.h"
20 #include "content/browser/download/download_file_impl.h"
21 #include "content/browser/download/download_file_manager.h" 21 #include "content/browser/download/download_file_manager.h"
22 #include "content/browser/download/download_item_factory.h"
22 #include "content/browser/download/download_manager_impl.h" 23 #include "content/browser/download/download_manager_impl.h"
23 #include "content/browser/download/download_request_handle.h" 24 #include "content/browser/download/download_request_handle.h"
24 #include "content/browser/download/mock_download_file.h" 25 #include "content/browser/download/mock_download_file.h"
25 #include "content/browser/power_save_blocker.h" 26 #include "content/public/browser/browser_context.h"
26 #include "content/public/browser/download_interrupt_reasons.h" 27 #include "content/public/browser/download_interrupt_reasons.h"
27 #include "content/public/browser/download_item.h" 28 #include "content/public/browser/download_item.h"
28 #include "content/public/browser/download_manager_delegate.h" 29 #include "content/public/browser/download_manager_delegate.h"
29 #include "content/public/test/mock_download_manager.h" 30 #include "content/public/test/mock_download_item.h"
30 #include "content/public/test/test_browser_context.h" 31 #include "content/public/test/test_browser_context.h"
31 #include "content/public/test/test_browser_thread.h" 32 #include "content/public/test/test_browser_thread.h"
32 #include "net/base/io_buffer.h"
33 #include "net/base/net_util.h" 33 #include "net/base/net_util.h"
34 #include "testing/gmock/include/gmock/gmock.h" 34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gmock_mutant.h" 35 #include "testing/gmock_mutant.h"
36 #include "testing/gtest/include/gtest/gtest.h" 36 #include "testing/gtest/include/gtest/gtest.h"
37 37
38 #if defined(USE_AURA) && defined(OS_WIN) 38 using ::testing::DoAll;
39 // http://crbug.com/105200 39 using ::testing::Ref;
40 #define MAYBE_StartDownload DISABLED_StartDownload 40 using ::testing::Return;
41 #define MAYBE_DownloadOverwriteTest DISABLED_DownloadOverwriteTest 41 using ::testing::ReturnRef;
42 #define MAYBE_DownloadRemoveTest DISABLED_DownloadRemoveTest 42 using ::testing::SetArgPointee;
43 #define MAYBE_DownloadFileErrorTest DownloadFileErrorTest 43 using ::testing::StrictMock;
44 #elif defined(OS_LINUX) 44 using ::testing::_;
45 // http://crbug.com/110886 for Linux
46 #define MAYBE_StartDownload DISABLED_StartDownload
47 #define MAYBE_DownloadOverwriteTest DISABLED_DownloadOverwriteTest
48 #define MAYBE_DownloadRemoveTest DISABLED_DownloadRemoveTest
49 #define MAYBE_DownloadFileErrorTest DISABLED_DownloadFileErrorTest
50 #else
51 #define MAYBE_StartDownload StartDownload
52 #define MAYBE_DownloadOverwriteTest DownloadOverwriteTest
53 #define MAYBE_DownloadRemoveTest DownloadRemoveTest
54 #define MAYBE_DownloadFileErrorTest DownloadFileErrorTest
55 #endif
56
57 using content::BrowserContext;
58 using content::BrowserThread;
59 using content::DownloadFile;
60 using content::DownloadId;
61 using content::DownloadItem; 45 using content::DownloadItem;
62 using content::DownloadManager; 46 using content::DownloadManager;
63 using content::WebContents; 47 using content::WebContents;
64 using ::testing::NiceMock;
65 using ::testing::ReturnRef;
66 using ::testing::Return;
67 48
68 namespace content { 49 namespace content {
69 class ByteStreamReader; 50 class ByteStreamReader;
70 } 51 }
71 52
72 namespace { 53 namespace {
73 54
74 FilePath GetTempDownloadPath(const FilePath& suggested_path) { 55 class MockDownloadManagerDelegate : public content::DownloadManagerDelegate {
75 return FilePath(suggested_path.value() + FILE_PATH_LITERAL(".temp"));
76 }
77
78 class MockDownloadFileFactory
79 : public DownloadFileManager::DownloadFileFactory {
80 public: 56 public:
81 MockDownloadFileFactory() {} 57 MockDownloadManagerDelegate();
82 58 virtual ~MockDownloadManagerDelegate();
83 virtual DownloadFile* CreateFile( 59
84 DownloadCreateInfo* info, 60 MOCK_METHOD0(Shutdown, void());
61 MOCK_METHOD0(GetNextId, content::DownloadId());
62 MOCK_METHOD1(ShouldStartDownload, bool(int32));
63 MOCK_METHOD1(ChooseDownloadPath, void(DownloadItem*));
64 MOCK_METHOD2(GetIntermediatePath, FilePath(const DownloadItem&, bool*));
65 MOCK_METHOD0(GetAlternativeWebContentsToNotifyForDownload, WebContents*());
66 MOCK_METHOD1(ShouldOpenFileBasedOnExtension, bool(const FilePath&));
67 MOCK_METHOD2(ShouldCompleteDownload, bool(
68 DownloadItem*, const base::Closure&));
69 MOCK_METHOD1(ShouldOpenDownload, bool(DownloadItem*));
70 MOCK_METHOD0(GenerateFileHash, bool());
71 MOCK_METHOD1(AddItemToPersistentStore, void(DownloadItem*));
72 MOCK_METHOD1(UpdateItemInPersistentStore, void(DownloadItem*));
73 MOCK_METHOD2(UpdatePathForItemInPersistentStore,
74 void(DownloadItem*, const FilePath&));
75 MOCK_METHOD1(RemoveItemFromPersistentStore, void(DownloadItem*));
76 MOCK_METHOD2(RemoveItemsFromPersistentStoreBetween, void(
77 base::Time remove_begin, base::Time remove_end));
78 MOCK_METHOD4(GetSaveDir, void(WebContents*, FilePath*, FilePath*, bool*));
79 MOCK_METHOD5(ChooseSavePath, void(
80 WebContents*, const FilePath&, const FilePath::StringType&,
81 bool, const content::SavePackagePathPickedCallback&));
82 };
83
84 MockDownloadManagerDelegate::MockDownloadManagerDelegate() { }
85
86 MockDownloadManagerDelegate::~MockDownloadManagerDelegate() { }
87
88 class MockDownloadFileManager : public DownloadFileManager {
89 public:
90 MockDownloadFileManager();
91
92 MOCK_METHOD0(Shutdown, void());
93 MOCK_METHOD3(MockStartDownload,
94 content::DownloadId(DownloadCreateInfo*,
95 content::ByteStreamReader* stream,
96 const DownloadRequestHandle&));
97
98 virtual content::DownloadId StartDownload(
99 scoped_ptr<DownloadCreateInfo> info,
85 scoped_ptr<content::ByteStreamReader> stream, 100 scoped_ptr<content::ByteStreamReader> stream,
86 const DownloadRequestHandle& request_handle, 101 const DownloadRequestHandle& request_handle) OVERRIDE {
87 DownloadManager* download_manager, 102 return MockStartDownload(info.get(), stream.get(), request_handle);
88 bool calculate_hash, 103 }
104
105 MOCK_METHOD1(CancelDownload, void(content::DownloadId));
106 MOCK_METHOD1(CompleteDownload, void(content::DownloadId));
107 MOCK_METHOD1(OnDownloadManagerShutdown, void(content::DownloadManager*));
108 MOCK_METHOD4(RenameInProgressDownloadFile,
109 void(content::DownloadId,
110 const FilePath&,
111 bool,
112 const RenameCompletionCallback&));
113 MOCK_METHOD4(RenameCompletingDownloadFile,
114 void(content::DownloadId,
115 const FilePath&,
116 bool,
117 const RenameCompletionCallback&));
118 MOCK_CONST_METHOD0(NumberOfActiveDownloads, int());
119 protected:
120 virtual ~MockDownloadFileManager();
121 };
122
123 MockDownloadFileManager::MockDownloadFileManager()
124 : DownloadFileManager(NULL) { }
125
126 MockDownloadFileManager::~MockDownloadFileManager() { }
127
128 class MockDownloadItemFactory
129 : public content::DownloadItemFactory,
130 public base::SupportsWeakPtr<MockDownloadItemFactory> {
131 public:
132 MockDownloadItemFactory();
133 virtual ~MockDownloadItemFactory();
134
135 // Access to map of created items.
136 // TODO(rdsmith): Could add type (save page, persisted, etc.)
137 // functionality if it's ever needed by consumers.
138
139 // Returns NULL if no item of that id is present.
140 content::MockDownloadItem* GetItem(int id);
141
142 // Remove and return an item made by the factory.
143 // Generally used during teardown.
144 content::MockDownloadItem* PopItem();
145
146 // Should be called when the item of this id is removed so that
147 // we don't keep dangling pointers.
148 void RemoveItem(int id);
149
150 // Overridden methods from DownloadItemFactory.
151 virtual content::DownloadItem* CreatePersistedItem(
152 DownloadItemImpl::Delegate* delegate,
153 content::DownloadId download_id,
154 const content::DownloadPersistentStoreInfo& info,
89 const net::BoundNetLog& bound_net_log) OVERRIDE; 155 const net::BoundNetLog& bound_net_log) OVERRIDE;
156 virtual content::DownloadItem* CreateActiveItem(
157 DownloadItemImpl::Delegate* delegate,
158 const DownloadCreateInfo& info,
159 DownloadRequestHandleInterface* request_handle,
160 bool is_otr,
161 const net::BoundNetLog& bound_net_log) OVERRIDE;
162 virtual content::DownloadItem* CreateSavePageItem(
163 DownloadItemImpl::Delegate* delegate,
164 const FilePath& path,
165 const GURL& url,
166 bool is_otr,
167 content::DownloadId download_id,
168 const std::string& mime_type,
169 const net::BoundNetLog& bound_net_log) OVERRIDE;
170
171 private:
172 std::map<int32, content::MockDownloadItem*> items_;
173
174 DISALLOW_COPY_AND_ASSIGN(MockDownloadItemFactory);
90 }; 175 };
91 176
92 DownloadFile* MockDownloadFileFactory::CreateFile( 177 MockDownloadItemFactory::MockDownloadItemFactory() {}
93 DownloadCreateInfo* info, 178
94 scoped_ptr<content::ByteStreamReader> stream, 179 MockDownloadItemFactory::~MockDownloadItemFactory() {}
95 const DownloadRequestHandle& request_handle, 180
96 DownloadManager* download_manager, 181 content::MockDownloadItem* MockDownloadItemFactory::GetItem(int id) {
97 bool calculate_hash, 182 if (items_.find(id) == items_.end())
183 return NULL;
184 return items_[id];
185 }
186
187 content::MockDownloadItem* MockDownloadItemFactory::PopItem() {
188 if (items_.empty())
189 return NULL;
190
191 std::map<int32, content::MockDownloadItem*>::iterator first_item
192 = items_.begin();
193 content::MockDownloadItem* result = first_item->second;
194 items_.erase(first_item);
195 return result;
196 }
197
198 void MockDownloadItemFactory::RemoveItem(int id) {
199 DCHECK(items_.find(id) != items_.end());
200 items_.erase(id);
201 }
202
203 content::DownloadItem* MockDownloadItemFactory::CreatePersistedItem(
204 DownloadItemImpl::Delegate* delegate,
205 content::DownloadId download_id,
206 const content::DownloadPersistentStoreInfo& info,
98 const net::BoundNetLog& bound_net_log) { 207 const net::BoundNetLog& bound_net_log) {
99 NOTREACHED(); 208 int local_id = download_id.local();
100 return NULL; 209 DCHECK(items_.find(local_id) == items_.end());
101 } 210
102 211 content::MockDownloadItem* result =
103 class TestDownloadManagerDelegate : public content::DownloadManagerDelegate { 212 new StrictMock<content::MockDownloadItem>;
213 EXPECT_CALL(*result, GetId())
214 .WillRepeatedly(Return(local_id));
215 items_[local_id] = result;
216
217 return result;
218 }
219
220 content::DownloadItem* MockDownloadItemFactory::CreateActiveItem(
221 DownloadItemImpl::Delegate* delegate,
222 const DownloadCreateInfo& info,
223 DownloadRequestHandleInterface* request_handle,
224 bool is_otr,
225 const net::BoundNetLog& bound_net_log) {
226 int local_id = info.download_id.local();
227 DCHECK(items_.find(local_id) == items_.end());
228
229 content::MockDownloadItem* result =
230 new StrictMock<content::MockDownloadItem>;
231 EXPECT_CALL(*result, GetId())
232 .WillRepeatedly(Return(local_id));
233 items_[local_id] = result;
234
235 return result;
236 }
237
238 content::DownloadItem* MockDownloadItemFactory::CreateSavePageItem(
239 DownloadItemImpl::Delegate* delegate,
240 const FilePath& path,
241 const GURL& url,
242 bool is_otr,
243 content::DownloadId download_id,
244 const std::string& mime_type,
245 const net::BoundNetLog& bound_net_log) {
246 int local_id = download_id.local();
247 DCHECK(items_.find(local_id) == items_.end());
248
249 content::MockDownloadItem* result =
250 new StrictMock<content::MockDownloadItem>;
251 EXPECT_CALL(*result, GetId())
252 .WillRepeatedly(Return(local_id));
253 items_[local_id] = result;
254
255 return result;
256 }
257
258 class MockBrowserContext : public content::BrowserContext {
104 public: 259 public:
105 explicit TestDownloadManagerDelegate(content::DownloadManager* dm) 260 MockBrowserContext() { }
106 : mark_content_dangerous_(false), 261 ~MockBrowserContext() { }
107 prompt_user_for_save_location_(false), 262
108 should_complete_download_(true), 263 MOCK_METHOD0(GetPath, FilePath());
109 download_manager_(dm) { 264 MOCK_CONST_METHOD0(IsOffTheRecord, bool());
110 } 265 MOCK_METHOD0(GetRequestContext, net::URLRequestContextGetter*());
111 266 MOCK_METHOD1(GetRequestContextForRenderProcess,
112 void set_download_directory(const FilePath& path) { 267 net::URLRequestContextGetter*(int renderer_child_id));
113 download_directory_ = path; 268 MOCK_METHOD0(GetRequestContextForMedia, net::URLRequestContextGetter*());
114 } 269 MOCK_METHOD0(GetResourceContext, content::ResourceContext*());
115 270 MOCK_METHOD0(GetDownloadManagerDelegate, content::DownloadManagerDelegate*());
116 void set_prompt_user_for_save_location(bool value) { 271 MOCK_METHOD0(GetGeolocationPermissionContext,
117 prompt_user_for_save_location_ = value; 272 content::GeolocationPermissionContext* ());
118 } 273 MOCK_METHOD0(GetSpeechRecognitionPreferences,
119 274 content::SpeechRecognitionPreferences* ());
120 virtual bool ShouldStartDownload(int32 download_id) OVERRIDE { 275 MOCK_METHOD0(DidLastSessionExitCleanly, bool());
121 DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id); 276 MOCK_METHOD0(GetSpecialStoragePolicy, quota::SpecialStoragePolicy*());
122 FilePath path = net::GenerateFileName(item->GetURL(),
123 item->GetContentDisposition(),
124 item->GetReferrerCharset(),
125 item->GetSuggestedFilename(),
126 item->GetMimeType(),
127 std::string());
128 DownloadItem::TargetDisposition disposition = item->GetTargetDisposition();
129 if (!ShouldOpenFileBasedOnExtension(path) && prompt_user_for_save_location_)
130 disposition = DownloadItem::TARGET_DISPOSITION_PROMPT;
131 item->OnTargetPathDetermined(download_directory_.Append(path),
132 disposition,
133 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
134 return true;
135 }
136
137 virtual FilePath GetIntermediatePath(const DownloadItem& item,
138 bool* ok_to_overwrite) OVERRIDE {
139 if (intermediate_path_.empty()) {
140 *ok_to_overwrite = true;
141 return GetTempDownloadPath(item.GetTargetFilePath());
142 } else {
143 *ok_to_overwrite = overwrite_intermediate_path_;
144 return intermediate_path_;
145 }
146 }
147
148 virtual void ChooseDownloadPath(DownloadItem* item) OVERRIDE {
149 if (!expected_suggested_path_.empty()) {
150 EXPECT_STREQ(expected_suggested_path_.value().c_str(),
151 item->GetTargetFilePath().value().c_str());
152 }
153 if (file_selection_response_.empty()) {
154 BrowserThread::PostTask(
155 BrowserThread::UI, FROM_HERE,
156 base::Bind(&DownloadManager::FileSelectionCanceled,
157 download_manager_,
158 item->GetId()));
159 } else {
160 BrowserThread::PostTask(
161 BrowserThread::UI, FROM_HERE,
162 base::Bind(&DownloadManager::FileSelected,
163 download_manager_,
164 file_selection_response_,
165 item->GetId()));
166 }
167 expected_suggested_path_.clear();
168 file_selection_response_.clear();
169 }
170
171 virtual bool ShouldOpenFileBasedOnExtension(const FilePath& path) OVERRIDE {
172 return path.Extension() == FilePath::StringType(FILE_PATH_LITERAL(".pdf"));
173 }
174
175 virtual void AddItemToPersistentStore(DownloadItem* item) OVERRIDE {
176 static int64 db_handle = DownloadItem::kUninitializedHandle;
177 download_manager_->OnItemAddedToPersistentStore(item->GetId(), --db_handle);
178 }
179
180 void SetFileSelectionExpectation(const FilePath& suggested_path,
181 const FilePath& response) {
182 expected_suggested_path_ = suggested_path;
183 file_selection_response_ = response;
184 }
185
186 void SetMarkContentsDangerous(bool dangerous) {
187 mark_content_dangerous_ = dangerous;
188 }
189
190 void SetIntermediatePath(const FilePath& intermediate_path,
191 bool overwrite_intermediate_path) {
192 intermediate_path_ = intermediate_path;
193 overwrite_intermediate_path_ = overwrite_intermediate_path;
194 }
195
196 void SetShouldCompleteDownload(bool value) {
197 should_complete_download_ = value;
198 }
199
200 void InvokeDownloadCompletionCallback() {
201 EXPECT_FALSE(download_completion_callback_.is_null());
202 download_completion_callback_.Run();
203 download_completion_callback_.Reset();
204 }
205
206 virtual bool ShouldCompleteDownload(
207 DownloadItem* item,
208 const base::Closure& complete_callback) OVERRIDE {
209 download_completion_callback_ = complete_callback;
210 if (mark_content_dangerous_) {
211 CHECK(!complete_callback.is_null());
212 BrowserThread::PostTask(
213 BrowserThread::UI, FROM_HERE,
214 base::Bind(&TestDownloadManagerDelegate::MarkContentDangerous,
215 base::Unretained(this), item->GetId()));
216 mark_content_dangerous_ = false;
217 return false;
218 } else {
219 return should_complete_download_;
220 }
221 }
222
223 private:
224 void MarkContentDangerous(
225 int32 download_id) {
226 DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id);
227 if (!item)
228 return;
229 item->OnContentCheckCompleted(
230 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT);
231 InvokeDownloadCompletionCallback();
232 }
233
234 FilePath download_directory_;
235 FilePath expected_suggested_path_;
236 FilePath file_selection_response_;
237 FilePath intermediate_path_;
238 bool overwrite_intermediate_path_;
239 bool mark_content_dangerous_;
240 bool prompt_user_for_save_location_;
241 bool should_complete_download_;
242 DownloadManager* download_manager_;
243 base::Closure download_completion_callback_;
244
245 DISALLOW_COPY_AND_ASSIGN(TestDownloadManagerDelegate);
246 }; 277 };
247 278
248 } // namespace 279 } // namespace
249 280
250 class DownloadManagerTest : public testing::Test { 281 class DownloadManagerTest : public testing::Test {
251 public: 282 public:
252 static const char* kTestData; 283 static const char* kTestData;
253 static const size_t kTestDataLen; 284 static const size_t kTestDataLen;
254 285
255 DownloadManagerTest() 286 DownloadManagerTest()
256 : browser_context(new content::TestBrowserContext()), 287 : ui_thread_(content::BrowserThread::UI, &message_loop_),
257 download_manager_(new DownloadManagerImpl(NULL)), 288 file_thread_(content::BrowserThread::FILE, &message_loop_),
258 ui_thread_(BrowserThread::UI, &message_loop_), 289 next_download_id_(0) {
259 file_thread_(BrowserThread::FILE, &message_loop_) { 290 }
260 download_manager_delegate_.reset( 291
261 new TestDownloadManagerDelegate(download_manager_.get())); 292 // We tear down everything in TearDown().
262 download_manager_->SetDelegate(download_manager_delegate_.get()); 293 ~DownloadManagerTest() {}
263 download_manager_->Init(browser_context.get()); 294
264 } 295 // Create a MockDownloadItemFactory, MockDownloadManagerDelegate,
265 296 // and MockDownloadFileManager, then create a DownloadManager that points
266 ~DownloadManagerTest() { 297 // at all of those.
298 virtual void SetUp() {
299 DCHECK(!download_manager_.get());
300
301 mock_download_item_factory_ = (new MockDownloadItemFactory())->AsWeakPtr();
302 mock_download_manager_delegate_.reset(
303 new StrictMock<MockDownloadManagerDelegate>);
304 EXPECT_CALL(*mock_download_manager_delegate_.get(), Shutdown())
305 .WillOnce(Return());
306 mock_download_file_manager_ = new StrictMock<MockDownloadFileManager>;
307 EXPECT_CALL(*mock_download_file_manager_.get(),
308 OnDownloadManagerShutdown(_));
309 mock_browser_context_.reset(new StrictMock<MockBrowserContext>);
310 EXPECT_CALL(*mock_browser_context_.get(), IsOffTheRecord())
311 .WillRepeatedly(Return(false));
312
313 download_manager_ = new DownloadManagerImpl(
314 mock_download_file_manager_.get(),
315 scoped_ptr<content::DownloadItemFactory>(
316 mock_download_item_factory_.get()).Pass(), NULL);
317 download_manager_->SetDelegate(mock_download_manager_delegate_.get());
318 download_manager_->Init(mock_browser_context_.get());
319 }
320
321 virtual void TearDown() {
322 while (content::MockDownloadItem*
323 item = mock_download_item_factory_->PopItem()) {
324 EXPECT_CALL(*item, GetSafetyState())
325 .WillOnce(Return(content::DownloadItem::SAFE));
326 EXPECT_CALL(*item, IsPartialDownload())
327 .WillOnce(Return(false));
328 }
329
267 download_manager_->Shutdown(); 330 download_manager_->Shutdown();
268 // browser_context must outlive download_manager_, so we explicitly delete
269 // download_manager_ first.
270 download_manager_ = NULL; 331 download_manager_ = NULL;
271 download_manager_delegate_.reset();
272 browser_context.reset(NULL);
273 message_loop_.RunAllPending(); 332 message_loop_.RunAllPending();
274 } 333 ASSERT_EQ(NULL, mock_download_item_factory_.get());
275 334 message_loop_.RunAllPending();
276 // Create a temporary directory as the downloads directory. 335 mock_download_manager_delegate_.reset();
277 bool CreateTempDownloadsDirectory() { 336 mock_download_file_manager_ = NULL;
278 if (!scoped_download_dir_.CreateUniqueTempDir()) 337 mock_browser_context_.reset();
279 return false; 338 }
280 download_manager_delegate_->set_download_directory( 339
281 scoped_download_dir_.path()); 340 // Returns download id.
282 return true; 341 content::MockDownloadItem& AddItemToManager() {
283 } 342 DownloadCreateInfo info;
284 343 DownloadRequestHandle handle;
285 void AddDownloadToFileManager(DownloadId id, DownloadFile* download_file) { 344
286 file_manager()->downloads_[id] = 345 static const char* kDownloadIdDomain = "Test download id domain";
287 download_file; 346
288 } 347 // Args are ignored except for download id, so everything else can be
289 348 // null.
290 void AddMockDownloadToFileManager(DownloadId id, 349 int id = next_download_id_;
291 MockDownloadFile* download_file) { 350 ++next_download_id_;
292 AddDownloadToFileManager(id, download_file); 351 info.download_id = content::DownloadId(kDownloadIdDomain, id);
293 EXPECT_CALL(*download_file, GetDownloadManager()) 352 download_manager_->CreateDownloadItem(&info, handle);
294 .WillRepeatedly(Return(download_manager_)); 353
295 } 354 DCHECK(mock_download_item_factory_->GetItem(id));
296 355 content::MockDownloadItem& item(*mock_download_item_factory_->GetItem(id));
297 void OnResponseCompleted(DownloadId download_id, int64 size, 356 ON_CALL(item, GetId())
298 const std::string& hash) { 357 .WillByDefault(Return(id));
299 download_manager_->OnResponseCompleted(download_id.local(), size, hash); 358
300 } 359 return item;
301 360 }
302 void ContinueDownloadWithPath(DownloadItem* download, const FilePath& path) { 361
303 download->OnTargetPathDetermined( 362 content::MockDownloadItem& GetMockDownloadItem(int id) {
304 path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, 363 content::MockDownloadItem* itemp = mock_download_item_factory_->GetItem(id);
305 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); 364
306 download_manager_->OnTargetPathAvailable(download); 365 DCHECK(itemp);
307 } 366 return *itemp;
308 367 }
309 void OnDownloadInterrupted(DownloadId download_id, int64 size, 368
310 const std::string& hash_state, 369 void RemoveMockDownloadItem(int id) {
311 content::DownloadInterruptReason reason) { 370 // Owned by DownloadManager; should be deleted there.
312 download_manager_->OnDownloadInterrupted(download_id.local(), size, 371 mock_download_item_factory_->RemoveItem(id);
313 hash_state, reason); 372 }
314 } 373
315 374 MockDownloadManagerDelegate& GetMockDownloadManagerDelegate() {
316 // Get the download item with ID |id|. 375 return *mock_download_manager_delegate_;
317 DownloadItem* GetActiveDownloadItem(DownloadId id) { 376 }
318 return download_manager_->GetActiveDownload(id.local()); 377
319 } 378 MockDownloadFileManager& GetMockDownloadFileManager() {
320 379 return *mock_download_file_manager_;
321 FilePath GetPathInDownloadsDir(const FilePath::StringType& fragment) { 380 }
322 DCHECK(scoped_download_dir_.IsValid()); 381
323 FilePath full_path(scoped_download_dir_.path().Append(fragment)); 382 // Probe at private internals.
324 return full_path.NormalizePathSeparators(); 383 DownloadItem* GetActiveDownloadItem(int32 id) {
384 return download_manager_->GetActiveDownload(id);
385 }
386
387 void AddItemToHistory(content::MockDownloadItem& item, int64 db_handle) {
388 // For DCHECK in AddDownloadItemToHistory. Don't want to use
389 // WillRepeatedly as it may have to return true after this.
390 if (DCHECK_IS_ON())
391 EXPECT_CALL(item, IsPersisted())
392 .WillOnce(Return(false));
393
394 EXPECT_CALL(item, SetDbHandle(db_handle));
395 EXPECT_CALL(item, SetIsPersisted());
396 EXPECT_CALL(item, GetDbHandle())
397 .WillRepeatedly(Return(db_handle));
398
399 // Null out ShowDownloadInBrowser
400 EXPECT_CALL(item, GetWebContents())
401 .WillOnce(Return(static_cast<WebContents*>(NULL)));
402 EXPECT_CALL(GetMockDownloadManagerDelegate(),
403 GetAlternativeWebContentsToNotifyForDownload())
404 .WillOnce(Return(static_cast<WebContents*>(NULL)));
405
406 EXPECT_CALL(item, IsInProgress())
407 .WillOnce(Return(true));
408
409 // Null out MaybeCompleteDownload
410 EXPECT_CALL(item, AllDataSaved())
411 .WillOnce(Return(false));
412
413 download_manager_->OnItemAddedToPersistentStore(item.GetId(), db_handle);
325 } 414 }
326 415
327 protected: 416 protected:
328 scoped_ptr<content::TestBrowserContext> browser_context; 417 // Key test variable; we'll keep it available to sub-classes.
329 scoped_ptr<TestDownloadManagerDelegate> download_manager_delegate_;
330 scoped_refptr<DownloadManagerImpl> download_manager_; 418 scoped_refptr<DownloadManagerImpl> download_manager_;
331 scoped_refptr<DownloadFileManager> file_manager_; 419
420 private:
332 MessageLoopForUI message_loop_; 421 MessageLoopForUI message_loop_;
333 content::TestBrowserThread ui_thread_; 422 content::TestBrowserThread ui_thread_;
334 content::TestBrowserThread file_thread_; 423 content::TestBrowserThread file_thread_;
335 ScopedTempDir scoped_download_dir_; 424 base::WeakPtr<MockDownloadItemFactory> mock_download_item_factory_;
336 425 scoped_ptr<MockDownloadManagerDelegate> mock_download_manager_delegate_;
337 DownloadFileManager* file_manager() { 426 scoped_refptr<MockDownloadFileManager> mock_download_file_manager_;
338 if (!file_manager_) { 427 scoped_ptr<MockBrowserContext> mock_browser_context_;
339 file_manager_ = new DownloadFileManager(new MockDownloadFileFactory); 428 int next_download_id_;
340 download_manager_->SetFileManagerForTesting(file_manager_);
341 }
342 return file_manager_;
343 }
344 429
345 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest); 430 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest);
346 }; 431 };
347 432
348 const char* DownloadManagerTest::kTestData = "a;sdlfalsdfjalsdkfjad"; 433 // Does the DownloadManager prompt when requested?
349 const size_t DownloadManagerTest::kTestDataLen = 434 TEST_F(DownloadManagerTest, RestartDownload) {
350 strlen(DownloadManagerTest::kTestData); 435 // Put a mock we have a handle to on the download manager.
351 436 content::MockDownloadItem& item(AddItemToManager());
352 // A DownloadFile that we can inject errors into. 437 int download_id = item.GetId();
353 class DownloadFileWithErrors : public DownloadFileImpl { 438
354 public: 439 // Confirm we're internally consistent.
355 DownloadFileWithErrors(DownloadCreateInfo* info, 440 EXPECT_EQ(&item, GetActiveDownloadItem(download_id));
356 scoped_ptr<content::ByteStreamReader> stream, 441
357 DownloadManager* manager, 442 ScopedTempDir download_dir;
358 bool calculate_hash); 443 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
359 virtual ~DownloadFileWithErrors() {} 444 FilePath expected_path(download_dir.path().Append(
360 445 FILE_PATH_LITERAL("location")));
361 // BaseFile delegated functions. 446
362 virtual net::Error Initialize() OVERRIDE; 447 EXPECT_CALL(item, GetTargetDisposition())
363 virtual net::Error AppendDataToFile(const char* data, 448 .WillOnce(Return(DownloadItem::TARGET_DISPOSITION_PROMPT));
364 size_t data_len) OVERRIDE; 449 EXPECT_CALL(GetMockDownloadManagerDelegate(), ChooseDownloadPath(&item));
365 virtual net::Error Rename(const FilePath& full_path) OVERRIDE; 450 download_manager_->RestartDownload(download_id);
366 451
367 void set_forced_error(net::Error error) { forced_error_ = error; } 452 // The alternative pathway goes straight to OnTargetPathAvailable,
368 void clear_forced_error() { forced_error_ = net::OK; } 453 // so it more naturally belongs below.
369 net::Error forced_error() const { return forced_error_; } 454 }
370 455
371 private: 456 // Do the results of GetIntermediatePath get passed through to the
372 net::Error ReturnError(net::Error function_error) { 457 // download? Note that this path is tested from RestartDownload
373 if (forced_error_ != net::OK) { 458 // to test the non-prompting path in RestartDownload as well.
374 net::Error ret = forced_error_; 459 TEST_F(DownloadManagerTest, OnTargetPathAvailable) {
375 clear_forced_error(); 460 // Put a mock we have a handle to on the download manager.
376 return ret; 461 content::MockDownloadItem& item(AddItemToManager());
377 } 462
378 463 ScopedTempDir download_dir;
379 return function_error; 464 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
380 } 465 FilePath target_path(download_dir.path().Append(
381 466 FILE_PATH_LITERAL("location")));
382 net::Error forced_error_; 467 FilePath intermediate_path(download_dir.path().Append(
383 }; 468 FILE_PATH_LITERAL("location.crdownload")));
384 469
385 DownloadFileWithErrors::DownloadFileWithErrors( 470 EXPECT_CALL(item, GetTargetDisposition())
386 DownloadCreateInfo* info, 471 .WillOnce(Return(DownloadItem::TARGET_DISPOSITION_UNIQUIFY));
387 scoped_ptr<content::ByteStreamReader> stream, 472 EXPECT_CALL(GetMockDownloadManagerDelegate(),
388 DownloadManager* manager, 473 GetIntermediatePath(Ref(item), _))
389 bool calculate_hash) 474 .WillOnce(DoAll(SetArgPointee<1>(true), Return(intermediate_path)));
390 : DownloadFileImpl(info, 475 // Finesse DCHECK with WillRepeatedly.
391 stream.Pass(), 476 EXPECT_CALL(item, GetTargetFilePath())
392 new DownloadRequestHandle(), 477 .WillRepeatedly(ReturnRef(target_path));
393 manager, 478 EXPECT_CALL(item, OnIntermediatePathDetermined(
394 calculate_hash, 479 &GetMockDownloadFileManager(), intermediate_path, true));
395 scoped_ptr<content::PowerSaveBlocker>(NULL).Pass(), 480 download_manager_->RestartDownload(item.GetId());
396 net::BoundNetLog()), 481 }
397 forced_error_(net::OK) { 482
398 } 483 // Do the results of an OnDownloadInterrupted get passed through properly
399 484 // to the DownloadItem? This test tests non-persisted downloads.
400 net::Error DownloadFileWithErrors::Initialize() { 485 TEST_F(DownloadManagerTest, OnDownloadInterrupted_NonPersisted) {
401 return ReturnError(DownloadFileImpl::Initialize()); 486 // Put a mock we have a handle to on the download manager.
402 } 487 content::MockDownloadItem& item(AddItemToManager());
403 488 int download_id = item.GetId();
404 net::Error DownloadFileWithErrors::AppendDataToFile(const char* data, 489
405 size_t data_len) { 490 int64 size = 0xdeadbeef;
406 return ReturnError(DownloadFileImpl::AppendDataToFile(data, data_len)); 491 const std::string hash_state("Undead beef");
407 } 492 content::DownloadInterruptReason reason(
408 493 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
409 net::Error DownloadFileWithErrors::Rename(const FilePath& full_path) { 494
410 return ReturnError(DownloadFileImpl::Rename(full_path)); 495 EXPECT_CALL(item, Interrupted(size, hash_state, reason));
411 } 496 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
412 497 EXPECT_CALL(item, IsPersisted())
413 namespace { 498 .WillOnce(Return(false));
414 499 download_manager_->OnDownloadInterrupted(
415 const struct { 500 download_id, size, hash_state, reason);
416 const char* url; 501 EXPECT_EQ(&item, GetActiveDownloadItem(download_id));
417 const char* mime_type; 502 }
418 bool save_as; 503
419 bool prompt_for_download; 504 // Do the results of an OnDownloadInterrupted get passed through properly
420 bool expected_save_as; 505 // to the DownloadItem? This test tests persisted downloads.
421 } kStartDownloadCases[] = { 506 TEST_F(DownloadManagerTest, OnDownloadInterrupted_Persisted) {
422 { "http://www.foo.com/dont-open.html", 507 // Put a mock we have a handle to on the download manager.
423 "text/html", 508 content::MockDownloadItem& item(AddItemToManager());
424 false, 509 int download_id = item.GetId();
425 false, 510 int64 db_handle = 0x7;
426 false, }, 511 AddItemToHistory(item, db_handle);
427 { "http://www.foo.com/save-as.html", 512
428 "text/html", 513 int64 size = 0xdeadbeef;
429 true, 514 const std::string hash_state("Undead beef");
430 false, 515 content::DownloadInterruptReason reason(
431 true, }, 516 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
432 { "http://www.foo.com/always-prompt.html", 517
433 "text/html", 518 EXPECT_CALL(item, Interrupted(size, hash_state, reason));
434 false, 519 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
435 true, 520 EXPECT_CALL(item, IsPersisted())
436 true, }, 521 .WillOnce(Return(true));
437 { "http://www.foo.com/user-script-text-html-mimetype.user.js", 522 EXPECT_CALL(GetMockDownloadManagerDelegate(),
438 "text/html", 523 UpdateItemInPersistentStore(&item));
439 false, 524 download_manager_->OnDownloadInterrupted(
440 false, 525 download_id, size, hash_state, reason);
441 false, }, 526 EXPECT_EQ(NULL, GetActiveDownloadItem(download_id));
442 { "http://www.foo.com/extensionless-extension", 527
443 "application/x-chrome-extension", 528 // Remove so we don't get errors on shutdown.
444 true, 529 EXPECT_CALL(GetMockDownloadManagerDelegate(),
445 false, 530 RemoveItemFromPersistentStore(&item));
446 true, }, 531 download_manager_->DownloadRemoved(&item);
447 { "http://www.foo.com/save-as.pdf", 532 RemoveMockDownloadItem(download_id);
448 "application/pdf", 533 }
449 true, 534
450 false, 535 // Does DownloadCancelled remove Download from appropriate queues?
451 true, }, 536 // This test tests non-persisted downloads.
452 { "http://www.foo.com/sometimes_prompt.pdf", 537 TEST_F(DownloadManagerTest, OnDownloadCancelled_NonPersisted) {
453 "application/pdf", 538 // Put a mock we have a handle to on the download manager.
454 false, 539 content::MockDownloadItem& item(AddItemToManager());
455 true, 540
456 false, }, 541 EXPECT_CALL(item, IsPersisted())
457 { "http://www.foo.com/always_prompt.jar", 542 .WillRepeatedly(Return(false));
458 "application/jar", 543 EXPECT_CALL(item, GetState())
459 false, 544 .WillRepeatedly(Return(DownloadItem::CANCELLED));
460 true, 545 EXPECT_CALL(item, GetDbHandle())
461 true, }, 546 .WillRepeatedly(Return(DownloadItem::kUninitializedHandle));
462 }; 547
463 548 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
464 // This is an observer that records what download IDs have opened a select 549 download_manager_->DownloadCancelled(&item);
465 // file dialog. 550 // TODO(rdsmith): Confirm that the download item is no longer on the
466 class SelectFileObserver : public DownloadManager::Observer { 551 // active list by calling GetActiveDownloadItem(id). Currently, the
467 public: 552 // item is left on the active list for rendez-vous with the history
468 explicit SelectFileObserver(DownloadManager* download_manager) 553 // system :-{.
469 : download_manager_(download_manager) { 554 }
470 DCHECK(download_manager_.get()); 555
471 download_manager_->AddObserver(this); 556 // Does DownloadCancelled remove Download from appropriate queues?
472 } 557 // This test tests persisted downloads.
473 558 TEST_F(DownloadManagerTest, OnDownloadCancelled_Persisted) {
474 ~SelectFileObserver() { 559 // Put a mock we have a handle to on the download manager.
475 download_manager_->RemoveObserver(this); 560 content::MockDownloadItem& item(AddItemToManager());
476 } 561 int download_id = item.GetId();
477 562 int64 db_handle = 0x7;
478 // Downloadmanager::Observer functions. 563 AddItemToHistory(item, db_handle);
479 virtual void ModelChanged(DownloadManager* manager) OVERRIDE {} 564
480 virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {} 565 EXPECT_CALL(item, IsPersisted())
481 virtual void SelectFileDialogDisplayed( 566 .WillRepeatedly(Return(true));
482 DownloadManager* manager, int32 id) OVERRIDE { 567 EXPECT_CALL(GetMockDownloadManagerDelegate(),
483 file_dialog_ids_.insert(id); 568 UpdateItemInPersistentStore(&item));
484 } 569 EXPECT_CALL(item, GetState())
485 570 .WillRepeatedly(Return(DownloadItem::CANCELLED));
486 bool ShowedFileDialogForId(int32 id) { 571 EXPECT_CALL(item, GetDbHandle())
487 return file_dialog_ids_.find(id) != file_dialog_ids_.end(); 572 .WillRepeatedly(Return(db_handle));
488 } 573
489 574 EXPECT_CALL(item, OffThreadCancel(&GetMockDownloadFileManager()));
490 private: 575 download_manager_->DownloadCancelled(&item);
491 std::set<int32> file_dialog_ids_; 576 EXPECT_EQ(NULL, GetActiveDownloadItem(download_id));
492 scoped_refptr<DownloadManager> download_manager_; 577 }
493 };
494
495 // This observer tracks the progress of |DownloadItem|s.
496 class ItemObserver : public DownloadItem::Observer {
497 public:
498 explicit ItemObserver(DownloadItem* tracked)
499 : tracked_(tracked), states_hit_(0),
500 was_updated_(false), was_opened_(false) {
501 DCHECK(tracked_);
502 tracked_->AddObserver(this);
503 // Record the initial state.
504 OnDownloadUpdated(tracked_);
505 }
506 ~ItemObserver() {
507 tracked_->RemoveObserver(this);
508 }
509
510 bool hit_state(int state) const {
511 return (1 << state) & states_hit_;
512 }
513 bool was_updated() const { return was_updated_; }
514 bool was_opened() const { return was_opened_; }
515
516 private:
517 // DownloadItem::Observer methods
518 virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
519 DCHECK_EQ(tracked_, download);
520 states_hit_ |= (1 << download->GetState());
521 was_updated_ = true;
522 }
523 virtual void OnDownloadOpened(DownloadItem* download) OVERRIDE{
524 DCHECK_EQ(tracked_, download);
525 states_hit_ |= (1 << download->GetState());
526 was_opened_ = true;
527 }
528
529 DownloadItem* tracked_;
530 int states_hit_;
531 bool was_updated_;
532 bool was_opened_;
533 };
534
535 } // namespace
536
537 TEST_F(DownloadManagerTest, MAYBE_StartDownload) {
538 content::TestBrowserThread io_thread(BrowserThread::IO, &message_loop_);
539 ASSERT_TRUE(CreateTempDownloadsDirectory());
540 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kStartDownloadCases); ++i) {
541 DVLOG(1) << "Test case " << i;
542 download_manager_delegate_->set_prompt_user_for_save_location(
543 kStartDownloadCases[i].prompt_for_download);
544
545 SelectFileObserver observer(download_manager_);
546 // Normally, the download system takes ownership of info, and is
547 // responsible for deleting it. In these unit tests, however, we
548 // don't call the function that deletes it, so we do so ourselves.
549 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
550 info->prompt_user_for_save_location = kStartDownloadCases[i].save_as;
551 info->url_chain.push_back(GURL(kStartDownloadCases[i].url));
552 info->mime_type = kStartDownloadCases[i].mime_type;
553 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
554
555 scoped_ptr<content::ByteStreamWriter> stream_writer;
556 scoped_ptr<content::ByteStreamReader> stream_reader;
557 content::CreateByteStream(message_loop_.message_loop_proxy(),
558 message_loop_.message_loop_proxy(),
559 kTestDataLen, &stream_writer, &stream_reader);
560
561 DownloadFile* download_file(
562 new DownloadFileImpl(info.get(),
563 stream_reader.Pass(),
564 new DownloadRequestHandle(),
565 download_manager_, false,
566 scoped_ptr<content::PowerSaveBlocker>(NULL).Pass(),
567 net::BoundNetLog()));
568 AddDownloadToFileManager(info->download_id, download_file);
569 download_file->Initialize();
570 download_manager_->StartDownload(info->download_id.local());
571 message_loop_.RunAllPending();
572
573 // SelectFileObserver will have recorded any attempt to open the
574 // select file dialog.
575 // Note that DownloadManager::FileSelectionCanceled() is never called.
576 EXPECT_EQ(kStartDownloadCases[i].expected_save_as,
577 observer.ShowedFileDialogForId(info->download_id.local()));
578
579 file_manager()->CancelDownload(info->download_id);
580 }
581 }
582
583 namespace {
584
585 enum OverwriteDownloadPath {
586 DONT_OVERWRITE,
587 OVERWRITE
588 };
589
590 enum ResponseCompletionTime {
591 COMPLETES_BEFORE_RENAME,
592 COMPLETES_AFTER_RENAME
593 };
594
595 // Test cases to be used with DownloadFilenameTest. The paths are relative to
596 // the temporary downloads directory used for testing.
597 const struct DownloadFilenameTestCase {
598 // DownloadItem properties prior to calling RestartDownload().
599 const FilePath::CharType* target_path;
600 DownloadItem::TargetDisposition target_disposition;
601
602 // If we receive a ChooseDownloadPath() call to prompt the user for a download
603 // location, |expected_prompt_path| is the expected prompt path. The
604 // TestDownloadManagerDelegate will respond with |chosen_path|. If
605 // |chosen_path| is empty, then the file choose dialog be cancelled.
606 const FilePath::CharType* expected_prompt_path;
607 const FilePath::CharType* chosen_path;
608
609 // Response to GetIntermediatePath(). If |intermediate_path| is empty, then a
610 // temporary path is constructed with
611 // GetTempDownloadPath(item->GetTargetFilePath()).
612 const FilePath::CharType* intermediate_path;
613 OverwriteDownloadPath overwrite_intermediate_path;
614
615 // Determines when OnResponseCompleted() is called. If this is
616 // COMPLETES_BEFORE_RENAME, then the response completes before the filename is
617 // determines.
618 ResponseCompletionTime completion;
619
620 // The expected intermediate path for the download.
621 const FilePath::CharType* expected_intermediate_path;
622
623 // The expected final path for the download.
624 const FilePath::CharType* expected_final_path;
625 } kDownloadFilenameTestCases[] = {
626
627 #define TARGET FILE_PATH_LITERAL
628 #define INTERMEDIATE FILE_PATH_LITERAL
629 #define EXPECTED_PROMPT FILE_PATH_LITERAL
630 #define PROMPT_RESPONSE FILE_PATH_LITERAL
631 #define EXPECTED_INTERMEDIATE FILE_PATH_LITERAL
632 #define EXPECTED_FINAL FILE_PATH_LITERAL
633
634 {
635 // 0: No prompting.
636 TARGET("foo.txt"),
637 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
638
639 EXPECTED_PROMPT(""),
640 PROMPT_RESPONSE(""),
641
642 INTERMEDIATE("foo.txt.intermediate"),
643 OVERWRITE,
644
645 COMPLETES_AFTER_RENAME,
646 EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
647 EXPECTED_FINAL("foo.txt"),
648 },
649 {
650 // 1: With prompting. No rename.
651 TARGET("foo.txt"),
652 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
653
654 EXPECTED_PROMPT("foo.txt"),
655 PROMPT_RESPONSE("foo.txt"),
656
657 INTERMEDIATE("foo.txt.intermediate"),
658 OVERWRITE,
659
660 COMPLETES_AFTER_RENAME,
661 EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
662 EXPECTED_FINAL("foo.txt"),
663 },
664 {
665 // 2: With prompting. Download is renamed.
666 TARGET("foo.txt"),
667 DownloadItem::TARGET_DISPOSITION_PROMPT,
668
669 EXPECTED_PROMPT("foo.txt"),
670 PROMPT_RESPONSE("bar.txt"),
671
672 INTERMEDIATE("bar.txt.intermediate"),
673 OVERWRITE,
674
675 COMPLETES_AFTER_RENAME,
676 EXPECTED_INTERMEDIATE("bar.txt.intermediate"),
677 EXPECTED_FINAL("bar.txt"),
678 },
679 {
680 // 3: With prompting. Download path is changed.
681 TARGET("foo.txt"),
682 DownloadItem::TARGET_DISPOSITION_PROMPT,
683
684 EXPECTED_PROMPT("foo.txt"),
685 PROMPT_RESPONSE("Foo/bar.txt"),
686
687 INTERMEDIATE("Foo/bar.txt.intermediate"),
688 OVERWRITE,
689
690 COMPLETES_AFTER_RENAME,
691 EXPECTED_INTERMEDIATE("Foo/bar.txt.intermediate"),
692 EXPECTED_FINAL("Foo/bar.txt"),
693 },
694 {
695 // 4: No prompting. Intermediate path exists. Doesn't overwrite
696 // intermediate path.
697 TARGET("exists.png"),
698 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
699
700 EXPECTED_PROMPT(""),
701 PROMPT_RESPONSE(""),
702
703 INTERMEDIATE("exists.png.temp"),
704 DONT_OVERWRITE,
705
706 COMPLETES_AFTER_RENAME,
707 EXPECTED_INTERMEDIATE("exists.png (1).temp"),
708 EXPECTED_FINAL("exists.png"),
709 },
710 {
711 // 5: No prompting. Intermediate path exists. Overwrites.
712 TARGET("exists.png"),
713 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
714
715 EXPECTED_PROMPT(""),
716 PROMPT_RESPONSE(""),
717
718 INTERMEDIATE("exists.png.temp"),
719 OVERWRITE,
720
721 COMPLETES_AFTER_RENAME,
722 EXPECTED_INTERMEDIATE("exists.png.temp"),
723 EXPECTED_FINAL("exists.png"),
724 },
725 {
726 // 6: No prompting. Final path exists. Doesn't overwrite.
727 TARGET("exists.txt"),
728 DownloadItem::TARGET_DISPOSITION_UNIQUIFY,
729
730 EXPECTED_PROMPT(""),
731 PROMPT_RESPONSE(""),
732
733 INTERMEDIATE("exists.txt.temp"),
734 OVERWRITE,
735
736 COMPLETES_AFTER_RENAME,
737 EXPECTED_INTERMEDIATE("exists.txt.temp"),
738 EXPECTED_FINAL("exists (1).txt"),
739 },
740 {
741 // 7: No prompting. Final path exists. Overwrites.
742 TARGET("exists.txt"),
743 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
744
745 EXPECTED_PROMPT(""),
746 PROMPT_RESPONSE(""),
747
748 INTERMEDIATE("exists.txt.temp"),
749 OVERWRITE,
750
751 COMPLETES_AFTER_RENAME,
752 EXPECTED_INTERMEDIATE("exists.txt.temp"),
753 EXPECTED_FINAL("exists.txt"),
754 },
755 {
756 // 8: No prompting. Response completes before filename determination.
757 TARGET("foo.txt"),
758 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
759
760 EXPECTED_PROMPT(""),
761 PROMPT_RESPONSE(""),
762
763 INTERMEDIATE("foo.txt.intermediate"),
764 OVERWRITE,
765
766 COMPLETES_BEFORE_RENAME,
767 EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
768 EXPECTED_FINAL("foo.txt"),
769 },
770 {
771 // 9: With prompting. Download path is changed. Response completes before
772 // filename determination.
773 TARGET("foo.txt"),
774 DownloadItem::TARGET_DISPOSITION_PROMPT,
775
776 EXPECTED_PROMPT("foo.txt"),
777 PROMPT_RESPONSE("Foo/bar.txt"),
778
779 INTERMEDIATE("Foo/bar.txt.intermediate"),
780 OVERWRITE,
781
782 COMPLETES_BEFORE_RENAME,
783 EXPECTED_INTERMEDIATE("Foo/bar.txt.intermediate"),
784 EXPECTED_FINAL("Foo/bar.txt"),
785 },
786
787 #undef TARGET
788 #undef INTERMEDIATE
789 #undef EXPECTED_PROMPT
790 #undef PROMPT_RESPONSE
791 #undef EXPECTED_INTERMEDIATE
792 #undef EXPECTED_FINAL
793 };
794
795 } // namespace
796
797 TEST_F(DownloadManagerTest, DownloadFilenameTest) {
798 ASSERT_TRUE(CreateTempDownloadsDirectory());
799
800 // We create a known file to test file uniquification.
801 ASSERT_TRUE(file_util::WriteFile(
802 GetPathInDownloadsDir(FILE_PATH_LITERAL("exists.txt")), "", 0) == 0);
803 ASSERT_TRUE(file_util::WriteFile(
804 GetPathInDownloadsDir(FILE_PATH_LITERAL("exists.png.temp")), "", 0) == 0);
805
806 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadFilenameTestCases); ++i) {
807 const DownloadFilenameTestCase& test_case = kDownloadFilenameTestCases[i];
808 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
809
810 SCOPED_TRACE(testing::Message() << "Running test case " << i);
811 info->url_chain.push_back(GURL());
812
813 MockDownloadFile* download_file(
814 new ::testing::StrictMock<MockDownloadFile>());
815 FilePath target_path = GetPathInDownloadsDir(test_case.target_path);
816 FilePath expected_prompt_path =
817 GetPathInDownloadsDir(test_case.expected_prompt_path);
818 FilePath chosen_path = GetPathInDownloadsDir(test_case.chosen_path);
819 FilePath intermediate_path =
820 GetPathInDownloadsDir(test_case.intermediate_path);
821 FilePath expected_intermediate_path =
822 GetPathInDownloadsDir(test_case.expected_intermediate_path);
823 FilePath expected_final_path =
824 GetPathInDownloadsDir(test_case.expected_final_path);
825
826 EXPECT_CALL(*download_file, Rename(expected_intermediate_path))
827 .WillOnce(Return(net::OK));
828 EXPECT_CALL(*download_file, Rename(expected_final_path))
829 .WillOnce(Return(net::OK));
830 #if defined(OS_MACOSX)
831 EXPECT_CALL(*download_file, AnnotateWithSourceInformation());
832 #endif
833 EXPECT_CALL(*download_file, Detach());
834
835 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
836 AddMockDownloadToFileManager(info->download_id, download_file);
837 DownloadItem* download = GetActiveDownloadItem(info->download_id);
838 ASSERT_TRUE(download != NULL);
839
840 if (test_case.completion == COMPLETES_BEFORE_RENAME)
841 OnResponseCompleted(info->download_id, 1024, std::string("fake_hash"));
842
843 download->OnTargetPathDetermined(
844 target_path, test_case.target_disposition,
845 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
846 download_manager_delegate_->SetFileSelectionExpectation(
847 expected_prompt_path, chosen_path);
848 download_manager_delegate_->SetIntermediatePath(
849 intermediate_path, test_case.overwrite_intermediate_path);
850 download_manager_delegate_->SetShouldCompleteDownload(false);
851 download_manager_->RestartDownload(info->download_id.local());
852 message_loop_.RunAllPending();
853
854 if (test_case.completion == COMPLETES_AFTER_RENAME) {
855 OnResponseCompleted(info->download_id, 1024, std::string("fake_hash"));
856 message_loop_.RunAllPending();
857 }
858
859 EXPECT_EQ(expected_intermediate_path.value(),
860 download->GetFullPath().value());
861 download_manager_delegate_->SetShouldCompleteDownload(true);
862 download_manager_delegate_->InvokeDownloadCompletionCallback();
863 message_loop_.RunAllPending();
864 EXPECT_EQ(expected_final_path.value(),
865 download->GetTargetFilePath().value());
866 }
867 }
868
869 void WriteCopyToStream(const char *source,
870 size_t len, content::ByteStreamWriter* stream) {
871 scoped_refptr<net::IOBuffer> copy(new net::IOBuffer(len));
872 memcpy(copy.get()->data(), source, len);
873 stream->Write(copy, len);
874 }
875
876 TEST_F(DownloadManagerTest, DownloadInterruptTest) {
877 using ::testing::_;
878 using ::testing::CreateFunctor;
879 using ::testing::Invoke;
880 using ::testing::Return;
881
882 // Normally, the download system takes ownership of info, and is
883 // responsible for deleting it. In these unit tests, however, we
884 // don't call the function that deletes it, so we do so ourselves.
885 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
886 info->prompt_user_for_save_location = false;
887 info->url_chain.push_back(GURL());
888 info->total_bytes = static_cast<int64>(kTestDataLen);
889 const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
890 const FilePath cr_path(GetTempDownloadPath(new_path));
891
892 MockDownloadFile* download_file(new NiceMock<MockDownloadFile>());
893
894 EXPECT_CALL(*download_file, Rename(cr_path))
895 .WillOnce(Return(net::OK));
896 EXPECT_CALL(*download_file, Cancel());
897
898 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
899 // |download_file| is owned by DownloadFileManager.
900 AddMockDownloadToFileManager(info->download_id, download_file);
901
902 DownloadItem* download = GetActiveDownloadItem(info->download_id);
903 ASSERT_TRUE(download != NULL);
904 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
905 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
906
907 ContinueDownloadWithPath(download, new_path);
908 message_loop_.RunAllPending();
909 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) != NULL);
910
911 int64 error_size = 3;
912 OnDownloadInterrupted(info->download_id, error_size, "",
913 content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
914 message_loop_.RunAllPending();
915
916 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) == NULL);
917 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
918 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
919 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
920 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
921 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
922 EXPECT_TRUE(observer->was_updated());
923 EXPECT_FALSE(observer->was_opened());
924 EXPECT_FALSE(download->GetFileExternallyRemoved());
925 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
926
927 download->Cancel(true);
928
929 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
930 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
931 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
932 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
933 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
934 EXPECT_TRUE(observer->was_updated());
935 EXPECT_FALSE(observer->was_opened());
936 EXPECT_FALSE(download->GetFileExternallyRemoved());
937 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
938 EXPECT_EQ(download->GetReceivedBytes(), error_size);
939 EXPECT_EQ(download->GetTotalBytes(), static_cast<int64>(kTestDataLen));
940 }
941
942 // Test the behavior of DownloadFileManager and DownloadManager in the event
943 // of a file error while writing the download to disk.
944 TEST_F(DownloadManagerTest, MAYBE_DownloadFileErrorTest) {
945 // Create a temporary file and a mock stream.
946 FilePath path;
947 ASSERT_TRUE(file_util::CreateTemporaryFile(&path));
948
949 // This file stream will be used, until the first rename occurs.
950 net::FileStream* stream = new net::FileStream(NULL);
951 ASSERT_EQ(0, stream->OpenSync(
952 path,
953 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE));
954
955 // Make sure the DFM exists; we'll need it later.
956 // TODO(rdsmith): This is ugly and should be rewritten, but a large
957 // rewrite of this test is in progress in a different CL, so doing it
958 // the hacky way for now.
959 (void) file_manager();
960
961 // Normally, the download system takes ownership of info, and is
962 // responsible for deleting it. In these unit tests, however, we
963 // don't call the function that deletes it, so we do so ourselves.
964 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
965 info->prompt_user_for_save_location = false;
966 info->url_chain.push_back(GURL());
967 info->total_bytes = static_cast<int64>(kTestDataLen * 3);
968 info->save_info.file_path = path;
969 info->save_info.file_stream.reset(stream);
970 scoped_ptr<content::ByteStreamWriter> stream_input;
971 scoped_ptr<content::ByteStreamReader> stream_output;
972 content::CreateByteStream(message_loop_.message_loop_proxy(),
973 message_loop_.message_loop_proxy(),
974 kTestDataLen, &stream_input, &stream_output);
975
976 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
977
978 // Create a download file that we can insert errors into.
979 scoped_ptr<DownloadFileWithErrors> download_file(new DownloadFileWithErrors(
980 info.get(), stream_output.Pass(), download_manager_, false));
981 download_file->Initialize();
982
983 DownloadItem* download = GetActiveDownloadItem(info->download_id);
984 ASSERT_TRUE(download != NULL);
985
986 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
987 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
988
989 // Add some data before finalizing the file name.
990 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
991
992 // Finalize the file name.
993 ContinueDownloadWithPath(download, path);
994 message_loop_.RunAllPending();
995 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) != NULL);
996
997 // Add more data.
998 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
999
1000 // Add more data, but an error occurs.
1001 download_file->set_forced_error(net::ERR_FAILED);
1002 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1003 message_loop_.RunAllPending();
1004
1005 // Check the state. The download should have been interrupted.
1006 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) == NULL);
1007 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1008 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED));
1009 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
1010 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1011 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1012 EXPECT_TRUE(observer->was_updated());
1013 EXPECT_FALSE(observer->was_opened());
1014 EXPECT_FALSE(download->GetFileExternallyRemoved());
1015 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1016
1017 // Clean up.
1018 download->Cancel(true);
1019 message_loop_.RunAllPending();
1020 }
1021
1022 TEST_F(DownloadManagerTest, DownloadCancelTest) {
1023 using ::testing::_;
1024 using ::testing::CreateFunctor;
1025 using ::testing::Invoke;
1026 using ::testing::Return;
1027
1028 // Normally, the download system takes ownership of info, and is
1029 // responsible for deleting it. In these unit tests, however, we
1030 // don't call the function that deletes it, so we do so ourselves.
1031 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
1032 info->prompt_user_for_save_location = false;
1033 info->url_chain.push_back(GURL());
1034 const FilePath new_path(FILE_PATH_LITERAL("foo.zip"));
1035 const FilePath cr_path(GetTempDownloadPath(new_path));
1036
1037 MockDownloadFile* download_file(new NiceMock<MockDownloadFile>());
1038
1039 // |download_file| is owned by DownloadFileManager.
1040 EXPECT_CALL(*download_file, Rename(cr_path))
1041 .WillOnce(Return(net::OK));
1042 EXPECT_CALL(*download_file, Cancel());
1043
1044 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
1045 AddMockDownloadToFileManager(info->download_id, download_file);
1046
1047 DownloadItem* download = GetActiveDownloadItem(info->download_id);
1048 ASSERT_TRUE(download != NULL);
1049
1050 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1051 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
1052
1053 ContinueDownloadWithPath(download, new_path);
1054 message_loop_.RunAllPending();
1055 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) != NULL);
1056
1057 download->Cancel(false);
1058 message_loop_.RunAllPending();
1059
1060 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) != NULL);
1061 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1062 EXPECT_TRUE(observer->hit_state(DownloadItem::CANCELLED));
1063 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1064 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE));
1065 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1066 EXPECT_TRUE(observer->was_updated());
1067 EXPECT_FALSE(observer->was_opened());
1068 EXPECT_FALSE(download->GetFileExternallyRemoved());
1069 EXPECT_EQ(DownloadItem::CANCELLED, download->GetState());
1070
1071 file_manager()->CancelDownload(info->download_id);
1072
1073 EXPECT_FALSE(file_util::PathExists(new_path));
1074 EXPECT_FALSE(file_util::PathExists(cr_path));
1075 }
1076
1077 TEST_F(DownloadManagerTest, MAYBE_DownloadOverwriteTest) {
1078 using ::testing::_;
1079 using ::testing::CreateFunctor;
1080 using ::testing::Invoke;
1081 using ::testing::Return;
1082
1083 ASSERT_TRUE(CreateTempDownloadsDirectory());
1084 // File names we're using.
1085 const FilePath new_path(GetPathInDownloadsDir(FILE_PATH_LITERAL("foo.txt")));
1086 const FilePath cr_path(GetTempDownloadPath(new_path));
1087 EXPECT_FALSE(file_util::PathExists(new_path));
1088
1089 // Create the file that we will overwrite. Will be automatically cleaned
1090 // up when temp_dir_ is destroyed.
1091 FILE* fp = file_util::OpenFile(new_path, "w");
1092 file_util::CloseFile(fp);
1093 EXPECT_TRUE(file_util::PathExists(new_path));
1094
1095 // Construct the unique file name that normally would be created, but
1096 // which we will override.
1097 int uniquifier =
1098 file_util::GetUniquePathNumber(new_path, FILE_PATH_LITERAL(""));
1099 FilePath unique_new_path = new_path;
1100 EXPECT_NE(0, uniquifier);
1101 unique_new_path = unique_new_path.InsertBeforeExtensionASCII(
1102 StringPrintf(" (%d)", uniquifier));
1103
1104 // Normally, the download system takes ownership of info, and is
1105 // responsible for deleting it. In these unit tests, however, we
1106 // don't call the function that deletes it, so we do so ourselves.
1107 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
1108 info->prompt_user_for_save_location = true;
1109 info->url_chain.push_back(GURL());
1110 scoped_ptr<content::ByteStreamWriter> stream_input;
1111 scoped_ptr<content::ByteStreamReader> stream_output;
1112 content::CreateByteStream(message_loop_.message_loop_proxy(),
1113 message_loop_.message_loop_proxy(),
1114 kTestDataLen, &stream_input, &stream_output);
1115
1116 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
1117
1118 DownloadItem* download = GetActiveDownloadItem(info->download_id);
1119 ASSERT_TRUE(download != NULL);
1120
1121 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1122 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
1123
1124 // Create and initialize the download file. We're bypassing the first part
1125 // of the download process and skipping to the part after the final file
1126 // name has been chosen, so we need to initialize the download file
1127 // properly.
1128 DownloadFile* download_file(
1129 new DownloadFileImpl(info.get(), stream_output.Pass(),
1130 new DownloadRequestHandle(),
1131 download_manager_, false,
1132 scoped_ptr<content::PowerSaveBlocker>(NULL).Pass(),
1133 net::BoundNetLog()));
1134 download_file->Rename(cr_path);
1135 // This creates the .temp version of the file.
1136 download_file->Initialize();
1137 // |download_file| is owned by DownloadFileManager.
1138 AddDownloadToFileManager(info->download_id, download_file);
1139
1140 ContinueDownloadWithPath(download, new_path);
1141 message_loop_.RunAllPending();
1142 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) != NULL);
1143
1144 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1145
1146 // Finish the download.
1147 OnResponseCompleted(info->download_id, kTestDataLen, "");
1148 message_loop_.RunAllPending();
1149
1150 // Download is complete.
1151 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) == NULL);
1152 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1153 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1154 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1155 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
1156 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1157 EXPECT_TRUE(observer->was_updated());
1158 EXPECT_FALSE(observer->was_opened());
1159 EXPECT_FALSE(download->GetFileExternallyRemoved());
1160 EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
1161
1162 EXPECT_TRUE(file_util::PathExists(new_path));
1163 EXPECT_FALSE(file_util::PathExists(cr_path));
1164 EXPECT_FALSE(file_util::PathExists(unique_new_path));
1165 std::string file_contents;
1166 EXPECT_TRUE(file_util::ReadFileToString(new_path, &file_contents));
1167 EXPECT_EQ(std::string(kTestData), file_contents);
1168 }
1169
1170 TEST_F(DownloadManagerTest, MAYBE_DownloadRemoveTest) {
1171 using ::testing::_;
1172 using ::testing::CreateFunctor;
1173 using ::testing::Invoke;
1174 using ::testing::Return;
1175
1176 ASSERT_TRUE(CreateTempDownloadsDirectory());
1177
1178 // File names we're using.
1179 const FilePath new_path(GetPathInDownloadsDir(FILE_PATH_LITERAL("foo.txt")));
1180 const FilePath cr_path(GetTempDownloadPath(new_path));
1181 EXPECT_FALSE(file_util::PathExists(new_path));
1182
1183 // Normally, the download system takes ownership of info, and is
1184 // responsible for deleting it. In these unit tests, however, we
1185 // don't call the function that deletes it, so we do so ourselves.
1186 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
1187 info->prompt_user_for_save_location = true;
1188 info->url_chain.push_back(GURL());
1189 scoped_ptr<content::ByteStreamWriter> stream_input;
1190 scoped_ptr<content::ByteStreamReader> stream_output;
1191 content::CreateByteStream(message_loop_.message_loop_proxy(),
1192 message_loop_.message_loop_proxy(),
1193 kTestDataLen, &stream_input, &stream_output);
1194
1195 download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
1196
1197 DownloadItem* download = GetActiveDownloadItem(info->download_id);
1198 ASSERT_TRUE(download != NULL);
1199
1200 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1201 scoped_ptr<ItemObserver> observer(new ItemObserver(download));
1202
1203 // Create and initialize the download file. We're bypassing the first part
1204 // of the download process and skipping to the part after the final file
1205 // name has been chosen, so we need to initialize the download file
1206 // properly.
1207 DownloadFile* download_file(
1208 new DownloadFileImpl(info.get(), stream_output.Pass(),
1209 new DownloadRequestHandle(),
1210 download_manager_, false,
1211 scoped_ptr<content::PowerSaveBlocker>(NULL).Pass(),
1212 net::BoundNetLog()));
1213 download_file->Rename(cr_path);
1214 // This creates the .temp version of the file.
1215 download_file->Initialize();
1216 // |download_file| is owned by DownloadFileManager.
1217 AddDownloadToFileManager(info->download_id, download_file);
1218
1219 ContinueDownloadWithPath(download, new_path);
1220 message_loop_.RunAllPending();
1221 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) != NULL);
1222
1223 WriteCopyToStream(kTestData, kTestDataLen, stream_input.get());
1224
1225 // Finish the download.
1226 OnResponseCompleted(info->download_id, kTestDataLen, "");
1227 message_loop_.RunAllPending();
1228
1229 // Download is complete.
1230 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) == NULL);
1231 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1232 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1233 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1234 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
1235 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1236 EXPECT_TRUE(observer->was_updated());
1237 EXPECT_FALSE(observer->was_opened());
1238 EXPECT_FALSE(download->GetFileExternallyRemoved());
1239 EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
1240
1241 EXPECT_TRUE(file_util::PathExists(new_path));
1242 EXPECT_FALSE(file_util::PathExists(cr_path));
1243
1244 // Remove the downloaded file.
1245 ASSERT_TRUE(file_util::Delete(new_path, false));
1246 download->OnDownloadedFileRemoved();
1247 message_loop_.RunAllPending();
1248
1249 EXPECT_TRUE(GetActiveDownloadItem(info->download_id) == NULL);
1250 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS));
1251 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED));
1252 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED));
1253 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE));
1254 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING));
1255 EXPECT_TRUE(observer->was_updated());
1256 EXPECT_FALSE(observer->was_opened());
1257 EXPECT_TRUE(download->GetFileExternallyRemoved());
1258 EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
1259
1260 EXPECT_FALSE(file_util::PathExists(new_path));
1261 }
OLDNEW
« no previous file with comments | « content/browser/download/download_manager_impl.cc ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698