diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index b49c08caeb..12cb9ee0d3 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -225,6 +226,55 @@ JS::GCPtr Navigable::top_level_traversable() return verify_cast(navigable); } +Navigable::ChosenNavigable Navigable::choose_a_navigable(StringView name, TokenizedFeature::NoOpener, ActivateTab) +{ + // 1. Let chosen be null. + JS::GCPtr chosen = nullptr; + + // 2. Let windowType be "existing or none". + auto window_type = WindowType::ExistingOrNone; + + // 3. Let sandboxingFlagSet be current's active document's active sandboxing flag set. + [[maybe_unused]] auto sandboxing_flag_set = active_document()->active_sandboxing_flag_set(); + + // 4. If name is the empty string or an ASCII case-insensitive match for "_self", then set chosen to currentNavigable. + if (name.is_empty() || Infra::is_ascii_case_insensitive_match(name, "_self"sv)) { + chosen = this; + } + // 5. Otherwise, if name is an ASCII case-insensitive match for "_parent", + // set chosen to currentNavigable's parent, if any, and currentNavigable otherwise. + else if (Infra::is_ascii_case_insensitive_match(name, "_parent"sv)) { + if (auto parent = this->parent()) + chosen = parent; + else + chosen = this; + } + // 6. Otherwise, if name is an ASCII case-insensitive match for "_top", + // set chosen to currentNavigable's traversable navigable. + else if (Infra::is_ascii_case_insensitive_match(name, "_top"sv)) { + chosen = traversable_navigable(); + } + // 7. Otherwise, if name is not an ASCII case-insensitive match for "_blank", + // there exists a navigable whose target name is the same as name, currentNavigable's + // active browsing context is familiar with that navigable's active browsing context, + // and the user agent determines that the two browsing contexts are related enough that + // it is ok if they reach each other, set chosen to that navigable. If there are multiple + // matching navigables, the user agent should pick one in some arbitrary consistent manner, + // such as the most recently opened, most recently focused, or more closely related, and set + // chosen to it. + else if (!Infra::is_ascii_case_insensitive_match(name, "_blank"sv)) { + TODO(); + } + // Otherwise, a new top-level traversable is being requested, and what happens depends on the + // user agent's configuration and abilities — it is determined by the rules given for the first + // applicable option from the following list: + else { + TODO(); + } + + return { chosen.ptr(), window_type }; +} + // https://html.spec.whatwg.org/multipage/browsing-the-web.html#getting-session-history-entries Vector>& Navigable::get_session_history_entries() const { diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index 50ac7da32a..a1d111081a 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -9,9 +9,11 @@ #include #include +#include #include #include #include +#include namespace Web::HTML { @@ -63,6 +65,19 @@ public: JS::GCPtr traversable_navigable() const; JS::GCPtr top_level_traversable(); + enum class WindowType { + ExistingOrNone, + NewAndUnrestricted, + NewWithNoOpener, + }; + + struct ChosenNavigable { + JS::GCPtr navigable; + WindowType window_type; + }; + + ChosenNavigable choose_a_navigable(StringView name, TokenizedFeature::NoOpener no_opener, ActivateTab = ActivateTab::Yes); + static JS::GCPtr navigable_with_active_document(JS::NonnullGCPtr); enum class Traversal {