
Along with putting functions in the URL namespace into a DOMURL namespace. This is done as LibWeb is in an awkward situation where it needs two URL classes. AK::URL is the general purpose URL class which is all that is needed in 95% of cases. URL in the Web namespace is needed predominantly for interfacing with the javascript interfaces. Because of two URLs in the same namespace, AK::URL has had to be used throughout LibWeb. If we move AK::URL into a URL namespace, this becomes more painful - where ::URL::URL is required to specify the constructor (and something like ::URL::create_with_url_or_path in other places). To fix this problem - rename the class in LibWeb implementing the URL IDL interface to DOMURL, along with moving the other Web URL related classes into this DOMURL folder. One could argue that this name also makes the situation a little more clear in LibWeb for why these two URL classes need be used in the first place.
85 lines
3.7 KiB
C++
85 lines
3.7 KiB
C++
/*
|
||
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
|
||
*
|
||
* SPDX-License-Identifier: BSD-2-Clause
|
||
*/
|
||
|
||
#include <LibWeb/DOMURL/DOMURL.h>
|
||
#include <LibWeb/Fetch/Fetching/Checks.h>
|
||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||
|
||
namespace Web::Fetch::Fetching {
|
||
|
||
// https://fetch.spec.whatwg.org/#concept-cors-check
|
||
ErrorOr<bool> cors_check(Infrastructure::Request const& request, Infrastructure::Response const& response)
|
||
{
|
||
// 1. Let origin be the result of getting `Access-Control-Allow-Origin` from response’s header list.
|
||
auto origin = TRY(response.header_list()->get("Access-Control-Allow-Origin"sv.bytes()));
|
||
|
||
// 2. If origin is null, then return failure.
|
||
// NOTE: Null is not `null`.
|
||
if (!origin.has_value())
|
||
return false;
|
||
|
||
// 3. If request’s credentials mode is not "include" and origin is `*`, then return success.
|
||
if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include && origin->span() == "*"sv.bytes())
|
||
return true;
|
||
|
||
// 4. If the result of byte-serializing a request origin with request is not origin, then return failure.
|
||
if (TRY(request.byte_serialize_origin()) != *origin)
|
||
return false;
|
||
|
||
// 5. If request’s credentials mode is not "include", then return success.
|
||
if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include)
|
||
return true;
|
||
|
||
// 6. Let credentials be the result of getting `Access-Control-Allow-Credentials` from response’s header list.
|
||
auto credentials = TRY(response.header_list()->get("Access-Control-Allow-Credentials"sv.bytes()));
|
||
|
||
// 7. If credentials is `true`, then return success.
|
||
if (credentials.has_value() && credentials->span() == "true"sv.bytes())
|
||
return true;
|
||
|
||
// 8. Return failure.
|
||
return false;
|
||
}
|
||
|
||
// https://fetch.spec.whatwg.org/#concept-tao-check
|
||
ErrorOr<bool> tao_check(Infrastructure::Request const& request, Infrastructure::Response const& response)
|
||
{
|
||
// 1. If request’s timing allow failed flag is set, then return failure.
|
||
if (request.timing_allow_failed())
|
||
return false;
|
||
|
||
// 2. Let values be the result of getting, decoding, and splitting `Timing-Allow-Origin` from response’s header list.
|
||
auto values = TRY(response.header_list()->get_decode_and_split("Timing-Allow-Origin"sv.bytes()));
|
||
|
||
// 3. If values contains "*", then return success.
|
||
if (values.has_value() && values->contains_slow("*"sv))
|
||
return true;
|
||
|
||
// 4. If values contains the result of serializing a request origin with request, then return success.
|
||
if (values.has_value() && values->contains_slow(TRY(request.serialize_origin())))
|
||
return true;
|
||
|
||
// 5. If request’s mode is "navigate" and request’s current URL’s origin is not same origin with request’s origin, then return failure.
|
||
// NOTE: This is necessary for navigations of a nested browsing context. There, request’s origin would be the
|
||
// container document’s origin and the TAO check would return failure. Since navigation timing never
|
||
// validates the results of the TAO check, the nested document would still have access to the full timing
|
||
// information, but the container document would not.
|
||
if (request.mode() == Infrastructure::Request::Mode::Navigate
|
||
&& request.origin().has<HTML::Origin>()
|
||
&& !DOMURL::url_origin(request.current_url()).is_same_origin(request.origin().get<HTML::Origin>())) {
|
||
return false;
|
||
}
|
||
|
||
// 6. If request’s response tainting is "basic", then return success.
|
||
if (request.response_tainting() == Infrastructure::Request::ResponseTainting::Basic)
|
||
return true;
|
||
|
||
// 7. Return failure.
|
||
return false;
|
||
}
|
||
|
||
}
|