Bug 1850713: remove duplicated setting of early hint preloader id in `ScriptLoader...
[gecko.git] / accessible / html / HTMLElementAccessibles.cpp
blobe01de31ff24cae302d8f43e1885335c48c4c58ee
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "HTMLElementAccessibles.h"
8 #include "CacheConstants.h"
9 #include "nsCoreUtils.h"
10 #include "nsTextEquivUtils.h"
11 #include "Relation.h"
12 #include "mozilla/a11y/Role.h"
13 #include "States.h"
15 #include "mozilla/dom/HTMLLabelElement.h"
16 #include "mozilla/dom/HTMLDetailsElement.h"
17 #include "mozilla/dom/HTMLSummaryElement.h"
19 using namespace mozilla::a11y;
21 ////////////////////////////////////////////////////////////////////////////////
22 // HTMLHRAccessible
23 ////////////////////////////////////////////////////////////////////////////////
25 role HTMLHRAccessible::NativeRole() const { return roles::SEPARATOR; }
27 ////////////////////////////////////////////////////////////////////////////////
28 // HTMLBRAccessible
29 ////////////////////////////////////////////////////////////////////////////////
31 role HTMLBRAccessible::NativeRole() const { return roles::WHITESPACE; }
33 uint64_t HTMLBRAccessible::NativeState() const { return states::READONLY; }
35 ENameValueFlag HTMLBRAccessible::NativeName(nsString& aName) const {
36 aName = static_cast<char16_t>('\n'); // Newline char
37 return eNameOK;
40 ////////////////////////////////////////////////////////////////////////////////
41 // HTMLLabelAccessible
42 ////////////////////////////////////////////////////////////////////////////////
44 ENameValueFlag HTMLLabelAccessible::NativeName(nsString& aName) const {
45 nsTextEquivUtils::GetNameFromSubtree(this, aName);
46 return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
49 Relation HTMLLabelAccessible::RelationByType(RelationType aType) const {
50 Relation rel = AccessibleWrap::RelationByType(aType);
51 if (aType == RelationType::LABEL_FOR) {
52 dom::HTMLLabelElement* label = dom::HTMLLabelElement::FromNode(mContent);
53 rel.AppendTarget(mDoc, label->GetControl());
56 return rel;
59 void HTMLLabelAccessible::DOMAttributeChanged(int32_t aNameSpaceID,
60 nsAtom* aAttribute,
61 int32_t aModType,
62 const nsAttrValue* aOldValue,
63 uint64_t aOldState) {
64 HyperTextAccessible::DOMAttributeChanged(aNameSpaceID, aAttribute, aModType,
65 aOldValue, aOldState);
67 if (aAttribute == nsGkAtoms::_for) {
68 mDoc->QueueCacheUpdate(this, CacheDomain::Relations | CacheDomain::Actions);
72 bool HTMLLabelAccessible::HasPrimaryAction() const {
73 return nsCoreUtils::IsLabelWithControl(mContent);
76 void HTMLLabelAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
77 if (aIndex == 0) {
78 if (HasPrimaryAction()) {
79 aName.AssignLiteral("click");
84 ////////////////////////////////////////////////////////////////////////////////
85 // nsHTMLOuputAccessible
86 ////////////////////////////////////////////////////////////////////////////////
88 Relation HTMLOutputAccessible::RelationByType(RelationType aType) const {
89 Relation rel = AccessibleWrap::RelationByType(aType);
90 if (aType == RelationType::CONTROLLED_BY) {
91 rel.AppendIter(new IDRefsIterator(mDoc, mContent, nsGkAtoms::_for));
94 return rel;
97 void HTMLOutputAccessible::DOMAttributeChanged(int32_t aNameSpaceID,
98 nsAtom* aAttribute,
99 int32_t aModType,
100 const nsAttrValue* aOldValue,
101 uint64_t aOldState) {
102 HyperTextAccessible::DOMAttributeChanged(aNameSpaceID, aAttribute, aModType,
103 aOldValue, aOldState);
105 if (aAttribute == nsGkAtoms::_for) {
106 mDoc->QueueCacheUpdate(this, CacheDomain::Relations);
110 ////////////////////////////////////////////////////////////////////////////////
111 // HTMLSummaryAccessible
112 ////////////////////////////////////////////////////////////////////////////////
114 HTMLSummaryAccessible::HTMLSummaryAccessible(nsIContent* aContent,
115 DocAccessible* aDoc)
116 : HyperTextAccessible(aContent, aDoc) {
117 mGenericTypes |= eButton;
120 bool HTMLSummaryAccessible::HasPrimaryAction() const { return true; }
122 void HTMLSummaryAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
123 if (aIndex != eAction_Click) {
124 return;
127 dom::HTMLSummaryElement* summary =
128 dom::HTMLSummaryElement::FromNode(mContent);
129 if (!summary) {
130 return;
133 dom::HTMLDetailsElement* details = summary->GetDetails();
134 if (!details) {
135 return;
138 if (details->Open()) {
139 aName.AssignLiteral("collapse");
140 } else {
141 aName.AssignLiteral("expand");
145 uint64_t HTMLSummaryAccessible::NativeState() const {
146 uint64_t state = HyperTextAccessible::NativeState();
148 dom::HTMLSummaryElement* summary =
149 dom::HTMLSummaryElement::FromNode(mContent);
150 if (!summary) {
151 return state;
154 dom::HTMLDetailsElement* details = summary->GetDetails();
155 if (!details) {
156 return state;
159 if (details->Open()) {
160 state |= states::EXPANDED;
161 } else {
162 state |= states::COLLAPSED;
165 return state;
168 HTMLSummaryAccessible* HTMLSummaryAccessible::FromDetails(
169 LocalAccessible* details) {
170 if (!dom::HTMLDetailsElement::FromNodeOrNull(details->GetContent())) {
171 return nullptr;
174 HTMLSummaryAccessible* summaryAccessible = nullptr;
175 for (uint32_t i = 0; i < details->ChildCount(); i++) {
176 // Iterate through the children of our details accessible to locate main
177 // summary. This iteration includes the anonymous summary if the details
178 // element was not explicitly created with one.
179 LocalAccessible* child = details->LocalChildAt(i);
180 auto* summary =
181 mozilla::dom::HTMLSummaryElement::FromNodeOrNull(child->GetContent());
182 if (summary && summary->IsMainSummary()) {
183 summaryAccessible = static_cast<HTMLSummaryAccessible*>(child);
184 break;
188 return summaryAccessible;
191 ////////////////////////////////////////////////////////////////////////////////
192 // HTMLSummaryAccessible: Widgets
194 bool HTMLSummaryAccessible::IsWidget() const { return true; }
196 ////////////////////////////////////////////////////////////////////////////////
197 // HTMLHeaderOrFooterAccessible
198 ////////////////////////////////////////////////////////////////////////////////
200 role HTMLHeaderOrFooterAccessible::NativeRole() const {
201 // Only map header and footer if they are direct descendants of the body tag.
202 // If other sectioning or sectioning root elements, they become sections.
203 nsIContent* parent = mContent->GetParent();
204 while (parent) {
205 if (parent->IsAnyOfHTMLElements(
206 nsGkAtoms::article, nsGkAtoms::aside, nsGkAtoms::nav,
207 nsGkAtoms::section, nsGkAtoms::main, nsGkAtoms::blockquote,
208 nsGkAtoms::details, nsGkAtoms::dialog, nsGkAtoms::fieldset,
209 nsGkAtoms::figure, nsGkAtoms::td)) {
210 break;
212 parent = parent->GetParent();
215 // No sectioning or sectioning root elements found.
216 if (!parent) {
217 return roles::LANDMARK;
220 return roles::SECTION;
223 ////////////////////////////////////////////////////////////////////////////////
224 // HTMLSectionAccessible
225 ////////////////////////////////////////////////////////////////////////////////
227 role HTMLSectionAccessible::NativeRole() const {
228 nsAutoString name;
229 const_cast<HTMLSectionAccessible*>(this)->Name(name);
230 return name.IsEmpty() ? roles::SECTION : roles::REGION;