mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 12:37:43 +00:00
LibWeb: Convert SubtleCrypto::digest to use WebIDL Promises
We should be using WebIDL Promise in these methods, per the spec references in other specifications. That is, the HTML spec always links to WebIDL when it talks about `Promise<T>`. The Crypto seems to be missing those cross-references. While we're here, actually resolve the digest promise in parallel.
This commit is contained in:
parent
3e0c0ce7ae
commit
7bc7e2a48f
1 changed files with 43 additions and 43 deletions
|
@ -8,11 +8,15 @@
|
||||||
#include <LibCrypto/Hash/HashManager.h>
|
#include <LibCrypto/Hash/HashManager.h>
|
||||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||||
#include <LibJS/Runtime/Promise.h>
|
#include <LibJS/Runtime/Promise.h>
|
||||||
|
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||||
#include <LibWeb/Bindings/Intrinsics.h>
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
#include <LibWeb/Crypto/SubtleCrypto.h>
|
#include <LibWeb/Crypto/SubtleCrypto.h>
|
||||||
|
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||||
|
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||||
#include <LibWeb/WebIDL/AbstractOperations.h>
|
#include <LibWeb/WebIDL/AbstractOperations.h>
|
||||||
#include <LibWeb/WebIDL/Buffers.h>
|
#include <LibWeb/WebIDL/Buffers.h>
|
||||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||||
|
#include <LibWeb/WebIDL/Promise.h>
|
||||||
|
|
||||||
namespace Web::Crypto {
|
namespace Web::Crypto {
|
||||||
|
|
||||||
|
@ -119,69 +123,65 @@ JS::NonnullGCPtr<JS::Promise> SubtleCrypto::digest(AlgorithmIdentifier const& al
|
||||||
// 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the digest() method.
|
// 2. Let data be the result of getting a copy of the bytes held by the data parameter passed to the digest() method.
|
||||||
auto data_buffer_or_error = WebIDL::get_buffer_source_copy(*data->raw_object());
|
auto data_buffer_or_error = WebIDL::get_buffer_source_copy(*data->raw_object());
|
||||||
if (data_buffer_or_error.is_error()) {
|
if (data_buffer_or_error.is_error()) {
|
||||||
auto error = WebIDL::OperationError::create(realm, "Failed to copy bytes from ArrayBuffer"_fly_string);
|
auto promise = WebIDL::create_rejected_promise(realm, WebIDL::OperationError::create(realm, "Failed to copy bytes from ArrayBuffer"_fly_string));
|
||||||
auto promise = JS::Promise::create(realm);
|
return verify_cast<JS::Promise>(*promise->promise());
|
||||||
promise->reject(error.ptr());
|
|
||||||
return promise;
|
|
||||||
}
|
}
|
||||||
auto& data_buffer = data_buffer_or_error.value();
|
auto data_buffer = data_buffer_or_error.release_value();
|
||||||
|
|
||||||
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "digest".
|
// 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "digest".
|
||||||
auto normalized_algorithm = normalize_an_algorithm(algorithm, "digest"_string);
|
auto normalized_algorithm = normalize_an_algorithm(algorithm, "digest"_string);
|
||||||
|
|
||||||
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
|
||||||
|
// FIXME: Spec bug: link to https://webidl.spec.whatwg.org/#a-promise-rejected-with
|
||||||
if (normalized_algorithm.is_error()) {
|
if (normalized_algorithm.is_error()) {
|
||||||
auto promise = JS::Promise::create(realm);
|
auto promise = WebIDL::create_rejected_promise(realm, normalized_algorithm.release_error().release_value().value());
|
||||||
auto error = normalized_algorithm.release_error();
|
return verify_cast<JS::Promise>(*promise->promise());
|
||||||
auto error_value = error.value().value();
|
|
||||||
promise->reject(error_value);
|
|
||||||
return promise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Let promise be a new Promise.
|
// 5. Let promise be a new Promise.
|
||||||
auto promise = JS::Promise::create(realm);
|
auto promise = WebIDL::create_promise(realm);
|
||||||
|
|
||||||
// 6. Return promise and perform the remaining steps in parallel.
|
// 6. Return promise and perform the remaining steps in parallel.
|
||||||
// FIXME: We don't have a good abstraction for this yet, so we do it in sync.
|
Platform::EventLoopPlugin::the().deferred_invoke([&realm, algorithm_object = normalized_algorithm.release_value(), promise, data_buffer = move(data_buffer)]() -> void {
|
||||||
|
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
|
||||||
|
|
||||||
// 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
|
// 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
|
||||||
|
// FIXME: Need spec reference to https://webidl.spec.whatwg.org/#reject
|
||||||
|
|
||||||
// 8. Let result be the result of performing the digest operation specified by normalizedAlgorithm using algorithm, with data as message.
|
// 8. Let result be the result of performing the digest operation specified by normalizedAlgorithm using algorithm, with data as message.
|
||||||
auto algorithm_object = normalized_algorithm.release_value();
|
auto algorithm_name = algorithm_object.name;
|
||||||
auto algorithm_name = algorithm_object.name;
|
|
||||||
|
|
||||||
::Crypto::Hash::HashKind hash_kind;
|
::Crypto::Hash::HashKind hash_kind;
|
||||||
if (algorithm_name.equals_ignoring_ascii_case("SHA-1"sv)) {
|
if (algorithm_name.equals_ignoring_ascii_case("SHA-1"sv)) {
|
||||||
hash_kind = ::Crypto::Hash::HashKind::SHA1;
|
hash_kind = ::Crypto::Hash::HashKind::SHA1;
|
||||||
} else if (algorithm_name.equals_ignoring_ascii_case("SHA-256"sv)) {
|
} else if (algorithm_name.equals_ignoring_ascii_case("SHA-256"sv)) {
|
||||||
hash_kind = ::Crypto::Hash::HashKind::SHA256;
|
hash_kind = ::Crypto::Hash::HashKind::SHA256;
|
||||||
} else if (algorithm_name.equals_ignoring_ascii_case("SHA-384"sv)) {
|
} else if (algorithm_name.equals_ignoring_ascii_case("SHA-384"sv)) {
|
||||||
hash_kind = ::Crypto::Hash::HashKind::SHA384;
|
hash_kind = ::Crypto::Hash::HashKind::SHA384;
|
||||||
} else if (algorithm_name.equals_ignoring_ascii_case("SHA-512"sv)) {
|
} else if (algorithm_name.equals_ignoring_ascii_case("SHA-512"sv)) {
|
||||||
hash_kind = ::Crypto::Hash::HashKind::SHA512;
|
hash_kind = ::Crypto::Hash::HashKind::SHA512;
|
||||||
} else {
|
} else {
|
||||||
auto error = WebIDL::NotSupportedError::create(realm, MUST(String::formatted("Invalid hash function '{}'", algorithm_name)));
|
WebIDL::reject_promise(realm, promise, WebIDL::NotSupportedError::create(realm, MUST(String::formatted("Invalid hash function '{}'", algorithm_name))));
|
||||||
promise->reject(error.ptr());
|
return;
|
||||||
return promise;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
::Crypto::Hash::Manager hash { hash_kind };
|
::Crypto::Hash::Manager hash { hash_kind };
|
||||||
hash.update(data_buffer);
|
hash.update(data_buffer);
|
||||||
|
|
||||||
auto digest = hash.digest();
|
auto digest = hash.digest();
|
||||||
auto result_buffer = ByteBuffer::copy(digest.immutable_data(), hash.digest_size());
|
auto result_buffer = ByteBuffer::copy(digest.immutable_data(), hash.digest_size());
|
||||||
if (result_buffer.is_error()) {
|
if (result_buffer.is_error()) {
|
||||||
auto error = WebIDL::OperationError::create(realm, "Failed to create result buffer"_fly_string);
|
WebIDL::reject_promise(realm, promise, WebIDL::OperationError::create(realm, "Failed to create result buffer"_fly_string));
|
||||||
promise->reject(error.ptr());
|
return;
|
||||||
return promise;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto result = JS::ArrayBuffer::create(realm, result_buffer.release_value());
|
auto result = JS::ArrayBuffer::create(realm, result_buffer.release_value());
|
||||||
|
|
||||||
// 9. Resolve promise with result.
|
// 9. Resolve promise with result.
|
||||||
promise->fulfill(result);
|
WebIDL::resolve_promise(realm, promise, result);
|
||||||
|
});
|
||||||
|
|
||||||
return promise;
|
return verify_cast<JS::Promise>(*promise->promise());
|
||||||
}
|
}
|
||||||
|
|
||||||
SubtleCrypto::SupportedAlgorithmsMap& SubtleCrypto::supported_algorithms_internal()
|
SubtleCrypto::SupportedAlgorithmsMap& SubtleCrypto::supported_algorithms_internal()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue