Commit da9aac88 authored by Hiroki Nakagawa's avatar Hiroki Nakagawa Committed by Commit Bot

PlzWorker: Support AppCache's fallback case for shared workers

This CL makes SharedWorkerScriptFetcher ask network interceptors if they want
to handle a response served by the default network loader. This is necessary for
supporting AppCache's fallback.

A possible confusing point of this CL is
SharedWorkerScriptFetcher::OnReceiveResponse() can be called twice. First, it's
called when the interceptor or the default network loader serves the shared
worker's main script. Then, it's called again when the interceptor wants to
serve an alternative response for the response served by the default network
loader.

Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: I93b45fa1f2e42422c0e85d3a67471c891dc5992a
Bug: 715632
Reviewed-on: https://chromium-review.googlesource.com/c/1224611Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596122}
parent df242b02
......@@ -600,6 +600,8 @@ bool AppCacheRequestHandler::MaybeCreateLoaderForResponse(
return false;
}
DCHECK(was_called);
if (IsMainResourceType(resource_type_))
should_create_subresource_loader_ = true;
return true;
}
......
......@@ -7,7 +7,6 @@
#include "base/feature_list.h"
#include "content/browser/shared_worker/shared_worker_script_loader.h"
#include "content/browser/shared_worker/shared_worker_script_loader_factory.h"
#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_loader_throttle.h"
......@@ -71,7 +70,8 @@ SharedWorkerScriptFetcher::SharedWorkerScriptFetcher(
CreateAndStartCallback callback)
: script_loader_factory_(std::move(script_loader_factory)),
resource_request_(std::move(resource_request)),
callback_(std::move(callback)) {
callback_(std::move(callback)),
response_url_loader_binding_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
......@@ -104,14 +104,49 @@ void SharedWorkerScriptFetcher::OnReceiveResponse(
const network::ResourceResponseHead& head) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// TODO(nhiroki): Support AppCache's fallback case. See
// NavigationLoaderInterceptor::MaybeCreateLoaderForResponse() for
// reference (https://crbug.com/715632).
base::WeakPtr<SharedWorkerScriptLoader> script_loader =
script_loader_factory_->GetScriptLoader();
if (script_loader && script_loader->default_loader_used_) {
// If the default network loader was used to handle the URL load request we
// need to see if the request interceptors want to potentially create a new
// loader for the response, e.g. AppCache's fallback.
DCHECK(!response_url_loader_);
network::mojom::URLLoaderClientRequest response_client_request;
if (script_loader->MaybeCreateLoaderForResponse(head, &response_url_loader_,
&response_client_request,
url_loader_.get())) {
DCHECK(response_url_loader_);
response_url_loader_binding_.Bind(std::move(response_client_request));
subresource_loader_params_ = script_loader->TakeSubresourceLoaderParams();
url_loader_.reset();
// OnReceiveResponse() will be called again.
return;
}
}
blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params =
blink::mojom::SharedWorkerMainScriptLoadParams::New();
// Fill in params for loading shared worker's main script and subresources.
main_script_load_params->response_head = head;
main_script_load_params->url_loader_client_endpoints = url_loader_->Unbind();
if (url_loader_) {
// The main script was served by a request interceptor or the default
// network loader.
DCHECK(!response_url_loader_);
main_script_load_params->url_loader_client_endpoints =
url_loader_->Unbind();
subresource_loader_params_ = script_loader->TakeSubresourceLoaderParams();
} else {
// The main script was served by the default network loader first, and then
// a request interceptor created another loader |response_url_loader_| for
// serving an alternative response.
DCHECK(response_url_loader_);
DCHECK(response_url_loader_binding_.is_bound());
main_script_load_params->url_loader_client_endpoints =
network::mojom::URLLoaderClientEndpoints::New(
response_url_loader_.PassInterface(),
response_url_loader_binding_.Unbind());
}
for (size_t i = 0; i < redirect_infos_.size(); ++i) {
main_script_load_params->redirect_infos.emplace_back(redirect_infos_[i]);
......@@ -119,11 +154,8 @@ void SharedWorkerScriptFetcher::OnReceiveResponse(
redirect_response_heads_[i]);
}
base::Optional<SubresourceLoaderParams> subresource_loader_params =
script_loader_factory_->TakeSubresourceLoaderParams();
std::move(callback_).Run(std::move(main_script_load_params),
std::move(subresource_loader_params),
std::move(subresource_loader_params_),
true /* success */);
delete this;
}
......
......@@ -7,6 +7,8 @@
#include "base/callback.h"
#include "base/optional.h"
#include "content/common/navigation_subresource_loader_params.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader.mojom.h"
......@@ -22,7 +24,6 @@ namespace content {
class SharedWorkerScriptLoaderFactory;
class ThrottlingURLLoader;
class URLLoaderThrottle;
struct SubresourceLoaderParams;
// NetworkService (PlzWorker):
// This is an implementation of the URLLoaderClient for shared worker's main
......@@ -71,10 +72,22 @@ class SharedWorkerScriptFetcher : public network::mojom::URLLoaderClient {
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
std::unique_ptr<SharedWorkerScriptLoaderFactory> script_loader_factory_;
std::unique_ptr<network::ResourceRequest> resource_request_;
CreateAndStartCallback callback_;
// URLLoader instance backed by a request interceptor (e.g.,
// AppCacheRequestHandler) or the network service.
std::unique_ptr<ThrottlingURLLoader> url_loader_;
// URLLoader instance for handling a response received from the default
// network loader. This can be provided by an interceptor. For example,
// AppCache's interceptor creates this for AppCache's fallback case.
network::mojom::URLLoaderPtr response_url_loader_;
mojo::Binding<network::mojom::URLLoaderClient> response_url_loader_binding_;
base::Optional<SubresourceLoaderParams> subresource_loader_params_;
std::vector<net::RedirectInfo> redirect_infos_;
std::vector<network::ResourceResponseHead> redirect_response_heads_;
};
......
......@@ -117,6 +117,7 @@ void SharedWorkerScriptLoader::MaybeStartLoader(
void SharedWorkerScriptLoader::LoadFromNetwork(
bool reset_subresource_loader_params) {
default_loader_used_ = true;
network::mojom::URLLoaderClientPtr client;
if (url_loader_client_binding_)
url_loader_client_binding_.Unbind();
......@@ -245,4 +246,22 @@ void SharedWorkerScriptLoader::OnComplete(
client_->OnComplete(status);
}
bool SharedWorkerScriptLoader::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* response_url_loader,
network::mojom::URLLoaderClientRequest* response_client_request,
ThrottlingURLLoader* url_loader) {
DCHECK(default_loader_used_);
for (auto& interceptor : interceptors_) {
if (interceptor->MaybeCreateLoaderForResponse(response, response_url_loader,
response_client_request,
url_loader)) {
subresource_loader_params_ =
interceptor->MaybeCreateSubresourceLoaderParams();
return true;
}
}
return false;
}
} // namespace content
......@@ -20,6 +20,7 @@ class SharedURLLoaderFactory;
namespace content {
class AppCacheHost;
class ThrottlingURLLoader;
class NavigationLoaderInterceptor;
class ResourceContext;
class ServiceWorkerProviderHost;
......@@ -83,12 +84,25 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
mojo::ScopedDataPipeConsumerHandle body) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
// Returns a URLLoader client endpoint if an interceptor wants to handle the
// response, i.e. return a different response. For e.g. AppCache may have
// fallback content.
bool MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* response_url_loader,
network::mojom::URLLoaderClientRequest* response_client_request,
ThrottlingURLLoader* url_loader);
base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
return std::move(subresource_loader_params_);
}
base::WeakPtr<SharedWorkerScriptLoader> GetWeakPtr();
// Set to true if the default URLLoader (network service) was used for the
// current request.
bool default_loader_used_ = false;
private:
void Start();
void MaybeStartLoader(
......
......@@ -89,10 +89,4 @@ void SharedWorkerScriptLoaderFactory::Clone(
NOTREACHED();
}
base::Optional<SubresourceLoaderParams>
SharedWorkerScriptLoaderFactory::TakeSubresourceLoaderParams() {
DCHECK(script_loader_);
return script_loader_->TakeSubresourceLoaderParams();
}
} // namespace content
......@@ -59,7 +59,9 @@ class SharedWorkerScriptLoaderFactory
traffic_annotation) override;
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams();
base::WeakPtr<SharedWorkerScriptLoader> GetScriptLoader() {
return script_loader_;
}
private:
const int process_id_;
......
# These tests currently fail when run with --enable-features=NetworkSerivce
# See https://crbug.com/729849
crbug.com/829417 external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https.html [ Timeout ]
Bug(none) http/tests/security/cors-rfc1918 [ Crash Timeout ]
Bug(none) http/tests/security/powerfulFeatureRestrictions/old-powerful-features-on-insecure-origin.html [ Pass Timeout ]
Bug(none) virtual/outofblink-cors/http/tests/security/cors-rfc1918 [ Crash Timeout ]
......
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