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