diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2023-04-20 16:52:01 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-04-21 20:44:47 +0100 |
commit | 22e0603bf7d1f958885832510c8a4c128d905ea8 (patch) | |
tree | aeb5764ffe6ac21b663145de8d38cc9e122b29fd /Userland/Libraries/LibWeb/Fetch | |
parent | 6d93e03211795d8285d7bbd3a8e1b6fe458262e8 (diff) | |
download | serenity-22e0603bf7d1f958885832510c8a4c128d905ea8.zip |
LibWeb: Implement integrity-metadata part of fetch algorithm
Specifically, this makes `<link>` elements with an `integrity` attribute
actually work. Previously, we would load their resource, and then drop
it on the floor without actually using it.
The Subresource Integrity code is in `LibWeb/SRI`, since SRI is the name
of the recommendation spec: https://www.w3.org/TR/SRI/
However, the Fetch spec links to the editor's draft, which varies
significantly from the recommendation, and so that is what the code is
based on and what the spec comments link to:
https://w3c.github.io/webappsec-subresource-integrity/
Fixes #18408
Diffstat (limited to 'Userland/Libraries/LibWeb/Fetch')
-rw-r--r-- | Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp index 5e5051d3d4..a4be68d3a3 100644 --- a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org> * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org> + * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -38,6 +39,7 @@ #include <LibWeb/Loader/ResourceLoader.h> #include <LibWeb/Platform/EventLoopPlugin.h> #include <LibWeb/ReferrerPolicy/AbstractOperations.h> +#include <LibWeb/SRI/SRI.h> #include <LibWeb/URL/URL.h> #include <LibWeb/WebIDL/DOMException.h> @@ -479,22 +481,39 @@ WebIDL::ExceptionOr<Optional<JS::NonnullGCPtr<PendingResponse>>> main_fetch(JS:: if (!request->integrity_metadata().is_empty()) { // 1. Let processBodyError be this step: run fetch response handover given fetchParams and a network // error. - auto process_body_error = [&]() -> WebIDL::ExceptionOr<void> { - return fetch_response_handover(realm, fetch_params, Infrastructure::Response::network_error(vm, "Response body could not be processed"sv)); + // FIXME: The spec disagrees on whether fully_read()'s process_body_error should take an argument or not. + // See https://github.com/whatwg/fetch/issues/1636 + // For now, define two versions of processBodyError + auto process_body_error_no_argument = [&realm, &vm, &fetch_params]() { + TRY_OR_IGNORE(fetch_response_handover(realm, fetch_params, Infrastructure::Response::network_error(vm, "Response body could not be processed"sv))); + }; + Infrastructure::Body::ProcessBodyErrorCallback process_body_error = [&realm, &vm, &fetch_params](auto&) { + TRY_OR_IGNORE(fetch_response_handover(realm, fetch_params, Infrastructure::Response::network_error(vm, "Response body could not be processed"sv))); }; // 2. If response’s body is null, then run processBodyError and abort these steps. if (!response->body().has_value()) { - TRY_OR_IGNORE(process_body_error()); + process_body_error_no_argument(); return; } - // FIXME: 3. Let processBody given bytes be these steps: - // 1. If bytes do not match request’s integrity metadata, then run processBodyError and abort these steps. - // 2. Set response’s body to bytes as a body. - // 3. Run fetch response handover given fetchParams and response. + // 3. Let processBody given bytes be these steps: + Infrastructure::Body::ProcessBodyCallback process_body = [&realm, &request, &response, &fetch_params, process_body_error = move(process_body_error_no_argument)](ByteBuffer bytes) { + // 1. If bytes do not match request’s integrity metadata, then run processBodyError and abort these steps. + if (!TRY_OR_IGNORE(SRI::do_bytes_match_metadata_list(bytes, request->integrity_metadata()))) { + process_body_error(); + return; + } + + // 2. Set response’s body to bytes as a body. + response->set_body(TRY_OR_IGNORE(Infrastructure::byte_sequence_as_body(realm, bytes))); + + // 3. Run fetch response handover given fetchParams and response. + TRY_OR_IGNORE(fetch_response_handover(realm, fetch_params, *response)); + }; - // FIXME: 4. Fully read response’s body given processBody and processBodyError. + // 4. Fully read response’s body given processBody and processBodyError. + TRY_OR_IGNORE(response->body()->fully_read(realm, move(process_body), move(process_body_error), fetch_params.task_destination())); } // 23. Otherwise, run fetch response handover given fetchParams and response. else { |