blob: 63416de5d441b3f161cd1d9ee4018987f10a1a4a [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/loader/subresource_proxying_url_loader_service.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "content/browser/loader/prefetch_url_loader_service_context.h"
#include "content/browser/loader/subresource_proxying_url_loader.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
#include "content/public/common/content_client.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/load_flags.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
namespace content {
SubresourceProxyingURLLoaderService::BindContext::BindContext(
FrameTreeNodeId frame_tree_node_id,
scoped_refptr<network::SharedURLLoaderFactory> factory,
base::WeakPtr<RenderFrameHostImpl> render_frame_host,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache)
: frame_tree_node_id(frame_tree_node_id),
factory(factory),
render_frame_host(std::move(render_frame_host)),
cross_origin_factory(nullptr),
prefetched_signed_exchange_cache(
std::move(prefetched_signed_exchange_cache)) {}
void SubresourceProxyingURLLoaderService::BindContext::OnDidCommitNavigation(
WeakDocumentPtr committed_document) {
document = committed_document;
}
SubresourceProxyingURLLoaderService::BindContext::~BindContext() = default;
SubresourceProxyingURLLoaderService::SubresourceProxyingURLLoaderService(
BrowserContext* browser_context)
: prefetch_url_loader_service_context_(
std::make_unique<PrefetchURLLoaderServiceContext>(
browser_context,
loader_factory_receivers_)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
base::WeakPtr<SubresourceProxyingURLLoaderService::BindContext>
SubresourceProxyingURLLoaderService::GetFactory(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
FrameTreeNodeId frame_tree_node_id,
scoped_refptr<network::SharedURLLoaderFactory>
subresource_proxying_factory_bundle,
base::WeakPtr<RenderFrameHostImpl> render_frame_host,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto bind_context = base::MakeRefCounted<BindContext>(
frame_tree_node_id, subresource_proxying_factory_bundle,
std::move(render_frame_host),
std::move(prefetched_signed_exchange_cache));
base::WeakPtr<BindContext> weak_bind_context =
bind_context->weak_ptr_factory.GetWeakPtr();
loader_factory_receivers_.Add(this, std::move(receiver),
std::move(bind_context));
return weak_bind_context;
}
void SubresourceProxyingURLLoaderService::CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request_in,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!PrefetchURLLoaderServiceContext::IsPrefetchRequest(
resource_request_in) &&
!resource_request_in.browsing_topics &&
!resource_request_in.ad_auction_headers) {
loader_factory_receivers_.ReportBadMessage(
"Unexpected `resource_request_in` in "
"SubresourceProxyingURLLoaderService::CreateLoaderAndStart(): it's not "
"a prefetch or browsing_topics or ad_auction_headers request.");
return;
}
if (PrefetchURLLoaderServiceContext::IsPrefetchRequest(resource_request_in) &&
(resource_request_in.browsing_topics ||
resource_request_in.ad_auction_headers)) {
loader_factory_receivers_.ReportBadMessage(
"Unexpected `resource_request_in` in "
"SubresourceProxyingURLLoaderService::CreateLoaderAndStart(): prefetch "
"cannot be set at the same time with browsing_topics or "
"ad_auction_headers.");
return;
}
if (resource_request_in.browsing_topics &&
!base::FeatureList::IsEnabled(network::features::kBrowsingTopics)) {
loader_factory_receivers_.ReportBadMessage(
"Unexpected `resource_request_in` in "
"SubresourceProxyingURLLoaderService::CreateLoaderAndStart(): "
"browsing_topics is set when Topics API is disabled.");
return;
}
if (resource_request_in.ad_auction_headers &&
!base::FeatureList::IsEnabled(network::features::kInterestGroupStorage)) {
loader_factory_receivers_.ReportBadMessage(
"Unexpected `resource_request_in` in "
"SubresourceProxyingURLLoaderService::CreateLoaderAndStart(): "
"ad_auction_headers is set when InterestGroupStorage is disabled.");
return;
}
if (PrefetchURLLoaderServiceContext::IsPrefetchRequest(resource_request_in)) {
prefetch_url_loader_service_context_->CreatePrefetchLoaderAndStart(
std::move(receiver), request_id, options, resource_request_in,
std::move(client), traffic_annotation);
return;
}
// For non-prefetch requests, fall back to `SubresourceProxyingURLLoader`.
CreateSubresourceProxyingLoaderAndStart(
std::move(receiver), request_id, options, resource_request_in,
std::move(client), traffic_annotation);
}
void SubresourceProxyingURLLoaderService::
CreateSubresourceProxyingLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request_in,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
BindContext* current_context =
loader_factory_receivers_.current_context().get();
auto loader = std::make_unique<SubresourceProxyingURLLoader>(
current_context->document, request_id, options, resource_request_in,
std::move(client), traffic_annotation, current_context->factory);
auto* raw_loader = loader.get();
subresource_proxying_loader_receivers_.Add(raw_loader, std::move(receiver),
std::move(loader));
}
SubresourceProxyingURLLoaderService::~SubresourceProxyingURLLoaderService() =
default;
void SubresourceProxyingURLLoaderService::Clone(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
loader_factory_receivers_.Add(this, std::move(receiver),
loader_factory_receivers_.current_context());
}
} // namespace content