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 3 // found in the LICENSE file. 4 5 // This file contains download browser tests that are known to be runnable 6 // in a pure content context. Over time tests should be migrated here. 7 8 #include "base/command_line.h" 9 #include "base/files/file_path.h" 10 #include "base/files/file_util.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/strings/stringprintf.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/threading/platform_thread.h" 16 #include "base/time/time.h" 17 #include "content/browser/byte_stream.h" 18 #include "content/browser/download/download_file_factory.h" 19 #include "content/browser/download/download_file_impl.h" 20 #include "content/browser/download/download_item_impl.h" 21 #include "content/browser/download/download_manager_impl.h" 22 #include "content/browser/download/download_resource_handler.h" 23 #include "content/browser/web_contents/web_contents_impl.h" 24 #include "content/public/browser/power_save_blocker.h" 25 #include "content/public/common/content_switches.h" 26 #include "content/public/common/webplugininfo.h" 27 #include "content/public/test/browser_test_utils.h" 28 #include "content/public/test/content_browser_test.h" 29 #include "content/public/test/content_browser_test_utils.h" 30 #include "content/public/test/download_test_observer.h" 31 #include "content/public/test/test_file_error_injector.h" 32 #include "content/public/test/test_utils.h" 33 #include "content/shell/browser/shell.h" 34 #include "content/shell/browser/shell_browser_context.h" 35 #include "content/shell/browser/shell_download_manager_delegate.h" 36 #include "content/shell/browser/shell_network_delegate.h" 37 #include "content/test/net/url_request_slow_download_job.h" 38 #include "net/test/embedded_test_server/embedded_test_server.h" 39 #include "net/test/embedded_test_server/http_request.h" 40 #include "net/test/embedded_test_server/http_response.h" 41 #include "net/test/spawned_test_server/spawned_test_server.h" 42 #include "net/test/url_request/url_request_mock_http_job.h" 43 #include "testing/gmock/include/gmock/gmock.h" 44 #include "testing/gtest/include/gtest/gtest.h" 45 #include "url/gurl.h" 46 47 #if defined(ENABLE_PLUGINS) 48 #include "content/browser/plugin_service_impl.h" 49 #endif 50 51 using ::net::test_server::EmbeddedTestServer; 52 using ::testing::AllOf; 53 using ::testing::Field; 54 using ::testing::InSequence; 55 using ::testing::Property; 56 using ::testing::Return; 57 using ::testing::StrictMock; 58 using ::testing::_; 59 60 namespace content { 61 62 namespace { 63 64 class MockDownloadItemObserver : public DownloadItem::Observer { 65 public: 66 MockDownloadItemObserver() {} 67 virtual ~MockDownloadItemObserver() {} 68 69 MOCK_METHOD1(OnDownloadUpdated, void(DownloadItem*)); 70 MOCK_METHOD1(OnDownloadOpened, void(DownloadItem*)); 71 MOCK_METHOD1(OnDownloadRemoved, void(DownloadItem*)); 72 MOCK_METHOD1(OnDownloadDestroyed, void(DownloadItem*)); 73 }; 74 75 class MockDownloadManagerObserver : public DownloadManager::Observer { 76 public: 77 MockDownloadManagerObserver(DownloadManager* manager) { 78 manager_ = manager; 79 manager->AddObserver(this); 80 } 81 virtual ~MockDownloadManagerObserver() { 82 if (manager_) 83 manager_->RemoveObserver(this); 84 } 85 86 MOCK_METHOD2(OnDownloadCreated, void(DownloadManager*, DownloadItem*)); 87 MOCK_METHOD1(ModelChanged, void(DownloadManager*)); 88 void ManagerGoingDown(DownloadManager* manager) { 89 DCHECK_EQ(manager_, manager); 90 MockManagerGoingDown(manager); 91 92 manager_->RemoveObserver(this); 93 manager_ = NULL; 94 } 95 96 MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*)); 97 private: 98 DownloadManager* manager_; 99 }; 100 101 class DownloadFileWithDelayFactory; 102 103 static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) { 104 // We're in a content_browsertest; we know that the DownloadManager 105 // is a DownloadManagerImpl. 106 return static_cast<DownloadManagerImpl*>( 107 BrowserContext::GetDownloadManager( 108 shell->web_contents()->GetBrowserContext())); 109 } 110 111 class DownloadFileWithDelay : public DownloadFileImpl { 112 public: 113 DownloadFileWithDelay( 114 scoped_ptr<DownloadSaveInfo> save_info, 115 const base::FilePath& default_download_directory, 116 const GURL& url, 117 const GURL& referrer_url, 118 bool calculate_hash, 119 scoped_ptr<ByteStreamReader> stream, 120 const net::BoundNetLog& bound_net_log, 121 scoped_ptr<PowerSaveBlocker> power_save_blocker, 122 base::WeakPtr<DownloadDestinationObserver> observer, 123 base::WeakPtr<DownloadFileWithDelayFactory> owner); 124 125 virtual ~DownloadFileWithDelay(); 126 127 // Wraps DownloadFileImpl::Rename* and intercepts the return callback, 128 // storing it in the factory that produced this object for later 129 // retrieval. 130 virtual void RenameAndUniquify( 131 const base::FilePath& full_path, 132 const RenameCompletionCallback& callback) OVERRIDE; 133 virtual void RenameAndAnnotate( 134 const base::FilePath& full_path, 135 const RenameCompletionCallback& callback) OVERRIDE; 136 137 private: 138 static void RenameCallbackWrapper( 139 const base::WeakPtr<DownloadFileWithDelayFactory>& factory, 140 const RenameCompletionCallback& original_callback, 141 DownloadInterruptReason reason, 142 const base::FilePath& path); 143 144 // This variable may only be read on the FILE thread, and may only be 145 // indirected through (e.g. methods on DownloadFileWithDelayFactory called) 146 // on the UI thread. This is because after construction, 147 // DownloadFileWithDelay lives on the file thread, but 148 // DownloadFileWithDelayFactory is purely a UI thread object. 149 base::WeakPtr<DownloadFileWithDelayFactory> owner_; 150 151 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay); 152 }; 153 154 // All routines on this class must be called on the UI thread. 155 class DownloadFileWithDelayFactory : public DownloadFileFactory { 156 public: 157 DownloadFileWithDelayFactory(); 158 virtual ~DownloadFileWithDelayFactory(); 159 160 // DownloadFileFactory interface. 161 virtual DownloadFile* CreateFile( 162 scoped_ptr<DownloadSaveInfo> save_info, 163 const base::FilePath& default_download_directory, 164 const GURL& url, 165 const GURL& referrer_url, 166 bool calculate_hash, 167 scoped_ptr<ByteStreamReader> stream, 168 const net::BoundNetLog& bound_net_log, 169 base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE; 170 171 void AddRenameCallback(base::Closure callback); 172 void GetAllRenameCallbacks(std::vector<base::Closure>* results); 173 174 // Do not return until GetAllRenameCallbacks() will return a non-empty list. 175 void WaitForSomeCallback(); 176 177 private: 178 base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_; 179 std::vector<base::Closure> rename_callbacks_; 180 bool waiting_; 181 182 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory); 183 }; 184 185 DownloadFileWithDelay::DownloadFileWithDelay( 186 scoped_ptr<DownloadSaveInfo> save_info, 187 const base::FilePath& default_download_directory, 188 const GURL& url, 189 const GURL& referrer_url, 190 bool calculate_hash, 191 scoped_ptr<ByteStreamReader> stream, 192 const net::BoundNetLog& bound_net_log, 193 scoped_ptr<PowerSaveBlocker> power_save_blocker, 194 base::WeakPtr<DownloadDestinationObserver> observer, 195 base::WeakPtr<DownloadFileWithDelayFactory> owner) 196 : DownloadFileImpl( 197 save_info.Pass(), default_download_directory, url, referrer_url, 198 calculate_hash, stream.Pass(), bound_net_log, observer), 199 owner_(owner) {} 200 201 DownloadFileWithDelay::~DownloadFileWithDelay() {} 202 203 void DownloadFileWithDelay::RenameAndUniquify( 204 const base::FilePath& full_path, 205 const RenameCompletionCallback& callback) { 206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 207 DownloadFileImpl::RenameAndUniquify( 208 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper, 209 owner_, callback)); 210 } 211 212 void DownloadFileWithDelay::RenameAndAnnotate( 213 const base::FilePath& full_path, const RenameCompletionCallback& callback) { 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 215 DownloadFileImpl::RenameAndAnnotate( 216 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper, 217 owner_, callback)); 218 } 219 220 // static 221 void DownloadFileWithDelay::RenameCallbackWrapper( 222 const base::WeakPtr<DownloadFileWithDelayFactory>& factory, 223 const RenameCompletionCallback& original_callback, 224 DownloadInterruptReason reason, 225 const base::FilePath& path) { 226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 227 if (!factory) 228 return; 229 factory->AddRenameCallback(base::Bind(original_callback, reason, path)); 230 } 231 232 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory() 233 : weak_ptr_factory_(this), 234 waiting_(false) {} 235 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {} 236 237 DownloadFile* DownloadFileWithDelayFactory::CreateFile( 238 scoped_ptr<DownloadSaveInfo> save_info, 239 const base::FilePath& default_download_directory, 240 const GURL& url, 241 const GURL& referrer_url, 242 bool calculate_hash, 243 scoped_ptr<ByteStreamReader> stream, 244 const net::BoundNetLog& bound_net_log, 245 base::WeakPtr<DownloadDestinationObserver> observer) { 246 scoped_ptr<PowerSaveBlocker> psb( 247 PowerSaveBlocker::Create( 248 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, 249 "Download in progress")); 250 return new DownloadFileWithDelay( 251 save_info.Pass(), default_download_directory, url, referrer_url, 252 calculate_hash, stream.Pass(), bound_net_log, 253 psb.Pass(), observer, weak_ptr_factory_.GetWeakPtr()); 254 } 255 256 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) { 257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 258 rename_callbacks_.push_back(callback); 259 if (waiting_) 260 base::MessageLoopForUI::current()->Quit(); 261 } 262 263 void DownloadFileWithDelayFactory::GetAllRenameCallbacks( 264 std::vector<base::Closure>* results) { 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 266 results->swap(rename_callbacks_); 267 } 268 269 void DownloadFileWithDelayFactory::WaitForSomeCallback() { 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 271 272 if (rename_callbacks_.empty()) { 273 waiting_ = true; 274 RunMessageLoop(); 275 waiting_ = false; 276 } 277 } 278 279 class CountingDownloadFile : public DownloadFileImpl { 280 public: 281 CountingDownloadFile( 282 scoped_ptr<DownloadSaveInfo> save_info, 283 const base::FilePath& default_downloads_directory, 284 const GURL& url, 285 const GURL& referrer_url, 286 bool calculate_hash, 287 scoped_ptr<ByteStreamReader> stream, 288 const net::BoundNetLog& bound_net_log, 289 scoped_ptr<PowerSaveBlocker> power_save_blocker, 290 base::WeakPtr<DownloadDestinationObserver> observer) 291 : DownloadFileImpl(save_info.Pass(), default_downloads_directory, 292 url, referrer_url, calculate_hash, 293 stream.Pass(), bound_net_log, observer) {} 294 295 virtual ~CountingDownloadFile() { 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 297 active_files_--; 298 } 299 300 virtual void Initialize(const InitializeCallback& callback) OVERRIDE { 301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 302 active_files_++; 303 return DownloadFileImpl::Initialize(callback); 304 } 305 306 static void GetNumberActiveFiles(int* result) { 307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 308 *result = active_files_; 309 } 310 311 // Can be called on any thread, and will block (running message loop) 312 // until data is returned. 313 static int GetNumberActiveFilesFromFileThread() { 314 int result = -1; 315 BrowserThread::PostTaskAndReply( 316 BrowserThread::FILE, 317 FROM_HERE, 318 base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result), 319 base::MessageLoop::current()->QuitClosure()); 320 base::MessageLoop::current()->Run(); 321 DCHECK_NE(-1, result); 322 return result; 323 } 324 325 private: 326 static int active_files_; 327 }; 328 329 int CountingDownloadFile::active_files_ = 0; 330 331 class CountingDownloadFileFactory : public DownloadFileFactory { 332 public: 333 CountingDownloadFileFactory() {} 334 virtual ~CountingDownloadFileFactory() {} 335 336 // DownloadFileFactory interface. 337 virtual DownloadFile* CreateFile( 338 scoped_ptr<DownloadSaveInfo> save_info, 339 const base::FilePath& default_downloads_directory, 340 const GURL& url, 341 const GURL& referrer_url, 342 bool calculate_hash, 343 scoped_ptr<ByteStreamReader> stream, 344 const net::BoundNetLog& bound_net_log, 345 base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE { 346 scoped_ptr<PowerSaveBlocker> psb( 347 PowerSaveBlocker::Create( 348 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, 349 "Download in progress")); 350 return new CountingDownloadFile( 351 save_info.Pass(), default_downloads_directory, url, referrer_url, 352 calculate_hash, stream.Pass(), bound_net_log, 353 psb.Pass(), observer); 354 } 355 }; 356 357 class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate { 358 public: 359 TestShellDownloadManagerDelegate() 360 : delay_download_open_(false) {} 361 virtual ~TestShellDownloadManagerDelegate() {} 362 363 virtual bool ShouldOpenDownload( 364 DownloadItem* item, 365 const DownloadOpenDelayedCallback& callback) OVERRIDE { 366 if (delay_download_open_) { 367 delayed_callbacks_.push_back(callback); 368 return false; 369 } 370 return true; 371 } 372 373 void SetDelayedOpen(bool delay) { 374 delay_download_open_ = delay; 375 } 376 377 void GetDelayedCallbacks( 378 std::vector<DownloadOpenDelayedCallback>* callbacks) { 379 callbacks->swap(delayed_callbacks_); 380 } 381 private: 382 bool delay_download_open_; 383 std::vector<DownloadOpenDelayedCallback> delayed_callbacks_; 384 }; 385 386 // Record all state transitions and byte counts on the observed download. 387 class RecordingDownloadObserver : DownloadItem::Observer { 388 public: 389 struct RecordStruct { 390 DownloadItem::DownloadState state; 391 int bytes_received; 392 }; 393 394 typedef std::vector<RecordStruct> RecordVector; 395 396 RecordingDownloadObserver(DownloadItem* download) 397 : download_(download) { 398 last_state_.state = download->GetState(); 399 last_state_.bytes_received = download->GetReceivedBytes(); 400 download_->AddObserver(this); 401 } 402 403 virtual ~RecordingDownloadObserver() { 404 RemoveObserver(); 405 } 406 407 void CompareToExpectedRecord(const RecordStruct expected[], size_t size) { 408 EXPECT_EQ(size, record_.size()); 409 int min = size > record_.size() ? record_.size() : size; 410 for (int i = 0; i < min; ++i) { 411 EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i; 412 EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received) 413 << "Iteration " << i; 414 } 415 } 416 417 private: 418 virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE { 419 DCHECK_EQ(download_, download); 420 DownloadItem::DownloadState state = download->GetState(); 421 int bytes = download->GetReceivedBytes(); 422 if (last_state_.state != state || last_state_.bytes_received > bytes) { 423 last_state_.state = state; 424 last_state_.bytes_received = bytes; 425 record_.push_back(last_state_); 426 } 427 } 428 429 virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE { 430 DCHECK_EQ(download_, download); 431 RemoveObserver(); 432 } 433 434 void RemoveObserver() { 435 if (download_) { 436 download_->RemoveObserver(this); 437 download_ = NULL; 438 } 439 } 440 441 DownloadItem* download_; 442 RecordStruct last_state_; 443 RecordVector record_; 444 }; 445 446 // Get the next created download. 447 class DownloadCreateObserver : DownloadManager::Observer { 448 public: 449 DownloadCreateObserver(DownloadManager* manager) 450 : manager_(manager), 451 item_(NULL), 452 waiting_(false) { 453 manager_->AddObserver(this); 454 } 455 456 virtual ~DownloadCreateObserver() { 457 if (manager_) 458 manager_->RemoveObserver(this); 459 manager_ = NULL; 460 } 461 462 virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE { 463 DCHECK_EQ(manager_, manager); 464 manager_->RemoveObserver(this); 465 manager_ = NULL; 466 } 467 468 virtual void OnDownloadCreated(DownloadManager* manager, 469 DownloadItem* download) OVERRIDE { 470 if (!item_) 471 item_ = download; 472 473 if (waiting_) 474 base::MessageLoopForUI::current()->Quit(); 475 } 476 477 DownloadItem* WaitForFinished() { 478 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 479 if (!item_) { 480 waiting_ = true; 481 RunMessageLoop(); 482 waiting_ = false; 483 } 484 return item_; 485 } 486 487 private: 488 DownloadManager* manager_; 489 DownloadItem* item_; 490 bool waiting_; 491 }; 492 493 494 // Filter for waiting for a certain number of bytes. 495 bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) { 496 return download->GetReceivedBytes() >= number_of_bytes; 497 } 498 499 // Filter for download completion. 500 bool DownloadCompleteFilter(DownloadItem* download) { 501 return download->GetState() == DownloadItem::COMPLETE; 502 } 503 504 // Filter for saving the size of the download when the first IN_PROGRESS 505 // is hit. 506 bool InitialSizeFilter(int* download_size, DownloadItem* download) { 507 if (download->GetState() != DownloadItem::IN_PROGRESS) 508 return false; 509 510 *download_size = download->GetReceivedBytes(); 511 return true; 512 } 513 514 // Request handler to be used with CreateRedirectHandler(). 515 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse( 516 const std::string& relative_url, 517 const GURL& target_url, 518 const net::test_server::HttpRequest& request) { 519 scoped_ptr<net::test_server::BasicHttpResponse> response; 520 if (request.relative_url == relative_url) { 521 response.reset(new net::test_server::BasicHttpResponse); 522 response->set_code(net::HTTP_FOUND); 523 response->AddCustomHeader("Location", target_url.spec()); 524 } 525 return response.PassAs<net::test_server::HttpResponse>(); 526 } 527 528 // Creates a request handler for EmbeddedTestServer that responds with a HTTP 529 // 302 redirect if the request URL matches |relative_url|. 530 EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler( 531 const std::string& relative_url, 532 const GURL& target_url) { 533 return base::Bind( 534 &HandleRequestAndSendRedirectResponse, relative_url, target_url); 535 } 536 537 // Request handler to be used with CreateBasicResponseHandler(). 538 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse( 539 const std::string& relative_url, 540 const std::string& content_type, 541 const std::string& body, 542 const net::test_server::HttpRequest& request) { 543 scoped_ptr<net::test_server::BasicHttpResponse> response; 544 if (request.relative_url == relative_url) { 545 response.reset(new net::test_server::BasicHttpResponse); 546 response->set_content_type(content_type); 547 response->set_content(body); 548 } 549 return response.PassAs<net::test_server::HttpResponse>(); 550 } 551 552 // Creates a request handler for an EmbeddedTestServer that response with an 553 // HTTP 200 status code, a Content-Type header and a body. 554 EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler( 555 const std::string& relative_url, 556 const std::string& content_type, 557 const std::string& body) { 558 return base::Bind( 559 &HandleRequestAndSendBasicResponse, relative_url, content_type, body); 560 } 561 562 } // namespace 563 564 class DownloadContentTest : public ContentBrowserTest { 565 protected: 566 // An initial send from a website of at least this size will not be 567 // help up by buffering in the underlying downloads ByteStream data 568 // transfer. This is important because on resumption tests we wait 569 // until we've gotten the data we expect before allowing the test server 570 // to send its reset, to get around hard close semantics on the Windows 571 // socket layer implementation. 572 int GetSafeBufferChunk() const { 573 return (DownloadResourceHandler::kDownloadByteStreamSize / 574 ByteStreamWriter::kFractionBufferBeforeSending) + 1; 575 } 576 577 virtual void SetUpOnMainThread() OVERRIDE { 578 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir()); 579 580 test_delegate_.reset(new TestShellDownloadManagerDelegate()); 581 test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path()); 582 DownloadManager* manager = DownloadManagerForShell(shell()); 583 manager->GetDelegate()->Shutdown(); 584 manager->SetDelegate(test_delegate_.get()); 585 test_delegate_->SetDownloadManager(manager); 586 587 BrowserThread::PostTask( 588 BrowserThread::IO, FROM_HERE, 589 base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler)); 590 base::FilePath mock_base(GetTestFilePath("download", "")); 591 BrowserThread::PostTask( 592 BrowserThread::IO, 593 FROM_HERE, 594 base::Bind( 595 &net::URLRequestMockHTTPJob::AddUrlHandler, 596 mock_base, 597 make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); 598 } 599 600 TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() { 601 return test_delegate_.get(); 602 } 603 604 // Create a DownloadTestObserverTerminal that will wait for the 605 // specified number of downloads to finish. 606 DownloadTestObserver* CreateWaiter( 607 Shell* shell, int num_downloads) { 608 DownloadManager* download_manager = DownloadManagerForShell(shell); 609 return new DownloadTestObserverTerminal(download_manager, num_downloads, 610 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); 611 } 612 613 // Create a DownloadTestObserverInProgress that will wait for the 614 // specified number of downloads to start. 615 DownloadCreateObserver* CreateInProgressWaiter( 616 Shell* shell, int num_downloads) { 617 DownloadManager* download_manager = DownloadManagerForShell(shell); 618 return new DownloadCreateObserver(download_manager); 619 } 620 621 DownloadTestObserver* CreateInterruptedWaiter( 622 Shell* shell, int num_downloads) { 623 DownloadManager* download_manager = DownloadManagerForShell(shell); 624 return new DownloadTestObserverInterrupted(download_manager, num_downloads, 625 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); 626 } 627 628 // Note: Cannot be used with other alternative DownloadFileFactorys 629 void SetupEnsureNoPendingDownloads() { 630 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting( 631 scoped_ptr<DownloadFileFactory>( 632 new CountingDownloadFileFactory()).Pass()); 633 } 634 635 bool EnsureNoPendingDownloads() { 636 bool result = true; 637 BrowserThread::PostTask( 638 BrowserThread::IO, FROM_HERE, 639 base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result)); 640 base::MessageLoop::current()->Run(); 641 return result && 642 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0); 643 } 644 645 void NavigateToURLAndWaitForDownload( 646 Shell* shell, 647 const GURL& url, 648 DownloadItem::DownloadState expected_terminal_state) { 649 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1)); 650 NavigateToURL(shell, url); 651 observer->WaitForFinished(); 652 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state)); 653 } 654 655 // Checks that |path| is has |file_size| bytes, and matches the |value| 656 // string. 657 bool VerifyFile(const base::FilePath& path, 658 const std::string& value, 659 const int64 file_size) { 660 std::string file_contents; 661 662 bool read = base::ReadFileToString(path, &file_contents); 663 EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl; 664 if (!read) 665 return false; // Couldn't read the file. 666 667 // Note: we don't handle really large files (more than size_t can hold) 668 // so we will fail in that case. 669 size_t expected_size = static_cast<size_t>(file_size); 670 671 // Check the size. 672 EXPECT_EQ(expected_size, file_contents.size()); 673 if (expected_size != file_contents.size()) 674 return false; 675 676 // Check the contents. 677 EXPECT_EQ(value, file_contents); 678 if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0) 679 return false; 680 681 return true; 682 } 683 684 // Start a download and return the item. 685 DownloadItem* StartDownloadAndReturnItem(GURL url) { 686 scoped_ptr<DownloadCreateObserver> observer( 687 CreateInProgressWaiter(shell(), 1)); 688 NavigateToURL(shell(), url); 689 observer->WaitForFinished(); 690 std::vector<DownloadItem*> downloads; 691 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); 692 EXPECT_EQ(1u, downloads.size()); 693 if (1u != downloads.size()) 694 return NULL; 695 return downloads[0]; 696 } 697 698 // Wait for data 699 void WaitForData(DownloadItem* download, int size) { 700 DownloadUpdatedObserver data_observer( 701 download, base::Bind(&DataReceivedFilter, size)); 702 data_observer.WaitForEvent(); 703 ASSERT_EQ(size, download->GetReceivedBytes()); 704 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); 705 } 706 707 // Tell the test server to release a pending RST and confirm 708 // that the interrupt is received properly (for download resumption 709 // testing). 710 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) { 711 scoped_ptr<DownloadTestObserver> rst_observer( 712 CreateInterruptedWaiter(shell(), 1)); 713 NavigateToURL(shell(), test_server()->GetURL("download-finish")); 714 rst_observer->WaitForFinished(); 715 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); 716 } 717 718 // Confirm file status expected for the given location in a stream 719 // provided by the resume test server. 720 void ConfirmFileStatusForResume( 721 DownloadItem* download, bool file_exists, 722 int received_bytes, int total_bytes, 723 const base::FilePath& expected_filename) { 724 // expected_filename is only known if the file exists. 725 ASSERT_EQ(file_exists, !expected_filename.empty()); 726 EXPECT_EQ(received_bytes, download->GetReceivedBytes()); 727 EXPECT_EQ(total_bytes, download->GetTotalBytes()); 728 EXPECT_EQ(expected_filename.value(), 729 download->GetFullPath().BaseName().value()); 730 EXPECT_EQ(file_exists, 731 (!download->GetFullPath().empty() && 732 base::PathExists(download->GetFullPath()))); 733 734 if (file_exists) { 735 std::string file_contents; 736 EXPECT_TRUE(base::ReadFileToString( 737 download->GetFullPath(), &file_contents)); 738 739 ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size()); 740 for (int i = 0; i < received_bytes; ++i) { 741 EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i]) 742 << "File contents diverged at position " << i 743 << " for " << expected_filename.value(); 744 745 if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i]) 746 return; 747 } 748 } 749 } 750 751 private: 752 static void EnsureNoPendingDownloadJobsOnIO(bool* result) { 753 if (URLRequestSlowDownloadJob::NumberOutstandingRequests()) 754 *result = false; 755 BrowserThread::PostTask( 756 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure()); 757 } 758 759 // Location of the downloads directory for these tests 760 base::ScopedTempDir downloads_directory_; 761 scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_; 762 }; 763 764 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) { 765 SetupEnsureNoPendingDownloads(); 766 767 // Create a download, wait until it's started, and confirm 768 // we're in the expected state. 769 scoped_ptr<DownloadCreateObserver> observer( 770 CreateInProgressWaiter(shell(), 1)); 771 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl)); 772 observer->WaitForFinished(); 773 774 std::vector<DownloadItem*> downloads; 775 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); 776 ASSERT_EQ(1u, downloads.size()); 777 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState()); 778 779 // Cancel the download and wait for download system quiesce. 780 downloads[0]->Cancel(true); 781 scoped_refptr<DownloadTestFlushObserver> flush_observer( 782 new DownloadTestFlushObserver(DownloadManagerForShell(shell()))); 783 flush_observer->WaitForFlush(); 784 785 // Get the important info from other threads and check it. 786 EXPECT_TRUE(EnsureNoPendingDownloads()); 787 } 788 789 // Check that downloading multiple (in this case, 2) files does not result in 790 // corrupted files. 791 IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) { 792 SetupEnsureNoPendingDownloads(); 793 794 // Create a download, wait until it's started, and confirm 795 // we're in the expected state. 796 scoped_ptr<DownloadCreateObserver> observer1( 797 CreateInProgressWaiter(shell(), 1)); 798 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl)); 799 observer1->WaitForFinished(); 800 801 std::vector<DownloadItem*> downloads; 802 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); 803 ASSERT_EQ(1u, downloads.size()); 804 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState()); 805 DownloadItem* download1 = downloads[0]; // The only download. 806 807 // Start the second download and wait until it's done. 808 base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); 809 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file)); 810 // Download the file and wait. 811 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); 812 813 // Should now have 2 items on the manager. 814 downloads.clear(); 815 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); 816 ASSERT_EQ(2u, downloads.size()); 817 // We don't know the order of the downloads. 818 DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0]; 819 820 ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState()); 821 ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState()); 822 823 // Allow the first request to finish. 824 scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1)); 825 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl)); 826 observer2->WaitForFinished(); // Wait for the third request. 827 EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE)); 828 829 // Get the important info from other threads and check it. 830 EXPECT_TRUE(EnsureNoPendingDownloads()); 831 832 // The |DownloadItem|s should now be done and have the final file names. 833 // Verify that the files have the expected data and size. 834 // |file1| should be full of '*'s, and |file2| should be the same as the 835 // source file. 836 base::FilePath file1(download1->GetTargetFilePath()); 837 size_t file_size1 = URLRequestSlowDownloadJob::kFirstDownloadSize + 838 URLRequestSlowDownloadJob::kSecondDownloadSize; 839 std::string expected_contents(file_size1, '*'); 840 ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1)); 841 842 base::FilePath file2(download2->GetTargetFilePath()); 843 ASSERT_TRUE(base::ContentsEqual( 844 file2, GetTestFilePath("download", "download-test.lib"))); 845 } 846 847 #if defined(ENABLE_PLUGINS) 848 // Content served with a MIME type of application/octet-stream should be 849 // downloaded even when a plugin can be found that handles the file type. 850 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) { 851 const base::FilePath::CharType kTestFilePath[] = 852 FILE_PATH_LITERAL("octet-stream.abc"); 853 const char kTestPluginName[] = "TestPlugin"; 854 const char kTestMimeType[] = "application/x-test-mime-type"; 855 const char kTestFileType[] = "abc"; 856 857 WebPluginInfo plugin_info; 858 plugin_info.name = base::ASCIIToUTF16(kTestPluginName); 859 plugin_info.mime_types.push_back( 860 WebPluginMimeType(kTestMimeType, kTestFileType, "")); 861 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false); 862 863 // The following is served with a Content-Type of application/octet-stream. 864 GURL url( 865 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath))); 866 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); 867 } 868 #endif 869 870 // Try to cancel just before we release the download file, by delaying final 871 // rename callback. 872 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) { 873 // Setup new factory. 874 DownloadFileWithDelayFactory* file_factory = 875 new DownloadFileWithDelayFactory(); 876 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell())); 877 download_manager->SetDownloadFileFactoryForTesting( 878 scoped_ptr<DownloadFileFactory>(file_factory).Pass()); 879 880 // Create a download 881 base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); 882 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file)); 883 884 // Wait until the first (intermediate file) rename and execute the callback. 885 file_factory->WaitForSomeCallback(); 886 std::vector<base::Closure> callbacks; 887 file_factory->GetAllRenameCallbacks(&callbacks); 888 ASSERT_EQ(1u, callbacks.size()); 889 callbacks[0].Run(); 890 callbacks.clear(); 891 892 // Wait until the second (final) rename callback is posted. 893 file_factory->WaitForSomeCallback(); 894 file_factory->GetAllRenameCallbacks(&callbacks); 895 ASSERT_EQ(1u, callbacks.size()); 896 897 // Cancel it. 898 std::vector<DownloadItem*> items; 899 download_manager->GetAllDownloads(&items); 900 ASSERT_EQ(1u, items.size()); 901 items[0]->Cancel(true); 902 RunAllPendingInMessageLoop(); 903 904 // Check state. 905 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState()); 906 907 // Run final rename callback. 908 callbacks[0].Run(); 909 callbacks.clear(); 910 911 // Check state. 912 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState()); 913 } 914 915 // Try to cancel just after we release the download file, by delaying 916 // in ShouldOpenDownload. 917 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) { 918 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell())); 919 920 // Mark delegate for delayed open. 921 GetDownloadManagerDelegate()->SetDelayedOpen(true); 922 923 // Setup new factory. 924 DownloadFileWithDelayFactory* file_factory = 925 new DownloadFileWithDelayFactory(); 926 download_manager->SetDownloadFileFactoryForTesting( 927 scoped_ptr<DownloadFileFactory>(file_factory).Pass()); 928 929 // Create a download 930 base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); 931 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file)); 932 933 // Wait until the first (intermediate file) rename and execute the callback. 934 file_factory->WaitForSomeCallback(); 935 std::vector<base::Closure> callbacks; 936 file_factory->GetAllRenameCallbacks(&callbacks); 937 ASSERT_EQ(1u, callbacks.size()); 938 callbacks[0].Run(); 939 callbacks.clear(); 940 941 // Wait until the second (final) rename callback is posted. 942 file_factory->WaitForSomeCallback(); 943 file_factory->GetAllRenameCallbacks(&callbacks); 944 ASSERT_EQ(1u, callbacks.size()); 945 946 // Call it. 947 callbacks[0].Run(); 948 callbacks.clear(); 949 950 // Confirm download still IN_PROGRESS (internal state COMPLETING). 951 std::vector<DownloadItem*> items; 952 download_manager->GetAllDownloads(&items); 953 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState()); 954 955 // Cancel the download; confirm cancel fails. 956 ASSERT_EQ(1u, items.size()); 957 items[0]->Cancel(true); 958 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState()); 959 960 // Need to complete open test. 961 std::vector<DownloadOpenDelayedCallback> delayed_callbacks; 962 GetDownloadManagerDelegate()->GetDelayedCallbacks( 963 &delayed_callbacks); 964 ASSERT_EQ(1u, delayed_callbacks.size()); 965 delayed_callbacks[0].Run(true); 966 967 // *Now* the download should be complete. 968 EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState()); 969 } 970 971 // Try to shutdown with a download in progress to make sure shutdown path 972 // works properly. 973 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) { 974 // Create a download that won't complete. 975 scoped_ptr<DownloadCreateObserver> observer( 976 CreateInProgressWaiter(shell(), 1)); 977 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl)); 978 observer->WaitForFinished(); 979 980 // Get the item. 981 std::vector<DownloadItem*> items; 982 DownloadManagerForShell(shell())->GetAllDownloads(&items); 983 ASSERT_EQ(1u, items.size()); 984 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState()); 985 986 // Shutdown the download manager and make sure we get the right 987 // notifications in the right order. 988 StrictMock<MockDownloadItemObserver> item_observer; 989 items[0]->AddObserver(&item_observer); 990 MockDownloadManagerObserver manager_observer( 991 DownloadManagerForShell(shell())); 992 // Don't care about ModelChanged() events. 993 EXPECT_CALL(manager_observer, ModelChanged(_)) 994 .WillRepeatedly(Return()); 995 { 996 InSequence notifications; 997 998 EXPECT_CALL(manager_observer, MockManagerGoingDown( 999 DownloadManagerForShell(shell()))) 1000 .WillOnce(Return()); 1001 EXPECT_CALL(item_observer, OnDownloadUpdated( 1002 AllOf(items[0], 1003 Property(&DownloadItem::GetState, DownloadItem::CANCELLED)))) 1004 .WillOnce(Return()); 1005 EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0])) 1006 .WillOnce(Return()); 1007 } 1008 1009 // See http://crbug.com/324525. If we have a refcount release/post task 1010 // race, the second post will stall the IO thread long enough so that we'll 1011 // lose the race and crash. The first stall is just to give the UI thread 1012 // a chance to get the second stall onto the IO thread queue after the cancel 1013 // message created by Shutdown and before the notification callback 1014 // created by the IO thread in canceling the request. 1015 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 1016 base::Bind(&base::PlatformThread::Sleep, 1017 base::TimeDelta::FromMilliseconds(25))); 1018 DownloadManagerForShell(shell())->Shutdown(); 1019 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 1020 base::Bind(&base::PlatformThread::Sleep, 1021 base::TimeDelta::FromMilliseconds(25))); 1022 items.clear(); 1023 } 1024 1025 // Try to shutdown just after we release the download file, by delaying 1026 // release. 1027 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) { 1028 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell())); 1029 1030 // Mark delegate for delayed open. 1031 GetDownloadManagerDelegate()->SetDelayedOpen(true); 1032 1033 // Setup new factory. 1034 DownloadFileWithDelayFactory* file_factory = 1035 new DownloadFileWithDelayFactory(); 1036 download_manager->SetDownloadFileFactoryForTesting( 1037 scoped_ptr<DownloadFileFactory>(file_factory).Pass()); 1038 1039 // Create a download 1040 base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); 1041 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file)); 1042 1043 // Wait until the first (intermediate file) rename and execute the callback. 1044 file_factory->WaitForSomeCallback(); 1045 std::vector<base::Closure> callbacks; 1046 file_factory->GetAllRenameCallbacks(&callbacks); 1047 ASSERT_EQ(1u, callbacks.size()); 1048 callbacks[0].Run(); 1049 callbacks.clear(); 1050 1051 // Wait until the second (final) rename callback is posted. 1052 file_factory->WaitForSomeCallback(); 1053 file_factory->GetAllRenameCallbacks(&callbacks); 1054 ASSERT_EQ(1u, callbacks.size()); 1055 1056 // Call it. 1057 callbacks[0].Run(); 1058 callbacks.clear(); 1059 1060 // Confirm download isn't complete yet. 1061 std::vector<DownloadItem*> items; 1062 DownloadManagerForShell(shell())->GetAllDownloads(&items); 1063 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState()); 1064 1065 // Cancel the download; confirm cancel fails anyway. 1066 ASSERT_EQ(1u, items.size()); 1067 items[0]->Cancel(true); 1068 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState()); 1069 RunAllPendingInMessageLoop(); 1070 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState()); 1071 1072 MockDownloadItemObserver observer; 1073 items[0]->AddObserver(&observer); 1074 EXPECT_CALL(observer, OnDownloadDestroyed(items[0])); 1075 1076 // Shutdown the download manager. Mostly this is confirming a lack of 1077 // crashes. 1078 DownloadManagerForShell(shell())->Shutdown(); 1079 } 1080 1081 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) { 1082 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1083 switches::kEnableDownloadResumption); 1084 ASSERT_TRUE(test_server()->Start()); 1085 1086 GURL url = test_server()->GetURL( 1087 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", 1088 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1089 1090 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); 1091 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); 1092 1093 DownloadItem* download(StartDownloadAndReturnItem(url)); 1094 WaitForData(download, GetSafeBufferChunk()); 1095 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); 1096 1097 // Confirm resumption while in progress doesn't do anything. 1098 download->Resume(); 1099 ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes()); 1100 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); 1101 1102 // Tell the server to send the RST and confirm the interrupt happens. 1103 ReleaseRSTAndConfirmInterruptForResume(download); 1104 ConfirmFileStatusForResume( 1105 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1106 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1107 1108 // Resume, confirming received bytes on resumption is correct. 1109 // Make sure no creation calls are included. 1110 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0); 1111 int initial_size = 0; 1112 DownloadUpdatedObserver initial_size_observer( 1113 download, base::Bind(&InitialSizeFilter, &initial_size)); 1114 download->Resume(); 1115 initial_size_observer.WaitForEvent(); 1116 EXPECT_EQ(GetSafeBufferChunk(), initial_size); 1117 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); 1118 1119 // and wait for expected data. 1120 WaitForData(download, GetSafeBufferChunk() * 2); 1121 1122 // Tell the server to send the RST and confirm the interrupt happens. 1123 ReleaseRSTAndConfirmInterruptForResume(download); 1124 ConfirmFileStatusForResume( 1125 download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3, 1126 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1127 1128 // Resume and wait for completion. 1129 DownloadUpdatedObserver completion_observer( 1130 download, base::Bind(DownloadCompleteFilter)); 1131 download->Resume(); 1132 completion_observer.WaitForEvent(); 1133 1134 ConfirmFileStatusForResume( 1135 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, 1136 base::FilePath(FILE_PATH_LITERAL("rangereset"))); 1137 1138 // Confirm resumption while complete doesn't do anything. 1139 download->Resume(); 1140 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes()); 1141 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState()); 1142 RunAllPendingInMessageLoop(); 1143 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes()); 1144 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState()); 1145 } 1146 1147 // Confirm restart fallback happens if a range request is bounced. 1148 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) { 1149 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1150 switches::kEnableDownloadResumption); 1151 ASSERT_TRUE(test_server()->Start()); 1152 1153 // Auto-restart if server doesn't handle ranges. 1154 GURL url = test_server()->GetURL( 1155 base::StringPrintf( 1156 // First download hits an RST, rest don't, no ranges. 1157 "rangereset?size=%d&rst_boundary=%d&" 1158 "token=NoRange&rst_limit=1&bounce_range", 1159 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1160 1161 // Start the download and wait for first data chunk. 1162 DownloadItem* download(StartDownloadAndReturnItem(url)); 1163 WaitForData(download, GetSafeBufferChunk()); 1164 1165 RecordingDownloadObserver recorder(download); 1166 1167 ReleaseRSTAndConfirmInterruptForResume(download); 1168 ConfirmFileStatusForResume( 1169 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1170 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1171 1172 DownloadUpdatedObserver completion_observer( 1173 download, base::Bind(DownloadCompleteFilter)); 1174 download->Resume(); 1175 completion_observer.WaitForEvent(); 1176 1177 ConfirmFileStatusForResume( 1178 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, 1179 base::FilePath(FILE_PATH_LITERAL("rangereset"))); 1180 1181 static const RecordingDownloadObserver::RecordStruct expected_record[] = { 1182 // Result of RST 1183 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()}, 1184 // Starting continuation 1185 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()}, 1186 // Notification of receiving whole file. 1187 {DownloadItem::IN_PROGRESS, 0}, 1188 // Completion. 1189 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3}, 1190 }; 1191 1192 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record)); 1193 } 1194 1195 // Confirm restart fallback happens if a precondition is failed. 1196 IN_PROC_BROWSER_TEST_F(DownloadContentTest, 1197 ResumeInterruptedDownloadBadPrecondition) { 1198 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1199 switches::kEnableDownloadResumption); 1200 ASSERT_TRUE(test_server()->Start()); 1201 1202 GURL url = test_server()->GetURL(base::StringPrintf( 1203 // First download hits an RST, rest don't, precondition fail. 1204 "rangereset?size=%d&rst_boundary=%d&" 1205 "token=BadPrecondition&rst_limit=1&fail_precondition=2", 1206 GetSafeBufferChunk() * 3, 1207 GetSafeBufferChunk())); 1208 1209 // Start the download and wait for first data chunk. 1210 DownloadItem* download(StartDownloadAndReturnItem(url)); 1211 WaitForData(download, GetSafeBufferChunk()); 1212 1213 RecordingDownloadObserver recorder(download); 1214 1215 ReleaseRSTAndConfirmInterruptForResume(download); 1216 ConfirmFileStatusForResume( 1217 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1218 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1219 EXPECT_EQ("BadPrecondition2", download->GetETag()); 1220 1221 DownloadUpdatedObserver completion_observer( 1222 download, base::Bind(DownloadCompleteFilter)); 1223 download->Resume(); 1224 completion_observer.WaitForEvent(); 1225 1226 ConfirmFileStatusForResume( 1227 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, 1228 base::FilePath(FILE_PATH_LITERAL("rangereset"))); 1229 EXPECT_EQ("BadPrecondition0", download->GetETag()); 1230 1231 static const RecordingDownloadObserver::RecordStruct expected_record[] = { 1232 // Result of RST 1233 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()}, 1234 // Starting continuation 1235 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()}, 1236 // Server precondition fail. 1237 {DownloadItem::INTERRUPTED, 0}, 1238 // Notification of successful restart. 1239 {DownloadItem::IN_PROGRESS, 0}, 1240 // Completion. 1241 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3}, 1242 }; 1243 1244 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record)); 1245 } 1246 1247 // Confirm we don't try to resume if we don't have a verifier. 1248 IN_PROC_BROWSER_TEST_F(DownloadContentTest, 1249 ResumeInterruptedDownloadNoVerifiers) { 1250 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1251 switches::kEnableDownloadResumption); 1252 ASSERT_TRUE(test_server()->Start()); 1253 1254 GURL url = test_server()->GetURL( 1255 base::StringPrintf( 1256 // First download hits an RST, rest don't, no verifiers. 1257 "rangereset?size=%d&rst_boundary=%d&" 1258 "token=NoRange&rst_limit=1&no_verifiers", 1259 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1260 1261 // Start the download and wait for first data chunk. 1262 DownloadItem* download(StartDownloadAndReturnItem(url)); 1263 WaitForData(download, GetSafeBufferChunk()); 1264 1265 RecordingDownloadObserver recorder(download); 1266 1267 ReleaseRSTAndConfirmInterruptForResume(download); 1268 ConfirmFileStatusForResume( 1269 download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1270 base::FilePath()); 1271 1272 DownloadUpdatedObserver completion_observer( 1273 download, base::Bind(DownloadCompleteFilter)); 1274 download->Resume(); 1275 completion_observer.WaitForEvent(); 1276 1277 ConfirmFileStatusForResume( 1278 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, 1279 base::FilePath(FILE_PATH_LITERAL("rangereset"))); 1280 1281 static const RecordingDownloadObserver::RecordStruct expected_record[] = { 1282 // Result of RST 1283 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()}, 1284 // Restart for lack of verifiers 1285 {DownloadItem::IN_PROGRESS, 0}, 1286 // Completion. 1287 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3}, 1288 }; 1289 1290 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record)); 1291 } 1292 1293 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) { 1294 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1295 switches::kEnableDownloadResumption); 1296 ASSERT_TRUE(test_server()->Start()); 1297 1298 GURL url = test_server()->GetURL( 1299 base::StringPrintf( 1300 // First download hits an RST, rest don't 1301 "rangereset?size=%d&rst_boundary=%d&" 1302 "token=NoRange&rst_limit=1", 1303 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1304 1305 // Start the download and wait for first data chunk. 1306 DownloadItem* download(StartDownloadAndReturnItem(url)); 1307 WaitForData(download, GetSafeBufferChunk()); 1308 1309 RecordingDownloadObserver recorder(download); 1310 1311 ReleaseRSTAndConfirmInterruptForResume(download); 1312 ConfirmFileStatusForResume( 1313 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1314 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1315 1316 // Delete the intermediate file. 1317 base::DeleteFile(download->GetFullPath(), false); 1318 1319 DownloadUpdatedObserver completion_observer( 1320 download, base::Bind(DownloadCompleteFilter)); 1321 download->Resume(); 1322 completion_observer.WaitForEvent(); 1323 1324 ConfirmFileStatusForResume( 1325 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, 1326 base::FilePath(FILE_PATH_LITERAL("rangereset"))); 1327 1328 static const RecordingDownloadObserver::RecordStruct expected_record[] = { 1329 // Result of RST 1330 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()}, 1331 // Starting continuation 1332 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()}, 1333 // Error because file isn't there. 1334 {DownloadItem::INTERRUPTED, 0}, 1335 // Restart. 1336 {DownloadItem::IN_PROGRESS, 0}, 1337 // Completion. 1338 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3}, 1339 }; 1340 1341 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record)); 1342 } 1343 1344 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) { 1345 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1346 switches::kEnableDownloadResumption); 1347 base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); 1348 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file)); 1349 1350 // Setup the error injector. 1351 scoped_refptr<TestFileErrorInjector> injector( 1352 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); 1353 1354 TestFileErrorInjector::FileErrorInfo err = { 1355 url.spec(), 1356 TestFileErrorInjector::FILE_OPERATION_INITIALIZE, 1357 0, 1358 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE 1359 }; 1360 injector->AddError(err); 1361 injector->InjectErrors(); 1362 1363 // Start and watch for interrupt. 1364 scoped_ptr<DownloadTestObserver> int_observer( 1365 CreateInterruptedWaiter(shell(), 1)); 1366 DownloadItem* download(StartDownloadAndReturnItem(url)); 1367 int_observer->WaitForFinished(); 1368 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); 1369 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, 1370 download->GetLastReason()); 1371 EXPECT_EQ(0, download->GetReceivedBytes()); 1372 EXPECT_TRUE(download->GetFullPath().empty()); 1373 EXPECT_TRUE(download->GetTargetFilePath().empty()); 1374 1375 // We need to make sure that any cross-thread downloads communication has 1376 // quiesced before clearing and injecting the new errors, as the 1377 // InjectErrors() routine alters the currently in use download file 1378 // factory, which is a file thread object. 1379 RunAllPendingInMessageLoop(BrowserThread::FILE); 1380 RunAllPendingInMessageLoop(); 1381 1382 // Clear the old errors list. 1383 injector->ClearErrors(); 1384 injector->InjectErrors(); 1385 1386 // Resume and watch completion. 1387 DownloadUpdatedObserver completion_observer( 1388 download, base::Bind(DownloadCompleteFilter)); 1389 download->Resume(); 1390 completion_observer.WaitForEvent(); 1391 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); 1392 } 1393 1394 IN_PROC_BROWSER_TEST_F(DownloadContentTest, 1395 ResumeWithFileIntermediateRenameError) { 1396 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1397 switches::kEnableDownloadResumption); 1398 base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); 1399 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file)); 1400 1401 // Setup the error injector. 1402 scoped_refptr<TestFileErrorInjector> injector( 1403 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); 1404 1405 TestFileErrorInjector::FileErrorInfo err = { 1406 url.spec(), 1407 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY, 1408 0, 1409 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE 1410 }; 1411 injector->AddError(err); 1412 injector->InjectErrors(); 1413 1414 // Start and watch for interrupt. 1415 scoped_ptr<DownloadTestObserver> int_observer( 1416 CreateInterruptedWaiter(shell(), 1)); 1417 DownloadItem* download(StartDownloadAndReturnItem(url)); 1418 int_observer->WaitForFinished(); 1419 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); 1420 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, 1421 download->GetLastReason()); 1422 EXPECT_TRUE(download->GetFullPath().empty()); 1423 // Target path will have been set after file name determination. GetFullPath() 1424 // being empty is sufficient to signal that filename determination needs to be 1425 // redone. 1426 EXPECT_FALSE(download->GetTargetFilePath().empty()); 1427 1428 // We need to make sure that any cross-thread downloads communication has 1429 // quiesced before clearing and injecting the new errors, as the 1430 // InjectErrors() routine alters the currently in use download file 1431 // factory, which is a file thread object. 1432 RunAllPendingInMessageLoop(BrowserThread::FILE); 1433 RunAllPendingInMessageLoop(); 1434 1435 // Clear the old errors list. 1436 injector->ClearErrors(); 1437 injector->InjectErrors(); 1438 1439 // Resume and watch completion. 1440 DownloadUpdatedObserver completion_observer( 1441 download, base::Bind(DownloadCompleteFilter)); 1442 download->Resume(); 1443 completion_observer.WaitForEvent(); 1444 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); 1445 } 1446 1447 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) { 1448 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1449 switches::kEnableDownloadResumption); 1450 base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); 1451 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file)); 1452 1453 // Setup the error injector. 1454 scoped_refptr<TestFileErrorInjector> injector( 1455 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); 1456 1457 DownloadManagerForShell(shell())->RemoveAllDownloads(); 1458 TestFileErrorInjector::FileErrorInfo err = { 1459 url.spec(), 1460 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE, 1461 0, 1462 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE 1463 }; 1464 injector->AddError(err); 1465 injector->InjectErrors(); 1466 1467 // Start and watch for interrupt. 1468 scoped_ptr<DownloadTestObserver> int_observer( 1469 CreateInterruptedWaiter(shell(), 1)); 1470 DownloadItem* download(StartDownloadAndReturnItem(url)); 1471 int_observer->WaitForFinished(); 1472 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); 1473 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, 1474 download->GetLastReason()); 1475 EXPECT_TRUE(download->GetFullPath().empty()); 1476 // Target path should still be intact. 1477 EXPECT_FALSE(download->GetTargetFilePath().empty()); 1478 1479 // We need to make sure that any cross-thread downloads communication has 1480 // quiesced before clearing and injecting the new errors, as the 1481 // InjectErrors() routine alters the currently in use download file 1482 // factory, which is a file thread object. 1483 RunAllPendingInMessageLoop(BrowserThread::FILE); 1484 RunAllPendingInMessageLoop(); 1485 1486 // Clear the old errors list. 1487 injector->ClearErrors(); 1488 injector->InjectErrors(); 1489 1490 // Resume and watch completion. 1491 DownloadUpdatedObserver completion_observer( 1492 download, base::Bind(DownloadCompleteFilter)); 1493 download->Resume(); 1494 completion_observer.WaitForEvent(); 1495 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); 1496 } 1497 1498 // An interrupted download should remove the intermediate file when it is 1499 // cancelled. 1500 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) { 1501 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1502 switches::kEnableDownloadResumption); 1503 ASSERT_TRUE(test_server()->Start()); 1504 1505 GURL url1 = test_server()->GetURL( 1506 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", 1507 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1508 1509 DownloadItem* download(StartDownloadAndReturnItem(url1)); 1510 WaitForData(download, GetSafeBufferChunk()); 1511 1512 ReleaseRSTAndConfirmInterruptForResume(download); 1513 ConfirmFileStatusForResume( 1514 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1515 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1516 1517 base::FilePath intermediate_path(download->GetFullPath()); 1518 ASSERT_FALSE(intermediate_path.empty()); 1519 EXPECT_TRUE(base::PathExists(intermediate_path)); 1520 1521 download->Cancel(true /* user_cancel */); 1522 RunAllPendingInMessageLoop(BrowserThread::FILE); 1523 RunAllPendingInMessageLoop(); 1524 1525 // The intermediate file should now be gone. 1526 EXPECT_FALSE(base::PathExists(intermediate_path)); 1527 EXPECT_TRUE(download->GetFullPath().empty()); 1528 } 1529 1530 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) { 1531 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1532 switches::kEnableDownloadResumption); 1533 ASSERT_TRUE(test_server()->Start()); 1534 1535 // An interrupted download should remove the intermediate file when it is 1536 // removed. 1537 { 1538 GURL url1 = test_server()->GetURL( 1539 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", 1540 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1541 1542 DownloadItem* download(StartDownloadAndReturnItem(url1)); 1543 WaitForData(download, GetSafeBufferChunk()); 1544 ReleaseRSTAndConfirmInterruptForResume(download); 1545 ConfirmFileStatusForResume( 1546 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1547 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1548 1549 base::FilePath intermediate_path(download->GetFullPath()); 1550 ASSERT_FALSE(intermediate_path.empty()); 1551 EXPECT_TRUE(base::PathExists(intermediate_path)); 1552 1553 download->Remove(); 1554 RunAllPendingInMessageLoop(BrowserThread::FILE); 1555 RunAllPendingInMessageLoop(); 1556 1557 // The intermediate file should now be gone. 1558 EXPECT_FALSE(base::PathExists(intermediate_path)); 1559 } 1560 1561 // A completed download shouldn't delete the downloaded file when it is 1562 // removed. 1563 { 1564 // Start the second download and wait until it's done. 1565 base::FilePath file2(FILE_PATH_LITERAL("download-test.lib")); 1566 GURL url2(net::URLRequestMockHTTPJob::GetMockUrl(file2)); 1567 scoped_ptr<DownloadTestObserver> completion_observer( 1568 CreateWaiter(shell(), 1)); 1569 DownloadItem* download(StartDownloadAndReturnItem(url2)); 1570 completion_observer->WaitForFinished(); 1571 1572 // The target path should exist. 1573 base::FilePath target_path(download->GetTargetFilePath()); 1574 EXPECT_TRUE(base::PathExists(target_path)); 1575 download->Remove(); 1576 RunAllPendingInMessageLoop(BrowserThread::FILE); 1577 RunAllPendingInMessageLoop(); 1578 1579 // The file should still exist. 1580 EXPECT_TRUE(base::PathExists(target_path)); 1581 } 1582 } 1583 1584 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) { 1585 SetupEnsureNoPendingDownloads(); 1586 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1587 switches::kEnableDownloadResumption); 1588 ASSERT_TRUE(test_server()->Start()); 1589 1590 GURL url = test_server()->GetURL( 1591 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", 1592 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1593 1594 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); 1595 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); 1596 1597 DownloadItem* download(StartDownloadAndReturnItem(url)); 1598 WaitForData(download, GetSafeBufferChunk()); 1599 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); 1600 1601 // Tell the server to send the RST and confirm the interrupt happens. 1602 ReleaseRSTAndConfirmInterruptForResume(download); 1603 ConfirmFileStatusForResume( 1604 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1605 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1606 1607 base::FilePath intermediate_path(download->GetFullPath()); 1608 ASSERT_FALSE(intermediate_path.empty()); 1609 EXPECT_TRUE(base::PathExists(intermediate_path)); 1610 1611 // Resume and remove download. We expect only a single OnDownloadCreated() 1612 // call, and that's for the second download created below. 1613 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); 1614 download->Resume(); 1615 download->Remove(); 1616 1617 // The intermediate file should now be gone. 1618 RunAllPendingInMessageLoop(BrowserThread::FILE); 1619 RunAllPendingInMessageLoop(); 1620 EXPECT_FALSE(base::PathExists(intermediate_path)); 1621 1622 // Start the second download and wait until it's done. The test server is 1623 // single threaded. The response to this download request should follow the 1624 // response to the previous resumption request. 1625 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); 1626 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); 1627 1628 EXPECT_TRUE(EnsureNoPendingDownloads()); 1629 } 1630 1631 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) { 1632 SetupEnsureNoPendingDownloads(); 1633 base::CommandLine::ForCurrentProcess()->AppendSwitch( 1634 switches::kEnableDownloadResumption); 1635 ASSERT_TRUE(test_server()->Start()); 1636 1637 GURL url = test_server()->GetURL( 1638 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", 1639 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); 1640 1641 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); 1642 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); 1643 1644 DownloadItem* download(StartDownloadAndReturnItem(url)); 1645 WaitForData(download, GetSafeBufferChunk()); 1646 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); 1647 1648 // Tell the server to send the RST and confirm the interrupt happens. 1649 ReleaseRSTAndConfirmInterruptForResume(download); 1650 ConfirmFileStatusForResume( 1651 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, 1652 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); 1653 1654 base::FilePath intermediate_path(download->GetFullPath()); 1655 ASSERT_FALSE(intermediate_path.empty()); 1656 EXPECT_TRUE(base::PathExists(intermediate_path)); 1657 1658 // Resume and cancel download. We expect only a single OnDownloadCreated() 1659 // call, and that's for the second download created below. 1660 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); 1661 download->Resume(); 1662 download->Cancel(true); 1663 1664 // The intermediate file should now be gone. 1665 RunAllPendingInMessageLoop(BrowserThread::FILE); 1666 RunAllPendingInMessageLoop(); 1667 EXPECT_FALSE(base::PathExists(intermediate_path)); 1668 EXPECT_TRUE(download->GetFullPath().empty()); 1669 1670 // Start the second download and wait until it's done. The test server is 1671 // single threaded. The response to this download request should follow the 1672 // response to the previous resumption request. 1673 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); 1674 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); 1675 1676 EXPECT_TRUE(EnsureNoPendingDownloads()); 1677 } 1678 1679 // Check that the cookie policy is correctly updated when downloading a file 1680 // that redirects cross origin. 1681 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) { 1682 ASSERT_TRUE(test_server()->Start()); 1683 net::HostPortPair host_port = test_server()->host_port_pair(); 1684 DCHECK_EQ(host_port.host(), std::string("127.0.0.1")); 1685 1686 // Block third-party cookies. 1687 ShellNetworkDelegate::SetAcceptAllCookies(false); 1688 1689 // |url| redirects to a different origin |download| which tries to set a 1690 // cookie. 1691 std::string download(base::StringPrintf( 1692 "http://localhost:%d/set-cookie?A=B", host_port.port())); 1693 GURL url(test_server()->GetURL("server-redirect?" + download)); 1694 1695 // Download the file. 1696 SetupEnsureNoPendingDownloads(); 1697 scoped_ptr<DownloadUrlParameters> dl_params( 1698 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url)); 1699 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1)); 1700 DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass()); 1701 observer->WaitForFinished(); 1702 1703 // Get the important info from other threads and check it. 1704 EXPECT_TRUE(EnsureNoPendingDownloads()); 1705 1706 std::vector<DownloadItem*> downloads; 1707 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); 1708 ASSERT_EQ(1u, downloads.size()); 1709 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState()); 1710 1711 // Check that the cookies were correctly set. 1712 EXPECT_EQ("A=B", 1713 content::GetCookies(shell()->web_contents()->GetBrowserContext(), 1714 GURL(download))); 1715 } 1716 1717 // A filename suggestion specified via a @download attribute should not be 1718 // effective if the final download URL is in another origin from the original 1719 // download URL. 1720 IN_PROC_BROWSER_TEST_F(DownloadContentTest, 1721 DownloadAttributeCrossOriginRedirect) { 1722 EmbeddedTestServer origin_one; 1723 EmbeddedTestServer origin_two; 1724 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady()); 1725 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady()); 1726 1727 // The download-attribute.html page contains an anchor element whose href is 1728 // set to the value of the query parameter (specified as |target| in the URL 1729 // below). The suggested filename for the anchor is 'suggested-filename'. When 1730 // the page is loaded, a script simulates a click on the anchor, triggering a 1731 // download of the target URL. 1732 // 1733 // We construct two test servers; origin_one and origin_two. Once started, the 1734 // server URLs will differ by the port number. Therefore they will be in 1735 // different origins. 1736 GURL download_url = origin_one.GetURL("/ping"); 1737 GURL referrer_url = origin_one.GetURL( 1738 std::string("/download-attribute.html?target=") + download_url.spec()); 1739 1740 // <origin_one>/download-attribute.html initiates a download of 1741 // <origin_one>/ping, which redirects to <origin_two>/download. 1742 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); 1743 origin_one.RegisterRequestHandler( 1744 CreateRedirectHandler("/ping", origin_two.GetURL("/download"))); 1745 origin_two.RegisterRequestHandler(CreateBasicResponseHandler( 1746 "/download", "application/octet-stream", "Hello")); 1747 1748 NavigateToURLAndWaitForDownload( 1749 shell(), referrer_url, DownloadItem::COMPLETE); 1750 1751 std::vector<DownloadItem*> downloads; 1752 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); 1753 ASSERT_EQ(1u, downloads.size()); 1754 1755 EXPECT_EQ(FILE_PATH_LITERAL("download"), 1756 downloads[0]->GetTargetFilePath().BaseName().value()); 1757 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); 1758 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); 1759 } 1760 1761 // A filename suggestion specified via a @download attribute should be effective 1762 // if the final download URL is in the same origin as the initial download URL. 1763 // Test that this holds even if there are cross origin redirects in the middle 1764 // of the redirect chain. 1765 IN_PROC_BROWSER_TEST_F(DownloadContentTest, 1766 DownloadAttributeSameOriginRedirect) { 1767 EmbeddedTestServer origin_one; 1768 EmbeddedTestServer origin_two; 1769 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady()); 1770 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady()); 1771 1772 // The download-attribute.html page contains an anchor element whose href is 1773 // set to the value of the query parameter (specified as |target| in the URL 1774 // below). The suggested filename for the anchor is 'suggested-filename'. When 1775 // the page is loaded, a script simulates a click on the anchor, triggering a 1776 // download of the target URL. 1777 // 1778 // We construct two test servers; origin_one and origin_two. Once started, the 1779 // server URLs will differ by the port number. Therefore they will be in 1780 // different origins. 1781 GURL download_url = origin_one.GetURL("/ping"); 1782 GURL referrer_url = origin_one.GetURL( 1783 std::string("/download-attribute.html?target=") + download_url.spec()); 1784 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); 1785 1786 // <origin_one>/download-attribute.html initiates a download of 1787 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally 1788 // to <origin_one>/download. 1789 origin_one.RegisterRequestHandler( 1790 CreateRedirectHandler("/ping", origin_two.GetURL("/pong"))); 1791 origin_two.RegisterRequestHandler( 1792 CreateRedirectHandler("/pong", origin_one.GetURL("/download"))); 1793 origin_one.RegisterRequestHandler(CreateBasicResponseHandler( 1794 "/download", "application/octet-stream", "Hello")); 1795 1796 NavigateToURLAndWaitForDownload( 1797 shell(), referrer_url, DownloadItem::COMPLETE); 1798 1799 std::vector<DownloadItem*> downloads; 1800 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); 1801 ASSERT_EQ(1u, downloads.size()); 1802 1803 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"), 1804 downloads[0]->GetTargetFilePath().BaseName().value()); 1805 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); 1806 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); 1807 } 1808 1809 // The file empty.bin is served with a MIME type of application/octet-stream. 1810 // The content body is empty. Make sure this case is handled properly and we 1811 // don't regress on http://crbug.com/320394. 1812 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) { 1813 EmbeddedTestServer test_server; 1814 ASSERT_TRUE(test_server.InitializeAndWaitUntilReady()); 1815 1816 GURL url = test_server.GetURL("/empty.bin"); 1817 test_server.ServeFilesFromDirectory(GetTestFilePath("download", "")); 1818 1819 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); 1820 // That's it. This should work without crashing. 1821 } 1822 1823 } // namespace content 1824