chromium/content/browser/loader/navigation_url_loader_impl.cc

// Copyright 2017 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/navigation_url_loader_impl.h"

#include <map>
#include <memory>
#include <optional>
#include <string_view>
#include <utility>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/download/public/common/download_stats.h"
#include "content/browser/about_url_loader_factory.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/client_hints/client_hints.h"
#include "content/browser/data_url_loader_factory.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/file_system/file_system_url_loader_factory.h"
#include "content/browser/loader/file_url_loader_factory.h"
#include "content/browser/loader/navigation_early_hints_manager.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/response_head_update_params.h"
#include "content/browser/loader/subresource_proxying_url_loader_service.h"
#include "content/browser/loader/url_loader_factory_utils.h"
#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/preloading/prefetch/prefetch_url_loader_interceptor.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigation_request_info.h"
#include "content/browser/service_worker/service_worker_client.h"
#include "content/browser/service_worker/service_worker_main_resource_handle.h"
#include "content/browser/service_worker/service_worker_main_resource_loader_interceptor.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_request_handler.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_hints.h"
#include "content/public/browser/client_hints_controller_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_utils.h"
#include "content/public/browser/frame_accept_header.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/network_service_util.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/url_loader_request_interceptor.h"
#include "content/public/browser/url_loader_throttles.h"
#include "content/public/browser/web_ui_url_loader_factory.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/referrer.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/common/webplugininfo.h"
#include "media/media_buildflags.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/cert/sct_status_flags.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/http/http_content_disposition.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_status_code.h"
#include "net/ssl/ssl_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_util.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/parsed_headers.h"
#include "services/network/public/cpp/request_destination.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/cpp/url_loader_factory_builder.h"
#include "services/network/public/cpp/url_util.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/loader/mime_sniffing_throttle.h"
#include "third_party/blink/public/common/loader/record_load_histograms.h"
#include "third_party/blink/public/common/loader/throttling_url_loader.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_router_rule.mojom.h"
#include "url/origin.h"

#if BUILDFLAG(IS_ANDROID)
#include "content/browser/android/content_url_loader_factory.h"
#endif

#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/public/browser/plugin_service.h"
#endif

namespace content {

namespace {

BASE_FEATURE();

class NavigationLoaderInterceptorBrowserContainer
    : public NavigationLoaderInterceptor {};

class NavigationTimingThrottle : public blink::URLLoaderThrottle {};

const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =;

std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
    const NavigationRequestInfo& request_info,
    FrameTreeNode* frame_tree_node,
    mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer,
    mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
        trust_token_observer,
    mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
        shared_dictionary_observer,
    mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
        url_loader_network_observer,
    mojo::PendingRemote<network::mojom::DevToolsObserver> devtools_observer,
    mojo::PendingRemote<network::mojom::AcceptCHFrameObserver>
        accept_ch_frame_observer) {}

// Called for requests that we don't have a URLLoaderFactory for.
void UnknownSchemeCallback(
    bool handled_externally,
    const network::ResourceRequest& /* resource_request */,
    mojo::PendingReceiver<network::mojom::URLLoader> receiver,
    mojo::PendingRemote<network::mojom::URLLoaderClient> client) {}

void LogQueueTimeHistogram(std::string_view name,
                           bool is_outermost_main_frame) {}

void LogAcceptCHFrameStatus(AcceptCHFrameRestart status) {}

bool IsSameOriginRedirect(const std::vector<GURL>& url_chain) {}

// TODO(https://crbug.com/346000235) there is a known failure with extensions
// See test: ExtensionWebRequestApiTestWithContextType.HSTSUpgradeAfterRedirect
// We still want to check this in debug mode to avoid further regressions, but
// because it was affecting to many developers with DCHECK_IS_ON() this was
// downgraded as a DEBUG only check.
// After getting the approval to rewrite the CSP parser in Rust, we should be
// able to remove "pre-parsing" of CSP in the network process and directly
// parse them later in the browser process. This will make this check to become
// unnecessary.
#ifndef NDEBUG
void CheckParsedHeadersEquals(const network::mojom::ParsedHeadersPtr& lhs,
                              const network::mojom::ParsedHeadersPtr& rhs,
                              const GURL& url) {}
#endif  // NDEBUG

}  // namespace

