Bug 1867925 - Mark some storage-access-api tests as intermittent after wpt-sync....
[gecko.git] / accessible / base / HTMLMarkupMap.h
blob74ed09b6272cea857911396d9c3bd34111c5da49
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 MARKUPMAP(
9 a,
10 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
11 // An anchor element without an href attribute and without a click
12 // listener should be a generic.
13 if (!aElement->HasAttr(nsGkAtoms::href) &&
14 !nsCoreUtils::HasClickListener(aElement)) {
15 return new HyperTextAccessible(aElement, aContext->Document());
17 // Only some roles truly enjoy life as HTMLLinkAccessibles, for
18 // details see closed bug 494807.
19 const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aElement);
20 if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
21 roleMapEntry->role != roles::LINK) {
22 return new HyperTextAccessible(aElement, aContext->Document());
25 return new HTMLLinkAccessible(aElement, aContext->Document());
29 MARKUPMAP(abbr, New_HyperText, 0)
31 MARKUPMAP(acronym, New_HyperText, 0)
33 MARKUPMAP(address, New_HyperText, roles::GROUPING)
35 MARKUPMAP(article, New_HyperText, roles::ARTICLE, Attr(xmlroles, article))
37 MARKUPMAP(aside, New_HyperText, roles::LANDMARK)
39 MARKUPMAP(blockquote, New_HyperText, roles::BLOCKQUOTE)
41 MARKUPMAP(
42 button,
43 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
44 return new HTMLButtonAccessible(aElement, aContext->Document());
48 MARKUPMAP(
49 caption,
50 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
51 if (aContext->IsTable()) {
52 dom::HTMLTableElement* tableEl =
53 dom::HTMLTableElement::FromNode(aContext->GetContent());
54 if (tableEl && tableEl == aElement->GetParent() &&
55 tableEl->GetCaption() == aElement) {
56 return new HTMLCaptionAccessible(aElement, aContext->Document());
59 return nullptr;
63 MARKUPMAP(code, New_HyperText, roles::CODE)
65 MARKUPMAP(dd, New_HTMLDtOrDd<HyperTextAccessible>, roles::DEFINITION)
67 MARKUPMAP(del, New_HyperText, roles::CONTENT_DELETION)
69 MARKUPMAP(details, New_HyperText, roles::DETAILS)
71 MARKUPMAP(dialog, New_HyperText, roles::DIALOG)
73 MARKUPMAP(
74 div,
75 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
76 // Never create an accessible if we're part of an anonymous
77 // subtree.
78 if (aElement->IsInNativeAnonymousSubtree()) {
79 return nullptr;
81 // Always create an accessible if the div has an id.
82 if (aElement->HasAttr(nsGkAtoms::id)) {
83 return new HyperTextAccessible(aElement, aContext->Document());
85 // Never create an accessible if the div is not display:block; or
86 // display:inline-block or the like.
87 nsIFrame* f = aElement->GetPrimaryFrame();
88 if (!f || !f->IsBlockFrameOrSubclass()) {
89 return nullptr;
91 // Check for various conditions to determine if this is a block
92 // break and needs to be rendered.
93 // If its previous sibling is an inline element, we probably want
94 // to break, so render.
95 // FIXME: This looks extremely incorrect in presence of shadow DOM,
96 // display: contents, and what not.
97 nsIContent* prevSibling = aElement->GetPreviousSibling();
98 if (prevSibling) {
99 nsIFrame* prevSiblingFrame = prevSibling->GetPrimaryFrame();
100 if (prevSiblingFrame && prevSiblingFrame->IsInlineOutside()) {
101 return new HyperTextAccessible(aElement, aContext->Document());
104 // Now, check the children.
105 nsIContent* firstChild = aElement->GetFirstChild();
106 if (firstChild) {
107 nsIFrame* firstChildFrame = firstChild->GetPrimaryFrame();
108 if (!firstChildFrame) {
109 // The first child is invisible, but this might be due to an
110 // invisible text node. Try the next.
111 firstChild = firstChild->GetNextSibling();
112 if (!firstChild) {
113 // If there's no next sibling, there's only one child, so there's
114 // nothing more we can do.
115 return nullptr;
117 firstChildFrame = firstChild->GetPrimaryFrame();
119 // Check to see if first child has an inline frame.
120 if (firstChildFrame && firstChildFrame->IsInlineOutside()) {
121 return new HyperTextAccessible(aElement, aContext->Document());
123 nsIContent* lastChild = aElement->GetLastChild();
124 MOZ_ASSERT(lastChild);
125 if (lastChild != firstChild) {
126 nsIFrame* lastChildFrame = lastChild->GetPrimaryFrame();
127 if (!lastChildFrame) {
128 // The last child is invisible, but this might be due to an
129 // invisible text node. Try the next.
130 lastChild = lastChild->GetPreviousSibling();
131 MOZ_ASSERT(lastChild);
132 if (lastChild == firstChild) {
133 return nullptr;
135 lastChildFrame = lastChild->GetPrimaryFrame();
137 // Check to see if last child has an inline frame.
138 if (lastChildFrame && lastChildFrame->IsInlineOutside()) {
139 return new HyperTextAccessible(aElement, aContext->Document());
143 return nullptr;
145 roles::SECTION)
147 MARKUPMAP(
149 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
150 return new HTMLListAccessible(aElement, aContext->Document());
152 roles::DEFINITION_LIST)
154 MARKUPMAP(dt, New_HTMLDtOrDd<HTMLLIAccessible>, roles::TERM)
156 MARKUPMAP(
157 figcaption,
158 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
159 return new HTMLFigcaptionAccessible(aElement, aContext->Document());
161 roles::CAPTION)
163 MARKUPMAP(
164 figure,
165 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
166 return new HTMLFigureAccessible(aElement, aContext->Document());
168 roles::FIGURE, Attr(xmlroles, figure))
170 MARKUPMAP(
171 fieldset,
172 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
173 return new HTMLGroupboxAccessible(aElement, aContext->Document());
177 MARKUPMAP(
178 form,
179 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
180 return new HTMLFormAccessible(aElement, aContext->Document());
184 MARKUPMAP(
185 footer,
186 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
187 return new HTMLHeaderOrFooterAccessible(aElement, aContext->Document());
191 MARKUPMAP(
192 header,
193 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
194 return new HTMLHeaderOrFooterAccessible(aElement, aContext->Document());
198 MARKUPMAP(h1, New_HyperText, roles::HEADING)
200 MARKUPMAP(h2, New_HyperText, roles::HEADING)
202 MARKUPMAP(h3, New_HyperText, roles::HEADING)
204 MARKUPMAP(h4, New_HyperText, roles::HEADING)
206 MARKUPMAP(h5, New_HyperText, roles::HEADING)
208 MARKUPMAP(h6, New_HyperText, roles::HEADING)
210 MARKUPMAP(
212 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
213 return new HTMLHRAccessible(aElement, aContext->Document());
217 MARKUPMAP(
218 input,
219 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
220 // TODO(emilio): This would be faster if it used
221 // HTMLInputElement's already-parsed representation.
222 if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
223 nsGkAtoms::checkbox, eIgnoreCase)) {
224 return new CheckboxAccessible(aElement, aContext->Document());
226 if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
227 nsGkAtoms::image, eIgnoreCase)) {
228 return new HTMLButtonAccessible(aElement, aContext->Document());
230 if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
231 nsGkAtoms::radio, eIgnoreCase)) {
232 return new HTMLRadioButtonAccessible(aElement, aContext->Document());
234 if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
235 nsGkAtoms::time, eIgnoreCase)) {
236 return new HTMLDateTimeAccessible<roles::TIME_EDITOR>(
237 aElement, aContext->Document());
239 if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
240 nsGkAtoms::date, eIgnoreCase) ||
241 aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
242 nsGkAtoms::datetime_local, eIgnoreCase)) {
243 return new HTMLDateTimeAccessible<roles::DATE_EDITOR>(
244 aElement, aContext->Document());
246 return nullptr;
250 MARKUPMAP(ins, New_HyperText, roles::CONTENT_INSERTION)
252 MARKUPMAP(
253 label,
254 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
255 return new HTMLLabelAccessible(aElement, aContext->Document());
257 roles::LABEL)
259 MARKUPMAP(
260 legend,
261 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
262 return new HTMLLegendAccessible(aElement, aContext->Document());
264 roles::LABEL)
266 MARKUPMAP(
268 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
269 // If list item is a child of accessible list then create an
270 // accessible for it unconditionally by tag name. nsBlockFrame
271 // creates the list item accessible for other elements styled as
272 // list items.
273 if (aContext->IsList() &&
274 aContext->GetContent() == aElement->GetParent()) {
275 return new HTMLLIAccessible(aElement, aContext->Document());
278 return nullptr;
282 MARKUPMAP(main, New_HyperText, roles::LANDMARK)
284 MARKUPMAP(map, nullptr, roles::TEXT_CONTAINER)
286 MARKUPMAP(mark, New_HyperText, roles::MARK, Attr(xmlroles, mark))
288 MARKUPMAP(
289 menu,
290 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
291 return new HTMLListAccessible(aElement, aContext->Document());
293 roles::LIST)
295 MARKUPMAP(nav, New_HyperText, roles::LANDMARK)
297 MARKUPMAP(
299 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
300 return new HTMLListAccessible(aElement, aContext->Document());
302 roles::LIST)
304 MARKUPMAP(
305 option,
306 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
307 return new HTMLSelectOptionAccessible(aElement, aContext->Document());
311 MARKUPMAP(
312 optgroup,
313 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
314 return new HTMLSelectOptGroupAccessible(aElement, aContext->Document());
318 MARKUPMAP(
319 output,
320 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
321 return new HTMLOutputAccessible(aElement, aContext->Document());
323 roles::STATUSBAR, Attr(aria_live, polite))
325 MARKUPMAP(p, nullptr, roles::PARAGRAPH)
327 MARKUPMAP(
328 progress,
329 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
330 return new HTMLProgressAccessible(aElement, aContext->Document());
334 MARKUPMAP(q, New_HyperText, 0)
336 MARKUPMAP(s, New_HyperText, roles::CONTENT_DELETION)
338 MARKUPMAP(
339 section,
340 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
341 return new HTMLSectionAccessible(aElement, aContext->Document());
345 MARKUPMAP(sub, New_HyperText, roles::SUBSCRIPT)
347 MARKUPMAP(
348 summary,
349 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
350 return new HTMLSummaryAccessible(aElement, aContext->Document());
352 roles::SUMMARY)
354 MARKUPMAP(sup, New_HyperText, roles::SUPERSCRIPT)
356 MARKUPMAP(
357 table,
358 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
359 return new HTMLTableAccessible(aElement, aContext->Document());
361 roles::TABLE)
363 MARKUPMAP(time, New_HyperText, 0, Attr(xmlroles, time),
364 AttrFromDOM(datetime, datetime))
366 MARKUPMAP(tbody, nullptr, roles::GROUPING)
368 MARKUPMAP(
370 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
371 if (!aContext->IsHTMLTableRow()) {
372 return nullptr;
374 if (aElement->HasAttr(nsGkAtoms::scope)) {
375 return new HTMLTableHeaderCellAccessible(aElement,
376 aContext->Document());
378 return new HTMLTableCellAccessible(aElement, aContext->Document());
382 MARKUPMAP(tfoot, nullptr, roles::GROUPING)
384 MARKUPMAP(
386 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
387 if (!aContext->IsHTMLTableRow()) {
388 return nullptr;
390 return new HTMLTableHeaderCellAccessible(aElement, aContext->Document());
394 MARKUPMAP(thead, nullptr, roles::GROUPING)
396 MARKUPMAP(
398 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
399 if (aContext->IsTableRow()) {
400 // A <tr> within a row isn't valid.
401 return nullptr;
403 const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aElement);
404 if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
405 roleMapEntry->role != roles::ROW) {
406 // There is a valid ARIA role which isn't "row". Don't treat this as an
407 // HTML table row.
408 return nullptr;
410 // Check if this <tr> is within a table. We check the grandparent because
411 // it might be inside a rowgroup. We don't specifically check for an HTML
412 // table because there are cases where there is a <tr> inside a
413 // <div role="table"> such as Monorail.
414 if (aContext->IsTable() ||
415 (aContext->LocalParent() && aContext->LocalParent()->IsTable())) {
416 return new HTMLTableRowAccessible(aElement, aContext->Document());
418 return nullptr;
420 roles::ROW)
422 MARKUPMAP(
424 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
425 return new HTMLListAccessible(aElement, aContext->Document());
427 roles::LIST)
429 MARKUPMAP(
430 meter,
431 [](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
432 return new HTMLMeterAccessible(aElement, aContext->Document());
434 roles::METER)
436 MARKUPMAP(search, New_HyperText, roles::LANDMARK)