blob: 95fd4e70338b14d70b40452163f6c645ce6f0da2 [file] [log] [blame]
// Copyright 2019 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/core/loader/loader_factory_for_frame.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
LoaderFactoryForFrame::LoaderFactoryForFrame(DocumentLoader& document_loader,
LocalDOMWindow& window)
: document_loader_(document_loader),
window_(window),
prefetched_signed_exchange_manager_(
document_loader.GetPrefetchedSignedExchangeManager()),
keep_alive_handle_factory_(&window) {
window.GetFrame()->GetLocalFrameHostRemote().GetKeepAliveHandleFactory(
keep_alive_handle_factory_.BindNewPipeAndPassReceiver(
window.GetTaskRunner(TaskType::kNetworking)));
}
void LoaderFactoryForFrame::Trace(Visitor* visitor) const {
visitor->Trace(document_loader_);
visitor->Trace(window_);
visitor->Trace(prefetched_signed_exchange_manager_);
visitor->Trace(keep_alive_handle_factory_);
LoaderFactory::Trace(visitor);
}
std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
const ResourceRequest& request,
const ResourceLoaderOptions& options,
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper) {
WrappedResourceRequest webreq(request);
mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
url_loader_factory;
if (options.url_loader_factory) {
mojo::Remote<network::mojom::blink::URLLoaderFactory>
url_loader_factory_remote(std::move(options.url_loader_factory->data));
url_loader_factory_remote->Clone(
url_loader_factory.InitWithNewPipeAndPassReceiver());
}
// Resolve any blob: URLs that haven't been resolved yet. The XHR and
// fetch() API implementations resolve blob URLs earlier because there can
// be arbitrarily long delays between creating requests with those APIs and
// actually creating the URL loader here. Other subresource loading will
// immediately create the URL loader so resolving those blob URLs here is
// simplest.
// Don't resolve the URL again if this is a shared worker request though, as
// in that case the browser process will have already done so and the code
// here should just go through the normal non-blob specific code path (note
// that this is only strictly true if NetworkService/S13nSW is enabled, but
// if that isn't the case we're going to run into race conditions resolving
// the blob URL anyway so it doesn't matter if the blob URL gets resolved
// here or later in the browser process, so skipping blob URL resolution
// here for all shared worker loads is okay even with NetworkService/S13nSW
// disabled).
// TODO(mek): Move the RequestContext check to the worker side's relevant
// callsite when we make Shared Worker loading off-main-thread.
if (request.Url().ProtocolIs("blob") && !url_loader_factory &&
request.GetRequestContext() !=
mojom::blink::RequestContextType::SHARED_WORKER) {
window_->GetPublicURLManager().Resolve(
request.Url(), url_loader_factory.InitWithNewPipeAndPassReceiver());
}
LocalFrame* frame = window_->GetFrame();
DCHECK(frame);
FrameScheduler* frame_scheduler = frame->GetFrameScheduler();
DCHECK(frame_scheduler);
// TODO(altimin): frame_scheduler->CreateResourceLoadingTaskRunnerHandle is
// used when creating a URLLoader, and ResourceFetcher::GetTaskRunner is
// used whenever asynchronous tasks around resource loading are posted. Modify
// the code so that all the tasks related to loading a resource use the
// resource loader handle's task runner.
if (url_loader_factory) {
return Platform::Current()
->WrapURLLoaderFactory(std::move(url_loader_factory))
->CreateURLLoader(webreq, CreateTaskRunnerHandle(freezable_task_runner),
CreateTaskRunnerHandle(unfreezable_task_runner),
/*keep_alive_handle=*/mojo::NullRemote(),
back_forward_cache_loader_helper);
}
if (document_loader_->GetServiceWorkerNetworkProvider()) {
mojo::PendingRemote<mojom::blink::KeepAliveHandle> pending_remote;
mojo::PendingReceiver<mojom::blink::KeepAliveHandle> pending_receiver =
pending_remote.InitWithNewPipeAndPassReceiver();
auto loader =
document_loader_->GetServiceWorkerNetworkProvider()->CreateURLLoader(
webreq, CreateTaskRunnerHandle(freezable_task_runner),
CreateTaskRunnerHandle(unfreezable_task_runner),
std::move(pending_remote), back_forward_cache_loader_helper);
if (loader) {
IssueKeepAliveHandleIfRequested(request, frame->GetLocalFrameHostRemote(),
std::move(pending_receiver));
return loader;
}
}
if (prefetched_signed_exchange_manager_) {
auto loader =
prefetched_signed_exchange_manager_->MaybeCreateURLLoader(webreq);
if (loader)
return loader;
}
mojo::PendingRemote<mojom::blink::KeepAliveHandle> pending_remote;
IssueKeepAliveHandleIfRequested(
request, frame->GetLocalFrameHostRemote(),
pending_remote.InitWithNewPipeAndPassReceiver());
return frame->GetURLLoaderFactory()->CreateURLLoader(
webreq, CreateTaskRunnerHandle(freezable_task_runner),
CreateTaskRunnerHandle(unfreezable_task_runner),
std::move(pending_remote), back_forward_cache_loader_helper);
}
std::unique_ptr<WebCodeCacheLoader>
LoaderFactoryForFrame::CreateCodeCacheLoader() {
return Platform::Current()->CreateCodeCacheLoader();
}
std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
LoaderFactoryForFrame::CreateTaskRunnerHandle(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
return scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
std::move(task_runner));
}
void LoaderFactoryForFrame::IssueKeepAliveHandleIfRequested(
const ResourceRequest& request,
mojom::blink::LocalFrameHost& local_frame_host,
mojo::PendingReceiver<mojom::blink::KeepAliveHandle> pending_receiver) {
DCHECK(pending_receiver);
if (request.GetKeepalive() && keep_alive_handle_factory_.is_bound()) {
keep_alive_handle_factory_->IssueKeepAliveHandle(
std::move(pending_receiver));
}
if (!keep_alive_handle_factory_.is_bound()) {
// TODO(crbug.com/1188074): Remove this CHECK once the investigation is
// done.
CHECK(window_->IsContextDestroyed());
}
}
} // namespace blink