chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc

/*
    Copyright (C) 1998 Lars Knoll ([email protected])
    Copyright (C) 2001 Dirk Mueller ([email protected])
    Copyright (C) 2002 Waldo Bastian ([email protected])
    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
    rights reserved.
    Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

    This class provides all functionality needed for loading images, style
    sheets and html pages from the web. It has a memory cache for these objects.
*/

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#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 =;

// Timeout for link preloads to be used after window.onload
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() {}

// Calls to PriorityObservers() that don't need to explicitly interact with the
// map should be guarded with a call to PriorityObserverMapCreated(), to avoid
// unnecessarily creating a PriorityObserverMap.
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) {}

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
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) {}
}  // namespace

// Used to ensure a ResourceRequest is correctly configured. Specifically
// PrepareRequestForCacheAccess() is called first. If the resource can not be
// served from the cache, UpgradeForLoaderIfNecessary() is called to complete
// the necessary steps before loading.
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) {}

// This method simply takes in information about a ResourceRequest, and returns
// a priority. It will not be called for ResourceRequests that already have a
// pre-set priority (e.g., requests coming from a Service Worker) except for
// images, which may need to be reprioritized.
// platform/loader/fetch/README.md contains more details on prioritization
// as well as links to all of the relevant places in the code where priority
// is determined. If the priority logic is updated here, be sure to update
// the other code as needed.
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) {}

// Boost the priority for the first N not-small images from the preload scanner
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) {}

}  // namespace

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 {}

// static
const ResourceFetcher::ResourceFetcherSet&
ResourceFetcher::MainThreadFetchers() {}

// The followings should match with `ResourceType` in
// `third_party/blink/renderer/platform/loader/fetch/resource.h`
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() {}

}  // namespace blink