Chromium Code Reviews| Index: content/browser/download/download_browsertest.cc |
| diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc |
| index 276f3c4587cd4588cec75db5199cfa1b60dba8e0..9e8cab2fb87f8e9b8d0925748f95b6e9468d1134 100644 |
| --- a/content/browser/download/download_browsertest.cc |
| +++ b/content/browser/download/download_browsertest.cc |
| @@ -36,18 +36,22 @@ |
| #include "content/shell/browser/shell_network_delegate.h" |
| #include "content/test/net/url_request_mock_http_job.h" |
| #include "content/test/net/url_request_slow_download_job.h" |
| +#include "net/test/embedded_test_server/embedded_test_server.h" |
| +#include "net/test/embedded_test_server/http_request.h" |
| +#include "net/test/embedded_test_server/http_response.h" |
| #include "net/test/spawned_test_server/spawned_test_server.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| -using ::testing::_; |
| +using ::net::test_server::EmbeddedTestServer; |
| using ::testing::AllOf; |
| using ::testing::Field; |
| using ::testing::InSequence; |
| using ::testing::Property; |
| using ::testing::Return; |
| using ::testing::StrictMock; |
| +using ::testing::_; |
| namespace content { |
| @@ -503,6 +507,54 @@ bool InitialSizeFilter(int* download_size, DownloadItem* download) { |
| return true; |
| } |
| +// Request handler to be used with CreateRedirectHandler(). |
| +scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse( |
| + const std::string& relative_url, |
| + const GURL& target_url, |
| + const net::test_server::HttpRequest& request) { |
| + scoped_ptr<net::test_server::BasicHttpResponse> response; |
| + if (request.relative_url == relative_url) { |
| + response.reset(new net::test_server::BasicHttpResponse); |
| + response->set_code(net::HTTP_FOUND); |
| + response->AddCustomHeader("Location", target_url.spec()); |
| + } |
| + return response.PassAs<net::test_server::HttpResponse>(); |
| +} |
| + |
| +// Creates a request handler for EmbeddedTestServer that responds with a HTTP |
| +// 302 redirect if the request URL matches |relative_url|. |
| +EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler( |
| + const std::string& relative_url, |
| + const GURL& target_url) { |
| + return base::Bind( |
| + &HandleRequestAndSendRedirectResponse, relative_url, target_url); |
| +} |
| + |
| +// Request handler to be used with CreateBasicResponseHandler(). |
| +scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse( |
| + const std::string& relative_url, |
| + const std::string& content_type, |
| + const std::string& body, |
| + const net::test_server::HttpRequest& request) { |
| + scoped_ptr<net::test_server::BasicHttpResponse> response; |
| + if (request.relative_url == relative_url) { |
| + response.reset(new net::test_server::BasicHttpResponse); |
| + response->set_content_type(content_type); |
| + response->set_content(body); |
| + } |
| + return response.PassAs<net::test_server::HttpResponse>(); |
| +} |
| + |
| +// Creates a request handler for an EmbeddedTestServer that response with an |
| +// HTTP 200 status code, a Content-Type header and a body. |
| +EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler( |
| + const std::string& relative_url, |
| + const std::string& content_type, |
| + const std::string& body) { |
| + return base::Bind( |
| + &HandleRequestAndSendBasicResponse, relative_url, content_type, body); |
| +} |
| + |
| } // namespace |
| class DownloadContentTest : public ContentBrowserTest { |
| @@ -582,8 +634,10 @@ class DownloadContentTest : public ContentBrowserTest { |
| (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0); |
| } |
| - void DownloadAndWait(Shell* shell, const GURL& url, |
| - DownloadItem::DownloadState expected_terminal_state) { |
| + void NavigateToURLAndWaitForDownload( |
| + Shell* shell, |
| + const GURL& url, |
| + DownloadItem::DownloadState expected_terminal_state) { |
| scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1)); |
| NavigateToURL(shell, url); |
| observer->WaitForFinished(); |
| @@ -746,7 +800,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) { |
| base::FilePath file(FILE_PATH_LITERAL("download-test.lib")); |
| GURL url(URLRequestMockHTTPJob::GetMockUrl(file)); |
| // Download the file and wait. |
| - DownloadAndWait(shell(), url, DownloadItem::COMPLETE); |
| + NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); |
| // Should now have 2 items on the manager. |
| downloads.clear(); |
| @@ -800,7 +854,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) { |
| // The following is served with a Content-Type of application/octet-stream. |
| GURL url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath))); |
| - DownloadAndWait(shell(), url, DownloadItem::COMPLETE); |
| + NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE); |
| } |
| #endif |
| @@ -1560,7 +1614,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) { |
| // single threaded. The response to this download request should follow the |
| // response to the previous resumption request. |
| GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); |
| - DownloadAndWait(shell(), url2, DownloadItem::COMPLETE); |
| + NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); |
| EXPECT_TRUE(EnsureNoPendingDownloads()); |
| } |
| @@ -1608,7 +1662,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) { |
| // single threaded. The response to this download request should follow the |
| // response to the previous resumption request. |
| GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x")); |
| - DownloadAndWait(shell(), url2, DownloadItem::COMPLETE); |
| + NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE); |
| EXPECT_TRUE(EnsureNoPendingDownloads()); |
| } |
| @@ -1651,4 +1705,96 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) { |
| GURL(download))); |
| } |
| +// A filename suggestion specified via a @download attribute should not be |
| +// effective if the final download URL is in another origin from the original |
| +// download URL. |
| +IN_PROC_BROWSER_TEST_F(DownloadContentTest, |
| + DownloadAttributeCrossOriginRedirect) { |
| + EmbeddedTestServer origin_one; |
| + EmbeddedTestServer origin_two; |
| + ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady()); |
| + ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady()); |
| + |
| + // The download-attribute.html page contains an anchor element whose href is |
| + // set to the value of the query parameter (specified as |target| in the URL |
| + // below). The suggested filename for the anchor is 'suggested-filename'. When |
| + // the page is loaded, a script simulates a click on the anchor, triggering a |
| + // download of the target URL. |
| + // |
| + // We construct two test servers; origin_one and origin_two. Once started, the |
| + // server URLs will differ by the port number. Therefore they will be in |
| + // different origins. |
| + GURL download_url = origin_one.GetURL("/ping"); |
| + GURL referrer_url = origin_one.GetURL( |
| + std::string("/download-attribute.html?target=") + download_url.spec()); |
| + |
| + // <origin_one>/download-attribute.html initiates a download of |
| + // <origin_one>/ping, which redirects to <origin_two>/download. |
| + origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); |
| + origin_one.RegisterRequestHandler( |
| + CreateRedirectHandler("/ping", origin_two.GetURL("/download"))); |
| + origin_two.RegisterRequestHandler(CreateBasicResponseHandler( |
| + "/download", "application/octet-stream", "Hello")); |
| + |
| + NavigateToURLAndWaitForDownload( |
| + shell(), referrer_url, DownloadItem::COMPLETE); |
| + |
| + std::vector<DownloadItem*> downloads; |
| + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); |
| + ASSERT_EQ(1u, downloads.size()); |
| + |
| + EXPECT_EQ(FILE_PATH_LITERAL("download"), |
|
Randy Smith (Not in Mondays)
2014/04/24 22:08:43
Suggestion: Comment that this is the key check, an
asanka
2014/04/25 22:08:07
Done.
|
| + downloads[0]->GetTargetFilePath().BaseName().value()); |
| + ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); |
| + ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); |
| +} |
| + |
| +// A filename suggestion specified via a @download attribute should be effective |
| +// if the final download URL is in the same origin as the initial download URL. |
| +// Test that this holds even if there are cross origin redirects in the middle |
| +// of the redirect chain. |
| +IN_PROC_BROWSER_TEST_F(DownloadContentTest, |
| + DownloadAttributeSameOriginRedirect) { |
| + EmbeddedTestServer origin_one; |
| + EmbeddedTestServer origin_two; |
| + ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady()); |
| + ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady()); |
| + |
| + // The download-attribute.html page contains an anchor element whose href is |
| + // set to the value of the query parameter (specified as |target| in the URL |
| + // below). The suggested filename for the anchor is 'suggested-filename'. When |
| + // the page is loaded, a script simulates a click on the anchor, triggering a |
| + // download of the target URL. |
| + // |
| + // We construct two test servers; origin_one and origin_two. Once started, the |
| + // server URLs will differ by the port number. Therefore they will be in |
| + // different origins. |
| + GURL download_url = origin_one.GetURL("/ping"); |
| + GURL referrer_url = origin_one.GetURL( |
| + std::string("/download-attribute.html?target=") + download_url.spec()); |
| + origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); |
| + |
| + // <origin_one>/download-attribute.html initiates a download of |
| + // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally |
| + // to <origin_one>/download. |
| + origin_one.RegisterRequestHandler( |
| + CreateRedirectHandler("/ping", origin_two.GetURL("/pong"))); |
| + origin_two.RegisterRequestHandler( |
| + CreateRedirectHandler("/pong", origin_one.GetURL("/download"))); |
| + origin_one.RegisterRequestHandler(CreateBasicResponseHandler( |
| + "/download", "application/octet-stream", "Hello")); |
| + |
| + NavigateToURLAndWaitForDownload( |
| + shell(), referrer_url, DownloadItem::COMPLETE); |
| + |
| + std::vector<DownloadItem*> downloads; |
| + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); |
| + ASSERT_EQ(1u, downloads.size()); |
| + |
| + EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"), |
| + downloads[0]->GetTargetFilePath().BaseName().value()); |
| + ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); |
| + ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); |
| +} |
| + |
| } // namespace content |