1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:expandtab:shiftwidth=2:tabstop=2:
3 : */
4 : /* ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is mozilla.org code.
18 : *
19 : * The Initial Developer of the Original Code is IBM Corporation
20 : * Portions created by the Initial Developer are Copyright (C) 2007
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Aaron Leventhal <aleventh@us.ibm.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsARIAMap.h"
41 :
42 : #include "nsIAccessibleRole.h"
43 : #include "Role.h"
44 : #include "States.h"
45 :
46 : #include "nsIContent.h"
47 :
48 : using namespace mozilla::a11y;
49 :
50 : /**
51 : * This list of WAI-defined roles are currently hardcoded.
52 : * Eventually we will most likely be loading an RDF resource that contains this information
53 : * Using RDF will also allow for role extensibility. See bug 280138.
54 : *
55 : * Definition of nsRoleMapEntry and nsStateMapEntry contains comments explaining this table.
56 : *
57 : * When no nsIAccessibleRole enum mapping exists for an ARIA role, the
58 : * role will be exposed via the object attribute "xml-roles".
59 : * In addition, in MSAA, the unmapped role will also be exposed as a BSTR string role.
60 : *
61 : * There are no nsIAccessibleRole enums for the following landmark roles:
62 : * banner, contentinfo, main, navigation, note, search, secondary, seealso, breadcrumbs
63 : */
64 :
65 : nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
66 : {
67 : {
68 : "alert",
69 : roles::ALERT,
70 : kUseMapRole,
71 : eNoValue,
72 : eNoAction,
73 : eNoLiveAttr,
74 : kNoReqStates
75 : },
76 : {
77 : "alertdialog",
78 : roles::DIALOG,
79 : kUseMapRole,
80 : eNoValue,
81 : eNoAction,
82 : eNoLiveAttr,
83 : kNoReqStates
84 : },
85 : {
86 : "application",
87 : roles::APPLICATION,
88 : kUseMapRole,
89 : eNoValue,
90 : eNoAction,
91 : eNoLiveAttr,
92 : kNoReqStates
93 : },
94 : {
95 : "article",
96 : roles::DOCUMENT,
97 : kUseMapRole,
98 : eNoValue,
99 : eNoAction,
100 : eNoLiveAttr,
101 : states::READONLY
102 : },
103 : {
104 : "button",
105 : roles::PUSHBUTTON,
106 : kUseMapRole,
107 : eNoValue,
108 : ePressAction,
109 : eNoLiveAttr,
110 : kNoReqStates,
111 : eARIAPressed
112 : },
113 : {
114 : "checkbox",
115 : roles::CHECKBUTTON,
116 : kUseMapRole,
117 : eNoValue,
118 : eCheckUncheckAction,
119 : eNoLiveAttr,
120 : kNoReqStates,
121 : eARIACheckableMixed,
122 : eARIAReadonly
123 : },
124 : {
125 : "columnheader",
126 : roles::COLUMNHEADER,
127 : kUseMapRole,
128 : eNoValue,
129 : eSortAction,
130 : eNoLiveAttr,
131 : kNoReqStates,
132 : eARIASelectable,
133 : eARIAReadonly
134 : },
135 : {
136 : "combobox",
137 : roles::COMBOBOX,
138 : kUseMapRole,
139 : eNoValue,
140 : eOpenCloseAction,
141 : eNoLiveAttr,
142 : states::COLLAPSED | states::HASPOPUP,
143 : eARIAAutoComplete,
144 : eARIAReadonly
145 : },
146 : {
147 : "dialog",
148 : roles::DIALOG,
149 : kUseMapRole,
150 : eNoValue,
151 : eNoAction,
152 : eNoLiveAttr,
153 : kNoReqStates
154 : },
155 : {
156 : "directory",
157 : roles::LIST,
158 : kUseMapRole,
159 : eNoValue,
160 : eNoAction,
161 : eNoLiveAttr,
162 : kNoReqStates
163 : },
164 : {
165 : "document",
166 : roles::DOCUMENT,
167 : kUseMapRole,
168 : eNoValue,
169 : eNoAction,
170 : eNoLiveAttr,
171 : states::READONLY
172 : },
173 : {
174 : "grid",
175 : roles::TABLE,
176 : kUseMapRole,
177 : eNoValue,
178 : eNoAction,
179 : eNoLiveAttr,
180 : states::FOCUSABLE,
181 : eARIAMultiSelectable,
182 : eARIAReadonly
183 : },
184 : {
185 : "gridcell",
186 : roles::GRID_CELL,
187 : kUseMapRole,
188 : eNoValue,
189 : eNoAction,
190 : eNoLiveAttr,
191 : kNoReqStates,
192 : eARIASelectable,
193 : eARIAReadonly
194 : },
195 : {
196 : "group",
197 : roles::GROUPING,
198 : kUseMapRole,
199 : eNoValue,
200 : eNoAction,
201 : eNoLiveAttr,
202 : kNoReqStates
203 : },
204 : {
205 : "heading",
206 : roles::HEADING,
207 : kUseMapRole,
208 : eNoValue,
209 : eNoAction,
210 : eNoLiveAttr,
211 : kNoReqStates
212 : },
213 : {
214 : "img",
215 : roles::GRAPHIC,
216 : kUseMapRole,
217 : eNoValue,
218 : eNoAction,
219 : eNoLiveAttr,
220 : kNoReqStates
221 : },
222 : {
223 : "link",
224 : roles::LINK,
225 : kUseMapRole,
226 : eNoValue,
227 : eJumpAction,
228 : eNoLiveAttr,
229 : states::LINKED
230 : },
231 : {
232 : "list",
233 : roles::LIST,
234 : kUseMapRole,
235 : eNoValue,
236 : eNoAction,
237 : eNoLiveAttr,
238 : states::READONLY
239 : },
240 : {
241 : "listbox",
242 : roles::LISTBOX,
243 : kUseMapRole,
244 : eNoValue,
245 : eNoAction,
246 : eNoLiveAttr,
247 : kNoReqStates,
248 : eARIAMultiSelectable,
249 : eARIAReadonly
250 : },
251 : {
252 : "listitem",
253 : roles::LISTITEM,
254 : kUseMapRole,
255 : eNoValue,
256 : eNoAction, // XXX: should depend on state, parent accessible
257 : eNoLiveAttr,
258 : states::READONLY
259 : },
260 : {
261 : "log",
262 : roles::NOTHING,
263 : kUseNativeRole,
264 : eNoValue,
265 : eNoAction,
266 : ePoliteLiveAttr,
267 : kNoReqStates
268 : },
269 : {
270 : "marquee",
271 : roles::ANIMATION,
272 : kUseMapRole,
273 : eNoValue,
274 : eNoAction,
275 : eOffLiveAttr,
276 : kNoReqStates
277 : },
278 : {
279 : "math",
280 : roles::FLAT_EQUATION,
281 : kUseMapRole,
282 : eNoValue,
283 : eNoAction,
284 : eNoLiveAttr,
285 : kNoReqStates
286 : },
287 : {
288 : "menu",
289 : roles::MENUPOPUP,
290 : kUseMapRole,
291 : eNoValue,
292 : eNoAction, // XXX: technically accessibles of menupopup role haven't
293 : // any action, but menu can be open or close.
294 : eNoLiveAttr,
295 : kNoReqStates
296 : },
297 : {
298 : "menubar",
299 : roles::MENUBAR,
300 : kUseMapRole,
301 : eNoValue,
302 : eNoAction,
303 : eNoLiveAttr,
304 : kNoReqStates
305 : },
306 : {
307 : "menuitem",
308 : roles::MENUITEM,
309 : kUseMapRole,
310 : eNoValue,
311 : eClickAction,
312 : eNoLiveAttr,
313 : kNoReqStates,
314 : eARIACheckedMixed
315 : },
316 : {
317 : "menuitemcheckbox",
318 : roles::CHECK_MENU_ITEM,
319 : kUseMapRole,
320 : eNoValue,
321 : eClickAction,
322 : eNoLiveAttr,
323 : kNoReqStates,
324 : eARIACheckableMixed
325 : },
326 : {
327 : "menuitemradio",
328 : roles::RADIO_MENU_ITEM,
329 : kUseMapRole,
330 : eNoValue,
331 : eClickAction,
332 : eNoLiveAttr,
333 : kNoReqStates,
334 : eARIACheckableBool
335 : },
336 : {
337 : "option",
338 : roles::OPTION,
339 : kUseMapRole,
340 : eNoValue,
341 : eSelectAction,
342 : eNoLiveAttr,
343 : kNoReqStates,
344 : eARIASelectable,
345 : eARIACheckedMixed
346 : },
347 : {
348 : "presentation",
349 : roles::NOTHING,
350 : kUseMapRole,
351 : eNoValue,
352 : eNoAction,
353 : eNoLiveAttr,
354 : kNoReqStates
355 : },
356 : {
357 : "progressbar",
358 : roles::PROGRESSBAR,
359 : kUseMapRole,
360 : eHasValueMinMax,
361 : eNoAction,
362 : eNoLiveAttr,
363 : states::READONLY
364 : },
365 : {
366 : "radio",
367 : roles::RADIOBUTTON,
368 : kUseMapRole,
369 : eNoValue,
370 : eSelectAction,
371 : eNoLiveAttr,
372 : kNoReqStates,
373 : eARIACheckableBool
374 : },
375 : {
376 : "radiogroup",
377 : roles::GROUPING,
378 : kUseMapRole,
379 : eNoValue,
380 : eNoAction,
381 : eNoLiveAttr,
382 : kNoReqStates
383 : },
384 : {
385 : "region",
386 : roles::PANE,
387 : kUseMapRole,
388 : eNoValue,
389 : eNoAction,
390 : eNoLiveAttr,
391 : kNoReqStates
392 : },
393 : {
394 : "row",
395 : roles::ROW,
396 : kUseMapRole,
397 : eNoValue,
398 : eNoAction,
399 : eNoLiveAttr,
400 : kNoReqStates,
401 : eARIASelectable
402 : },
403 : {
404 : "rowheader",
405 : roles::ROWHEADER,
406 : kUseMapRole,
407 : eNoValue,
408 : eSortAction,
409 : eNoLiveAttr,
410 : kNoReqStates,
411 : eARIASelectable,
412 : eARIAReadonly
413 : },
414 : {
415 : "scrollbar",
416 : roles::SCROLLBAR,
417 : kUseMapRole,
418 : eHasValueMinMax,
419 : eNoAction,
420 : eNoLiveAttr,
421 : kNoReqStates,
422 : eARIAOrientation,
423 : eARIAReadonly
424 : },
425 : {
426 : "separator",
427 : roles::SEPARATOR,
428 : kUseMapRole,
429 : eNoValue,
430 : eNoAction,
431 : eNoLiveAttr,
432 : kNoReqStates,
433 : eARIAOrientation
434 : },
435 : {
436 : "slider",
437 : roles::SLIDER,
438 : kUseMapRole,
439 : eHasValueMinMax,
440 : eNoAction,
441 : eNoLiveAttr,
442 : kNoReqStates,
443 : eARIAOrientation,
444 : eARIAReadonly
445 : },
446 : {
447 : "spinbutton",
448 : roles::SPINBUTTON,
449 : kUseMapRole,
450 : eHasValueMinMax,
451 : eNoAction,
452 : eNoLiveAttr,
453 : kNoReqStates,
454 : eARIAReadonly
455 : },
456 : {
457 : "status",
458 : roles::STATUSBAR,
459 : kUseMapRole,
460 : eNoValue,
461 : eNoAction,
462 : ePoliteLiveAttr,
463 : kNoReqStates
464 : },
465 : {
466 : "tab",
467 : roles::PAGETAB,
468 : kUseMapRole,
469 : eNoValue,
470 : eSwitchAction,
471 : eNoLiveAttr,
472 : kNoReqStates,
473 : eARIASelectable
474 : },
475 : {
476 : "tablist",
477 : roles::PAGETABLIST,
478 : kUseMapRole,
479 : eNoValue,
480 : eNoAction,
481 : ePoliteLiveAttr,
482 : kNoReqStates
483 : },
484 : {
485 : "tabpanel",
486 : roles::PROPERTYPAGE,
487 : kUseMapRole,
488 : eNoValue,
489 : eNoAction,
490 : eNoLiveAttr,
491 : kNoReqStates
492 : },
493 : {
494 : "textbox",
495 : roles::ENTRY,
496 : kUseMapRole,
497 : eNoValue,
498 : eActivateAction,
499 : eNoLiveAttr,
500 : kNoReqStates,
501 : eARIAAutoComplete,
502 : eARIAMultiline,
503 : eARIAReadonlyOrEditable
504 : },
505 : {
506 : "timer",
507 : roles::NOTHING,
508 : kUseNativeRole,
509 : eNoValue,
510 : eNoAction,
511 : eOffLiveAttr,
512 : kNoReqStates
513 : },
514 : {
515 : "toolbar",
516 : roles::TOOLBAR,
517 : kUseMapRole,
518 : eNoValue,
519 : eNoAction,
520 : eNoLiveAttr,
521 : kNoReqStates
522 : },
523 : {
524 : "tooltip",
525 : roles::TOOLTIP,
526 : kUseMapRole,
527 : eNoValue,
528 : eNoAction,
529 : eNoLiveAttr,
530 : kNoReqStates
531 : },
532 : {
533 : "tree",
534 : roles::OUTLINE,
535 : kUseMapRole,
536 : eNoValue,
537 : eNoAction,
538 : eNoLiveAttr,
539 : kNoReqStates,
540 : eARIAReadonly,
541 : eARIAMultiSelectable
542 : },
543 : {
544 : "treegrid",
545 : roles::TREE_TABLE,
546 : kUseMapRole,
547 : eNoValue,
548 : eNoAction,
549 : eNoLiveAttr,
550 : kNoReqStates,
551 : eARIAReadonly,
552 : eARIAMultiSelectable
553 : },
554 : {
555 : "treeitem",
556 : roles::OUTLINEITEM,
557 : kUseMapRole,
558 : eNoValue,
559 : eActivateAction, // XXX: should expose second 'expand/collapse' action based
560 : // on states
561 : eNoLiveAttr,
562 : kNoReqStates,
563 : eARIASelectable,
564 : eARIACheckedMixed
565 : }
566 : };
567 :
568 : PRUint32 nsARIAMap::gWAIRoleMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIRoleMap);
569 :
570 : nsRoleMapEntry nsARIAMap::gLandmarkRoleMap = {
571 : "",
572 : roles::NOTHING,
573 : kUseNativeRole,
574 : eNoValue,
575 : eNoAction,
576 : eNoLiveAttr,
577 : kNoReqStates
578 : };
579 :
580 : nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
581 : "",
582 : roles::NOTHING,
583 : kUseMapRole,
584 : eNoValue,
585 : eNoAction,
586 : eNoLiveAttr,
587 : kNoReqStates
588 : };
589 :
590 1464 : nsStateMapEntry nsARIAMap::gWAIStateMap[] = {
591 : // eARIANone
592 : nsStateMapEntry(),
593 :
594 : // eARIAAutoComplete
595 : nsStateMapEntry(&nsGkAtoms::aria_autocomplete,
596 : "inline", states::SUPPORTS_AUTOCOMPLETION,
597 : "list", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION,
598 : "both", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION),
599 :
600 : // eARIABusy
601 : nsStateMapEntry(&nsGkAtoms::aria_busy,
602 : "true", states::BUSY,
603 : "error", states::INVALID),
604 :
605 : // eARIACheckableBool
606 : nsStateMapEntry(&nsGkAtoms::aria_checked, kBoolType,
607 : states::CHECKABLE, states::CHECKED, 0, true),
608 :
609 : // eARIACheckableMixed
610 : nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType,
611 : states::CHECKABLE, states::CHECKED, 0, true),
612 :
613 : // eARIACheckedMixed
614 : nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType,
615 : states::CHECKABLE, states::CHECKED, 0),
616 :
617 : // eARIADisabled
618 : nsStateMapEntry(&nsGkAtoms::aria_disabled, kBoolType,
619 : 0, states::UNAVAILABLE),
620 :
621 : // eARIAExpanded
622 : nsStateMapEntry(&nsGkAtoms::aria_expanded, kBoolType,
623 : 0, states::EXPANDED, states::COLLAPSED),
624 :
625 : // eARIAHasPopup
626 : nsStateMapEntry(&nsGkAtoms::aria_haspopup, kBoolType,
627 : 0, states::HASPOPUP),
628 :
629 : // eARIAInvalid
630 : nsStateMapEntry(&nsGkAtoms::aria_invalid, kBoolType,
631 : 0, states::INVALID),
632 :
633 : // eARIAMultiline
634 : nsStateMapEntry(&nsGkAtoms::aria_multiline, kBoolType,
635 : 0, states::MULTI_LINE, states::SINGLE_LINE, true),
636 :
637 : // eARIAMultiSelectable
638 : nsStateMapEntry(&nsGkAtoms::aria_multiselectable, kBoolType,
639 : 0, states::MULTISELECTABLE | states::EXTSELECTABLE),
640 :
641 : // eARIAOrientation
642 : nsStateMapEntry(&nsGkAtoms::aria_orientation, eUseFirstState,
643 : "horizontal", states::HORIZONTAL,
644 : "vertical", states::VERTICAL),
645 :
646 : // eARIAPressed
647 : nsStateMapEntry(&nsGkAtoms::aria_pressed, kMixedType,
648 : states::CHECKABLE, states::PRESSED),
649 :
650 : // eARIAReadonly
651 : nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType,
652 : 0, states::READONLY),
653 :
654 : // eARIAReadonlyOrEditable
655 : nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType,
656 : 0, states::READONLY, states::EDITABLE, true),
657 :
658 : // eARIARequired
659 : nsStateMapEntry(&nsGkAtoms::aria_required, kBoolType,
660 : 0, states::REQUIRED),
661 :
662 : // eARIASelectable
663 : nsStateMapEntry(&nsGkAtoms::aria_selected, kBoolType,
664 : states::SELECTABLE, states::SELECTED, 0, true)
665 1464 : };
666 :
667 : /**
668 : * Universal (Global) states:
669 : * The following state rules are applied to any accessible element,
670 : * whether there is an ARIA role or not:
671 : */
672 : eStateMapEntryID nsARIAMap::gWAIUnivStateMap[] = {
673 : eARIABusy,
674 : eARIADisabled,
675 : eARIAExpanded, // Currently under spec review but precedent exists
676 : eARIAHasPopup, // Note this is technically a "property"
677 : eARIAInvalid,
678 : eARIARequired, // XXX not global, Bug 553117
679 : eARIANone
680 : };
681 :
682 :
683 : /**
684 : * ARIA attribute map for attribute characteristics
685 : *
686 : * @note ARIA attributes that don't have any flags are not included here
687 : */
688 : nsAttributeCharacteristics nsARIAMap::gWAIUnivAttrMap[] = {
689 : {&nsGkAtoms::aria_activedescendant, ATTR_BYPASSOBJ },
690 : {&nsGkAtoms::aria_atomic, ATTR_VALTOKEN },
691 : {&nsGkAtoms::aria_busy, ATTR_VALTOKEN },
692 : {&nsGkAtoms::aria_checked, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, /* exposes checkable obj attr */
693 : {&nsGkAtoms::aria_controls, ATTR_BYPASSOBJ },
694 : {&nsGkAtoms::aria_describedby, ATTR_BYPASSOBJ },
695 : {&nsGkAtoms::aria_disabled, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
696 : {&nsGkAtoms::aria_dropeffect, ATTR_VALTOKEN },
697 : {&nsGkAtoms::aria_expanded, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
698 : {&nsGkAtoms::aria_flowto, ATTR_BYPASSOBJ },
699 : {&nsGkAtoms::aria_grabbed, ATTR_VALTOKEN },
700 : {&nsGkAtoms::aria_haspopup, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
701 : {&nsGkAtoms::aria_hidden, ATTR_VALTOKEN },/* always expose obj attr */
702 : {&nsGkAtoms::aria_invalid, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
703 : {&nsGkAtoms::aria_label, ATTR_BYPASSOBJ },
704 : {&nsGkAtoms::aria_labelledby, ATTR_BYPASSOBJ },
705 : {&nsGkAtoms::aria_level, ATTR_BYPASSOBJ }, /* handled via groupPosition */
706 : {&nsGkAtoms::aria_live, ATTR_VALTOKEN },
707 : {&nsGkAtoms::aria_multiline, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
708 : {&nsGkAtoms::aria_multiselectable, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
709 : {&nsGkAtoms::aria_owns, ATTR_BYPASSOBJ },
710 : {&nsGkAtoms::aria_orientation, ATTR_VALTOKEN },
711 : {&nsGkAtoms::aria_posinset, ATTR_BYPASSOBJ }, /* handled via groupPosition */
712 : {&nsGkAtoms::aria_pressed, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
713 : {&nsGkAtoms::aria_readonly, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
714 : {&nsGkAtoms::aria_relevant, ATTR_BYPASSOBJ },
715 : {&nsGkAtoms::aria_required, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
716 : {&nsGkAtoms::aria_selected, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
717 : {&nsGkAtoms::aria_setsize, ATTR_BYPASSOBJ }, /* handled via groupPosition */
718 : {&nsGkAtoms::aria_sort, ATTR_VALTOKEN },
719 : {&nsGkAtoms::aria_valuenow, ATTR_BYPASSOBJ },
720 : {&nsGkAtoms::aria_valuemin, ATTR_BYPASSOBJ },
721 : {&nsGkAtoms::aria_valuemax, ATTR_BYPASSOBJ },
722 : {&nsGkAtoms::aria_valuetext, ATTR_BYPASSOBJ }
723 : };
724 :
725 : PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivAttrMap);
726 :
727 :
728 : ////////////////////////////////////////////////////////////////////////////////
729 : // nsStateMapEntry
730 :
731 1464 : nsStateMapEntry::nsStateMapEntry() :
732 : mAttributeName(nsnull),
733 : mIsToken(false),
734 : mPermanentState(0),
735 : mValue1(nsnull),
736 : mState1(0),
737 : mValue2(nsnull),
738 : mState2(0),
739 : mValue3(nsnull),
740 : mState3(0),
741 : mDefaultState(0),
742 1464 : mDefinedIfAbsent(false)
743 1464 : {}
744 :
745 20496 : nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType,
746 : PRUint64 aPermanentState,
747 : PRUint64 aTrueState,
748 : PRUint64 aFalseState,
749 : bool aDefinedIfAbsent) :
750 : mAttributeName(aAttrName),
751 : mIsToken(true),
752 : mPermanentState(aPermanentState),
753 : mValue1("false"),
754 : mState1(aFalseState),
755 : mValue2(nsnull),
756 : mState2(0),
757 : mValue3(nsnull),
758 : mState3(0),
759 : mDefaultState(aTrueState),
760 20496 : mDefinedIfAbsent(aDefinedIfAbsent)
761 : {
762 20496 : if (aType == kMixedType) {
763 4392 : mValue2 = "mixed";
764 4392 : mState2 = states::MIXED;
765 : }
766 20496 : }
767 :
768 2928 : nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
769 : const char* aValue1, PRUint64 aState1,
770 : const char* aValue2, PRUint64 aState2,
771 : const char* aValue3, PRUint64 aState3) :
772 : mAttributeName(aAttrName), mIsToken(false), mPermanentState(0),
773 : mValue1(aValue1), mState1(aState1),
774 : mValue2(aValue2), mState2(aState2),
775 : mValue3(aValue3), mState3(aState3),
776 2928 : mDefaultState(0), mDefinedIfAbsent(false)
777 : {
778 2928 : }
779 :
780 1464 : nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
781 : EDefaultStateRule aDefaultStateRule,
782 : const char* aValue1, PRUint64 aState1,
783 : const char* aValue2, PRUint64 aState2,
784 : const char* aValue3, PRUint64 aState3) :
785 : mAttributeName(aAttrName), mIsToken(true), mPermanentState(0),
786 : mValue1(aValue1), mState1(aState1),
787 : mValue2(aValue2), mState2(aState2),
788 : mValue3(aValue3), mState3(aState3),
789 1464 : mDefaultState(0), mDefinedIfAbsent(true)
790 : {
791 1464 : if (aDefaultStateRule == eUseFirstState)
792 1464 : mDefaultState = aState1;
793 1464 : }
794 :
795 : bool
796 0 : nsStateMapEntry::MapToStates(nsIContent* aContent, PRUint64* aState,
797 : eStateMapEntryID aStateMapEntryID)
798 : {
799 : // Return true if we should continue.
800 0 : if (aStateMapEntryID == eARIANone)
801 0 : return false;
802 :
803 0 : const nsStateMapEntry& entry = nsARIAMap::gWAIStateMap[aStateMapEntryID];
804 :
805 0 : if (entry.mIsToken) {
806 : // If attribute is considered as defined when it's absent then let's act
807 : // attribute value is "false" supposedly.
808 0 : bool hasAttr = aContent->HasAttr(kNameSpaceID_None, *entry.mAttributeName);
809 0 : if (entry.mDefinedIfAbsent && !hasAttr) {
810 0 : if (entry.mPermanentState)
811 0 : *aState |= entry.mPermanentState;
812 0 : if (entry.mState1)
813 0 : *aState |= entry.mState1;
814 0 : return true;
815 : }
816 :
817 : // We only have attribute state mappings for NMTOKEN (and boolean) based
818 : // ARIA attributes. According to spec, a value of "undefined" is to be
819 : // treated equivalent to "", or the absence of the attribute. We bail out
820 : // for this case here.
821 : // Note: If this method happens to be called with a non-token based
822 : // attribute, for example: aria-label="" or aria-label="undefined", we will
823 : // bail out and not explore a state mapping, which is safe.
824 0 : if (!hasAttr ||
825 : aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
826 0 : nsGkAtoms::_empty, eCaseMatters) ||
827 : aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
828 0 : nsGkAtoms::_undefined, eCaseMatters)) {
829 :
830 0 : if (entry.mPermanentState)
831 0 : *aState &= ~entry.mPermanentState;
832 0 : return true;
833 : }
834 :
835 0 : if (entry.mPermanentState)
836 0 : *aState |= entry.mPermanentState;
837 : }
838 :
839 0 : nsAutoString attrValue;
840 0 : if (!aContent->GetAttr(kNameSpaceID_None, *entry.mAttributeName, attrValue))
841 0 : return true;
842 :
843 : // Apply states for matched value. If no values was matched then apply default
844 : // states.
845 0 : bool applyDefaultStates = true;
846 0 : if (entry.mValue1) {
847 0 : if (attrValue.EqualsASCII(entry.mValue1)) {
848 0 : applyDefaultStates = false;
849 :
850 0 : if (entry.mState1)
851 0 : *aState |= entry.mState1;
852 0 : } else if (entry.mValue2) {
853 0 : if (attrValue.EqualsASCII(entry.mValue2)) {
854 0 : applyDefaultStates = false;
855 :
856 0 : if (entry.mState2)
857 0 : *aState |= entry.mState2;
858 :
859 0 : } else if (entry.mValue3) {
860 0 : if (attrValue.EqualsASCII(entry.mValue3)) {
861 0 : applyDefaultStates = false;
862 :
863 0 : if (entry.mState3)
864 0 : *aState |= entry.mState3;
865 :
866 : }
867 : }
868 : }
869 : }
870 :
871 0 : if (applyDefaultStates) {
872 0 : if (entry.mDefaultState)
873 0 : *aState |= entry.mDefaultState;
874 : }
875 :
876 0 : return true;
877 4392 : }
|