diff --git a/Userland/Libraries/LibWeb/IndexedDB/Internal/ConnectionQueueHandler.h b/Userland/Libraries/LibWeb/IndexedDB/Internal/ConnectionQueueHandler.h new file mode 100644 index 00000000000..76f2caf6ea5 --- /dev/null +++ b/Userland/Libraries/LibWeb/IndexedDB/Internal/ConnectionQueueHandler.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024, stelar7 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Web::IndexedDB { + +using ConnectionQueue = AK::Vector>; +using ConnectionMap = HashMap>; + +// https://w3c.github.io/IndexedDB/#connection-queues +class ConnectionQueueHandler { +public: + static ConnectionQueue& for_key_and_name(StorageAPI::StorageKey& key, String& name); + static ConnectionQueueHandler& the() + { + static ConnectionQueueHandler s_instance; + return s_instance; + } + +private: + ConnectionMap m_open_requests; +}; + +} diff --git a/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.cpp b/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.cpp index 1e84eab310f..2b96b198011 100644 --- a/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.cpp +++ b/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.cpp @@ -4,10 +4,14 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include namespace Web::IndexedDB { +using IDBDatabaseMapping = HashMap>>; +static IDBDatabaseMapping m_databases; + JS_DEFINE_ALLOCATOR(Database); Database::~Database() = default; @@ -23,5 +27,52 @@ void Database::visit_edges(Visitor& visitor) visitor.visit(m_associated_connections); } +ConnectionQueue& ConnectionQueueHandler::for_key_and_name(StorageAPI::StorageKey& key, String& name) +{ + return ConnectionQueueHandler::the().m_open_requests.ensure(key, [] { + return HashMap(); + }) + .ensure(name, [] { + return ConnectionQueue(); + }); +} + +Optional> Database::for_key_and_name(StorageAPI::StorageKey& key, String& name) +{ + return m_databases.ensure(key, [] { + return HashMap>(); + }) + .get(name); +} + +ErrorOr> Database::create_for_key_and_name(JS::Realm& realm, StorageAPI::StorageKey& key, String& name) +{ + auto database_mapping = TRY(m_databases.try_ensure(key, [] { + return HashMap>(); + })); + + return database_mapping.try_ensure(name, [&] { + return Database::create(realm, name); + }); +} + +ErrorOr Database::delete_for_key_and_name(StorageAPI::StorageKey& key, String& name) +{ + // FIXME: Is a missing entry a failure? + auto maybe_database_mapping = m_databases.get(key); + if (!maybe_database_mapping.has_value()) + return {}; + + auto& database_mapping = maybe_database_mapping.value(); + auto maybe_database = database_mapping.get(name); + if (!maybe_database.has_value()) + return {}; + + auto did_remove = database_mapping.remove(name); + if (!did_remove) + return {}; + + return {}; +} } diff --git a/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.h b/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.h index b06f3f98c29..303d1a9bfa5 100644 --- a/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.h +++ b/Userland/Libraries/LibWeb/IndexedDB/Internal/Database.h @@ -37,6 +37,10 @@ public: return connections; } + [[nodiscard]] static Optional> for_key_and_name(StorageAPI::StorageKey&, String&); + [[nodiscard]] static ErrorOr> create_for_key_and_name(JS::Realm&, StorageAPI::StorageKey&, String&); + [[nodiscard]] static ErrorOr delete_for_key_and_name(StorageAPI::StorageKey&, String&); + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, String const&); virtual ~Database();