diff options
author | Timothy Flynn <trflynn89@pm.me> | 2023-05-04 08:48:53 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-04 16:48:10 +0200 |
commit | f78eadf00f0b738ebd69a28e19890289cf184d9a (patch) | |
tree | ec4aea31527aea1d5536a8acb44bf70fb13a3f0b | |
parent | 88b89694433760da56a3e1e0684dc463fbfa76d5 (diff) | |
download | serenity-f78eadf00f0b738ebd69a28e19890289cf184d9a.zip |
LibWeb: Add an interface to be notified of Document state changes
Some HTML elements, e.g. HTMLMediaElement, need to take action when the
document becomes inactive.
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/DocumentObserver.cpp | 32 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/DocumentObserver.h | 31 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 1 |
6 files changed, 92 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 946d6d32f1..42d47c9f0c 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -126,9 +126,10 @@ set(SOURCES DOM/DOMTokenList.cpp DOM/DOMTokenList.idl DOM/Document.cpp - DOM/DocumentLoading.cpp DOM/DocumentFragment.cpp DOM/DocumentLoadEventDelayer.cpp + DOM/DocumentLoading.cpp + DOM/DocumentObserver.cpp DOM/DocumentType.cpp DOM/Element.cpp DOM/ElementFactory.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 0709bef0b9..a2c780a57f 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -23,6 +23,7 @@ #include <LibWeb/DOM/DOMImplementation.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/DocumentFragment.h> +#include <LibWeb/DOM/DocumentObserver.h> #include <LibWeb/DOM/DocumentType.h> #include <LibWeb/DOM/Element.h> #include <LibWeb/DOM/ElementFactory.h> @@ -371,6 +372,9 @@ void Document::visit_edges(Cell::Visitor& visitor) for (auto& node_iterator : m_node_iterators) visitor.visit(node_iterator); + for (auto& document_observer : m_document_observers) + visitor.visit(document_observer); + for (auto& target : m_pending_scroll_event_targets) visitor.visit(target); for (auto& target : m_pending_scrollend_event_targets) @@ -2032,6 +2036,18 @@ void Document::unregister_node_iterator(Badge<NodeIterator>, NodeIterator& node_ VERIFY(was_removed); } +void Document::register_document_observer(Badge<DocumentObserver>, DocumentObserver& document_observer) +{ + auto result = m_document_observers.set(document_observer); + VERIFY(result == AK::HashSetResult::InsertedNewEntry); +} + +void Document::unregister_document_observer(Badge<DocumentObserver>, DocumentObserver& document_observer) +{ + bool was_removed = m_document_observers.remove(document_observer); + VERIFY(was_removed); +} + void Document::increment_number_of_things_delaying_the_load_event(Badge<DocumentLoadEventDelayer>) { ++m_number_of_things_delaying_the_load_event; @@ -2437,6 +2453,11 @@ bool Document::is_allowed_to_use_feature(PolicyControlledFeature feature) const void Document::did_stop_being_active_document_in_browsing_context(Badge<HTML::BrowsingContext>) { tear_down_layout_tree(); + + for (auto& document_observer : m_document_observers) { + if (document_observer->document_became_inactive) + document_observer->document_became_inactive(); + } } // https://w3c.github.io/editing/docs/execCommand/#querycommandsupported() diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index f76ba77b46..b3a922200c 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -394,6 +394,9 @@ public: void register_node_iterator(Badge<NodeIterator>, NodeIterator&); void unregister_node_iterator(Badge<NodeIterator>, NodeIterator&); + void register_document_observer(Badge<DocumentObserver>, DocumentObserver&); + void unregister_document_observer(Badge<DocumentObserver>, DocumentObserver&); + template<typename Callback> void for_each_node_iterator(Callback callback) { @@ -588,6 +591,8 @@ private: HashTable<JS::GCPtr<NodeIterator>> m_node_iterators; + HashTable<JS::NonnullGCPtr<DocumentObserver>> m_document_observers; + // https://html.spec.whatwg.org/multipage/dom.html#is-initial-about:blank bool m_is_initial_about_blank { false }; diff --git a/Userland/Libraries/LibWeb/DOM/DocumentObserver.cpp b/Userland/Libraries/LibWeb/DOM/DocumentObserver.cpp new file mode 100644 index 0000000000..7ca2642af9 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/DocumentObserver.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Runtime/Realm.h> +#include <LibWeb/DOM/Document.h> +#include <LibWeb/DOM/DocumentObserver.h> + +namespace Web::DOM { + +DocumentObserver::DocumentObserver(JS::Realm& realm, DOM::Document& document) + : Bindings::PlatformObject(realm) + , m_document(document) +{ + m_document->register_document_observer({}, *this); +} + +void DocumentObserver::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_document); +} + +void DocumentObserver::finalize() +{ + Base::finalize(); + m_document->unregister_document_observer({}, *this); +} + +} diff --git a/Userland/Libraries/LibWeb/DOM/DocumentObserver.h b/Userland/Libraries/LibWeb/DOM/DocumentObserver.h new file mode 100644 index 0000000000..1378a2db05 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/DocumentObserver.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Forward.h> +#include <LibJS/SafeFunction.h> +#include <LibWeb/Bindings/PlatformObject.h> +#include <LibWeb/Forward.h> + +namespace Web::DOM { + +class DocumentObserver final : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(DocumentObserver, Bindings::PlatformObject); + +public: + JS::SafeFunction<void()> document_became_inactive; + +private: + explicit DocumentObserver(JS::Realm&, DOM::Document&); + + virtual void visit_edges(Cell::Visitor&) override; + virtual void finalize() override; + + JS::NonnullGCPtr<DOM::Document> m_document; +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 03df51f5a4..ba9687a466 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -189,6 +189,7 @@ class CustomEvent; class Document; class DocumentFragment; class DocumentLoadEventDelayer; +class DocumentObserver; class DocumentType; class DOMEventListener; class DOMImplementation; |