Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(815)

Unified Diff: content/browser/service_worker/service_worker_browsertest.cc

Issue 2790433003: Support redirect responses for NavigationPreload (Closed)
Patch Set: fix DevTools test Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | content/browser/service_worker/service_worker_fetch_dispatcher.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 af3770edc21448435fe0778badf3872deb1f88de..0bf0226cc9c3aed0141f33fa8fda9627d39c3a58 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)));
@@ -1542,6 +1576,21 @@ class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest {
return text_content;
}
+ void OpaqueRedirectResponseCheck(const std::string& text_content,
+ const GURL& page_url) const {
+ std::unique_ptr<base::Value> result = base::JSONReader::Read(text_content);
+ base::DictionaryValue* dict = nullptr;
+ ASSERT_TRUE(result->GetAsDictionary(&dict));
+ EXPECT_EQ("opaqueredirect", GetString(*dict, "type"));
+ EXPECT_EQ(page_url, GURL(GetString(*dict, "url")));
+ EXPECT_EQ(0, GetInt(*dict, "status"));
+ EXPECT_FALSE(GetBoolean(*dict, "ok"));
+ EXPECT_EQ("", GetString(*dict, "statusText"));
+ const base::ListValue* headers = nullptr;
+ ASSERT_TRUE(dict->GetList("headers", &headers));
+ EXPECT_EQ(0u, headers->GetSize());
+ }
+
std::map<std::string, std::vector<net::test_server::HttpRequest>>
request_log_;
@@ -1682,15 +1731,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 +1858,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 +1888,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".
@@ -1889,15 +1916,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, EmptyBody) {
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("[]", GetTextContent());
+ EXPECT_EQ("[]", LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
EXPECT_EQ(1, GetRequestCount(kPageUrl));
}
@@ -1940,17 +1959,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,
@@ -1965,28 +1975,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",
@@ -2002,21 +2002,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,
@@ -2041,38 +2032,28 @@ 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, NormalRedirect) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
const char kRedirectedPageUrl[] =
@@ -2083,8 +2064,6 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, RejectRedirects) {
"Location: /service_worker/navigation_preload_redirected.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);
@@ -2093,25 +2072,131 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, RejectRedirects) {
"text/javascript");
RegisterStaticFile(kRedirectedPageUrl, kRedirectedPage, "text/html");
- 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());
+ OpaqueRedirectResponseCheck(
+ LoadNavigationPreloadTestPage(page_url, worker_url, "RESOLVED"),
+ page_url);
// 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());
+}
+
+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 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_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 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(kRedirectedPageUrl1, kRedirectedPage, "text/html");
+
+ // 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(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");
+
+ // 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.
falken 2017/03/31 07:36:03 Make this a TODO with bug?
horo 2017/03/31 09:56:30 Done.
+ 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));
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+ InvalidRedirect_NoLocation) {
+ 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"
+ "Custom-Header: hello\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");
+
+ OpaqueRedirectResponseCheck(
+ LoadNavigationPreloadTestPage(page_url, worker_url, "RESOLVED"),
+ page_url);
+
+ // The page request must be sent only once, since the worker responded with
+ // a generated Response.
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+ InvalidRedirect_NoLocationWithBody) {
+ 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"
+ "Custom-Header: hello\r\n"
+ "\r\n"
+ "Body\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");
+
+ OpaqueRedirectResponseCheck(
+ LoadNavigationPreloadTestPage(page_url, worker_url, "RESOLVED"),
+ page_url);
+
+ // 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
« no previous file with comments | « no previous file | content/browser/service_worker/service_worker_fetch_dispatcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698