#include "services/network/cors/preflight_controller.h"
#include <algorithm>
#include <optional>
#include <vector>
#include "base/functional/bind.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/not_fatal_until.h"
#include "base/strings/string_util.h"
#include "base/unguessable_token.h"
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/network_isolation_key.h"
#include "net/cookies/site_for_cookies.h"
#include "net/http/http_request_headers.h"
#include "net/log/net_log.h"
#include "net/log/net_log_source.h"
#include "net/log/net_log_with_source.h"
#include "services/network/cors/cors_util.h"
#include "services/network/network_service.h"
#include "services/network/private_network_access_checker.h"
#include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/cpp/devtools_observer_util.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/header_util.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/clear_data_filter.mojom.h"
#include "services/network/public/mojom/devtools_observer.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/parsed_headers.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_network_service_observer.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "url/gurl.h"
namespace network::cors {
namespace {
const char kLowerCaseTrue[] = …;
int RetrieveCacheFlags(int load_flags) { … }
std::optional<std::string> GetHeaderString(
const scoped_refptr<net::HttpResponseHeaders>& headers,
const std::string& header_name) { … }
bool ShouldEnforcePrivateNetworkAccessHeader(
PrivateNetworkAccessPreflightBehavior behavior) { … }
std::string CreateAccessControlRequestHeadersHeader(
const net::HttpRequestHeaders& headers,
bool is_revalidating) { … }
std::unique_ptr<ResourceRequest> CreatePreflightRequest(
const ResourceRequest& request,
bool tainted,
const net::NetLogWithSource& net_log_for_actual_request,
const std::optional<base::UnguessableToken>& devtools_request_id,
const PreflightController::PreflightMode& preflight_mode) { … }
base::expected<void, CorsErrorStatus> CheckPreflightAccess(
const GURL& response_url,
const int response_status_code,
const std::optional<std::string>& allow_origin_header,
const std::optional<std::string>& allow_credentials_header,
mojom::CredentialsMode actual_credentials_mode,
const url::Origin& origin) { … }
std::optional<CorsErrorStatus> CheckAllowPrivateNetworkHeader(
const mojom::URLResponseHead& head,
const ResourceRequest& original_request) { … }
std::unique_ptr<PreflightResult> CreatePreflightResult(
const GURL& final_url,
const mojom::URLResponseHead& head,
const ResourceRequest& original_request,
bool tainted,
PrivateNetworkAccessPreflightBehavior private_network_access_behavior,
const mojom::ClientSecurityStatePtr& client_security_state,
base::WeakPtr<mojo::Remote<mojom::DevToolsObserver>> devtools_observer,
const PreflightController::PreflightMode& preflight_mode,
std::optional<CorsErrorStatus>* detected_error_status) { … }
std::optional<CorsErrorStatus> CheckPreflightResult(
const PreflightResult& result,
const ResourceRequest& original_request,
NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
bool acam_preflight_spec_conformant,
const PreflightController::PreflightMode& preflight_mode) { … }
}
const char kPreflightErrorHistogramName[] = …;
const char kPreflightWarningHistogramName[] = …;
class PreflightController::PreflightLoader final { … };
std::unique_ptr<ResourceRequest>
PreflightController::CreatePreflightRequestForTesting(
const ResourceRequest& request,
bool tainted) { … }
std::unique_ptr<PreflightResult>
PreflightController::CreatePreflightResultForTesting(
const GURL& final_url,
const mojom::URLResponseHead& head,
const ResourceRequest& original_request,
bool tainted,
PrivateNetworkAccessPreflightBehavior private_network_access_behavior,
std::optional<CorsErrorStatus>* detected_error_status) { … }
base::expected<void, CorsErrorStatus>
PreflightController::CheckPreflightAccessForTesting(
const GURL& response_url,
const int response_status_code,
const std::optional<std::string>& allow_origin_header,
const std::optional<std::string>& allow_credentials_header,
mojom::CredentialsMode actual_credentials_mode,
const url::Origin& origin) { … }
PreflightController::PreflightController(NetworkService* network_service)
: … { … }
PreflightController::~PreflightController() = default;
void PreflightController::PerformPreflightCheck(
CompletionCallback callback,
const ResourceRequest& request,
WithTrustedHeaderClient with_trusted_header_client,
NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
PrivateNetworkAccessPreflightBehavior private_network_access_behavior,
bool tainted,
const net::NetworkTrafficAnnotationTag& annotation_tag,
mojom::URLLoaderFactory* loader_factory,
const net::IsolationInfo& isolation_info,
mojom::ClientSecurityStatePtr client_security_state,
base::WeakPtr<mojo::Remote<mojom::DevToolsObserver>> devtools_observer,
const net::NetLogWithSource& net_log,
bool acam_preflight_spec_conformant,
mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
url_loader_network_service_observer,
const PreflightMode& preflight_mode) { … }
void PreflightController::ClearCorsPreflightCache(
mojom::ClearDataFilterPtr url_filter) { … }
void PreflightController::RemoveLoader(PreflightLoader* loader) { … }
void PreflightController::AppendToCache(
const url::Origin& origin,
const GURL& url,
const net::NetworkIsolationKey& network_isolation_key,
mojom::IPAddressSpace target_ip_address_space,
std::unique_ptr<PreflightResult> result) { … }
}