/* * Copyright (c) 2021-2023, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace WebView { struct CookieStorageKey { bool operator==(CookieStorageKey const&) const = default; ByteString name; ByteString domain; ByteString path; }; class CookieJar { struct Statements { SQL::StatementID create_table { 0 }; SQL::StatementID insert_cookie { 0 }; SQL::StatementID update_cookie { 0 }; SQL::StatementID expire_cookie { 0 }; SQL::StatementID select_cookie { 0 }; SQL::StatementID select_all_cookies { 0 }; }; struct PersistedStorage { Database& database; Statements statements; }; using TransientStorage = HashMap; public: static ErrorOr create(Database&); static CookieJar create(); ByteString get_cookie(const URL& url, Web::Cookie::Source source); void set_cookie(const URL& url, Web::Cookie::ParsedCookie const& parsed_cookie, Web::Cookie::Source source); void update_cookie(Web::Cookie::Cookie); void dump_cookies(); Vector get_all_cookies(); Vector get_all_cookies(URL const& url); Optional get_named_cookie(URL const& url, ByteString const& name); private: explicit CookieJar(PersistedStorage); explicit CookieJar(TransientStorage); static Optional canonicalize_domain(const URL& url); static bool domain_matches(ByteString const& string, ByteString const& domain_string); static bool path_matches(ByteString const& request_path, ByteString const& cookie_path); static ByteString default_path(const URL& url); enum class MatchingCookiesSpecMode { RFC6265, WebDriver, }; void store_cookie(Web::Cookie::ParsedCookie const& parsed_cookie, const URL& url, ByteString canonicalized_domain, Web::Cookie::Source source); Vector get_matching_cookies(const URL& url, ByteString const& canonicalized_domain, Web::Cookie::Source source, MatchingCookiesSpecMode mode = MatchingCookiesSpecMode::RFC6265); void insert_cookie_into_database(Web::Cookie::Cookie const& cookie); void update_cookie_in_database(Web::Cookie::Cookie const& cookie); using OnCookieFound = Function; using OnCookieNotFound = Function; void select_cookie_from_database(Web::Cookie::Cookie cookie, OnCookieFound on_result, OnCookieNotFound on_complete_without_results); using OnSelectAllCookiesResult = Function; void select_all_cookies_from_database(OnSelectAllCookiesResult on_result); void purge_expired_cookies(); Variant m_storage; }; } template<> struct AK::Traits : public AK::DefaultTraits { static unsigned hash(WebView::CookieStorageKey const& key) { unsigned hash = 0; hash = pair_int_hash(hash, string_hash(key.name.characters(), key.name.length())); hash = pair_int_hash(hash, string_hash(key.domain.characters(), key.domain.length())); hash = pair_int_hash(hash, string_hash(key.path.characters(), key.path.length())); return hash; } };