Commit 9ecea5f7 authored by Tsuyoshi Horo's avatar Tsuyoshi Horo Committed by Commit Bot

Reset the state of SWProviderHost when SXGRequestHandler handles the response.

I introduced skip_other_interceptors flag in crrev.com/c/1278433 to skip the
service worker handling of the synthesized redirection of signed exchange.
But this was wrong. We need to call ServiceWorkerProviderHost::SetDocumentUrl()
and SetTopmostFrameUrl() even after SignedExchangeRequestHandler started
handling the response to reject the service worker API calls from the page in
the signed exchange correctly. And also we need to call
SetControllerRegistration(null) to reset the controller state.

Bug: 894755,907712
Change-Id: Iace762636982429c23ec24d9af6a466468e4b9fb
Reviewed-on: https://chromium-review.googlesource.com/c/1347954Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610381}
parent 692edc28
...@@ -515,14 +515,28 @@ class NavigationURLLoaderImpl::URLLoaderRequestController ...@@ -515,14 +515,28 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
} }
// The ResourceDispatcherHostImpl can be null in unit tests. // The ResourceDispatcherHostImpl can be null in unit tests.
if (!intercepted && ResourceDispatcherHostImpl::Get()) { ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
ResourceDispatcherHostImpl::Get()->BeginNavigationRequest( if (!intercepted && rdh) {
rdh->BeginNavigationRequest(
resource_context_, url_request_context_getter->GetURLRequestContext(), resource_context_, url_request_context_getter->GetURLRequestContext(),
upload_file_system_context, *request_info_, upload_file_system_context, *request_info_,
std::move(navigation_ui_data_), std::move(url_loader_client), std::move(navigation_ui_data_), std::move(url_loader_client),
std::move(url_loader), service_worker_navigation_handle_core, std::move(url_loader), service_worker_navigation_handle_core,
appcache_handle_core, options, resource_request_->priority, appcache_handle_core, options, resource_request_->priority,
global_request_id_); global_request_id_);
if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
// Get the SWProviderHost for non-S13nSW path. For S13nSW path,
// |service_worker_provider_host_| must be set in
// CreateServiceWorkerInterceptor().
net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
ServiceWorkerProviderHost* service_worker_provider_host =
ServiceWorkerRequestHandler::GetProviderHost(url_request);
if (service_worker_provider_host) {
service_worker_provider_host_ =
service_worker_provider_host->AsWeakPtr();
}
}
} }
// TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't // TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
...@@ -1376,6 +1390,17 @@ class NavigationURLLoaderImpl::URLLoaderRequestController ...@@ -1376,6 +1390,17 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
new_interceptors; new_interceptors;
new_interceptors.push_back(std::move(interceptors_[i])); new_interceptors.push_back(std::move(interceptors_[i]));
new_interceptors.swap(interceptors_); new_interceptors.swap(interceptors_);
if (service_worker_provider_host_) {
// Reset the state of ServiceWorkerProviderHost.
// Currently we don't support Service Worker in Signed Exchange
// pages. The page will not be controlled by service workers. And
// Service Worker related APIs will fail with NoDocumentURL error.
// TODO(crbug/898733): Support SignedExchange loading and Service
// Worker integration.
service_worker_provider_host_->SetControllerRegistration(
nullptr, false /* notify_controllerchange */);
service_worker_provider_host_->UpdateURLs(GURL(), GURL());
}
} }
return true; return true;
} }
...@@ -1391,8 +1416,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController ...@@ -1391,8 +1416,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor( std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
const NavigationRequestInfo& request_info, const NavigationRequestInfo& request_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core) ServiceWorkerNavigationHandleCore*
const { service_worker_navigation_handle_core) {
const ResourceType resource_type = request_info.is_main_frame const ResourceType resource_type = request_info.is_main_frame
? RESOURCE_TYPE_MAIN_FRAME ? RESOURCE_TYPE_MAIN_FRAME
: RESOURCE_TYPE_SUB_FRAME; : RESOURCE_TYPE_SUB_FRAME;
...@@ -1408,7 +1433,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController ...@@ -1408,7 +1433,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
request_info.begin_params->skip_service_worker, resource_type, request_info.begin_params->skip_service_worker, resource_type,
request_info.begin_params->request_context_type, frame_type, request_info.begin_params->request_context_type, frame_type,
request_info.are_ancestors_secure, request_info.common_params.post_data, request_info.are_ancestors_secure, request_info.common_params.post_data,
web_contents_getter_); web_contents_getter_, &service_worker_provider_host_);
} }
std::unique_ptr<SignedExchangeRequestHandler> std::unique_ptr<SignedExchangeRequestHandler>
...@@ -1543,6 +1568,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController ...@@ -1543,6 +1568,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// If true, redirect checks will be handled in a proxy, and not here. // If true, redirect checks will be handled in a proxy, and not here.
bool bypass_redirect_checks_; bool bypass_redirect_checks_;
// Used to reset the state of ServiceWorkerProviderHost when
// SignedExchangeRequestHandler will handle the response.
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_;
mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_; mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
......
...@@ -146,7 +146,8 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( ...@@ -146,7 +146,8 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
network::mojom::RequestContextFrameType frame_type, network::mojom::RequestContextFrameType frame_type,
bool is_parent_frame_secure, bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body, scoped_refptr<network::ResourceRequestBody> body,
base::RepeatingCallback<WebContents*()> web_contents_getter) { base::RepeatingCallback<WebContents*()> web_contents_getter,
base::WeakPtr<ServiceWorkerProviderHost>* out_provider_host) {
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK(navigation_handle_core); DCHECK(navigation_handle_core);
...@@ -165,22 +166,22 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( ...@@ -165,22 +166,22 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
return nullptr; return nullptr;
// Initialize the SWProviderHost. // Initialize the SWProviderHost.
base::WeakPtr<ServiceWorkerProviderHost> provider_host = *out_provider_host = ServiceWorkerProviderHost::PreCreateNavigationHost(
ServiceWorkerProviderHost::PreCreateNavigationHost( context->AsWeakPtr(), is_parent_frame_secure,
context->AsWeakPtr(), is_parent_frame_secure, std::move(web_contents_getter));
std::move(web_contents_getter));
std::unique_ptr<ServiceWorkerRequestHandler> handler( std::unique_ptr<ServiceWorkerRequestHandler> handler(
provider_host->CreateRequestHandler( (*out_provider_host)
network::mojom::FetchRequestMode::kNavigate, ->CreateRequestHandler(
network::mojom::FetchCredentialsMode::kInclude, network::mojom::FetchRequestMode::kNavigate,
network::mojom::FetchRedirectMode::kManual, network::mojom::FetchCredentialsMode::kInclude,
std::string() /* integrity */, false /* keepalive */, resource_type, network::mojom::FetchRedirectMode::kManual,
request_context_type, frame_type, blob_storage_context->AsWeakPtr(), std::string() /* integrity */, false /* keepalive */,
body, skip_service_worker)); resource_type, request_context_type, frame_type,
blob_storage_context->AsWeakPtr(), body, skip_service_worker));
navigation_handle_core->DidPreCreateProviderHost( navigation_handle_core->DidPreCreateProviderHost(
provider_host->provider_id()); (*out_provider_host)->provider_id());
return base::WrapUnique<NavigationLoaderInterceptor>(handler.release()); return base::WrapUnique<NavigationLoaderInterceptor>(handler.release());
} }
......
...@@ -81,7 +81,8 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler ...@@ -81,7 +81,8 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
network::mojom::RequestContextFrameType frame_type, network::mojom::RequestContextFrameType frame_type,
bool is_parent_frame_secure, bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body, scoped_refptr<network::ResourceRequestBody> body,
base::RepeatingCallback<WebContents*()> web_contents_getter); base::RepeatingCallback<WebContents*()> web_contents_getter,
base::WeakPtr<ServiceWorkerProviderHost>* out_provider_host);
static std::unique_ptr<NavigationLoaderInterceptor> InitializeForSharedWorker( static std::unique_ptr<NavigationLoaderInterceptor> InitializeForSharedWorker(
const network::ResourceRequest& resource_request, const network::ResourceRequest& resource_request,
......
...@@ -169,6 +169,7 @@ class ServiceWorkerRequestHandlerTest : public testing::Test { ...@@ -169,6 +169,7 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
bool expected_handler_created) { bool expected_handler_created) {
std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core = std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core =
CreateNavigationHandleCore(helper_->context_wrapper()); CreateNavigationHandleCore(helper_->context_wrapper());
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host;
std::unique_ptr<NavigationLoaderInterceptor> interceptor = std::unique_ptr<NavigationLoaderInterceptor> interceptor =
ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
GURL(url), nullptr /* resource_context */, GURL(url), nullptr /* resource_context */,
...@@ -177,7 +178,8 @@ class ServiceWorkerRequestHandlerTest : public testing::Test { ...@@ -177,7 +178,8 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
blink::mojom::RequestContextType::HYPERLINK, blink::mojom::RequestContextType::HYPERLINK,
network::mojom::RequestContextFrameType::kTopLevel, network::mojom::RequestContextFrameType::kTopLevel,
true /* is_parent_frame_secure */, nullptr /* body */, true /* is_parent_frame_secure */, nullptr /* body */,
base::RepeatingCallback<WebContents*(void)>()); base::RepeatingCallback<WebContents*(void)>(),
&service_worker_provider_host);
return !!interceptor.get(); return !!interceptor.get();
} }
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock-matchers.h"
#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content { namespace content {
...@@ -522,7 +523,8 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerRealCertVerifierBrowserTest, ...@@ -522,7 +523,8 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerRealCertVerifierBrowserTest,
enum class SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam { enum class SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam {
kLegacy, kLegacy,
kServiceWorkerServicification kServiceWorkerServicification,
kNetworkService
}; };
class SignedExchangeRequestHandlerWithServiceWorkerBrowserTest class SignedExchangeRequestHandlerWithServiceWorkerBrowserTest
...@@ -532,14 +534,23 @@ class SignedExchangeRequestHandlerWithServiceWorkerBrowserTest ...@@ -532,14 +534,23 @@ class SignedExchangeRequestHandlerWithServiceWorkerBrowserTest
public: public:
SignedExchangeRequestHandlerWithServiceWorkerBrowserTest() = default; SignedExchangeRequestHandlerWithServiceWorkerBrowserTest() = default;
void SetUp() override { void SetUp() override {
if (GetParam() == switch (GetParam()) {
SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam :: case SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
kServiceWorkerServicification) { kLegacy:
feature_list_.InitWithFeatures( feature_list_.InitWithFeatures(
{blink::features::kServiceWorkerServicification}, {}); {}, {blink::features::kServiceWorkerServicification,
} else { network::features::kNetworkService});
feature_list_.InitWithFeatures( break;
{}, {blink::features::kServiceWorkerServicification}); case SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
kServiceWorkerServicification:
feature_list_.InitWithFeatures(
{blink::features::kServiceWorkerServicification},
{network::features::kNetworkService});
break;
case SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
kNetworkService:
feature_list_.InitAndEnableFeature(network::features::kNetworkService);
break;
} }
SignedExchangeRequestHandlerBrowserTestBase::SetUp(); SignedExchangeRequestHandlerBrowserTestBase::SetUp();
} }
...@@ -551,16 +562,11 @@ class SignedExchangeRequestHandlerWithServiceWorkerBrowserTest ...@@ -551,16 +562,11 @@ class SignedExchangeRequestHandlerWithServiceWorkerBrowserTest
SignedExchangeRequestHandlerWithServiceWorkerBrowserTest); SignedExchangeRequestHandlerWithServiceWorkerBrowserTest);
}; };
INSTANTIATE_TEST_CASE_P(
SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
testing::Values(
SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::kLegacy,
SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
kServiceWorkerServicification));
IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest, IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
Simple) { LogicalUrlInServiceWorkerScope) {
// SW-scope: https://test.example.org/test/
// SXG physical URL: http://127.0.0.1:PORT/sxg/test.example.org_test.sxg
// SXG logical URL: https://test.example.org/test/
InstallUrlInterceptor( InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"), GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor"); "content/test/data/sxg/test.example.org.public.pem.cbor");
...@@ -589,9 +595,134 @@ IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest, ...@@ -589,9 +595,134 @@ IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
TitleWatcher title_watcher(shell()->web_contents(), title); TitleWatcher title_watcher(shell()->web_contents(), title);
title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("Generated")); title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("Generated"));
NavigateToURL(shell(), url); NavigateToURL(shell(), url);
// The page content shoud be served from the signed exchange.
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
}
IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
NotControlledByDistributorsSW) {
// SW-scope: http://127.0.0.1:PORT/sxg/
// SXG physical URL: http://127.0.0.1:PORT/sxg/test.example.org_test.sxg
// SXG logical URL: https://test.example.org/test/
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor");
InstallMockCert();
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
const GURL install_sw_url = embedded_test_server()->GetURL(
"/sxg/no-respond-with-service-worker.html");
{
base::string16 title = base::ASCIIToUTF16("Done");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), install_sw_url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
}
base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), embedded_test_server()->GetURL(
"/sxg/test.example.org_test.sxg"));
EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
// The page must not be controlled by the service worker of the physical URL.
EXPECT_EQ(false, EvalJs(shell(), "!!navigator.serviceWorker.controller"));
} }
IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
NotControlledBySameOriginDistributorsSW) {
// SW-scope: https://test.example.org/scope/
// SXG physical URL: https://test.example.org/scope/test.example.org_test.sxg
// SXG logical URL: https://test.example.org/test/
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor");
InstallMockCert();
InstallUrlInterceptor(GURL("https://test.example.org/scope/test.sxg"),
"content/test/data/sxg/test.example.org_test.sxg");
const GURL install_sw_url = GURL(
"https://test.example.org/scope/no-respond-with-service-worker.html");
InstallUrlInterceptor(
install_sw_url,
"content/test/data/sxg/no-respond-with-service-worker.html");
InstallUrlInterceptor(
GURL("https://test.example.org/scope/no-respond-with-service-worker.js"),
"content/test/data/sxg/no-respond-with-service-worker.js");
{
base::string16 title = base::ASCIIToUTF16("Done");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), install_sw_url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
}
base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), GURL("https://test.example.org/scope/test.sxg"));
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
// The page must not be controlled by the service worker of the physical URL.
EXPECT_EQ(false, EvalJs(shell(), "!!navigator.serviceWorker.controller"));
}
IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
RegisterServiceWorkerFromSignedExchange) {
// SXG physical URL: http://127.0.0.1:PORT/sxg/test.example.org_test.sxg
// SXG logical URL: https://test.example.org/test/
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor");
InstallMockCert();
InstallUrlInterceptor(
GURL("https://test.example.org/test/publisher-service-worker.js"),
"content/test/data/sxg/publisher-service-worker.js");
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
{
base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
}
const std::string register_sw_script =
"(async function() {"
" try {"
" const registration = await navigator.serviceWorker.register("
" 'publisher-service-worker.js', {scope: './'});"
" window.domAutomationController.send(true);"
" } catch (e) {"
" window.domAutomationController.send(false);"
" }"
"})();";
bool result = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
register_sw_script, &result));
// serviceWorker.register() fails because the document URL of
// ServiceWorkerProviderHost is empty.
EXPECT_FALSE(result);
}
INSTANTIATE_TEST_CASE_P(
SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
testing::Values(
SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::kLegacy,
SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
kServiceWorkerServicification,
SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
kNetworkService));
struct SignedExchangeAcceptHeaderBrowserTestParam { struct SignedExchangeAcceptHeaderBrowserTestParam {
SignedExchangeAcceptHeaderBrowserTestParam( SignedExchangeAcceptHeaderBrowserTestParam(
bool sxg_enabled, bool sxg_enabled,
......
<script>
async function register(script, scope) {
const registration = await navigator.serviceWorker.register(
script, {scope: scope});
await new Promise(resolve =>
registration.installing.addEventListener('statechange', resolve));
}
async function initialize() {
await register('no-respond-with-service-worker.js', './');
document.title = 'Done';
}
initialize();
</script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
self.addEventListener('fetch', (event) => {
});
HTTP/1.1 200 OK
Content-Type: application/javascript
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment