Bug 1877642 - Disable browser_fullscreen-tab-close-race.js on apple_silicon !debug...
[gecko.git] / accessible / base / ARIAMap.cpp
blobd53592acf025ea35baaa49e0cb3c0fb6652356dd
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 #include "ARIAMap.h"
10 #include "AccAttributes.h"
11 #include "nsAccUtils.h"
12 #include "nsCoreUtils.h"
13 #include "mozilla/a11y/Role.h"
14 #include "States.h"
16 #include "nsAttrName.h"
17 #include "nsWhitespaceTokenizer.h"
19 #include "mozilla/BinarySearch.h"
20 #include "mozilla/dom/Element.h"
22 #include "nsUnicharUtils.h"
24 using namespace mozilla;
25 using namespace mozilla::a11y;
26 using namespace mozilla::a11y::aria;
28 static const uint32_t kGenericAccType = 0;
30 /**
31 * This list of WAI-defined roles are currently hardcoded.
32 * Eventually we will most likely be loading an RDF resource that contains this
33 * information Using RDF will also allow for role extensibility. See bug 280138.
35 * Definition of nsRoleMapEntry contains comments explaining this table.
37 * When no Role enum mapping exists for an ARIA role, the role will be exposed
38 * via the object attribute "xml-roles".
40 * Note: the list must remain alphabetically ordered to support binary search.
43 static const nsRoleMapEntry sWAIRoleMaps[] = {
44 // clang-format off
45 { // alert
46 nsGkAtoms::alert,
47 roles::ALERT,
48 kUseMapRole,
49 eNoValue,
50 eNoAction,
51 #if defined(XP_MACOSX)
52 eAssertiveLiveAttr,
53 #else
54 eNoLiveAttr,
55 #endif
56 eAlert,
57 kNoReqStates
59 { // alertdialog
60 nsGkAtoms::alertdialog,
61 roles::DIALOG,
62 kUseMapRole,
63 eNoValue,
64 eNoAction,
65 eNoLiveAttr,
66 kGenericAccType,
67 kNoReqStates
69 { // application
70 nsGkAtoms::application,
71 roles::APPLICATION,
72 kUseMapRole,
73 eNoValue,
74 eNoAction,
75 eNoLiveAttr,
76 eLandmark,
77 kNoReqStates
79 { // article
80 nsGkAtoms::article,
81 roles::ARTICLE,
82 kUseMapRole,
83 eNoValue,
84 eNoAction,
85 eNoLiveAttr,
86 kGenericAccType,
87 kNoReqStates,
88 eReadonlyUntilEditable
90 { // banner
91 nsGkAtoms::banner,
92 roles::LANDMARK,
93 kUseMapRole,
94 eNoValue,
95 eNoAction,
96 eNoLiveAttr,
97 eLandmark,
98 kNoReqStates
100 { // blockquote
101 nsGkAtoms::blockquote,
102 roles::BLOCKQUOTE,
103 kUseMapRole,
104 eNoValue,
105 eNoAction,
106 eNoLiveAttr,
107 kGenericAccType,
109 { // button
110 nsGkAtoms::button,
111 roles::PUSHBUTTON,
112 kUseMapRole,
113 eNoValue,
114 ePressAction,
115 eNoLiveAttr,
116 eButton,
117 kNoReqStates
118 // eARIAPressed is auto applied on any button
120 { // caption
121 nsGkAtoms::caption,
122 roles::CAPTION,
123 kUseMapRole,
124 eNoValue,
125 eNoAction,
126 eNoLiveAttr,
127 kGenericAccType,
129 { // cell
130 nsGkAtoms::cell,
131 roles::CELL,
132 kUseMapRole,
133 eNoValue,
134 eNoAction,
135 eNoLiveAttr,
136 eTableCell,
137 kNoReqStates
139 { // checkbox
140 nsGkAtoms::checkbox,
141 roles::CHECKBUTTON,
142 kUseMapRole,
143 eNoValue,
144 eCheckUncheckAction,
145 eNoLiveAttr,
146 kGenericAccType,
147 kNoReqStates,
148 eARIACheckableMixed,
149 eARIAReadonly
151 { // code
152 nsGkAtoms::code,
153 roles::CODE,
154 kUseMapRole,
155 eNoValue,
156 eNoAction,
157 eNoLiveAttr,
158 kGenericAccType,
160 { // columnheader
161 nsGkAtoms::columnheader,
162 roles::COLUMNHEADER,
163 kUseMapRole,
164 eNoValue,
165 eSortAction,
166 eNoLiveAttr,
167 eTableCell,
168 kNoReqStates,
169 eARIASelectableIfDefined,
170 eARIAReadonly
172 { // combobox, which consists of text input and popup
173 nsGkAtoms::combobox,
174 roles::EDITCOMBOBOX,
175 kUseMapRole,
176 eNoValue,
177 eOpenCloseAction,
178 eNoLiveAttr,
179 eCombobox,
180 states::COLLAPSED | states::HASPOPUP,
181 eARIAAutoComplete,
182 eARIAReadonly,
183 eARIAOrientation
185 { // comment
186 nsGkAtoms::comment,
187 roles::COMMENT,
188 kUseMapRole,
189 eNoValue,
190 eNoAction,
191 eNoLiveAttr,
192 kGenericAccType,
194 { // complementary
195 nsGkAtoms::complementary,
196 roles::LANDMARK,
197 kUseMapRole,
198 eNoValue,
199 eNoAction,
200 eNoLiveAttr,
201 eLandmark,
202 kNoReqStates
204 { // contentinfo
205 nsGkAtoms::contentinfo,
206 roles::LANDMARK,
207 kUseMapRole,
208 eNoValue,
209 eNoAction,
210 eNoLiveAttr,
211 eLandmark,
212 kNoReqStates
214 { // definition
215 nsGkAtoms::definition,
216 roles::DEFINITION,
217 kUseMapRole,
218 eNoValue,
219 eNoAction,
220 eNoLiveAttr,
221 kGenericAccType,
223 { // deletion
224 nsGkAtoms::deletion,
225 roles::CONTENT_DELETION,
226 kUseMapRole,
227 eNoValue,
228 eNoAction,
229 eNoLiveAttr,
230 kGenericAccType,
232 { // dialog
233 nsGkAtoms::dialog,
234 roles::DIALOG,
235 kUseMapRole,
236 eNoValue,
237 eNoAction,
238 eNoLiveAttr,
239 kGenericAccType,
240 kNoReqStates
242 { // directory
243 nsGkAtoms::directory,
244 roles::LIST,
245 kUseMapRole,
246 eNoValue,
247 eNoAction,
248 eNoLiveAttr,
249 eList,
250 states::READONLY
252 { // doc-abstract
253 nsGkAtoms::docAbstract,
254 roles::SECTION,
255 kUseMapRole,
256 eNoValue,
257 eNoAction,
258 eNoLiveAttr,
259 kGenericAccType,
260 kNoReqStates
262 { // doc-acknowledgments
263 nsGkAtoms::docAcknowledgments,
264 roles::LANDMARK,
265 kUseMapRole,
266 eNoValue,
267 eNoAction,
268 eNoLiveAttr,
269 eLandmark,
270 kNoReqStates
272 { // doc-afterword
273 nsGkAtoms::docAfterword,
274 roles::LANDMARK,
275 kUseMapRole,
276 eNoValue,
277 eNoAction,
278 eNoLiveAttr,
279 eLandmark,
280 kNoReqStates
282 { // doc-appendix
283 nsGkAtoms::docAppendix,
284 roles::LANDMARK,
285 kUseMapRole,
286 eNoValue,
287 eNoAction,
288 eNoLiveAttr,
289 eLandmark,
290 kNoReqStates
292 { // doc-backlink
293 nsGkAtoms::docBacklink,
294 roles::LINK,
295 kUseMapRole,
296 eNoValue,
297 eJumpAction,
298 eNoLiveAttr,
299 kGenericAccType,
300 states::LINKED
302 { // doc-biblioentry
303 nsGkAtoms::docBiblioentry,
304 roles::LISTITEM,
305 kUseMapRole,
306 eNoValue,
307 eNoAction,
308 eNoLiveAttr,
309 kGenericAccType,
310 states::READONLY
312 { // doc-bibliography
313 nsGkAtoms::docBibliography,
314 roles::LANDMARK,
315 kUseMapRole,
316 eNoValue,
317 eNoAction,
318 eNoLiveAttr,
319 eLandmark,
320 kNoReqStates
322 { // doc-biblioref
323 nsGkAtoms::docBiblioref,
324 roles::LINK,
325 kUseMapRole,
326 eNoValue,
327 eJumpAction,
328 eNoLiveAttr,
329 kGenericAccType,
330 states::LINKED
332 { // doc-chapter
333 nsGkAtoms::docChapter,
334 roles::LANDMARK,
335 kUseMapRole,
336 eNoValue,
337 eNoAction,
338 eNoLiveAttr,
339 eLandmark,
340 kNoReqStates
342 { // doc-colophon
343 nsGkAtoms::docColophon,
344 roles::SECTION,
345 kUseMapRole,
346 eNoValue,
347 eNoAction,
348 eNoLiveAttr,
349 kGenericAccType,
350 kNoReqStates
352 { // doc-conclusion
353 nsGkAtoms::docConclusion,
354 roles::LANDMARK,
355 kUseMapRole,
356 eNoValue,
357 eNoAction,
358 eNoLiveAttr,
359 eLandmark,
360 kNoReqStates
362 { // doc-cover
363 nsGkAtoms::docCover,
364 roles::GRAPHIC,
365 kUseMapRole,
366 eNoValue,
367 eNoAction,
368 eNoLiveAttr,
369 kGenericAccType,
370 kNoReqStates
372 { // doc-credit
373 nsGkAtoms::docCredit,
374 roles::SECTION,
375 kUseMapRole,
376 eNoValue,
377 eNoAction,
378 eNoLiveAttr,
379 kGenericAccType,
380 kNoReqStates
382 { // doc-credits
383 nsGkAtoms::docCredits,
384 roles::LANDMARK,
385 kUseMapRole,
386 eNoValue,
387 eNoAction,
388 eNoLiveAttr,
389 eLandmark,
390 kNoReqStates
392 { // doc-dedication
393 nsGkAtoms::docDedication,
394 roles::SECTION,
395 kUseMapRole,
396 eNoValue,
397 eNoAction,
398 eNoLiveAttr,
399 kGenericAccType,
400 kNoReqStates
402 { // doc-endnote
403 nsGkAtoms::docEndnote,
404 roles::LISTITEM,
405 kUseMapRole,
406 eNoValue,
407 eNoAction,
408 eNoLiveAttr,
409 kGenericAccType,
410 states::READONLY
412 { // doc-endnotes
413 nsGkAtoms::docEndnotes,
414 roles::LANDMARK,
415 kUseMapRole,
416 eNoValue,
417 eNoAction,
418 eNoLiveAttr,
419 eLandmark,
420 kNoReqStates
422 { // doc-epigraph
423 nsGkAtoms::docEpigraph,
424 roles::SECTION,
425 kUseMapRole,
426 eNoValue,
427 eNoAction,
428 eNoLiveAttr,
429 kGenericAccType,
430 kNoReqStates
432 { // doc-epilogue
433 nsGkAtoms::docEpilogue,
434 roles::LANDMARK,
435 kUseMapRole,
436 eNoValue,
437 eNoAction,
438 eNoLiveAttr,
439 eLandmark,
440 kNoReqStates
442 { // doc-errata
443 nsGkAtoms::docErrata,
444 roles::LANDMARK,
445 kUseMapRole,
446 eNoValue,
447 eNoAction,
448 eNoLiveAttr,
449 eLandmark,
450 kNoReqStates
452 { // doc-example
453 nsGkAtoms::docExample,
454 roles::SECTION,
455 kUseMapRole,
456 eNoValue,
457 eNoAction,
458 eNoLiveAttr,
459 kGenericAccType,
460 kNoReqStates
462 { // doc-footnote
463 nsGkAtoms::docFootnote,
464 roles::FOOTNOTE,
465 kUseMapRole,
466 eNoValue,
467 eNoAction,
468 eNoLiveAttr,
469 eLandmark,
470 kNoReqStates
472 { // doc-foreword
473 nsGkAtoms::docForeword,
474 roles::LANDMARK,
475 kUseMapRole,
476 eNoValue,
477 eNoAction,
478 eNoLiveAttr,
479 eLandmark,
480 kNoReqStates
482 { // doc-glossary
483 nsGkAtoms::docGlossary,
484 roles::LANDMARK,
485 kUseMapRole,
486 eNoValue,
487 eNoAction,
488 eNoLiveAttr,
489 eLandmark,
490 kNoReqStates
492 { // doc-glossref
493 nsGkAtoms::docGlossref,
494 roles::LINK,
495 kUseMapRole,
496 eNoValue,
497 eJumpAction,
498 eNoLiveAttr,
499 kGenericAccType,
500 states::LINKED
502 { // doc-index
503 nsGkAtoms::docIndex,
504 roles::NAVIGATION,
505 kUseMapRole,
506 eNoValue,
507 eNoAction,
508 eNoLiveAttr,
509 eLandmark,
510 kNoReqStates
512 { // doc-introduction
513 nsGkAtoms::docIntroduction,
514 roles::LANDMARK,
515 kUseMapRole,
516 eNoValue,
517 eNoAction,
518 eNoLiveAttr,
519 eLandmark,
520 kNoReqStates
522 { // doc-noteref
523 nsGkAtoms::docNoteref,
524 roles::LINK,
525 kUseMapRole,
526 eNoValue,
527 eJumpAction,
528 eNoLiveAttr,
529 kGenericAccType,
530 states::LINKED
532 { // doc-notice
533 nsGkAtoms::docNotice,
534 roles::NOTE,
535 kUseMapRole,
536 eNoValue,
537 eNoAction,
538 eNoLiveAttr,
539 kGenericAccType,
540 kNoReqStates
542 { // doc-pagebreak
543 nsGkAtoms::docPagebreak,
544 roles::SEPARATOR,
545 kUseMapRole,
546 eNoValue,
547 eNoAction,
548 eNoLiveAttr,
549 kGenericAccType,
550 kNoReqStates
552 { // doc-pagelist
553 nsGkAtoms::docPagelist,
554 roles::NAVIGATION,
555 kUseMapRole,
556 eNoValue,
557 eNoAction,
558 eNoLiveAttr,
559 eLandmark,
560 kNoReqStates
562 { // doc-part
563 nsGkAtoms::docPart,
564 roles::LANDMARK,
565 kUseMapRole,
566 eNoValue,
567 eNoAction,
568 eNoLiveAttr,
569 eLandmark,
570 kNoReqStates
572 { // doc-preface
573 nsGkAtoms::docPreface,
574 roles::LANDMARK,
575 kUseMapRole,
576 eNoValue,
577 eNoAction,
578 eNoLiveAttr,
579 eLandmark,
580 kNoReqStates
582 { // doc-prologue
583 nsGkAtoms::docPrologue,
584 roles::LANDMARK,
585 kUseMapRole,
586 eNoValue,
587 eNoAction,
588 eNoLiveAttr,
589 eLandmark,
590 kNoReqStates
592 { // doc-pullquote
593 nsGkAtoms::docPullquote,
594 roles::SECTION,
595 kUseMapRole,
596 eNoValue,
597 eNoAction,
598 eNoLiveAttr,
599 kGenericAccType,
600 kNoReqStates
602 { // doc-qna
603 nsGkAtoms::docQna,
604 roles::SECTION,
605 kUseMapRole,
606 eNoValue,
607 eNoAction,
608 eNoLiveAttr,
609 kGenericAccType,
610 kNoReqStates
612 { // doc-subtitle
613 nsGkAtoms::docSubtitle,
614 roles::HEADING,
615 kUseMapRole,
616 eNoValue,
617 eNoAction,
618 eNoLiveAttr,
619 kGenericAccType,
620 kNoReqStates
622 { // doc-tip
623 nsGkAtoms::docTip,
624 roles::NOTE,
625 kUseMapRole,
626 eNoValue,
627 eNoAction,
628 eNoLiveAttr,
629 kGenericAccType,
630 kNoReqStates
632 { // doc-toc
633 nsGkAtoms::docToc,
634 roles::NAVIGATION,
635 kUseMapRole,
636 eNoValue,
637 eNoAction,
638 eNoLiveAttr,
639 eLandmark,
640 kNoReqStates
642 { // document
643 nsGkAtoms::document,
644 roles::NON_NATIVE_DOCUMENT,
645 kUseMapRole,
646 eNoValue,
647 eNoAction,
648 eNoLiveAttr,
649 kGenericAccType,
650 kNoReqStates,
651 eReadonlyUntilEditable
653 { // emphasis
654 nsGkAtoms::emphasis,
655 roles::EMPHASIS,
656 kUseMapRole,
657 eNoValue,
658 eNoAction,
659 eNoLiveAttr,
660 kGenericAccType,
661 kNoReqStates
663 { // feed
664 nsGkAtoms::feed,
665 roles::GROUPING,
666 kUseMapRole,
667 eNoValue,
668 eNoAction,
669 eNoLiveAttr,
670 kGenericAccType,
671 kNoReqStates
673 { // figure
674 nsGkAtoms::figure,
675 roles::FIGURE,
676 kUseMapRole,
677 eNoValue,
678 eNoAction,
679 eNoLiveAttr,
680 kGenericAccType,
681 kNoReqStates
683 { // form
684 nsGkAtoms::form,
685 roles::FORM,
686 kUseMapRole,
687 eNoValue,
688 eNoAction,
689 eNoLiveAttr,
690 eLandmark,
691 kNoReqStates
693 { // generic
694 nsGkAtoms::generic,
695 roles::SECTION,
696 kUseMapRole,
697 eNoValue,
698 eNoAction,
699 eNoLiveAttr,
700 kGenericAccType,
701 kNoReqStates
703 { // graphics-document
704 nsGkAtoms::graphicsDocument,
705 roles::NON_NATIVE_DOCUMENT,
706 kUseMapRole,
707 eNoValue,
708 eNoAction,
709 eNoLiveAttr,
710 kGenericAccType,
711 kNoReqStates,
712 eReadonlyUntilEditable
714 { // graphics-object
715 nsGkAtoms::graphicsObject,
716 roles::GROUPING,
717 kUseMapRole,
718 eNoValue,
719 eNoAction,
720 eNoLiveAttr,
721 kGenericAccType,
722 kNoReqStates
724 { // graphics-symbol
725 nsGkAtoms::graphicsSymbol,
726 roles::GRAPHIC,
727 kUseMapRole,
728 eNoValue,
729 eNoAction,
730 eNoLiveAttr,
731 kGenericAccType,
732 kNoReqStates
734 { // grid
735 nsGkAtoms::grid,
736 roles::GRID,
737 kUseMapRole,
738 eNoValue,
739 eNoAction,
740 eNoLiveAttr,
741 eSelect | eTable,
742 kNoReqStates,
743 eARIAMultiSelectable,
744 eARIAReadonly,
745 eFocusableUntilDisabled
747 { // gridcell
748 nsGkAtoms::gridcell,
749 roles::GRID_CELL,
750 kUseMapRole,
751 eNoValue,
752 eNoAction,
753 eNoLiveAttr,
754 eTableCell,
755 kNoReqStates,
756 eARIASelectable,
757 eARIAReadonly
759 { // group
760 nsGkAtoms::group,
761 roles::GROUPING,
762 kUseMapRole,
763 eNoValue,
764 eNoAction,
765 eNoLiveAttr,
766 kGenericAccType,
767 kNoReqStates
769 { // heading
770 nsGkAtoms::heading,
771 roles::HEADING,
772 kUseMapRole,
773 eNoValue,
774 eNoAction,
775 eNoLiveAttr,
776 kGenericAccType,
777 kNoReqStates
779 { // image
780 nsGkAtoms::image,
781 roles::GRAPHIC,
782 kUseMapRole,
783 eNoValue,
784 eNoAction,
785 eNoLiveAttr,
786 kGenericAccType,
787 kNoReqStates
789 { // img
790 nsGkAtoms::img,
791 roles::GRAPHIC,
792 kUseMapRole,
793 eNoValue,
794 eNoAction,
795 eNoLiveAttr,
796 kGenericAccType,
797 kNoReqStates
799 { // insertion
800 nsGkAtoms::insertion,
801 roles::CONTENT_INSERTION,
802 kUseMapRole,
803 eNoValue,
804 eNoAction,
805 eNoLiveAttr,
806 kGenericAccType,
808 { // key
809 nsGkAtoms::key,
810 roles::KEY,
811 kUseMapRole,
812 eNoValue,
813 ePressAction,
814 eNoLiveAttr,
815 kGenericAccType,
816 kNoReqStates,
817 eARIAPressed
819 { // link
820 nsGkAtoms::link,
821 roles::LINK,
822 kUseMapRole,
823 eNoValue,
824 eJumpAction,
825 eNoLiveAttr,
826 kGenericAccType,
827 states::LINKED
829 { // list
830 nsGkAtoms::list_,
831 roles::LIST,
832 kUseMapRole,
833 eNoValue,
834 eNoAction,
835 eNoLiveAttr,
836 eList,
837 states::READONLY
839 { // listbox
840 nsGkAtoms::listbox,
841 roles::LISTBOX,
842 kUseMapRole,
843 eNoValue,
844 eNoAction,
845 eNoLiveAttr,
846 eListControl | eSelect,
847 states::VERTICAL,
848 eARIAMultiSelectable,
849 eARIAReadonly,
850 eFocusableUntilDisabled,
851 eARIAOrientation
853 { // listitem
854 nsGkAtoms::listitem,
855 roles::LISTITEM,
856 kUseMapRole,
857 eNoValue,
858 eNoAction, // XXX: should depend on state, parent accessible
859 eNoLiveAttr,
860 kGenericAccType,
861 states::READONLY
863 { // log
864 nsGkAtoms::log_,
865 roles::NOTHING,
866 kUseNativeRole,
867 eNoValue,
868 eNoAction,
869 ePoliteLiveAttr,
870 kGenericAccType,
871 kNoReqStates
873 { // main
874 nsGkAtoms::main,
875 roles::LANDMARK,
876 kUseMapRole,
877 eNoValue,
878 eNoAction,
879 eNoLiveAttr,
880 eLandmark,
881 kNoReqStates
883 { // mark
884 nsGkAtoms::mark,
885 roles::MARK,
886 kUseMapRole,
887 eNoValue,
888 eNoAction,
889 eNoLiveAttr,
890 kGenericAccType,
892 { // marquee
893 nsGkAtoms::marquee,
894 roles::ANIMATION,
895 kUseMapRole,
896 eNoValue,
897 eNoAction,
898 eOffLiveAttr,
899 kGenericAccType,
900 kNoReqStates
902 { // math
903 nsGkAtoms::math,
904 roles::FLAT_EQUATION,
905 kUseMapRole,
906 eNoValue,
907 eNoAction,
908 eNoLiveAttr,
909 kGenericAccType,
910 kNoReqStates
912 { // menu
913 nsGkAtoms::menu,
914 roles::MENUPOPUP,
915 kUseMapRole,
916 eNoValue,
917 eNoAction, // XXX: technically accessibles of menupopup role haven't
918 // any action, but menu can be open or close.
919 eNoLiveAttr,
920 kGenericAccType,
921 states::VERTICAL,
922 eARIAOrientation
924 { // menubar
925 nsGkAtoms::menubar,
926 roles::MENUBAR,
927 kUseMapRole,
928 eNoValue,
929 eNoAction,
930 eNoLiveAttr,
931 kGenericAccType,
932 states::HORIZONTAL,
933 eARIAOrientation
935 { // menuitem
936 nsGkAtoms::menuitem,
937 roles::MENUITEM,
938 kUseMapRole,
939 eNoValue,
940 eClickAction,
941 eNoLiveAttr,
942 kGenericAccType,
943 kNoReqStates
945 { // menuitemcheckbox
946 nsGkAtoms::menuitemcheckbox,
947 roles::CHECK_MENU_ITEM,
948 kUseMapRole,
949 eNoValue,
950 eClickAction,
951 eNoLiveAttr,
952 kGenericAccType,
953 kNoReqStates,
954 eARIACheckableMixed,
955 eARIAReadonly
957 { // menuitemradio
958 nsGkAtoms::menuitemradio,
959 roles::RADIO_MENU_ITEM,
960 kUseMapRole,
961 eNoValue,
962 eClickAction,
963 eNoLiveAttr,
964 kGenericAccType,
965 kNoReqStates,
966 eARIACheckableBool,
967 eARIAReadonly
969 { // meter
970 nsGkAtoms::meter,
971 roles::METER,
972 kUseMapRole,
973 eHasValueMinMax,
974 eNoAction,
975 eNoLiveAttr,
976 kGenericAccType,
977 states::READONLY
979 { // navigation
980 nsGkAtoms::navigation,
981 roles::LANDMARK,
982 kUseMapRole,
983 eNoValue,
984 eNoAction,
985 eNoLiveAttr,
986 eLandmark,
987 kNoReqStates
989 { // none
990 nsGkAtoms::none,
991 roles::NOTHING,
992 kUseMapRole,
993 eNoValue,
994 eNoAction,
995 eNoLiveAttr,
996 kGenericAccType,
997 kNoReqStates
999 { // note
1000 nsGkAtoms::note_,
1001 roles::NOTE,
1002 kUseMapRole,
1003 eNoValue,
1004 eNoAction,
1005 eNoLiveAttr,
1006 kGenericAccType,
1007 kNoReqStates
1009 { // option
1010 nsGkAtoms::option,
1011 roles::OPTION,
1012 kUseMapRole,
1013 eNoValue,
1014 eSelectAction,
1015 eNoLiveAttr,
1016 kGenericAccType,
1017 kNoReqStates,
1018 eARIASelectable,
1019 eARIACheckedMixed
1021 { // paragraph
1022 nsGkAtoms::paragraph,
1023 roles::PARAGRAPH,
1024 kUseMapRole,
1025 eNoValue,
1026 eNoAction,
1027 eNoLiveAttr,
1028 kGenericAccType,
1030 { // presentation
1031 nsGkAtoms::presentation,
1032 roles::NOTHING,
1033 kUseMapRole,
1034 eNoValue,
1035 eNoAction,
1036 eNoLiveAttr,
1037 kGenericAccType,
1038 kNoReqStates
1040 { // progressbar
1041 nsGkAtoms::progressbar,
1042 roles::PROGRESSBAR,
1043 kUseMapRole,
1044 eHasValueMinMax,
1045 eNoAction,
1046 eNoLiveAttr,
1047 kGenericAccType,
1048 states::READONLY,
1049 eIndeterminateIfNoValue
1051 { // radio
1052 nsGkAtoms::radio,
1053 roles::RADIOBUTTON,
1054 kUseMapRole,
1055 eNoValue,
1056 eSelectAction,
1057 eNoLiveAttr,
1058 kGenericAccType,
1059 kNoReqStates,
1060 eARIACheckableBool
1062 { // radiogroup
1063 nsGkAtoms::radiogroup,
1064 roles::RADIO_GROUP,
1065 kUseMapRole,
1066 eNoValue,
1067 eNoAction,
1068 eNoLiveAttr,
1069 kGenericAccType,
1070 kNoReqStates,
1071 eARIAOrientation,
1072 eARIAReadonly
1074 { // region
1075 nsGkAtoms::region,
1076 roles::REGION,
1077 kUseMapRole,
1078 eNoValue,
1079 eNoAction,
1080 eNoLiveAttr,
1081 eLandmark,
1082 kNoReqStates
1084 { // row
1085 nsGkAtoms::row,
1086 roles::ROW,
1087 kUseMapRole,
1088 eNoValue,
1089 eNoAction,
1090 eNoLiveAttr,
1091 eTableRow,
1092 kNoReqStates,
1093 eARIASelectable
1095 { // rowgroup
1096 nsGkAtoms::rowgroup,
1097 roles::ROWGROUP,
1098 kUseMapRole,
1099 eNoValue,
1100 eNoAction,
1101 eNoLiveAttr,
1102 kGenericAccType,
1103 kNoReqStates
1105 { // rowheader
1106 nsGkAtoms::rowheader,
1107 roles::ROWHEADER,
1108 kUseMapRole,
1109 eNoValue,
1110 eSortAction,
1111 eNoLiveAttr,
1112 eTableCell,
1113 kNoReqStates,
1114 eARIASelectableIfDefined,
1115 eARIAReadonly
1117 { // scrollbar
1118 nsGkAtoms::scrollbar,
1119 roles::SCROLLBAR,
1120 kUseMapRole,
1121 eHasValueMinMax,
1122 eNoAction,
1123 eNoLiveAttr,
1124 kGenericAccType,
1125 states::VERTICAL,
1126 eARIAOrientation,
1127 eARIAReadonly
1129 { // search
1130 nsGkAtoms::search,
1131 roles::LANDMARK,
1132 kUseMapRole,
1133 eNoValue,
1134 eNoAction,
1135 eNoLiveAttr,
1136 eLandmark,
1137 kNoReqStates
1139 { // searchbox
1140 nsGkAtoms::searchbox,
1141 roles::ENTRY,
1142 kUseMapRole,
1143 eNoValue,
1144 eActivateAction,
1145 eNoLiveAttr,
1146 kGenericAccType,
1147 kNoReqStates,
1148 eARIAAutoComplete,
1149 eARIAMultiline,
1150 eARIAReadonlyOrEditable
1152 { // separator
1153 nsGkAtoms::separator_,
1154 roles::SEPARATOR,
1155 kUseMapRole,
1156 eHasValueMinMaxIfFocusable,
1157 eNoAction,
1158 eNoLiveAttr,
1159 kGenericAccType,
1160 states::HORIZONTAL,
1161 eARIAOrientation
1163 { // slider
1164 nsGkAtoms::slider,
1165 roles::SLIDER,
1166 kUseMapRole,
1167 eHasValueMinMax,
1168 eNoAction,
1169 eNoLiveAttr,
1170 kGenericAccType,
1171 states::HORIZONTAL,
1172 eARIAOrientation,
1173 eARIAReadonly
1175 { // spinbutton
1176 nsGkAtoms::spinbutton,
1177 roles::SPINBUTTON,
1178 kUseMapRole,
1179 eHasValueMinMax,
1180 eNoAction,
1181 eNoLiveAttr,
1182 kGenericAccType,
1183 kNoReqStates,
1184 eARIAReadonly
1186 { // status
1187 nsGkAtoms::status,
1188 roles::STATUSBAR,
1189 kUseMapRole,
1190 eNoValue,
1191 eNoAction,
1192 ePoliteLiveAttr,
1193 kGenericAccType,
1194 kNoReqStates
1196 { // strong
1197 nsGkAtoms::strong,
1198 roles::STRONG,
1199 kUseMapRole,
1200 eNoValue,
1201 eNoAction,
1202 eNoLiveAttr,
1203 kGenericAccType,
1204 kNoReqStates
1206 { // subscript
1207 nsGkAtoms::subscript,
1208 roles::SUBSCRIPT,
1209 kUseMapRole,
1210 eNoValue,
1211 eNoAction,
1212 eNoLiveAttr,
1213 kGenericAccType
1215 { // suggestion
1216 nsGkAtoms::suggestion,
1217 roles::SUGGESTION,
1218 kUseMapRole,
1219 eNoValue,
1220 eNoAction,
1221 eNoLiveAttr,
1222 kGenericAccType,
1224 { // superscript
1225 nsGkAtoms::superscript,
1226 roles::SUPERSCRIPT,
1227 kUseMapRole,
1228 eNoValue,
1229 eNoAction,
1230 eNoLiveAttr,
1231 kGenericAccType
1233 { // switch
1234 nsGkAtoms::svgSwitch,
1235 roles::SWITCH,
1236 kUseMapRole,
1237 eNoValue,
1238 eCheckUncheckAction,
1239 eNoLiveAttr,
1240 kGenericAccType,
1241 kNoReqStates,
1242 eARIACheckableBool,
1243 eARIAReadonly
1245 { // tab
1246 nsGkAtoms::tab,
1247 roles::PAGETAB,
1248 kUseMapRole,
1249 eNoValue,
1250 eSwitchAction,
1251 eNoLiveAttr,
1252 kGenericAccType,
1253 kNoReqStates,
1254 eARIASelectable
1256 { // table
1257 nsGkAtoms::table,
1258 roles::TABLE,
1259 kUseMapRole,
1260 eNoValue,
1261 eNoAction,
1262 eNoLiveAttr,
1263 eTable,
1264 kNoReqStates,
1265 eARIASelectable
1267 { // tablist
1268 nsGkAtoms::tablist,
1269 roles::PAGETABLIST,
1270 kUseMapRole,
1271 eNoValue,
1272 eNoAction,
1273 eNoLiveAttr,
1274 eSelect,
1275 states::HORIZONTAL,
1276 eARIAOrientation,
1277 eARIAMultiSelectable
1279 { // tabpanel
1280 nsGkAtoms::tabpanel,
1281 roles::PROPERTYPAGE,
1282 kUseMapRole,
1283 eNoValue,
1284 eNoAction,
1285 eNoLiveAttr,
1286 kGenericAccType,
1287 kNoReqStates
1289 { // term
1290 nsGkAtoms::term,
1291 roles::TERM,
1292 kUseMapRole,
1293 eNoValue,
1294 eNoAction,
1295 eNoLiveAttr,
1296 kGenericAccType,
1297 states::READONLY
1299 { // textbox
1300 nsGkAtoms::textbox,
1301 roles::ENTRY,
1302 kUseMapRole,
1303 eNoValue,
1304 eActivateAction,
1305 eNoLiveAttr,
1306 kGenericAccType,
1307 kNoReqStates,
1308 eARIAAutoComplete,
1309 eARIAMultiline,
1310 eARIAReadonlyOrEditable
1312 { // time
1313 nsGkAtoms::time,
1314 roles::TIME,
1315 kUseMapRole,
1316 eNoValue,
1317 eNoAction,
1318 eNoLiveAttr,
1319 kNoReqStates
1321 { // timer
1322 nsGkAtoms::timer,
1323 roles::NOTHING,
1324 kUseNativeRole,
1325 eNoValue,
1326 eNoAction,
1327 eOffLiveAttr,
1328 kNoReqStates
1330 { // toolbar
1331 nsGkAtoms::toolbar,
1332 roles::TOOLBAR,
1333 kUseMapRole,
1334 eNoValue,
1335 eNoAction,
1336 eNoLiveAttr,
1337 kGenericAccType,
1338 states::HORIZONTAL,
1339 eARIAOrientation
1341 { // tooltip
1342 nsGkAtoms::tooltip,
1343 roles::TOOLTIP,
1344 kUseMapRole,
1345 eNoValue,
1346 eNoAction,
1347 eNoLiveAttr,
1348 kGenericAccType,
1349 kNoReqStates
1351 { // tree
1352 nsGkAtoms::tree,
1353 roles::OUTLINE,
1354 kUseMapRole,
1355 eNoValue,
1356 eNoAction,
1357 eNoLiveAttr,
1358 eSelect,
1359 states::VERTICAL,
1360 eARIAReadonly,
1361 eARIAMultiSelectable,
1362 eFocusableUntilDisabled,
1363 eARIAOrientation
1365 { // treegrid
1366 nsGkAtoms::treegrid,
1367 roles::TREE_TABLE,
1368 kUseMapRole,
1369 eNoValue,
1370 eNoAction,
1371 eNoLiveAttr,
1372 eSelect | eTable,
1373 kNoReqStates,
1374 eARIAReadonly,
1375 eARIAMultiSelectable,
1376 eFocusableUntilDisabled,
1377 eARIAOrientation
1379 { // treeitem
1380 nsGkAtoms::treeitem,
1381 roles::OUTLINEITEM,
1382 kUseMapRole,
1383 eNoValue,
1384 eActivateAction, // XXX: should expose second 'expand/collapse' action based
1385 // on states
1386 eNoLiveAttr,
1387 kGenericAccType,
1388 kNoReqStates,
1389 eARIASelectable,
1390 eARIACheckedMixed
1392 // clang-format on
1395 static const nsRoleMapEntry sLandmarkRoleMap = {
1396 nsGkAtoms::_empty, roles::NOTHING, kUseNativeRole, eNoValue,
1397 eNoAction, eNoLiveAttr, kGenericAccType, kNoReqStates};
1399 nsRoleMapEntry aria::gEmptyRoleMap = {
1400 nsGkAtoms::_empty, roles::TEXT_CONTAINER, kUseMapRole, eNoValue,
1401 eNoAction, eNoLiveAttr, kGenericAccType, kNoReqStates};
1404 * Universal (Global) states:
1405 * The following state rules are applied to any accessible element,
1406 * whether there is an ARIA role or not:
1408 static const EStateRule sWAIUnivStateMap[] = {
1409 eARIABusy, eARIACurrent, eARIADisabled,
1410 eARIAExpanded, // Currently under spec review but precedent exists
1411 eARIAHasPopup, // Note this is a tokenised attribute starting in ARIA 1.1
1412 eARIAInvalid, eARIAModal,
1413 eARIARequired, // XXX not global, Bug 553117
1414 eARIANone};
1417 * ARIA attribute map for attribute characteristics.
1418 * @note ARIA attributes that don't have any flags are not included here.
1421 struct AttrCharacteristics {
1422 const nsStaticAtom* const attributeName;
1423 const uint8_t characteristics;
1426 static const AttrCharacteristics gWAIUnivAttrMap[] = {
1427 // clang-format off
1428 {nsGkAtoms::aria_activedescendant, ATTR_BYPASSOBJ },
1429 {nsGkAtoms::aria_atomic, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
1430 {nsGkAtoms::aria_busy, ATTR_VALTOKEN | ATTR_GLOBAL },
1431 {nsGkAtoms::aria_checked, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, /* exposes checkable obj attr */
1432 {nsGkAtoms::aria_colcount, ATTR_VALINT },
1433 {nsGkAtoms::aria_colindex, ATTR_VALINT },
1434 {nsGkAtoms::aria_controls, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1435 {nsGkAtoms::aria_current, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
1436 {nsGkAtoms::aria_describedby, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1437 // XXX Ideally, aria-description shouldn't expose a description object
1438 // attribute (i.e. it should have ATTR_BYPASSOBJ). However, until the
1439 // description-from attribute is implemented (bug 1726087), clients such as
1440 // NVDA depend on the description object attribute to work out whether the
1441 // accDescription originated from aria-description.
1442 {nsGkAtoms::aria_description, ATTR_GLOBAL },
1443 {nsGkAtoms::aria_details, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1444 {nsGkAtoms::aria_disabled, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
1445 {nsGkAtoms::aria_dropeffect, ATTR_VALTOKEN | ATTR_GLOBAL },
1446 {nsGkAtoms::aria_errormessage, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1447 {nsGkAtoms::aria_expanded, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
1448 {nsGkAtoms::aria_flowto, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1449 {nsGkAtoms::aria_grabbed, ATTR_VALTOKEN | ATTR_GLOBAL },
1450 {nsGkAtoms::aria_haspopup, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
1451 {nsGkAtoms::aria_hidden, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, /* handled special way */
1452 {nsGkAtoms::aria_invalid, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
1453 {nsGkAtoms::aria_label, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1454 {nsGkAtoms::aria_labelledby, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1455 {nsGkAtoms::aria_level, ATTR_BYPASSOBJ }, /* handled via groupPosition */
1456 {nsGkAtoms::aria_live, ATTR_VALTOKEN | ATTR_GLOBAL },
1457 {nsGkAtoms::aria_modal, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
1458 {nsGkAtoms::aria_multiline, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
1459 {nsGkAtoms::aria_multiselectable, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
1460 {nsGkAtoms::aria_owns, ATTR_BYPASSOBJ | ATTR_GLOBAL },
1461 {nsGkAtoms::aria_orientation, ATTR_VALTOKEN },
1462 {nsGkAtoms::aria_posinset, ATTR_BYPASSOBJ }, /* handled via groupPosition */
1463 {nsGkAtoms::aria_pressed, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
1464 {nsGkAtoms::aria_readonly, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
1465 {nsGkAtoms::aria_relevant, ATTR_GLOBAL },
1466 {nsGkAtoms::aria_required, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
1467 {nsGkAtoms::aria_rowcount, ATTR_VALINT },
1468 {nsGkAtoms::aria_rowindex, ATTR_VALINT },
1469 {nsGkAtoms::aria_selected, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
1470 {nsGkAtoms::aria_setsize, ATTR_BYPASSOBJ }, /* handled via groupPosition */
1471 {nsGkAtoms::aria_sort, ATTR_VALTOKEN },
1472 {nsGkAtoms::aria_valuenow, ATTR_BYPASSOBJ },
1473 {nsGkAtoms::aria_valuemin, ATTR_BYPASSOBJ },
1474 {nsGkAtoms::aria_valuemax, ATTR_BYPASSOBJ },
1475 {nsGkAtoms::aria_valuetext, ATTR_BYPASSOBJ }
1476 // clang-format on
1479 const nsRoleMapEntry* aria::GetRoleMap(dom::Element* aEl) {
1480 return GetRoleMapFromIndex(GetRoleMapIndex(aEl));
1483 uint8_t aria::GetFirstValidRoleMapIndexExcluding(
1484 dom::Element* aEl, std::initializer_list<nsStaticAtom*> aRolesToSkip) {
1485 nsAutoString roles;
1486 if (!aEl || !nsAccUtils::GetARIAAttr(aEl, nsGkAtoms::role, roles) ||
1487 roles.IsEmpty()) {
1488 // We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
1489 return NO_ROLE_MAP_ENTRY_INDEX;
1492 nsWhitespaceTokenizer tokenizer(roles);
1493 while (tokenizer.hasMoreTokens()) {
1494 // Do a binary search through table for the next role in role list
1495 const nsDependentSubstring role = tokenizer.nextToken();
1497 // Skip any roles that we aren't interested in.
1498 bool shouldSkip = false;
1499 for (nsStaticAtom* atomRole : aRolesToSkip) {
1500 if (role.Equals(atomRole->GetUTF16String())) {
1501 shouldSkip = true;
1502 break;
1505 if (shouldSkip) {
1506 continue;
1509 size_t idx;
1510 auto comparator = [&role](const nsRoleMapEntry& aEntry) {
1511 return Compare(role, aEntry.ARIARoleString(),
1512 nsCaseInsensitiveStringComparator);
1514 if (BinarySearchIf(sWAIRoleMaps, 0, ArrayLength(sWAIRoleMaps), comparator,
1515 &idx)) {
1516 return idx;
1520 // Always use some entry index if there is a non-empty role string
1521 // To ensure an accessible object is created
1522 return LANDMARK_ROLE_MAP_ENTRY_INDEX;
1525 uint8_t aria::GetRoleMapIndex(dom::Element* aEl) {
1526 // Get the rolemap index of the first valid role, excluding nothing.
1527 return GetFirstValidRoleMapIndexExcluding(aEl, {});
1530 const nsRoleMapEntry* aria::GetRoleMapFromIndex(uint8_t aRoleMapIndex) {
1531 switch (aRoleMapIndex) {
1532 case NO_ROLE_MAP_ENTRY_INDEX:
1533 return nullptr;
1534 case EMPTY_ROLE_MAP_ENTRY_INDEX:
1535 return &gEmptyRoleMap;
1536 case LANDMARK_ROLE_MAP_ENTRY_INDEX:
1537 return &sLandmarkRoleMap;
1538 default:
1539 return sWAIRoleMaps + aRoleMapIndex;
1543 uint8_t aria::GetIndexFromRoleMap(const nsRoleMapEntry* aRoleMapEntry) {
1544 if (aRoleMapEntry == nullptr) {
1545 return NO_ROLE_MAP_ENTRY_INDEX;
1546 } else if (aRoleMapEntry == &gEmptyRoleMap) {
1547 return EMPTY_ROLE_MAP_ENTRY_INDEX;
1548 } else if (aRoleMapEntry == &sLandmarkRoleMap) {
1549 return LANDMARK_ROLE_MAP_ENTRY_INDEX;
1550 } else {
1551 uint8_t index = aRoleMapEntry - sWAIRoleMaps;
1552 MOZ_ASSERT(aria::IsRoleMapIndexValid(index));
1553 return index;
1557 bool aria::IsRoleMapIndexValid(uint8_t aRoleMapIndex) {
1558 switch (aRoleMapIndex) {
1559 case NO_ROLE_MAP_ENTRY_INDEX:
1560 case EMPTY_ROLE_MAP_ENTRY_INDEX:
1561 case LANDMARK_ROLE_MAP_ENTRY_INDEX:
1562 return true;
1564 return aRoleMapIndex < ArrayLength(sWAIRoleMaps);
1567 uint64_t aria::UniversalStatesFor(mozilla::dom::Element* aElement) {
1568 uint64_t state = 0;
1569 uint32_t index = 0;
1570 while (MapToState(sWAIUnivStateMap[index], aElement, &state)) index++;
1572 return state;
1575 uint8_t aria::AttrCharacteristicsFor(nsAtom* aAtom) {
1576 for (uint32_t i = 0; i < ArrayLength(gWAIUnivAttrMap); i++) {
1577 if (gWAIUnivAttrMap[i].attributeName == aAtom) {
1578 return gWAIUnivAttrMap[i].characteristics;
1582 return 0;
1585 bool aria::HasDefinedARIAHidden(nsIContent* aContent) {
1586 return aContent && aContent->IsElement() &&
1587 nsAccUtils::ARIAAttrValueIs(aContent->AsElement(),
1588 nsGkAtoms::aria_hidden, nsGkAtoms::_true,
1589 eCaseMatters);
1592 ////////////////////////////////////////////////////////////////////////////////
1593 // AttrIterator class
1595 AttrIterator::AttrIterator(nsIContent* aContent)
1596 : mElement(dom::Element::FromNode(aContent)),
1597 mIteratingDefaults(false),
1598 mAttrIdx(0),
1599 mAttrCharacteristics(0) {
1600 mAttrs = mElement ? &mElement->GetAttrs() : nullptr;
1601 mAttrCount = mAttrs ? mAttrs->AttrCount() : 0;
1604 bool AttrIterator::Next() {
1605 while (mAttrIdx < mAttrCount) {
1606 const nsAttrName* attr = mAttrs->GetSafeAttrNameAt(mAttrIdx);
1607 mAttrIdx++;
1608 if (attr->NamespaceEquals(kNameSpaceID_None)) {
1609 mAttrAtom = attr->Atom();
1610 nsDependentAtomString attrStr(mAttrAtom);
1611 if (!StringBeginsWith(attrStr, u"aria-"_ns)) continue; // Not ARIA
1613 if (mIteratingDefaults) {
1614 if (mOverriddenAttrs.Contains(mAttrAtom)) {
1615 continue;
1617 } else {
1618 mOverriddenAttrs.Insert(mAttrAtom);
1621 // AttrCharacteristicsFor has to search for the entry, so cache it here
1622 // rather than having to search again later.
1623 mAttrCharacteristics = aria::AttrCharacteristicsFor(mAttrAtom);
1624 if (mAttrCharacteristics & ATTR_BYPASSOBJ) {
1625 continue; // No need to handle exposing as obj attribute here
1628 if ((mAttrCharacteristics & ATTR_VALTOKEN) &&
1629 !nsAccUtils::HasDefinedARIAToken(mAttrs, mAttrAtom)) {
1630 continue; // only expose token based attributes if they are defined
1633 if ((mAttrCharacteristics & ATTR_BYPASSOBJ_IF_FALSE) &&
1634 mAttrs->AttrValueIs(kNameSpaceID_None, mAttrAtom, nsGkAtoms::_false,
1635 eCaseMatters)) {
1636 continue; // only expose token based attribute if value is not 'false'.
1639 return true;
1643 mAttrCharacteristics = 0;
1644 mAttrAtom = nullptr;
1646 if (const auto* defaults = nsAccUtils::GetARIADefaults(mElement);
1647 !mIteratingDefaults && defaults) {
1648 mIteratingDefaults = true;
1649 mAttrs = defaults;
1650 mAttrCount = mAttrs->AttrCount();
1651 mAttrIdx = 0;
1652 return Next();
1655 return false;
1658 nsAtom* AttrIterator::AttrName() const { return mAttrAtom; }
1660 void AttrIterator::AttrValue(nsAString& aAttrValue) const {
1661 nsAutoString value;
1662 if (mAttrs->GetAttr(mAttrAtom, value)) {
1663 if (mAttrCharacteristics & ATTR_VALTOKEN) {
1664 nsAtom* normalizedValue =
1665 nsAccUtils::NormalizeARIAToken(mAttrs, mAttrAtom);
1666 if (normalizedValue) {
1667 nsDependentAtomString normalizedValueStr(normalizedValue);
1668 aAttrValue.Assign(normalizedValueStr);
1669 return;
1672 aAttrValue.Assign(value);
1676 bool AttrIterator::ExposeAttr(AccAttributes* aTargetAttrs) const {
1677 if (mAttrCharacteristics & ATTR_VALTOKEN) {
1678 nsAtom* normalizedValue = nsAccUtils::NormalizeARIAToken(mAttrs, mAttrAtom);
1679 if (normalizedValue) {
1680 aTargetAttrs->SetAttribute(mAttrAtom, normalizedValue);
1681 return true;
1683 } else if (mAttrCharacteristics & ATTR_VALINT) {
1684 int32_t intVal;
1685 if (nsCoreUtils::GetUIntAttrValue(mAttrs->GetAttr(mAttrAtom), &intVal)) {
1686 aTargetAttrs->SetAttribute(mAttrAtom, intVal);
1687 return true;
1689 if (mAttrAtom == nsGkAtoms::aria_colcount ||
1690 mAttrAtom == nsGkAtoms::aria_rowcount) {
1691 // These attributes allow a value of -1.
1692 if (mAttrs->AttrValueIs(kNameSpaceID_None, mAttrAtom, u"-1"_ns,
1693 eCaseMatters)) {
1694 aTargetAttrs->SetAttribute(mAttrAtom, -1);
1695 return true;
1698 return false; // Invalid value.
1700 nsAutoString value;
1701 if (mAttrs->GetAttr(mAttrAtom, value)) {
1702 aTargetAttrs->SetAttribute(mAttrAtom, std::move(value));
1703 return true;
1705 return false;