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 5be9fd5626bfcaa09d5a05b770d29cd95e69e29b..49151dfd32af32b43de0b155640c83165ce4692c 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 |