From 528fa3bbdbf480303aee887f30a18a9a8933f5ac Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Fri, 25 Oct 2024 10:26:01 -0400 Subject: [PATCH] LibWeb: Add a NavigationObserver to be notified of navigable updates This contains a hook to be notified when a navigable navigation is complete, to be used by WebDriver. (cherry picked from commit 74ef9dc3936d678fdf811bb3c1b39a6ffba2b106) --- Userland/Libraries/LibWeb/CMakeLists.txt | 1 + Userland/Libraries/LibWeb/Forward.h | 1 + Userland/Libraries/LibWeb/HTML/Navigable.cpp | 21 +++++++++ Userland/Libraries/LibWeb/HTML/Navigable.h | 5 +++ .../LibWeb/HTML/NavigationObserver.cpp | 43 +++++++++++++++++++ .../LibWeb/HTML/NavigationObserver.h | 34 +++++++++++++++ 6 files changed, 105 insertions(+) create mode 100644 Userland/Libraries/LibWeb/HTML/NavigationObserver.cpp create mode 100644 Userland/Libraries/LibWeb/HTML/NavigationObserver.h diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 2fc4f7f6175..f0a9a0db4f8 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -410,6 +410,7 @@ set(SOURCES HTML/NavigationDestination.cpp HTML/NavigationCurrentEntryChangeEvent.cpp HTML/NavigationHistoryEntry.cpp + HTML/NavigationObserver.cpp HTML/NavigationParams.cpp HTML/NavigationTransition.cpp HTML/Navigator.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index db02cfe4f45..a3eaf6b87ed 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -490,6 +490,7 @@ class Navigation; class NavigationCurrentEntryChangeEvent; class NavigationDestination; class NavigationHistoryEntry; +class NavigationObserver; class NavigationTransition; class Navigator; class PageTransitionEvent; diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index 423ca68f7dc..22a4a85e966 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -124,6 +125,7 @@ void Navigable::visit_edges(Cell::Visitor& visitor) visitor.visit(m_current_session_history_entry); visitor.visit(m_active_session_history_entry); visitor.visit(m_container); + visitor.visit(m_navigation_observers); m_event_handler.visit_edges(visitor); } @@ -213,6 +215,13 @@ void Navigable::activate_history_entry(JS::GCPtr entry) // 5. Make active newDocument. new_document->make_active(); + + if (m_ongoing_navigation.has()) { + for (auto navigation_observer : m_navigation_observers) { + if (navigation_observer->navigation_complete()) + navigation_observer->navigation_complete()->function()(); + } + } } // https://html.spec.whatwg.org/multipage/document-sequences.html#nav-document @@ -2228,4 +2237,16 @@ void Navigable::paste(String const& text) m_event_handler.handle_paste(text); } +void Navigable::register_navigation_observer(Badge, NavigationObserver& navigation_observer) +{ + auto result = m_navigation_observers.set(navigation_observer); + VERIFY(result == AK::HashSetResult::InsertedNewEntry); +} + +void Navigable::unregister_navigation_observer(Badge, NavigationObserver& navigation_observer) +{ + bool was_removed = m_navigation_observers.remove(navigation_observer); + VERIFY(was_removed); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index b42fe28c1ac..b7265afbfe3 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -57,6 +57,9 @@ public: ErrorOr initialize_navigable(JS::NonnullGCPtr document_state, JS::GCPtr parent); + void register_navigation_observer(Badge, NavigationObserver&); + void unregister_navigation_observer(Badge, NavigationObserver&); + Vector> child_navigables() const; bool is_traversable() const; @@ -239,6 +242,8 @@ private: JS::NonnullGCPtr m_page; + HashTable> m_navigation_observers; + bool m_has_been_destroyed { false }; CSSPixelSize m_size; diff --git a/Userland/Libraries/LibWeb/HTML/NavigationObserver.cpp b/Userland/Libraries/LibWeb/HTML/NavigationObserver.cpp new file mode 100644 index 00000000000..7b95ccfa0e7 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigationObserver.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::HTML { + +JS_DEFINE_ALLOCATOR(NavigationObserver); + +NavigationObserver::NavigationObserver(JS::Realm& realm, Navigable& navigable) + : Bindings::PlatformObject(realm) + , m_navigable(navigable) +{ + m_navigable->register_navigation_observer({}, *this); +} + +void NavigationObserver::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_navigable); + visitor.visit(m_navigation_complete); +} + +void NavigationObserver::finalize() +{ + Base::finalize(); + m_navigable->unregister_navigation_observer({}, *this); +} + +void NavigationObserver::set_navigation_complete(Function callback) +{ + if (callback) + m_navigation_complete = JS::create_heap_function(vm().heap(), move(callback)); + else + m_navigation_complete = nullptr; +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/NavigationObserver.h b/Userland/Libraries/LibWeb/HTML/NavigationObserver.h new file mode 100644 index 00000000000..03be96d23b9 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigationObserver.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Web::HTML { + +class NavigationObserver final : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(NavigationObserver, Bindings::PlatformObject); + JS_DECLARE_ALLOCATOR(NavigationObserver); + +public: + [[nodiscard]] JS::GCPtr> navigation_complete() const { return m_navigation_complete; } + void set_navigation_complete(Function); + +private: + NavigationObserver(JS::Realm&, Navigable&); + + virtual void visit_edges(Cell::Visitor&) override; + virtual void finalize() override; + + JS::NonnullGCPtr m_navigable; + JS::GCPtr> m_navigation_complete; +}; + +}