|
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/. */ |
|
7 |
|
8 #include "ARIAMap.h" |
|
9 |
|
10 #include "nsAccUtils.h" |
|
11 #include "nsCoreUtils.h" |
|
12 #include "Role.h" |
|
13 #include "States.h" |
|
14 |
|
15 #include "nsAttrName.h" |
|
16 #include "nsWhitespaceTokenizer.h" |
|
17 |
|
18 using namespace mozilla; |
|
19 using namespace mozilla::a11y; |
|
20 using namespace mozilla::a11y::aria; |
|
21 |
|
22 static const uint32_t kGenericAccType = 0; |
|
23 |
|
24 /** |
|
25 * This list of WAI-defined roles are currently hardcoded. |
|
26 * Eventually we will most likely be loading an RDF resource that contains this information |
|
27 * Using RDF will also allow for role extensibility. See bug 280138. |
|
28 * |
|
29 * Definition of nsRoleMapEntry contains comments explaining this table. |
|
30 * |
|
31 * When no nsIAccessibleRole enum mapping exists for an ARIA role, the |
|
32 * role will be exposed via the object attribute "xml-roles". |
|
33 * In addition, in MSAA, the unmapped role will also be exposed as a BSTR string role. |
|
34 * |
|
35 * There are no nsIAccessibleRole enums for the following landmark roles: |
|
36 * banner, contentinfo, main, navigation, note, search, secondary, seealso, breadcrumbs |
|
37 */ |
|
38 |
|
39 static nsRoleMapEntry sWAIRoleMaps[] = |
|
40 { |
|
41 { // alert |
|
42 &nsGkAtoms::alert, |
|
43 roles::ALERT, |
|
44 kUseMapRole, |
|
45 eNoValue, |
|
46 eNoAction, |
|
47 eNoLiveAttr, |
|
48 kGenericAccType, |
|
49 kNoReqStates |
|
50 }, |
|
51 { // alertdialog |
|
52 &nsGkAtoms::alertdialog, |
|
53 roles::DIALOG, |
|
54 kUseMapRole, |
|
55 eNoValue, |
|
56 eNoAction, |
|
57 eNoLiveAttr, |
|
58 kGenericAccType, |
|
59 kNoReqStates |
|
60 }, |
|
61 { // application |
|
62 &nsGkAtoms::application, |
|
63 roles::APPLICATION, |
|
64 kUseMapRole, |
|
65 eNoValue, |
|
66 eNoAction, |
|
67 eNoLiveAttr, |
|
68 kGenericAccType, |
|
69 kNoReqStates |
|
70 }, |
|
71 { // article |
|
72 &nsGkAtoms::article, |
|
73 roles::DOCUMENT, |
|
74 kUseMapRole, |
|
75 eNoValue, |
|
76 eNoAction, |
|
77 eNoLiveAttr, |
|
78 kGenericAccType, |
|
79 kNoReqStates, |
|
80 eReadonlyUntilEditable |
|
81 }, |
|
82 { // button |
|
83 &nsGkAtoms::button, |
|
84 roles::PUSHBUTTON, |
|
85 kUseMapRole, |
|
86 eNoValue, |
|
87 ePressAction, |
|
88 eNoLiveAttr, |
|
89 eButton, |
|
90 kNoReqStates |
|
91 // eARIAPressed is auto applied on any button |
|
92 }, |
|
93 { // checkbox |
|
94 &nsGkAtoms::checkbox, |
|
95 roles::CHECKBUTTON, |
|
96 kUseMapRole, |
|
97 eNoValue, |
|
98 eCheckUncheckAction, |
|
99 eNoLiveAttr, |
|
100 kGenericAccType, |
|
101 kNoReqStates, |
|
102 eARIACheckableMixed, |
|
103 eARIAReadonly |
|
104 }, |
|
105 { // columnheader |
|
106 &nsGkAtoms::columnheader, |
|
107 roles::COLUMNHEADER, |
|
108 kUseMapRole, |
|
109 eNoValue, |
|
110 eSortAction, |
|
111 eNoLiveAttr, |
|
112 eTableCell, |
|
113 kNoReqStates, |
|
114 eARIASelectableIfDefined, |
|
115 eARIAReadonlyOrEditableIfDefined |
|
116 }, |
|
117 { // combobox |
|
118 &nsGkAtoms::combobox, |
|
119 roles::COMBOBOX, |
|
120 kUseMapRole, |
|
121 eNoValue, |
|
122 eOpenCloseAction, |
|
123 eNoLiveAttr, |
|
124 kGenericAccType, |
|
125 states::COLLAPSED | states::HASPOPUP, |
|
126 eARIAAutoComplete, |
|
127 eARIAReadonly |
|
128 }, |
|
129 { // dialog |
|
130 &nsGkAtoms::dialog, |
|
131 roles::DIALOG, |
|
132 kUseMapRole, |
|
133 eNoValue, |
|
134 eNoAction, |
|
135 eNoLiveAttr, |
|
136 kGenericAccType, |
|
137 kNoReqStates |
|
138 }, |
|
139 { // directory |
|
140 &nsGkAtoms::directory, |
|
141 roles::LIST, |
|
142 kUseMapRole, |
|
143 eNoValue, |
|
144 eNoAction, |
|
145 eNoLiveAttr, |
|
146 eList, |
|
147 kNoReqStates |
|
148 }, |
|
149 { // document |
|
150 &nsGkAtoms::document, |
|
151 roles::DOCUMENT, |
|
152 kUseMapRole, |
|
153 eNoValue, |
|
154 eNoAction, |
|
155 eNoLiveAttr, |
|
156 kGenericAccType, |
|
157 kNoReqStates, |
|
158 eReadonlyUntilEditable |
|
159 }, |
|
160 { // form |
|
161 &nsGkAtoms::form, |
|
162 roles::FORM, |
|
163 kUseMapRole, |
|
164 eNoValue, |
|
165 eNoAction, |
|
166 eNoLiveAttr, |
|
167 kGenericAccType, |
|
168 kNoReqStates |
|
169 }, |
|
170 { // grid |
|
171 &nsGkAtoms::grid, |
|
172 roles::TABLE, |
|
173 kUseMapRole, |
|
174 eNoValue, |
|
175 eNoAction, |
|
176 eNoLiveAttr, |
|
177 eSelect | eTable, |
|
178 kNoReqStates, |
|
179 eARIAMultiSelectable, |
|
180 eARIAReadonlyOrEditable, |
|
181 eFocusableUntilDisabled |
|
182 }, |
|
183 { // gridcell |
|
184 &nsGkAtoms::gridcell, |
|
185 roles::GRID_CELL, |
|
186 kUseMapRole, |
|
187 eNoValue, |
|
188 eNoAction, |
|
189 eNoLiveAttr, |
|
190 eTableCell, |
|
191 kNoReqStates, |
|
192 eARIASelectable, |
|
193 eARIAReadonlyOrEditableIfDefined |
|
194 }, |
|
195 { // group |
|
196 &nsGkAtoms::group, |
|
197 roles::GROUPING, |
|
198 kUseMapRole, |
|
199 eNoValue, |
|
200 eNoAction, |
|
201 eNoLiveAttr, |
|
202 kGenericAccType, |
|
203 kNoReqStates |
|
204 }, |
|
205 { // heading |
|
206 &nsGkAtoms::heading, |
|
207 roles::HEADING, |
|
208 kUseMapRole, |
|
209 eNoValue, |
|
210 eNoAction, |
|
211 eNoLiveAttr, |
|
212 kGenericAccType, |
|
213 kNoReqStates |
|
214 }, |
|
215 { // img |
|
216 &nsGkAtoms::img, |
|
217 roles::GRAPHIC, |
|
218 kUseMapRole, |
|
219 eNoValue, |
|
220 eNoAction, |
|
221 eNoLiveAttr, |
|
222 kGenericAccType, |
|
223 kNoReqStates |
|
224 }, |
|
225 { // key |
|
226 &nsGkAtoms::key, |
|
227 roles::KEY, |
|
228 kUseMapRole, |
|
229 eNoValue, |
|
230 ePressAction, |
|
231 eNoLiveAttr, |
|
232 kGenericAccType, |
|
233 kNoReqStates, |
|
234 eARIAPressed |
|
235 }, |
|
236 { // link |
|
237 &nsGkAtoms::link, |
|
238 roles::LINK, |
|
239 kUseMapRole, |
|
240 eNoValue, |
|
241 eJumpAction, |
|
242 eNoLiveAttr, |
|
243 kGenericAccType, |
|
244 states::LINKED |
|
245 }, |
|
246 { // list |
|
247 &nsGkAtoms::list, |
|
248 roles::LIST, |
|
249 kUseMapRole, |
|
250 eNoValue, |
|
251 eNoAction, |
|
252 eNoLiveAttr, |
|
253 eList, |
|
254 states::READONLY |
|
255 }, |
|
256 { // listbox |
|
257 &nsGkAtoms::listbox, |
|
258 roles::LISTBOX, |
|
259 kUseMapRole, |
|
260 eNoValue, |
|
261 eNoAction, |
|
262 eNoLiveAttr, |
|
263 eListControl | eSelect, |
|
264 kNoReqStates, |
|
265 eARIAMultiSelectable, |
|
266 eARIAReadonly, |
|
267 eFocusableUntilDisabled |
|
268 }, |
|
269 { // listitem |
|
270 &nsGkAtoms::listitem, |
|
271 roles::LISTITEM, |
|
272 kUseMapRole, |
|
273 eNoValue, |
|
274 eNoAction, // XXX: should depend on state, parent accessible |
|
275 eNoLiveAttr, |
|
276 kGenericAccType, |
|
277 states::READONLY |
|
278 }, |
|
279 { // log |
|
280 &nsGkAtoms::log_, |
|
281 roles::NOTHING, |
|
282 kUseNativeRole, |
|
283 eNoValue, |
|
284 eNoAction, |
|
285 ePoliteLiveAttr, |
|
286 kGenericAccType, |
|
287 kNoReqStates |
|
288 }, |
|
289 { // marquee |
|
290 &nsGkAtoms::marquee, |
|
291 roles::ANIMATION, |
|
292 kUseMapRole, |
|
293 eNoValue, |
|
294 eNoAction, |
|
295 eOffLiveAttr, |
|
296 kGenericAccType, |
|
297 kNoReqStates |
|
298 }, |
|
299 { // math |
|
300 &nsGkAtoms::math, |
|
301 roles::FLAT_EQUATION, |
|
302 kUseMapRole, |
|
303 eNoValue, |
|
304 eNoAction, |
|
305 eNoLiveAttr, |
|
306 kGenericAccType, |
|
307 kNoReqStates |
|
308 }, |
|
309 { // menu |
|
310 &nsGkAtoms::menu, |
|
311 roles::MENUPOPUP, |
|
312 kUseMapRole, |
|
313 eNoValue, |
|
314 eNoAction, // XXX: technically accessibles of menupopup role haven't |
|
315 // any action, but menu can be open or close. |
|
316 eNoLiveAttr, |
|
317 kGenericAccType, |
|
318 kNoReqStates |
|
319 }, |
|
320 { // menubar |
|
321 &nsGkAtoms::menubar, |
|
322 roles::MENUBAR, |
|
323 kUseMapRole, |
|
324 eNoValue, |
|
325 eNoAction, |
|
326 eNoLiveAttr, |
|
327 kGenericAccType, |
|
328 kNoReqStates |
|
329 }, |
|
330 { // menuitem |
|
331 &nsGkAtoms::menuitem, |
|
332 roles::MENUITEM, |
|
333 kUseMapRole, |
|
334 eNoValue, |
|
335 eClickAction, |
|
336 eNoLiveAttr, |
|
337 kGenericAccType, |
|
338 kNoReqStates, |
|
339 eARIACheckedMixed |
|
340 }, |
|
341 { // menuitemcheckbox |
|
342 &nsGkAtoms::menuitemcheckbox, |
|
343 roles::CHECK_MENU_ITEM, |
|
344 kUseMapRole, |
|
345 eNoValue, |
|
346 eClickAction, |
|
347 eNoLiveAttr, |
|
348 kGenericAccType, |
|
349 kNoReqStates, |
|
350 eARIACheckableMixed |
|
351 }, |
|
352 { // menuitemradio |
|
353 &nsGkAtoms::menuitemradio, |
|
354 roles::RADIO_MENU_ITEM, |
|
355 kUseMapRole, |
|
356 eNoValue, |
|
357 eClickAction, |
|
358 eNoLiveAttr, |
|
359 kGenericAccType, |
|
360 kNoReqStates, |
|
361 eARIACheckableBool |
|
362 }, |
|
363 { // note |
|
364 &nsGkAtoms::note_, |
|
365 roles::NOTE, |
|
366 kUseMapRole, |
|
367 eNoValue, |
|
368 eNoAction, |
|
369 eNoLiveAttr, |
|
370 kGenericAccType, |
|
371 kNoReqStates |
|
372 }, |
|
373 { // option |
|
374 &nsGkAtoms::option, |
|
375 roles::OPTION, |
|
376 kUseMapRole, |
|
377 eNoValue, |
|
378 eSelectAction, |
|
379 eNoLiveAttr, |
|
380 kGenericAccType, |
|
381 kNoReqStates, |
|
382 eARIASelectable, |
|
383 eARIACheckedMixed |
|
384 }, |
|
385 { // presentation |
|
386 &nsGkAtoms::presentation, |
|
387 roles::NOTHING, |
|
388 kUseMapRole, |
|
389 eNoValue, |
|
390 eNoAction, |
|
391 eNoLiveAttr, |
|
392 kGenericAccType, |
|
393 kNoReqStates |
|
394 }, |
|
395 { // progressbar |
|
396 &nsGkAtoms::progressbar, |
|
397 roles::PROGRESSBAR, |
|
398 kUseMapRole, |
|
399 eHasValueMinMax, |
|
400 eNoAction, |
|
401 eNoLiveAttr, |
|
402 kGenericAccType, |
|
403 states::READONLY, |
|
404 eIndeterminateIfNoValue |
|
405 }, |
|
406 { // radio |
|
407 &nsGkAtoms::radio, |
|
408 roles::RADIOBUTTON, |
|
409 kUseMapRole, |
|
410 eNoValue, |
|
411 eSelectAction, |
|
412 eNoLiveAttr, |
|
413 kGenericAccType, |
|
414 kNoReqStates, |
|
415 eARIACheckableBool |
|
416 }, |
|
417 { // radiogroup |
|
418 &nsGkAtoms::radiogroup, |
|
419 roles::GROUPING, |
|
420 kUseMapRole, |
|
421 eNoValue, |
|
422 eNoAction, |
|
423 eNoLiveAttr, |
|
424 kGenericAccType, |
|
425 kNoReqStates |
|
426 }, |
|
427 { // region |
|
428 &nsGkAtoms::region, |
|
429 roles::PANE, |
|
430 kUseMapRole, |
|
431 eNoValue, |
|
432 eNoAction, |
|
433 eNoLiveAttr, |
|
434 kGenericAccType, |
|
435 kNoReqStates |
|
436 }, |
|
437 { // row |
|
438 &nsGkAtoms::row, |
|
439 roles::ROW, |
|
440 kUseMapRole, |
|
441 eNoValue, |
|
442 eNoAction, |
|
443 eNoLiveAttr, |
|
444 eTableRow, |
|
445 kNoReqStates, |
|
446 eARIASelectable |
|
447 }, |
|
448 { // rowgroup |
|
449 &nsGkAtoms::rowgroup, |
|
450 roles::GROUPING, |
|
451 kUseMapRole, |
|
452 eNoValue, |
|
453 eNoAction, |
|
454 eNoLiveAttr, |
|
455 kGenericAccType, |
|
456 kNoReqStates |
|
457 }, |
|
458 { // rowheader |
|
459 &nsGkAtoms::rowheader, |
|
460 roles::ROWHEADER, |
|
461 kUseMapRole, |
|
462 eNoValue, |
|
463 eSortAction, |
|
464 eNoLiveAttr, |
|
465 eTableCell, |
|
466 kNoReqStates, |
|
467 eARIASelectableIfDefined, |
|
468 eARIAReadonlyOrEditableIfDefined |
|
469 }, |
|
470 { // scrollbar |
|
471 &nsGkAtoms::scrollbar, |
|
472 roles::SCROLLBAR, |
|
473 kUseMapRole, |
|
474 eHasValueMinMax, |
|
475 eNoAction, |
|
476 eNoLiveAttr, |
|
477 kGenericAccType, |
|
478 kNoReqStates, |
|
479 eARIAOrientation, |
|
480 eARIAReadonly |
|
481 }, |
|
482 { // separator |
|
483 &nsGkAtoms::separator_, |
|
484 roles::SEPARATOR, |
|
485 kUseMapRole, |
|
486 eNoValue, |
|
487 eNoAction, |
|
488 eNoLiveAttr, |
|
489 kGenericAccType, |
|
490 kNoReqStates, |
|
491 eARIAOrientation |
|
492 }, |
|
493 { // slider |
|
494 &nsGkAtoms::slider, |
|
495 roles::SLIDER, |
|
496 kUseMapRole, |
|
497 eHasValueMinMax, |
|
498 eNoAction, |
|
499 eNoLiveAttr, |
|
500 kGenericAccType, |
|
501 kNoReqStates, |
|
502 eARIAOrientation, |
|
503 eARIAReadonly |
|
504 }, |
|
505 { // spinbutton |
|
506 &nsGkAtoms::spinbutton, |
|
507 roles::SPINBUTTON, |
|
508 kUseMapRole, |
|
509 eHasValueMinMax, |
|
510 eNoAction, |
|
511 eNoLiveAttr, |
|
512 kGenericAccType, |
|
513 kNoReqStates, |
|
514 eARIAReadonly |
|
515 }, |
|
516 { // status |
|
517 &nsGkAtoms::status, |
|
518 roles::STATUSBAR, |
|
519 kUseMapRole, |
|
520 eNoValue, |
|
521 eNoAction, |
|
522 ePoliteLiveAttr, |
|
523 kGenericAccType, |
|
524 kNoReqStates |
|
525 }, |
|
526 { // tab |
|
527 &nsGkAtoms::tab, |
|
528 roles::PAGETAB, |
|
529 kUseMapRole, |
|
530 eNoValue, |
|
531 eSwitchAction, |
|
532 eNoLiveAttr, |
|
533 kGenericAccType, |
|
534 kNoReqStates, |
|
535 eARIASelectable |
|
536 }, |
|
537 { // tablist |
|
538 &nsGkAtoms::tablist, |
|
539 roles::PAGETABLIST, |
|
540 kUseMapRole, |
|
541 eNoValue, |
|
542 eNoAction, |
|
543 eNoLiveAttr, |
|
544 eSelect, |
|
545 kNoReqStates |
|
546 }, |
|
547 { // tabpanel |
|
548 &nsGkAtoms::tabpanel, |
|
549 roles::PROPERTYPAGE, |
|
550 kUseMapRole, |
|
551 eNoValue, |
|
552 eNoAction, |
|
553 eNoLiveAttr, |
|
554 kGenericAccType, |
|
555 kNoReqStates |
|
556 }, |
|
557 { // textbox |
|
558 &nsGkAtoms::textbox, |
|
559 roles::ENTRY, |
|
560 kUseMapRole, |
|
561 eNoValue, |
|
562 eActivateAction, |
|
563 eNoLiveAttr, |
|
564 kGenericAccType, |
|
565 kNoReqStates, |
|
566 eARIAAutoComplete, |
|
567 eARIAMultiline, |
|
568 eARIAReadonlyOrEditable |
|
569 }, |
|
570 { // timer |
|
571 &nsGkAtoms::timer, |
|
572 roles::NOTHING, |
|
573 kUseNativeRole, |
|
574 eNoValue, |
|
575 eNoAction, |
|
576 eOffLiveAttr, |
|
577 kNoReqStates |
|
578 }, |
|
579 { // toolbar |
|
580 &nsGkAtoms::toolbar, |
|
581 roles::TOOLBAR, |
|
582 kUseMapRole, |
|
583 eNoValue, |
|
584 eNoAction, |
|
585 eNoLiveAttr, |
|
586 kGenericAccType, |
|
587 kNoReqStates |
|
588 }, |
|
589 { // tooltip |
|
590 &nsGkAtoms::tooltip, |
|
591 roles::TOOLTIP, |
|
592 kUseMapRole, |
|
593 eNoValue, |
|
594 eNoAction, |
|
595 eNoLiveAttr, |
|
596 kGenericAccType, |
|
597 kNoReqStates |
|
598 }, |
|
599 { // tree |
|
600 &nsGkAtoms::tree, |
|
601 roles::OUTLINE, |
|
602 kUseMapRole, |
|
603 eNoValue, |
|
604 eNoAction, |
|
605 eNoLiveAttr, |
|
606 eSelect, |
|
607 kNoReqStates, |
|
608 eARIAReadonly, |
|
609 eARIAMultiSelectable, |
|
610 eFocusableUntilDisabled |
|
611 }, |
|
612 { // treegrid |
|
613 &nsGkAtoms::treegrid, |
|
614 roles::TREE_TABLE, |
|
615 kUseMapRole, |
|
616 eNoValue, |
|
617 eNoAction, |
|
618 eNoLiveAttr, |
|
619 eSelect | eTable, |
|
620 kNoReqStates, |
|
621 eARIAReadonlyOrEditable, |
|
622 eARIAMultiSelectable, |
|
623 eFocusableUntilDisabled |
|
624 }, |
|
625 { // treeitem |
|
626 &nsGkAtoms::treeitem, |
|
627 roles::OUTLINEITEM, |
|
628 kUseMapRole, |
|
629 eNoValue, |
|
630 eActivateAction, // XXX: should expose second 'expand/collapse' action based |
|
631 // on states |
|
632 eNoLiveAttr, |
|
633 kGenericAccType, |
|
634 kNoReqStates, |
|
635 eARIASelectable, |
|
636 eARIACheckedMixed |
|
637 } |
|
638 }; |
|
639 |
|
640 static nsRoleMapEntry sLandmarkRoleMap = { |
|
641 &nsGkAtoms::_empty, |
|
642 roles::NOTHING, |
|
643 kUseNativeRole, |
|
644 eNoValue, |
|
645 eNoAction, |
|
646 eNoLiveAttr, |
|
647 kGenericAccType, |
|
648 kNoReqStates |
|
649 }; |
|
650 |
|
651 nsRoleMapEntry aria::gEmptyRoleMap = { |
|
652 &nsGkAtoms::_empty, |
|
653 roles::NOTHING, |
|
654 kUseMapRole, |
|
655 eNoValue, |
|
656 eNoAction, |
|
657 eNoLiveAttr, |
|
658 kGenericAccType, |
|
659 kNoReqStates |
|
660 }; |
|
661 |
|
662 /** |
|
663 * Universal (Global) states: |
|
664 * The following state rules are applied to any accessible element, |
|
665 * whether there is an ARIA role or not: |
|
666 */ |
|
667 static const EStateRule sWAIUnivStateMap[] = { |
|
668 eARIABusy, |
|
669 eARIADisabled, |
|
670 eARIAExpanded, // Currently under spec review but precedent exists |
|
671 eARIAHasPopup, // Note this is technically a "property" |
|
672 eARIAInvalid, |
|
673 eARIARequired, // XXX not global, Bug 553117 |
|
674 eARIANone |
|
675 }; |
|
676 |
|
677 |
|
678 /** |
|
679 * ARIA attribute map for attribute characteristics. |
|
680 * @note ARIA attributes that don't have any flags are not included here. |
|
681 */ |
|
682 |
|
683 struct AttrCharacteristics |
|
684 { |
|
685 nsIAtom** attributeName; |
|
686 const uint8_t characteristics; |
|
687 }; |
|
688 |
|
689 static const AttrCharacteristics gWAIUnivAttrMap[] = { |
|
690 {&nsGkAtoms::aria_activedescendant, ATTR_BYPASSOBJ }, |
|
691 {&nsGkAtoms::aria_atomic, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
692 {&nsGkAtoms::aria_busy, ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
693 {&nsGkAtoms::aria_checked, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, /* exposes checkable obj attr */ |
|
694 {&nsGkAtoms::aria_controls, ATTR_BYPASSOBJ | ATTR_GLOBAL }, |
|
695 {&nsGkAtoms::aria_describedby, ATTR_BYPASSOBJ | ATTR_GLOBAL }, |
|
696 {&nsGkAtoms::aria_disabled, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
697 {&nsGkAtoms::aria_dropeffect, ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
698 {&nsGkAtoms::aria_expanded, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, |
|
699 {&nsGkAtoms::aria_flowto, ATTR_BYPASSOBJ | ATTR_GLOBAL }, |
|
700 {&nsGkAtoms::aria_grabbed, ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
701 {&nsGkAtoms::aria_haspopup, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
702 {&nsGkAtoms::aria_hidden, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
703 {&nsGkAtoms::aria_invalid, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
704 {&nsGkAtoms::aria_label, ATTR_BYPASSOBJ | ATTR_GLOBAL }, |
|
705 {&nsGkAtoms::aria_labelledby, ATTR_BYPASSOBJ | ATTR_GLOBAL }, |
|
706 {&nsGkAtoms::aria_level, ATTR_BYPASSOBJ }, /* handled via groupPosition */ |
|
707 {&nsGkAtoms::aria_live, ATTR_VALTOKEN | ATTR_GLOBAL }, |
|
708 {&nsGkAtoms::aria_multiline, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, |
|
709 {&nsGkAtoms::aria_multiselectable, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, |
|
710 {&nsGkAtoms::aria_owns, ATTR_BYPASSOBJ | ATTR_GLOBAL }, |
|
711 {&nsGkAtoms::aria_orientation, ATTR_VALTOKEN }, |
|
712 {&nsGkAtoms::aria_posinset, ATTR_BYPASSOBJ }, /* handled via groupPosition */ |
|
713 {&nsGkAtoms::aria_pressed, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, |
|
714 {&nsGkAtoms::aria_readonly, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, |
|
715 {&nsGkAtoms::aria_relevant, ATTR_BYPASSOBJ | ATTR_GLOBAL }, |
|
716 {&nsGkAtoms::aria_required, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, |
|
717 {&nsGkAtoms::aria_selected, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, |
|
718 {&nsGkAtoms::aria_setsize, ATTR_BYPASSOBJ }, /* handled via groupPosition */ |
|
719 {&nsGkAtoms::aria_sort, ATTR_VALTOKEN }, |
|
720 {&nsGkAtoms::aria_valuenow, ATTR_BYPASSOBJ }, |
|
721 {&nsGkAtoms::aria_valuemin, ATTR_BYPASSOBJ }, |
|
722 {&nsGkAtoms::aria_valuemax, ATTR_BYPASSOBJ }, |
|
723 {&nsGkAtoms::aria_valuetext, ATTR_BYPASSOBJ } |
|
724 }; |
|
725 |
|
726 nsRoleMapEntry* |
|
727 aria::GetRoleMap(nsINode* aNode) |
|
728 { |
|
729 nsIContent* content = nsCoreUtils::GetRoleContent(aNode); |
|
730 nsAutoString roles; |
|
731 if (!content || |
|
732 !content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roles) || |
|
733 roles.IsEmpty()) { |
|
734 // We treat role="" as if the role attribute is absent (per aria spec:8.1.1) |
|
735 return nullptr; |
|
736 } |
|
737 |
|
738 nsWhitespaceTokenizer tokenizer(roles); |
|
739 while (tokenizer.hasMoreTokens()) { |
|
740 // Do a binary search through table for the next role in role list |
|
741 const nsDependentSubstring role = tokenizer.nextToken(); |
|
742 uint32_t low = 0; |
|
743 uint32_t high = ArrayLength(sWAIRoleMaps); |
|
744 while (low < high) { |
|
745 uint32_t idx = (low + high) / 2; |
|
746 int32_t compare = Compare(role, sWAIRoleMaps[idx].ARIARoleString()); |
|
747 if (compare == 0) |
|
748 return sWAIRoleMaps + idx; |
|
749 |
|
750 if (compare < 0) |
|
751 high = idx; |
|
752 else |
|
753 low = idx + 1; |
|
754 } |
|
755 } |
|
756 |
|
757 // Always use some entry if there is a non-empty role string |
|
758 // To ensure an accessible object is created |
|
759 return &sLandmarkRoleMap; |
|
760 } |
|
761 |
|
762 uint64_t |
|
763 aria::UniversalStatesFor(mozilla::dom::Element* aElement) |
|
764 { |
|
765 uint64_t state = 0; |
|
766 uint32_t index = 0; |
|
767 while (MapToState(sWAIUnivStateMap[index], aElement, &state)) |
|
768 index++; |
|
769 |
|
770 return state; |
|
771 } |
|
772 |
|
773 uint8_t |
|
774 aria::AttrCharacteristicsFor(nsIAtom* aAtom) |
|
775 { |
|
776 for (uint32_t i = 0; i < ArrayLength(gWAIUnivAttrMap); i++) |
|
777 if (*gWAIUnivAttrMap[i].attributeName == aAtom) |
|
778 return gWAIUnivAttrMap[i].characteristics; |
|
779 |
|
780 return 0; |
|
781 } |
|
782 |
|
783 //////////////////////////////////////////////////////////////////////////////// |
|
784 // AttrIterator class |
|
785 |
|
786 bool |
|
787 AttrIterator::Next(nsAString& aAttrName, nsAString& aAttrValue) |
|
788 { |
|
789 while (mAttrIdx < mAttrCount) { |
|
790 const nsAttrName* attr = mContent->GetAttrNameAt(mAttrIdx); |
|
791 mAttrIdx++; |
|
792 if (attr->NamespaceEquals(kNameSpaceID_None)) { |
|
793 nsIAtom* attrAtom = attr->Atom(); |
|
794 nsDependentAtomString attrStr(attrAtom); |
|
795 if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-"))) |
|
796 continue; // Not ARIA |
|
797 |
|
798 uint8_t attrFlags = aria::AttrCharacteristicsFor(attrAtom); |
|
799 if (attrFlags & ATTR_BYPASSOBJ) |
|
800 continue; // No need to handle exposing as obj attribute here |
|
801 |
|
802 if ((attrFlags & ATTR_VALTOKEN) && |
|
803 !nsAccUtils::HasDefinedARIAToken(mContent, attrAtom)) |
|
804 continue; // only expose token based attributes if they are defined |
|
805 |
|
806 if ((attrFlags & ATTR_BYPASSOBJ_IF_FALSE) && |
|
807 mContent->AttrValueIs(kNameSpaceID_None, attrAtom, |
|
808 nsGkAtoms::_false, eCaseMatters)) { |
|
809 continue; // only expose token based attribute if value is not 'false'. |
|
810 } |
|
811 |
|
812 nsAutoString value; |
|
813 if (mContent->GetAttr(kNameSpaceID_None, attrAtom, value)) { |
|
814 aAttrName.Assign(Substring(attrStr, 5)); |
|
815 aAttrValue.Assign(value); |
|
816 return true; |
|
817 } |
|
818 } |
|
819 } |
|
820 |
|
821 return false; |
|
822 } |
|
823 |