Chromium Code Reviews| 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 <queue> | |
| 9 | |
| 8 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 9 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 10 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 11 #include "base/files/scoped_temp_dir.h" | 13 #include "base/files/scoped_temp_dir.h" |
| 12 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/threading/platform_thread.h" | 16 #include "base/threading/platform_thread.h" |
| 15 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 16 #include "content/browser/byte_stream.h" | 18 #include "content/browser/byte_stream.h" |
| 17 #include "content/browser/download/download_file_factory.h" | 19 #include "content/browser/download/download_file_factory.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 29 #include "content/public/test/content_browser_test_utils.h" | 31 #include "content/public/test/content_browser_test_utils.h" |
| 30 #include "content/public/test/download_test_observer.h" | 32 #include "content/public/test/download_test_observer.h" |
| 31 #include "content/public/test/test_file_error_injector.h" | 33 #include "content/public/test/test_file_error_injector.h" |
| 32 #include "content/public/test/test_utils.h" | 34 #include "content/public/test/test_utils.h" |
| 33 #include "content/shell/browser/shell.h" | 35 #include "content/shell/browser/shell.h" |
| 34 #include "content/shell/browser/shell_browser_context.h" | 36 #include "content/shell/browser/shell_browser_context.h" |
| 35 #include "content/shell/browser/shell_download_manager_delegate.h" | 37 #include "content/shell/browser/shell_download_manager_delegate.h" |
| 36 #include "content/shell/browser/shell_network_delegate.h" | 38 #include "content/shell/browser/shell_network_delegate.h" |
| 37 #include "content/test/net/url_request_mock_http_job.h" | 39 #include "content/test/net/url_request_mock_http_job.h" |
| 38 #include "content/test/net/url_request_slow_download_job.h" | 40 #include "content/test/net/url_request_slow_download_job.h" |
| 41 #include "net/test/embedded_test_server/embedded_test_server.h" | |
| 42 #include "net/test/embedded_test_server/http_request.h" | |
| 43 #include "net/test/embedded_test_server/http_response.h" | |
| 39 #include "net/test/spawned_test_server/spawned_test_server.h" | 44 #include "net/test/spawned_test_server/spawned_test_server.h" |
| 40 #include "testing/gmock/include/gmock/gmock.h" | 45 #include "testing/gmock/include/gmock/gmock.h" |
| 41 #include "testing/gtest/include/gtest/gtest.h" | 46 #include "testing/gtest/include/gtest/gtest.h" |
| 42 #include "url/gurl.h" | 47 #include "url/gurl.h" |
| 43 | 48 |
| 44 using ::testing::_; | 49 using ::testing::_; |
| 45 using ::testing::AllOf; | 50 using ::testing::AllOf; |
| 46 using ::testing::Field; | 51 using ::testing::Field; |
| 47 using ::testing::InSequence; | 52 using ::testing::InSequence; |
| 48 using ::testing::Property; | 53 using ::testing::Property; |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 // Filter for saving the size of the download when the first IN_PROGRESS | 501 // Filter for saving the size of the download when the first IN_PROGRESS |
| 497 // is hit. | 502 // is hit. |
| 498 bool InitialSizeFilter(int* download_size, DownloadItem* download) { | 503 bool InitialSizeFilter(int* download_size, DownloadItem* download) { |
| 499 if (download->GetState() != DownloadItem::IN_PROGRESS) | 504 if (download->GetState() != DownloadItem::IN_PROGRESS) |
| 500 return false; | 505 return false; |
| 501 | 506 |
| 502 *download_size = download->GetReceivedBytes(); | 507 *download_size = download->GetReceivedBytes(); |
| 503 return true; | 508 return true; |
| 504 } | 509 } |
| 505 | 510 |
| 511 // RAII test server. Once instantiated, it initializes an embedded test server. | |
| 512 // Expectations can be set via the OnURL method. | |
| 513 // | |
| 514 // Call HasFatalFailure() after constructing a TestServer instance to check if | |
| 515 // the initialization was successful. | |
| 516 // | |
| 517 // Example: | |
| 518 // | |
| 519 // TEST_F(Foo, Bar) { | |
| 520 // TestServer test_server; | |
| 521 // if (HasFatalFailure()) | |
| 522 // return; | |
| 523 // | |
| 524 // test_server.OnURL("/foo").RedirectTo("/bar"); | |
| 525 // test_server.OnURL("/bar").SendBody("baz"); | |
| 526 // ... | |
| 527 // test_server.ServeFilesFromDirectory(test_file_path); | |
| 528 // ... | |
| 529 // // Do something that fetches "/foo". | |
| 530 // } | |
| 531 // | |
| 532 // Note that the order of the OnURL() calls are significant. The server expects | |
| 533 // the requests to arrive in the same order as the OnURL() calls. | |
| 534 // TODO(asanka): Consider migrating more tests to use the embedded test server. | |
|
Randy Smith (Not in Mondays)
2014/04/23 19:12:27
I'd encourage this; this type of infrastructure lo
asanka
2014/04/23 22:59:27
I actually removed this TestServer since in the en
| |
| 535 class TestServer { | |
| 536 public: | |
| 537 // An expectation for a request. Created by TestServer::OnURL(). | |
| 538 class ExpectedRequest { | |
| 539 public: | |
| 540 // Respond with a status code of 302 and a Location header set to | |
| 541 // |redirect_url|. | |
| 542 ExpectedRequest& RedirectTo(const GURL& redirect_url); | |
| 543 | |
| 544 // Set the body of the response to |string|. Overwrites the current body if | |
| 545 // one had been previously set. | |
| 546 ExpectedRequest& SendBody(const std::string& string); | |
|
Randy Smith (Not in Mondays)
2014/04/23 19:12:27
Should you say what happens if you use both Redire
asanka
2014/04/23 22:59:27
Removed.
| |
| 547 | |
| 548 // Set the Content-Type to |mime_type|. | |
| 549 ExpectedRequest& WithContentType(const char* mime_type); | |
| 550 | |
| 551 private: | |
| 552 friend class TestServer; | |
| 553 | |
| 554 // Construct a ExpectedRequest that will expect an HTTP GET for | |
| 555 // |relative_url|. | |
| 556 ExpectedRequest(const std::string& relative_url); | |
| 557 | |
| 558 // Returns true if this expectation matches |url|. | |
| 559 bool MatchesUrl(const std::string& url) const; | |
| 560 | |
| 561 // Returns the HttpResponse for this expectation. Once this is called, the | |
| 562 // ExpectedRequest object is no longer valid. | |
| 563 scoped_ptr<net::test_server::HttpResponse> GetResponse(); | |
| 564 | |
| 565 std::string relative_url_; | |
| 566 scoped_ptr<net::test_server::BasicHttpResponse> response_; | |
| 567 DISALLOW_COPY_AND_ASSIGN(ExpectedRequest); | |
| 568 }; | |
| 569 | |
| 570 TestServer(); | |
| 571 ~TestServer(); | |
| 572 | |
| 573 // Create a new expectation for receiving an HTTP GET for |relative_url|. By | |
| 574 // default the response is an HTTP 200 with an empty body. The response can be | |
| 575 // modified via the returned |ExpectedRequest| reference. Note that the | |
| 576 // reference becomes invalidated once a request has been received by the | |
| 577 // server. | |
| 578 ExpectedRequest& OnURL(const std::string& relative_url); | |
|
Randy Smith (Not in Mondays)
2014/04/23 19:12:27
Huh. I twitch somewhat hard at returning a non-co
asanka
2014/04/23 22:59:27
Hehe. It's a builder pattern. See for example htt
| |
| 579 | |
| 580 // Get the absolue URL for |relative_url|. | |
| 581 GURL GetURL(const std::string& relative_url); | |
| 582 | |
| 583 // Serve files contained within |directory|. See | |
| 584 // EmbeddedTestServer::ServeFilesFromDirectory(). | |
| 585 void ServeFilesFromDirectory(const base::FilePath& directory); | |
|
Randy Smith (Not in Mondays)
2014/04/23 19:12:27
Probably worthwhile calling out that any ExpectedR
asanka
2014/04/23 22:59:27
Removed.
| |
| 586 | |
| 587 private: | |
| 588 scoped_ptr<net::test_server::HttpResponse> HandleRequest( | |
| 589 const net::test_server::HttpRequest& request); | |
| 590 void InitializeAndWaitUntilReady(); | |
| 591 void ShutdownAndWaitUntilComplete(); | |
| 592 | |
| 593 net::test_server::EmbeddedTestServer embedded_test_server_; | |
| 594 std::queue<ExpectedRequest*> expected_requests_; | |
| 595 DISALLOW_COPY_AND_ASSIGN(TestServer); | |
| 596 }; | |
| 597 | |
| 598 TestServer::ExpectedRequest::ExpectedRequest(const std::string& relative_url) | |
| 599 : relative_url_(relative_url), | |
| 600 response_(new net::test_server::BasicHttpResponse) { | |
| 601 } | |
| 602 | |
| 603 TestServer::ExpectedRequest& TestServer::ExpectedRequest::RedirectTo( | |
| 604 const GURL& redirect_url) { | |
| 605 response_->set_code(net::HTTP_FOUND); | |
| 606 response_->AddCustomHeader("Location", redirect_url.spec()); | |
| 607 return *this; | |
| 608 } | |
| 609 | |
| 610 TestServer::ExpectedRequest& TestServer::ExpectedRequest::SendBody( | |
| 611 const std::string& string) { | |
| 612 response_->set_content(string); | |
| 613 return *this; | |
| 614 } | |
| 615 | |
| 616 TestServer::ExpectedRequest& TestServer::ExpectedRequest::WithContentType( | |
| 617 const char* mime_type) { | |
| 618 response_->set_content_type(mime_type); | |
| 619 return *this; | |
| 620 } | |
| 621 | |
| 622 bool TestServer::ExpectedRequest::MatchesUrl(const std::string& url) const { | |
| 623 return relative_url_ == url; | |
| 624 } | |
| 625 | |
| 626 scoped_ptr<net::test_server::HttpResponse> | |
| 627 TestServer::ExpectedRequest::GetResponse() { | |
| 628 return response_.PassAs<net::test_server::HttpResponse>(); | |
| 629 } | |
| 630 | |
| 631 TestServer::TestServer() { | |
| 632 InitializeAndWaitUntilReady(); | |
| 633 } | |
| 634 | |
| 635 TestServer::~TestServer() { | |
| 636 EXPECT_TRUE(expected_requests_.empty()); | |
| 637 while (!expected_requests_.empty()) { | |
| 638 delete expected_requests_.front(); | |
| 639 expected_requests_.pop(); | |
| 640 } | |
| 641 ShutdownAndWaitUntilComplete(); | |
| 642 } | |
| 643 | |
| 644 void TestServer::InitializeAndWaitUntilReady() { | |
| 645 ASSERT_TRUE(embedded_test_server_.InitializeAndWaitUntilReady()); | |
| 646 embedded_test_server_.RegisterRequestHandler( | |
| 647 base::Bind(&TestServer::HandleRequest, base::Unretained(this))); | |
| 648 } | |
| 649 | |
| 650 void TestServer::ShutdownAndWaitUntilComplete() { | |
| 651 ASSERT_TRUE(embedded_test_server_.ShutdownAndWaitUntilComplete()); | |
| 652 } | |
| 653 | |
| 654 TestServer::ExpectedRequest& TestServer::OnURL( | |
| 655 const std::string& relative_url) { | |
| 656 ExpectedRequest* request = new ExpectedRequest(relative_url); | |
| 657 expected_requests_.push(request); | |
| 658 return *request; | |
| 659 } | |
| 660 | |
| 661 void TestServer::ServeFilesFromDirectory(const base::FilePath& directory) { | |
| 662 embedded_test_server_.ServeFilesFromDirectory(directory); | |
| 663 } | |
| 664 | |
| 665 GURL TestServer::GetURL(const std::string& relative_url) { | |
| 666 return embedded_test_server_.GetURL(relative_url); | |
| 667 } | |
| 668 | |
| 669 scoped_ptr<net::test_server::HttpResponse> TestServer::HandleRequest( | |
| 670 const net::test_server::HttpRequest& request) { | |
| 671 scoped_ptr<net::test_server::HttpResponse> response; | |
| 672 if (!expected_requests_.empty() && | |
| 673 expected_requests_.front()->MatchesUrl(request.relative_url)) { | |
| 674 scoped_ptr<ExpectedRequest> expected_request(expected_requests_.front()); | |
| 675 response = expected_request->GetResponse(); | |
| 676 expected_requests_.pop(); | |
| 677 } | |
| 678 return response.Pass(); | |
| 679 } | |
| 680 | |
| 506 } // namespace | 681 } // namespace |
| 507 | 682 |
| 508 class DownloadContentTest : public ContentBrowserTest { | 683 class DownloadContentTest : public ContentBrowserTest { |
| 509 protected: | 684 protected: |
| 510 // An initial send from a website of at least this size will not be | 685 // An initial send from a website of at least this size will not be |
| 511 // help up by buffering in the underlying downloads ByteStream data | 686 // help up by buffering in the underlying downloads ByteStream data |
| 512 // transfer. This is important because on resumption tests we wait | 687 // transfer. This is important because on resumption tests we wait |
| 513 // until we've gotten the data we expect before allowing the test server | 688 // until we've gotten the data we expect before allowing the test server |
| 514 // to send its reset, to get around hard close semantics on the Windows | 689 // to send its reset, to get around hard close semantics on the Windows |
| 515 // socket layer implementation. | 690 // socket layer implementation. |
| (...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1644 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | 1819 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); |
| 1645 ASSERT_EQ(1u, downloads.size()); | 1820 ASSERT_EQ(1u, downloads.size()); |
| 1646 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState()); | 1821 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState()); |
| 1647 | 1822 |
| 1648 // Check that the cookies were correctly set. | 1823 // Check that the cookies were correctly set. |
| 1649 EXPECT_EQ("A=B", | 1824 EXPECT_EQ("A=B", |
| 1650 content::GetCookies(shell()->web_contents()->GetBrowserContext(), | 1825 content::GetCookies(shell()->web_contents()->GetBrowserContext(), |
| 1651 GURL(download))); | 1826 GURL(download))); |
| 1652 } | 1827 } |
| 1653 | 1828 |
| 1829 // A filename suggestion specified via a @download attribute should be effective | |
| 1830 // if the final download URL is in the same origin as the initial download URL. | |
| 1831 // Test that this holds even if there are cross origin redirects in the middle | |
| 1832 // of the redirect chain. | |
| 1833 IN_PROC_BROWSER_TEST_F(DownloadContentTest, | |
| 1834 DownloadAttributeSameOriginRedirect) { | |
| 1835 TestServer origin_one; | |
| 1836 TestServer origin_two; | |
| 1837 if (HasFatalFailure()) | |
| 1838 return; | |
| 1839 | |
| 1840 // The download-attribute.html page contains an anchor element whose href is | |
| 1841 // set to the value of the query parameter (specified as |target| in the URL | |
| 1842 // below). The suggested filename for the anchor is 'suggested-filename'. When | |
| 1843 // the page is loaded, a script simulates a click on the anchor, triggering a | |
| 1844 // download of the target URL. | |
| 1845 // | |
| 1846 // We construct two test servers; origin_one and origin_two. Once started, the | |
| 1847 // server URLs will differ by the port number. Therefore they will be in | |
| 1848 // different origins. | |
| 1849 GURL download_url = origin_one.GetURL("/ping"); | |
| 1850 GURL referrer_url = origin_one.GetURL( | |
| 1851 std::string("/download-attribute.html?target=") + download_url.spec()); | |
| 1852 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); | |
| 1853 | |
| 1854 // <origin_one>/download-attribute.html initiates a download of | |
| 1855 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally | |
| 1856 // to <origin_one>/download. | |
| 1857 origin_one.OnURL("/ping").RedirectTo(origin_two.GetURL("/pong")); | |
| 1858 origin_two.OnURL("/pong").RedirectTo(origin_one.GetURL("/download")); | |
| 1859 origin_one.OnURL("/download").SendBody("Hello").WithContentType( | |
| 1860 "application/octet-stream"); | |
| 1861 | |
| 1862 DownloadAndWait(shell(), referrer_url, DownloadItem::COMPLETE); | |
|
Randy Smith (Not in Mondays)
2014/04/23 19:12:27
nit: Chuckle. This relies on "DownloadAndWait()"
asanka
2014/04/23 22:59:27
I renamed the function to NavigateToURLAndWaitForD
| |
| 1863 | |
| 1864 std::vector<DownloadItem*> downloads; | |
| 1865 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | |
| 1866 ASSERT_EQ(1u, downloads.size()); | |
| 1867 | |
| 1868 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"), | |
| 1869 downloads[0]->GetTargetFilePath().BaseName().value()); | |
| 1870 } | |
| 1871 | |
| 1872 // A filename suggestion specified via a @download attribute should not be | |
| 1873 // effective if the final download URL is in another origin from the original | |
| 1874 // download URL. | |
|
Randy Smith (Not in Mondays)
2014/04/23 19:12:27
nit: I'd interchange the order of these two tests;
asanka
2014/04/23 22:59:27
Done.
| |
| 1875 IN_PROC_BROWSER_TEST_F(DownloadContentTest, | |
| 1876 DownloadAttributeCrossOriginRedirect) { | |
| 1877 TestServer origin_one; | |
| 1878 TestServer origin_two; | |
| 1879 if (HasFatalFailure()) | |
| 1880 return; | |
| 1881 | |
| 1882 // The download-attribute.html page contains an anchor element whose href is | |
| 1883 // set to the value of the query parameter (specified as |target| in the URL | |
| 1884 // below). The suggested filename for the anchor is 'suggested-filename'. When | |
| 1885 // the page is loaded, a script simulates a click on the anchor, triggering a | |
| 1886 // download of the target URL. | |
| 1887 // | |
| 1888 // We construct two test servers; origin_one and origin_two. Once started, the | |
| 1889 // server URLs will differ by the port number. Therefore they will be in | |
| 1890 // different origins. | |
| 1891 GURL download_url = origin_one.GetURL("/ping"); | |
| 1892 GURL referrer_url = origin_one.GetURL( | |
| 1893 std::string("/download-attribute.html?target=") + download_url.spec()); | |
| 1894 | |
| 1895 // <origin_one>/download-attribute.html initiates a download of | |
| 1896 // <origin_one>/ping, which redirects to <origin_two>/download. | |
| 1897 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); | |
| 1898 origin_one.OnURL("/ping").RedirectTo(origin_two.GetURL("/download")); | |
| 1899 origin_two.OnURL("/download").SendBody("Hello").WithContentType( | |
| 1900 "application/octet-stream"); | |
| 1901 | |
| 1902 DownloadAndWait(shell(), referrer_url, DownloadItem::COMPLETE); | |
| 1903 | |
| 1904 std::vector<DownloadItem*> downloads; | |
| 1905 DownloadManagerForShell(shell())->GetAllDownloads(&downloads); | |
| 1906 ASSERT_EQ(1u, downloads.size()); | |
| 1907 | |
| 1908 EXPECT_EQ(FILE_PATH_LITERAL("download"), | |
| 1909 downloads[0]->GetTargetFilePath().BaseName().value()); | |
| 1910 } | |
| 1911 | |
| 1654 } // namespace content | 1912 } // namespace content |
| OLD | NEW |