/src/serenity/Userland/Libraries/LibWeb/Fetch/Fetching/Checks.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibWeb/DOMURL/DOMURL.h> |
8 | | #include <LibWeb/Fetch/Fetching/Checks.h> |
9 | | #include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h> |
10 | | #include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h> |
11 | | |
12 | | namespace Web::Fetch::Fetching { |
13 | | |
14 | | // https://fetch.spec.whatwg.org/#concept-cors-check |
15 | | bool cors_check(Infrastructure::Request const& request, Infrastructure::Response const& response) |
16 | 0 | { |
17 | | // 1. Let origin be the result of getting `Access-Control-Allow-Origin` from response’s header list. |
18 | 0 | auto origin = response.header_list()->get("Access-Control-Allow-Origin"sv.bytes()); |
19 | | |
20 | | // 2. If origin is null, then return failure. |
21 | | // NOTE: Null is not `null`. |
22 | 0 | if (!origin.has_value()) |
23 | 0 | return false; |
24 | | |
25 | | // 3. If request’s credentials mode is not "include" and origin is `*`, then return success. |
26 | 0 | if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include && origin->span() == "*"sv.bytes()) |
27 | 0 | return true; |
28 | | |
29 | | // 4. If the result of byte-serializing a request origin with request is not origin, then return failure. |
30 | 0 | if (request.byte_serialize_origin() != *origin) |
31 | 0 | return false; |
32 | | |
33 | | // 5. If request’s credentials mode is not "include", then return success. |
34 | 0 | if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include) |
35 | 0 | return true; |
36 | | |
37 | | // 6. Let credentials be the result of getting `Access-Control-Allow-Credentials` from response’s header list. |
38 | 0 | auto credentials = response.header_list()->get("Access-Control-Allow-Credentials"sv.bytes()); |
39 | | |
40 | | // 7. If credentials is `true`, then return success. |
41 | 0 | if (credentials.has_value() && credentials->span() == "true"sv.bytes()) |
42 | 0 | return true; |
43 | | |
44 | | // 8. Return failure. |
45 | 0 | return false; |
46 | 0 | } |
47 | | |
48 | | // https://fetch.spec.whatwg.org/#concept-tao-check |
49 | | bool tao_check(Infrastructure::Request const& request, Infrastructure::Response const& response) |
50 | 0 | { |
51 | | // 1. If request’s timing allow failed flag is set, then return failure. |
52 | 0 | if (request.timing_allow_failed()) |
53 | 0 | return false; |
54 | | |
55 | | // 2. Let values be the result of getting, decoding, and splitting `Timing-Allow-Origin` from response’s header list. |
56 | 0 | auto values = response.header_list()->get_decode_and_split("Timing-Allow-Origin"sv.bytes()); |
57 | | |
58 | | // 3. If values contains "*", then return success. |
59 | 0 | if (values.has_value() && values->contains_slow("*"sv)) |
60 | 0 | return true; |
61 | | |
62 | | // 4. If values contains the result of serializing a request origin with request, then return success. |
63 | 0 | if (values.has_value() && values->contains_slow(request.serialize_origin())) |
64 | 0 | return true; |
65 | | |
66 | | // 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. |
67 | | // NOTE: This is necessary for navigations of a nested browsing context. There, request’s origin would be the |
68 | | // container document’s origin and the TAO check would return failure. Since navigation timing never |
69 | | // validates the results of the TAO check, the nested document would still have access to the full timing |
70 | | // information, but the container document would not. |
71 | 0 | if (request.mode() == Infrastructure::Request::Mode::Navigate |
72 | 0 | && request.origin().has<URL::Origin>() |
73 | 0 | && !request.current_url().origin().is_same_origin(request.origin().get<URL::Origin>())) { |
74 | 0 | return false; |
75 | 0 | } |
76 | | |
77 | | // 6. If request’s response tainting is "basic", then return success. |
78 | 0 | if (request.response_tainting() == Infrastructure::Request::ResponseTainting::Basic) |
79 | 0 | return true; |
80 | | |
81 | | // 7. Return failure. |
82 | 0 | return false; |
83 | 0 | } |
84 | | |
85 | | } |