/* * Copyright (c) 2021-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace WebView { struct CookieStorageKey { bool operator==(CookieStorageKey const&) const = default; String name; String domain; String path; }; class CookieJar { struct Statements { Database::StatementID insert_cookie { 0 }; Database::StatementID expire_cookie { 0 }; Database::StatementID select_all_cookies { 0 }; }; class TransientStorage { public: using Cookies = HashMap; void set_cookies(Cookies); void set_cookie(CookieStorageKey, Web::Cookie::Cookie); Optional get_cookie(CookieStorageKey const&); size_t size() const { return m_cookies.size(); } UnixDateTime purge_expired_cookies(); auto take_dirty_cookies() { return move(m_dirty_cookies); } template void for_each_cookie(Callback callback) { for (auto& it : m_cookies) callback(it.value); } private: Cookies m_cookies; Cookies m_dirty_cookies; }; struct PersistedStorage { void insert_cookie(Web::Cookie::Cookie const& cookie); TransientStorage::Cookies select_all_cookies(); Database& database; Statements statements; RefPtr synchronization_timer {}; }; public: static ErrorOr> create(Database&); static NonnullOwnPtr create(); ~CookieJar(); String get_cookie(const URL::URL& url, Web::Cookie::Source source); void set_cookie(const URL::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::URL const& url); Optional get_named_cookie(URL::URL const& url, StringView name); private: explicit CookieJar(Optional); AK_MAKE_NONCOPYABLE(CookieJar); AK_MAKE_NONMOVABLE(CookieJar); static Optional canonicalize_domain(const URL::URL& url); static bool domain_matches(StringView string, StringView domain_string); static bool path_matches(StringView request_path, StringView cookie_path); static String default_path(const URL::URL& url); enum class MatchingCookiesSpecMode { RFC6265, WebDriver, }; void store_cookie(Web::Cookie::ParsedCookie const& parsed_cookie, const URL::URL& url, String canonicalized_domain, Web::Cookie::Source source); Vector get_matching_cookies(const URL::URL& url, StringView canonicalized_domain, Web::Cookie::Source source, MatchingCookiesSpecMode mode = MatchingCookiesSpecMode::RFC6265); Optional m_persisted_storage; TransientStorage m_transient_storage; }; } template<> struct AK::Traits : public AK::DefaultTraits { static unsigned hash(WebView::CookieStorageKey const& key) { unsigned hash = 0; hash = pair_int_hash(hash, key.name.hash()); hash = pair_int_hash(hash, key.domain.hash()); hash = pair_int_hash(hash, key.path.hash()); return hash; } };