Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/base/ARIAMap.cpp
Line
Count
Source (jump to first uncovered line)
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
#include "mozilla/BinarySearch.h"
19
#include "mozilla/dom/Element.h"
20
21
using namespace mozilla;
22
using namespace mozilla::a11y;
23
using namespace mozilla::a11y::aria;
24
25
static const uint32_t kGenericAccType = 0;
26
27
/**
28
 *  This list of WAI-defined roles are currently hardcoded.
29
 *  Eventually we will most likely be loading an RDF resource that contains this information
30
 *  Using RDF will also allow for role extensibility. See bug 280138.
31
 *
32
 *  Definition of nsRoleMapEntry contains comments explaining this table.
33
 *
34
 *  When no Role enum mapping exists for an ARIA role, the role will be exposed
35
 *  via the object attribute "xml-roles".
36
 */
37
38
static const nsRoleMapEntry sWAIRoleMaps[] =
39
{
40
  { // alert
41
    &nsGkAtoms::alert,
42
    roles::ALERT,
43
    kUseMapRole,
44
    eNoValue,
45
    eNoAction,
46
    eNoLiveAttr,
47
    eAlert,
48
    kNoReqStates
49
  },
50
  { // alertdialog
51
    &nsGkAtoms::alertdialog,
52
    roles::DIALOG,
53
    kUseMapRole,
54
    eNoValue,
55
    eNoAction,
56
    eNoLiveAttr,
57
    kGenericAccType,
58
    kNoReqStates
59
  },
60
  { // application
61
    &nsGkAtoms::application,
62
    roles::APPLICATION,
63
    kUseMapRole,
64
    eNoValue,
65
    eNoAction,
66
    eNoLiveAttr,
67
    eLandmark,
68
    kNoReqStates
69
  },
70
  { // article
71
    &nsGkAtoms::article,
72
    roles::ARTICLE,
73
    kUseMapRole,
74
    eNoValue,
75
    eNoAction,
76
    eNoLiveAttr,
77
    kGenericAccType,
78
    kNoReqStates,
79
    eReadonlyUntilEditable
80
  },
81
  { // banner
82
    &nsGkAtoms::banner,
83
    roles::NOTHING,
84
    kUseNativeRole,
85
    eNoValue,
86
    eNoAction,
87
    eNoLiveAttr,
88
    eLandmark,
89
    kNoReqStates
90
  },
91
  { // blockquote
92
    &nsGkAtoms::blockquote,
93
    roles::BLOCKQUOTE,
94
    kUseMapRole,
95
    eNoValue,
96
    eNoAction,
97
    eNoLiveAttr,
98
    kGenericAccType,
99
  },
100
  { // button
101
    &nsGkAtoms::button,
102
    roles::PUSHBUTTON,
103
    kUseMapRole,
104
    eNoValue,
105
    ePressAction,
106
    eNoLiveAttr,
107
    eButton,
108
    kNoReqStates
109
    // eARIAPressed is auto applied on any button
110
  },
111
  { // caption
112
    &nsGkAtoms::caption,
113
    roles::CAPTION,
114
    kUseMapRole,
115
    eNoValue,
116
    eNoAction,
117
    eNoLiveAttr,
118
    kGenericAccType,
119
  },
120
  { // cell
121
    &nsGkAtoms::cell,
122
    roles::CELL,
123
    kUseMapRole,
124
    eNoValue,
125
    eNoAction,
126
    eNoLiveAttr,
127
    eTableCell,
128
    kNoReqStates
129
  },
130
  { // checkbox
131
    &nsGkAtoms::checkbox,
132
    roles::CHECKBUTTON,
133
    kUseMapRole,
134
    eNoValue,
135
    eCheckUncheckAction,
136
    eNoLiveAttr,
137
    kGenericAccType,
138
    kNoReqStates,
139
    eARIACheckableMixed,
140
    eARIAReadonly
141
  },
142
  { // columnheader
143
    &nsGkAtoms::columnheader,
144
    roles::COLUMNHEADER,
145
    kUseMapRole,
146
    eNoValue,
147
    eSortAction,
148
    eNoLiveAttr,
149
    eTableCell,
150
    kNoReqStates,
151
    eARIASelectableIfDefined,
152
    eARIAReadonlyOrEditableIfDefined
153
  },
154
  { // combobox, which consists of text input and popup
155
    &nsGkAtoms::combobox,
156
    roles::EDITCOMBOBOX,
157
    kUseMapRole,
158
    eNoValue,
159
    eOpenCloseAction,
160
    eNoLiveAttr,
161
    eCombobox,
162
    states::COLLAPSED | states::HASPOPUP,
163
    eARIAAutoComplete,
164
    eARIAReadonly,
165
    eARIAOrientation
166
  },
167
  { // complementary
168
    &nsGkAtoms::complementary,
169
    roles::NOTHING,
170
    kUseNativeRole,
171
    eNoValue,
172
    eNoAction,
173
    eNoLiveAttr,
174
    eLandmark,
175
    kNoReqStates
176
  },
177
  { // contentinfo
178
    &nsGkAtoms::contentinfo,
179
    roles::NOTHING,
180
    kUseNativeRole,
181
    eNoValue,
182
    eNoAction,
183
    eNoLiveAttr,
184
    eLandmark,
185
    kNoReqStates
186
  },
187
  { // dialog
188
    &nsGkAtoms::dialog,
189
    roles::DIALOG,
190
    kUseMapRole,
191
    eNoValue,
192
    eNoAction,
193
    eNoLiveAttr,
194
    kGenericAccType,
195
    kNoReqStates
196
  },
197
  { // directory
198
    &nsGkAtoms::directory,
199
    roles::LIST,
200
    kUseMapRole,
201
    eNoValue,
202
    eNoAction,
203
    eNoLiveAttr,
204
    eList,
205
    states::READONLY
206
  },
207
  { // doc-abstract
208
    &nsGkAtoms::docAbstract,
209
    roles::SECTION,
210
    kUseMapRole,
211
    eNoValue,
212
    eNoAction,
213
    eNoLiveAttr,
214
    kGenericAccType,
215
    kNoReqStates
216
  },
217
  { // doc-acknowledgments
218
    &nsGkAtoms::docAcknowledgments,
219
    roles::LANDMARK,
220
    kUseMapRole,
221
    eNoValue,
222
    eNoAction,
223
    eNoLiveAttr,
224
    eLandmark,
225
    kNoReqStates
226
  },
227
  { // doc-afterword
228
    &nsGkAtoms::docAfterword,
229
    roles::LANDMARK,
230
    kUseMapRole,
231
    eNoValue,
232
    eNoAction,
233
    eNoLiveAttr,
234
    eLandmark,
235
    kNoReqStates
236
  },
237
  { // doc-appendix
238
    &nsGkAtoms::docAppendix,
239
    roles::LANDMARK,
240
    kUseMapRole,
241
    eNoValue,
242
    eNoAction,
243
    eNoLiveAttr,
244
    eLandmark,
245
    kNoReqStates
246
  },
247
  { // doc-backlink
248
    &nsGkAtoms::docBacklink,
249
    roles::LINK,
250
    kUseMapRole,
251
    eNoValue,
252
    eJumpAction,
253
    eNoLiveAttr,
254
    kGenericAccType,
255
    states::LINKED
256
  },
257
  { // doc-biblioentry
258
    &nsGkAtoms::docBiblioentry,
259
    roles::LISTITEM,
260
    kUseMapRole,
261
    eNoValue,
262
    eNoAction,
263
    eNoLiveAttr,
264
    kGenericAccType,
265
    states::READONLY
266
  },
267
  { // doc-bibliography
268
    &nsGkAtoms::docBibliography,
269
    roles::LANDMARK,
270
    kUseMapRole,
271
    eNoValue,
272
    eNoAction,
273
    eNoLiveAttr,
274
    eLandmark,
275
    kNoReqStates
276
  },
277
  { // doc-biblioref
278
    &nsGkAtoms::docBiblioref,
279
    roles::LINK,
280
    kUseMapRole,
281
    eNoValue,
282
    eJumpAction,
283
    eNoLiveAttr,
284
    kGenericAccType,
285
    states::LINKED
286
  },
287
  { // doc-chapter
288
    &nsGkAtoms::docChapter,
289
    roles::LANDMARK,
290
    kUseMapRole,
291
    eNoValue,
292
    eNoAction,
293
    eNoLiveAttr,
294
    eLandmark,
295
    kNoReqStates
296
  },
297
  { // doc-colophon
298
    &nsGkAtoms::docColophon,
299
    roles::SECTION,
300
    kUseMapRole,
301
    eNoValue,
302
    eNoAction,
303
    eNoLiveAttr,
304
    kGenericAccType,
305
    kNoReqStates
306
  },
307
  { // doc-conclusion
308
    &nsGkAtoms::docConclusion,
309
    roles::LANDMARK,
310
    kUseMapRole,
311
    eNoValue,
312
    eNoAction,
313
    eNoLiveAttr,
314
    eLandmark,
315
    kNoReqStates
316
  },
317
  { // doc-cover
318
    &nsGkAtoms::docCover,
319
    roles::GRAPHIC,
320
    kUseMapRole,
321
    eNoValue,
322
    eNoAction,
323
    eNoLiveAttr,
324
    kGenericAccType,
325
    kNoReqStates
326
  },
327
  { // doc-credit
328
    &nsGkAtoms::docCredit,
329
    roles::SECTION,
330
    kUseMapRole,
331
    eNoValue,
332
    eNoAction,
333
    eNoLiveAttr,
334
    kGenericAccType,
335
    kNoReqStates
336
  },
337
  { // doc-credits
338
    &nsGkAtoms::docCredits,
339
    roles::LANDMARK,
340
    kUseMapRole,
341
    eNoValue,
342
    eNoAction,
343
    eNoLiveAttr,
344
    eLandmark,
345
    kNoReqStates
346
  },
347
  { // doc-dedication
348
    &nsGkAtoms::docDedication,
349
    roles::SECTION,
350
    kUseMapRole,
351
    eNoValue,
352
    eNoAction,
353
    eNoLiveAttr,
354
    kGenericAccType,
355
    kNoReqStates
356
  },
357
  { // doc-endnote
358
    &nsGkAtoms::docEndnote,
359
    roles::LISTITEM,
360
    kUseMapRole,
361
    eNoValue,
362
    eNoAction,
363
    eNoLiveAttr,
364
    kGenericAccType,
365
    states::READONLY
366
  },
367
  { // doc-endnotes
368
    &nsGkAtoms::docEndnotes,
369
    roles::LANDMARK,
370
    kUseMapRole,
371
    eNoValue,
372
    eNoAction,
373
    eNoLiveAttr,
374
    eLandmark,
375
    kNoReqStates
376
  },
377
  { // doc-epigraph
378
    &nsGkAtoms::docEpigraph,
379
    roles::SECTION,
380
    kUseMapRole,
381
    eNoValue,
382
    eNoAction,
383
    eNoLiveAttr,
384
    kGenericAccType,
385
    kNoReqStates
386
  },
387
  { // doc-epilogue
388
    &nsGkAtoms::docEpilogue,
389
    roles::LANDMARK,
390
    kUseMapRole,
391
    eNoValue,
392
    eNoAction,
393
    eNoLiveAttr,
394
    eLandmark,
395
    kNoReqStates
396
  },
397
  { // doc-errata
398
    &nsGkAtoms::docErrata,
399
    roles::LANDMARK,
400
    kUseMapRole,
401
    eNoValue,
402
    eNoAction,
403
    eNoLiveAttr,
404
    eLandmark,
405
    kNoReqStates
406
  },
407
  { // doc-example
408
    &nsGkAtoms::docExample,
409
    roles::SECTION,
410
    kUseMapRole,
411
    eNoValue,
412
    eNoAction,
413
    eNoLiveAttr,
414
    kGenericAccType,
415
    kNoReqStates
416
  },
417
  { // doc-footnote
418
    &nsGkAtoms::docFootnote,
419
    roles::FOOTNOTE,
420
    kUseMapRole,
421
    eNoValue,
422
    eNoAction,
423
    eNoLiveAttr,
424
    eLandmark,
425
    kNoReqStates
426
  },
427
  { // doc-foreword
428
    &nsGkAtoms::docForeword,
429
    roles::LANDMARK,
430
    kUseMapRole,
431
    eNoValue,
432
    eNoAction,
433
    eNoLiveAttr,
434
    eLandmark,
435
    kNoReqStates
436
  },
437
  { // doc-glossary
438
    &nsGkAtoms::docGlossary,
439
    roles::LANDMARK,
440
    kUseMapRole,
441
    eNoValue,
442
    eNoAction,
443
    eNoLiveAttr,
444
    eLandmark,
445
    kNoReqStates
446
  },
447
  { // doc-glossref
448
    &nsGkAtoms::docGlossref,
449
    roles::LINK,
450
    kUseMapRole,
451
    eNoValue,
452
    eJumpAction,
453
    eNoLiveAttr,
454
    kGenericAccType,
455
    states::LINKED
456
  },
457
  { // doc-index
458
    &nsGkAtoms::docIndex,
459
    roles::NAVIGATION,
460
    kUseMapRole,
461
    eNoValue,
462
    eNoAction,
463
    eNoLiveAttr,
464
    eLandmark,
465
    kNoReqStates
466
  },
467
  { // doc-introduction
468
    &nsGkAtoms::docIntroduction,
469
    roles::LANDMARK,
470
    kUseMapRole,
471
    eNoValue,
472
    eNoAction,
473
    eNoLiveAttr,
474
    eLandmark,
475
    kNoReqStates
476
  },
477
  { // doc-noteref
478
    &nsGkAtoms::docNoteref,
479
    roles::LINK,
480
    kUseMapRole,
481
    eNoValue,
482
    eJumpAction,
483
    eNoLiveAttr,
484
    kGenericAccType,
485
    states::LINKED
486
  },
487
  { // doc-notice
488
    &nsGkAtoms::docNotice,
489
    roles::NOTE,
490
    kUseMapRole,
491
    eNoValue,
492
    eNoAction,
493
    eNoLiveAttr,
494
    kGenericAccType,
495
    kNoReqStates
496
  },
497
  { // doc-pagebreak
498
    &nsGkAtoms::docPagebreak,
499
    roles::SEPARATOR,
500
    kUseMapRole,
501
    eNoValue,
502
    eNoAction,
503
    eNoLiveAttr,
504
    kGenericAccType,
505
    kNoReqStates
506
  },
507
  { // doc-pagelist
508
    &nsGkAtoms::docPagelist,
509
    roles::NAVIGATION,
510
    kUseMapRole,
511
    eNoValue,
512
    eNoAction,
513
    eNoLiveAttr,
514
    eLandmark,
515
    kNoReqStates
516
  },
517
  { // doc-part
518
    &nsGkAtoms::docPart,
519
    roles::LANDMARK,
520
    kUseMapRole,
521
    eNoValue,
522
    eNoAction,
523
    eNoLiveAttr,
524
    eLandmark,
525
    kNoReqStates
526
  },
527
  { // doc-preface
528
    &nsGkAtoms::docPreface,
529
    roles::LANDMARK,
530
    kUseMapRole,
531
    eNoValue,
532
    eNoAction,
533
    eNoLiveAttr,
534
    eLandmark,
535
    kNoReqStates
536
  },
537
  { // doc-prologue
538
    &nsGkAtoms::docPrologue,
539
    roles::LANDMARK,
540
    kUseMapRole,
541
    eNoValue,
542
    eNoAction,
543
    eNoLiveAttr,
544
    eLandmark,
545
    kNoReqStates
546
  },
547
  { // doc-pullquote
548
    &nsGkAtoms::docPullquote,
549
    roles::SECTION,
550
    kUseMapRole,
551
    eNoValue,
552
    eNoAction,
553
    eNoLiveAttr,
554
    kGenericAccType,
555
    kNoReqStates
556
  },
557
  { // doc-qna
558
    &nsGkAtoms::docQna,
559
    roles::SECTION,
560
    kUseMapRole,
561
    eNoValue,
562
    eNoAction,
563
    eNoLiveAttr,
564
    kGenericAccType,
565
    kNoReqStates
566
  },
567
  { // doc-subtitle
568
    &nsGkAtoms::docSubtitle,
569
    roles::HEADING,
570
    kUseMapRole,
571
    eNoValue,
572
    eNoAction,
573
    eNoLiveAttr,
574
    kGenericAccType,
575
    kNoReqStates
576
  },
577
  { // doc-tip
578
    &nsGkAtoms::docTip,
579
    roles::NOTE,
580
    kUseMapRole,
581
    eNoValue,
582
    eNoAction,
583
    eNoLiveAttr,
584
    kGenericAccType,
585
    kNoReqStates
586
  },
587
  { // doc-toc
588
    &nsGkAtoms::docToc,
589
    roles::NAVIGATION,
590
    kUseMapRole,
591
    eNoValue,
592
    eNoAction,
593
    eNoLiveAttr,
594
    eLandmark,
595
    kNoReqStates
596
  },
597
  { // document
598
    &nsGkAtoms::document,
599
    roles::NON_NATIVE_DOCUMENT,
600
    kUseMapRole,
601
    eNoValue,
602
    eNoAction,
603
    eNoLiveAttr,
604
    kGenericAccType,
605
    kNoReqStates,
606
    eReadonlyUntilEditable
607
  },
608
  { // feed
609
    &nsGkAtoms::feed,
610
    roles::GROUPING,
611
    kUseMapRole,
612
    eNoValue,
613
    eNoAction,
614
    eNoLiveAttr,
615
    kGenericAccType,
616
    kNoReqStates
617
  },
618
  { // figure
619
    &nsGkAtoms::figure,
620
    roles::FIGURE,
621
    kUseMapRole,
622
    eNoValue,
623
    eNoAction,
624
    eNoLiveAttr,
625
    kGenericAccType,
626
    kNoReqStates
627
  },
628
  { // form
629
    &nsGkAtoms::form,
630
    roles::FORM,
631
    kUseMapRole,
632
    eNoValue,
633
    eNoAction,
634
    eNoLiveAttr,
635
    eLandmark,
636
    kNoReqStates
637
  },
638
  { // graphics-document
639
    &nsGkAtoms::graphicsDocument,
640
    roles::NON_NATIVE_DOCUMENT,
641
    kUseMapRole,
642
    eNoValue,
643
    eNoAction,
644
    eNoLiveAttr,
645
    kGenericAccType,
646
    kNoReqStates,
647
    eReadonlyUntilEditable
648
  },
649
  { // graphics-object
650
    &nsGkAtoms::graphicsObject,
651
    roles::GROUPING,
652
    kUseMapRole,
653
    eNoValue,
654
    eNoAction,
655
    eNoLiveAttr,
656
    kGenericAccType,
657
    kNoReqStates
658
  },
659
  { // graphics-symbol
660
    &nsGkAtoms::graphicsSymbol,
661
    roles::GRAPHIC,
662
    kUseMapRole,
663
    eNoValue,
664
    eNoAction,
665
    eNoLiveAttr,
666
    kGenericAccType,
667
    kNoReqStates
668
  },
669
  { // grid
670
    &nsGkAtoms::grid,
671
    roles::TABLE,
672
    kUseMapRole,
673
    eNoValue,
674
    eNoAction,
675
    eNoLiveAttr,
676
    eSelect | eTable,
677
    kNoReqStates,
678
    eARIAMultiSelectable,
679
    eARIAReadonlyOrEditable,
680
    eFocusableUntilDisabled
681
  },
682
  { // gridcell
683
    &nsGkAtoms::gridcell,
684
    roles::GRID_CELL,
685
    kUseMapRole,
686
    eNoValue,
687
    eNoAction,
688
    eNoLiveAttr,
689
    eTableCell,
690
    kNoReqStates,
691
    eARIASelectable,
692
    eARIAReadonlyOrEditableIfDefined
693
  },
694
  { // group
695
    &nsGkAtoms::group,
696
    roles::GROUPING,
697
    kUseMapRole,
698
    eNoValue,
699
    eNoAction,
700
    eNoLiveAttr,
701
    kGenericAccType,
702
    kNoReqStates
703
  },
704
  { // heading
705
    &nsGkAtoms::heading,
706
    roles::HEADING,
707
    kUseMapRole,
708
    eNoValue,
709
    eNoAction,
710
    eNoLiveAttr,
711
    kGenericAccType,
712
    kNoReqStates
713
  },
714
  { // img
715
    &nsGkAtoms::img,
716
    roles::GRAPHIC,
717
    kUseMapRole,
718
    eNoValue,
719
    eNoAction,
720
    eNoLiveAttr,
721
    kGenericAccType,
722
    kNoReqStates
723
  },
724
  { // key
725
    &nsGkAtoms::key,
726
    roles::KEY,
727
    kUseMapRole,
728
    eNoValue,
729
    ePressAction,
730
    eNoLiveAttr,
731
    kGenericAccType,
732
    kNoReqStates,
733
    eARIAPressed
734
  },
735
  { // link
736
    &nsGkAtoms::link,
737
    roles::LINK,
738
    kUseMapRole,
739
    eNoValue,
740
    eJumpAction,
741
    eNoLiveAttr,
742
    kGenericAccType,
743
    states::LINKED
744
  },
745
  { // list
746
    &nsGkAtoms::list_,
747
    roles::LIST,
748
    kUseMapRole,
749
    eNoValue,
750
    eNoAction,
751
    eNoLiveAttr,
752
    eList,
753
    states::READONLY
754
  },
755
  { // listbox
756
    &nsGkAtoms::listbox,
757
    roles::LISTBOX,
758
    kUseMapRole,
759
    eNoValue,
760
    eNoAction,
761
    eNoLiveAttr,
762
    eListControl | eSelect,
763
    states::VERTICAL,
764
    eARIAMultiSelectable,
765
    eARIAReadonly,
766
    eFocusableUntilDisabled,
767
    eARIAOrientation
768
  },
769
  { // listitem
770
    &nsGkAtoms::listitem,
771
    roles::LISTITEM,
772
    kUseMapRole,
773
    eNoValue,
774
    eNoAction, // XXX: should depend on state, parent accessible
775
    eNoLiveAttr,
776
    kGenericAccType,
777
    states::READONLY
778
  },
779
  { // log
780
    &nsGkAtoms::log_,
781
    roles::NOTHING,
782
    kUseNativeRole,
783
    eNoValue,
784
    eNoAction,
785
    ePoliteLiveAttr,
786
    kGenericAccType,
787
    kNoReqStates
788
  },
789
  { // main
790
    &nsGkAtoms::main,
791
    roles::NOTHING,
792
    kUseNativeRole,
793
    eNoValue,
794
    eNoAction,
795
    eNoLiveAttr,
796
    eLandmark,
797
    kNoReqStates
798
  },
799
  { // marquee
800
    &nsGkAtoms::marquee,
801
    roles::ANIMATION,
802
    kUseMapRole,
803
    eNoValue,
804
    eNoAction,
805
    eOffLiveAttr,
806
    kGenericAccType,
807
    kNoReqStates
808
  },
809
  { // math
810
    &nsGkAtoms::math,
811
    roles::FLAT_EQUATION,
812
    kUseMapRole,
813
    eNoValue,
814
    eNoAction,
815
    eNoLiveAttr,
816
    kGenericAccType,
817
    kNoReqStates
818
  },
819
  { // menu
820
    &nsGkAtoms::menu,
821
    roles::MENUPOPUP,
822
    kUseMapRole,
823
    eNoValue,
824
    eNoAction, // XXX: technically accessibles of menupopup role haven't
825
               // any action, but menu can be open or close.
826
    eNoLiveAttr,
827
    kGenericAccType,
828
    states::VERTICAL,
829
    eARIAOrientation
830
  },
831
  { // menubar
832
    &nsGkAtoms::menubar,
833
    roles::MENUBAR,
834
    kUseMapRole,
835
    eNoValue,
836
    eNoAction,
837
    eNoLiveAttr,
838
    kGenericAccType,
839
    states::HORIZONTAL,
840
    eARIAOrientation
841
  },
842
  { // menuitem
843
    &nsGkAtoms::menuitem,
844
    roles::MENUITEM,
845
    kUseMapRole,
846
    eNoValue,
847
    eClickAction,
848
    eNoLiveAttr,
849
    kGenericAccType,
850
    kNoReqStates
851
  },
852
  { // menuitemcheckbox
853
    &nsGkAtoms::menuitemcheckbox,
854
    roles::CHECK_MENU_ITEM,
855
    kUseMapRole,
856
    eNoValue,
857
    eClickAction,
858
    eNoLiveAttr,
859
    kGenericAccType,
860
    kNoReqStates,
861
    eARIACheckableMixed,
862
    eARIAReadonly
863
  },
864
  { // menuitemradio
865
    &nsGkAtoms::menuitemradio,
866
    roles::RADIO_MENU_ITEM,
867
    kUseMapRole,
868
    eNoValue,
869
    eClickAction,
870
    eNoLiveAttr,
871
    kGenericAccType,
872
    kNoReqStates,
873
    eARIACheckableBool,
874
    eARIAReadonly
875
  },
876
  { // navigation
877
    &nsGkAtoms::navigation,
878
    roles::NOTHING,
879
    kUseNativeRole,
880
    eNoValue,
881
    eNoAction,
882
    eNoLiveAttr,
883
    eLandmark,
884
    kNoReqStates
885
  },
886
  { // none
887
    &nsGkAtoms::none,
888
    roles::NOTHING,
889
    kUseMapRole,
890
    eNoValue,
891
    eNoAction,
892
    eNoLiveAttr,
893
    kGenericAccType,
894
    kNoReqStates
895
  },
896
  { // note
897
    &nsGkAtoms::note_,
898
    roles::NOTE,
899
    kUseMapRole,
900
    eNoValue,
901
    eNoAction,
902
    eNoLiveAttr,
903
    kGenericAccType,
904
    kNoReqStates
905
  },
906
  { // option
907
    &nsGkAtoms::option,
908
    roles::OPTION,
909
    kUseMapRole,
910
    eNoValue,
911
    eSelectAction,
912
    eNoLiveAttr,
913
    kGenericAccType,
914
    kNoReqStates,
915
    eARIASelectable,
916
    eARIACheckedMixed
917
  },
918
  { // paragraph
919
    &nsGkAtoms::paragraph,
920
    roles::PARAGRAPH,
921
    kUseMapRole,
922
    eNoValue,
923
    eNoAction,
924
    eNoLiveAttr,
925
    kGenericAccType,
926
  },
927
  { // presentation
928
    &nsGkAtoms::presentation,
929
    roles::NOTHING,
930
    kUseMapRole,
931
    eNoValue,
932
    eNoAction,
933
    eNoLiveAttr,
934
    kGenericAccType,
935
    kNoReqStates
936
  },
937
  { // progressbar
938
    &nsGkAtoms::progressbar,
939
    roles::PROGRESSBAR,
940
    kUseMapRole,
941
    eHasValueMinMax,
942
    eNoAction,
943
    eNoLiveAttr,
944
    kGenericAccType,
945
    states::READONLY,
946
    eIndeterminateIfNoValue
947
  },
948
  { // radio
949
    &nsGkAtoms::radio,
950
    roles::RADIOBUTTON,
951
    kUseMapRole,
952
    eNoValue,
953
    eSelectAction,
954
    eNoLiveAttr,
955
    kGenericAccType,
956
    kNoReqStates,
957
    eARIACheckableBool
958
  },
959
  { // radiogroup
960
    &nsGkAtoms::radiogroup,
961
    roles::RADIO_GROUP,
962
    kUseMapRole,
963
    eNoValue,
964
    eNoAction,
965
    eNoLiveAttr,
966
    kGenericAccType,
967
    kNoReqStates,
968
    eARIAOrientation,
969
    eARIAReadonly
970
  },
971
  { // region
972
    &nsGkAtoms::region,
973
    roles::REGION,
974
    kUseMapRole,
975
    eNoValue,
976
    eNoAction,
977
    eNoLiveAttr,
978
    eLandmark,
979
    kNoReqStates
980
  },
981
  { // row
982
    &nsGkAtoms::row,
983
    roles::ROW,
984
    kUseMapRole,
985
    eNoValue,
986
    eNoAction,
987
    eNoLiveAttr,
988
    eTableRow,
989
    kNoReqStates,
990
    eARIASelectable
991
  },
992
  { // rowgroup
993
    &nsGkAtoms::rowgroup,
994
    roles::GROUPING,
995
    kUseMapRole,
996
    eNoValue,
997
    eNoAction,
998
    eNoLiveAttr,
999
    kGenericAccType,
1000
    kNoReqStates
1001
  },
1002
  { // rowheader
1003
    &nsGkAtoms::rowheader,
1004
    roles::ROWHEADER,
1005
    kUseMapRole,
1006
    eNoValue,
1007
    eSortAction,
1008
    eNoLiveAttr,
1009
    eTableCell,
1010
    kNoReqStates,
1011
    eARIASelectableIfDefined,
1012
    eARIAReadonlyOrEditableIfDefined
1013
  },
1014
  { // scrollbar
1015
    &nsGkAtoms::scrollbar,
1016
    roles::SCROLLBAR,
1017
    kUseMapRole,
1018
    eHasValueMinMax,
1019
    eNoAction,
1020
    eNoLiveAttr,
1021
    kGenericAccType,
1022
    states::VERTICAL,
1023
    eARIAOrientation,
1024
    eARIAReadonly
1025
  },
1026
  { // search
1027
    &nsGkAtoms::search,
1028
    roles::NOTHING,
1029
    kUseNativeRole,
1030
    eNoValue,
1031
    eNoAction,
1032
    eNoLiveAttr,
1033
    eLandmark,
1034
    kNoReqStates
1035
  },
1036
  { // searchbox
1037
    &nsGkAtoms::searchbox,
1038
    roles::ENTRY,
1039
    kUseMapRole,
1040
    eNoValue,
1041
    eActivateAction,
1042
    eNoLiveAttr,
1043
    kGenericAccType,
1044
    kNoReqStates,
1045
    eARIAAutoComplete,
1046
    eARIAMultiline,
1047
    eARIAReadonlyOrEditable
1048
  },
1049
  { // separator
1050
    &nsGkAtoms::separator_,
1051
    roles::SEPARATOR,
1052
    kUseMapRole,
1053
    eHasValueMinMaxIfFocusable,
1054
    eNoAction,
1055
    eNoLiveAttr,
1056
    kGenericAccType,
1057
    states::HORIZONTAL,
1058
    eARIAOrientation
1059
  },
1060
  { // slider
1061
    &nsGkAtoms::slider,
1062
    roles::SLIDER,
1063
    kUseMapRole,
1064
    eHasValueMinMax,
1065
    eNoAction,
1066
    eNoLiveAttr,
1067
    kGenericAccType,
1068
    states::HORIZONTAL,
1069
    eARIAOrientation,
1070
    eARIAReadonly
1071
  },
1072
  { // spinbutton
1073
    &nsGkAtoms::spinbutton,
1074
    roles::SPINBUTTON,
1075
    kUseMapRole,
1076
    eHasValueMinMax,
1077
    eNoAction,
1078
    eNoLiveAttr,
1079
    kGenericAccType,
1080
    kNoReqStates,
1081
    eARIAReadonly
1082
  },
1083
  { // status
1084
    &nsGkAtoms::status,
1085
    roles::STATUSBAR,
1086
    kUseMapRole,
1087
    eNoValue,
1088
    eNoAction,
1089
    ePoliteLiveAttr,
1090
    kGenericAccType,
1091
    kNoReqStates
1092
  },
1093
  { // switch
1094
    &nsGkAtoms::svgSwitch,
1095
    roles::SWITCH,
1096
    kUseMapRole,
1097
    eNoValue,
1098
    eCheckUncheckAction,
1099
    eNoLiveAttr,
1100
    kGenericAccType,
1101
    kNoReqStates,
1102
    eARIACheckableBool,
1103
    eARIAReadonly
1104
  },
1105
  { // tab
1106
    &nsGkAtoms::tab,
1107
    roles::PAGETAB,
1108
    kUseMapRole,
1109
    eNoValue,
1110
    eSwitchAction,
1111
    eNoLiveAttr,
1112
    kGenericAccType,
1113
    kNoReqStates,
1114
    eARIASelectable
1115
  },
1116
  { // table
1117
    &nsGkAtoms::table,
1118
    roles::TABLE,
1119
    kUseMapRole,
1120
    eNoValue,
1121
    eNoAction,
1122
    eNoLiveAttr,
1123
    eTable,
1124
    kNoReqStates,
1125
    eARIASelectable
1126
  },
1127
  { // tablist
1128
    &nsGkAtoms::tablist,
1129
    roles::PAGETABLIST,
1130
    kUseMapRole,
1131
    eNoValue,
1132
    eNoAction,
1133
    eNoLiveAttr,
1134
    eSelect,
1135
    states::HORIZONTAL,
1136
    eARIAOrientation,
1137
    eARIAMultiSelectable
1138
  },
1139
  { // tabpanel
1140
    &nsGkAtoms::tabpanel,
1141
    roles::PROPERTYPAGE,
1142
    kUseMapRole,
1143
    eNoValue,
1144
    eNoAction,
1145
    eNoLiveAttr,
1146
    kGenericAccType,
1147
    kNoReqStates
1148
  },
1149
  { // term
1150
    &nsGkAtoms::term,
1151
    roles::TERM,
1152
    kUseMapRole,
1153
    eNoValue,
1154
    eNoAction,
1155
    eNoLiveAttr,
1156
    kGenericAccType,
1157
    states::READONLY
1158
  },
1159
  { // textbox
1160
    &nsGkAtoms::textbox,
1161
    roles::ENTRY,
1162
    kUseMapRole,
1163
    eNoValue,
1164
    eActivateAction,
1165
    eNoLiveAttr,
1166
    kGenericAccType,
1167
    kNoReqStates,
1168
    eARIAAutoComplete,
1169
    eARIAMultiline,
1170
    eARIAReadonlyOrEditable
1171
  },
1172
  { // timer
1173
    &nsGkAtoms::timer,
1174
    roles::NOTHING,
1175
    kUseNativeRole,
1176
    eNoValue,
1177
    eNoAction,
1178
    eOffLiveAttr,
1179
    kNoReqStates
1180
  },
1181
  { // toolbar
1182
    &nsGkAtoms::toolbar,
1183
    roles::TOOLBAR,
1184
    kUseMapRole,
1185
    eNoValue,
1186
    eNoAction,
1187
    eNoLiveAttr,
1188
    kGenericAccType,
1189
    states::HORIZONTAL,
1190
    eARIAOrientation
1191
  },
1192
  { // tooltip
1193
    &nsGkAtoms::tooltip,
1194
    roles::TOOLTIP,
1195
    kUseMapRole,
1196
    eNoValue,
1197
    eNoAction,
1198
    eNoLiveAttr,
1199
    kGenericAccType,
1200
    kNoReqStates
1201
  },
1202
  { // tree
1203
    &nsGkAtoms::tree,
1204
    roles::OUTLINE,
1205
    kUseMapRole,
1206
    eNoValue,
1207
    eNoAction,
1208
    eNoLiveAttr,
1209
    eSelect,
1210
    states::VERTICAL,
1211
    eARIAReadonly,
1212
    eARIAMultiSelectable,
1213
    eFocusableUntilDisabled,
1214
    eARIAOrientation
1215
  },
1216
  { // treegrid
1217
    &nsGkAtoms::treegrid,
1218
    roles::TREE_TABLE,
1219
    kUseMapRole,
1220
    eNoValue,
1221
    eNoAction,
1222
    eNoLiveAttr,
1223
    eSelect | eTable,
1224
    kNoReqStates,
1225
    eARIAReadonlyOrEditable,
1226
    eARIAMultiSelectable,
1227
    eFocusableUntilDisabled,
1228
    eARIAOrientation
1229
  },
1230
  { // treeitem
1231
    &nsGkAtoms::treeitem,
1232
    roles::OUTLINEITEM,
1233
    kUseMapRole,
1234
    eNoValue,
1235
    eActivateAction, // XXX: should expose second 'expand/collapse' action based
1236
                     // on states
1237
    eNoLiveAttr,
1238
    kGenericAccType,
1239
    kNoReqStates,
1240
    eARIASelectable,
1241
    eARIACheckedMixed
1242
  }
1243
};
1244
1245
static const nsRoleMapEntry sLandmarkRoleMap = {
1246
  &nsGkAtoms::_empty,
1247
  roles::NOTHING,
1248
  kUseNativeRole,
1249
  eNoValue,
1250
  eNoAction,
1251
  eNoLiveAttr,
1252
  kGenericAccType,
1253
  kNoReqStates
1254
};
1255
1256
nsRoleMapEntry aria::gEmptyRoleMap = {
1257
  &nsGkAtoms::_empty,
1258
  roles::NOTHING,
1259
  kUseMapRole,
1260
  eNoValue,
1261
  eNoAction,
1262
  eNoLiveAttr,
1263
  kGenericAccType,
1264
  kNoReqStates
1265
};
1266
1267
/**
1268
 * Universal (Global) states:
1269
 * The following state rules are applied to any accessible element,
1270
 * whether there is an ARIA role or not:
1271
 */
