From a469bbd1786db749e63f081fc7e0fe193f37090b Mon Sep 17 00:00:00 2001 From: Jonah Date: Sun, 11 Dec 2022 10:56:37 -0600 Subject: LibWeb: Add Functionality to Dump to Accessibility Tree This will be used to display the accessibility tree in the inspector. --- Userland/Libraries/LibWeb/DOM/Document.cpp | 19 +++++++++++++ Userland/Libraries/LibWeb/DOM/Document.h | 2 ++ Userland/Libraries/LibWeb/DOM/Node.cpp | 45 ++++++++++++++++++++++++++++++ Userland/Libraries/LibWeb/DOM/Node.h | 4 +++ 4 files changed, 70 insertions(+) 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 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 #include #include +#include #include #include #include @@ -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(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(this); + + if (is(element) || is(element)) + return; + + if (element->include_in_accessibility_tree()) { + auto current_node = AccessibilityTreeNode::create(const_cast(&this->document()), this); + parent.append_child(current_node); + if (has_child_nodes()) { + for_each_child([¤t_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(&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 #include #include +#include +#include #include #include #include @@ -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 m_registered_observer_list; + void build_accessibility_tree(AccessibilityTreeNode& parent) const; + private: void queue_tree_mutation_record(JS::NonnullGCPtr added_nodes, JS::NonnullGCPtr removed_nodes, Node* previous_sibling, Node* next_sibling); -- cgit v1.2.3