ladybird/Userland/Libraries/LibWeb/HTML/Navigation.h
Shannon Booth e800605ad3 AK+LibURL: Move AK::URL into a new URL library
This URL library ends up being a relatively fundamental base library of
the system, as LibCore depends on LibURL.

This change has two main benefits:
 * Moving AK back more towards being an agnostic library that can
   be used between the kernel and userspace. URL has never really fit
   that description - and is not used in the kernel.
 * URL _should_ depend on LibUnicode, as it needs punnycode support.
   However, it's not really possible to do this inside of AK as it can't
   depend on any external library. This change brings us a little closer
   to being able to do that, but unfortunately we aren't there quite
   yet, as the code generators depend on LibCore.
2024-03-18 14:06:28 -04:00

194 lines
9.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Promise.h>
#include <LibWeb/Bindings/NavigationPrototype.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/HTML/HistoryHandlingBehavior.h>
#include <LibWeb/HTML/Navigable.h>
#include <LibWeb/HTML/NavigationType.h>
#include <LibWeb/HTML/StructuredSerialize.h>
namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigationupdatecurrententryoptions
struct NavigationUpdateCurrentEntryOptions {
JS::Value state;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigationoptions
struct NavigationOptions {
Optional<JS::Value> info;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigationnavigateoptions
struct NavigationNavigateOptions : public NavigationOptions {
Optional<JS::Value> state;
Bindings::NavigationHistoryBehavior history = Bindings::NavigationHistoryBehavior::Auto;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigationreloadoptions
struct NavigationReloadOptions : public NavigationOptions {
Optional<JS::Value> state;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigationresult
struct NavigationResult {
// FIXME: Are we supposed to return a PromiseCapability (WebIDL::Promise) here?
JS::NonnullGCPtr<JS::Object> committed;
JS::NonnullGCPtr<JS::Object> finished;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-api-method-tracker
struct NavigationAPIMethodTracker final : public JS::Cell {
JS_CELL(NavigationAPIMethodTracker, JS::Cell);
NavigationAPIMethodTracker(JS::NonnullGCPtr<Navigation> navigation,
Optional<String> key,
JS::Value info,
Optional<SerializationRecord> serialized_state,
JS::GCPtr<NavigationHistoryEntry> commited_to_entry,
JS::NonnullGCPtr<WebIDL::Promise> committed_promise,
JS::NonnullGCPtr<WebIDL::Promise> finished_promise);
virtual void visit_edges(Cell::Visitor&) override;
JS::NonnullGCPtr<Navigation> navigation;
Optional<String> key;
JS::Value info;
Optional<SerializationRecord> serialized_state;
JS::GCPtr<NavigationHistoryEntry> commited_to_entry;
JS::NonnullGCPtr<WebIDL::Promise> committed_promise;
JS::NonnullGCPtr<WebIDL::Promise> finished_promise;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-interface
class Navigation : public DOM::EventTarget {
WEB_PLATFORM_OBJECT(Navigation, DOM::EventTarget);
JS_DECLARE_ALLOCATOR(Navigation);
public:
[[nodiscard]] static JS::NonnullGCPtr<Navigation> create(JS::Realm&);
// IDL properties and methods
Vector<JS::NonnullGCPtr<NavigationHistoryEntry>> entries() const;
JS::GCPtr<NavigationHistoryEntry> current_entry() const;
WebIDL::ExceptionOr<void> update_current_entry(NavigationUpdateCurrentEntryOptions);
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigation-transition
JS::GCPtr<NavigationTransition> transition() const { return m_transition; }
bool can_go_back() const;
bool can_go_forward() const;
WebIDL::ExceptionOr<NavigationResult> navigate(String url, NavigationNavigateOptions const&);
WebIDL::ExceptionOr<NavigationResult> reload(NavigationReloadOptions const&);
WebIDL::ExceptionOr<NavigationResult> traverse_to(String key, NavigationOptions const&);
WebIDL::ExceptionOr<NavigationResult> back(NavigationOptions const&);
WebIDL::ExceptionOr<NavigationResult> forward(NavigationOptions const&);
// Event Handlers
void set_onnavigate(WebIDL::CallbackType*);
WebIDL::CallbackType* onnavigate();
void set_onnavigatesuccess(WebIDL::CallbackType*);
WebIDL::CallbackType* onnavigatesuccess();
void set_onnavigateerror(WebIDL::CallbackType*);
WebIDL::CallbackType* onnavigateerror();
void set_oncurrententrychange(WebIDL::CallbackType*);
WebIDL::CallbackType* oncurrententrychange();
// Abstract Operations
bool has_entries_and_events_disabled() const;
i64 get_the_navigation_api_entry_index(SessionHistoryEntry const&) const;
void abort_the_ongoing_navigation(Optional<JS::NonnullGCPtr<WebIDL::DOMException>> error = {});
bool fire_a_traverse_navigate_event(JS::NonnullGCPtr<SessionHistoryEntry> destination_she, UserNavigationInvolvement = UserNavigationInvolvement::None);
bool fire_a_push_replace_reload_navigate_event(
Bindings::NavigationType,
URL::URL destination_url,
bool is_same_document,
UserNavigationInvolvement = UserNavigationInvolvement::None,
Optional<Vector<XHR::FormDataEntry>&> form_data_entry_list = {},
Optional<SerializationRecord> navigation_api_state = {},
Optional<SerializationRecord> classic_history_api_state = {});
bool fire_a_download_request_navigate_event(URL::URL destination_url, UserNavigationInvolvement user_involvement, String filename);
void initialize_the_navigation_api_entries_for_a_new_document(Vector<JS::NonnullGCPtr<SessionHistoryEntry>> const& new_shes, JS::NonnullGCPtr<SessionHistoryEntry> initial_she);
void update_the_navigation_api_entries_for_a_same_document_navigation(JS::NonnullGCPtr<SessionHistoryEntry> destination_she, Bindings::NavigationType);
virtual ~Navigation() override;
// Internal Getters/Setters
JS::GCPtr<NavigateEvent> ongoing_navigate_event() const { return m_ongoing_navigate_event; }
bool focus_changed_during_ongoing_navigation() const { return m_focus_changed_during_ongoing_navigation; }
void set_focus_changed_during_ongoing_navigation(bool b) { m_focus_changed_during_ongoing_navigation = b; }
private:
explicit Navigation(JS::Realm&);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;
using AnyException = decltype(declval<WebIDL::ExceptionOr<void>>().exception());
NavigationResult early_error_result(AnyException);
JS::NonnullGCPtr<NavigationAPIMethodTracker> maybe_set_the_upcoming_non_traverse_api_method_tracker(JS::Value info, Optional<SerializationRecord>);
JS::NonnullGCPtr<NavigationAPIMethodTracker> add_an_upcoming_traverse_api_method_tracker(String destination_key, JS::Value info);
WebIDL::ExceptionOr<NavigationResult> perform_a_navigation_api_traversal(String key, NavigationOptions const&);
void promote_an_upcoming_api_method_tracker_to_ongoing(Optional<String> destination_key);
void resolve_the_finished_promise(JS::NonnullGCPtr<NavigationAPIMethodTracker>);
void reject_the_finished_promise(JS::NonnullGCPtr<NavigationAPIMethodTracker>, JS::Value exception);
void clean_up(JS::NonnullGCPtr<NavigationAPIMethodTracker>);
void notify_about_the_committed_to_entry(JS::NonnullGCPtr<NavigationAPIMethodTracker>, JS::NonnullGCPtr<NavigationHistoryEntry>);
bool inner_navigate_event_firing_algorithm(
Bindings::NavigationType,
JS::NonnullGCPtr<NavigationDestination>,
UserNavigationInvolvement,
Optional<Vector<XHR::FormDataEntry>&> form_data_entry_list,
Optional<String> download_request_filename,
Optional<SerializationRecord> classic_history_api_state);
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-entry-list
// Each Navigation has an associated entry list, a list of NavigationHistoryEntry objects, initially empty.
Vector<JS::NonnullGCPtr<NavigationHistoryEntry>> m_entry_list;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-current-entry-index
// Each Navigation has an associated current entry index, an integer, initially 1.
i64 m_current_entry_index { -1 };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigation-transition
// Each Navigation has a transition, which is a NavigationTransition or null, initially null.
JS::GCPtr<NavigationTransition> m_transition { nullptr };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#ongoing-navigate-event
JS::GCPtr<NavigateEvent> m_ongoing_navigate_event { nullptr };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#focus-changed-during-ongoing-navigation
bool m_focus_changed_during_ongoing_navigation { false };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#suppress-normal-scroll-restoration-during-ongoing-navigation
bool m_suppress_scroll_restoration_during_ongoing_navigation { false };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#ongoing-api-method-tracker
JS::GCPtr<NavigationAPIMethodTracker> m_ongoing_api_method_tracker = nullptr;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#upcoming-non-traverse-api-method-tracker
JS::GCPtr<NavigationAPIMethodTracker> m_upcoming_non_traverse_api_method_tracker = nullptr;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#upcoming-non-traverse-api-method-tracker
HashMap<String, JS::NonnullGCPtr<NavigationAPIMethodTracker>> m_upcoming_traverse_api_method_trackers;
};
HistoryHandlingBehavior to_history_handling_behavior(Bindings::NavigationHistoryBehavior);
}