From 6942bdcfce154bcd6825701da04cd8fa6233c8e3 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 4 Sep 2023 15:33:08 +0200 Subject: [PATCH] LibWeb: Update top_level_browsing_context() to use navigables --- .../Libraries/LibWeb/HTML/BrowsingContext.cpp | 35 +++++++++++++++---- .../Libraries/LibWeb/HTML/BrowsingContext.h | 10 +----- .../LibWeb/HTML/CrossOrigin/Reporting.cpp | 4 +-- Userland/Libraries/LibWeb/HTML/Focus.cpp | 14 ++++---- .../LibWeb/HTML/HTMLInputElement.cpp | 2 +- .../LibWeb/HTML/NavigableContainer.cpp | 2 +- Userland/Libraries/LibWeb/HTML/Window.cpp | 2 +- .../Libraries/LibWeb/Internals/Internals.cpp | 2 +- .../IntersectionObserver.cpp | 2 +- 9 files changed, 43 insertions(+), 30 deletions(-) diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index 34afe297c4..0fa704b614 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -251,8 +251,8 @@ WebIDL::ExceptionOr BrowsingContext if (creator->origin().is_same_origin(creator->relevant_settings_object().top_level_origin)) { // then set document's cross-origin opener policy to creator's browsing context's top-level browsing context's active document's cross-origin opener policy. VERIFY(creator->browsing_context()); - VERIFY(creator->browsing_context()->top_level_browsing_context().active_document()); - document->set_cross_origin_opener_policy(creator->browsing_context()->top_level_browsing_context().active_document()->cross_origin_opener_policy()); + VERIFY(creator->browsing_context()->top_level_browsing_context()->active_document()); + document->set_cross_origin_opener_policy(creator->browsing_context()->top_level_browsing_context()->active_document()->cross_origin_opener_policy()); } } @@ -409,6 +409,27 @@ void BrowsingContext::scroll_to_anchor(DeprecatedString const& fragment) m_page->client().page_did_request_scroll_into_view(target_rect); } +JS::GCPtr BrowsingContext::top_level_browsing_context() const +{ + auto const* start = this; + + // 1. If start's active document is not fully active, then return null. + if (!start->active_document()->is_fully_active()) { + return nullptr; + } + + // 2. Let navigable be start's active document's node navigable. + auto navigable = start->active_document()->navigable(); + + // 3. While navigable's parent is not null, set navigable to navigable's parent. + while (navigable->parent()) { + navigable = navigable->parent(); + } + + // 4. Return navigable's active browsing context. + return navigable->active_browsing_context(); +} + CSSPixelRect BrowsingContext::to_top_level_rect(CSSPixelRect const& a_rect) { auto rect = a_rect; @@ -583,7 +604,7 @@ BrowsingContext::ChosenBrowsingContext BrowsingContext::choose_a_browsing_contex // The rules for choosing a browsing context, given a browsing context name name, a browsing context current, and // a boolean noopener are as follows: JS::GCPtr matching_name_in_tree = nullptr; - top_level_browsing_context().for_each_in_subtree([&](auto& context) { + top_level_browsing_context()->for_each_in_subtree([&](auto& context) { if (context.name() == name) { matching_name_in_tree = &context; return IterationDecision::Break; @@ -618,7 +639,7 @@ BrowsingContext::ChosenBrowsingContext BrowsingContext::choose_a_browsing_contex // 6. Otherwise, if name is an ASCII case-insensitive match for "_top", set chosen to current's top-level browsing // context, if any, and current otherwise. else if (Infra::is_ascii_case_insensitive_match(name, "_top"sv)) { - chosen = &top_level_browsing_context(); + chosen = top_level_browsing_context(); } // 7. Otherwise, if name is not an ASCII case-insensitive match for "_blank", there exists a browsing context @@ -655,9 +676,9 @@ BrowsingContext::ChosenBrowsingContext BrowsingContext::choose_a_browsing_contex // 2. If current's top-level browsing context's active document's cross-origin opener policy's value is // "same-origin" or "same-origin-plus-COEP", then: - if (top_level_browsing_context().active_document()->cross_origin_opener_policy().value == CrossOriginOpenerPolicyValue::SameOrigin || top_level_browsing_context().active_document()->cross_origin_opener_policy().value == CrossOriginOpenerPolicyValue::SameOriginPlusCOEP) { + if (top_level_browsing_context()->active_document()->cross_origin_opener_policy().value == CrossOriginOpenerPolicyValue::SameOrigin || top_level_browsing_context()->active_document()->cross_origin_opener_policy().value == CrossOriginOpenerPolicyValue::SameOriginPlusCOEP) { // 1. Let currentDocument be current's active document. - auto* current_document = top_level_browsing_context().active_document(); + auto* current_document = top_level_browsing_context()->active_document(); // 2. If currentDocument's origin is not same origin with currentDocument's relevant settings object's // top-level origin, then set noopener to true, name to "_blank", and windowType to "new with no opener". @@ -871,7 +892,7 @@ void BrowsingContext::set_system_visibility_state(VisibilityState visibility_sta // When a user-agent determines that the system visibility state for top-level browsing context context // has changed to newState, it must queue a task on the user interaction task source to update // the visibility state of all the Document objects in the top-level browsing context's document family with newState. - auto document_family = top_level_browsing_context().document_family(); + auto document_family = top_level_browsing_context()->document_family(); // From the new navigable version, where it tells us what global object to use here: // 1. Let document be navigable's active document. diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h index 775d687af0..360ad4c95b 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h @@ -142,15 +142,7 @@ public: void scroll_to(CSSPixelPoint); void scroll_to_anchor(DeprecatedString const&); - BrowsingContext& top_level_browsing_context() - { - BrowsingContext* context = this; - while (context->parent()) - context = context->parent(); - return *context; - } - - BrowsingContext const& top_level_browsing_context() const { return const_cast(this)->top_level_browsing_context(); } + JS::GCPtr top_level_browsing_context() const; enum class WindowType { ExistingOrNone, diff --git a/Userland/Libraries/LibWeb/HTML/CrossOrigin/Reporting.cpp b/Userland/Libraries/LibWeb/HTML/CrossOrigin/Reporting.cpp index 81da84e14d..e308a024d6 100644 --- a/Userland/Libraries/LibWeb/HTML/CrossOrigin/Reporting.cpp +++ b/Userland/Libraries/LibWeb/HTML/CrossOrigin/Reporting.cpp @@ -27,11 +27,11 @@ void check_if_access_between_two_browsing_contexts_should_be_reported(BrowsingCo auto accessor_accessed_relationship = AccessorAccessedRelationship::None; // 5. If accessed's top-level browsing context's opener browsing context is accessor or an ancestor of accessor, then set accessorAccessedRelationship to accessor is opener. - if (auto opener = accessed.top_level_browsing_context().opener_browsing_context(); opener && (opener == &accessor || opener->is_ancestor_of(accessor))) + if (auto opener = accessed.top_level_browsing_context()->opener_browsing_context(); opener && (opener == &accessor || opener->is_ancestor_of(accessor))) accessor_accessed_relationship = AccessorAccessedRelationship::AccessorIsOpener; // 6. If accessor's top-level browsing context's opener browsing context is accessed or an ancestor of accessed, then set accessorAccessedRelationship to accessor is openee. - if (auto opener = accessor.top_level_browsing_context().opener_browsing_context(); opener && (opener == &accessed || opener->is_ancestor_of(accessed))) + if (auto opener = accessor.top_level_browsing_context()->opener_browsing_context(); opener && (opener == &accessed || opener->is_ancestor_of(accessed))) accessor_accessed_relationship = AccessorAccessedRelationship::AccessorIsOpenee; // FIXME: 7. Queue violation reports for accesses, given accessorAccessedRelationship, accessor's top-level browsing context's active document's cross-origin opener policy, accessed's top-level browsing context's active document's cross-origin opener policy, accessor's active document's URL, accessed's active document's URL, accessor's top-level browsing context's initial URL, accessed's top-level browsing context's initial URL, accessor's active document's origin, accessed's active document's origin, accessor's top-level browsing context's opener origin at creation, accessed's top-level browsing context's opener origin at creation, accessor's top-level browsing context's active document's referrer, accessed's top-level browsing context's active document's referrer, P, and environment. diff --git a/Userland/Libraries/LibWeb/HTML/Focus.cpp b/Userland/Libraries/LibWeb/HTML/Focus.cpp index 23f35e1940..f073205e5c 100644 --- a/Userland/Libraries/LibWeb/HTML/Focus.cpp +++ b/Userland/Libraries/LibWeb/HTML/Focus.cpp @@ -187,13 +187,13 @@ void run_focusing_steps(DOM::Node* new_focus_target, DOM::Node* fallback_target, // 5. If new focus target is the currently focused area of a top-level browsing context, then return. if (!new_focus_target->document().browsing_context()) return; - auto& top_level_browsing_context = new_focus_target->document().browsing_context()->top_level_browsing_context(); - if (new_focus_target == top_level_browsing_context.currently_focused_area().ptr()) + auto top_level_browsing_context = new_focus_target->document().browsing_context()->top_level_browsing_context(); + if (new_focus_target == top_level_browsing_context->currently_focused_area().ptr()) return; // 6. Let old chain be the current focus chain of the top-level browsing context in which // new focus target finds itself. - auto old_chain = focus_chain(top_level_browsing_context.currently_focused_area()); + auto old_chain = focus_chain(top_level_browsing_context->currently_focused_area()); // 7. Let new chain be the focus chain of new focus target. auto new_chain = focus_chain(new_focus_target); @@ -220,8 +220,8 @@ void run_unfocusing_steps(DOM::Node* old_focus_target) if (is_shadow_host(old_focus_target)) { auto* shadow_root = static_cast(old_focus_target)->shadow_root_internal(); if (shadow_root->delegates_focus()) { - auto& top_level_browsing_context = old_focus_target->document().browsing_context()->top_level_browsing_context(); - if (auto currently_focused_area = top_level_browsing_context.currently_focused_area()) { + auto top_level_browsing_context = old_focus_target->document().browsing_context()->top_level_browsing_context(); + if (auto currently_focused_area = top_level_browsing_context->currently_focused_area()) { if (shadow_root->is_shadow_including_ancestor_of(*currently_focused_area)) { old_focus_target = currently_focused_area; } @@ -238,10 +238,10 @@ void run_unfocusing_steps(DOM::Node* old_focus_target) // NOTE: HTMLAreaElement is currently missing the shapes property - auto& top_level_browsing_context = old_focus_target->document().browsing_context()->top_level_browsing_context(); + auto top_level_browsing_context = old_focus_target->document().browsing_context()->top_level_browsing_context(); // 4. Let old chain be the current focus chain of the top-level browsing context in which old focus target finds itself. - auto old_chain = focus_chain(top_level_browsing_context.currently_focused_area()); + auto old_chain = focus_chain(top_level_browsing_context->currently_focused_area()); // 5. If old focus target is not one of the entries in old chain, then return. for (auto& node : old_chain) { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index e02c0a9890..46c2d9b611 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -201,7 +201,7 @@ static void show_the_picker_if_applicable(HTMLInputElement& element) // FIXME: Pass along accept attribute information https://html.spec.whatwg.org/multipage/input.html#attr-input-accept // The accept attribute may be specified to provide user agents with a hint of what file types will be accepted. - element.document().browsing_context()->top_level_browsing_context().page()->client().page_did_request_file_picker(weak_element, multiple); + element.document().browsing_context()->top_level_browsing_context()->page()->client().page_did_request_file_picker(weak_element, multiple); return; } diff --git a/Userland/Libraries/LibWeb/HTML/NavigableContainer.cpp b/Userland/Libraries/LibWeb/HTML/NavigableContainer.cpp index d3ffa3ba6a..4af92389a2 100644 --- a/Userland/Libraries/LibWeb/HTML/NavigableContainer.cpp +++ b/Userland/Libraries/LibWeb/HTML/NavigableContainer.cpp @@ -64,7 +64,7 @@ WebIDL::ExceptionOr NavigableContainer::create_new_child_navigable() // 2. Let group be element's node document's browsing context's top-level browsing context's group. VERIFY(document().browsing_context()); - auto group = document().browsing_context()->top_level_browsing_context().group(); + auto group = document().browsing_context()->top_level_browsing_context()->group(); VERIFY(group); // 3. Let browsingContext and document be the result of creating a new browsing context and document given element's node document, element, and group. diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 832e42c7f9..76edd3381e 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -895,7 +895,7 @@ JS::GCPtr Window::top() const return {}; // 2. Return this's navigable's top-level traversable's active WindowProxy. - return browsing_context->top_level_browsing_context().window_proxy(); + return browsing_context->top_level_browsing_context()->window_proxy(); } // https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-parent diff --git a/Userland/Libraries/LibWeb/Internals/Internals.cpp b/Userland/Libraries/LibWeb/Internals/Internals.cpp index 1779e7d9ff..bba926c5d0 100644 --- a/Userland/Libraries/LibWeb/Internals/Internals.cpp +++ b/Userland/Libraries/LibWeb/Internals/Internals.cpp @@ -42,7 +42,7 @@ void Internals::gc() JS::Object* Internals::hit_test(double x, double y) { - auto* active_document = global_object().browsing_context()->top_level_browsing_context().active_document(); + auto* active_document = global_object().browsing_context()->top_level_browsing_context()->active_document(); // NOTE: Force a layout update just before hit testing. This is because the current layout tree, which is required // for stacking context traversal, might not exist if this call occurs between the tear_down_layout_tree() // and update_layout() calls diff --git a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp index 80aa391719..b359bbc1c8 100644 --- a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp +++ b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp @@ -155,7 +155,7 @@ Variant, JS::Handle, Empty> Intersection Variant, JS::Handle> IntersectionObserver::intersection_root() const { if (!m_root.has_value()) - return JS::make_handle(global_object().browsing_context()->top_level_browsing_context().active_document()); + return JS::make_handle(global_object().browsing_context()->top_level_browsing_context()->active_document()); return m_root.value(); }