/* * Copyright (c) 2024-2025, Shannon Booth * Copyright (c) 2025, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include namespace Web::StorageAPI { // https://storage.spec.whatwg.org/#storage-bottle class StorageBottle : public GC::Cell { GC_CELL(StorageBottle, GC::Cell); public: static GC::Ref create(GC::Heap& heap, GC::Ref page, StorageType type, StorageKey key, Optional quota); virtual ~StorageBottle() = default; // A storage bottle also has a proxy map reference set, which is initially an empty set GC::Ref proxy() { return *this; } virtual size_t size() const = 0; virtual Vector keys() const = 0; virtual Optional get(String const&) const = 0; virtual WebView::StorageOperationError set(String const& key, String const& value) = 0; virtual void clear() = 0; virtual void remove(String const&) = 0; Optional quota() const { return m_quota; } protected: explicit StorageBottle(Optional quota) : m_quota(quota) { } Optional m_quota; }; class LocalStorageBottle final : public StorageBottle { GC_CELL(LocalStorageBottle, StorageBottle); GC_DECLARE_ALLOCATOR(LocalStorageBottle); public: static GC::Ref create(GC::Heap& heap, GC::Ref page, StorageKey key, Optional quota) { return heap.allocate(page, key, quota); } virtual size_t size() const override; virtual Vector keys() const override; virtual Optional get(String const&) const override; virtual WebView::StorageOperationError set(String const& key, String const& value) override; virtual void clear() override; virtual void remove(String const&) override; virtual void visit_edges(GC::Cell::Visitor& visitor) override; private: explicit LocalStorageBottle(GC::Ref page, StorageKey key, Optional quota) : StorageBottle(quota) , m_page(move(page)) , m_storage_key(move(key)) { } GC::Ref m_page; StorageKey m_storage_key; }; class SessionStorageBottle final : public StorageBottle { GC_CELL(SessionStorageBottle, StorageBottle); GC_DECLARE_ALLOCATOR(SessionStorageBottle); public: static GC::Ref create(GC::Heap& heap, Optional quota) { return heap.allocate(quota); } virtual size_t size() const override; virtual Vector keys() const override; virtual Optional get(String const&) const override; virtual WebView::StorageOperationError set(String const& key, String const& value) override; virtual void clear() override; virtual void remove(String const&) override; private: explicit SessionStorageBottle(Optional quota) : StorageBottle(quota) { } // A storage bottle has a map, which is initially an empty map OrderedHashMap m_map; }; using BottleMap = Array, to_underlying(StorageEndpointType::Count)>; // https://storage.spec.whatwg.org/#storage-bucket // A storage bucket is a place for storage endpoints to store data. class StorageBucket : public GC::Cell { GC_CELL(StorageBucket, GC::Cell); GC_DECLARE_ALLOCATOR(StorageBucket); public: static GC::Ref create(GC::Heap& heap, GC::Ref page, StorageKey key, StorageType type) { return heap.allocate(page, key, type); } BottleMap& bottle_map() { return m_bottle_map; } BottleMap const& bottle_map() const { return m_bottle_map; } virtual void visit_edges(GC::Cell::Visitor& visitor) override; private: explicit StorageBucket(GC::Ref page, StorageKey key, StorageType type); // A storage bucket has a bottle map of storage identifiers to storage bottles. BottleMap m_bottle_map; }; GC::Ptr obtain_a_session_storage_bottle_map(HTML::EnvironmentSettingsObject&, StorageEndpointType endpoint_type); GC::Ptr obtain_a_storage_bottle_map(StorageType, HTML::EnvironmentSettingsObject&, StorageEndpointType endpoint_type); }