// TODO(kinuko): Fix the method ordering and move these methods after the ctor.
NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {}

void NavigationURLLoaderImpl::Start() {}

void NavigationURLLoaderImpl::CreateInterceptors() {}

void NavigationURLLoaderImpl::Restart() {}

void NavigationURLLoaderImpl::MaybeStartLoader(
    size_t next_interceptor_index,
    std::optional<NavigationLoaderInterceptor::Result> interceptor_result) {}

void NavigationURLLoaderImpl::StartInterceptedRequest(
    scoped_refptr<network::SharedURLLoaderFactory> single_request_factory) {}

void NavigationURLLoaderImpl::StartNonInterceptedRequest(
    ResponseHeadUpdateParams head_update_params) {}
void NavigationURLLoaderImpl::FallbackToNonInterceptedRequest(
    ResponseHeadUpdateParams head_update_params) {}

scoped_refptr<network::SharedURLLoaderFactory>
NavigationURLLoaderImpl::GetOrCreateNonNetworkLoaderFactory() {}

// static
std::pair</*is_cacheable=*/bool, scoped_refptr<network::SharedURLLoaderFactory>>
NavigationURLLoaderImpl::CreateNonNetworkLoaderFactory(
    BrowserContext* browser_context,
    StoragePartitionImpl* storage_partition,
    FrameTreeNode* frame_tree_node,
    const ukm::SourceIdObj& ukm_id,
    NavigationUIData* navigation_ui_data,
    const NavigationRequestInfo& request_info,
    base::RepeatingCallback<WebContents*()> web_contents_getter,
    const network::ResourceRequest& resource_request) {}

void NavigationURLLoaderImpl::CreateThrottlingLoaderAndStart(
    scoped_refptr<network::SharedURLLoaderFactory> factory,
    std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
        additional_throttles) {}

void NavigationURLLoaderImpl::OnReceiveEarlyHints(
    network::mojom::EarlyHintsPtr early_hints) {}

void NavigationURLLoaderImpl::OnReceiveResponse(
    network::mojom::URLResponseHeadPtr head,
    mojo::ScopedDataPipeConsumerHandle response_body,
    std::optional<mojo_base::BigBuffer> cached_metadata) {}

#if BUILDFLAG(ENABLE_PLUGINS)
void NavigationURLLoaderImpl::CheckPluginAndContinueOnReceiveResponse(
    network::mojom::URLResponseHeadPtr head,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    bool is_download_if_not_handled_by_plugin,
    const std::vector<WebPluginInfo>& plugins) {}
#endif

void NavigationURLLoaderImpl::CallOnReceivedResponse(
    network::mojom::URLResponseHeadPtr head,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    bool is_download) {}

void NavigationURLLoaderImpl::OnReceiveRedirect(
    const net::RedirectInfo& redirect_info,
    network::mojom::URLResponseHeadPtr head) {}

void NavigationURLLoaderImpl::OnUploadProgress(
    int64_t current_position,
    int64_t total_size,
    OnUploadProgressCallback callback) {}

void NavigationURLLoaderImpl::OnTransferSizeUpdated(
    int32_t transfer_size_diff) {}

void NavigationURLLoaderImpl::OnComplete(
    const network::URLLoaderCompletionStatus& status) {}

void NavigationURLLoaderImpl::OnAcceptCHFrameReceived(
    const url::Origin& origin,
    const std::vector<network::mojom::WebClientHintsType>& accept_ch_frame,
    OnAcceptCHFrameReceivedCallback callback) {}

void NavigationURLLoaderImpl::Clone(
    mojo::PendingReceiver<network::mojom::AcceptCHFrameObserver> listener) {}

