OLD | NEW |
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 "content/browser/download/download_file_manager.h" | 5 #include "content/browser/download/download_file_manager.h" |
6 | 6 |
7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/scoped_temp_dir.h" | 10 #include "base/scoped_temp_dir.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 using content::BrowserThread; | 25 using content::BrowserThread; |
26 using content::BrowserThreadImpl; | 26 using content::BrowserThreadImpl; |
27 using content::DownloadId; | 27 using content::DownloadId; |
28 using content::MockDownloadManager; | 28 using content::MockDownloadManager; |
29 | 29 |
30 using ::testing::_; | 30 using ::testing::_; |
31 using ::testing::AtLeast; | 31 using ::testing::AtLeast; |
32 using ::testing::Mock; | 32 using ::testing::Mock; |
33 using ::testing::Return; | 33 using ::testing::Return; |
34 using ::testing::SaveArg; | |
35 using ::testing::StrictMock; | 34 using ::testing::StrictMock; |
36 using ::testing::StrEq; | 35 using ::testing::StrEq; |
37 | 36 |
38 namespace { | 37 namespace { |
39 | 38 |
40 // MockDownloadManager with the addition of a mock callback used for testing. | 39 // MockDownloadManager with the addition of a mock callback used for testing. |
41 class TestDownloadManager : public MockDownloadManager { | 40 class TestDownloadManager : public MockDownloadManager { |
42 public: | 41 public: |
43 MOCK_METHOD3(OnDownloadRenamed, | 42 MOCK_METHOD2(OnDownloadRenamed, |
44 void(int download_id, | 43 void(int download_id, const FilePath& full_path)); |
45 content::DownloadInterruptReason reason, | |
46 const FilePath& full_path)); | |
47 private: | 44 private: |
48 ~TestDownloadManager() {} | 45 ~TestDownloadManager() {} |
49 }; | 46 }; |
50 | 47 |
51 class MockDownloadFileFactory : | 48 class MockDownloadFileFactory : |
52 public DownloadFileManager::DownloadFileFactory { | 49 public DownloadFileManager::DownloadFileFactory { |
53 | 50 |
54 public: | 51 public: |
55 MockDownloadFileFactory() {} | 52 MockDownloadFileFactory() {} |
56 virtual ~MockDownloadFileFactory() {} | 53 virtual ~MockDownloadFileFactory() {} |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 // renamed to. If there is an existing file at | 205 // renamed to. If there is an existing file at |
209 // |new_path| and |replace| is false, then |new_path| | 206 // |new_path| and |replace| is false, then |new_path| |
210 // will be uniquified. | 207 // will be uniquified. |
211 // |rename_error| is the error to inject. For no error, | 208 // |rename_error| is the error to inject. For no error, |
212 // use content::DOWNLOAD_INTERRUPT_REASON_NONE. | 209 // use content::DOWNLOAD_INTERRUPT_REASON_NONE. |
213 // |state| whether we are renaming an in-progress download or a | 210 // |state| whether we are renaming an in-progress download or a |
214 // completed download. | 211 // completed download. |
215 // |should_overwrite| indicates whether to replace or uniquify the file. | 212 // |should_overwrite| indicates whether to replace or uniquify the file. |
216 void RenameFile(const DownloadId& id, | 213 void RenameFile(const DownloadId& id, |
217 const FilePath& new_path, | 214 const FilePath& new_path, |
218 bool should_overwrite) { | 215 const FilePath& unique_path, |
| 216 content::DownloadInterruptReason rename_error, |
| 217 RenameFileState state, |
| 218 RenameFileOverwrite should_overwrite) { |
219 MockDownloadFile* file = download_file_factory_->GetExistingFile(id); | 219 MockDownloadFile* file = download_file_factory_->GetExistingFile(id); |
220 ASSERT_TRUE(file != NULL); | 220 ASSERT_TRUE(file != NULL); |
221 content::DownloadFile::RenameCompletionCallback rename_callback; | |
222 | 221 |
223 EXPECT_CALL(*file, Rename(new_path, should_overwrite, _)) | 222 EXPECT_CALL(*file, Rename(unique_path)) |
224 .WillOnce(SaveArg<2>(&rename_callback)); | 223 .Times(1) |
| 224 .WillOnce(Return(rename_error)); |
225 | 225 |
226 content::DownloadFile::RenameCompletionCallback passed_callback( | 226 if (rename_error != content::DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 227 EXPECT_CALL(*file, BytesSoFar()) |
| 228 .Times(AtLeast(1)) |
| 229 .WillRepeatedly(Return(byte_count_[id])); |
| 230 EXPECT_CALL(*file, GetHashState()) |
| 231 .Times(AtLeast(1)); |
| 232 EXPECT_CALL(*file, GetDownloadManager()) |
| 233 .Times(AtLeast(1)); |
| 234 } |
| 235 |
| 236 download_file_manager_->RenameDownloadFile( |
| 237 id, new_path, (should_overwrite == OVERWRITE), |
227 base::Bind(&TestDownloadManager::OnDownloadRenamed, | 238 base::Bind(&TestDownloadManager::OnDownloadRenamed, |
228 download_manager_, id.local())); | 239 download_manager_, id.local())); |
229 | 240 |
230 download_file_manager_->RenameDownloadFile( | 241 if (rename_error != content::DOWNLOAD_INTERRUPT_REASON_NONE) { |
231 id, new_path, should_overwrite, passed_callback); | 242 EXPECT_CALL(*download_manager_, |
232 | 243 OnDownloadInterrupted( |
233 EXPECT_TRUE(rename_callback.Equals(passed_callback)); | 244 id.local(), |
| 245 byte_count_[id], |
| 246 "", |
| 247 rename_error)); |
| 248 EXPECT_CALL(*download_manager_, |
| 249 OnDownloadRenamed(id.local(), FilePath())); |
| 250 ProcessAllPendingMessages(); |
| 251 ++error_count_[id]; |
| 252 } else { |
| 253 EXPECT_CALL(*download_manager_, |
| 254 OnDownloadRenamed(id.local(), unique_path)); |
| 255 ProcessAllPendingMessages(); |
| 256 } |
234 } | 257 } |
235 | 258 |
236 void Complete(DownloadId id) { | 259 void Complete(DownloadId id) { |
237 MockDownloadFile* file = download_file_factory_->GetExistingFile(id); | 260 MockDownloadFile* file = download_file_factory_->GetExistingFile(id); |
238 ASSERT_TRUE(file != NULL); | 261 ASSERT_TRUE(file != NULL); |
239 | 262 |
240 EXPECT_CALL(*file, AnnotateWithSourceInformation()) | 263 EXPECT_CALL(*file, AnnotateWithSourceInformation()) |
241 .WillOnce(Return()); | 264 .WillOnce(Return()); |
242 EXPECT_CALL(*file, Detach()) | 265 EXPECT_CALL(*file, Detach()) |
243 .WillOnce(Return()); | 266 .WillOnce(Return()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 TEST_F(DownloadFileManagerTest, Complete) { | 338 TEST_F(DownloadFileManagerTest, Complete) { |
316 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); | 339 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
317 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); | 340 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); |
318 info->download_id = dummy_id; | 341 info->download_id = dummy_id; |
319 | 342 |
320 CreateDownloadFile(info.Pass()); | 343 CreateDownloadFile(info.Pass()); |
321 | 344 |
322 Complete(dummy_id); | 345 Complete(dummy_id); |
323 } | 346 } |
324 | 347 |
325 TEST_F(DownloadFileManagerTest, Rename) { | 348 TEST_F(DownloadFileManagerTest, RenameInProgress) { |
326 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); | 349 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
327 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); | 350 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); |
328 info->download_id = dummy_id; | 351 info->download_id = dummy_id; |
329 ScopedTempDir download_dir; | 352 ScopedTempDir download_dir; |
330 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); | 353 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); |
331 | 354 |
332 CreateDownloadFile(info.Pass()); | 355 CreateDownloadFile(info.Pass()); |
333 | 356 |
334 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); | 357 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); |
335 RenameFile(dummy_id, foo, true); | 358 RenameFile(dummy_id, foo, foo, content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 359 IN_PROGRESS, OVERWRITE); |
336 | 360 |
337 CleanUp(dummy_id); | 361 CleanUp(dummy_id); |
338 } | 362 } |
339 | 363 |
340 TEST_F(DownloadFileManagerTest, RenameNoOverwrite) { | 364 TEST_F(DownloadFileManagerTest, RenameInProgressWithUniquification) { |
341 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); | 365 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
342 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); | 366 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); |
343 info->download_id = dummy_id; | 367 info->download_id = dummy_id; |
344 ScopedTempDir download_dir; | 368 ScopedTempDir download_dir; |
345 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); | 369 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); |
346 | 370 |
347 CreateDownloadFile(info.Pass()); | 371 CreateDownloadFile(info.Pass()); |
348 | 372 |
349 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); | 373 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); |
350 RenameFile(dummy_id, foo, false); | 374 FilePath unique_foo(foo.InsertBeforeExtension(FILE_PATH_LITERAL(" (1)"))); |
| 375 ASSERT_EQ(0, file_util::WriteFile(foo, "", 0)); |
| 376 RenameFile(dummy_id, foo, unique_foo, |
| 377 content::DOWNLOAD_INTERRUPT_REASON_NONE, IN_PROGRESS, |
| 378 DONT_OVERWRITE); |
| 379 |
| 380 CleanUp(dummy_id); |
| 381 } |
| 382 |
| 383 TEST_F(DownloadFileManagerTest, RenameInProgressWithError) { |
| 384 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
| 385 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); |
| 386 info->download_id = dummy_id; |
| 387 ScopedTempDir download_dir; |
| 388 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); |
| 389 |
| 390 CreateDownloadFile(info.Pass()); |
| 391 |
| 392 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); |
| 393 RenameFile(dummy_id, foo, foo, |
| 394 content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG, |
| 395 IN_PROGRESS, OVERWRITE); |
| 396 |
| 397 CleanUp(dummy_id); |
| 398 } |
| 399 |
| 400 TEST_F(DownloadFileManagerTest, RenameWithUniquification) { |
| 401 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
| 402 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); |
| 403 info->download_id = dummy_id; |
| 404 ScopedTempDir download_dir; |
| 405 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); |
| 406 |
| 407 CreateDownloadFile(info.Pass()); |
| 408 |
| 409 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); |
| 410 FilePath unique_foo(foo.InsertBeforeExtension(FILE_PATH_LITERAL(" (1)"))); |
| 411 // Create a file at |foo|. Since we are specifying DONT_OVERWRITE, |
| 412 // RenameDownloadFile() should pick "foo (1).txt" instead of |
| 413 // overwriting this file. |
| 414 ASSERT_EQ(0, file_util::WriteFile(foo, "", 0)); |
| 415 RenameFile(dummy_id, foo, unique_foo, |
| 416 content::DOWNLOAD_INTERRUPT_REASON_NONE, COMPLETE, DONT_OVERWRITE); |
351 | 417 |
352 CleanUp(dummy_id); | 418 CleanUp(dummy_id); |
353 } | 419 } |
354 | 420 |
355 TEST_F(DownloadFileManagerTest, RenameTwice) { | 421 TEST_F(DownloadFileManagerTest, RenameTwice) { |
356 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); | 422 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
357 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); | 423 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); |
358 info->download_id = dummy_id; | 424 info->download_id = dummy_id; |
359 ScopedTempDir download_dir; | 425 ScopedTempDir download_dir; |
360 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); | 426 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); |
361 | 427 |
362 CreateDownloadFile(info.Pass()); | 428 CreateDownloadFile(info.Pass()); |
363 | 429 |
364 FilePath crfoo(download_dir.path().Append( | 430 FilePath crfoo(download_dir.path().Append( |
365 FILE_PATH_LITERAL("foo.txt.crdownload"))); | 431 FILE_PATH_LITERAL("foo.txt.crdownload"))); |
366 RenameFile(dummy_id, crfoo, true); | 432 RenameFile(dummy_id, crfoo, crfoo, content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 433 IN_PROGRESS, OVERWRITE); |
367 | 434 |
368 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); | 435 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); |
369 RenameFile(dummy_id, foo, true); | 436 RenameFile(dummy_id, foo, foo, content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 437 COMPLETE, OVERWRITE); |
370 | 438 |
371 CleanUp(dummy_id); | 439 CleanUp(dummy_id); |
372 } | 440 } |
373 | 441 |
374 TEST_F(DownloadFileManagerTest, TwoDownloads) { | 442 TEST_F(DownloadFileManagerTest, TwoDownloads) { |
375 // Same as StartDownload, at first. | 443 // Same as StartDownload, at first. |
376 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); | 444 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); |
377 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); | 445 DownloadId dummy_id(download_manager_.get(), kDummyDownloadId); |
378 info->download_id = dummy_id; | 446 info->download_id = dummy_id; |
379 scoped_ptr<DownloadCreateInfo> info2(new DownloadCreateInfo); | 447 scoped_ptr<DownloadCreateInfo> info2(new DownloadCreateInfo); |
380 DownloadId dummy_id2(download_manager_.get(), kDummyDownloadId2); | 448 DownloadId dummy_id2(download_manager_.get(), kDummyDownloadId2); |
381 info2->download_id = dummy_id2; | 449 info2->download_id = dummy_id2; |
382 ScopedTempDir download_dir; | 450 ScopedTempDir download_dir; |
383 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); | 451 ASSERT_TRUE(download_dir.CreateUniqueTempDir()); |
384 | 452 |
385 CreateDownloadFile(info.Pass()); | 453 CreateDownloadFile(info.Pass()); |
386 CreateDownloadFile(info2.Pass()); | 454 CreateDownloadFile(info2.Pass()); |
387 | 455 |
388 FilePath crbar(download_dir.path().Append( | 456 FilePath crbar(download_dir.path().Append( |
389 FILE_PATH_LITERAL("bar.txt.crdownload"))); | 457 FILE_PATH_LITERAL("bar.txt.crdownload"))); |
390 RenameFile(dummy_id2, crbar, true); | 458 RenameFile(dummy_id2, crbar, crbar, content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 459 IN_PROGRESS, OVERWRITE); |
391 | 460 |
392 FilePath crfoo(download_dir.path().Append( | 461 FilePath crfoo(download_dir.path().Append( |
393 FILE_PATH_LITERAL("foo.txt.crdownload"))); | 462 FILE_PATH_LITERAL("foo.txt.crdownload"))); |
394 RenameFile(dummy_id, crfoo, true); | 463 RenameFile(dummy_id, crfoo, crfoo, content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 464 IN_PROGRESS, OVERWRITE); |
395 | 465 |
396 | 466 |
397 FilePath bar(download_dir.path().Append(FILE_PATH_LITERAL("bar.txt"))); | 467 FilePath bar(download_dir.path().Append(FILE_PATH_LITERAL("bar.txt"))); |
398 RenameFile(dummy_id2, bar, true); | 468 RenameFile(dummy_id2, bar, bar, content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 469 COMPLETE, OVERWRITE); |
399 | 470 |
400 CleanUp(dummy_id2); | 471 CleanUp(dummy_id2); |
401 | 472 |
402 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); | 473 FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt"))); |
403 RenameFile(dummy_id, foo, true); | 474 RenameFile(dummy_id, foo, foo, content::DOWNLOAD_INTERRUPT_REASON_NONE, |
| 475 COMPLETE, OVERWRITE); |
404 | 476 |
405 CleanUp(dummy_id); | 477 CleanUp(dummy_id); |
406 } | 478 } |
407 | 479 |
408 // TODO(ahendrickson) -- A test for download manager shutdown. | 480 // TODO(ahendrickson) -- A test for download manager shutdown. |
409 // Expected call sequence: | 481 // Expected call sequence: |
410 // OnDownloadManagerShutdown | 482 // OnDownloadManagerShutdown |
411 // DownloadFile::GetDownloadManager | 483 // DownloadFile::GetDownloadManager |
412 // DownloadFile::CancelDownloadRequest | 484 // DownloadFile::CancelDownloadRequest |
413 // DownloadFile::~DownloadFile | 485 // DownloadFile::~DownloadFile |
OLD | NEW |