mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
AK+LibWeb: Move generation of random UUIDs into AK
This will let us use this more outside of LibWeb more easily. Stop handling tiny OOM while we are here.
This commit is contained in:
Notes:
github-actions[bot]
2026-03-24 16:07:31 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/58791db8181 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8589 Reviewed-by: https://github.com/shannonbooth
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AK/Platform.h>
|
||||
#include <AK/Random.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/UFixedBigInt.h>
|
||||
#include <AK/UFixedBigIntDivision.h>
|
||||
|
||||
@@ -89,6 +90,52 @@ u64 get_random_uniform_64(u64 max_bounds)
|
||||
return random_value % max_bounds;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#dfn-generate-a-random-uuid
|
||||
String generate_random_uuid()
|
||||
{
|
||||
// 1. Let bytes be a byte sequence of length 16.
|
||||
u8 bytes[16];
|
||||
|
||||
// 2. Fill bytes with cryptographically secure random bytes.
|
||||
fill_with_random(bytes);
|
||||
|
||||
// 3. Set the 4 most significant bits of bytes[6], which represent the UUID version, to 0100.
|
||||
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
||||
|
||||
// 4. Set the 2 most significant bits of bytes[8], which represent the UUID variant, to 10.
|
||||
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
||||
|
||||
// 5. Return the string concatenation of «
|
||||
// hexadecimal representation of bytes[0],
|
||||
// hexadecimal representation of bytes[1],
|
||||
// hexadecimal representation of bytes[2],
|
||||
// hexadecimal representation of bytes[3],
|
||||
// "-",
|
||||
// hexadecimal representation of bytes[4],
|
||||
// hexadecimal representation of bytes[5],
|
||||
// "-",
|
||||
// hexadecimal representation of bytes[6],
|
||||
// hexadecimal representation of bytes[7],
|
||||
// "-",
|
||||
// hexadecimal representation of bytes[8],
|
||||
// hexadecimal representation of bytes[9],
|
||||
// "-",
|
||||
// hexadecimal representation of bytes[10],
|
||||
// hexadecimal representation of bytes[11],
|
||||
// hexadecimal representation of bytes[12],
|
||||
// hexadecimal representation of bytes[13],
|
||||
// hexadecimal representation of bytes[14],
|
||||
// hexadecimal representation of bytes[15]
|
||||
// ».
|
||||
return MUST(String::formatted(
|
||||
"{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
|
||||
bytes[0], bytes[1], bytes[2], bytes[3],
|
||||
bytes[4], bytes[5],
|
||||
bytes[6], bytes[7],
|
||||
bytes[8], bytes[9],
|
||||
bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]));
|
||||
}
|
||||
|
||||
XorShift128PlusRNG::XorShift128PlusRNG()
|
||||
{
|
||||
// Splitmix64 is used as xorshift is sensitive to being seeded with all 0s
|
||||
|
||||
@@ -31,6 +31,8 @@ inline T get_random()
|
||||
u32 get_random_uniform(u32 max_bounds);
|
||||
u64 get_random_uniform_64(u64 max_bounds);
|
||||
|
||||
String generate_random_uuid();
|
||||
|
||||
// http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
|
||||
class XorShift128PlusRNG {
|
||||
public:
|
||||
@@ -58,6 +60,7 @@ inline void shuffle(Collection& collection)
|
||||
|
||||
#if USING_AK_GLOBALLY
|
||||
using AK::fill_with_random;
|
||||
using AK::generate_random_uuid;
|
||||
using AK::get_random;
|
||||
using AK::get_random_uniform;
|
||||
using AK::shuffle;
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
*/
|
||||
|
||||
#include <AK/Random.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/Runtime/TypedArray.h>
|
||||
#include <LibWeb/Bindings/CryptoPrototype.h>
|
||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Crypto/Crypto.h>
|
||||
#include <LibWeb/Crypto/SubtleCrypto.h>
|
||||
@@ -39,6 +37,12 @@ void Crypto::initialize(JS::Realm& realm)
|
||||
m_subtle = SubtleCrypto::create(realm);
|
||||
}
|
||||
|
||||
void Crypto::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_subtle);
|
||||
}
|
||||
|
||||
GC::Ref<SubtleCrypto> Crypto::subtle() const
|
||||
{
|
||||
return *m_subtle;
|
||||
@@ -73,70 +77,15 @@ WebIDL::ExceptionOr<GC::Root<WebIDL::ArrayBufferView>> Crypto::get_random_values
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#dfn-Crypto-method-randomUUID
|
||||
WebIDL::ExceptionOr<String> Crypto::random_uuid() const
|
||||
String Crypto::random_uuid() const
|
||||
{
|
||||
auto& vm = realm().vm();
|
||||
|
||||
return TRY_OR_THROW_OOM(vm, generate_random_uuid());
|
||||
}
|
||||
|
||||
void Crypto::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_subtle);
|
||||
return generate_random_uuid();
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#dfn-generate-a-random-uuid
|
||||
ErrorOr<String> generate_random_uuid()
|
||||
String generate_random_uuid()
|
||||
{
|
||||
// 1. Let bytes be a byte sequence of length 16.
|
||||
u8 bytes[16];
|
||||
|
||||
// 2. Fill bytes with cryptographically secure random bytes.
|
||||
fill_with_random(bytes);
|
||||
|
||||
// 3. Set the 4 most significant bits of bytes[6], which represent the UUID version, to 0100.
|
||||
bytes[6] &= ~(1 << 7);
|
||||
bytes[6] |= 1 << 6;
|
||||
bytes[6] &= ~(1 << 5);
|
||||
bytes[6] &= ~(1 << 4);
|
||||
|
||||
// 4. Set the 2 most significant bits of bytes[8], which represent the UUID variant, to 10.
|
||||
bytes[8] |= 1 << 7;
|
||||
bytes[8] &= ~(1 << 6);
|
||||
|
||||
/* 5. Return the string concatenation of
|
||||
«
|
||||
hexadecimal representation of bytes[0],
|
||||
hexadecimal representation of bytes[1],
|
||||
hexadecimal representation of bytes[2],
|
||||
hexadecimal representation of bytes[3],
|
||||
"-",
|
||||
hexadecimal representation of bytes[4],
|
||||
hexadecimal representation of bytes[5],
|
||||
"-",
|
||||
hexadecimal representation of bytes[6],
|
||||
hexadecimal representation of bytes[7],
|
||||
"-",
|
||||
hexadecimal representation of bytes[8],
|
||||
hexadecimal representation of bytes[9],
|
||||
"-",
|
||||
hexadecimal representation of bytes[10],
|
||||
hexadecimal representation of bytes[11],
|
||||
hexadecimal representation of bytes[12],
|
||||
hexadecimal representation of bytes[13],
|
||||
hexadecimal representation of bytes[14],
|
||||
hexadecimal representation of bytes[15]
|
||||
».
|
||||
*/
|
||||
StringBuilder builder;
|
||||
TRY(builder.try_appendff("{:02x}{:02x}{:02x}{:02x}-", bytes[0], bytes[1], bytes[2], bytes[3]));
|
||||
TRY(builder.try_appendff("{:02x}{:02x}-", bytes[4], bytes[5]));
|
||||
TRY(builder.try_appendff("{:02x}{:02x}-", bytes[6], bytes[7]));
|
||||
TRY(builder.try_appendff("{:02x}{:02x}-", bytes[8], bytes[9]));
|
||||
TRY(builder.try_appendff("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]));
|
||||
|
||||
return builder.to_string();
|
||||
return AK::generate_random_uuid();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
GC::Ref<SubtleCrypto> subtle() const;
|
||||
|
||||
WebIDL::ExceptionOr<GC::Root<WebIDL::ArrayBufferView>> get_random_values(GC::Root<WebIDL::ArrayBufferView>) const;
|
||||
WebIDL::ExceptionOr<String> random_uuid() const;
|
||||
String random_uuid() const;
|
||||
|
||||
protected:
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
@@ -37,6 +37,6 @@ private:
|
||||
GC::Ptr<SubtleCrypto> m_subtle;
|
||||
};
|
||||
|
||||
WEB_API ErrorOr<String> generate_random_uuid();
|
||||
WEB_API String generate_random_uuid();
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ ErrorOr<Utf16String> generate_new_blob_url()
|
||||
TRY(result.try_append('/'));
|
||||
|
||||
// 9. Generate a UUID [RFC4122] as a string and append it to result.
|
||||
auto uuid = TRY(Crypto::generate_random_uuid());
|
||||
auto uuid = Crypto::generate_random_uuid();
|
||||
TRY(result.try_append(uuid));
|
||||
|
||||
// 10. Return result.
|
||||
|
||||
@@ -1685,7 +1685,7 @@ void Navigable::begin_navigation(NavigateParams params)
|
||||
// NOTE: This step is handled in Navigable::navigate()
|
||||
|
||||
// 7. Let navigationId be the result of generating a random UUID.
|
||||
String navigation_id = MUST(Crypto::generate_random_uuid());
|
||||
auto navigation_id = Crypto::generate_random_uuid();
|
||||
|
||||
// FIXME: 8. If the surrounding agent is equal to navigable's active document's relevant agent, then continue these steps.
|
||||
// Otherwise, queue a global task on the navigation and traversal task source given navigable's active window to continue these steps.
|
||||
|
||||
@@ -25,8 +25,8 @@ void SessionHistoryEntry::visit_edges(Cell::Visitor& visitor)
|
||||
SessionHistoryEntry::SessionHistoryEntry()
|
||||
: m_classic_history_api_state(MUST(structured_serialize_for_storage(vm(), JS::js_null())))
|
||||
, m_navigation_api_state(MUST(structured_serialize_for_storage(vm(), JS::js_undefined())))
|
||||
, m_navigation_api_key(MUST(Crypto::generate_random_uuid()))
|
||||
, m_navigation_api_id(MUST(Crypto::generate_random_uuid()))
|
||||
, m_navigation_api_key(Crypto::generate_random_uuid())
|
||||
, m_navigation_api_id(Crypto::generate_random_uuid())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ IDBDatabase::IDBDatabase(JS::Realm& realm, Database& db)
|
||||
: EventTarget(realm)
|
||||
, m_name(db.name())
|
||||
, m_associated_database(db)
|
||||
, m_uuid(Crypto::generate_random_uuid())
|
||||
{
|
||||
m_uuid = MUST(Crypto::generate_random_uuid());
|
||||
db.associate(*this);
|
||||
m_object_store_set = Vector<GC::Ref<ObjectStore>> { db.object_stores() };
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ IDBRequest::~IDBRequest() = default;
|
||||
IDBRequest::IDBRequest(JS::Realm& realm, IDBRequestSource source)
|
||||
: EventTarget(realm)
|
||||
, m_source(source)
|
||||
, m_uuid(Crypto::generate_random_uuid())
|
||||
{
|
||||
m_uuid = MUST(Crypto::generate_random_uuid());
|
||||
}
|
||||
|
||||
void IDBRequest::initialize(JS::Realm& realm)
|
||||
|
||||
@@ -26,8 +26,8 @@ IDBTransaction::IDBTransaction(JS::Realm& realm, GC::Ref<IDBDatabase> connection
|
||||
, m_mode(mode)
|
||||
, m_durability(durability)
|
||||
, m_scope(move(scopes))
|
||||
, m_uuid(Crypto::generate_random_uuid())
|
||||
{
|
||||
m_uuid = MUST(Crypto::generate_random_uuid());
|
||||
connection->add_transaction(*this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1365,7 +1365,7 @@ GC_DEFINE_ALLOCATOR(ActionExecutor);
|
||||
void wait_for_an_action_queue_token(InputState& input_state)
|
||||
{
|
||||
// 1. Let token be a new unique identifier.
|
||||
auto token = MUST(Crypto::generate_random_uuid());
|
||||
auto token = Crypto::generate_random_uuid();
|
||||
|
||||
// 2. Enqueue token in input state's actions queue.
|
||||
input_state.actions_queue.append(token);
|
||||
|
||||
@@ -629,7 +629,7 @@ void ViewImplementation::initialize_client(CreateNewClient create_new_client)
|
||||
m_client_state.client->register_view(m_client_state.page_index, *this);
|
||||
}
|
||||
|
||||
m_client_state.client_handle = MUST(Web::Crypto::generate_random_uuid());
|
||||
m_client_state.client_handle = Web::Crypto::generate_random_uuid();
|
||||
client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle);
|
||||
client().async_set_zoom_level(m_client_state.page_index, m_zoom_level);
|
||||
client().async_set_viewport(m_client_state.page_index, viewport_size(), m_device_pixel_ratio, m_is_fullscreen);
|
||||
|
||||
@@ -1716,7 +1716,7 @@ Web::WebDriver::Response WebDriverConnection::element_click_impl(StringView elem
|
||||
};
|
||||
|
||||
// 3. Let input id be a the result of generating a UUID.
|
||||
auto input_id = MUST(Web::Crypto::generate_random_uuid());
|
||||
auto input_id = Web::Crypto::generate_random_uuid();
|
||||
|
||||
// 4. Let source be the result of create an input source with input state, and "pointer".
|
||||
auto source = Web::WebDriver::create_input_source(input_state, Web::WebDriver::InputSourceType::Pointer, Web::WebDriver::PointerInputSource::Subtype::Mouse);
|
||||
@@ -2035,7 +2035,7 @@ Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(StringView
|
||||
auto& input_state = Web::WebDriver::get_input_state(*current_top_level_browsing_context());
|
||||
|
||||
// 10. Let input id be a the result of generating a UUID.
|
||||
auto input_id = MUST(Web::Crypto::generate_random_uuid());
|
||||
auto input_id = Web::Crypto::generate_random_uuid();
|
||||
|
||||
// 11. Let source be the result of create an input source with input state, and "key".
|
||||
auto source = Web::WebDriver::create_input_source(input_state, Web::WebDriver::InputSourceType::Key, {});
|
||||
|
||||
@@ -35,7 +35,7 @@ static HashMap<String, NonnullRefPtr<Session>> s_http_sessions;
|
||||
ErrorOr<NonnullRefPtr<Session>> Session::create(NonnullRefPtr<Client> client, JsonObject& capabilities, Web::WebDriver::SessionFlags flags)
|
||||
{
|
||||
// 1. Let session id be the result of generating a UUID.
|
||||
auto session_id = MUST(Web::Crypto::generate_random_uuid());
|
||||
auto session_id = Web::Crypto::generate_random_uuid();
|
||||
|
||||
// 2. Let session be a new session with session ID session id, and HTTP flag flags contains "http".
|
||||
auto session = adopt_ref(*new Session(client, capabilities, move(session_id), flags));
|
||||
|
||||
Reference in New Issue
Block a user