1272
static const EStateRule sWAIUnivStateMap[] = {
1273
  eARIABusy,
1274
  eARIACurrent,
1275
  eARIADisabled,
1276
  eARIAExpanded,  // Currently under spec review but precedent exists
1277
  eARIAHasPopup,  // Note this is a tokenised attribute starting in ARIA 1.1
1278
  eARIAInvalid,
1279
  eARIAModal,
1280
  eARIARequired,  // XXX not global, Bug 553117
1281
  eARIANone
1282
};
1283
1284
1285
/**
1286
 * ARIA attribute map for attribute characteristics.
1287
 * @note ARIA attributes that don't have any flags are not included here.
1288
 */
1289
1290
struct AttrCharacteristics
1291
{
1292
  nsStaticAtom** attributeName;
1293
  const uint8_t characteristics;
1294
};
1295
1296
static const AttrCharacteristics gWAIUnivAttrMap[] = {
1297
  {&nsGkAtoms::aria_activedescendant,  ATTR_BYPASSOBJ                               },
1298
  {&nsGkAtoms::aria_atomic,   ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
1299
  {&nsGkAtoms::aria_busy,                               ATTR_VALTOKEN | ATTR_GLOBAL },
1300
  {&nsGkAtoms::aria_checked,           ATTR_BYPASSOBJ | ATTR_VALTOKEN               }, /* exposes checkable obj attr */
1301
  {&nsGkAtoms::aria_controls,          ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1302
  {&nsGkAtoms::aria_describedby,       ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1303
  {&nsGkAtoms::aria_details,           ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1304
  {&nsGkAtoms::aria_disabled,          ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
1305
  {&nsGkAtoms::aria_dropeffect,                         ATTR_VALTOKEN | ATTR_GLOBAL },
1306
  {&nsGkAtoms::aria_errormessage,      ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1307
  {&nsGkAtoms::aria_expanded,          ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
1308
  {&nsGkAtoms::aria_flowto,            ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1309
  {&nsGkAtoms::aria_grabbed,                            ATTR_VALTOKEN | ATTR_GLOBAL },
1310
  {&nsGkAtoms::aria_haspopup,          ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
1311
  {&nsGkAtoms::aria_hidden,            ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, /* handled special way */
1312
  {&nsGkAtoms::aria_invalid,           ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
1313
  {&nsGkAtoms::aria_label,             ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1314
  {&nsGkAtoms::aria_labelledby,        ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1315
  {&nsGkAtoms::aria_level,             ATTR_BYPASSOBJ                               }, /* handled via groupPosition */
1316
  {&nsGkAtoms::aria_live,                               ATTR_VALTOKEN | ATTR_GLOBAL },
1317
  {&nsGkAtoms::aria_modal,             ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
1318
  {&nsGkAtoms::aria_multiline,         ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
1319
  {&nsGkAtoms::aria_multiselectable,   ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
1320
  {&nsGkAtoms::aria_owns,              ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1321
  {&nsGkAtoms::aria_orientation,                        ATTR_VALTOKEN               },
1322
  {&nsGkAtoms::aria_posinset,          ATTR_BYPASSOBJ                               }, /* handled via groupPosition */
1323
  {&nsGkAtoms::aria_pressed,           ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
1324
  {&nsGkAtoms::aria_readonly,          ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
1325
  {&nsGkAtoms::aria_relevant,          ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
1326
  {&nsGkAtoms::aria_required,          ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
1327
  {&nsGkAtoms::aria_selected,          ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
1328
  {&nsGkAtoms::aria_setsize,           ATTR_BYPASSOBJ                               }, /* handled via groupPosition */
1329
  {&nsGkAtoms::aria_sort,                               ATTR_VALTOKEN               },
1330
  {&nsGkAtoms::aria_valuenow,          ATTR_BYPASSOBJ                               },
1331
  {&nsGkAtoms::aria_valuemin,          ATTR_BYPASSOBJ                               },
1332
  {&nsGkAtoms::aria_valuemax,          ATTR_BYPASSOBJ                               },
1333
  {&nsGkAtoms::aria_valuetext,         ATTR_BYPASSOBJ                               }
1334
};
1335
1336
namespace {
1337
1338
struct RoleComparator
1339
{
1340
  const nsDependentSubstring& mRole;
1341
0
  explicit RoleComparator(const nsDependentSubstring& aRole) : mRole(aRole) {}
1342
0
  int operator()(const nsRoleMapEntry& aEntry) const {
1343
0
    return Compare(mRole, aEntry.ARIARoleString());
1344
0
  }
1345
};
1346
1347
}
1348
1349
const nsRoleMapEntry*
1350
aria::GetRoleMap(dom::Element* aEl)
1351
0
{
1352
0
  return GetRoleMapFromIndex(GetRoleMapIndex(aEl));
1353
0
}
1354
1355
uint8_t
1356
aria::GetRoleMapIndex(dom::Element* aEl)
1357
0
{
1358
0
  nsAutoString roles;
1359
0
  if (!aEl || !aEl->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roles) ||
1360
0
      roles.IsEmpty()) {
1361
0
    // We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
1362
0
    return NO_ROLE_MAP_ENTRY_INDEX;
1363
0
  }
1364
0
1365
0
  nsWhitespaceTokenizer tokenizer(roles);
1366
0
  while (tokenizer.hasMoreTokens()) {
1367
0
    // Do a binary search through table for the next role in role list
1368
0
    const nsDependentSubstring role = tokenizer.nextToken();
1369
0
    size_t idx;
1370
0
    if (BinarySearchIf(sWAIRoleMaps, 0, ArrayLength(sWAIRoleMaps),
1371
0
                       RoleComparator(role), &idx)) {
1372
0
      return idx;
1373
0
    }
1374
0
  }
1375
0
1376
0
  // Always use some entry index if there is a non-empty role string
1377
0
  // To ensure an accessible object is created
1378
0
  return LANDMARK_ROLE_MAP_ENTRY_INDEX;
1379
0
}
1380
1381
1382
const nsRoleMapEntry*
1383
aria::GetRoleMapFromIndex(uint8_t aRoleMapIndex)
1384
{
1385
  switch (aRoleMapIndex) {
1386
    case NO_ROLE_MAP_ENTRY_INDEX:
1387
      return nullptr;
1388
    case EMPTY_ROLE_MAP_ENTRY_INDEX:
1389
      return &gEmptyRoleMap;
1390
    case LANDMARK_ROLE_MAP_ENTRY_INDEX:
1391
      return &sLandmarkRoleMap;
1392
    default:
1393
      return sWAIRoleMaps + aRoleMapIndex;
1394
  }
1395
}
1396
1397
uint8_t
1398
aria::GetIndexFromRoleMap(const nsRoleMapEntry* aRoleMapEntry)
1399
0
{
1400
0
  if (aRoleMapEntry == nullptr) {
1401
0
    return NO_ROLE_MAP_ENTRY_INDEX;
1402
0
  } else if (aRoleMapEntry == &gEmptyRoleMap) {
1403
0
    return EMPTY_ROLE_MAP_ENTRY_INDEX;
1404
0
  } else if (aRoleMapEntry == &sLandmarkRoleMap) {
1405
0
      return LANDMARK_ROLE_MAP_ENTRY_INDEX;
1406
0
  } else {
1407
0
    return aRoleMapEntry - sWAIRoleMaps;
1408
0
  }
1409
0
}
1410
1411
uint64_t
1412
aria::UniversalStatesFor(mozilla::dom::Element* aElement)
1413
0
{
1414
0
  uint64_t state = 0;
1415
0
  uint32_t index = 0;
1416
0
  while (MapToState(sWAIUnivStateMap[index], aElement, &state))
1417
0
    index++;
1418
0
1419
0
  return state;
1420
0
}
1421
1422
uint8_t
1423
aria::AttrCharacteristicsFor(nsAtom* aAtom)
1424
0
{
1425
0
  for (uint32_t i = 0; i < ArrayLength(gWAIUnivAttrMap); i++)
1426
0
    if (*gWAIUnivAttrMap[i].attributeName == aAtom)
1427
0
      return gWAIUnivAttrMap[i].characteristics;
1428
0
1429
0
  return 0;
1430
0
}
1431
1432
bool
1433
aria::HasDefinedARIAHidden(nsIContent* aContent)
1434
0
{
1435
0
  return aContent && aContent->IsElement() &&
1436
0
    aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
1437
0
                                       nsGkAtoms::aria_hidden,
1438
0
                                       nsGkAtoms::_true, eCaseMatters);
1439
0
}
1440
1441
////////////////////////////////////////////////////////////////////////////////
1442
// AttrIterator class
1443
1444
bool
1445
AttrIterator::Next(nsAString& aAttrName, nsAString& aAttrValue)
1446
0
{
1447
0
  while (mAttrIdx < mAttrCount) {
1448
0
    const nsAttrName* attr = mElement->GetAttrNameAt(mAttrIdx);
1449
0
    mAttrIdx++;
1450
0
    if (attr->NamespaceEquals(kNameSpaceID_None)) {
1451
0
      nsAtom* attrAtom = attr->Atom();
1452
0
      nsDependentAtomString attrStr(attrAtom);
1453
0
      if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
1454
0
        continue; // Not ARIA
1455
0
1456
0
      uint8_t attrFlags = aria::AttrCharacteristicsFor(attrAtom);
1457
0
      if (attrFlags & ATTR_BYPASSOBJ)
1458
0
        continue; // No need to handle exposing as obj attribute here
1459
0
1460
0
      if ((attrFlags & ATTR_VALTOKEN) &&
1461
0
           !nsAccUtils::HasDefinedARIAToken(mElement, attrAtom))
1462
0
        continue; // only expose token based attributes if they are defined
1463
0
1464
0
      if ((attrFlags & ATTR_BYPASSOBJ_IF_FALSE) &&
1465
0
          mElement->AttrValueIs(kNameSpaceID_None, attrAtom,
1466
0
                                nsGkAtoms::_false, eCaseMatters)) {
1467
0
        continue; // only expose token based attribute if value is not 'false'.
1468
0
      }
1469
0
1470
0
      nsAutoString value;
1471
0
      if (mElement->GetAttr(kNameSpaceID_None, attrAtom, value)) {
1472
0
        aAttrName.Assign(Substring(attrStr, 5));
1473
0
        aAttrValue.Assign(value);
1474
0
        return true;
1475
0
      }
1476
0
    }
1477
0
  }
1478
0
1479
0
  return false;
1480
0
}
1481