Support CORS preflight requests with OutOfBlinkCors (fixes issue #3006)

A CORS preflight request is an "OPTIONS" request sent to a server prior to a
cross-origin XMLHttpRequest or Fetch request. The server's response determines
which HTTP request methods are allowed and supported, and whether credentials
such as Cookies and HTTP Authentication should be sent with requests.

A CORS preflight request will only be sent if certain conditions are met. For
example, it will be sent for requests that have potentially unsafe HTTP
methods [1] or request headers [2]. See the NeedsPreflight function in
services/network/cors/cors_url_loader.cc for full details.

CORS preflight functionality is implemented in the network service and will not
be triggered if the client handles the request instead of allowing it to proceed
over the network. Since the preflight request itself also runs in the network
service it cannot be intercepted by the client.

[1] https://fetch.spec.whatwg.org/#cors-safelisted-method
[2] https://fetch.spec.whatwg.org/#cors-safelisted-request-header
This commit is contained in:
Marshall Greenblatt
2020-09-11 12:52:35 -04:00
parent 88faf1023a
commit cc56720bd2
4 changed files with 319 additions and 45 deletions

View File

@@ -131,6 +131,43 @@ class ResourceContextData : public base::SupportsUserData::Data {
DISALLOW_COPY_AND_ASSIGN(ResourceContextData);
};
// CORS preflight requests are handled in the network process, so we just need
// to continue all of the callbacks and then delete ourself.
class CorsPreflightRequest : public network::mojom::TrustedHeaderClient {
public:
explicit CorsPreflightRequest(
mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver)
: weak_factory_(this) {
header_client_receiver_.Bind(std::move(receiver));
header_client_receiver_.set_disconnect_handler(base::BindOnce(
&CorsPreflightRequest::OnDestroy, weak_factory_.GetWeakPtr()));
}
// mojom::TrustedHeaderClient methods:
void OnBeforeSendHeaders(const net::HttpRequestHeaders& headers,
OnBeforeSendHeadersCallback callback) override {
std::move(callback).Run(net::OK, base::nullopt);
}
void OnHeadersReceived(const std::string& headers,
const net::IPEndPoint& remote_endpoint,
OnHeadersReceivedCallback callback) override {
std::move(callback).Run(net::OK, base::nullopt, GURL());
OnDestroy();
}
private:
void OnDestroy() { delete this; }
mojo::Receiver<network::mojom::TrustedHeaderClient> header_client_receiver_{
this};
base::WeakPtrFactory<CorsPreflightRequest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CorsPreflightRequest);
};
//==============================
// InterceptedRequest
//=============================
@@ -1302,10 +1339,10 @@ void ProxyURLLoaderFactory::OnLoaderCreated(
}
void ProxyURLLoaderFactory::OnLoaderForCorsPreflightCreated(
const ::network::ResourceRequest& request,
mojo::PendingReceiver<network::mojom::TrustedHeaderClient> header_client) {
const network::ResourceRequest& request,
mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) {
CEF_REQUIRE_IOT();
// TODO(cef): Should we do something here?
new CorsPreflightRequest(std::move(receiver));
}
void ProxyURLLoaderFactory::OnTargetFactoryError() {

View File

@@ -168,8 +168,8 @@ class ProxyURLLoaderFactory
mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver)
override;
void OnLoaderForCorsPreflightCreated(
const ::network::ResourceRequest& request,
mojo::PendingReceiver<network::mojom::TrustedHeaderClient> header_client)
const network::ResourceRequest& request,
mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver)
override;
private: