/* * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::HTML { // https://html.spec.whatwg.org/multipage/history.html#scroll-restoration-mode enum class ScrollRestorationMode { // https://html.spec.whatwg.org/multipage/history.html#dom-scrollrestoration-auto // The user agent is responsible for restoring the scroll position upon navigation. Auto, // https://html.spec.whatwg.org/multipage/history.html#dom-scrollrestoration-manual // The page is responsible for restoring the scroll position and the user agent does not attempt to do so automatically. Manual, }; struct SessionHistoryNestedHistoryDescriptor; // IPC-friendly descriptors for the parts of session history entries and document states that can survive // WebContent process swaps. // // https://html.spec.whatwg.org/multipage/browsing-the-web.html#session-history-entry // https://html.spec.whatwg.org/multipage/browsing-the-web.html#document-state struct SessionHistoryDocumentStateDescriptor { // AD-HOC: The spec models shared document state by object identity. The UI-process mirror uses a stable // descriptor ID so entries that share a document state can be reconstructed after IPC. u64 id { 0 }; Variant history_policy_container { DocumentState::Client::Tag }; Fetch::Infrastructure::Request::ReferrerType request_referrer { Fetch::Infrastructure::Request::Referrer::Client }; ReferrerPolicy::ReferrerPolicy request_referrer_policy { ReferrerPolicy::DEFAULT_REFERRER_POLICY }; Optional initiator_origin; Optional origin; Optional about_base_url; Variant resource; bool reload_pending { false }; bool ever_populated { false }; String navigable_target_name; Vector nested_histories; }; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-scroll-position struct SessionHistoryEntryScrollPositionData { // FIXME: Track all restorable scrollable regions. Currently only the viewport is persisted. Optional viewport_scroll_position; bool operator==(SessionHistoryEntryScrollPositionData const&) const = default; }; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#session-history-entry struct SessionHistoryEntryDescriptor { i32 step { 0 }; URL::URL url; SessionHistoryDocumentStateDescriptor document_state; SerializationRecord classic_history_api_state; SerializationRecord navigation_api_state; String navigation_api_key; String navigation_api_id; ScrollRestorationMode scroll_restoration_mode { ScrollRestorationMode::Auto }; SessionHistoryEntryScrollPositionData scroll_position_data; }; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#nested-history struct SessionHistoryNestedHistoryDescriptor { String id; Vector entries; }; // https://html.spec.whatwg.org/multipage/history.html#session-history-entry class WEB_API SessionHistoryEntry final : public RefCounted { public: static NonnullRefPtr create(); SessionHistoryEntry(); ~SessionHistoryEntry(); enum class Pending { Tag, }; [[nodiscard]] Variant step() const { return m_step; } void set_step(Variant step) { m_step = step; } [[nodiscard]] Optional step_value() const { if (auto const* step = m_step.get_pointer()) return *step; return {}; } [[nodiscard]] URL::URL const& url() const { return m_url; } void set_url(URL::URL url) { m_url = move(url); } [[nodiscard]] RefPtr document_state() const; void set_document_state(RefPtr); [[nodiscard]] SerializationRecord const& classic_history_api_state() const { return m_classic_history_api_state; } void set_classic_history_api_state(SerializationRecord classic_history_api_state) { m_classic_history_api_state = move(classic_history_api_state); } [[nodiscard]] SerializationRecord const& navigation_api_state() const { return m_navigation_api_state; } void set_navigation_api_state(SerializationRecord navigation_api_state) { m_navigation_api_state = move(navigation_api_state); } [[nodiscard]] String const& navigation_api_key() const { return m_navigation_api_key; } void set_navigation_api_key(String navigation_api_key) { m_navigation_api_key = move(navigation_api_key); } [[nodiscard]] String const& navigation_api_id() const { return m_navigation_api_id; } void set_navigation_api_id(String navigation_api_id) { m_navigation_api_id = move(navigation_api_id); } [[nodiscard]] ScrollRestorationMode scroll_restoration_mode() const { return m_scroll_restoration_mode; } void set_scroll_restoration_mode(ScrollRestorationMode scroll_restoration_mode) { m_scroll_restoration_mode = scroll_restoration_mode; } [[nodiscard]] SessionHistoryEntryScrollPositionData const& scroll_position_data() const { return m_scroll_position_data; } void set_scroll_position_data(SessionHistoryEntryScrollPositionData scroll_position_data) { m_scroll_position_data = move(scroll_position_data); } private: // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-step // step, a non-negative integer or "pending", initially "pending". Variant m_step { Pending::Tag }; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-url // URL, a URL URL::URL m_url; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-document-state RefPtr m_document_state; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-classic-history-api-state // classic history API state, which is serialized state, initially StructuredSerializeForStorage(null). SerializationRecord m_classic_history_api_state; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-navigation-api-state // navigation API state, which is a serialized state, initially StructuredSerializeForStorage(undefined). SerializationRecord m_navigation_api_state; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-navigation-api-key // navigation API key, which is a string, initially set to the result of generating a random UUID. String m_navigation_api_key; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-navigation-api-id // navigation API ID, which is a string, initially set to the result of generating a random UUID. String m_navigation_api_id; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-scroll-restoration-mode // scroll restoration mode, a scroll restoration mode, initially "auto" ScrollRestorationMode m_scroll_restoration_mode { ScrollRestorationMode::Auto }; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-scroll-position // scroll position data, which is scroll position data for the document's restorable scrollable regions SessionHistoryEntryScrollPositionData m_scroll_position_data; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-other // FIXME: persisted user state, which is implementation-defined, initially null // NOTE: This is where we could remember the state of form controls, for example. }; struct SessionHistoryEntryDescriptorCreationState { HashMap document_state_ids; u64 next_document_state_id { 1 }; }; WEB_API SessionHistoryEntryDescriptor create_session_history_entry_descriptor(SessionHistoryEntry const&, SessionHistoryEntryDescriptorCreationState&); WEB_API bool session_history_entry_descriptors_match(SessionHistoryEntryDescriptor const&, SessionHistoryEntryDescriptor const&); enum class MatchNestedHistories { Yes, No, }; WEB_API bool session_history_entry_descriptors_match_ignoring_document_state_id(SessionHistoryEntryDescriptor const&, SessionHistoryEntryDescriptor const&, MatchNestedHistories = MatchNestedHistories::Yes); WEB_API bool session_history_entry_matches_descriptor_ignoring_document_state_id(SessionHistoryEntry const&, SessionHistoryEntryDescriptor const&, MatchNestedHistories = MatchNestedHistories::Yes); } namespace IPC { template<> WEB_API ErrorOr encode(Encoder&, Web::HTML::SessionHistoryEntryDescriptor const&); template<> WEB_API ErrorOr decode(Decoder&); template<> WEB_API ErrorOr encode(Encoder&, Web::HTML::SessionHistoryEntryScrollPositionData const&); template<> WEB_API ErrorOr decode(Decoder&); template<> WEB_API ErrorOr encode(Encoder&, Web::HTML::SessionHistoryDocumentStateDescriptor const&); template<> WEB_API ErrorOr decode(Decoder&); template<> WEB_API ErrorOr encode(Encoder&, Web::HTML::SessionHistoryNestedHistoryDescriptor const&); template<> WEB_API ErrorOr decode(Decoder&); }