summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2023-05-04 08:48:53 -0400
committerAndreas Kling <kling@serenityos.org>2023-05-04 16:48:10 +0200
commitf78eadf00f0b738ebd69a28e19890289cf184d9a (patch)
treeec4aea31527aea1d5536a8acb44bf70fb13a3f0b
parent88b89694433760da56a3e1e0684dc463fbfa76d5 (diff)
downloadserenity-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.txt3
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp21
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h5
-rw-r--r--Userland/Libraries/LibWeb/DOM/DocumentObserver.cpp32
-rw-r--r--Userland/Libraries/LibWeb/DOM/DocumentObserver.h31
-rw-r--r--Userland/Libraries/LibWeb/Forward.h1
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;