| Index: content/browser/service_worker/service_worker_browsertest.cc
|
| diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
|
| index 1fdc638be2f9bc68b4c64fec2d8bf058e3e49212..9551a4878cddab2ba063592e17f3c052d42851a3 100644
|
| --- a/content/browser/service_worker/service_worker_browsertest.cc
|
| +++ b/content/browser/service_worker/service_worker_browsertest.cc
|
| @@ -388,6 +388,22 @@ bool CheckHeader(const base::DictionaryValue& dict,
|
| return false;
|
| }
|
|
|
| +bool HasHeader(const base::DictionaryValue& dict,
|
| + base::StringPiece header_name) {
|
| + const base::ListValue* headers = nullptr;
|
| + EXPECT_TRUE(dict.GetList("headers", &headers));
|
| + for (size_t i = 0; i < headers->GetSize(); ++i) {
|
| + const base::ListValue* name_value_pair = nullptr;
|
| + EXPECT_TRUE(headers->GetList(i, &name_value_pair));
|
| + EXPECT_EQ(2u, name_value_pair->GetSize());
|
| + std::string name;
|
| + EXPECT_TRUE(name_value_pair->GetString(0, &name));
|
| + if (name == header_name)
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| net::HttpResponseInfo CreateHttpResponseInfo() {
|
| net::HttpResponseInfo info;
|
| const char data[] =
|
| @@ -1498,6 +1514,24 @@ class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest {
|
| observer->Wait();
|
| }
|
|
|
| + std::string LoadNavigationPreloadTestPage(const GURL& page_url,
|
| + const GURL& worker_url,
|
| + const char* expected_result) {
|
| + RegisterMonitorRequestHandler();
|
| + StartServerAndNavigateToSetup();
|
| + SetupForNavigationPreloadTest(page_url, worker_url);
|
| +
|
| + const base::string16 title = base::ASCIIToUTF16("PASS");
|
| + TitleWatcher title_watcher(shell()->web_contents(), title);
|
| + title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
|
| + title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("REJECTED"));
|
| + title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("RESOLVED"));
|
| + NavigateToURL(shell(), page_url);
|
| + EXPECT_EQ(base::ASCIIToUTF16(expected_result),
|
| + title_watcher.WaitAndGetTitle());
|
| + return GetTextContent();
|
| + }
|
| +
|
| void RegisterMonitorRequestHandler() {
|
| embedded_test_server()->RegisterRequestMonitor(
|
| base::Bind(&self::MonitorRequestHandler, base::Unretained(this)));
|
| @@ -1682,15 +1716,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
|
| RegisterStaticFile(kPageUrl, kPage, "text/html");
|
| RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
|
|
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| -
|
| - const base::string16 title = base::ASCIIToUTF16("PASS");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| - EXPECT_EQ("Hello world.", GetTextContent());
|
| + EXPECT_EQ("Hello world.",
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
|
|
|
| // The page request must be sent once or twice:
|
| // - A navigation preload request may be sent. But it is possible that the
|
| @@ -1816,16 +1843,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| RegisterStaticFile(kPageUrl, kPage, "text/html");
|
| RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
|
|
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| -
|
| - const base::string16 title = base::ASCIIToUTF16("PASS");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| - EXPECT_EQ("Hello world.", GetTextContent());
|
| + EXPECT_EQ("Hello world.",
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
|
|
|
| // The page request must be sent only once, since the worker responded with
|
| // the navigation preload response
|
| @@ -1854,15 +1873,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, GetResponseText) {
|
| RegisterStaticFile(kPageUrl, kPage, "text/html");
|
| RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
|
|
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| -
|
| - const base::string16 title = base::ASCIIToUTF16("PASS");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| - EXPECT_EQ("Hello world.", GetTextContent());
|
| + EXPECT_EQ("Hello world.",
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
|
|
|
| // The page request must be sent only once, since the worker responded with
|
| // "Hello world".
|
| @@ -1907,17 +1919,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
|
| "text/javascript");
|
|
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| -
|
| - const base::string16 title = base::ASCIIToUTF16("REJECTED");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("RESOLVED"));
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| EXPECT_EQ("NetworkError: Service Worker navigation preload network error.",
|
| - GetTextContent());
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "REJECTED"));
|
| }
|
|
|
| IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| @@ -1932,28 +1935,18 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
|
| "text/javascript");
|
|
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| -
|
| - const base::string16 title = base::ASCIIToUTF16("RESOLVED");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("REJECTED"));
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| + std::unique_ptr<base::Value> result = base::JSONReader::Read(
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "RESOLVED"));
|
|
|
| // The page request must be sent only once, since the worker responded with
|
| // a generated Response.
|
| EXPECT_EQ(1, GetRequestCount(kPageUrl));
|
| - std::unique_ptr<base::Value> result =
|
| - base::JSONReader::Read(GetTextContent());
|
| base::DictionaryValue* dict = nullptr;
|
| ASSERT_TRUE(result->GetAsDictionary(&dict));
|
| EXPECT_EQ("basic", GetString(*dict, "type"));
|
| EXPECT_EQ(page_url, GURL(GetString(*dict, "url")));
|
| EXPECT_EQ(200, GetInt(*dict, "status"));
|
| - EXPECT_EQ(true, GetBoolean(*dict, "ok"));
|
| + EXPECT_TRUE(GetBoolean(*dict, "ok"));
|
| EXPECT_EQ("OK", GetString(*dict, "statusText"));
|
| EXPECT_TRUE(CheckHeader(*dict, "content-type", "text/html"));
|
| EXPECT_TRUE(CheckHeader(*dict, "content-length",
|
| @@ -1969,21 +1962,12 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NotEnabled) {
|
| RegisterStaticFile(kPageUrl, kPage, "text/html");
|
| RegisterStaticFile(kWorkerUrl, kPreloadResponseTestScript, "text/javascript");
|
|
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| -
|
| - const base::string16 title = base::ASCIIToUTF16("RESOLVED");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("REJECTED"));
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| + EXPECT_EQ("Resolved with undefined.",
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "RESOLVED"));
|
|
|
| // The page request must not be sent, since the worker responded with a
|
| // generated Response and the navigation preload isn't enabled.
|
| EXPECT_EQ(0, GetRequestCount(kPageUrl));
|
| - EXPECT_EQ("Resolved with undefined.", GetTextContent());
|
| }
|
|
|
| IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| @@ -2008,77 +1992,90 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
|
| "text/javascript");
|
|
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| -
|
| - const base::string16 title = base::ASCIIToUTF16("RESOLVED");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("REJECTED"));
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| + std::unique_ptr<base::Value> result = base::JSONReader::Read(
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "RESOLVED"));
|
|
|
| // The page request must be sent only once, since the worker responded with
|
| // a generated Response.
|
| EXPECT_EQ(1, GetRequestCount(kPageUrl));
|
| - std::unique_ptr<base::Value> result =
|
| - base::JSONReader::Read(GetTextContent());
|
| base::DictionaryValue* dict = nullptr;
|
| ASSERT_TRUE(result->GetAsDictionary(&dict));
|
| EXPECT_EQ("basic", GetString(*dict, "type"));
|
| EXPECT_EQ(page_url, GURL(GetString(*dict, "url")));
|
| EXPECT_EQ(201, GetInt(*dict, "status"));
|
| - EXPECT_EQ(true, GetBoolean(*dict, "ok"));
|
| + EXPECT_TRUE(GetBoolean(*dict, "ok"));
|
| EXPECT_EQ("HELLOWORLD", GetString(*dict, "statusText"));
|
| EXPECT_TRUE(CheckHeader(*dict, "content-type", "text/html"));
|
| EXPECT_TRUE(CheckHeader(*dict, "content-length", "32"));
|
| EXPECT_TRUE(CheckHeader(*dict, "custom-header", "pen pineapple, apple pen"));
|
| // The forbidden response headers (Set-Cookie, Set-Cookie2) must be removed.
|
| - EXPECT_FALSE(dict->HasKey("set-cookie"));
|
| - EXPECT_FALSE(dict->HasKey("set-cookie2"));
|
| + EXPECT_FALSE(HasHeader(*dict, "set-cookie"));
|
| + EXPECT_FALSE(HasHeader(*dict, "set-cookie2"));
|
| }
|
|
|
| -IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, RejectRedirects) {
|
| +IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| + InvalidRedirect_MultiLocation) {
|
| const char kPageUrl[] = "/service_worker/navigation_preload.html";
|
| const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
|
| - const char kRedirectedPageUrl[] =
|
| - "/service_worker/navigation_preload_redirected.html";
|
| + const char kRedirectedPageUrl1[] =
|
| + "/service_worker/navigation_preload_redirected1.html";
|
| + const char kRedirectedPageUrl2[] =
|
| + "/service_worker/navigation_preload_redirected2.html";
|
| const char kPageResponse[] =
|
| "HTTP/1.1 302 Found\r\n"
|
| "Connection: close\r\n"
|
| - "Location: /service_worker/navigation_preload_redirected.html\r\n"
|
| + "Location: /service_worker/navigation_preload_redirected1.html\r\n"
|
| + "Location: /service_worker/navigation_preload_redirected2.html\r\n"
|
| "\r\n";
|
| const char kRedirectedPage[] = "<title>ERROR</title>Redirected page.";
|
| - const GURL redirecred_page_url =
|
| - embedded_test_server()->GetURL(kRedirectedPageUrl);
|
| const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
|
| const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
|
| RegisterCustomResponse(kPageUrl, kPageResponse);
|
| RegisterStaticFile(
|
| kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
|
| "text/javascript");
|
| - RegisterStaticFile(kRedirectedPageUrl, kRedirectedPage, "text/html");
|
| -
|
| - RegisterMonitorRequestHandler();
|
| - StartServerAndNavigateToSetup();
|
| - SetupForNavigationPreloadTest(page_url, worker_url);
|
| + RegisterStaticFile(kRedirectedPageUrl1, kRedirectedPage, "text/html");
|
|
|
| - const base::string16 title = base::ASCIIToUTF16("REJECTED");
|
| - TitleWatcher title_watcher(shell()->web_contents(), title);
|
| - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("RESOLVED"));
|
| - NavigateToURL(shell(), page_url);
|
| - EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
|
| + // According to the spec, multiple Location headers is not an error. So the
|
| + // preloadResponse must be resolved with an opaque redirect response.
|
| + // But Chrome treats multiple Location headers as an error (crbug.com/98895).
|
| + EXPECT_EQ("NetworkError: Service Worker navigation preload network error.",
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "REJECTED"));
|
|
|
| // The page request must be sent only once, since the worker responded with
|
| // a generated Response.
|
| EXPECT_EQ(1, GetRequestCount(kPageUrl));
|
| // The redirected request must not be sent.
|
| - EXPECT_EQ(0, GetRequestCount(kRedirectedPageUrl));
|
| - EXPECT_EQ(
|
| - "NetworkError: Service Worker navigation preload doesn't support "
|
| - "redirects.",
|
| - GetTextContent());
|
| + EXPECT_EQ(0, GetRequestCount(kRedirectedPageUrl1));
|
| + EXPECT_EQ(0, GetRequestCount(kRedirectedPageUrl2));
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
|
| + InvalidRedirect_InvalidLocation) {
|
| + const char kPageUrl[] = "/service_worker/navigation_preload.html";
|
| + const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
|
| + const char kPageResponse[] =
|
| + "HTTP/1.1 302 Found\r\n"
|
| + "Connection: close\r\n"
|
| + "Location: http://\r\n"
|
| + "\r\n";
|
| + const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
|
| + const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
|
| + RegisterCustomResponse(kPageUrl, kPageResponse);
|
| + RegisterStaticFile(
|
| + kWorkerUrl, kEnableNavigationPreloadScript + kPreloadResponseTestScript,
|
| + "text/javascript");
|
| +
|
| + // TODO(horo): According to the spec, even if the location URL is invalid, the
|
| + // preloadResponse must be resolve with an opaque redirect response. But
|
| + // currently Chrome handles the invalid location URL in the browser process as
|
| + // an error. crbug.com/707185
|
| + EXPECT_EQ("NetworkError: Service Worker navigation preload network error.",
|
| + LoadNavigationPreloadTestPage(page_url, worker_url, "REJECTED"));
|
| +
|
| + // The page request must be sent only once, since the worker responded with
|
| + // a generated Response.
|
| + EXPECT_EQ(1, GetRequestCount(kPageUrl));
|
| }
|
|
|
| // Tests responding with the navigation preload response when the navigation
|
|
|