#include "content/renderer/service_worker/service_worker_subresource_loader.h"
#include <optional>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/task/sequenced_task_runner.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "content/common/features.h"
#include "content/common/fetch/fetch_request_type_converters.h"
#include "content/common/service_worker/race_network_request_url_loader_client.h"
#include "content/common/service_worker/service_worker_router_evaluator.h"
#include "content/public/common/content_features.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/net_errors.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/record_ontransfersizeupdate_utils.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/service_worker_router_info.mojom-shared.h"
#include "services/network/public/mojom/service_worker_router_info.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/service_worker/service_worker_loader_helpers.h"
#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_fetch_handler_bypass_option.mojom-shared.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom.h"
#include "third_party/blink/public/platform/web_url_response.h"
namespace content {
namespace {
constexpr char kServiceWorkerSubresourceLoaderScope[] = …;
template <typename T>
static std::string MojoEnumToString(T mojo_enum) { … }
network::mojom::URLResponseHeadPtr RewriteResponseHead(
base::TimeTicks service_worker_start_time,
base::TimeTicks service_worker_ready_time,
base::TimeTicks service_worker_router_evaluation_start,
std::optional<network::mojom::ServiceWorkerRouterInfo>
service_worker_router_info,
network::mojom::URLResponseHeadPtr response_head) { … }
class HeaderRewritingURLLoaderClient : public network::mojom::URLLoaderClient { … };
void RestoreRequestBody(network::ResourceRequestBody* body,
network::DataElementChunkedDataPipe original_body) { … }
blink::mojom::ServiceWorkerFetchEventTimingPtr AdjustTimingIfNeededCrBug1342408(
blink::mojom::ServiceWorkerFetchEventTimingPtr timing) { … }
bool IsStaticRouterRaceRequestFixEnabled() { … }
}
class ServiceWorkerSubresourceLoader::StreamWaiter
: public blink::mojom::ServiceWorkerStreamCallback { … };
bool ServiceWorkerSubresourceLoader::MaybeStartAutoPreload() { … }
bool ServiceWorkerSubresourceLoader::MaybeStartRaceNetworkRequest() { … }
bool ServiceWorkerSubresourceLoader::StartRaceNetworkRequest() { … }
ServiceWorkerSubresourceLoader::ServiceWorkerSubresourceLoader(
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
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<ControllerServiceWorkerConnector> controller_connector,
scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
scoped_refptr<base::SequencedTaskRunner> task_runner,
base::WeakPtr<ServiceWorkerSubresourceLoaderFactory>
service_worker_subresource_loader_factory)
: … { … }
ServiceWorkerSubresourceLoader::~ServiceWorkerSubresourceLoader() = default;
void ServiceWorkerSubresourceLoader::OnMojoDisconnect() { … }
void ServiceWorkerSubresourceLoader::MaybeDeleteThis() { … }
void ServiceWorkerSubresourceLoader::StartRequest(
const network::ResourceRequest& resource_request) { … }
void ServiceWorkerSubresourceLoader::DispatchFetchEvent() { … }
void ServiceWorkerSubresourceLoader::DispatchFetchEventForSubresource() { … }
void ServiceWorkerSubresourceLoader::OnFetchEventFinished(
blink::mojom::ServiceWorkerEventStatus status) { … }
void ServiceWorkerSubresourceLoader::OnConnectionClosed() { … }
void ServiceWorkerSubresourceLoader::SettleFetchEventDispatch(
std::optional<blink::ServiceWorkerStatusCode> status) { … }
void ServiceWorkerSubresourceLoader::OnResponse(
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerFetchEventTimingPtr timing) { … }
void ServiceWorkerSubresourceLoader::OnResponseStream(
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::ServiceWorkerFetchEventTimingPtr timing) { … }
void ServiceWorkerSubresourceLoader::OnFallback(
std::optional<network::DataElementChunkedDataPipe> request_body,
blink::mojom::ServiceWorkerFetchEventTimingPtr timing) { … }
bool ServiceWorkerSubresourceLoader::
IsResponseAlreadyCommittedByRaceNetworkRequest() { … }
void ServiceWorkerSubresourceLoader::UpdateResponseTiming(
blink::mojom::ServiceWorkerFetchEventTimingPtr timing) { … }
void ServiceWorkerSubresourceLoader::StartResponse(
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) { … }
void ServiceWorkerSubresourceLoader::CommitResponseHeaders(
const network::mojom::URLResponseHeadPtr& response_head) { … }
void ServiceWorkerSubresourceLoader::CommitResponseBody(
const network::mojom::URLResponseHeadPtr& response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
std::optional<mojo_base::BigBuffer> cached_metadata) { … }
void ServiceWorkerSubresourceLoader::CommitEmptyResponseAndComplete() { … }
void ServiceWorkerSubresourceLoader::CommitCompleted(int error_code,
const char* reason) { … }
void ServiceWorkerSubresourceLoader::HandleRedirect(
const net::RedirectInfo& redirect_info,
const network::mojom::URLResponseHeadPtr& response_head) { … }
void ServiceWorkerSubresourceLoader::
RecordTimingMetricsForFetchHandlerHandledCase() { … }
void ServiceWorkerSubresourceLoader::
RecordTimingMetricsForNetworkFallbackCase() { … }
void ServiceWorkerSubresourceLoader::
RecordTimingMetricsForRaceNetworkReqestCase() { … }
bool ServiceWorkerSubresourceLoader::InitRecordTimingMetricsIfEligible(
const net::LoadTimingInfo& load_timing) { … }
void ServiceWorkerSubresourceLoader::
RecordForwardServiceWorkerToWorkerReadyTiming(
const net::LoadTimingInfo& load_timing) { … }
void ServiceWorkerSubresourceLoader::RecordWorkerReadyToFetchHandlerEndTiming(
const net::LoadTimingInfo& load_timing) { … }
void ServiceWorkerSubresourceLoader::
RecordFetchHandlerEndToResponseReceivedTiming(
const net::LoadTimingInfo& load_timing) { … }
void ServiceWorkerSubresourceLoader::RecordResponseReceivedToCompletedTiming(
const net::LoadTimingInfo& load_timing) { … }
void ServiceWorkerSubresourceLoader::
RecordFetchHandlerEndToFallbackNetworkTiming(
const net::LoadTimingInfo& load_timing) { … }
void ServiceWorkerSubresourceLoader::RecordStartToCompletedTiming(
const net::LoadTimingInfo& load_timing) { … }
void ServiceWorkerSubresourceLoader::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) { … }
void ServiceWorkerSubresourceLoader::SetPriority(net::RequestPriority priority,
int intra_priority_value) { … }
void ServiceWorkerSubresourceLoader::PauseReadingBodyFromNet() { … }
void ServiceWorkerSubresourceLoader::ResumeReadingBodyFromNet() { … }
int ServiceWorkerSubresourceLoader::StartBlobReading(
mojo::ScopedDataPipeConsumerHandle* body_pipe) { … }
void ServiceWorkerSubresourceLoader::OnSideDataReadingComplete(
mojo::ScopedDataPipeConsumerHandle data_pipe,
std::optional<mojo_base::BigBuffer> metadata) { … }
void ServiceWorkerSubresourceLoader::OnBodyReadingComplete(int net_error) { … }
bool ServiceWorkerSubresourceLoader::IsMainResourceLoader() { … }
void ServiceWorkerSubresourceLoader::SetCommitResponsibility(
FetchResponseFrom fetch_response_from) { … }
std::optional<ServiceWorkerRouterEvaluator::Result>
ServiceWorkerSubresourceLoader::EvaluateRouterConditions() const { … }
void ServiceWorkerSubresourceLoaderFactory::Create(
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
scoped_refptr<base::SequencedTaskRunner> task_runner) { … }
ServiceWorkerSubresourceLoaderFactory::ServiceWorkerSubresourceLoaderFactory(
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: … { … }
ServiceWorkerSubresourceLoaderFactory::
~ServiceWorkerSubresourceLoaderFactory() = default;
void ServiceWorkerSubresourceLoaderFactory::CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { … }
void ServiceWorkerSubresourceLoaderFactory::Clone(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) { … }
void ServiceWorkerSubresourceLoaderFactory::OnMojoDisconnect() { … }
void ServiceWorkerSubresourceLoader::TransitionToStatus(Status new_status) { … }
void ServiceWorkerSubresourceLoader::DidCacheStorageMatch(
base::TimeTicks event_dispatch_time,
blink::mojom::MatchResultPtr result) { … }
}