blob: b67bdebf9ce82eb041d08a588917bcc791f24e87 [file] [log] [blame]
// Copyright 2017 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.
#include "content/renderer/loader/web_worker_fetch_context_impl.h"
#include <utility>
#include "base/bind.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "content/child/child_thread_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
#include "content/renderer/service_worker/service_worker_subresource_loader.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/loader_constants.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
#include "third_party/blink/public/platform/child_url_loader_factory_bundle.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_context.h"
#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
#include "third_party/blink/public/platform/url_loader_throttle_provider.h"
#include "third_party/blink/public/platform/weak_wrapper_resource_load_info_notifier.h"
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_code_cache_loader.h"
#include "third_party/blink/public/platform/web_frame_request_blocker.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_url_request_extra_data.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle_provider.h"
namespace content {
WebWorkerFetchContextImpl::RewriteURLFunction g_rewrite_url = nullptr;
namespace {
// Runs on a background thread created in ResetServiceWorkerURLLoaderFactory().
void CreateServiceWorkerSubresourceLoaderFactory(
mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
remote_container_host,
const std::string& client_id,
std::unique_ptr<network::PendingSharedURLLoaderFactory> fallback_factory,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<base::SequencedTaskRunner> worker_timing_callback_task_runner,
base::RepeatingCallback<
void(int, mojo::PendingReceiver<blink::mojom::WorkerTimingContainer>)>
worker_timing_callback) {
ServiceWorkerSubresourceLoaderFactory::Create(
base::MakeRefCounted<ControllerServiceWorkerConnector>(
std::move(remote_container_host),
mojo::NullRemote() /* remote_controller */, client_id),
network::SharedURLLoaderFactory::Create(std::move(fallback_factory)),
std::move(receiver), std::move(task_runner),
std::move(worker_timing_callback_task_runner),
std::move(worker_timing_callback));
}
} // namespace
// static
void WebWorkerFetchContextImpl::InstallRewriteURLFunction(
RewriteURLFunction rewrite_url) {
CHECK(!g_rewrite_url);
g_rewrite_url = rewrite_url;
}
// An implementation of WebURLLoaderFactory that is aware of service workers. In
// the usual case, it creates a loader that uses |loader_factory_|. But if the
// worker fetch context is controlled by a service worker, it creates a loader
// that uses |service_worker_loader_factory_| for requests that should be
// intercepted by the service worker.
class WebWorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory {
public:
Factory(scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
const blink::WebVector<blink::WebString>& cors_exempt_header_list,
base::WaitableEvent* terminate_sync_load_event)
: WebURLLoaderFactory(std::move(loader_factory),
cors_exempt_header_list,
terminate_sync_load_event) {}
~Factory() override = default;
std::unique_ptr<blink::WebURLLoader> CreateURLLoader(
const blink::WebURLRequest& request,
std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
freezable_task_runner_handle,
std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
unfreezable_task_runner_handle,
blink::CrossVariantMojoRemote<blink::mojom::KeepAliveHandleInterfaceBase>
keep_alive_handle,
blink::WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
override {
DCHECK(freezable_task_runner_handle);
DCHECK(unfreezable_task_runner_handle);
if (CanCreateServiceWorkerURLLoader(request)) {
// Create our own URLLoader to route the request to the controller service
// worker.
return std::make_unique<blink::WebURLLoader>(
cors_exempt_header_list_, terminate_sync_load_event_,
std::move(freezable_task_runner_handle),
std::move(unfreezable_task_runner_handle),
service_worker_loader_factory_, std::move(keep_alive_handle),
back_forward_cache_loader_helper);
}
return std::make_unique<blink::WebURLLoader>(
cors_exempt_header_list_, terminate_sync_load_event_,
std::move(freezable_task_runner_handle),
std::move(unfreezable_task_runner_handle), loader_factory_,
std::move(keep_alive_handle), back_forward_cache_loader_helper);
}
void SetServiceWorkerURLLoaderFactory(
mojo::PendingRemote<network::mojom::URLLoaderFactory>
service_worker_loader_factory) {
if (!service_worker_loader_factory) {
service_worker_loader_factory_ = nullptr;
return;
}
service_worker_loader_factory_ =
base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(service_worker_loader_factory));
}
base::WeakPtr<Factory> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
private:
bool CanCreateServiceWorkerURLLoader(const blink::WebURLRequest& request) {
// TODO(horo): Unify this code path with
// ServiceWorkerNetworkProviderForFrame::CreateURLLoader that is used
// for document cases.
// We need the service worker loader factory populated in order to create
// our own URLLoader for subresource loading via a service worker.
if (!service_worker_loader_factory_)
return false;
// If the URL is not http(s) or otherwise allowed, do not intercept the
// request. Schemes like 'blob' and 'file' are not eligible to be
// intercepted by service workers.
// TODO(falken): Let ServiceWorkerSubresourceLoaderFactory handle the
// request and move this check there (i.e., for such URLs, it should use
// its fallback factory).
if (!GURL(request.Url()).SchemeIsHTTPOrHTTPS() &&
!OriginCanAccessServiceWorkers(request.Url())) {
return false;
}
// If GetSkipServiceWorker() returns true, no need to intercept the request.
if (request.GetSkipServiceWorker())
return false;
return true;
}
scoped_refptr<network::SharedURLLoaderFactory> service_worker_loader_factory_;
base::WeakPtrFactory<Factory> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Factory);
};
scoped_refptr<WebWorkerFetchContextImpl> WebWorkerFetchContextImpl::Create(
blink::WebServiceWorkerProviderContext* provider_context,
const blink::RendererPreferences& renderer_preferences,
mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
watcher_receiver,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_loader_factory,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_fallback_factory,
mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
pending_subresource_loader_updater,
const std::vector<std::string>& cors_exempt_header_list,
mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
pending_resource_load_info_notifier) {
mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
service_worker_client_receiver;
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
service_worker_worker_client_registry;
mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
service_worker_container_host;
// Some sandboxed iframes are not allowed to use service worker so don't have
// a real service worker provider, so the provider context is null.
if (provider_context) {
provider_context->BindServiceWorkerWorkerClientRegistryReceiver(
service_worker_worker_client_registry.InitWithNewPipeAndPassReceiver());
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClient> worker_client;
service_worker_client_receiver =
worker_client.InitWithNewPipeAndPassReceiver();
provider_context->BindServiceWorkerWorkerClientRemote(
std::move(worker_client));
service_worker_container_host =
provider_context->CloneRemoteContainerHost();
}
scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context =
base::AdoptRef(new WebWorkerFetchContextImpl(
renderer_preferences, std::move(watcher_receiver),
std::move(service_worker_client_receiver),
std::move(service_worker_worker_client_registry),
std::move(service_worker_container_host),
std::move(pending_loader_factory),
std::move(pending_fallback_factory),
std::move(pending_subresource_loader_updater),
GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
blink::URLLoaderThrottleProviderType::kWorker),
GetContentClient()
->renderer()
->CreateWebSocketHandshakeThrottleProvider(),
cors_exempt_header_list,
std::move(pending_resource_load_info_notifier)));
if (provider_context) {
worker_fetch_context->set_controller_service_worker_mode(
provider_context->GetControllerServiceWorkerMode());
worker_fetch_context->set_client_id(provider_context->client_id());
} else {
worker_fetch_context->set_controller_service_worker_mode(
blink::mojom::ControllerServiceWorkerMode::kNoController);
}
return worker_fetch_context;
}
WebWorkerFetchContextImpl::WebWorkerFetchContextImpl(
const blink::RendererPreferences& renderer_preferences,
mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
preference_watcher_receiver,
mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
service_worker_client_receiver,
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
pending_service_worker_worker_client_registry,
mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
service_worker_container_host,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_loader_factory,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_fallback_factory,
mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
pending_subresource_loader_updater,
std::unique_ptr<blink::URLLoaderThrottleProvider> throttle_provider,
std::unique_ptr<blink::WebSocketHandshakeThrottleProvider>
websocket_handshake_throttle_provider,
const std::vector<std::string>& cors_exempt_header_list,
mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
pending_resource_load_info_notifier)
: service_worker_client_receiver_(
std::move(service_worker_client_receiver)),
pending_service_worker_worker_client_registry_(
std::move(pending_service_worker_worker_client_registry)),
pending_service_worker_container_host_(
std::move(service_worker_container_host)),
pending_loader_factory_(std::move(pending_loader_factory)),
pending_fallback_factory_(std::move(pending_fallback_factory)),
pending_subresource_loader_updater_(
std::move(pending_subresource_loader_updater)),
renderer_preferences_(renderer_preferences),
preference_watcher_pending_receiver_(
std::move(preference_watcher_receiver)),
throttle_provider_(std::move(throttle_provider)),
websocket_handshake_throttle_provider_(
std::move(websocket_handshake_throttle_provider)),
cors_exempt_header_list_(cors_exempt_header_list),
pending_resource_load_info_notifier_(
std::move(pending_resource_load_info_notifier)) {}
WebWorkerFetchContextImpl::~WebWorkerFetchContextImpl() = default;
void WebWorkerFetchContextImpl::SetTerminateSyncLoadEvent(
base::WaitableEvent* terminate_sync_load_event) {
DCHECK(!terminate_sync_load_event_);
terminate_sync_load_event_ = terminate_sync_load_event;
}
scoped_refptr<WebWorkerFetchContextImpl>
WebWorkerFetchContextImpl::CloneForNestedWorkerDeprecated(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
DCHECK(!base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
service_worker_client_receiver;
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
service_worker_worker_client_registry;
if (service_worker_worker_client_registry_) {
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClient>
service_worker_client;
service_worker_client_receiver =
service_worker_client.InitWithNewPipeAndPassReceiver();
service_worker_worker_client_registry_->RegisterWorkerClient(
std::move(service_worker_client));
service_worker_worker_client_registry_->CloneWorkerClientRegistry(
service_worker_worker_client_registry.InitWithNewPipeAndPassReceiver());
}
mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
service_worker_container_host;
if (service_worker_container_host_) {
service_worker_container_host_->CloneContainerHost(
service_worker_container_host.InitWithNewPipeAndPassReceiver());
}
// |pending_subresource_loader_updater| is not used for
// non-PlzDedicatedWorker.
scoped_refptr<WebWorkerFetchContextImpl> new_context =
CloneForNestedWorkerInternal(
std::move(service_worker_client_receiver),
std::move(service_worker_worker_client_registry),
std::move(service_worker_container_host), loader_factory_->Clone(),
fallback_factory_->Clone(),
/*pending_subresource_loader_updater=*/mojo::NullReceiver(),
std::move(task_runner));
new_context->controller_service_worker_mode_ =
controller_service_worker_mode_;
return new_context;
}
scoped_refptr<WebWorkerFetchContextImpl>
WebWorkerFetchContextImpl::CloneForNestedWorker(
blink::WebServiceWorkerProviderContext* service_worker_provider_context,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_loader_factory,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_fallback_factory,
mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
pending_subresource_loader_updater,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
DCHECK(base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
DCHECK(pending_loader_factory);
DCHECK(pending_fallback_factory);
DCHECK(task_runner);
if (!service_worker_provider_context) {
return CloneForNestedWorkerInternal(
/*service_worker_client_receiver=*/mojo::NullReceiver(),
/*service_worker_worker_client_registry=*/mojo::NullRemote(),
/*container_host=*/mojo::NullRemote(),
std::move(pending_loader_factory), std::move(pending_fallback_factory),
std::move(pending_subresource_loader_updater), std::move(task_runner));
}
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
service_worker_worker_client_registry;
service_worker_provider_context
->BindServiceWorkerWorkerClientRegistryReceiver(
service_worker_worker_client_registry
.InitWithNewPipeAndPassReceiver());
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClient> worker_client;
mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
service_worker_client_receiver =
worker_client.InitWithNewPipeAndPassReceiver();
service_worker_provider_context->BindServiceWorkerWorkerClientRemote(
std::move(worker_client));
mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
service_worker_container_host =
service_worker_provider_context->CloneRemoteContainerHost();
scoped_refptr<WebWorkerFetchContextImpl> new_context =
CloneForNestedWorkerInternal(
std::move(service_worker_client_receiver),
std::move(service_worker_worker_client_registry),
std::move(service_worker_container_host),
std::move(pending_loader_factory),
std::move(pending_fallback_factory),
std::move(pending_subresource_loader_updater),
std::move(task_runner));
new_context->controller_service_worker_mode_ =
service_worker_provider_context->GetControllerServiceWorkerMode();
return new_context;
}
void WebWorkerFetchContextImpl::InitializeOnWorkerThread(
blink::AcceptLanguagesWatcher* watcher) {
DCHECK(!receiver_.is_bound());
DCHECK(!preference_watcher_receiver_.is_bound());
loader_factory_ = network::SharedURLLoaderFactory::Create(
std::move(pending_loader_factory_));
fallback_factory_ = network::SharedURLLoaderFactory::Create(
std::move(pending_fallback_factory_));
subresource_loader_updater_.Bind(
std::move(pending_subresource_loader_updater_));
if (service_worker_client_receiver_.is_valid())
receiver_.Bind(std::move(service_worker_client_receiver_));
if (pending_service_worker_worker_client_registry_) {
service_worker_worker_client_registry_.Bind(
std::move(pending_service_worker_worker_client_registry_));
}
if (preference_watcher_pending_receiver_.is_valid()) {
preference_watcher_receiver_.Bind(
std::move(preference_watcher_pending_receiver_));
}
if (pending_service_worker_container_host_) {
service_worker_container_host_.Bind(
std::move(pending_service_worker_container_host_));
}
if (pending_resource_load_info_notifier_) {
resource_load_info_notifier_.Bind(
std::move(pending_resource_load_info_notifier_));
resource_load_info_notifier_.set_disconnect_handler(base::BindOnce(
&WebWorkerFetchContextImpl::ResetWeakWrapperResourceLoadInfoNotifier,
base::Unretained(this)));
}
accept_languages_watcher_ = watcher;
DCHECK(loader_factory_);
DCHECK(!web_loader_factory_);
web_loader_factory_ = std::make_unique<Factory>(
loader_factory_, cors_exempt_header_list(), terminate_sync_load_event_);
ResetServiceWorkerURLLoaderFactory();
}
blink::WebURLLoaderFactory* WebWorkerFetchContextImpl::GetURLLoaderFactory() {
return web_loader_factory_.get();
}
std::unique_ptr<blink::WebURLLoaderFactory>
WebWorkerFetchContextImpl::WrapURLLoaderFactory(
blink::CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase>
url_loader_factory) {
return std::make_unique<blink::WebURLLoaderFactory>(
base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(url_loader_factory)),
cors_exempt_header_list(), terminate_sync_load_event_);
}
std::unique_ptr<blink::WebCodeCacheLoader>
WebWorkerFetchContextImpl::CreateCodeCacheLoader() {
return blink::WebCodeCacheLoader::Create(terminate_sync_load_event_);
}
void WebWorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) {
if (renderer_preferences_.enable_do_not_track) {
request.SetHttpHeaderField(
blink::WebString::FromUTF8(blink::kDoNotTrackHeader), "1");
}
auto url_request_extra_data =
base::MakeRefCounted<blink::WebURLRequestExtraData>();
url_request_extra_data->set_frame_request_blocker(frame_request_blocker_);
if (throttle_provider_) {
url_request_extra_data->set_url_loader_throttles(
throttle_provider_->CreateThrottles(ancestor_frame_id_, request));
}
request.SetURLRequestExtraData(std::move(url_request_extra_data));
if (g_rewrite_url)
request.SetUrl(g_rewrite_url(request.Url().GetString().Utf8(), false));
if (!renderer_preferences_.enable_referrers) {
request.SetReferrerString(blink::WebString());
request.SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
}
}
blink::mojom::ControllerServiceWorkerMode
WebWorkerFetchContextImpl::GetControllerServiceWorkerMode() const {
return controller_service_worker_mode_;
}
void WebWorkerFetchContextImpl::SetIsOnSubframe(bool is_on_sub_frame) {
is_on_sub_frame_ = is_on_sub_frame;
}
bool WebWorkerFetchContextImpl::IsOnSubframe() const {
return is_on_sub_frame_;
}
net::SiteForCookies WebWorkerFetchContextImpl::SiteForCookies() const {
return site_for_cookies_;
}
base::Optional<blink::WebSecurityOrigin>
WebWorkerFetchContextImpl::TopFrameOrigin() const {
// TODO(jkarlin): set_top_frame_origin is only called for dedicated workers.
// Determine the top-frame-origin of a shared worker as well. See
// https://crbug.com/918868.
return top_frame_origin_;
}
void WebWorkerFetchContextImpl::SetSubresourceFilterBuilder(
std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder>
subresource_filter_builder) {
subresource_filter_builder_ = std::move(subresource_filter_builder);
}
std::unique_ptr<blink::WebDocumentSubresourceFilter>
WebWorkerFetchContextImpl::TakeSubresourceFilter() {
if (!subresource_filter_builder_)
return nullptr;
return std::move(subresource_filter_builder_)->Build();
}
std::unique_ptr<blink::WebSocketHandshakeThrottle>
WebWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
if (!websocket_handshake_throttle_provider_)
return nullptr;
return websocket_handshake_throttle_provider_->CreateThrottle(
ancestor_frame_id_, std::move(task_runner));
}
blink::CrossVariantMojoReceiver<
blink::mojom::WorkerTimingContainerInterfaceBase>
WebWorkerFetchContextImpl::TakePendingWorkerTimingReceiver(int request_id) {
auto iter = worker_timing_container_receivers_.find(request_id);
if (iter == worker_timing_container_receivers_.end()) {
return {};
}
auto receiver = std::move(iter->second);
worker_timing_container_receivers_.erase(iter);
return std::move(receiver);
}
void WebWorkerFetchContextImpl::SetIsOfflineMode(bool is_offline_mode) {
// Worker doesn't support offline mode. There should be no callers.
NOTREACHED();
}
void WebWorkerFetchContextImpl::set_controller_service_worker_mode(
blink::mojom::ControllerServiceWorkerMode mode) {
controller_service_worker_mode_ = mode;
}
void WebWorkerFetchContextImpl::set_ancestor_frame_id(int id) {
ancestor_frame_id_ = id;
}
void WebWorkerFetchContextImpl::set_frame_request_blocker(
scoped_refptr<blink::WebFrameRequestBlocker> frame_request_blocker) {
frame_request_blocker_ = frame_request_blocker;
}
void WebWorkerFetchContextImpl::set_site_for_cookies(
const net::SiteForCookies& site_for_cookies) {
site_for_cookies_ = site_for_cookies;
}
void WebWorkerFetchContextImpl::set_top_frame_origin(
const blink::WebSecurityOrigin& top_frame_origin) {
top_frame_origin_ = top_frame_origin;
}
void WebWorkerFetchContextImpl::set_client_id(
const blink::WebString& client_id) {
// Make a deep copy because we will visit it on the worker thread.
client_id_ = client_id.IsolatedCopy();
}
void WebWorkerFetchContextImpl::OnControllerChanged(
blink::mojom::ControllerServiceWorkerMode mode) {
set_controller_service_worker_mode(mode);
ResetServiceWorkerURLLoaderFactory();
}
scoped_refptr<WebWorkerFetchContextImpl>
WebWorkerFetchContextImpl::CloneForNestedWorkerInternal(
mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
service_worker_client_receiver,
mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
service_worker_worker_client_registry,
mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
service_worker_container_host,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_loader_factory,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_fallback_factory,
mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
pending_subresource_loader_updater,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
pending_resource_load_info_notifier;
if (resource_load_info_notifier_) {
resource_load_info_notifier_->Clone(
pending_resource_load_info_notifier.InitWithNewPipeAndPassReceiver());
}
mojo::PendingRemote<blink::mojom::RendererPreferenceWatcher>
preference_watcher;
auto new_context = base::AdoptRef(new WebWorkerFetchContextImpl(
renderer_preferences_,
preference_watcher.InitWithNewPipeAndPassReceiver(),
std::move(service_worker_client_receiver),
std::move(service_worker_worker_client_registry),
std::move(service_worker_container_host),
std::move(pending_loader_factory), std::move(pending_fallback_factory),
std::move(pending_subresource_loader_updater),
throttle_provider_ ? throttle_provider_->Clone() : nullptr,
websocket_handshake_throttle_provider_
? websocket_handshake_throttle_provider_->Clone(
std::move(task_runner))
: nullptr,
cors_exempt_header_list_,
std::move(pending_resource_load_info_notifier)));
new_context->is_on_sub_frame_ = is_on_sub_frame_;
new_context->ancestor_frame_id_ = ancestor_frame_id_;
new_context->frame_request_blocker_ = frame_request_blocker_;
new_context->site_for_cookies_ = site_for_cookies_;
new_context->top_frame_origin_ = top_frame_origin_;
child_preference_watchers_.Add(std::move(preference_watcher));
return new_context;
}
void WebWorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() {
if (!web_loader_factory_)
return;
if (GetControllerServiceWorkerMode() !=
blink::mojom::ControllerServiceWorkerMode::kControlled) {
web_loader_factory_->SetServiceWorkerURLLoaderFactory(mojo::NullRemote());
return;
}
if (!service_worker_container_host_)
return;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
service_worker_url_loader_factory;
mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
service_worker_container_host;
service_worker_container_host_->CloneContainerHost(
service_worker_container_host.InitWithNewPipeAndPassReceiver());
// To avoid potential dead-lock while synchronous loading, create the
// SubresourceLoaderFactory on a background thread.
auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
task_runner->PostTask(
FROM_HERE,
base::BindOnce(
&CreateServiceWorkerSubresourceLoaderFactory,
std::move(service_worker_container_host), client_id_.Utf8(),
fallback_factory_->Clone(),
service_worker_url_loader_factory.InitWithNewPipeAndPassReceiver(),
task_runner, base::SequencedTaskRunnerHandle::Get(),
base::BindRepeating(
&WebWorkerFetchContextImpl::AddPendingWorkerTimingReceiver,
weak_factory_.GetWeakPtr())));
web_loader_factory_->SetServiceWorkerURLLoaderFactory(
std::move(service_worker_url_loader_factory));
}
void WebWorkerFetchContextImpl::UpdateSubresourceLoaderFactories(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories) {
auto subresource_loader_factory_bundle =
base::MakeRefCounted<blink::ChildURLLoaderFactoryBundle>(
std::make_unique<blink::ChildPendingURLLoaderFactoryBundle>(
std::move(subresource_loader_factories)));
loader_factory_ = network::SharedURLLoaderFactory::Create(
subresource_loader_factory_bundle->Clone());
fallback_factory_ = network::SharedURLLoaderFactory::Create(
subresource_loader_factory_bundle->CloneWithoutAppCacheFactory());
web_loader_factory_ = std::make_unique<Factory>(
loader_factory_, cors_exempt_header_list(), terminate_sync_load_event_);
ResetServiceWorkerURLLoaderFactory();
}
void WebWorkerFetchContextImpl::NotifyUpdate(
const blink::RendererPreferences& new_prefs) {
if (accept_languages_watcher_ &&
renderer_preferences_.accept_languages != new_prefs.accept_languages)
accept_languages_watcher_->NotifyUpdate();
renderer_preferences_ = new_prefs;
for (auto& watcher : child_preference_watchers_)
watcher->NotifyUpdate(new_prefs);
}
blink::WebString WebWorkerFetchContextImpl::GetAcceptLanguages() const {
return blink::WebString::FromUTF8(renderer_preferences_.accept_languages);
}
void WebWorkerFetchContextImpl::ResetWeakWrapperResourceLoadInfoNotifier() {
weak_wrapper_resource_load_info_notifier_.reset();
}
blink::WebVector<blink::WebString>
WebWorkerFetchContextImpl::cors_exempt_header_list() {
blink::WebVector<blink::WebString> web_cors_exempt_header_list(
cors_exempt_header_list_.size());
std::transform(
cors_exempt_header_list_.begin(), cors_exempt_header_list_.end(),
web_cors_exempt_header_list.begin(),
[](const std::string& h) { return blink::WebString::FromLatin1(h); });
return web_cors_exempt_header_list;
}
void WebWorkerFetchContextImpl::AddPendingWorkerTimingReceiver(
int request_id,
mojo::PendingReceiver<blink::mojom::WorkerTimingContainer> receiver) {
// TODO(https://crbug.com/900700): Handle redirects properly. Currently on
// redirect, the receiver is replaced with a new one, discarding the timings
// before the redirect.
worker_timing_container_receivers_[request_id] = std::move(receiver);
}
std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
WebWorkerFetchContextImpl::CreateResourceLoadInfoNotifierWrapper() {
// If |resource_load_info_notifier_| is unbound, we will create
// ResourceLoadInfoNotifierWrapper without wrapping a ResourceLoadInfoNotifier
// and only collect histograms.
if (!resource_load_info_notifier_) {
return std::make_unique<blink::ResourceLoadInfoNotifierWrapper>(
/*resource_load_info_notifier=*/nullptr);
}
if (!weak_wrapper_resource_load_info_notifier_) {
weak_wrapper_resource_load_info_notifier_ =
std::make_unique<blink::WeakWrapperResourceLoadInfoNotifier>(
resource_load_info_notifier_.get());
}
return std::make_unique<blink::ResourceLoadInfoNotifierWrapper>(
weak_wrapper_resource_load_info_notifier_->AsWeakPtr());
}
} // namespace content