From a8529629e24d8515ac7f6bf729700a8a4275b0aa Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Sat, 3 May 2025 13:49:38 +0100 Subject: [PATCH] LibWeb/HTML: Update "is script closable" to current spec Corresponds to https://github.com/whatwg/html/commit/d7fc63a84acbaff464ed40353f14d4ee010c8749 and https://github.com/whatwg/html/commit/7a48703e7768f555c6ab89d16ba8439ab96e0e94 --- Libraries/LibWeb/HTML/Navigable.cpp | 34 +++++++++----------- Libraries/LibWeb/HTML/TraversableNavigable.h | 6 ++++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Libraries/LibWeb/HTML/Navigable.cpp b/Libraries/LibWeb/HTML/Navigable.cpp index a6c54e9f247..65c4870050c 100644 --- a/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Libraries/LibWeb/HTML/Navigable.cpp @@ -150,16 +150,14 @@ void Navigable::NavigateParams::visit_edges(Cell::Visitor& visitor) // https://html.spec.whatwg.org/multipage/nav-history-apis.html#script-closable bool Navigable::is_script_closable() { - // A navigable is script-closable if its active browsing context is an auxiliary browsing context that was created - // by a script (as opposed to by an action of the user), or if it is a top-level traversable whose session history - // entries's size is 1. - if (auto browsing_context = active_browsing_context(); browsing_context && browsing_context->is_auxiliary()) - return true; + // A navigable is script-closable if it is a top-level traversable, and any of the following are true: + // - its is created by web content is true; or + // - its session history entries's size is 1. + if (!is_top_level_traversable()) + return false; - if (is_top_level_traversable()) - return get_session_history_entries().size() == 1; - - return false; + return as(this)->is_created_by_web_content() + || get_session_history_entries().size() == 1; } void Navigable::set_delaying_load_events(bool value) @@ -381,7 +379,7 @@ Navigable::ChosenNavigable Navigable::choose_a_navigable(StringView name, Tokeni // 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. + // 3. Let sandboxingFlagSet be currentNavigable's active document's active sandboxing flag set. 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. @@ -455,13 +453,10 @@ Navigable::ChosenNavigable Navigable::choose_a_navigable(StringView name, Tokeni // NOTE: In the presence of an opener policy, // nested documents that are cross-origin with their top-level browsing context's active document always set noopener to true. - // 5. Let chosen be null. - chosen = nullptr; - - // 6. Let targetName be the empty string. + // 5. Let targetName be the empty string. String target_name; - // 7. If name is not an ASCII case-insensitive match for "_blank", then set targetName to name. + // 6. If name is not an ASCII case-insensitive match for "_blank", then set targetName to name. if (!Infra::is_ascii_case_insensitive_match(name, "_blank"sv)) target_name = MUST(String::from_utf8(name)); @@ -475,12 +470,12 @@ Navigable::ChosenNavigable Navigable::choose_a_navigable(StringView name, Tokeni }; auto create_new_traversable = GC::create_function(heap(), move(create_new_traversable_closure)); - // 8. If noopener is true, then set chosen to the result of creating a new top-level traversable given null and targetName. + // 7. If noopener is true, then set chosen to the result of creating a new top-level traversable given null and targetName. if (no_opener == TokenizedFeature::NoOpener::Yes) { chosen = create_new_traversable->function()(nullptr); } - // 9. Otherwise: + // 8. Otherwise: else { // 1. Set chosen to the result of creating a new top-level traversable given currentNavigable's active browsing context, targetName, and currentNavigable. // FIXME: "and currentNavigable", which is the openerNavigableForWebDriver parameter. @@ -492,10 +487,13 @@ Navigable::ChosenNavigable Navigable::choose_a_navigable(StringView name, Tokeni chosen->active_browsing_context()->set_the_one_permitted_sandboxed_navigator(active_browsing_context()); } - // 10. If sandboxingFlagSet's sandbox propagates to auxiliary browsing contexts flag is set, + // 9. If sandboxingFlagSet's sandbox propagates to auxiliary browsing contexts flag is set, // then all the flags that are set in sandboxingFlagSet must be set in chosen's active browsing context's popup sandboxing flag set. if (has_flag(sandboxing_flag_set, SandboxingFlagSet::SandboxPropagatesToAuxiliaryBrowsingContexts)) chosen->active_browsing_context()->set_popup_sandboxing_flag_set(chosen->active_browsing_context()->popup_sandboxing_flag_set() | sandboxing_flag_set); + + // 10. Set chosen's is created by web content to true. + as(*chosen).set_is_created_by_web_content(true); } // --> If the user agent has been configured such that in this instance it will choose currentNavigable diff --git a/Libraries/LibWeb/HTML/TraversableNavigable.h b/Libraries/LibWeb/HTML/TraversableNavigable.h index 8ccc236a95d..a63cd50f728 100644 --- a/Libraries/LibWeb/HTML/TraversableNavigable.h +++ b/Libraries/LibWeb/HTML/TraversableNavigable.h @@ -47,6 +47,9 @@ public: VisibilityState system_visibility_state() const { return m_system_visibility_state; } void set_system_visibility_state(VisibilityState); + bool is_created_by_web_content() const { return m_is_created_by_web_content; } + void set_is_created_by_web_content(bool value) { m_is_created_by_web_content = value; } + struct HistoryObjectLengthAndIndex { u64 script_history_length; u64 script_history_index; @@ -156,6 +159,9 @@ private: // https://html.spec.whatwg.org/multipage/document-sequences.html#system-visibility-state VisibilityState m_system_visibility_state { VisibilityState::Hidden }; + // https://html.spec.whatwg.org/multipage/document-sequences.html#is-created-by-web-content + bool m_is_created_by_web_content { false }; + // https://storage.spec.whatwg.org/#traversable-navigable-storage-shed // A traversable navigable holds a storage shed, which is a storage shed. A traversable navigable’s storage shed holds all session storage data. StorageAPI::StorageShed m_storage_shed;