summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonah <jonahshafran@gmail.com>2022-12-11 10:56:37 -0600
committerSam Atkins <atkinssj@gmail.com>2023-01-07 10:51:53 +0000
commita469bbd1786db749e63f081fc7e0fe193f37090b (patch)
treea038d54b7d51997f554b1c0cd4fb0636e1957739
parent3eef54823ab4f718009ecedf212431e59c0426ab (diff)
downloadserenity-a469bbd1786db749e63f081fc7e0fe193f37090b.zip
LibWeb: Add Functionality to Dump to Accessibility Tree
This will be used to display the accessibility tree in the inspector.
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp19
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h2
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.cpp45
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.h4
4 files changed, 70 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp
index da9e71952b..8c9b24b247 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Document.cpp
@@ -2338,4 +2338,23 @@ JS::NonnullGCPtr<DOM::Document> Document::appropriate_template_contents_owner_do
return *this;
}
+DeprecatedString Document::dump_accessibility_tree_as_json()
+{
+ StringBuilder builder;
+ auto accessibility_tree = AccessibilityTreeNode::create(this, nullptr);
+ build_accessibility_tree(*&accessibility_tree);
+ auto json = MUST(JsonObjectSerializer<>::try_create(builder));
+
+ // Empty document
+ if (!accessibility_tree->value()) {
+ MUST(json.add("type"sv, "element"sv));
+ MUST(json.add("role"sv, "document"sv));
+ } else {
+ accessibility_tree->serialize_tree_as_json(json);
+ }
+
+ MUST(json.finish());
+ return builder.to_deprecated_string();
+}
+
}
diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h
index 6f2946a8e6..2278959b61 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.h
+++ b/Userland/Libraries/LibWeb/DOM/Document.h
@@ -447,6 +447,8 @@ public:
bool query_command_supported(DeprecatedString const&) const;
+ DeprecatedString dump_accessibility_tree_as_json();
+
protected:
virtual void visit_edges(Cell::Visitor&) override;
diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp
index 735ab0e1f2..2929682465 100644
--- a/Userland/Libraries/LibWeb/DOM/Node.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Node.cpp
@@ -29,6 +29,7 @@
#include <LibWeb/DOM/StaticNodeList.h>
#include <LibWeb/HTML/BrowsingContextContainer.h>
#include <LibWeb/HTML/HTMLAnchorElement.h>
+#include <LibWeb/HTML/HTMLStyleElement.h>
#include <LibWeb/HTML/Origin.h>
#include <LibWeb/HTML/Parser/HTMLParser.h>
#include <LibWeb/Layout/InitialContainingBlock.h>
@@ -1542,4 +1543,48 @@ bool Node::is_following(Node const& other) const
return false;
}
+void Node::build_accessibility_tree(AccessibilityTreeNode& parent) const
+{
+ if (is_uninteresting_whitespace_node())
+ return;
+
+ if (is_document()) {
+ auto const* document = static_cast<DOM::Document const*>(this);
+ auto const* document_element = document->document_element();
+ if (document_element) {
+ parent.set_value(document_element);
+ if (document_element->has_child_nodes())
+ document_element->for_each_child([&parent](DOM::Node const& child) {
+ child.build_accessibility_tree(parent);
+ });
+ }
+ } else if (is_element()) {
+ auto const* element = static_cast<DOM::Element const*>(this);
+
+ if (is<HTML::HTMLScriptElement>(element) || is<HTML::HTMLStyleElement>(element))
+ return;
+
+ if (element->include_in_accessibility_tree()) {
+ auto current_node = AccessibilityTreeNode::create(const_cast<Document*>(&this->document()), this);
+ parent.append_child(current_node);
+ if (has_child_nodes()) {
+ for_each_child([&current_node](DOM::Node& child) {
+ child.build_accessibility_tree(*current_node);
+ });
+ }
+ } else if (has_child_nodes()) {
+ for_each_child([&parent](DOM::Node& child) {
+ child.build_accessibility_tree(parent);
+ });
+ }
+ } else if (is_text()) {
+ parent.append_child(AccessibilityTreeNode::create(const_cast<Document*>(&this->document()), this));
+ if (has_child_nodes()) {
+ for_each_child([&parent](DOM::Node& child) {
+ child.build_accessibility_tree(parent);
+ });
+ }
+ }
+}
+
}
diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h
index ef70f68f36..01bfbe6cea 100644
--- a/Userland/Libraries/LibWeb/DOM/Node.h
+++ b/Userland/Libraries/LibWeb/DOM/Node.h
@@ -12,6 +12,8 @@
#include <AK/RefPtr.h>
#include <AK/TypeCasts.h>
#include <AK/Vector.h>
+#include <LibWeb/DOM/ARIARoleNames.h>
+#include <LibWeb/DOM/AccessibilityTreeNode.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/DOMParsing/XMLSerializer.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
@@ -640,6 +642,8 @@ protected:
// "Nodes have a strong reference to registered observers in their registered observer list." https://dom.spec.whatwg.org/#garbage-collection
Vector<RegisteredObserver&> m_registered_observer_list;
+ void build_accessibility_tree(AccessibilityTreeNode& parent) const;
+
private:
void queue_tree_mutation_record(JS::NonnullGCPtr<NodeList> added_nodes, JS::NonnullGCPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling);