#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include <algorithm>
#include <limits>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include "base/auto_reset.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "services/network/public/cpp/request_mode.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
#include "third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request_utils.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h"
#include "third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h"
#include "third_party/blink/renderer/platform/loader/fetch/subresource_web_bundle.h"
#include "third_party/blink/renderer/platform/loader/fetch/subresource_web_bundle_list.h"
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
#include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
#include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
#include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/known_ports.h"
#include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
#include "third_party/blink/renderer/platform/weborigin/reporting_disposition.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
constexpr uint32_t ResourceFetcher::kKeepaliveInflightBytesQuota;
namespace {
constexpr base::TimeDelta kKeepaliveLoadersTimeout = …;
static constexpr base::TimeDelta kUnusedPreloadTimeout = …;
static constexpr char kCrossDocumentCachedResource[] = …;
static constexpr char kEarlyHintsInitiatorType[] = …;
#define RESOURCE_HISTOGRAM_PREFIX …
#define RESOURCE_TYPE_NAME(name) …
const std::string ResourceTypeName(ResourceType type) { … }
ResourceLoadPriority TypeToPriority(ResourceType type) { … }
bool ShouldResourceBeAddedToMemoryCache(const FetchParameters& params,
Resource* resource) { … }
bool ShouldResourceBeKeptStrongReferenceByType(
Resource* resource,
const SecurityOrigin* settings_object_origin) { … }
bool ShouldResourceBeKeptStrongReference(
Resource* resource,
const SecurityOrigin* settings_object_origin) { … }
base::TimeDelta GetResourceStrongReferenceTimeout(Resource* resource) { … }
static ResourceFetcher::ResourceFetcherSet& MainThreadFetchersSet() { … }
static bool& PriorityObserverMapCreated() { … }
PriorityObserverMap;
static ThreadSpecific<PriorityObserverMap>& PriorityObservers() { … }
std::unique_ptr<TracedValue> CreateTracedValueWithPriority(
blink::ResourceLoadPriority priority) { … }
std::unique_ptr<TracedValue> CreateTracedValueForUnusedPreload(
const KURL& url,
Resource::MatchStatus status,
String request_id) { … }
std::unique_ptr<TracedValue> CreateTracedValueForUnusedEarlyHintsPreload(
const KURL& url) { … }
enum class BoostImagePriorityReason { … };
void MaybeRecordBoostImagePriorityReason(const bool is_first_n,
const bool is_potentially_lcp_element,
const bool is_small_image) { … }
constexpr char kLCPPDeferUnusedPreloadHistogramPrefix[] = …;
std::string LinkPreloadStrForHistogram(bool link_preload) { … }
void RecordDeferUnusedPreloadHistograms(const Resource* resource) { … }
}
class ResourceFetcher::ResourcePrepareHelper final
: public ResourceRequestContext { … };
ResourceFetcherInit::ResourceFetcherInit(
DetachableResourceFetcherProperties& properties,
FetchContext* context,
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
ResourceFetcher::LoaderFactory* loader_factory,
ContextLifecycleNotifier* context_lifecycle_notifier,
BackForwardCacheLoaderHelper* back_forward_cache_loader_helper)
: … { … }
bool ResourceFetcher::IsSimplifyLoadingTransparentPlaceholderImageEnabled() { … }
mojom::blink::RequestContextType ResourceFetcher::DetermineRequestContext(
ResourceType type,
IsImageSet is_image_set) { … }
network::mojom::RequestDestination ResourceFetcher::DetermineRequestDestination(
ResourceType type) { … }
void ResourceFetcher::AddPriorityObserverForTesting(
const KURL& resource_url,
base::OnceCallback<void(int)> callback,
bool new_load_only) { … }
ResourceLoadPriority ResourceFetcher::ComputeLoadPriority(
ResourceType type,
const ResourceRequestHead& resource_request,
ResourcePriority::VisibilityStatus visibility,
FetchParameters::DeferOption defer_option,
FetchParameters::SpeculativePreloadType speculative_preload_type,
RenderBlockingBehavior render_blocking_behavior,
mojom::blink::ScriptType script_type,
bool is_link_preload,
const std::optional<float> resource_width,
const std::optional<float> resource_height,
bool is_potentially_lcp_element,
bool is_potentially_lcp_influencer) { … }
ResourceLoadPriority ResourceFetcher::AdjustImagePriority(
const ResourceLoadPriority priority_so_far,
const ResourceType type,
const ResourceRequestHead& resource_request,
const FetchParameters::SpeculativePreloadType speculative_preload_type,
const bool is_link_preload,
const std::optional<float> resource_width,
const std::optional<float> resource_height,
const bool is_potentially_lcp_element) { … }
ResourceFetcher::ResourceFetcher(const ResourceFetcherInit& init)
: … { … }
ResourceFetcher::~ResourceFetcher() { … }
bool ResourceFetcher::IsDetached() const { … }
Resource* ResourceFetcher::CachedResource(const KURL& resource_url) const { … }
bool ResourceFetcher::ResourceHasBeenEmulatedLoadStartedForInspector(
const KURL& resource_url) const { … }
const HeapHashSet<Member<Resource>>
ResourceFetcher::MoveResourceStrongReferences() { … }
mojom::ControllerServiceWorkerMode
ResourceFetcher::IsControlledByServiceWorker() const { … }
ResourceFetcher::DeferPolicy ResourceFetcher::GetDeferPolicy(
ResourceType type,
const FetchParameters& params) const { … }
bool ResourceFetcher::ResourceAlreadyLoadStarted(Resource* resource,
RevalidationPolicy policy) { … }
bool ResourceFetcher::ResourceNeedsLoad(Resource* resource,
RevalidationPolicy policy,
DeferPolicy defer_policy) const { … }
void ResourceFetcher::DidLoadResourceFromMemoryCache(
Resource* resource,
const ResourceRequest& request,
bool is_static_data,
RenderBlockingBehavior render_blocking_behavior) { … }
Resource* ResourceFetcher::CreateResourceForStaticData(
const FetchParameters& params,
const ResourceFactory& factory) { … }
Resource* ResourceFetcher::ResourceForBlockedRequest(
const FetchParameters& params,
const ResourceFactory& factory,
ResourceRequestBlockedReason blocked_reason,
ResourceClient* client) { … }
void ResourceFetcher::MakePreloadedResourceBlockOnloadIfNeeded(
Resource* resource,
const FetchParameters& params) { … }
ResourceFetcher::RevalidationPolicyForMetrics
ResourceFetcher::MapToPolicyForMetrics(RevalidationPolicy policy,
Resource* resource,
DeferPolicy defer_policy) { … }
void ResourceFetcher::UpdateMemoryCacheStats(
Resource* resource,
RevalidationPolicyForMetrics policy,
const FetchParameters& params,
const ResourceFactory& factory,
bool is_static_data,
bool same_top_frame_site_resource_cached) const { … }
bool ResourceFetcher::ContainsAsPreload(Resource* resource) const { … }
void ResourceFetcher::RemovePreload(Resource* resource) { … }
std::optional<ResourceRequestBlockedReason>
ResourceFetcher::UpdateRequestForTransparentPlaceholderImage(
FetchParameters& params) { … }
KURL ResourceFetcher::PrepareRequestForWebBundle(
ResourceRequest& resource_request) const { … }
SubresourceWebBundleList*
ResourceFetcher::GetOrCreateSubresourceWebBundleList() { … }
ukm::MojoUkmRecorder* ResourceFetcher::UkmRecorder() { … }
Resource* ResourceFetcher::RequestResource(FetchParameters& params,
const ResourceFactory& factory,
ResourceClient* client) { … }
void ResourceFetcher::RemoveResourceStrongReference(Resource* resource) { … }
bool ResourceFetcher::HasStrongReferenceForTesting(Resource* resource) { … }
void ResourceFetcher::ResourceTimingReportTimerFired(TimerBase* timer) { … }
void ResourceFetcher::InitializeRevalidation(
ResourceRequest& revalidating_request,
Resource* resource) { … }
namespace {
bool UseRenderBlockingTaskPriority(
const mojom::blink::RequestContextType request_context,
const RenderBlockingBehavior render_blocking_behavior) { … }
}
std::unique_ptr<URLLoader> ResourceFetcher::CreateURLLoader(
const network::ResourceRequest& network_request,
const ResourceLoaderOptions& options,
const mojom::blink::RequestContextType request_context,
const RenderBlockingBehavior render_blocking_behavior,
const std::optional<base::UnguessableToken>&
service_worker_race_network_request_token,
bool is_from_origin_dirty_style_sheet) { … }
CodeCacheHost* ResourceFetcher::GetCodeCacheHost() { … }
void ResourceFetcher::AddToMemoryCacheIfNeeded(const FetchParameters& params,
Resource* resource) { … }
Resource* ResourceFetcher::CreateResourceForLoading(
const FetchParameters& params,
const ResourceFactory& factory) { … }
void ResourceFetcher::StorePerformanceTimingInitiatorInformation(
Resource* resource,
RenderBlockingBehavior render_blocking_behavior) { … }
void ResourceFetcher::RecordResourceTimingOnRedirect(
Resource* resource,
const ResourceResponse& redirect_response,
const KURL& new_url) { … }
static bool IsDownloadOrStreamRequest(const ResourceRequest& request) { … }
Resource* ResourceFetcher::MatchPreload(const FetchParameters& params,
ResourceType type) { … }
void ResourceFetcher::PrintPreloadMismatch(Resource* resource,
Resource::MatchStatus status) { … }
void ResourceFetcher::InsertAsPreloadIfNecessary(Resource* resource,
const FetchParameters& params,
ResourceType type) { … }
bool ResourceFetcher::IsImageResourceDisallowedToBeReused(
const Resource& existing_resource) const { … }
ResourceFetcher::RevalidationPolicy
ResourceFetcher::DetermineRevalidationPolicy(
ResourceType type,
const FetchParameters& fetch_params,
const Resource& existing_resource,
bool is_static_data) const { … }
const char* ResourceFetcher::GetNameFor(RevalidationPolicy policy) { … }
std::pair<ResourceFetcher::RevalidationPolicy, const char*>
ResourceFetcher::DetermineRevalidationPolicyInternal(
ResourceType type,
const FetchParameters& fetch_params,
const Resource& existing_resource,
bool is_static_data) const { … }
void ResourceFetcher::SetAutoLoadImages(bool enable) { … }
bool ResourceFetcher::ShouldDeferImageLoad(const KURL& url) const { … }
void ResourceFetcher::ReloadImagesIfNotDeferred() { … }
FetchContext& ResourceFetcher::Context() const { … }
void ResourceFetcher::ClearContext() { … }
int ResourceFetcher::BlockingRequestCount() const { … }
int ResourceFetcher::NonblockingRequestCount() const { … }
int ResourceFetcher::ActiveRequestCount() const { … }
void ResourceFetcher::EnableIsPreloadedForTest() { … }
bool ResourceFetcher::IsPreloadedForTest(const KURL& url) const { … }
void ResourceFetcher::ClearPreloads(ClearPreloadsPolicy policy) { … }
void ResourceFetcher::ScheduleWarnUnusedPreloads(
base::OnceCallback<void(Vector<KURL> unused_preloads)> callback) { … }
void ResourceFetcher::WarnUnusedPreloads(
base::OnceCallback<void(Vector<KURL> unused_preloads)> callback) { … }
void ResourceFetcher::HandleLoaderFinish(Resource* resource,
base::TimeTicks response_end,
LoaderFinishType type,
uint32_t inflight_keepalive_bytes) { … }
void ResourceFetcher::HandleLoaderError(Resource* resource,
base::TimeTicks finish_time,
const ResourceError& error,
uint32_t inflight_keepalive_bytes) { … }
void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) { … }
bool ResourceFetcher::StartLoad(Resource* resource,
bool is_potentially_unused_preload) { … }
bool ResourceFetcher::StartLoad(
Resource* resource,
ResourceRequestBody request_body,
ImageLoadBlockingPolicy policy,
RenderBlockingBehavior render_blocking_behavior) { … }
void ResourceFetcher::ScheduleLoadingPotentiallyUnusedPreload(
Resource* resource) { … }
void ResourceFetcher::StartLoadAndFinishIfFailed(
Resource* resource,
bool is_potentially_unused_preload) { … }
void ResourceFetcher::ScheduleStartLoadAndFinishIfFailed(
Resource* resource,
bool is_potentially_unused_preload) { … }
void ResourceFetcher::RemoveResourceLoader(ResourceLoader* loader) { … }
void ResourceFetcher::StopFetching() { … }
void ResourceFetcher::SetDefersLoading(LoaderFreezeMode mode) { … }
void ResourceFetcher::UpdateAllImageResourcePriorities() { … }
String ResourceFetcher::GetCacheIdentifier(const KURL& url) const { … }
std::optional<base::UnguessableToken>
ResourceFetcher::GetSubresourceBundleToken(const KURL& url) const { … }
std::optional<KURL> ResourceFetcher::GetSubresourceBundleSourceUrl(
const KURL& url) const { … }
void ResourceFetcher::EmulateLoadStartedForInspector(
Resource* resource,
mojom::blink::RequestContextType request_context,
network::mojom::RequestDestination request_destination,
const AtomicString& initiator_name) { … }
void ResourceFetcher::PrepareForLeakDetection() { … }
void ResourceFetcher::StopFetchingInternal(StopFetchingTarget target) { … }
void ResourceFetcher::StopFetchingIncludingKeepaliveLoaders() { … }
void ResourceFetcher::ScheduleStaleRevalidate(Resource* stale_resource) { … }
void ResourceFetcher::RevalidateStaleResource(Resource* stale_resource) { … }
mojom::blink::BlobRegistry* ResourceFetcher::GetBlobRegistry() { … }
FrameOrWorkerScheduler* ResourceFetcher::GetFrameOrWorkerScheduler() { … }
void ResourceFetcher::PopulateAndAddResourceTimingInfo(
Resource* resource,
const PendingResourceTimingInfo& pending_info,
base::TimeTicks response_end) { … }
SubresourceWebBundle* ResourceFetcher::GetMatchingBundle(
const KURL& url) const { … }
void ResourceFetcher::CancelWebBundleSubresourceLoadersFor(
const base::UnguessableToken& web_bundle_token) { … }
void ResourceFetcher::MaybeSaveResourceToStrongReference(Resource* resource) { … }
void ResourceFetcher::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel level) { … }
void ResourceFetcher::MaybeRecordLCPPSubresourceMetrics(
const KURL& document_url) { … }
void ResourceFetcher::MarkEarlyHintConsumedIfNeeded(
uint64_t inspector_id,
Resource* resource,
const ResourceResponse& response) { … }
bool ResourceFetcher::IsPotentiallyUnusedPreload(
ResourceType type,
const FetchParameters& params) const { … }
void ResourceFetcher::Trace(Visitor* visitor) const { … }
const ResourceFetcher::ResourceFetcherSet&
ResourceFetcher::MainThreadFetchers() { … }
void ResourceFetcher::RecordResourceHistogram(
std::string_view prefix,
ResourceType type,
RevalidationPolicyForMetrics policy) const { … }
void ResourceFetcher::UpdateServiceWorkerSubresourceMetrics(
ResourceType resource_type,
bool handled_by_serviceworker,
const blink::ServiceWorkerRouterInfo* router_info) { … }
ResourceFetcher::ResourcePrepareHelper::ResourcePrepareHelper(
ResourceFetcher& fetcher,
FetchParameters& params,
const ResourceFactory& factory)
: … { … }
std::optional<ResourceRequestBlockedReason>
ResourceFetcher::ResourcePrepareHelper::PrepareRequestForCacheAccess(
WebScopedVirtualTimePauser& pauser) { … }
void ResourceFetcher::ResourcePrepareHelper::UpgradeForLoaderIfNecessary(
WebScopedVirtualTimePauser& pauser) { … }
ResourceLoadPriority
ResourceFetcher::ResourcePrepareHelper::ComputeLoadPriority(
const FetchParameters& params) { … }
void ResourceFetcher::ResourcePrepareHelper::RecordTrace() { … }
}