summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/Fetch
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2023-04-20 16:52:01 +0100
committerLinus Groh <mail@linusgroh.de>2023-04-21 20:44:47 +0100
commit22e0603bf7d1f958885832510c8a4c128d905ea8 (patch)
treeaeb5764ffe6ac21b663145de8d38cc9e122b29fd /Userland/Libraries/LibWeb/Fetch
parent6d93e03211795d8285d7bbd3a8e1b6fe458262e8 (diff)
downloadserenity-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.cpp35
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 {