diff options
author | Jonah <jonahshafran@gmail.com> | 2022-12-11 10:56:37 -0600 |
---|---|---|
committer | Sam Atkins <atkinssj@gmail.com> | 2023-01-07 10:51:53 +0000 |
commit | a469bbd1786db749e63f081fc7e0fe193f37090b (patch) | |
tree | a038d54b7d51997f554b1c0cd4fb0636e1957739 /Userland/Libraries/LibWeb/DOM | |
parent | 3eef54823ab4f718009ecedf212431e59c0426ab (diff) | |
download | serenity-a469bbd1786db749e63f081fc7e0fe193f37090b.zip |
LibWeb: Add Functionality to Dump to Accessibility Tree
This will be used to display the accessibility tree in the inspector.
Diffstat (limited to 'Userland/Libraries/LibWeb/DOM')
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.cpp | 19 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Node.cpp | 45 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Node.h | 4 |
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([¤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<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); |