blob: 4de4b610db2e9374665e85f1f9f70af70a0c0082 [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.h"
#include "content/browser/browsing_topics/browsing_topics_url_loader_interceptor.h"
#include "content/browser/interest_group/ad_auction_url_loader_interceptor.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/early_hints.mojom.h"
namespace content {
SubresourceProxyingURLLoader::SubresourceProxyingURLLoader(
WeakDocumentPtr document,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory)
: resource_request_(resource_request),
forwarding_client_(std::move(client)) {
DCHECK(network_loader_factory);
CHECK(resource_request_.browsing_topics ||
resource_request_.ad_auction_headers);
if (resource_request_.browsing_topics) {
interceptors_.push_back(
std::make_unique<BrowsingTopicsURLLoaderInterceptor>(
document, resource_request_));
}
if (resource_request_.ad_auction_headers) {
interceptors_.push_back(std::make_unique<AdAuctionURLLoaderInterceptor>(
document, resource_request_));
}
// Make a copy of `resource_request`, because we may need to modify the
// request.
network::ResourceRequest new_resource_request = resource_request;
for (auto& interceptor : interceptors_) {
interceptor->WillStartRequest(new_resource_request.headers);
}
network_loader_factory->CreateLoaderAndStart(
loader_.BindNewPipeAndPassReceiver(), request_id, options,
new_resource_request, client_receiver_.BindNewPipeAndPassRemote(),
traffic_annotation);
client_receiver_.set_disconnect_handler(
base::BindOnce(&SubresourceProxyingURLLoader::OnNetworkConnectionError,
base::Unretained(this)));
}
SubresourceProxyingURLLoader::~SubresourceProxyingURLLoader() = default;
void SubresourceProxyingURLLoader::FollowRedirect(
const std::vector<std::string>& removed_headers,
const net::HttpRequestHeaders& modified_headers,
const net::HttpRequestHeaders& modified_cors_exempt_headers,
const std::optional<GURL>& new_url) {
std::vector<std::string> new_removed_headers = removed_headers;
net::HttpRequestHeaders new_modified_headers = modified_headers;
for (auto& interceptor : interceptors_) {
interceptor->WillFollowRedirect(new_url, new_removed_headers,
new_modified_headers);
}
loader_->FollowRedirect(new_removed_headers, new_modified_headers,
modified_cors_exempt_headers, new_url);
}
void SubresourceProxyingURLLoader::SetPriority(net::RequestPriority priority,
int intra_priority_value) {
loader_->SetPriority(priority, intra_priority_value);
}
void SubresourceProxyingURLLoader::OnReceiveEarlyHints(
network::mojom::EarlyHintsPtr early_hints) {
forwarding_client_->OnReceiveEarlyHints(std::move(early_hints));
}
void SubresourceProxyingURLLoader::OnReceiveResponse(
network::mojom::URLResponseHeadPtr head,
mojo::ScopedDataPipeConsumerHandle body,
std::optional<mojo_base::BigBuffer> cached_metadata) {
for (auto& interceptor : interceptors_) {
interceptor->OnReceiveResponse(head);
}
forwarding_client_->OnReceiveResponse(std::move(head), std::move(body),
std::move(cached_metadata));
}
void SubresourceProxyingURLLoader::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
network::mojom::URLResponseHeadPtr head) {
for (auto& interceptor : interceptors_) {
interceptor->OnReceiveRedirect(redirect_info, head);
}
forwarding_client_->OnReceiveRedirect(redirect_info, std::move(head));
}
void SubresourceProxyingURLLoader::OnUploadProgress(
int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) {
forwarding_client_->OnUploadProgress(current_position, total_size,
std::move(callback));
}
void SubresourceProxyingURLLoader::OnTransferSizeUpdated(
int32_t transfer_size_diff) {
forwarding_client_->OnTransferSizeUpdated(transfer_size_diff);
}
void SubresourceProxyingURLLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {
forwarding_client_->OnComplete(status);
}
void SubresourceProxyingURLLoader::OnNetworkConnectionError() {
// The network loader has an error; we should let the client know it's closed
// by dropping this, which will in turn make this loader destroyed.
forwarding_client_.reset();
}
} // namespace content