blob: 671bba02ed20b8db7a889bbea7bf231740681ff7 [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 "third_party/blink/renderer/modules/service_worker/web_service_worker_fetch_context_impl.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "third_party/blink/public/common/loader/loader_constants.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/internet_disconnected_web_url_loader.h"
#include "third_party/blink/public/platform/url_loader_throttle_provider.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 blink {
// static
scoped_refptr<WebServiceWorkerFetchContext>
WebServiceWorkerFetchContext::Create(
const RendererPreferences& renderer_preferences,
const WebURL& worker_script_url,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_url_loader_factory,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_script_loader_factory,
const WebURL& script_url_to_skip_throttling,
std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
std::unique_ptr<WebSocketHandshakeThrottleProvider>
websocket_handshake_throttle_provider,
CrossVariantMojoReceiver<
mojom::blink::RendererPreferenceWatcherInterfaceBase>
preference_watcher_receiver,
CrossVariantMojoReceiver<
mojom::blink::SubresourceLoaderUpdaterInterfaceBase>
pending_subresource_loader_updater,
const WebVector<WebString>& cors_exempt_header_list) {
// Create isolated copies for `worker_script_url` and
// `script_url_to_skip_throttling` as the fetch context will be used on a
// service worker thread that is different from the current thread.
return base::MakeRefCounted<WebServiceWorkerFetchContextImpl>(
renderer_preferences, KURL::CreateIsolated(worker_script_url.GetString()),
std::move(pending_url_loader_factory),
std::move(pending_script_loader_factory),
KURL::CreateIsolated(script_url_to_skip_throttling.GetString()),
std::move(throttle_provider),
std::move(websocket_handshake_throttle_provider),
std::move(preference_watcher_receiver),
std::move(pending_subresource_loader_updater), cors_exempt_header_list);
}
WebServiceWorkerFetchContextImpl::WebServiceWorkerFetchContextImpl(
const RendererPreferences& renderer_preferences,
const KURL& worker_script_url,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_url_loader_factory,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_script_loader_factory,
const KURL& script_url_to_skip_throttling,
std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
std::unique_ptr<WebSocketHandshakeThrottleProvider>
websocket_handshake_throttle_provider,
mojo::PendingReceiver<mojom::blink::RendererPreferenceWatcher>
preference_watcher_receiver,
mojo::PendingReceiver<mojom::blink::SubresourceLoaderUpdater>
pending_subresource_loader_updater,
const WebVector<WebString>& cors_exempt_header_list)
: renderer_preferences_(renderer_preferences),
worker_script_url_(worker_script_url),
pending_url_loader_factory_(std::move(pending_url_loader_factory)),
pending_script_loader_factory_(std::move(pending_script_loader_factory)),
script_url_to_skip_throttling_(script_url_to_skip_throttling),
throttle_provider_(std::move(throttle_provider)),
websocket_handshake_throttle_provider_(
std::move(websocket_handshake_throttle_provider)),
preference_watcher_pending_receiver_(
std::move(preference_watcher_receiver)),
pending_subresource_loader_updater_(
std::move(pending_subresource_loader_updater)),
cors_exempt_header_list_(cors_exempt_header_list) {}
WebServiceWorkerFetchContextImpl::~WebServiceWorkerFetchContextImpl() = default;
void WebServiceWorkerFetchContextImpl::SetTerminateSyncLoadEvent(
base::WaitableEvent* terminate_sync_load_event) {
DCHECK(!terminate_sync_load_event_);
terminate_sync_load_event_ = terminate_sync_load_event;
}
void WebServiceWorkerFetchContextImpl::InitializeOnWorkerThread(
AcceptLanguagesWatcher* watcher) {
preference_watcher_receiver_.Bind(
std::move(preference_watcher_pending_receiver_));
subresource_loader_updater_.Bind(
std::move(pending_subresource_loader_updater_));
web_url_loader_factory_ = std::make_unique<WebURLLoaderFactory>(
network::SharedURLLoaderFactory::Create(
std::move(pending_url_loader_factory_)),
cors_exempt_header_list_, terminate_sync_load_event_);
internet_disconnected_web_url_loader_factory_ =
std::make_unique<InternetDisconnectedWebURLLoaderFactory>();
if (pending_script_loader_factory_) {
web_script_loader_factory_ = std::make_unique<WebURLLoaderFactory>(
network::SharedURLLoaderFactory::Create(
std::move(pending_script_loader_factory_)),
cors_exempt_header_list_, terminate_sync_load_event_);
}
accept_languages_watcher_ = watcher;
}
WebURLLoaderFactory* WebServiceWorkerFetchContextImpl::GetURLLoaderFactory() {
if (is_offline_mode_)
return internet_disconnected_web_url_loader_factory_.get();
return web_url_loader_factory_.get();
}
std::unique_ptr<WebURLLoaderFactory>
WebServiceWorkerFetchContextImpl::WrapURLLoaderFactory(
CrossVariantMojoRemote<network::mojom::URLLoaderFactoryInterfaceBase>
url_loader_factory) {
return std::make_unique<WebURLLoaderFactory>(
base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(url_loader_factory)),
cors_exempt_header_list_, terminate_sync_load_event_);
}
WebURLLoaderFactory*
WebServiceWorkerFetchContextImpl::GetScriptLoaderFactory() {
return web_script_loader_factory_.get();
}
void WebServiceWorkerFetchContextImpl::WillSendRequest(WebURLRequest& request) {
if (renderer_preferences_.enable_do_not_track) {
request.SetHttpHeaderField(WebString::FromUTF8(kDoNotTrackHeader), "1");
}
auto url_request_extra_data = base::MakeRefCounted<WebURLRequestExtraData>();
url_request_extra_data->set_originated_from_service_worker(true);
const bool needs_to_skip_throttling =
static_cast<KURL>(request.Url()) == script_url_to_skip_throttling_ &&
(request.GetRequestContext() ==
mojom::blink::RequestContextType::SERVICE_WORKER ||
request.GetRequestContext() == mojom::blink::RequestContextType::SCRIPT);
if (needs_to_skip_throttling) {
// Throttling is needed when the skipped script is loaded again because it's
// served from ServiceWorkerInstalledScriptLoader after the second time,
// while at the first time the script comes from
// ServiceWorkerUpdatedScriptLoader which uses ThrottlingURLLoader in the
// browser process. See also comments at
// EmbeddedWorkerStartParams::script_url_to_skip_throttling.
// TODO(https://crbug.com/993641): need to simplify throttling for service
// worker scripts.
script_url_to_skip_throttling_ = KURL();
} else if (throttle_provider_) {
url_request_extra_data->set_url_loader_throttles(
throttle_provider_->CreateThrottles(MSG_ROUTING_NONE, request));
}
request.SetURLRequestExtraData(std::move(url_request_extra_data));
if (!renderer_preferences_.enable_referrers) {
request.SetReferrerString(WebString());
request.SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
}
}
mojom::ControllerServiceWorkerMode
WebServiceWorkerFetchContextImpl::GetControllerServiceWorkerMode() const {
return mojom::ControllerServiceWorkerMode::kNoController;
}
net::SiteForCookies WebServiceWorkerFetchContextImpl::SiteForCookies() const {
// According to the spec, we can use the |worker_script_url_| for
// SiteForCookies, because "site for cookies" for the service worker is
// the service worker's origin's host's registrable domain.
// https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-07#section-2.1.2
return net::SiteForCookies::FromUrl(worker_script_url_);
}
absl::optional<WebSecurityOrigin>
WebServiceWorkerFetchContextImpl::TopFrameOrigin() const {
return absl::nullopt;
}
std::unique_ptr<WebSocketHandshakeThrottle>
WebServiceWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
if (!websocket_handshake_throttle_provider_)
return nullptr;
return websocket_handshake_throttle_provider_->CreateThrottle(
MSG_ROUTING_NONE, std::move(task_runner));
}
void WebServiceWorkerFetchContextImpl::UpdateSubresourceLoaderFactories(
std::unique_ptr<PendingURLLoaderFactoryBundle>
subresource_loader_factories) {
web_url_loader_factory_ = std::make_unique<WebURLLoaderFactory>(
network::SharedURLLoaderFactory::Create(
std::move(subresource_loader_factories)),
cors_exempt_header_list_, terminate_sync_load_event_);
}
void WebServiceWorkerFetchContextImpl::NotifyUpdate(
const RendererPreferences& new_prefs) {
DCHECK(accept_languages_watcher_);
if (renderer_preferences_.accept_languages != new_prefs.accept_languages)
accept_languages_watcher_->NotifyUpdate();
renderer_preferences_ = new_prefs;
}
WebString WebServiceWorkerFetchContextImpl::GetAcceptLanguages() const {
return WebString::FromUTF8(renderer_preferences_.accept_languages);
}
CrossVariantMojoReceiver<mojom::WorkerTimingContainerInterfaceBase>
WebServiceWorkerFetchContextImpl::TakePendingWorkerTimingReceiver(
int request_id) {
// No receiver exists because requests from service workers are never handled
// by a service worker.
return {};
}
void WebServiceWorkerFetchContextImpl::SetIsOfflineMode(bool is_offline_mode) {
is_offline_mode_ = is_offline_mode;
}
} // namespace blink