Serenity Operating System
1/*
2 * Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Tuple.h>
8#include <LibWeb/DOM/AccessibilityTreeNode.h>
9#include <LibWeb/DOM/Document.h>
10#include <LibWeb/DOM/Element.h>
11#include <LibWeb/DOM/Node.h>
12#include <LibWeb/DOM/Text.h>
13
14namespace Web::DOM {
15
16WebIDL::ExceptionOr<JS::NonnullGCPtr<AccessibilityTreeNode>> AccessibilityTreeNode::create(Document* document, DOM::Node const* value)
17{
18 return MUST_OR_THROW_OOM(document->heap().allocate<AccessibilityTreeNode>(document->realm(), value));
19}
20
21AccessibilityTreeNode::AccessibilityTreeNode(JS::GCPtr<DOM::Node const> value)
22 : m_value(value)
23{
24 m_children = {};
25}
26
27void AccessibilityTreeNode::serialize_tree_as_json(JsonObjectSerializer<StringBuilder>& object, Document const& document) const
28{
29 if (value()->is_document()) {
30 VERIFY_NOT_REACHED();
31 } else if (value()->is_element()) {
32 auto const* element = static_cast<DOM::Element const*>(value().ptr());
33
34 if (element->include_in_accessibility_tree()) {
35 MUST(object.add("type"sv, "element"sv));
36
37 auto role = element->role_or_default();
38 bool has_role = role.has_value() && !ARIA::is_abstract_role(*role);
39
40 auto name = MUST(element->accessible_name(document));
41 MUST(object.add("name"sv, name));
42 auto description = MUST(element->accessible_description(document));
43 MUST(object.add("description"sv, description));
44
45 if (has_role)
46 MUST(object.add("role"sv, ARIA::role_name(*role)));
47 else
48 MUST(object.add("role"sv, ""sv));
49 } else {
50 VERIFY_NOT_REACHED();
51 }
52
53 } else if (value()->is_text()) {
54 MUST(object.add("type"sv, "text"sv));
55
56 auto const* text_node = static_cast<DOM::Text const*>(value().ptr());
57 MUST(object.add("text"sv, text_node->data()));
58 }
59
60 if (value()->has_child_nodes()) {
61 auto node_children = MUST(object.add_array("children"sv));
62 for (auto* child : children()) {
63 if (child->value()->is_uninteresting_whitespace_node())
64 continue;
65 JsonObjectSerializer<StringBuilder> child_object = MUST(node_children.add_object());
66 child->serialize_tree_as_json(child_object, document);
67 MUST(child_object.finish());
68 }
69 MUST(node_children.finish());
70 }
71}
72
73void AccessibilityTreeNode::visit_edges(Visitor& visitor)
74{
75 Base::visit_edges(visitor);
76 visitor.visit(value());
77 for (auto child : children())
78 child->visit_edges(visitor);
79}
80
81}