Commit 0fd45315 authored by Tsuyoshi Horo's avatar Tsuyoshi Horo Committed by Commit Bot

Skip other interceptors after SignedExchangeRequestHandler started handling the request

Currently when both service-worker-servicification and network-service are not
enabled, the internally redirected request doesn't go to the service worker.
But when service-worker-servicification or network-service is enabled, the
internally redirected request goes to the service worker.

We may support service worker integration, like FetchEvent's preloadResponse in
future. But we don't have plan to support service worker integration without
service-worker-servicification.

To make this behavior consistent, this CL makes
NavigationURLLoaderImpl::URLLoaderRequestController skip sending the redirected
request of signed exchange to the service worker.

Bug: 894755
Change-Id: I6f22819655169b4d3c30de0aa269911111c45586
Reviewed-on: https://chromium-review.googlesource.com/c/1278433Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#599815}
parent 2d1c9dbb
...@@ -573,7 +573,8 @@ bool AppCacheRequestHandler::MaybeCreateLoaderForResponse( ...@@ -573,7 +573,8 @@ bool AppCacheRequestHandler::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response, const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader, network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request, network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) { ThrottlingURLLoader* url_loader,
bool* skip_other_interceptors) {
// The sync interface of this method is inherited from the // The sync interface of this method is inherited from the
// NavigationLoaderInterceptor class. The LoaderCallback created here is // NavigationLoaderInterceptor class. The LoaderCallback created here is
// invoked synchronously in fallback cases, and only when there really is // invoked synchronously in fallback cases, and only when there really is
......
...@@ -84,7 +84,8 @@ class CONTENT_EXPORT AppCacheRequestHandler ...@@ -84,7 +84,8 @@ class CONTENT_EXPORT AppCacheRequestHandler
const network::ResourceResponseHead& response, const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader, network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request, network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) override; ThrottlingURLLoader* url_loader,
bool* skip_other_interceptors) override;
base::Optional<SubresourceLoaderParams> MaybeCreateSubresourceLoaderParams() base::Optional<SubresourceLoaderParams> MaybeCreateSubresourceLoaderParams()
override; override;
......
...@@ -17,7 +17,8 @@ bool NavigationLoaderInterceptor::MaybeCreateLoaderForResponse( ...@@ -17,7 +17,8 @@ bool NavigationLoaderInterceptor::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response, const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader, network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request, network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) { ThrottlingURLLoader* url_loader,
bool* skip_other_interceptors) {
return false; return false;
} }
......
...@@ -93,11 +93,17 @@ class CONTENT_EXPORT NavigationLoaderInterceptor { ...@@ -93,11 +93,17 @@ class CONTENT_EXPORT NavigationLoaderInterceptor {
// intercept the inflight loading if necessary. Note that the |url_loader| // intercept the inflight loading if necessary. Note that the |url_loader|
// will be reset after this method is called, which will also drop the // will be reset after this method is called, which will also drop the
// URLLoader held by |url_loader_| if it is not unbound yet. // URLLoader held by |url_loader_| if it is not unbound yet.
// |skip_other_interceptors| is set to true when this interceptor will
// exclusively handle the navigation even after redirections. TODO(horo): This
// flag was introduced to skip service worker after signed exchange redirect.
// Remove this flag when we support service worker and signed exchange
// integration. See crbug.com/894755#c1. Nullptr is not allowed.
virtual bool MaybeCreateLoaderForResponse( virtual bool MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response, const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader, network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request, network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader); ThrottlingURLLoader* url_loader,
bool* skip_other_interceptors);
}; };
} // namespace content } // namespace content
......
...@@ -1391,16 +1391,24 @@ class NavigationURLLoaderImpl::URLLoaderRequestController ...@@ -1391,16 +1391,24 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (!default_loader_used_) if (!default_loader_used_)
return false; return false;
for (auto& interceptor : interceptors_) { for (size_t i = 0u; i < interceptors_.size(); ++i) {
NavigationLoaderInterceptor* interceptor = interceptors_[i].get();
network::mojom::URLLoaderClientRequest response_client_request; network::mojom::URLLoaderClientRequest response_client_request;
bool skip_other_interceptors = false;
if (interceptor->MaybeCreateLoaderForResponse( if (interceptor->MaybeCreateLoaderForResponse(
response, &response_url_loader_, &response_client_request, response, &response_url_loader_, &response_client_request,
url_loader_.get())) { url_loader_.get(), &skip_other_interceptors)) {
if (response_loader_binding_.is_bound()) if (response_loader_binding_.is_bound())
response_loader_binding_.Close(); response_loader_binding_.Close();
response_loader_binding_.Bind(std::move(response_client_request)); response_loader_binding_.Bind(std::move(response_client_request));
default_loader_used_ = false; default_loader_used_ = false;
url_loader_.reset(); url_loader_.reset();
if (skip_other_interceptors) {
std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
new_interceptors;
new_interceptors.push_back(std::move(interceptors_[i]));
new_interceptors.swap(interceptors_);
}
return true; return true;
} }
} }
......
...@@ -101,7 +101,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor { ...@@ -101,7 +101,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
const network::ResourceResponseHead& response, const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader, network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request, network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) override { ThrottlingURLLoader* url_loader,
bool* skip_other_interceptors) override {
return false; return false;
} }
......
...@@ -7,9 +7,12 @@ ...@@ -7,9 +7,12 @@
#include <utility> #include <utility>
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/optional.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h" #include "content/browser/bad_message.h"
...@@ -44,6 +47,14 @@ namespace content { ...@@ -44,6 +47,14 @@ namespace content {
namespace { namespace {
base::Optional<EmbeddedWorkerInstance::CreateNetworkFactoryCallback>&
GetNetworkFactoryCallbackForTest() {
static base::NoDestructor<
base::Optional<EmbeddedWorkerInstance::CreateNetworkFactoryCallback>>
callback;
return *callback;
}
// When a service worker version's failure count exceeds // When a service worker version's failure count exceeds
// |kMaxSameProcessFailureCount|, the embedded worker is forced to start in a // |kMaxSameProcessFailureCount|, the embedded worker is forced to start in a
// new process. // new process.
...@@ -95,7 +106,16 @@ std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle( ...@@ -95,7 +106,16 @@ std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
bool use_non_network_factories) { bool use_non_network_factories) {
auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>(); auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
network::mojom::URLLoaderFactoryPtrInfo default_factory_info; network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
rph->CreateURLLoaderFactory(origin, mojo::MakeRequest(&default_factory_info)); if (!GetNetworkFactoryCallbackForTest()) {
rph->CreateURLLoaderFactory(origin,
mojo::MakeRequest(&default_factory_info));
} else {
network::mojom::URLLoaderFactoryPtr original_factory;
rph->CreateURLLoaderFactory(origin, mojo::MakeRequest(&original_factory));
GetNetworkFactoryCallbackForTest()->Run(
mojo::MakeRequest(&default_factory_info), rph->GetID(),
original_factory.PassInterface());
}
factory_bundle->default_factory_info() = std::move(default_factory_info); factory_bundle->default_factory_info() = std::move(default_factory_info);
if (use_non_network_factories) { if (use_non_network_factories) {
...@@ -1069,4 +1089,10 @@ std::string EmbeddedWorkerInstance::StartingPhaseToString(StartingPhase phase) { ...@@ -1069,4 +1089,10 @@ std::string EmbeddedWorkerInstance::StartingPhaseToString(StartingPhase phase) {
return std::string(); return std::string();
} }
// static
void EmbeddedWorkerInstance::SetNetworkFactoryForTesting(
const CreateNetworkFactoryCallback& create_network_factory_callback) {
GetNetworkFactoryCallbackForTest() = create_network_factory_callback;
}
} // namespace content } // namespace content
...@@ -200,6 +200,16 @@ class CONTENT_EXPORT EmbeddedWorkerInstance ...@@ -200,6 +200,16 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
static std::string StatusToString(EmbeddedWorkerStatus status); static std::string StatusToString(EmbeddedWorkerStatus status);
static std::string StartingPhaseToString(StartingPhase phase); static std::string StartingPhaseToString(StartingPhase phase);
using CreateNetworkFactoryCallback = base::RepeatingCallback<void(
network::mojom::URLLoaderFactoryRequest request,
int process_id,
network::mojom::URLLoaderFactoryPtrInfo original_factory)>;
// Allows overriding the URLLoaderFactory creation for loading subresources
// from service workers (i.e., fetch()) and for loading non-installed service
// worker scripts.
static void SetNetworkFactoryForTesting(
const CreateNetworkFactoryCallback& url_loader_factory_callback);
// Forces this instance into STOPPED status and releases any state about the // Forces this instance into STOPPED status and releases any state about the
// running worker. Called when connection with the renderer died or the // running worker. Called when connection with the renderer died or the
// renderer is unresponsive. Essentially, it throws away any information // renderer is unresponsive. Essentially, it throws away any information
......
...@@ -253,9 +253,13 @@ bool SharedWorkerScriptLoader::MaybeCreateLoaderForResponse( ...@@ -253,9 +253,13 @@ bool SharedWorkerScriptLoader::MaybeCreateLoaderForResponse(
ThrottlingURLLoader* url_loader) { ThrottlingURLLoader* url_loader) {
DCHECK(default_loader_used_); DCHECK(default_loader_used_);
for (auto& interceptor : interceptors_) { for (auto& interceptor : interceptors_) {
if (interceptor->MaybeCreateLoaderForResponse(response, response_url_loader, bool skip_other_interceptors = false;
response_client_request, if (interceptor->MaybeCreateLoaderForResponse(
url_loader)) { response, response_url_loader, response_client_request, url_loader,
&skip_other_interceptors)) {
// Both ServiceWorkerRequestHandler and AppCacheRequestHandler don't set
// skip_other_interceptors.
DCHECK(!skip_other_interceptors);
subresource_loader_params_ = subresource_loader_params_ =
interceptor->MaybeCreateSubresourceLoaderParams(); interceptor->MaybeCreateSubresourceLoaderParams();
return true; return true;
......
...@@ -83,7 +83,8 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse( ...@@ -83,7 +83,8 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response, const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader, network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request, network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) { ThrottlingURLLoader* url_loader,
bool* skip_other_interceptors) {
DCHECK(!signed_exchange_loader_); DCHECK(!signed_exchange_loader_);
if (!signed_exchange_utils::ShouldHandleAsSignedHTTPExchange( if (!signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(
request_initiator_.GetURL(), response)) { request_initiator_.GetURL(), response)) {
...@@ -109,6 +110,8 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse( ...@@ -109,6 +110,8 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse(
url_loader_factory_, url_loader_throttles_getter_, url_loader_factory_, url_loader_throttles_getter_,
base::BindRepeating([](int id) { return id; }, frame_tree_node_id_), base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
metric_recorder_); metric_recorder_);
*skip_other_interceptors = true;
return true; return true;
} }
......
...@@ -53,7 +53,8 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor { ...@@ -53,7 +53,8 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
const network::ResourceResponseHead& response, const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader, network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request, network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) override; ThrottlingURLLoader* url_loader,
bool* skip_other_interceptors) override;
private: private:
void StartResponse(const network::ResourceRequest& resource_request, void StartResponse(const network::ResourceRequest& resource_request,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "content/browser/loader/navigation_url_loader_impl.h" #include "content/browser/loader/navigation_url_loader_impl.h"
#include "content/browser/loader/resource_message_filter.h" #include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/url_loader_factory_impl.h" #include "content/browser/loader/url_loader_factory_impl.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/storage_partition_impl.h" #include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_getter.h" #include "content/browser/url_loader_factory_getter.h"
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
...@@ -227,6 +228,12 @@ URLLoaderInterceptor::URLLoaderInterceptor(const InterceptCallback& callback) ...@@ -227,6 +228,12 @@ URLLoaderInterceptor::URLLoaderInterceptor(const InterceptCallback& callback)
RenderFrameHostImpl::SetNetworkFactoryForTesting(base::BindRepeating( RenderFrameHostImpl::SetNetworkFactoryForTesting(base::BindRepeating(
&URLLoaderInterceptor::CreateURLLoaderFactoryForSubresources, &URLLoaderInterceptor::CreateURLLoaderFactoryForSubresources,
base::Unretained(this))); base::Unretained(this)));
// Note: This URLLoaderFactory creation callback will be used not only for
// subresource loading from service workers (i.e., fetch()), but also for
// loading non-installed service worker scripts.
EmbeddedWorkerInstance::SetNetworkFactoryForTesting(base::BindRepeating(
&URLLoaderInterceptor::CreateURLLoaderFactoryForSubresources,
base::Unretained(this)));
} }
StoragePartitionImpl:: StoragePartitionImpl::
...@@ -253,6 +260,8 @@ URLLoaderInterceptor::~URLLoaderInterceptor() { ...@@ -253,6 +260,8 @@ URLLoaderInterceptor::~URLLoaderInterceptor() {
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
RenderFrameHostImpl::SetNetworkFactoryForTesting( RenderFrameHostImpl::SetNetworkFactoryForTesting(
RenderFrameHostImpl::CreateNetworkFactoryCallback()); RenderFrameHostImpl::CreateNetworkFactoryCallback());
EmbeddedWorkerInstance::SetNetworkFactoryForTesting(
RenderFrameHostImpl::CreateNetworkFactoryCallback());
} }
StoragePartitionImpl:: StoragePartitionImpl::
......
...@@ -22,13 +22,18 @@ class URLLoaderFactoryGetter; ...@@ -22,13 +22,18 @@ class URLLoaderFactoryGetter;
// Helper class to intercept URLLoaderFactory calls for tests. // Helper class to intercept URLLoaderFactory calls for tests.
// This intercepts: // This intercepts:
// -frame requests (which start from the browser, with PlzNavigate) // -frame requests (which start from the browser, with PlzNavigate)
// -subresource requests // -subresource requests from pages and dedicad workers and shared workers.
// -at ResourceMessageFilter for non network-service code path // -at ResourceMessageFilter for non network-service code path
// -by sending renderer an intermediate URLLoaderFactory for network-service // -by sending renderer an intermediate URLLoaderFactory for network-service
// codepath, as that normally routes directly to the network process // code path, as that normally routes directly to the network process
// -subresource requests from service workers and requests of non-installed
// service worker scripts
// -at ResourceMessageFilter for non network-service code path
// -at EmbeddedWorkerInstance for network-service code path.
// -requests by the browser
//
// -http(s)://mock.failed.request/foo URLs internally, copying the behavior // -http(s)://mock.failed.request/foo URLs internally, copying the behavior
// of net::URLRequestFailedJob // of net::URLRequestFailedJob
// -requests by the browser
// //
// Prefer not to use this class. In order of ease of use & simplicity: // Prefer not to use this class. In order of ease of use & simplicity:
// -if you need to serve static data, use net::test::EmbeddedTestServer and // -if you need to serve static data, use net::test::EmbeddedTestServer and
......
<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('publisher-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) => {
event.respondWith(new Response(
'<title>Generated</title>',
{headers:[['content-type', 'text/html']]}));
});
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