| 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 // This file contains download browser tests that are known to be runnable | 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. | 6 // in a pure content context. Over time tests should be migrated here. |
| 7 | 7 |
| 8 #include <vector> |
| 9 |
| 10 #include "base/callback_helpers.h" |
| 8 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 9 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 10 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 11 #include "base/files/scoped_temp_dir.h" | 14 #include "base/files/scoped_temp_dir.h" |
| 15 #include "base/format_macros.h" |
| 12 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
| 13 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/threading/platform_thread.h" | 19 #include "base/threading/platform_thread.h" |
| 16 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 17 #include "content/browser/byte_stream.h" | 21 #include "content/browser/byte_stream.h" |
| 18 #include "content/browser/download/download_file_factory.h" | 22 #include "content/browser/download/download_file_factory.h" |
| 19 #include "content/browser/download/download_file_impl.h" | 23 #include "content/browser/download/download_file_impl.h" |
| 20 #include "content/browser/download/download_item_impl.h" | 24 #include "content/browser/download/download_item_impl.h" |
| 21 #include "content/browser/download/download_manager_impl.h" | 25 #include "content/browser/download/download_manager_impl.h" |
| 22 #include "content/browser/download/download_resource_handler.h" | 26 #include "content/browser/download/download_resource_handler.h" |
| 23 #include "content/browser/web_contents/web_contents_impl.h" | 27 #include "content/browser/web_contents/web_contents_impl.h" |
| 24 #include "content/public/browser/power_save_blocker.h" | 28 #include "content/public/browser/power_save_blocker.h" |
| 25 #include "content/public/common/content_switches.h" | 29 #include "content/public/common/content_switches.h" |
| 26 #include "content/public/common/webplugininfo.h" | 30 #include "content/public/common/webplugininfo.h" |
| 27 #include "content/public/test/browser_test_utils.h" | 31 #include "content/public/test/browser_test_utils.h" |
| 28 #include "content/public/test/content_browser_test.h" | 32 #include "content/public/test/content_browser_test.h" |
| 29 #include "content/public/test/content_browser_test_utils.h" | 33 #include "content/public/test/content_browser_test_utils.h" |
| 30 #include "content/public/test/download_test_observer.h" | 34 #include "content/public/test/download_test_observer.h" |
| 35 #include "content/public/test/test_download_request_handler.h" |
| 31 #include "content/public/test/test_file_error_injector.h" | 36 #include "content/public/test/test_file_error_injector.h" |
| 32 #include "content/public/test/test_utils.h" | 37 #include "content/public/test/test_utils.h" |
| 33 #include "content/shell/browser/shell.h" | 38 #include "content/shell/browser/shell.h" |
| 34 #include "content/shell/browser/shell_browser_context.h" | 39 #include "content/shell/browser/shell_browser_context.h" |
| 35 #include "content/shell/browser/shell_download_manager_delegate.h" | 40 #include "content/shell/browser/shell_download_manager_delegate.h" |
| 36 #include "content/shell/browser/shell_network_delegate.h" | 41 #include "content/shell/browser/shell_network_delegate.h" |
| 37 #include "net/test/embedded_test_server/embedded_test_server.h" | 42 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 38 #include "net/test/embedded_test_server/http_request.h" | 43 #include "net/test/embedded_test_server/http_request.h" |
| 39 #include "net/test/embedded_test_server/http_response.h" | 44 #include "net/test/embedded_test_server/http_response.h" |
| 40 #include "net/test/spawned_test_server/spawned_test_server.h" | |
| 41 #include "net/test/url_request/url_request_mock_http_job.h" | 45 #include "net/test/url_request/url_request_mock_http_job.h" |
| 42 #include "net/test/url_request/url_request_slow_download_job.h" | 46 #include "net/test/url_request/url_request_slow_download_job.h" |
| 43 #include "testing/gmock/include/gmock/gmock.h" | 47 #include "testing/gmock/include/gmock/gmock.h" |
| 44 #include "testing/gtest/include/gtest/gtest.h" | 48 #include "testing/gtest/include/gtest/gtest.h" |
| 45 #include "url/gurl.h" | 49 #include "url/gurl.h" |
| 46 | 50 |
| 47 #if defined(ENABLE_PLUGINS) | 51 #if defined(ENABLE_PLUGINS) |
| 48 #include "content/browser/plugin_service_impl.h" | 52 #include "content/browser/plugin_service_impl.h" |
| 49 #endif | 53 #endif |
| 50 | 54 |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 | 375 |
| 372 void GetDelayedCallbacks( | 376 void GetDelayedCallbacks( |
| 373 std::vector<DownloadOpenDelayedCallback>* callbacks) { | 377 std::vector<DownloadOpenDelayedCallback>* callbacks) { |
| 374 callbacks->swap(delayed_callbacks_); | 378 callbacks->swap(delayed_callbacks_); |
| 375 } | 379 } |
| 376 private: | 380 private: |
| 377 bool delay_download_open_; | 381 bool delay_download_open_; |
| 378 std::vector<DownloadOpenDelayedCallback> delayed_callbacks_; | 382 std::vector<DownloadOpenDelayedCallback> delayed_callbacks_; |
| 379 }; | 383 }; |
| 380 | 384 |
| 381 // Record all state transitions and byte counts on the observed download. | |
| 382 class RecordingDownloadObserver : DownloadItem::Observer { | |
| 383 public: | |
| 384 struct RecordStruct { | |
| 385 DownloadItem::DownloadState state; | |
| 386 int bytes_received; | |
| 387 }; | |
| 388 | |
| 389 typedef std::vector<RecordStruct> RecordVector; | |
| 390 | |
| 391 RecordingDownloadObserver(DownloadItem* download) | |
| 392 : download_(download) { | |
| 393 last_state_.state = download->GetState(); | |
| 394 last_state_.bytes_received = download->GetReceivedBytes(); | |
| 395 download_->AddObserver(this); | |
| 396 } | |
| 397 | |
| 398 ~RecordingDownloadObserver() override { RemoveObserver(); } | |
| 399 | |
| 400 void CompareToExpectedRecord(const RecordStruct expected[], size_t size) { | |
| 401 EXPECT_EQ(size, record_.size()); | |
| 402 int min = size > record_.size() ? record_.size() : size; | |
| 403 for (int i = 0; i < min; ++i) { | |
| 404 EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i; | |
| 405 EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received) | |
| 406 << "Iteration " << i; | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 private: | |
| 411 void OnDownloadUpdated(DownloadItem* download) override { | |
| 412 DCHECK_EQ(download_, download); | |
| 413 DownloadItem::DownloadState state = download->GetState(); | |
| 414 int bytes = download->GetReceivedBytes(); | |
| 415 if (last_state_.state != state || last_state_.bytes_received > bytes) { | |
| 416 last_state_.state = state; | |
| 417 last_state_.bytes_received = bytes; | |
| 418 record_.push_back(last_state_); | |
| 419 } | |
| 420 } | |
| 421 | |
| 422 void OnDownloadDestroyed(DownloadItem* download) override { | |
| 423 DCHECK_EQ(download_, download); | |
| 424 RemoveObserver(); | |
| 425 } | |
| 426 | |
| 427 void RemoveObserver() { | |
| 428 if (download_) { | |
| 429 download_->RemoveObserver(this); | |
| 430 download_ = NULL; | |
| 431 } | |
| 432 } | |
| 433 | |
| 434 DownloadItem* download_; | |
| 435 RecordStruct last_state_; | |
| 436 RecordVector record_; | |
| 437 }; | |
| 438 | |
| 439 // Get the next created download. | 385 // Get the next created download. |
| 440 class DownloadCreateObserver : DownloadManager::Observer { | 386 class DownloadCreateObserver : DownloadManager::Observer { |
| 441 public: | 387 public: |
| 442 DownloadCreateObserver(DownloadManager* manager) | 388 DownloadCreateObserver(DownloadManager* manager) |
| 443 : manager_(manager), | 389 : manager_(manager), item_(NULL) { |
| 444 item_(NULL), | |
| 445 waiting_(false) { | |
| 446 manager_->AddObserver(this); | 390 manager_->AddObserver(this); |
| 447 } | 391 } |
| 448 | 392 |
| 449 ~DownloadCreateObserver() override { | 393 ~DownloadCreateObserver() override { |
| 450 if (manager_) | 394 if (manager_) |
| 451 manager_->RemoveObserver(this); | 395 manager_->RemoveObserver(this); |
| 452 manager_ = NULL; | 396 manager_ = NULL; |
| 453 } | 397 } |
| 454 | 398 |
| 455 void ManagerGoingDown(DownloadManager* manager) override { | 399 void ManagerGoingDown(DownloadManager* manager) override { |
| 456 DCHECK_EQ(manager_, manager); | 400 DCHECK_EQ(manager_, manager); |
| 457 manager_->RemoveObserver(this); | 401 manager_->RemoveObserver(this); |
| 458 manager_ = NULL; | 402 manager_ = NULL; |
| 459 } | 403 } |
| 460 | 404 |
| 461 void OnDownloadCreated(DownloadManager* manager, | 405 void OnDownloadCreated(DownloadManager* manager, |
| 462 DownloadItem* download) override { | 406 DownloadItem* download) override { |
| 463 if (!item_) | 407 if (!item_) |
| 464 item_ = download; | 408 item_ = download; |
| 465 | 409 |
| 466 if (waiting_) | 410 if (!completion_closure_.is_null()) |
| 467 base::MessageLoopForUI::current()->QuitWhenIdle(); | 411 base::ResetAndReturn(&completion_closure_).Run(); |
| 468 } | 412 } |
| 469 | 413 |
| 470 DownloadItem* WaitForFinished() { | 414 DownloadItem* WaitForFinished() { |
| 471 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 415 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 472 if (!item_) { | 416 if (!item_) { |
| 473 waiting_ = true; | 417 base::RunLoop run_loop; |
| 474 RunMessageLoop(); | 418 completion_closure_ = run_loop.QuitClosure(); |
| 475 waiting_ = false; | 419 run_loop.Run(); |
| 476 } | 420 } |
| 477 return item_; | 421 return item_; |
| 478 } | 422 } |
| 479 | 423 |
| 480 private: | 424 private: |
| 481 DownloadManager* manager_; | 425 DownloadManager* manager_; |
| 482 DownloadItem* item_; | 426 DownloadItem* item_; |
| 483 bool waiting_; | 427 base::Closure completion_closure_; |
| 484 }; | 428 }; |
| 485 | 429 |
| 486 | 430 bool IsDownloadInState(DownloadItem::DownloadState state, DownloadItem* item) { |
| 487 // Filter for waiting for a certain number of bytes. | 431 return item->GetState() == state; |
| 488 bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) { | |
| 489 return download->GetReceivedBytes() >= number_of_bytes; | |
| 490 } | |
| 491 | |
| 492 // Filter for download completion. | |
| 493 bool DownloadCompleteFilter(DownloadItem* download) { | |
| 494 return download->GetState() == DownloadItem::COMPLETE; | |
| 495 } | |
| 496 | |
| 497 // Filter for saving the size of the download when the first IN_PROGRESS | |
| 498 // is hit. | |
| 499 bool InitialSizeFilter(int* download_size, DownloadItem* download) { | |
| 500 if (download->GetState() != DownloadItem::IN_PROGRESS) | |
| 501 return false; | |
| 502 | |
| 503 *download_size = download->GetReceivedBytes(); | |
| 504 return true; | |
| 505 } | 432 } |
| 506 | 433 |
| 507 // Request handler to be used with CreateRedirectHandler(). | 434 // Request handler to be used with CreateRedirectHandler(). |
| 508 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse( | 435 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse( |
| 509 const std::string& relative_url, | 436 const std::string& relative_url, |
| 510 const GURL& target_url, | 437 const GURL& target_url, |
| 511 const net::test_server::HttpRequest& request) { | 438 const net::test_server::HttpRequest& request) { |
| 512 scoped_ptr<net::test_server::BasicHttpResponse> response; | 439 scoped_ptr<net::test_server::BasicHttpResponse> response; |
| 513 if (request.relative_url == relative_url) { | 440 if (request.relative_url == relative_url) { |
| 514 response.reset(new net::test_server::BasicHttpResponse); | 441 response.reset(new net::test_server::BasicHttpResponse); |
| 515 response->set_code(net::HTTP_FOUND); | 442 response->set_code(net::HTTP_FOUND); |
| 516 response->AddCustomHeader("Location", target_url.spec()); | 443 response->AddCustomHeader("Location", target_url.spec()); |
| 517 } | 444 } |
| 518 return response.Pass(); | 445 return response.Pass(); |
| 519 } | 446 } |
| 520 | 447 |
| 521 // Creates a request handler for EmbeddedTestServer that responds with a HTTP | 448 // Creates a request handler for EmbeddedTestServer that responds with a HTTP |
| 522 // 302 redirect if the request URL matches |relative_url|. | 449 // 302 redirect if the request URL matches |relative_url|. |
| 523 net::EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler( | 450 net::EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler( |
| 524 const std::string& relative_url, | 451 const std::string& relative_url, |
| 525 const GURL& target_url) { | 452 const GURL& target_url) { |
| 526 return base::Bind( | 453 return base::Bind( |
| 527 &HandleRequestAndSendRedirectResponse, relative_url, target_url); | 454 &HandleRequestAndSendRedirectResponse, relative_url, target_url); |
| 528 } | 455 } |
| 529 | 456 |
| 530 // Request handler to be used with CreateBasicResponseHandler(). | 457 // Request handler to be used with CreateBasicResponseHandler(). |
| 531 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse( | 458 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse( |
| 532 const std::string& relative_url, | 459 const std::string& relative_url, |
| 460 const base::StringPairs& headers, |
| 533 const std::string& content_type, | 461 const std::string& content_type, |
| 534 const std::string& body, | 462 const std::string& body, |
| 535 const net::test_server::HttpRequest& request) { | 463 const net::test_server::HttpRequest& request) { |
| 536 scoped_ptr<net::test_server::BasicHttpResponse> response; | 464 scoped_ptr<net::test_server::BasicHttpResponse> response; |
| 537 if (request.relative_url == relative_url) { | 465 if (request.relative_url == relative_url) { |
| 538 response.reset(new net::test_server::BasicHttpResponse); | 466 response.reset(new net::test_server::BasicHttpResponse); |
| 467 for (const auto& pair : headers) |
| 468 response->AddCustomHeader(pair.first, pair.second); |
| 539 response->set_content_type(content_type); | 469 response->set_content_type(content_type); |
| 540 response->set_content(body); | 470 response->set_content(body); |
| 541 } | 471 } |
| 542 return response.Pass(); | 472 return response.Pass(); |
| 543 } | 473 } |
| 544 | 474 |
| 545 // Creates a request handler for an EmbeddedTestServer that response with an | 475 // Creates a request handler for an EmbeddedTestServer that response with an |
| 546 // HTTP 200 status code, a Content-Type header and a body. | 476 // HTTP 200 status code, a Content-Type header and a body. |
| 547 net::EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler( | 477 net::EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler( |
| 548 const std::string& relative_url, | 478 const std::string& relative_url, |
| 479 const base::StringPairs& headers, |
| 549 const std::string& content_type, | 480 const std::string& content_type, |
| 550 const std::string& body) { | 481 const std::string& body) { |
| 551 return base::Bind( | 482 return base::Bind(&HandleRequestAndSendBasicResponse, relative_url, headers, |
| 552 &HandleRequestAndSendBasicResponse, relative_url, content_type, body); | 483 content_type, body); |
| 553 } | 484 } |
| 554 | 485 |
| 555 } // namespace | 486 // Helper class to "flatten" handling of |
| 487 // TestDownloadRequestHandler::OnStartHandler. |
| 488 class TestRequestStartHandler { |
| 489 public: |
| 490 // Construct an OnStartHandler that can be set as the on_start_handler for |
| 491 // TestDownloadRequestHandler::Parameters. |
| 492 TestDownloadRequestHandler::OnStartHandler GetOnStartHandler() { |
| 493 EXPECT_FALSE(used_) << "GetOnStartHandler() should only be called once for " |
| 494 "an instance of TestRequestStartHandler."; |
| 495 used_ = true; |
| 496 return base::Bind(&TestRequestStartHandler::OnStartHandler, |
| 497 base::Unretained(this)); |
| 498 } |
| 499 |
| 500 // Wait until the OnStartHandlers returned in a prior call to |
| 501 // GetOnStartHandler() is invoked. |
| 502 void WaitForCallback() { |
| 503 if (response_callback_.is_null()) |
| 504 run_loop_.Run(); |
| 505 } |
| 506 |
| 507 // Respond to the OnStartHandler() invocation using |headers| and |error|. |
| 508 void RespondWith(const std::string& headers, net::Error error) { |
| 509 ASSERT_FALSE(response_callback_.is_null()); |
| 510 response_callback_.Run(headers, error); |
| 511 } |
| 512 |
| 513 // Return the headers returned from the invocation of OnStartHandler. |
| 514 const net::HttpRequestHeaders& headers() const { |
| 515 EXPECT_FALSE(response_callback_.is_null()); |
| 516 return request_headers_; |
| 517 } |
| 518 |
| 519 private: |
| 520 void OnStartHandler(const net::HttpRequestHeaders& headers, |
| 521 const TestDownloadRequestHandler::OnStartResponseCallback& |
| 522 response_callback) { |
| 523 request_headers_ = headers; |
| 524 response_callback_ = response_callback; |
| 525 if (run_loop_.running()) |
| 526 run_loop_.Quit(); |
| 527 } |
| 528 |
| 529 bool used_ = false; |
| 530 base::RunLoop run_loop_; |
| 531 net::HttpRequestHeaders request_headers_; |
| 532 TestDownloadRequestHandler::OnStartResponseCallback response_callback_; |
| 533 }; |
| 556 | 534 |
| 557 class DownloadContentTest : public ContentBrowserTest { | 535 class DownloadContentTest : public ContentBrowserTest { |
| 558 protected: | 536 protected: |
| 559 // An initial send from a website of at least this size will not be | |
| 560 // help up by buffering in the underlying downloads ByteStream data | |
| 561 // transfer. This is important because on resumption tests we wait | |
| 562 // until we've gotten the data we expect before allowing the test server | |
| 563 // to send its reset, to get around hard close semantics on the Windows | |
| 564 // socket layer implementation. | |
| 565 int GetSafeBufferChunk() const { | |
| 566 return (DownloadResourceHandler::kDownloadByteStreamSize / | |
| 567 ByteStreamWriter::kFractionBufferBeforeSending) + 1; | |
| 568 } | |
| 569 | |
| 570 void SetUpOnMainThread() override { | 537 void SetUpOnMainThread() override { |
| 571 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir()); | 538 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir()); |
| 572 | 539 |
| 573 test_delegate_.reset(new TestShellDownloadManagerDelegate()); | 540 test_delegate_.reset(new TestShellDownloadManagerDelegate()); |
| 574 test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path()); | 541 test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path()); |
| 575 DownloadManager* manager = DownloadManagerForShell(shell()); | 542 DownloadManager* manager = DownloadManagerForShell(shell()); |
| 576 manager->GetDelegate()->Shutdown(); | 543 manager->GetDelegate()->Shutdown(); |
| 577 manager->SetDelegate(test_delegate_.get()); | 544 manager->SetDelegate(test_delegate_.get()); |
| 578 test_delegate_->SetDownloadManager(manager); | 545 test_delegate_->SetDownloadManager(manager); |
| 579 | 546 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 594 | 561 |
| 595 // Create a DownloadTestObserverTerminal that will wait for the | 562 // Create a DownloadTestObserverTerminal that will wait for the |
| 596 // specified number of downloads to finish. | 563 // specified number of downloads to finish. |
| 597 DownloadTestObserver* CreateWaiter( | 564 DownloadTestObserver* CreateWaiter( |
| 598 Shell* shell, int num_downloads) { | 565 Shell* shell, int num_downloads) { |
| 599 DownloadManager* download_manager = DownloadManagerForShell(shell); | 566 DownloadManager* download_manager = DownloadManagerForShell(shell); |
| 600 return new DownloadTestObserverTerminal(download_manager, num_downloads, | 567 return new DownloadTestObserverTerminal(download_manager, num_downloads, |
| 601 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); | 568 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); |
| 602 } | 569 } |
| 603 | 570 |
| 604 // Create a DownloadTestObserverInProgress that will wait for the | 571 void WaitForInterrupt(DownloadItem* download) { |
| 605 // specified number of downloads to start. | 572 DownloadUpdatedObserver( |
| 606 DownloadCreateObserver* CreateInProgressWaiter( | 573 download, base::Bind(&IsDownloadInState, DownloadItem::INTERRUPTED)) |
| 607 Shell* shell, int num_downloads) { | 574 .WaitForEvent(); |
| 608 DownloadManager* download_manager = DownloadManagerForShell(shell); | |
| 609 return new DownloadCreateObserver(download_manager); | |
| 610 } | 575 } |
| 611 | 576 |
| 612 DownloadTestObserver* CreateInterruptedWaiter( | 577 void WaitForInProgress(DownloadItem* download) { |
| 613 Shell* shell, int num_downloads) { | 578 DownloadUpdatedObserver( |
| 614 DownloadManager* download_manager = DownloadManagerForShell(shell); | 579 download, base::Bind(&IsDownloadInState, DownloadItem::IN_PROGRESS)) |
| 615 return new DownloadTestObserverInterrupted(download_manager, num_downloads, | 580 .WaitForEvent(); |
| 616 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); | 581 } |
| 582 |
| 583 void WaitForCompletion(DownloadItem* download) { |
| 584 DownloadUpdatedObserver( |
| 585 download, base::Bind(&IsDownloadInState, DownloadItem::COMPLETE)) |
| 586 .WaitForEvent(); |
| 617 } | 587 } |
| 618 | 588 |
| 619 // Note: Cannot be used with other alternative DownloadFileFactorys | 589 // Note: Cannot be used with other alternative DownloadFileFactorys |
| 620 void SetupEnsureNoPendingDownloads() { | 590 void SetupEnsureNoPendingDownloads() { |
| 621 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting( | 591 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting( |
| 622 scoped_ptr<DownloadFileFactory>( | 592 scoped_ptr<DownloadFileFactory>( |
| 623 new CountingDownloadFileFactory()).Pass()); | 593 new CountingDownloadFileFactory()).Pass()); |
| 624 } | 594 } |
| 625 | 595 |
| 626 bool EnsureNoPendingDownloads() { | 596 bool EnsureNoPendingDownloads() { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 EXPECT_EQ(value, file_contents); | 638 EXPECT_EQ(value, file_contents); |
| 669 if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0) | 639 if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0) |
| 670 return false; | 640 return false; |
| 671 | 641 |
| 672 return true; | 642 return true; |
| 673 } | 643 } |
| 674 | 644 |
| 675 // Start a download and return the item. | 645 // Start a download and return the item. |
| 676 DownloadItem* StartDownloadAndReturnItem(GURL url) { | 646 DownloadItem* StartDownloadAndReturnItem(GURL url) { |
| 677 scoped_ptr<DownloadCreateObserver> observer( | 647 scoped_ptr<DownloadCreateObserver> observer( |
| 678 CreateInProgressWaiter(shell(), 1)); | 648 new DownloadCreateObserver(DownloadManagerForShell(shell()))); |
| 679 NavigateToURL(shell(), url); | 649 shell()->LoadURL(url); |
| 680 observer->WaitForFinished(); | 650 return observer->WaitForFinished(); |
| 681 std::vector<DownloadItem*> downloads; | |
| 682 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | |
| 683 EXPECT_EQ(1u, downloads.size()); | |
| 684 if (1u != downloads.size()) | |
| 685 return NULL; | |
| 686 return downloads[0]; | |
| 687 } | 651 } |
| 688 | 652 |
| 689 // Wait for data | 653 static void ReadAndVerifyFileContents(int seed, |
| 690 void WaitForData(DownloadItem* download, int size) { | 654 int64_t expected_size, |
| 691 DownloadUpdatedObserver data_observer( | 655 const base::FilePath& path) { |
| 692 download, base::Bind(&DataReceivedFilter, size)); | 656 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); |
| 693 data_observer.WaitForEvent(); | 657 ASSERT_TRUE(file.IsValid()); |
| 694 ASSERT_EQ(size, download->GetReceivedBytes()); | 658 int64_t file_length = file.GetLength(); |
| 695 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); | 659 ASSERT_EQ(expected_size, file_length); |
| 696 } | |
| 697 | 660 |
| 698 // Tell the test server to release a pending RST and confirm | 661 const int64_t kBufferSize = 64 * 1024; |
| 699 // that the interrupt is received properly (for download resumption | 662 std::vector<char> pattern; |
| 700 // testing). | 663 std::vector<char> data; |
| 701 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) { | 664 pattern.resize(kBufferSize); |
| 702 scoped_ptr<DownloadTestObserver> rst_observer( | 665 data.resize(kBufferSize); |
| 703 CreateInterruptedWaiter(shell(), 1)); | 666 for (int64_t offset = 0; offset < file_length;) { |
| 704 NavigateToURL(shell(), spawned_test_server()->GetURL("download-finish")); | 667 int bytes_read = file.Read(offset, &data.front(), kBufferSize); |
| 705 rst_observer->WaitForFinished(); | 668 ASSERT_LT(0, bytes_read); |
| 706 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); | 669 ASSERT_GE(kBufferSize, bytes_read); |
| 707 } | |
| 708 | 670 |
| 709 // Confirm file status expected for the given location in a stream | 671 TestDownloadRequestHandler::GetPatternBytes(seed, offset, bytes_read, |
| 710 // provided by the resume test server. | 672 &pattern.front()); |
| 711 void ConfirmFileStatusForResume( | 673 ASSERT_EQ(0, memcmp(&pattern.front(), &data.front(), bytes_read)) |
| 712 DownloadItem* download, bool file_exists, | 674 << "Comparing block at offset " << offset << " and length " |
| 713 int received_bytes, int total_bytes, | 675 << bytes_read; |
| 714 const base::FilePath& expected_filename) { | 676 offset += bytes_read; |
| 715 // expected_filename is only known if the file exists. | |
| 716 ASSERT_EQ(file_exists, !expected_filename.empty()); | |
| 717 EXPECT_EQ(received_bytes, download->GetReceivedBytes()); | |
| 718 EXPECT_EQ(total_bytes, download->GetTotalBytes()); | |
| 719 EXPECT_EQ(expected_filename.value(), | |
| 720 download->GetFullPath().BaseName().value()); | |
| 721 EXPECT_EQ(file_exists, | |
| 722 (!download->GetFullPath().empty() && | |
| 723 base::PathExists(download->GetFullPath()))); | |
| 724 | |
| 725 if (file_exists) { | |
| 726 std::string file_contents; | |
| 727 EXPECT_TRUE(base::ReadFileToString( | |
| 728 download->GetFullPath(), &file_contents)); | |
| 729 | |
| 730 ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size()); | |
| 731 for (int i = 0; i < received_bytes; ++i) { | |
| 732 EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i]) | |
| 733 << "File contents diverged at position " << i | |
| 734 << " for " << expected_filename.value(); | |
| 735 | |
| 736 if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i]) | |
| 737 return; | |
| 738 } | |
| 739 } | 677 } |
| 740 } | 678 } |
| 741 | 679 |
| 742 private: | 680 private: |
| 743 static void EnsureNoPendingDownloadJobsOnIO(bool* result) { | 681 static void EnsureNoPendingDownloadJobsOnIO(bool* result) { |
| 744 if (net::URLRequestSlowDownloadJob::NumberOutstandingRequests()) | 682 if (net::URLRequestSlowDownloadJob::NumberOutstandingRequests()) |
| 745 *result = false; | 683 *result = false; |
| 746 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 684 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 747 base::MessageLoop::QuitWhenIdleClosure()); | 685 base::MessageLoop::QuitWhenIdleClosure()); |
| 748 } | 686 } |
| 749 | 687 |
| 750 // Location of the downloads directory for these tests | 688 // Location of the downloads directory for these tests |
| 751 base::ScopedTempDir downloads_directory_; | 689 base::ScopedTempDir downloads_directory_; |
| 752 scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_; | 690 scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_; |
| 753 }; | 691 }; |
| 754 | 692 |
| 693 } // namespace |
| 694 |
| 755 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) { | 695 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) { |
| 756 SetupEnsureNoPendingDownloads(); | 696 SetupEnsureNoPendingDownloads(); |
| 757 | 697 |
| 758 // Create a download, wait until it's started, and confirm | 698 // Create a download, wait until it's started, and confirm |
| 759 // we're in the expected state. | 699 // we're in the expected state. |
| 760 scoped_ptr<DownloadCreateObserver> observer( | 700 DownloadItem* download = StartDownloadAndReturnItem( |
| 761 CreateInProgressWaiter(shell(), 1)); | 701 GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl)); |
| 762 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl)); | 702 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); |
| 763 observer->WaitForFinished(); | |
| 764 | |
| 765 std::vector<DownloadItem*> downloads; | |
| 766 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | |
| 767 ASSERT_EQ(1u, downloads.size()); | |
| 768 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState()); | |
| 769 | 703 |
| 770 // Cancel the download and wait for download system quiesce. | 704 // Cancel the download and wait for download system quiesce. |
| 771 downloads[0]->Cancel(true); | 705 download->Cancel(true); |
| 772 scoped_refptr<DownloadTestFlushObserver> flush_observer( | 706 scoped_refptr<DownloadTestFlushObserver> flush_observer( |
| 773 new DownloadTestFlushObserver(DownloadManagerForShell(shell()))); | 707 new DownloadTestFlushObserver(DownloadManagerForShell(shell()))); |
| 774 flush_observer->WaitForFlush(); | 708 flush_observer->WaitForFlush(); |
| 775 | 709 |
| 776 // Get the important info from other threads and check it. | 710 // Get the important info from other threads and check it. |
| 777 EXPECT_TRUE(EnsureNoPendingDownloads()); | 711 EXPECT_TRUE(EnsureNoPendingDownloads()); |
| 778 } | 712 } |
| 779 | 713 |
| 780 // Check that downloading multiple (in this case, 2) files does not result in | 714 // Check that downloading multiple (in this case, 2) files does not result in |
| 781 // corrupted files. | 715 // corrupted files. |
| 782 IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) { | 716 IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) { |
| 783 SetupEnsureNoPendingDownloads(); | 717 SetupEnsureNoPendingDownloads(); |
| 784 | 718 |
| 785 // Create a download, wait until it's started, and confirm | 719 // Create a download, wait until it's started, and confirm |
| 786 // we're in the expected state. | 720 // we're in the expected state. |
| 787 scoped_ptr<DownloadCreateObserver> observer1( | 721 DownloadItem* download1 = StartDownloadAndReturnItem( |
| 788 CreateInProgressWaiter(shell(), 1)); | 722 GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl)); |
| 789 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl)); | 723 ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState()); |
| 790 observer1->WaitForFinished(); | |
| 791 | |
| 792 std::vector<DownloadItem*> downloads; | |
| 793 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | |
| 794 ASSERT_EQ(1u, downloads.size()); | |
| 795 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState()); | |
| 796 DownloadItem* download1 = downloads[0]; // The only download. | |
| 797 | 724 |
| 798 // Start the second download and wait until it's done. | 725 // Start the second download and wait until it's done. |
| 799 GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); | 726 GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); |
| 800 // Download the file and wait. | 727 DownloadItem* download2 = StartDownloadAndReturnItem(url); |
| 801 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); | 728 WaitForCompletion(download2); |
| 802 | |
| 803 // Should now have 2 items on the manager. | |
| 804 downloads.clear(); | |
| 805 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | |
| 806 ASSERT_EQ(2u, downloads.size()); | |
| 807 // We don't know the order of the downloads. | |
| 808 DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0]; | |
| 809 | 729 |
| 810 ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState()); | 730 ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState()); |
| 811 ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState()); | 731 ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState()); |
| 812 | 732 |
| 813 // Allow the first request to finish. | 733 // Allow the first request to finish. |
| 814 scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1)); | 734 scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1)); |
| 815 NavigateToURL(shell(), | 735 NavigateToURL(shell(), |
| 816 GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); | 736 GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); |
| 817 observer2->WaitForFinished(); // Wait for the third request. | 737 observer2->WaitForFinished(); // Wait for the third request. |
| 818 EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE)); | 738 EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE)); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 delayed_callbacks[0].Run(true); | 875 delayed_callbacks[0].Run(true); |
| 956 | 876 |
| 957 // *Now* the download should be complete. | 877 // *Now* the download should be complete. |
| 958 EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState()); | 878 EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState()); |
| 959 } | 879 } |
| 960 | 880 |
| 961 // Try to shutdown with a download in progress to make sure shutdown path | 881 // Try to shutdown with a download in progress to make sure shutdown path |
| 962 // works properly. | 882 // works properly. |
| 963 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) { | 883 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) { |
| 964 // Create a download that won't complete. | 884 // Create a download that won't complete. |
| 965 scoped_ptr<DownloadCreateObserver> observer( | 885 DownloadItem* download = StartDownloadAndReturnItem( |
| 966 CreateInProgressWaiter(shell(), 1)); | 886 GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl)); |
| 967 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl)); | |
| 968 observer->WaitForFinished(); | |
| 969 | 887 |
| 970 // Get the item. | 888 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); |
| 971 std::vector<DownloadItem*> items; | |
| 972 DownloadManagerForShell(shell())->GetAllDownloads(&items); | |
| 973 ASSERT_EQ(1u, items.size()); | |
| 974 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState()); | |
| 975 | 889 |
| 976 // Shutdown the download manager and make sure we get the right | 890 // Shutdown the download manager and make sure we get the right |
| 977 // notifications in the right order. | 891 // notifications in the right order. |
| 978 StrictMock<MockDownloadItemObserver> item_observer; | 892 StrictMock<MockDownloadItemObserver> item_observer; |
| 979 items[0]->AddObserver(&item_observer); | 893 download->AddObserver(&item_observer); |
| 980 MockDownloadManagerObserver manager_observer( | 894 MockDownloadManagerObserver manager_observer( |
| 981 DownloadManagerForShell(shell())); | 895 DownloadManagerForShell(shell())); |
| 982 // Don't care about ModelChanged() events. | 896 // Don't care about ModelChanged() events. |
| 983 EXPECT_CALL(manager_observer, ModelChanged(_)) | 897 EXPECT_CALL(manager_observer, ModelChanged(_)) |
| 984 .WillRepeatedly(Return()); | 898 .WillRepeatedly(Return()); |
| 985 { | 899 { |
| 986 InSequence notifications; | 900 InSequence notifications; |
| 987 | 901 |
| 988 EXPECT_CALL(manager_observer, MockManagerGoingDown( | 902 EXPECT_CALL(manager_observer, MockManagerGoingDown( |
| 989 DownloadManagerForShell(shell()))) | 903 DownloadManagerForShell(shell()))) |
| 990 .WillOnce(Return()); | 904 .WillOnce(Return()); |
| 991 EXPECT_CALL(item_observer, OnDownloadUpdated( | 905 EXPECT_CALL( |
| 992 AllOf(items[0], | 906 item_observer, |
| 993 Property(&DownloadItem::GetState, DownloadItem::CANCELLED)))) | 907 OnDownloadUpdated(AllOf(download, Property(&DownloadItem::GetState, |
| 908 DownloadItem::CANCELLED)))) |
| 994 .WillOnce(Return()); | 909 .WillOnce(Return()); |
| 995 EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0])) | 910 EXPECT_CALL(item_observer, OnDownloadDestroyed(download)) |
| 996 .WillOnce(Return()); | 911 .WillOnce(Return()); |
| 997 } | 912 } |
| 998 | 913 |
| 999 // See http://crbug.com/324525. If we have a refcount release/post task | 914 // See http://crbug.com/324525. If we have a refcount release/post task |
| 1000 // race, the second post will stall the IO thread long enough so that we'll | 915 // race, the second post will stall the IO thread long enough so that we'll |
| 1001 // lose the race and crash. The first stall is just to give the UI thread | 916 // lose the race and crash. The first stall is just to give the UI thread |
| 1002 // a chance to get the second stall onto the IO thread queue after the cancel | 917 // a chance to get the second stall onto the IO thread queue after the cancel |
| 1003 // message created by Shutdown and before the notification callback | 918 // message created by Shutdown and before the notification callback |
| 1004 // created by the IO thread in canceling the request. | 919 // created by the IO thread in canceling the request. |
| 1005 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 920 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 1006 base::Bind(&base::PlatformThread::Sleep, | 921 base::Bind(&base::PlatformThread::Sleep, |
| 1007 base::TimeDelta::FromMilliseconds(25))); | 922 base::TimeDelta::FromMilliseconds(25))); |
| 1008 DownloadManagerForShell(shell())->Shutdown(); | 923 DownloadManagerForShell(shell())->Shutdown(); |
| 1009 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 924 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 1010 base::Bind(&base::PlatformThread::Sleep, | 925 base::Bind(&base::PlatformThread::Sleep, |
| 1011 base::TimeDelta::FromMilliseconds(25))); | 926 base::TimeDelta::FromMilliseconds(25))); |
| 1012 items.clear(); | |
| 1013 } | 927 } |
| 1014 | 928 |
| 1015 // Try to shutdown just after we release the download file, by delaying | 929 // Try to shutdown just after we release the download file, by delaying |
| 1016 // release. | 930 // release. |
| 1017 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) { | 931 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) { |
| 1018 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell())); | 932 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell())); |
| 1019 | 933 |
| 1020 // Mark delegate for delayed open. | 934 // Mark delegate for delayed open. |
| 1021 GetDownloadManagerDelegate()->SetDelayedOpen(true); | 935 GetDownloadManagerDelegate()->SetDelayedOpen(true); |
| 1022 | 936 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1061 | 975 |
| 1062 MockDownloadItemObserver observer; | 976 MockDownloadItemObserver observer; |
| 1063 items[0]->AddObserver(&observer); | 977 items[0]->AddObserver(&observer); |
| 1064 EXPECT_CALL(observer, OnDownloadDestroyed(items[0])); | 978 EXPECT_CALL(observer, OnDownloadDestroyed(items[0])); |
| 1065 | 979 |
| 1066 // Shutdown the download manager. Mostly this is confirming a lack of | 980 // Shutdown the download manager. Mostly this is confirming a lack of |
| 1067 // crashes. | 981 // crashes. |
| 1068 DownloadManagerForShell(shell())->Shutdown(); | 982 DownloadManagerForShell(shell())->Shutdown(); |
| 1069 } | 983 } |
| 1070 | 984 |
| 1071 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) { | 985 // Test resumption with a response that contains strong validators. |
| 1072 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 986 IN_PROC_BROWSER_TEST_F(DownloadContentTest, Resume_WithStrongValidators) { |
| 1073 switches::kEnableDownloadResumption); | 987 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1074 ASSERT_TRUE(spawned_test_server()->Start()); | 988 switches::kEnableDownloadResumption); |
| 1075 | 989 |
| 1076 GURL url = spawned_test_server()->GetURL( | 990 TestDownloadRequestHandler request_handler; |
| 1077 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", | 991 TestDownloadRequestHandler::Parameters parameters = |
| 1078 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | 992 TestDownloadRequestHandler::Parameters::WithSingleInterruption(); |
| 1079 | 993 const TestDownloadRequestHandler::InjectedError interruption = |
| 1080 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); | 994 parameters.injected_errors.front(); |
| 1081 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); | 995 request_handler.StartServing(parameters); |
| 1082 | 996 |
| 1083 DownloadItem* download(StartDownloadAndReturnItem(url)); | 997 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1084 WaitForData(download, GetSafeBufferChunk()); | 998 WaitForInterrupt(download); |
| 1085 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); | 999 |
| 1086 | 1000 ASSERT_EQ(interruption.offset, download->GetReceivedBytes()); |
| 1087 // Confirm resumption while in progress doesn't do anything. | 1001 ASSERT_EQ(parameters.size, download->GetTotalBytes()); |
| 1088 download->Resume(); | 1002 |
| 1089 ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes()); | 1003 download->Resume(); |
| 1090 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); | 1004 WaitForCompletion(download); |
| 1091 | 1005 |
| 1092 // Tell the server to send the RST and confirm the interrupt happens. | 1006 ASSERT_EQ(parameters.size, download->GetReceivedBytes()); |
| 1093 ReleaseRSTAndConfirmInterruptForResume(download); | 1007 ASSERT_EQ(parameters.size, download->GetTotalBytes()); |
| 1094 ConfirmFileStatusForResume( | 1008 ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents( |
| 1095 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | 1009 parameters.pattern_generator_seed, parameters.size, |
| 1096 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | 1010 download->GetTargetFilePath())); |
| 1097 | 1011 |
| 1098 // Resume, confirming received bytes on resumption is correct. | 1012 // Characterization risk: The next portion of the test examines the requests |
| 1099 // Make sure no creation calls are included. | 1013 // that were sent out while downloading our resource. These requests |
| 1100 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0); | 1014 // correspond to the requests that were generated by the browser and the |
| 1101 int initial_size = 0; | 1015 // downloads system and may change as implementation details change. |
| 1102 DownloadUpdatedObserver initial_size_observer( | 1016 TestDownloadRequestHandler::CompletedRequests requests; |
| 1103 download, base::Bind(&InitialSizeFilter, &initial_size)); | 1017 request_handler.GetCompletedRequestInfo(&requests); |
| 1104 download->Resume(); | 1018 |
| 1105 initial_size_observer.WaitForEvent(); | 1019 ASSERT_EQ(2u, requests.size()); |
| 1106 EXPECT_EQ(GetSafeBufferChunk(), initial_size); | 1020 |
| 1107 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); | 1021 // The first request only transferrs bytes up until the interruption point. |
| 1108 | 1022 EXPECT_EQ(interruption.offset, requests[0].transferred_byte_count); |
| 1109 // and wait for expected data. | 1023 |
| 1110 WaitForData(download, GetSafeBufferChunk() * 2); | 1024 // The next request should only have transferred the remainder of the |
| 1111 | 1025 // resource. |
| 1112 // Tell the server to send the RST and confirm the interrupt happens. | 1026 EXPECT_EQ(parameters.size - interruption.offset, |
| 1113 ReleaseRSTAndConfirmInterruptForResume(download); | 1027 requests[1].transferred_byte_count); |
| 1114 ConfirmFileStatusForResume( | 1028 |
| 1115 download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3, | 1029 std::string value; |
| 1116 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | 1030 ASSERT_TRUE(requests[1].request_headers.GetHeader( |
| 1117 | 1031 net::HttpRequestHeaders::kIfRange, &value)); |
| 1118 // Resume and wait for completion. | 1032 EXPECT_EQ(parameters.etag, value); |
| 1119 DownloadUpdatedObserver completion_observer( | 1033 |
| 1120 download, base::Bind(DownloadCompleteFilter)); | 1034 ASSERT_TRUE(requests[1].request_headers.GetHeader( |
| 1121 download->Resume(); | 1035 net::HttpRequestHeaders::kRange, &value)); |
| 1122 completion_observer.WaitForEvent(); | 1036 EXPECT_EQ(base::StringPrintf("bytes=%" PRId64 "-", interruption.offset), |
| 1123 | 1037 value); |
| 1124 ConfirmFileStatusForResume( | 1038 } |
| 1125 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, | 1039 |
| 1126 base::FilePath(FILE_PATH_LITERAL("rangereset"))); | 1040 // A partial resumption results in an HTTP 200 response. I.e. the server ignored |
| 1127 | 1041 // the range request and sent the entire resource instead. For If-Range requests |
| 1128 // Confirm resumption while complete doesn't do anything. | 1042 // (as opposed to If-Match), the behavior for a precondition failure is also to |
| 1129 download->Resume(); | 1043 // respond with a 200. So this test case covers both validation failure and |
| 1130 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes()); | 1044 // ignoring the range request. |
| 1131 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState()); | |
| 1132 RunAllPendingInMessageLoop(); | |
| 1133 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes()); | |
| 1134 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState()); | |
| 1135 } | |
| 1136 | |
| 1137 // Confirm restart fallback happens if a range request is bounced. | |
| 1138 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) { | |
| 1139 base::CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 1140 switches::kEnableDownloadResumption); | |
| 1141 ASSERT_TRUE(spawned_test_server()->Start()); | |
| 1142 | |
| 1143 // Auto-restart if server doesn't handle ranges. | |
| 1144 GURL url = spawned_test_server()->GetURL(base::StringPrintf( | |
| 1145 // First download hits an RST, rest don't, no ranges. | |
| 1146 "rangereset?size=%d&rst_boundary=%d&" | |
| 1147 "token=NoRange&rst_limit=1&bounce_range", | |
| 1148 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | |
| 1149 | |
| 1150 // Start the download and wait for first data chunk. | |
| 1151 DownloadItem* download(StartDownloadAndReturnItem(url)); | |
| 1152 WaitForData(download, GetSafeBufferChunk()); | |
| 1153 | |
| 1154 RecordingDownloadObserver recorder(download); | |
| 1155 | |
| 1156 ReleaseRSTAndConfirmInterruptForResume(download); | |
| 1157 ConfirmFileStatusForResume( | |
| 1158 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | |
| 1159 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | |
| 1160 | |
| 1161 DownloadUpdatedObserver completion_observer( | |
| 1162 download, base::Bind(DownloadCompleteFilter)); | |
| 1163 download->Resume(); | |
| 1164 completion_observer.WaitForEvent(); | |
| 1165 | |
| 1166 ConfirmFileStatusForResume( | |
| 1167 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, | |
| 1168 base::FilePath(FILE_PATH_LITERAL("rangereset"))); | |
| 1169 | |
| 1170 static const RecordingDownloadObserver::RecordStruct expected_record[] = { | |
| 1171 // Result of RST | |
| 1172 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()}, | |
| 1173 // Starting continuation | |
| 1174 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()}, | |
| 1175 // Notification of receiving whole file. | |
| 1176 {DownloadItem::IN_PROGRESS, 0}, | |
| 1177 // Completion. | |
| 1178 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3}, | |
| 1179 }; | |
| 1180 | |
| 1181 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record)); | |
| 1182 } | |
| 1183 | |
| 1184 // Confirm we don't try to resume if we don't have a verifier. | |
| 1185 IN_PROC_BROWSER_TEST_F(DownloadContentTest, | 1045 IN_PROC_BROWSER_TEST_F(DownloadContentTest, |
| 1186 ResumeInterruptedDownloadNoVerifiers) { | 1046 Resume_RestartIfNotPartialResponse) { |
| 1187 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1047 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1188 switches::kEnableDownloadResumption); | 1048 switches::kEnableDownloadResumption); |
| 1189 ASSERT_TRUE(spawned_test_server()->Start()); | 1049 const int kOriginalPatternGeneratorSeed = 1; |
| 1190 | 1050 const int kNewPatternGeneratorSeed = 2; |
| 1191 GURL url = spawned_test_server()->GetURL(base::StringPrintf( | 1051 |
| 1192 // First download hits an RST, rest don't, no verifiers. | 1052 TestDownloadRequestHandler::Parameters parameters = |
| 1193 "rangereset?size=%d&rst_boundary=%d&" | 1053 TestDownloadRequestHandler::Parameters::WithSingleInterruption(); |
| 1194 "token=NoRange&rst_limit=1&no_verifiers", | 1054 parameters.pattern_generator_seed = kOriginalPatternGeneratorSeed; |
| 1195 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | 1055 const TestDownloadRequestHandler::InjectedError interruption = |
| 1196 | 1056 parameters.injected_errors.front(); |
| 1197 // Start the download and wait for first data chunk. | 1057 |
| 1198 DownloadItem* download(StartDownloadAndReturnItem(url)); | 1058 TestDownloadRequestHandler request_handler; |
| 1199 WaitForData(download, GetSafeBufferChunk()); | 1059 request_handler.StartServing(parameters); |
| 1200 | 1060 |
| 1201 RecordingDownloadObserver recorder(download); | 1061 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1202 | 1062 WaitForInterrupt(download); |
| 1203 ReleaseRSTAndConfirmInterruptForResume(download); | 1063 |
| 1204 ConfirmFileStatusForResume( | 1064 ASSERT_EQ(interruption.offset, download->GetReceivedBytes()); |
| 1205 download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | 1065 ASSERT_EQ(parameters.size, download->GetTotalBytes()); |
| 1206 base::FilePath()); | 1066 |
| 1207 | 1067 parameters = TestDownloadRequestHandler::Parameters(); |
| 1208 DownloadUpdatedObserver completion_observer( | 1068 parameters.support_byte_ranges = false; |
| 1209 download, base::Bind(DownloadCompleteFilter)); | 1069 parameters.pattern_generator_seed = kNewPatternGeneratorSeed; |
| 1210 download->Resume(); | 1070 request_handler.StartServing(parameters); |
| 1211 completion_observer.WaitForEvent(); | 1071 |
| 1212 | 1072 download->Resume(); |
| 1213 ConfirmFileStatusForResume( | 1073 WaitForCompletion(download); |
| 1214 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, | 1074 |
| 1215 base::FilePath(FILE_PATH_LITERAL("rangereset"))); | 1075 ASSERT_EQ(parameters.size, download->GetReceivedBytes()); |
| 1216 | 1076 ASSERT_EQ(parameters.size, download->GetTotalBytes()); |
| 1217 static const RecordingDownloadObserver::RecordStruct expected_record[] = { | 1077 ASSERT_NO_FATAL_FAILURE( |
| 1218 // Result of RST | 1078 ReadAndVerifyFileContents(kNewPatternGeneratorSeed, parameters.size, |
| 1219 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()}, | 1079 download->GetTargetFilePath())); |
| 1220 // Restart for lack of verifiers | 1080 |
| 1221 {DownloadItem::IN_PROGRESS, 0}, | 1081 // When the downloads system sees the full response, it should accept the |
| 1222 // Completion. | 1082 // response without restarting. On the network, we should deterministically |
| 1223 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3}, | 1083 // see two requests: |
| 1224 }; | 1084 // * The original request which transfers upto our interruption point. |
| 1225 | 1085 // * The resumption attempt, which receives the entire entity. |
| 1226 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record)); | 1086 TestDownloadRequestHandler::CompletedRequests requests; |
| 1227 } | 1087 request_handler.GetCompletedRequestInfo(&requests); |
| 1228 | 1088 |
| 1229 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) { | 1089 ASSERT_EQ(2u, requests.size()); |
| 1230 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1090 |
| 1231 switches::kEnableDownloadResumption); | 1091 // The first request only transfers data up to the interruption point. |
| 1232 ASSERT_TRUE(spawned_test_server()->Start()); | 1092 EXPECT_EQ(interruption.offset, requests[0].transferred_byte_count); |
| 1233 | 1093 |
| 1234 GURL url = spawned_test_server()->GetURL(base::StringPrintf( | 1094 // The second request transfers the entire response. |
| 1235 // First download hits an RST, rest don't | 1095 EXPECT_EQ(parameters.size, requests[1].transferred_byte_count); |
| 1236 "rangereset?size=%d&rst_boundary=%d&" | 1096 |
| 1237 "token=NoRange&rst_limit=1", | 1097 std::string value; |
| 1238 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | 1098 ASSERT_TRUE(requests[1].request_headers.GetHeader( |
| 1239 | 1099 net::HttpRequestHeaders::kIfRange, &value)); |
| 1240 // Start the download and wait for first data chunk. | 1100 EXPECT_EQ(parameters.etag, value); |
| 1241 DownloadItem* download(StartDownloadAndReturnItem(url)); | 1101 |
| 1242 WaitForData(download, GetSafeBufferChunk()); | 1102 ASSERT_TRUE(requests[1].request_headers.GetHeader( |
| 1243 | 1103 net::HttpRequestHeaders::kRange, &value)); |
| 1244 RecordingDownloadObserver recorder(download); | 1104 EXPECT_EQ(base::StringPrintf("bytes=%" PRId64 "-", interruption.offset), |
| 1245 | 1105 value); |
| 1246 ReleaseRSTAndConfirmInterruptForResume(download); | 1106 } |
| 1247 ConfirmFileStatusForResume( | 1107 |
| 1248 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | 1108 // Confirm we restart if we don't have a verifier. |
| 1249 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | 1109 IN_PROC_BROWSER_TEST_F(DownloadContentTest, Resume_RestartIfNoETag) { |
| 1110 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1111 switches::kEnableDownloadResumption); |
| 1112 const int kOriginalPatternGeneratorSeed = 1; |
| 1113 const int kNewPatternGeneratorSeed = 2; |
| 1114 |
| 1115 TestDownloadRequestHandler::Parameters parameters = |
| 1116 TestDownloadRequestHandler::Parameters::WithSingleInterruption(); |
| 1117 ASSERT_EQ(1u, parameters.injected_errors.size()); |
| 1118 parameters.etag.clear(); |
| 1119 parameters.pattern_generator_seed = kOriginalPatternGeneratorSeed; |
| 1120 |
| 1121 TestDownloadRequestHandler request_handler; |
| 1122 request_handler.StartServing(parameters); |
| 1123 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1124 WaitForInterrupt(download); |
| 1125 |
| 1126 parameters.pattern_generator_seed = kNewPatternGeneratorSeed; |
| 1127 parameters.ClearInjectedErrors(); |
| 1128 request_handler.StartServing(parameters); |
| 1129 |
| 1130 download->Resume(); |
| 1131 WaitForCompletion(download); |
| 1132 |
| 1133 ASSERT_EQ(parameters.size, download->GetReceivedBytes()); |
| 1134 ASSERT_EQ(parameters.size, download->GetTotalBytes()); |
| 1135 ASSERT_NO_FATAL_FAILURE( |
| 1136 ReadAndVerifyFileContents(kNewPatternGeneratorSeed, parameters.size, |
| 1137 download->GetTargetFilePath())); |
| 1138 |
| 1139 TestDownloadRequestHandler::CompletedRequests requests; |
| 1140 request_handler.GetCompletedRequestInfo(&requests); |
| 1141 |
| 1142 // Neither If-Range nor Range headers should be present in the second request. |
| 1143 ASSERT_EQ(2u, requests.size()); |
| 1144 std::string value; |
| 1145 EXPECT_FALSE(requests[1].request_headers.GetHeader( |
| 1146 net::HttpRequestHeaders::kIfRange, &value)); |
| 1147 EXPECT_FALSE(requests[1].request_headers.GetHeader( |
| 1148 net::HttpRequestHeaders::kRange, &value)); |
| 1149 } |
| 1150 |
| 1151 // Partial file goes missing before the download is resumed. The download should |
| 1152 // restart. |
| 1153 IN_PROC_BROWSER_TEST_F(DownloadContentTest, Resume_RestartIfNoPartialFile) { |
| 1154 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1155 switches::kEnableDownloadResumption); |
| 1156 TestDownloadRequestHandler::Parameters parameters = |
| 1157 TestDownloadRequestHandler::Parameters::WithSingleInterruption(); |
| 1158 |
| 1159 TestDownloadRequestHandler request_handler; |
| 1160 request_handler.StartServing(parameters); |
| 1161 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1162 WaitForInterrupt(download); |
| 1250 | 1163 |
| 1251 // Delete the intermediate file. | 1164 // Delete the intermediate file. |
| 1252 base::DeleteFile(download->GetFullPath(), false); | 1165 ASSERT_TRUE(base::PathExists(download->GetFullPath())); |
| 1253 | 1166 ASSERT_TRUE(base::DeleteFile(download->GetFullPath(), false)); |
| 1254 DownloadUpdatedObserver completion_observer( | 1167 |
| 1255 download, base::Bind(DownloadCompleteFilter)); | 1168 parameters.ClearInjectedErrors(); |
| 1256 download->Resume(); | 1169 request_handler.StartServing(parameters); |
| 1257 completion_observer.WaitForEvent(); | 1170 |
| 1258 | 1171 download->Resume(); |
| 1259 ConfirmFileStatusForResume( | 1172 WaitForCompletion(download); |
| 1260 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3, | 1173 |
| 1261 base::FilePath(FILE_PATH_LITERAL("rangereset"))); | 1174 ASSERT_EQ(parameters.size, download->GetReceivedBytes()); |
| 1262 | 1175 ASSERT_EQ(parameters.size, download->GetTotalBytes()); |
| 1263 static const RecordingDownloadObserver::RecordStruct expected_record[] = { | 1176 ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents( |
| 1264 // Result of RST | 1177 parameters.pattern_generator_seed, parameters.size, |
| 1265 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()}, | 1178 download->GetTargetFilePath())); |
| 1266 // Starting continuation | 1179 } |
| 1267 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()}, | 1180 |
| 1268 // Error because file isn't there. | 1181 IN_PROC_BROWSER_TEST_F(DownloadContentTest, Resume_RecoverFromInitFileError) { |
| 1269 {DownloadItem::INTERRUPTED, 0}, | 1182 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1270 // Restart. | 1183 switches::kEnableDownloadResumption); |
| 1271 {DownloadItem::IN_PROGRESS, 0}, | 1184 TestDownloadRequestHandler request_handler; |
| 1272 // Completion. | 1185 request_handler.StartServing(TestDownloadRequestHandler::Parameters()); |
| 1273 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3}, | |
| 1274 }; | |
| 1275 | |
| 1276 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record)); | |
| 1277 } | |
| 1278 | |
| 1279 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) { | |
| 1280 base::CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 1281 switches::kEnableDownloadResumption); | |
| 1282 GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); | |
| 1283 | 1186 |
| 1284 // Setup the error injector. | 1187 // Setup the error injector. |
| 1285 scoped_refptr<TestFileErrorInjector> injector( | 1188 scoped_refptr<TestFileErrorInjector> injector( |
| 1286 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); | 1189 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); |
| 1287 | 1190 |
| 1288 TestFileErrorInjector::FileErrorInfo err = { | 1191 const TestFileErrorInjector::FileErrorInfo err = { |
| 1289 url.spec(), | 1192 request_handler.url().spec(), |
| 1290 TestFileErrorInjector::FILE_OPERATION_INITIALIZE, | 1193 TestFileErrorInjector::FILE_OPERATION_INITIALIZE, 0, |
| 1291 0, | 1194 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE}; |
| 1292 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE | |
| 1293 }; | |
| 1294 injector->AddError(err); | 1195 injector->AddError(err); |
| 1295 injector->InjectErrors(); | 1196 injector->InjectErrors(); |
| 1296 | 1197 |
| 1297 // Start and watch for interrupt. | 1198 // Start and watch for interrupt. |
| 1298 scoped_ptr<DownloadTestObserver> int_observer( | 1199 DownloadItem* download(StartDownloadAndReturnItem(request_handler.url())); |
| 1299 CreateInterruptedWaiter(shell(), 1)); | 1200 WaitForInterrupt(download); |
| 1300 DownloadItem* download(StartDownloadAndReturnItem(url)); | |
| 1301 int_observer->WaitForFinished(); | |
| 1302 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); | 1201 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); |
| 1303 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, | 1202 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| 1304 download->GetLastReason()); | 1203 download->GetLastReason()); |
| 1305 EXPECT_EQ(0, download->GetReceivedBytes()); | 1204 EXPECT_EQ(0, download->GetReceivedBytes()); |
| 1306 EXPECT_TRUE(download->GetFullPath().empty()); | 1205 EXPECT_TRUE(download->GetFullPath().empty()); |
| 1307 EXPECT_TRUE(download->GetTargetFilePath().empty()); | 1206 EXPECT_TRUE(download->GetTargetFilePath().empty()); |
| 1308 | 1207 |
| 1309 // We need to make sure that any cross-thread downloads communication has | 1208 // We need to make sure that any cross-thread downloads communication has |
| 1310 // quiesced before clearing and injecting the new errors, as the | 1209 // quiesced before clearing and injecting the new errors, as the |
| 1311 // InjectErrors() routine alters the currently in use download file | 1210 // InjectErrors() routine alters the currently in use download file |
| 1312 // factory, which is a file thread object. | 1211 // factory, which is a file thread object. |
| 1313 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1212 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1314 RunAllPendingInMessageLoop(); | 1213 RunAllPendingInMessageLoop(); |
| 1315 | 1214 |
| 1316 // Clear the old errors list. | 1215 // Clear the old errors list. |
| 1317 injector->ClearErrors(); | 1216 injector->ClearErrors(); |
| 1318 injector->InjectErrors(); | 1217 injector->InjectErrors(); |
| 1319 | 1218 |
| 1320 // Resume and watch completion. | 1219 // Resume and watch completion. |
| 1321 DownloadUpdatedObserver completion_observer( | |
| 1322 download, base::Bind(DownloadCompleteFilter)); | |
| 1323 download->Resume(); | 1220 download->Resume(); |
| 1324 completion_observer.WaitForEvent(); | 1221 WaitForCompletion(download); |
| 1325 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); | 1222 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); |
| 1326 } | 1223 } |
| 1327 | 1224 |
| 1328 IN_PROC_BROWSER_TEST_F(DownloadContentTest, | 1225 IN_PROC_BROWSER_TEST_F(DownloadContentTest, |
| 1329 ResumeWithFileIntermediateRenameError) { | 1226 Resume_RecoverFromIntermediateFileRenameError) { |
| 1330 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1227 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1331 switches::kEnableDownloadResumption); | 1228 switches::kEnableDownloadResumption); |
| 1332 GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); | 1229 TestDownloadRequestHandler request_handler; |
| 1230 request_handler.StartServing(TestDownloadRequestHandler::Parameters()); |
| 1333 | 1231 |
| 1334 // Setup the error injector. | 1232 // Setup the error injector. |
| 1335 scoped_refptr<TestFileErrorInjector> injector( | 1233 scoped_refptr<TestFileErrorInjector> injector( |
| 1336 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); | 1234 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); |
| 1337 | 1235 |
| 1338 TestFileErrorInjector::FileErrorInfo err = { | 1236 const TestFileErrorInjector::FileErrorInfo err = { |
| 1339 url.spec(), | 1237 request_handler.url().spec(), |
| 1340 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY, | 1238 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY, 0, |
| 1341 0, | 1239 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE}; |
| 1342 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE | |
| 1343 }; | |
| 1344 injector->AddError(err); | 1240 injector->AddError(err); |
| 1345 injector->InjectErrors(); | 1241 injector->InjectErrors(); |
| 1346 | 1242 |
| 1347 // Start and watch for interrupt. | 1243 // Start and watch for interrupt. |
| 1348 scoped_ptr<DownloadTestObserver> int_observer( | 1244 DownloadItem* download(StartDownloadAndReturnItem(request_handler.url())); |
| 1349 CreateInterruptedWaiter(shell(), 1)); | 1245 WaitForInterrupt(download); |
| 1350 DownloadItem* download(StartDownloadAndReturnItem(url)); | |
| 1351 int_observer->WaitForFinished(); | |
| 1352 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); | 1246 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); |
| 1353 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, | 1247 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| 1354 download->GetLastReason()); | 1248 download->GetLastReason()); |
| 1355 EXPECT_TRUE(download->GetFullPath().empty()); | 1249 EXPECT_TRUE(download->GetFullPath().empty()); |
| 1356 // Target path will have been set after file name determination. GetFullPath() | 1250 // Target path will have been set after file name determination. GetFullPath() |
| 1357 // being empty is sufficient to signal that filename determination needs to be | 1251 // being empty is sufficient to signal that filename determination needs to be |
| 1358 // redone. | 1252 // redone. |
| 1359 EXPECT_FALSE(download->GetTargetFilePath().empty()); | 1253 EXPECT_FALSE(download->GetTargetFilePath().empty()); |
| 1360 | 1254 |
| 1361 // We need to make sure that any cross-thread downloads communication has | 1255 // We need to make sure that any cross-thread downloads communication has |
| 1362 // quiesced before clearing and injecting the new errors, as the | 1256 // quiesced before clearing and injecting the new errors, as the |
| 1363 // InjectErrors() routine alters the currently in use download file | 1257 // InjectErrors() routine alters the currently in use download file |
| 1364 // factory, which is a file thread object. | 1258 // factory, which is a file thread object. |
| 1365 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1259 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1366 RunAllPendingInMessageLoop(); | 1260 RunAllPendingInMessageLoop(); |
| 1367 | 1261 |
| 1368 // Clear the old errors list. | 1262 // Clear the old errors list. |
| 1369 injector->ClearErrors(); | 1263 injector->ClearErrors(); |
| 1370 injector->InjectErrors(); | 1264 injector->InjectErrors(); |
| 1371 | 1265 |
| 1372 // Resume and watch completion. | |
| 1373 DownloadUpdatedObserver completion_observer( | |
| 1374 download, base::Bind(DownloadCompleteFilter)); | |
| 1375 download->Resume(); | 1266 download->Resume(); |
| 1376 completion_observer.WaitForEvent(); | 1267 WaitForCompletion(download); |
| 1377 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); | 1268 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); |
| 1378 } | 1269 } |
| 1379 | 1270 |
| 1380 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) { | 1271 IN_PROC_BROWSER_TEST_F(DownloadContentTest, |
| 1272 Resume_RecoverFromFinalRenameError) { |
| 1381 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1273 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1382 switches::kEnableDownloadResumption); | 1274 switches::kEnableDownloadResumption); |
| 1383 GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); | 1275 TestDownloadRequestHandler request_handler; |
| 1276 request_handler.StartServing(TestDownloadRequestHandler::Parameters()); |
| 1384 | 1277 |
| 1385 // Setup the error injector. | 1278 // Setup the error injector. |
| 1386 scoped_refptr<TestFileErrorInjector> injector( | 1279 scoped_refptr<TestFileErrorInjector> injector( |
| 1387 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); | 1280 TestFileErrorInjector::Create(DownloadManagerForShell(shell()))); |
| 1388 | 1281 |
| 1389 DownloadManagerForShell(shell())->RemoveAllDownloads(); | 1282 DownloadManagerForShell(shell())->RemoveAllDownloads(); |
| 1390 TestFileErrorInjector::FileErrorInfo err = { | 1283 TestFileErrorInjector::FileErrorInfo err = { |
| 1391 url.spec(), | 1284 request_handler.url().spec(), |
| 1392 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE, | 1285 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE, 0, |
| 1393 0, | 1286 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE}; |
| 1394 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE | |
| 1395 }; | |
| 1396 injector->AddError(err); | 1287 injector->AddError(err); |
| 1397 injector->InjectErrors(); | 1288 injector->InjectErrors(); |
| 1398 | 1289 |
| 1399 // Start and watch for interrupt. | 1290 // Start and watch for interrupt. |
| 1400 scoped_ptr<DownloadTestObserver> int_observer( | 1291 DownloadItem* download(StartDownloadAndReturnItem(request_handler.url())); |
| 1401 CreateInterruptedWaiter(shell(), 1)); | 1292 WaitForInterrupt(download); |
| 1402 DownloadItem* download(StartDownloadAndReturnItem(url)); | |
| 1403 int_observer->WaitForFinished(); | |
| 1404 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); | 1293 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); |
| 1405 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, | 1294 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, |
| 1406 download->GetLastReason()); | 1295 download->GetLastReason()); |
| 1407 EXPECT_TRUE(download->GetFullPath().empty()); | 1296 EXPECT_TRUE(download->GetFullPath().empty()); |
| 1408 // Target path should still be intact. | 1297 // Target path should still be intact. |
| 1409 EXPECT_FALSE(download->GetTargetFilePath().empty()); | 1298 EXPECT_FALSE(download->GetTargetFilePath().empty()); |
| 1410 | 1299 |
| 1411 // We need to make sure that any cross-thread downloads communication has | 1300 // We need to make sure that any cross-thread downloads communication has |
| 1412 // quiesced before clearing and injecting the new errors, as the | 1301 // quiesced before clearing and injecting the new errors, as the |
| 1413 // InjectErrors() routine alters the currently in use download file | 1302 // InjectErrors() routine alters the currently in use download file |
| 1414 // factory, which is a file thread object. | 1303 // factory, which is a file thread object. |
| 1415 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1304 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1416 RunAllPendingInMessageLoop(); | 1305 RunAllPendingInMessageLoop(); |
| 1417 | 1306 |
| 1418 // Clear the old errors list. | 1307 // Clear the old errors list. |
| 1419 injector->ClearErrors(); | 1308 injector->ClearErrors(); |
| 1420 injector->InjectErrors(); | 1309 injector->InjectErrors(); |
| 1421 | 1310 |
| 1422 // Resume and watch completion. | |
| 1423 DownloadUpdatedObserver completion_observer( | |
| 1424 download, base::Bind(DownloadCompleteFilter)); | |
| 1425 download->Resume(); | 1311 download->Resume(); |
| 1426 completion_observer.WaitForEvent(); | 1312 WaitForCompletion(download); |
| 1427 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); | 1313 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE); |
| 1428 } | 1314 } |
| 1429 | 1315 |
| 1430 // An interrupted download should remove the intermediate file when it is | 1316 // An interrupted download should remove the intermediate file when it is |
| 1431 // cancelled. | 1317 // cancelled. |
| 1432 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) { | 1318 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) { |
| 1433 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1319 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1434 switches::kEnableDownloadResumption); | 1320 switches::kEnableDownloadResumption); |
| 1435 ASSERT_TRUE(spawned_test_server()->Start()); | 1321 TestDownloadRequestHandler request_handler; |
| 1322 request_handler.StartServing( |
| 1323 TestDownloadRequestHandler::Parameters::WithSingleInterruption()); |
| 1436 | 1324 |
| 1437 GURL url1 = spawned_test_server()->GetURL( | 1325 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1438 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", | 1326 WaitForInterrupt(download); |
| 1439 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | |
| 1440 | 1327 |
| 1441 DownloadItem* download(StartDownloadAndReturnItem(url1)); | 1328 base::FilePath intermediate_path = download->GetFullPath(); |
| 1442 WaitForData(download, GetSafeBufferChunk()); | |
| 1443 | |
| 1444 ReleaseRSTAndConfirmInterruptForResume(download); | |
| 1445 ConfirmFileStatusForResume( | |
| 1446 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | |
| 1447 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | |
| 1448 | |
| 1449 base::FilePath intermediate_path(download->GetFullPath()); | |
| 1450 ASSERT_FALSE(intermediate_path.empty()); | 1329 ASSERT_FALSE(intermediate_path.empty()); |
| 1451 EXPECT_TRUE(base::PathExists(intermediate_path)); | 1330 ASSERT_TRUE(base::PathExists(intermediate_path)); |
| 1452 | 1331 |
| 1453 download->Cancel(true /* user_cancel */); | 1332 download->Cancel(true /* user_cancel */); |
| 1454 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1333 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1455 RunAllPendingInMessageLoop(); | 1334 RunAllPendingInMessageLoop(); |
| 1456 | 1335 |
| 1457 // The intermediate file should now be gone. | 1336 // The intermediate file should now be gone. |
| 1458 EXPECT_FALSE(base::PathExists(intermediate_path)); | 1337 EXPECT_FALSE(base::PathExists(intermediate_path)); |
| 1459 EXPECT_TRUE(download->GetFullPath().empty()); | 1338 EXPECT_TRUE(download->GetFullPath().empty()); |
| 1460 } | 1339 } |
| 1461 | 1340 |
| 1462 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) { | 1341 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveInterruptedDownload) { |
| 1463 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1342 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1464 switches::kEnableDownloadResumption); | 1343 switches::kEnableDownloadResumption); |
| 1465 ASSERT_TRUE(spawned_test_server()->Start()); | 1344 TestDownloadRequestHandler request_handler; |
| 1345 request_handler.StartServing( |
| 1346 TestDownloadRequestHandler::Parameters::WithSingleInterruption()); |
| 1466 | 1347 |
| 1467 // An interrupted download should remove the intermediate file when it is | 1348 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1468 // removed. | 1349 WaitForInterrupt(download); |
| 1469 { | |
| 1470 GURL url1 = spawned_test_server()->GetURL( | |
| 1471 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", | |
| 1472 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | |
| 1473 | 1350 |
| 1474 DownloadItem* download(StartDownloadAndReturnItem(url1)); | 1351 base::FilePath intermediate_path = download->GetFullPath(); |
| 1475 WaitForData(download, GetSafeBufferChunk()); | 1352 ASSERT_FALSE(intermediate_path.empty()); |
| 1476 ReleaseRSTAndConfirmInterruptForResume(download); | 1353 ASSERT_TRUE(base::PathExists(intermediate_path)); |
| 1477 ConfirmFileStatusForResume( | |
| 1478 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | |
| 1479 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | |
| 1480 | 1354 |
| 1481 base::FilePath intermediate_path(download->GetFullPath()); | 1355 download->Remove(); |
| 1482 ASSERT_FALSE(intermediate_path.empty()); | 1356 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1483 EXPECT_TRUE(base::PathExists(intermediate_path)); | 1357 RunAllPendingInMessageLoop(); |
| 1484 | 1358 |
| 1485 download->Remove(); | 1359 // The intermediate file should now be gone. |
| 1486 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1360 EXPECT_FALSE(base::PathExists(intermediate_path)); |
| 1487 RunAllPendingInMessageLoop(); | 1361 } |
| 1488 | 1362 |
| 1489 // The intermediate file should now be gone. | 1363 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveCompletedDownload) { |
| 1490 EXPECT_FALSE(base::PathExists(intermediate_path)); | |
| 1491 } | |
| 1492 | |
| 1493 // A completed download shouldn't delete the downloaded file when it is | 1364 // A completed download shouldn't delete the downloaded file when it is |
| 1494 // removed. | 1365 // removed. |
| 1495 { | 1366 TestDownloadRequestHandler request_handler; |
| 1496 // Start the second download and wait until it's done. | 1367 request_handler.StartServing(TestDownloadRequestHandler::Parameters()); |
| 1497 GURL url2(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); | 1368 scoped_ptr<DownloadTestObserver> completion_observer( |
| 1498 scoped_ptr<DownloadTestObserver> completion_observer( | 1369 CreateWaiter(shell(), 1)); |
| 1499 CreateWaiter(shell(), 1)); | 1370 DownloadItem* download(StartDownloadAndReturnItem(request_handler.url())); |
| 1500 DownloadItem* download(StartDownloadAndReturnItem(url2)); | 1371 completion_observer->WaitForFinished(); |
| 1501 completion_observer->WaitForFinished(); | |
| 1502 | 1372 |
| 1503 // The target path should exist. | 1373 // The target path should exist. |
| 1504 base::FilePath target_path(download->GetTargetFilePath()); | 1374 base::FilePath target_path(download->GetTargetFilePath()); |
| 1505 EXPECT_TRUE(base::PathExists(target_path)); | 1375 EXPECT_TRUE(base::PathExists(target_path)); |
| 1506 download->Remove(); | 1376 download->Remove(); |
| 1507 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1377 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1508 RunAllPendingInMessageLoop(); | 1378 RunAllPendingInMessageLoop(); |
| 1509 | 1379 |
| 1510 // The file should still exist. | 1380 // The file should still exist. |
| 1511 EXPECT_TRUE(base::PathExists(target_path)); | 1381 EXPECT_TRUE(base::PathExists(target_path)); |
| 1512 } | |
| 1513 } | 1382 } |
| 1514 | 1383 |
| 1515 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) { | 1384 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) { |
| 1516 SetupEnsureNoPendingDownloads(); | |
| 1517 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1385 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1518 switches::kEnableDownloadResumption); | 1386 switches::kEnableDownloadResumption); |
| 1519 ASSERT_TRUE(spawned_test_server()->Start()); | 1387 TestDownloadRequestHandler::Parameters parameters = |
| 1388 TestDownloadRequestHandler::Parameters::WithSingleInterruption(); |
| 1389 TestDownloadRequestHandler request_handler; |
| 1390 request_handler.StartServing(parameters); |
| 1520 | 1391 |
| 1521 GURL url = spawned_test_server()->GetURL( | 1392 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1522 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", | 1393 WaitForInterrupt(download); |
| 1523 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | |
| 1524 | |
| 1525 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); | |
| 1526 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); | |
| 1527 | |
| 1528 DownloadItem* download(StartDownloadAndReturnItem(url)); | |
| 1529 WaitForData(download, GetSafeBufferChunk()); | |
| 1530 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); | |
| 1531 | |
| 1532 // Tell the server to send the RST and confirm the interrupt happens. | |
| 1533 ReleaseRSTAndConfirmInterruptForResume(download); | |
| 1534 ConfirmFileStatusForResume( | |
| 1535 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | |
| 1536 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | |
| 1537 | 1394 |
| 1538 base::FilePath intermediate_path(download->GetFullPath()); | 1395 base::FilePath intermediate_path(download->GetFullPath()); |
| 1539 ASSERT_FALSE(intermediate_path.empty()); | 1396 ASSERT_FALSE(intermediate_path.empty()); |
| 1540 EXPECT_TRUE(base::PathExists(intermediate_path)); | 1397 EXPECT_TRUE(base::PathExists(intermediate_path)); |
| 1541 | 1398 |
| 1542 // Resume and remove download. We expect only a single OnDownloadCreated() | 1399 // Resume and remove download. We expect only a single OnDownloadCreated() |
| 1543 // call, and that's for the second download created below. | 1400 // call, and that's for the second download created below. |
| 1401 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); |
| 1544 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); | 1402 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); |
| 1403 |
| 1404 TestRequestStartHandler request_start_handler; |
| 1405 parameters.on_start_handler = request_start_handler.GetOnStartHandler(); |
| 1406 request_handler.StartServing(parameters); |
| 1407 |
| 1545 download->Resume(); | 1408 download->Resume(); |
| 1409 request_start_handler.WaitForCallback(); |
| 1410 |
| 1411 // At this point, the download resumption request has been sent out, but the |
| 1412 // reponse hasn't been received yet. |
| 1546 download->Remove(); | 1413 download->Remove(); |
| 1547 | 1414 |
| 1415 request_start_handler.RespondWith(std::string(), net::OK); |
| 1416 |
| 1548 // The intermediate file should now be gone. | 1417 // The intermediate file should now be gone. |
| 1549 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1418 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1550 RunAllPendingInMessageLoop(); | 1419 RunAllPendingInMessageLoop(); |
| 1551 EXPECT_FALSE(base::PathExists(intermediate_path)); | 1420 EXPECT_FALSE(base::PathExists(intermediate_path)); |
| 1552 | 1421 |
| 1553 // Start the second download and wait until it's done. The test server is | 1422 parameters.ClearInjectedErrors(); |
| 1554 // single threaded. The response to this download request should follow the | 1423 parameters.on_start_handler.Reset(); |
| 1555 // response to the previous resumption request. | 1424 request_handler.StartServing(parameters); |
| 1556 GURL url2( | |
| 1557 spawned_test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); | |
| 1558 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); | |
| 1559 | 1425 |
| 1426 // Start the second download and wait until it's done. This exercises the |
| 1427 // entire downloads stack and effectively flushes all of our worker threads. |
| 1428 // We are testing whether the URL request created in the previous |
| 1429 // DownloadItem::Resume() call reulted in a new download or not. |
| 1430 NavigateToURLAndWaitForDownload(shell(), request_handler.url(), |
| 1431 DownloadItem::COMPLETE); |
| 1560 EXPECT_TRUE(EnsureNoPendingDownloads()); | 1432 EXPECT_TRUE(EnsureNoPendingDownloads()); |
| 1561 } | 1433 } |
| 1562 | 1434 |
| 1563 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) { | 1435 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) { |
| 1564 SetupEnsureNoPendingDownloads(); | |
| 1565 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1436 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1566 switches::kEnableDownloadResumption); | 1437 switches::kEnableDownloadResumption); |
| 1567 ASSERT_TRUE(spawned_test_server()->Start()); | 1438 TestDownloadRequestHandler::Parameters parameters = |
| 1439 TestDownloadRequestHandler::Parameters::WithSingleInterruption(); |
| 1440 TestDownloadRequestHandler request_handler; |
| 1441 request_handler.StartServing(parameters); |
| 1568 | 1442 |
| 1569 GURL url = spawned_test_server()->GetURL( | 1443 DownloadItem* download = StartDownloadAndReturnItem(request_handler.url()); |
| 1570 base::StringPrintf("rangereset?size=%d&rst_boundary=%d", | 1444 WaitForInterrupt(download); |
| 1571 GetSafeBufferChunk() * 3, GetSafeBufferChunk())); | |
| 1572 | |
| 1573 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); | |
| 1574 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); | |
| 1575 | |
| 1576 DownloadItem* download(StartDownloadAndReturnItem(url)); | |
| 1577 WaitForData(download, GetSafeBufferChunk()); | |
| 1578 ::testing::Mock::VerifyAndClearExpectations(&dm_observer); | |
| 1579 | |
| 1580 // Tell the server to send the RST and confirm the interrupt happens. | |
| 1581 ReleaseRSTAndConfirmInterruptForResume(download); | |
| 1582 ConfirmFileStatusForResume( | |
| 1583 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3, | |
| 1584 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload"))); | |
| 1585 | 1445 |
| 1586 base::FilePath intermediate_path(download->GetFullPath()); | 1446 base::FilePath intermediate_path(download->GetFullPath()); |
| 1587 ASSERT_FALSE(intermediate_path.empty()); | 1447 ASSERT_FALSE(intermediate_path.empty()); |
| 1588 EXPECT_TRUE(base::PathExists(intermediate_path)); | 1448 EXPECT_TRUE(base::PathExists(intermediate_path)); |
| 1589 | 1449 |
| 1590 // Resume and cancel download. We expect only a single OnDownloadCreated() | 1450 // Resume and remove download. We expect only a single OnDownloadCreated() |
| 1591 // call, and that's for the second download created below. | 1451 // call, and that's for the second download created below. |
| 1452 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell())); |
| 1592 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); | 1453 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1); |
| 1454 |
| 1455 TestRequestStartHandler request_start_handler; |
| 1456 parameters.on_start_handler = request_start_handler.GetOnStartHandler(); |
| 1457 request_handler.StartServing(parameters); |
| 1458 |
| 1593 download->Resume(); | 1459 download->Resume(); |
| 1594 download->Cancel(true); | 1460 request_start_handler.WaitForCallback(); |
| 1461 |
| 1462 // At this point, the download item has initiated a network request for the |
| 1463 // resumption attempt, but hasn't received a response yet. |
| 1464 download->Cancel(true /* user_cancel */); |
| 1465 |
| 1466 request_start_handler.RespondWith(std::string(), net::OK); |
| 1595 | 1467 |
| 1596 // The intermediate file should now be gone. | 1468 // The intermediate file should now be gone. |
| 1469 RunAllPendingInMessageLoop(BrowserThread::IO); |
| 1597 RunAllPendingInMessageLoop(BrowserThread::FILE); | 1470 RunAllPendingInMessageLoop(BrowserThread::FILE); |
| 1598 RunAllPendingInMessageLoop(); | 1471 RunAllPendingInMessageLoop(); |
| 1599 EXPECT_FALSE(base::PathExists(intermediate_path)); | 1472 EXPECT_FALSE(base::PathExists(intermediate_path)); |
| 1600 EXPECT_TRUE(download->GetFullPath().empty()); | |
| 1601 | 1473 |
| 1602 // Start the second download and wait until it's done. The test server is | 1474 parameters.ClearInjectedErrors(); |
| 1603 // single threaded. The response to this download request should follow the | 1475 parameters.on_start_handler.Reset(); |
| 1604 // response to the previous resumption request. | 1476 request_handler.StartServing(parameters); |
| 1605 GURL url2( | |
| 1606 spawned_test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); | |
| 1607 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); | |
| 1608 | 1477 |
| 1478 // Start the second download and wait until it's done. This exercises the |
| 1479 // entire downloads stack and effectively flushes all of our worker threads. |
| 1480 // We are testing whether the URL request created in the previous |
| 1481 // DownloadItem::Resume() call reulted in a new download or not. |
| 1482 NavigateToURLAndWaitForDownload(shell(), request_handler.url(), |
| 1483 DownloadItem::COMPLETE); |
| 1609 EXPECT_TRUE(EnsureNoPendingDownloads()); | 1484 EXPECT_TRUE(EnsureNoPendingDownloads()); |
| 1610 } | 1485 } |
| 1611 | 1486 |
| 1612 // Check that the cookie policy is correctly updated when downloading a file | 1487 // Check that the cookie policy is correctly updated when downloading a file |
| 1613 // that redirects cross origin. | 1488 // that redirects cross origin. |
| 1614 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) { | 1489 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) { |
| 1615 ASSERT_TRUE(spawned_test_server()->Start()); | 1490 net::EmbeddedTestServer origin_one; |
| 1616 net::HostPortPair host_port = spawned_test_server()->host_port_pair(); | 1491 net::EmbeddedTestServer origin_two; |
| 1617 DCHECK_EQ(host_port.host(), std::string("127.0.0.1")); | 1492 ASSERT_TRUE(origin_one.Start()); |
| 1493 ASSERT_TRUE(origin_two.Start()); |
| 1618 | 1494 |
| 1619 // Block third-party cookies. | 1495 // Block third-party cookies. |
| 1620 ShellNetworkDelegate::SetAcceptAllCookies(false); | 1496 ShellNetworkDelegate::SetAcceptAllCookies(false); |
| 1621 | 1497 |
| 1622 // |url| redirects to a different origin |download| which tries to set a | 1498 // |url| redirects to a different origin |download| which tries to set a |
| 1623 // cookie. | 1499 // cookie. |
| 1624 std::string download(base::StringPrintf( | 1500 base::StringPairs cookie_header; |
| 1625 "http://localhost:%d/set-cookie?A=B", host_port.port())); | 1501 cookie_header.push_back( |
| 1626 GURL url(spawned_test_server()->GetURL("server-redirect?" + download)); | 1502 std::make_pair(std::string("Set-Cookie"), std::string("A=B"))); |
| 1503 origin_one.RegisterRequestHandler(CreateBasicResponseHandler( |
| 1504 "/foo", cookie_header, "application/octet-stream", "abcd")); |
| 1505 origin_two.RegisterRequestHandler( |
| 1506 CreateRedirectHandler("/bar", origin_one.GetURL("/foo"))); |
| 1627 | 1507 |
| 1628 // Download the file. | 1508 // Download the file. |
| 1629 SetupEnsureNoPendingDownloads(); | 1509 SetupEnsureNoPendingDownloads(); |
| 1630 scoped_ptr<DownloadUrlParameters> dl_params( | 1510 scoped_ptr<DownloadUrlParameters> download_parameters( |
| 1631 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url)); | 1511 DownloadUrlParameters::FromWebContents(shell()->web_contents(), |
| 1512 origin_two.GetURL("/bar"))); |
| 1632 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1)); | 1513 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1)); |
| 1633 DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass()); | 1514 DownloadManagerForShell(shell())->DownloadUrl(download_parameters.Pass()); |
| 1634 observer->WaitForFinished(); | 1515 observer->WaitForFinished(); |
| 1635 | 1516 |
| 1636 // Get the important info from other threads and check it. | 1517 // Get the important info from other threads and check it. |
| 1637 EXPECT_TRUE(EnsureNoPendingDownloads()); | 1518 EXPECT_TRUE(EnsureNoPendingDownloads()); |
| 1638 | 1519 |
| 1639 std::vector<DownloadItem*> downloads; | 1520 std::vector<DownloadItem*> downloads; |
| 1640 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | 1521 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); |
| 1641 ASSERT_EQ(1u, downloads.size()); | 1522 ASSERT_EQ(1u, downloads.size()); |
| 1642 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState()); | 1523 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState()); |
| 1643 | 1524 |
| 1644 // Check that the cookies were correctly set. | 1525 // Check that the cookies were correctly set. |
| 1645 EXPECT_EQ("A=B", | 1526 EXPECT_EQ("A=B", |
| 1646 content::GetCookies(shell()->web_contents()->GetBrowserContext(), | 1527 content::GetCookies(shell()->web_contents()->GetBrowserContext(), |
| 1647 GURL(download))); | 1528 origin_one.GetURL("/"))); |
| 1648 } | 1529 } |
| 1649 | 1530 |
| 1650 // A filename suggestion specified via a @download attribute should not be | 1531 // A filename suggestion specified via a @download attribute should not be |
| 1651 // effective if the final download URL is in another origin from the original | 1532 // effective if the final download URL is in another origin from the original |
| 1652 // download URL. | 1533 // download URL. |
| 1653 IN_PROC_BROWSER_TEST_F(DownloadContentTest, | 1534 IN_PROC_BROWSER_TEST_F(DownloadContentTest, |
| 1654 DownloadAttributeCrossOriginRedirect) { | 1535 DownloadAttributeCrossOriginRedirect) { |
| 1655 net::EmbeddedTestServer origin_one; | 1536 net::EmbeddedTestServer origin_one; |
| 1656 net::EmbeddedTestServer origin_two; | 1537 net::EmbeddedTestServer origin_two; |
| 1657 ASSERT_TRUE(origin_one.Start()); | 1538 ASSERT_TRUE(origin_one.Start()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1669 GURL download_url = origin_one.GetURL("/ping"); | 1550 GURL download_url = origin_one.GetURL("/ping"); |
| 1670 GURL referrer_url = origin_one.GetURL( | 1551 GURL referrer_url = origin_one.GetURL( |
| 1671 std::string("/download-attribute.html?target=") + download_url.spec()); | 1552 std::string("/download-attribute.html?target=") + download_url.spec()); |
| 1672 | 1553 |
| 1673 // <origin_one>/download-attribute.html initiates a download of | 1554 // <origin_one>/download-attribute.html initiates a download of |
| 1674 // <origin_one>/ping, which redirects to <origin_two>/download. | 1555 // <origin_one>/ping, which redirects to <origin_two>/download. |
| 1675 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); | 1556 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); |
| 1676 origin_one.RegisterRequestHandler( | 1557 origin_one.RegisterRequestHandler( |
| 1677 CreateRedirectHandler("/ping", origin_two.GetURL("/download"))); | 1558 CreateRedirectHandler("/ping", origin_two.GetURL("/download"))); |
| 1678 origin_two.RegisterRequestHandler(CreateBasicResponseHandler( | 1559 origin_two.RegisterRequestHandler(CreateBasicResponseHandler( |
| 1679 "/download", "application/octet-stream", "Hello")); | 1560 "/download", base::StringPairs(), "application/octet-stream", "Hello")); |
| 1680 | 1561 |
| 1681 NavigateToURLAndWaitForDownload( | 1562 NavigateToURLAndWaitForDownload( |
| 1682 shell(), referrer_url, DownloadItem::COMPLETE); | 1563 shell(), referrer_url, DownloadItem::COMPLETE); |
| 1683 | 1564 |
| 1684 std::vector<DownloadItem*> downloads; | 1565 std::vector<DownloadItem*> downloads; |
| 1685 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | 1566 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); |
| 1686 ASSERT_EQ(1u, downloads.size()); | 1567 ASSERT_EQ(1u, downloads.size()); |
| 1687 | 1568 |
| 1688 EXPECT_EQ(FILE_PATH_LITERAL("download"), | 1569 EXPECT_EQ(FILE_PATH_LITERAL("download"), |
| 1689 downloads[0]->GetTargetFilePath().BaseName().value()); | 1570 downloads[0]->GetTargetFilePath().BaseName().value()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1717 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); | 1598 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); |
| 1718 | 1599 |
| 1719 // <origin_one>/download-attribute.html initiates a download of | 1600 // <origin_one>/download-attribute.html initiates a download of |
| 1720 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally | 1601 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally |
| 1721 // to <origin_one>/download. | 1602 // to <origin_one>/download. |
| 1722 origin_one.RegisterRequestHandler( | 1603 origin_one.RegisterRequestHandler( |
| 1723 CreateRedirectHandler("/ping", origin_two.GetURL("/pong"))); | 1604 CreateRedirectHandler("/ping", origin_two.GetURL("/pong"))); |
| 1724 origin_two.RegisterRequestHandler( | 1605 origin_two.RegisterRequestHandler( |
| 1725 CreateRedirectHandler("/pong", origin_one.GetURL("/download"))); | 1606 CreateRedirectHandler("/pong", origin_one.GetURL("/download"))); |
| 1726 origin_one.RegisterRequestHandler(CreateBasicResponseHandler( | 1607 origin_one.RegisterRequestHandler(CreateBasicResponseHandler( |
| 1727 "/download", "application/octet-stream", "Hello")); | 1608 "/download", base::StringPairs(), "application/octet-stream", "Hello")); |
| 1728 | 1609 |
| 1729 NavigateToURLAndWaitForDownload( | 1610 NavigateToURLAndWaitForDownload( |
| 1730 shell(), referrer_url, DownloadItem::COMPLETE); | 1611 shell(), referrer_url, DownloadItem::COMPLETE); |
| 1731 | 1612 |
| 1732 std::vector<DownloadItem*> downloads; | 1613 std::vector<DownloadItem*> downloads; |
| 1733 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | 1614 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); |
| 1734 ASSERT_EQ(1u, downloads.size()); | 1615 ASSERT_EQ(1u, downloads.size()); |
| 1735 | 1616 |
| 1736 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"), | 1617 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"), |
| 1737 downloads[0]->GetTargetFilePath().BaseName().value()); | 1618 downloads[0]->GetTargetFilePath().BaseName().value()); |
| 1738 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); | 1619 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); |
| 1739 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); | 1620 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); |
| 1740 } | 1621 } |
| 1741 | 1622 |
| 1742 // The file empty.bin is served with a MIME type of application/octet-stream. | 1623 // The file empty.bin is served with a MIME type of application/octet-stream. |
| 1743 // The content body is empty. Make sure this case is handled properly and we | 1624 // The content body is empty. Make sure this case is handled properly and we |
| 1744 // don't regress on http://crbug.com/320394. | 1625 // don't regress on http://crbug.com/320394. |
| 1745 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) { | 1626 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) { |
| 1746 net::EmbeddedTestServer test_server; | 1627 GURL url = net::URLRequestMockHTTPJob::GetMockUrl("empty.bin"); |
| 1747 ASSERT_TRUE(test_server.Start()); | |
| 1748 | |
| 1749 GURL url = test_server.GetURL("/empty.bin"); | |
| 1750 test_server.ServeFilesFromDirectory(GetTestFilePath("download", "")); | |
| 1751 | |
| 1752 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); | 1628 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); |
| 1753 // That's it. This should work without crashing. | 1629 // That's it. This should work without crashing. |
| 1754 } | 1630 } |
| 1755 | 1631 |
| 1756 IN_PROC_BROWSER_TEST_F(DownloadContentTest, Spam) { | 1632 IN_PROC_BROWSER_TEST_F(DownloadContentTest, Spam) { |
| 1757 ASSERT_TRUE(embedded_test_server()->Start()); | 1633 ASSERT_TRUE(embedded_test_server()->Start()); |
| 1758 | 1634 |
| 1759 NavigateToURLAndWaitForDownload( | 1635 NavigateToURLAndWaitForDownload( |
| 1760 shell(), | 1636 shell(), |
| 1761 embedded_test_server()->GetURL( | 1637 embedded_test_server()->GetURL( |
| 1762 "/download/double-content-disposition.txt"), | 1638 "/download/double-content-disposition.txt"), |
| 1763 DownloadItem::COMPLETE); | 1639 DownloadItem::COMPLETE); |
| 1764 | 1640 |
| 1765 std::vector<DownloadItem*> downloads; | 1641 std::vector<DownloadItem*> downloads; |
| 1766 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | 1642 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); |
| 1767 ASSERT_EQ(1u, downloads.size()); | 1643 ASSERT_EQ(1u, downloads.size()); |
| 1768 | 1644 |
| 1769 EXPECT_EQ(FILE_PATH_LITERAL("Jumboshrimp.txt"), | 1645 EXPECT_EQ(FILE_PATH_LITERAL("Jumboshrimp.txt"), |
| 1770 downloads[0]->GetTargetFilePath().BaseName().value()); | 1646 downloads[0]->GetTargetFilePath().BaseName().value()); |
| 1771 } | 1647 } |
| 1772 | 1648 |
| 1773 } // namespace content | 1649 } // namespace content |
| OLD | NEW |