tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ARIAMap.cpp (40213B)


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