// Returns true if an interceptor wants to handle the response, i.e. return a
// different response, e.g. service workers.
bool NavigationURLLoaderImpl::MaybeCreateLoaderForResponse(
    const network::URLLoaderCompletionStatus& status,
    network::mojom::URLResponseHeadPtr* response) {}

std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
NavigationURLLoaderImpl::CreateURLLoaderThrottles() {}

std::unique_ptr<SignedExchangeRequestHandler>
NavigationURLLoaderImpl::CreateSignedExchangeRequestHandler(
    const NavigationRequestInfo& request_info,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {}

void NavigationURLLoaderImpl::ParseHeaders(
    const GURL& url,
    network::mojom::URLResponseHead* head,
    base::OnceClosure continuation) {}

// TODO(crbug.com/40552600): pass `navigation_ui_data` along with the
// request so that it could be modified.
NavigationURLLoaderImpl::NavigationURLLoaderImpl(
    BrowserContext* browser_context,
    StoragePartition* storage_partition,
    std::unique_ptr<NavigationRequestInfo> request_info,
    std::unique_ptr<NavigationUIData> navigation_ui_data,
    ServiceWorkerMainResourceHandle* service_worker_handle,
    scoped_refptr<PrefetchedSignedExchangeCache>
        prefetched_signed_exchange_cache,
    NavigationURLLoaderDelegate* delegate,
    mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer,
    mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
        trust_token_observer,
    mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
        shared_dictionary_observer,
    mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
        url_loader_network_observer,
    mojo::PendingRemote<network::mojom::DevToolsObserver> devtools_observer,
    std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
        initial_interceptors)
    :{}

// static
mojo::PendingRemote<network::mojom::URLLoaderFactory>
NavigationURLLoaderImpl::CreateTerminalNonNetworkLoaderFactory(
    BrowserContext* browser_context,
    StoragePartitionImpl* storage_partition,
    FrameTreeNode* frame_tree_node,
    const GURL& url) {}

scoped_refptr<network::SharedURLLoaderFactory>
NavigationURLLoaderImpl::CreateNetworkLoaderFactory(
    BrowserContext* browser_context,
    StoragePartitionImpl* storage_partition,
    FrameTreeNode* frame_tree_node,
    const ukm::SourceIdObj& ukm_id,
    bool* bypass_redirect_checks) {}

void NavigationURLLoaderImpl::FollowRedirect(
    const std::vector<std::string>& removed_headers,
    const net::HttpRequestHeaders& modified_headers,
    const net::HttpRequestHeaders& modified_cors_exempt_headers) {}

bool NavigationURLLoaderImpl::SetNavigationTimeout(base::TimeDelta timeout) {}

void NavigationURLLoaderImpl::CancelNavigationTimeout() {}

void NavigationURLLoaderImpl::NotifyResponseStarted(
    network::mojom::URLResponseHeadPtr response_head,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    mojo::ScopedDataPipeConsumerHandle response_body,
    const GlobalRequestID& global_request_id,
    bool is_download) {}

void NavigationURLLoaderImpl::NotifyRequestRedirected(
    net::RedirectInfo redirect_info,
    network::mojom::URLResponseHeadPtr response_head) {}

void NavigationURLLoaderImpl::NotifyRequestFailed(
    const network::URLLoaderCompletionStatus& status) {}

// static
mojo::PendingRemote<network::mojom::URLLoaderFactory>
NavigationURLLoaderImpl::CreateURLLoaderFactoryWithHeaderClient(
    mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>
        header_client,
    network::URLLoaderFactoryBuilder factory_builder,
    StoragePartitionImpl* partition) {}

void NavigationURLLoaderImpl::RecordReceivedResponseUkmForOutermostMainFrame() {}

void NavigationURLLoaderImpl::RecordServiceWorkerRouterEvaluationResults(
    network::mojom::ServiceWorkerRouterInfo* router_info) {}

}  // namespace content