#ifndef SERVICES_NETWORK_CORS_PREFLIGHT_CONTROLLER_H_
#define SERVICES_NETWORK_CORS_PREFLIGHT_CONTROLLER_H_
#include <memory>
#include <optional>
#include <string>
#include "base/component_export.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/types/expected.h"
#include "base/types/strong_alias.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/cors/preflight_cache.h"
#include "services/network/cors/preflight_result.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/clear_data_filter.mojom-forward.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "url/gurl.h"
namespace net {
class NetLogWithSource;
}
namespace network {
class NetworkService;
namespace cors {
class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
public:
using CompletionCallback =
base::OnceCallback<void(int net_error,
std::optional<CorsErrorStatus> cors_error_status,
bool has_authorization_covered_by_wildcard)>;
using WithTrustedHeaderClient =
base::StrongAlias<class WithTrustedHeaderClientTag, bool>;
static std::unique_ptr<ResourceRequest> CreatePreflightRequestForTesting(
const ResourceRequest& request,
bool tainted = false);
static std::unique_ptr<PreflightResult> CreatePreflightResultForTesting(
const GURL& final_url,
const mojom::URLResponseHead& head,
const ResourceRequest& original_request,
bool tainted,
std::optional<CorsErrorStatus>* detected_error_status);
static base::expected<void, CorsErrorStatus> 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);
explicit PreflightController(NetworkService* network_service);
PreflightController(const PreflightController&) = delete;
PreflightController& operator=(const PreflightController&) = delete;
~PreflightController();
void PerformPreflightCheck(
CompletionCallback callback,
int32_t request_id,
const ResourceRequest& resource_request,
WithTrustedHeaderClient with_trusted_header_client,
NonWildcardRequestHeadersSupport non_wildcard_request_headers_support,
bool tainted,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
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);
void ClearCorsPreflightCache(mojom::ClearDataFilterPtr url_filter);
PreflightCache& GetPreflightCacheForTesting() { return cache_; }
private:
class PreflightLoader;
void RemoveLoader(PreflightLoader* loader);
void AppendToCache(const url::Origin& origin,
const GURL& url,
const net::NetworkIsolationKey& network_isolation_key,
std::unique_ptr<PreflightResult> result);
NetworkService* network_service() { return network_service_; }
PreflightCache cache_;
std::set<std::unique_ptr<PreflightLoader>, base::UniquePtrComparator>
loaders_;
const raw_ptr<NetworkService> network_service_;
};
}
}
#endif