| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/AccessibilityTreeNode.h>
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Document.h>
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Element.h>
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Node.h>
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Text.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Web::DOM { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-19 19:47:52 +01:00
										 |  |  | JS_DEFINE_ALLOCATOR(AccessibilityTreeNode); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-13 13:05:26 +02:00
										 |  |  | JS::NonnullGCPtr<AccessibilityTreeNode> AccessibilityTreeNode::create(Document* document, DOM::Node const* value) | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-13 13:05:26 +02:00
										 |  |  |     return document->heap().allocate<AccessibilityTreeNode>(document->realm(), value); | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-25 10:44:51 -07:00
										 |  |  | AccessibilityTreeNode::AccessibilityTreeNode(JS::GCPtr<DOM::Node const> value) | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  |     : m_value(value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_children = {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-05 11:24:03 -06:00
										 |  |  | void AccessibilityTreeNode::serialize_tree_as_json(JsonObjectSerializer<StringBuilder>& object, Document const& document) const | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  | { | 
					
						
							|  |  |  |     if (value()->is_document()) { | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } else if (value()->is_element()) { | 
					
						
							| 
									
										
										
										
											2023-02-25 10:44:51 -07:00
										 |  |  |         auto const* element = static_cast<DOM::Element const*>(value().ptr()); | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (element->include_in_accessibility_tree()) { | 
					
						
							|  |  |  |             MUST(object.add("type"sv, "element"sv)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto role = element->role_or_default(); | 
					
						
							| 
									
										
										
										
											2023-01-28 22:23:16 +00:00
										 |  |  |             bool has_role = role.has_value() && !ARIA::is_abstract_role(*role); | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-05 11:24:03 -06:00
										 |  |  |             auto name = MUST(element->accessible_name(document)); | 
					
						
							|  |  |  |             MUST(object.add("name"sv, name)); | 
					
						
							|  |  |  |             auto description = MUST(element->accessible_description(document)); | 
					
						
							|  |  |  |             MUST(object.add("description"sv, description)); | 
					
						
							| 
									
										
										
										
											2023-11-02 14:30:00 +01:00
										 |  |  |             MUST(object.add("id"sv, element->unique_id())); | 
					
						
							| 
									
										
										
										
											2023-02-05 11:24:03 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  |             if (has_role) | 
					
						
							| 
									
										
										
										
											2023-01-28 22:23:16 +00:00
										 |  |  |                 MUST(object.add("role"sv, ARIA::role_name(*role))); | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  |             else | 
					
						
							|  |  |  |                 MUST(object.add("role"sv, ""sv)); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } else if (value()->is_text()) { | 
					
						
							|  |  |  |         MUST(object.add("type"sv, "text"sv)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-25 10:44:51 -07:00
										 |  |  |         auto const* text_node = static_cast<DOM::Text const*>(value().ptr()); | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  |         MUST(object.add("text"sv, text_node->data())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (value()->has_child_nodes()) { | 
					
						
							|  |  |  |         auto node_children = MUST(object.add_array("children"sv)); | 
					
						
							| 
									
										
										
										
											2023-02-26 16:09:02 -07:00
										 |  |  |         for (auto& child : children()) { | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  |             if (child->value()->is_uninteresting_whitespace_node()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             JsonObjectSerializer<StringBuilder> child_object = MUST(node_children.add_object()); | 
					
						
							| 
									
										
										
										
											2023-02-05 11:24:03 -06:00
										 |  |  |             child->serialize_tree_as_json(child_object, document); | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  |             MUST(child_object.finish()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         MUST(node_children.finish()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AccessibilityTreeNode::visit_edges(Visitor& visitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Base::visit_edges(visitor); | 
					
						
							| 
									
										
										
										
											2023-03-21 10:08:44 -07:00
										 |  |  |     visitor.visit(m_value); | 
					
						
							| 
									
										
										
										
											2024-04-15 13:58:21 +02:00
										 |  |  |     visitor.visit(m_children); | 
					
						
							| 
									
										
										
										
											2022-12-11 12:38:27 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |