mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
838eaaadf2
This revision adds a Gecko GRID role, matching the ARIA 'grid' role, and implements its platform mappings. It then remaps the ARIA 'grid' role to the Gecko GRID role. Finally, this revision removes the expected-fail for the relevant formerly-failing web platform test and updates existing tests. Differential Revision: https://phabricator.services.mozilla.com/D202040
1688 lines
36 KiB
C++
1688 lines
36 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
|
*/
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "ARIAMap.h"
|
|
|
|
#include "AccAttributes.h"
|
|
#include "nsAccUtils.h"
|
|
#include "nsCoreUtils.h"
|
|
#include "mozilla/a11y/Role.h"
|
|
#include "States.h"
|
|
|
|
#include "nsAttrName.h"
|
|
#include "nsWhitespaceTokenizer.h"
|
|
|
|
#include "mozilla/BinarySearch.h"
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
#include "nsUnicharUtils.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::a11y;
|
|
using namespace mozilla::a11y::aria;
|
|
|
|
static const uint32_t kGenericAccType = 0;
|
|
|
|
/**
|
|
* This list of WAI-defined roles are currently hardcoded.
|
|
* Eventually we will most likely be loading an RDF resource that contains this
|
|
* information Using RDF will also allow for role extensibility. See bug 280138.
|
|
*
|
|
* Definition of nsRoleMapEntry contains comments explaining this table.
|
|
*
|
|
* When no Role enum mapping exists for an ARIA role, the role will be exposed
|
|
* via the object attribute "xml-roles".
|
|
*
|
|
* Note: the list must remain alphabetically ordered to support binary search.
|
|
*/
|
|
|
|
static const nsRoleMapEntry sWAIRoleMaps[] = {
|
|
// clang-format off
|
|
{ // alert
|
|
nsGkAtoms::alert,
|
|
roles::ALERT,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
#if defined(XP_MACOSX)
|
|
eAssertiveLiveAttr,
|
|
#else
|
|
eNoLiveAttr,
|
|
#endif
|
|
eAlert,
|
|
kNoReqStates
|
|
},
|
|
{ // alertdialog
|
|
nsGkAtoms::alertdialog,
|
|
roles::DIALOG,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // application
|
|
nsGkAtoms::application,
|
|
roles::APPLICATION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // article
|
|
nsGkAtoms::article,
|
|
roles::ARTICLE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eReadonlyUntilEditable
|
|
},
|
|
{ // banner
|
|
nsGkAtoms::banner,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // blockquote
|
|
nsGkAtoms::blockquote,
|
|
roles::BLOCKQUOTE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // button
|
|
nsGkAtoms::button,
|
|
roles::PUSHBUTTON,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
ePressAction,
|
|
eNoLiveAttr,
|
|
eButton,
|
|
kNoReqStates
|
|
// eARIAPressed is auto applied on any button
|
|
},
|
|
{ // caption
|
|
nsGkAtoms::caption,
|
|
roles::CAPTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // cell
|
|
nsGkAtoms::cell,
|
|
roles::CELL,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eTableCell,
|
|
kNoReqStates
|
|
},
|
|
{ // checkbox
|
|
nsGkAtoms::checkbox,
|
|
roles::CHECKBUTTON,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eCheckUncheckAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIACheckableMixed,
|
|
eARIAReadonly
|
|
},
|
|
{ // code
|
|
nsGkAtoms::code,
|
|
roles::CODE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // columnheader
|
|
nsGkAtoms::columnheader,
|
|
roles::COLUMNHEADER,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eSortAction,
|
|
eNoLiveAttr,
|
|
eTableCell,
|
|
kNoReqStates,
|
|
eARIASelectableIfDefined,
|
|
eARIAReadonly
|
|
},
|
|
{ // combobox, which consists of text input and popup
|
|
nsGkAtoms::combobox,
|
|
roles::EDITCOMBOBOX,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eOpenCloseAction,
|
|
eNoLiveAttr,
|
|
eCombobox,
|
|
states::COLLAPSED | states::HASPOPUP,
|
|
eARIAAutoComplete,
|
|
eARIAReadonly,
|
|
eARIAOrientation
|
|
},
|
|
{ // comment
|
|
nsGkAtoms::comment,
|
|
roles::COMMENT,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // complementary
|
|
nsGkAtoms::complementary,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // contentinfo
|
|
nsGkAtoms::contentinfo,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // definition
|
|
nsGkAtoms::definition,
|
|
roles::DEFINITION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // deletion
|
|
nsGkAtoms::deletion,
|
|
roles::CONTENT_DELETION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // dialog
|
|
nsGkAtoms::dialog,
|
|
roles::DIALOG,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // directory
|
|
nsGkAtoms::directory,
|
|
roles::LIST,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eList,
|
|
states::READONLY
|
|
},
|
|
{ // doc-abstract
|
|
nsGkAtoms::docAbstract,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-acknowledgments
|
|
nsGkAtoms::docAcknowledgments,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-afterword
|
|
nsGkAtoms::docAfterword,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-appendix
|
|
nsGkAtoms::docAppendix,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-backlink
|
|
nsGkAtoms::docBacklink,
|
|
roles::LINK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eJumpAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::LINKED
|
|
},
|
|
{ // doc-biblioentry
|
|
nsGkAtoms::docBiblioentry,
|
|
roles::LISTITEM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::READONLY
|
|
},
|
|
{ // doc-bibliography
|
|
nsGkAtoms::docBibliography,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-biblioref
|
|
nsGkAtoms::docBiblioref,
|
|
roles::LINK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eJumpAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::LINKED
|
|
},
|
|
{ // doc-chapter
|
|
nsGkAtoms::docChapter,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-colophon
|
|
nsGkAtoms::docColophon,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-conclusion
|
|
nsGkAtoms::docConclusion,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-cover
|
|
nsGkAtoms::docCover,
|
|
roles::GRAPHIC,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-credit
|
|
nsGkAtoms::docCredit,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-credits
|
|
nsGkAtoms::docCredits,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-dedication
|
|
nsGkAtoms::docDedication,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-endnote
|
|
nsGkAtoms::docEndnote,
|
|
roles::LISTITEM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::READONLY
|
|
},
|
|
{ // doc-endnotes
|
|
nsGkAtoms::docEndnotes,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-epigraph
|
|
nsGkAtoms::docEpigraph,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-epilogue
|
|
nsGkAtoms::docEpilogue,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-errata
|
|
nsGkAtoms::docErrata,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-example
|
|
nsGkAtoms::docExample,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-footnote
|
|
nsGkAtoms::docFootnote,
|
|
roles::FOOTNOTE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-foreword
|
|
nsGkAtoms::docForeword,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-glossary
|
|
nsGkAtoms::docGlossary,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-glossref
|
|
nsGkAtoms::docGlossref,
|
|
roles::LINK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eJumpAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::LINKED
|
|
},
|
|
{ // doc-index
|
|
nsGkAtoms::docIndex,
|
|
roles::NAVIGATION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-introduction
|
|
nsGkAtoms::docIntroduction,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-noteref
|
|
nsGkAtoms::docNoteref,
|
|
roles::LINK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eJumpAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::LINKED
|
|
},
|
|
{ // doc-notice
|
|
nsGkAtoms::docNotice,
|
|
roles::NOTE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-pagebreak
|
|
nsGkAtoms::docPagebreak,
|
|
roles::SEPARATOR,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-pagelist
|
|
nsGkAtoms::docPagelist,
|
|
roles::NAVIGATION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-part
|
|
nsGkAtoms::docPart,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-preface
|
|
nsGkAtoms::docPreface,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-prologue
|
|
nsGkAtoms::docPrologue,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-pullquote
|
|
nsGkAtoms::docPullquote,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-qna
|
|
nsGkAtoms::docQna,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-subtitle
|
|
nsGkAtoms::docSubtitle,
|
|
roles::HEADING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-tip
|
|
nsGkAtoms::docTip,
|
|
roles::NOTE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // doc-toc
|
|
nsGkAtoms::docToc,
|
|
roles::NAVIGATION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // document
|
|
nsGkAtoms::document,
|
|
roles::NON_NATIVE_DOCUMENT,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eReadonlyUntilEditable
|
|
},
|
|
{ // emphasis
|
|
nsGkAtoms::emphasis,
|
|
roles::EMPHASIS,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // feed
|
|
nsGkAtoms::feed,
|
|
roles::GROUPING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // figure
|
|
nsGkAtoms::figure,
|
|
roles::FIGURE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // form
|
|
nsGkAtoms::form,
|
|
roles::FORM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // generic
|
|
nsGkAtoms::generic,
|
|
roles::SECTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // graphics-document
|
|
nsGkAtoms::graphicsDocument,
|
|
roles::NON_NATIVE_DOCUMENT,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eReadonlyUntilEditable
|
|
},
|
|
{ // graphics-object
|
|
nsGkAtoms::graphicsObject,
|
|
roles::GROUPING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // graphics-symbol
|
|
nsGkAtoms::graphicsSymbol,
|
|
roles::GRAPHIC,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // grid
|
|
nsGkAtoms::grid,
|
|
roles::GRID,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eSelect | eTable,
|
|
kNoReqStates,
|
|
eARIAMultiSelectable,
|
|
eARIAReadonly,
|
|
eFocusableUntilDisabled
|
|
},
|
|
{ // gridcell
|
|
nsGkAtoms::gridcell,
|
|
roles::GRID_CELL,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eTableCell,
|
|
kNoReqStates,
|
|
eARIASelectable,
|
|
eARIAReadonly
|
|
},
|
|
{ // group
|
|
nsGkAtoms::group,
|
|
roles::GROUPING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // heading
|
|
nsGkAtoms::heading,
|
|
roles::HEADING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // image
|
|
nsGkAtoms::image,
|
|
roles::GRAPHIC,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // img
|
|
nsGkAtoms::img,
|
|
roles::GRAPHIC,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // insertion
|
|
nsGkAtoms::insertion,
|
|
roles::CONTENT_INSERTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // key
|
|
nsGkAtoms::key,
|
|
roles::KEY,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
ePressAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIAPressed
|
|
},
|
|
{ // link
|
|
nsGkAtoms::link,
|
|
roles::LINK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eJumpAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::LINKED
|
|
},
|
|
{ // list
|
|
nsGkAtoms::list_,
|
|
roles::LIST,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eList,
|
|
states::READONLY
|
|
},
|
|
{ // listbox
|
|
nsGkAtoms::listbox,
|
|
roles::LISTBOX,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eListControl | eSelect,
|
|
states::VERTICAL,
|
|
eARIAMultiSelectable,
|
|
eARIAReadonly,
|
|
eFocusableUntilDisabled,
|
|
eARIAOrientation
|
|
},
|
|
{ // listitem
|
|
nsGkAtoms::listitem,
|
|
roles::LISTITEM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction, // XXX: should depend on state, parent accessible
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::READONLY
|
|
},
|
|
{ // log
|
|
nsGkAtoms::log_,
|
|
roles::NOTHING,
|
|
kUseNativeRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
ePoliteLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // main
|
|
nsGkAtoms::main,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // mark
|
|
nsGkAtoms::mark,
|
|
roles::MARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // marquee
|
|
nsGkAtoms::marquee,
|
|
roles::ANIMATION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eOffLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // math
|
|
nsGkAtoms::math,
|
|
roles::FLAT_EQUATION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // menu
|
|
nsGkAtoms::menu,
|
|
roles::MENUPOPUP,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction, // XXX: technically accessibles of menupopup role haven't
|
|
// any action, but menu can be open or close.
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::VERTICAL,
|
|
eARIAOrientation
|
|
},
|
|
{ // menubar
|
|
nsGkAtoms::menubar,
|
|
roles::MENUBAR,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::HORIZONTAL,
|
|
eARIAOrientation
|
|
},
|
|
{ // menuitem
|
|
nsGkAtoms::menuitem,
|
|
roles::MENUITEM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eClickAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // menuitemcheckbox
|
|
nsGkAtoms::menuitemcheckbox,
|
|
roles::CHECK_MENU_ITEM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eClickAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIACheckableMixed,
|
|
eARIAReadonly
|
|
},
|
|
{ // menuitemradio
|
|
nsGkAtoms::menuitemradio,
|
|
roles::RADIO_MENU_ITEM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eClickAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIACheckableBool,
|
|
eARIAReadonly
|
|
},
|
|
{ // meter
|
|
nsGkAtoms::meter,
|
|
roles::METER,
|
|
kUseMapRole,
|
|
eHasValueMinMax,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::READONLY
|
|
},
|
|
{ // navigation
|
|
nsGkAtoms::navigation,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // none
|
|
nsGkAtoms::none,
|
|
roles::NOTHING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // note
|
|
nsGkAtoms::note_,
|
|
roles::NOTE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // option
|
|
nsGkAtoms::option,
|
|
roles::OPTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eSelectAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIASelectable,
|
|
eARIACheckedMixed
|
|
},
|
|
{ // paragraph
|
|
nsGkAtoms::paragraph,
|
|
roles::PARAGRAPH,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // presentation
|
|
nsGkAtoms::presentation,
|
|
roles::NOTHING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // progressbar
|
|
nsGkAtoms::progressbar,
|
|
roles::PROGRESSBAR,
|
|
kUseMapRole,
|
|
eHasValueMinMax,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::READONLY,
|
|
eIndeterminateIfNoValue
|
|
},
|
|
{ // radio
|
|
nsGkAtoms::radio,
|
|
roles::RADIOBUTTON,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eSelectAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIACheckableBool
|
|
},
|
|
{ // radiogroup
|
|
nsGkAtoms::radiogroup,
|
|
roles::RADIO_GROUP,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIAOrientation,
|
|
eARIAReadonly
|
|
},
|
|
{ // region
|
|
nsGkAtoms::region,
|
|
roles::REGION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // row
|
|
nsGkAtoms::row,
|
|
roles::ROW,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eTableRow,
|
|
kNoReqStates,
|
|
eARIASelectable
|
|
},
|
|
{ // rowgroup
|
|
nsGkAtoms::rowgroup,
|
|
roles::GROUPING,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // rowheader
|
|
nsGkAtoms::rowheader,
|
|
roles::ROWHEADER,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eSortAction,
|
|
eNoLiveAttr,
|
|
eTableCell,
|
|
kNoReqStates,
|
|
eARIASelectableIfDefined,
|
|
eARIAReadonly
|
|
},
|
|
{ // scrollbar
|
|
nsGkAtoms::scrollbar,
|
|
roles::SCROLLBAR,
|
|
kUseMapRole,
|
|
eHasValueMinMax,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::VERTICAL,
|
|
eARIAOrientation,
|
|
eARIAReadonly
|
|
},
|
|
{ // search
|
|
nsGkAtoms::search,
|
|
roles::LANDMARK,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eLandmark,
|
|
kNoReqStates
|
|
},
|
|
{ // searchbox
|
|
nsGkAtoms::searchbox,
|
|
roles::ENTRY,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eActivateAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIAAutoComplete,
|
|
eARIAMultiline,
|
|
eARIAReadonlyOrEditable
|
|
},
|
|
{ // separator
|
|
nsGkAtoms::separator_,
|
|
roles::SEPARATOR,
|
|
kUseMapRole,
|
|
eHasValueMinMaxIfFocusable,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::HORIZONTAL,
|
|
eARIAOrientation
|
|
},
|
|
{ // slider
|
|
nsGkAtoms::slider,
|
|
roles::SLIDER,
|
|
kUseMapRole,
|
|
eHasValueMinMax,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::HORIZONTAL,
|
|
eARIAOrientation,
|
|
eARIAReadonly
|
|
},
|
|
{ // spinbutton
|
|
nsGkAtoms::spinbutton,
|
|
roles::SPINBUTTON,
|
|
kUseMapRole,
|
|
eHasValueMinMax,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIAReadonly
|
|
},
|
|
{ // status
|
|
nsGkAtoms::status,
|
|
roles::STATUSBAR,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
ePoliteLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // strong
|
|
nsGkAtoms::strong,
|
|
roles::STRONG,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // subscript
|
|
nsGkAtoms::subscript,
|
|
roles::SUBSCRIPT,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType
|
|
},
|
|
{ // suggestion
|
|
nsGkAtoms::suggestion,
|
|
roles::SUGGESTION,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
},
|
|
{ // superscript
|
|
nsGkAtoms::superscript,
|
|
roles::SUPERSCRIPT,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType
|
|
},
|
|
{ // switch
|
|
nsGkAtoms::svgSwitch,
|
|
roles::SWITCH,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eCheckUncheckAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIACheckableBool,
|
|
eARIAReadonly
|
|
},
|
|
{ // tab
|
|
nsGkAtoms::tab,
|
|
roles::PAGETAB,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eSwitchAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIASelectable
|
|
},
|
|
{ // table
|
|
nsGkAtoms::table,
|
|
roles::TABLE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eTable,
|
|
kNoReqStates,
|
|
eARIASelectable
|
|
},
|
|
{ // tablist
|
|
nsGkAtoms::tablist,
|
|
roles::PAGETABLIST,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eSelect,
|
|
states::HORIZONTAL,
|
|
eARIAOrientation,
|
|
eARIAMultiSelectable
|
|
},
|
|
{ // tabpanel
|
|
nsGkAtoms::tabpanel,
|
|
roles::PROPERTYPAGE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // term
|
|
nsGkAtoms::term,
|
|
roles::TERM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::READONLY
|
|
},
|
|
{ // textbox
|
|
nsGkAtoms::textbox,
|
|
roles::ENTRY,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eActivateAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIAAutoComplete,
|
|
eARIAMultiline,
|
|
eARIAReadonlyOrEditable
|
|
},
|
|
{ // time
|
|
nsGkAtoms::time,
|
|
roles::TIME,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kNoReqStates
|
|
},
|
|
{ // timer
|
|
nsGkAtoms::timer,
|
|
roles::NOTHING,
|
|
kUseNativeRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eOffLiveAttr,
|
|
kNoReqStates
|
|
},
|
|
{ // toolbar
|
|
nsGkAtoms::toolbar,
|
|
roles::TOOLBAR,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
states::HORIZONTAL,
|
|
eARIAOrientation
|
|
},
|
|
{ // tooltip
|
|
nsGkAtoms::tooltip,
|
|
roles::TOOLTIP,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates
|
|
},
|
|
{ // tree
|
|
nsGkAtoms::tree,
|
|
roles::OUTLINE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eSelect,
|
|
states::VERTICAL,
|
|
eARIAReadonly,
|
|
eARIAMultiSelectable,
|
|
eFocusableUntilDisabled,
|
|
eARIAOrientation
|
|
},
|
|
{ // treegrid
|
|
nsGkAtoms::treegrid,
|
|
roles::TREE_TABLE,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eNoAction,
|
|
eNoLiveAttr,
|
|
eSelect | eTable,
|
|
kNoReqStates,
|
|
eARIAReadonly,
|
|
eARIAMultiSelectable,
|
|
eFocusableUntilDisabled,
|
|
eARIAOrientation
|
|
},
|
|
{ // treeitem
|
|
nsGkAtoms::treeitem,
|
|
roles::OUTLINEITEM,
|
|
kUseMapRole,
|
|
eNoValue,
|
|
eActivateAction, // XXX: should expose second 'expand/collapse' action based
|
|
// on states
|
|
eNoLiveAttr,
|
|
kGenericAccType,
|
|
kNoReqStates,
|
|
eARIASelectable,
|
|
eARIACheckedMixed
|
|
}
|
|
// clang-format on
|
|
};
|
|
|
|
static const nsRoleMapEntry sLandmarkRoleMap = {
|
|
nsGkAtoms::_empty, roles::NOTHING, kUseNativeRole, eNoValue,
|
|
eNoAction, eNoLiveAttr, kGenericAccType, kNoReqStates};
|
|
|
|
nsRoleMapEntry aria::gEmptyRoleMap = {
|
|
nsGkAtoms::_empty, roles::TEXT_CONTAINER, kUseMapRole, eNoValue,
|
|
eNoAction, eNoLiveAttr, kGenericAccType, kNoReqStates};
|
|
|
|
/**
|
|
* Universal (Global) states:
|
|
* The following state rules are applied to any accessible element,
|
|
* whether there is an ARIA role or not:
|
|
*/
|
|
static const EStateRule sWAIUnivStateMap[] = {
|
|
eARIABusy, eARIACurrent, eARIADisabled,
|
|
eARIAExpanded, // Currently under spec review but precedent exists
|
|
eARIAHasPopup, // Note this is a tokenised attribute starting in ARIA 1.1
|
|
eARIAInvalid, eARIAModal,
|
|
eARIARequired, // XXX not global, Bug 553117
|
|
eARIANone};
|
|
|
|
/**
|
|
* ARIA attribute map for attribute characteristics.
|
|
* @note ARIA attributes that don't have any flags are not included here.
|
|
*/
|
|
|
|
struct AttrCharacteristics {
|
|
const nsStaticAtom* const attributeName;
|
|
const uint8_t characteristics;
|
|
};
|
|
|
|
static const AttrCharacteristics gWAIUnivAttrMap[] = {
|
|
// clang-format off
|
|
{nsGkAtoms::aria_activedescendant, ATTR_BYPASSOBJ },
|
|
{nsGkAtoms::aria_atomic, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_busy, ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_checked, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, /* exposes checkable obj attr */
|
|
{nsGkAtoms::aria_colcount, ATTR_VALINT },
|
|
{nsGkAtoms::aria_colindex, ATTR_VALINT },
|
|
{nsGkAtoms::aria_controls, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_current, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_describedby, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
// XXX Ideally, aria-description shouldn't expose a description object
|
|
// attribute (i.e. it should have ATTR_BYPASSOBJ). However, until the
|
|
// description-from attribute is implemented (bug 1726087), clients such as
|
|
// NVDA depend on the description object attribute to work out whether the
|
|
// accDescription originated from aria-description.
|
|
{nsGkAtoms::aria_description, ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_details, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_disabled, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_dropeffect, ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_errormessage, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_expanded, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_flowto, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_grabbed, ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_haspopup, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_hidden, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, /* handled special way */
|
|
{nsGkAtoms::aria_invalid, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_label, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_labelledby, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_level, ATTR_BYPASSOBJ }, /* handled via groupPosition */
|
|
{nsGkAtoms::aria_live, ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_modal, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_multiline, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_multiselectable, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_owns, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_orientation, ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_posinset, ATTR_BYPASSOBJ }, /* handled via groupPosition */
|
|
{nsGkAtoms::aria_pressed, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_readonly, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_relevant, ATTR_GLOBAL },
|
|
{nsGkAtoms::aria_required, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_rowcount, ATTR_VALINT },
|
|
{nsGkAtoms::aria_rowindex, ATTR_VALINT },
|
|
{nsGkAtoms::aria_selected, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_setsize, ATTR_BYPASSOBJ }, /* handled via groupPosition */
|
|
{nsGkAtoms::aria_sort, ATTR_VALTOKEN },
|
|
{nsGkAtoms::aria_valuenow, ATTR_BYPASSOBJ },
|
|
{nsGkAtoms::aria_valuemin, ATTR_BYPASSOBJ },
|
|
{nsGkAtoms::aria_valuemax, ATTR_BYPASSOBJ },
|
|
{nsGkAtoms::aria_valuetext, ATTR_BYPASSOBJ }
|
|
// clang-format on
|
|
};
|
|
|
|
const nsRoleMapEntry* aria::GetRoleMap(dom::Element* aEl) {
|
|
return GetRoleMapFromIndex(GetRoleMapIndex(aEl));
|
|
}
|
|
|
|
uint8_t aria::GetRoleMapIndex(dom::Element* aEl) {
|
|
nsAutoString roles;
|
|
if (!aEl || !nsAccUtils::GetARIAAttr(aEl, nsGkAtoms::role, roles) ||
|
|
roles.IsEmpty()) {
|
|
// We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
|
|
return NO_ROLE_MAP_ENTRY_INDEX;
|
|
}
|
|
|
|
nsWhitespaceTokenizer tokenizer(roles);
|
|
while (tokenizer.hasMoreTokens()) {
|
|
// Do a binary search through table for the next role in role list
|
|
const nsDependentSubstring role = tokenizer.nextToken();
|
|
size_t idx;
|
|
auto comparator = [&role](const nsRoleMapEntry& aEntry) {
|
|
return Compare(role, aEntry.ARIARoleString(),
|
|
nsCaseInsensitiveStringComparator);
|
|
};
|
|
if (BinarySearchIf(sWAIRoleMaps, 0, ArrayLength(sWAIRoleMaps), comparator,
|
|
&idx)) {
|
|
return idx;
|
|
}
|
|
}
|
|
|
|
// Always use some entry index if there is a non-empty role string
|
|
// To ensure an accessible object is created
|
|
return LANDMARK_ROLE_MAP_ENTRY_INDEX;
|
|
}
|
|
|
|
const nsRoleMapEntry* aria::GetRoleMapFromIndex(uint8_t aRoleMapIndex) {
|
|
switch (aRoleMapIndex) {
|
|
case NO_ROLE_MAP_ENTRY_INDEX:
|
|
return nullptr;
|
|
case EMPTY_ROLE_MAP_ENTRY_INDEX:
|
|
return &gEmptyRoleMap;
|
|
case LANDMARK_ROLE_MAP_ENTRY_INDEX:
|
|
return &sLandmarkRoleMap;
|
|
default:
|
|
return sWAIRoleMaps + aRoleMapIndex;
|
|
}
|
|
}
|
|
|
|
uint8_t aria::GetIndexFromRoleMap(const nsRoleMapEntry* aRoleMapEntry) {
|
|
if (aRoleMapEntry == nullptr) {
|
|
return NO_ROLE_MAP_ENTRY_INDEX;
|
|
} else if (aRoleMapEntry == &gEmptyRoleMap) {
|
|
return EMPTY_ROLE_MAP_ENTRY_INDEX;
|
|
} else if (aRoleMapEntry == &sLandmarkRoleMap) {
|
|
return LANDMARK_ROLE_MAP_ENTRY_INDEX;
|
|
} else {
|
|
uint8_t index = aRoleMapEntry - sWAIRoleMaps;
|
|
MOZ_ASSERT(aria::IsRoleMapIndexValid(index));
|
|
return index;
|
|
}
|
|
}
|
|
|
|
bool aria::IsRoleMapIndexValid(uint8_t aRoleMapIndex) {
|
|
switch (aRoleMapIndex) {
|
|
case NO_ROLE_MAP_ENTRY_INDEX:
|
|
case EMPTY_ROLE_MAP_ENTRY_INDEX:
|
|
case LANDMARK_ROLE_MAP_ENTRY_INDEX:
|
|
return true;
|
|
}
|
|
return aRoleMapIndex < ArrayLength(sWAIRoleMaps);
|
|
}
|
|
|
|
uint64_t aria::UniversalStatesFor(mozilla::dom::Element* aElement) {
|
|
uint64_t state = 0;
|
|
uint32_t index = 0;
|
|
while (MapToState(sWAIUnivStateMap[index], aElement, &state)) index++;
|
|
|
|
return state;
|
|
}
|
|
|
|
uint8_t aria::AttrCharacteristicsFor(nsAtom* aAtom) {
|
|
for (uint32_t i = 0; i < ArrayLength(gWAIUnivAttrMap); i++) {
|
|
if (gWAIUnivAttrMap[i].attributeName == aAtom) {
|
|
return gWAIUnivAttrMap[i].characteristics;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool aria::HasDefinedARIAHidden(nsIContent* aContent) {
|
|
return aContent && aContent->IsElement() &&
|
|
nsAccUtils::ARIAAttrValueIs(aContent->AsElement(),
|
|
nsGkAtoms::aria_hidden, nsGkAtoms::_true,
|
|
eCaseMatters);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// AttrIterator class
|
|
|
|
AttrIterator::AttrIterator(nsIContent* aContent)
|
|
: mElement(dom::Element::FromNode(aContent)),
|
|
mIteratingDefaults(false),
|
|
mAttrIdx(0),
|
|
mAttrCharacteristics(0) {
|
|
mAttrs = mElement ? &mElement->GetAttrs() : nullptr;
|
|
mAttrCount = mAttrs ? mAttrs->AttrCount() : 0;
|
|
}
|
|
|
|
bool AttrIterator::Next() {
|
|
while (mAttrIdx < mAttrCount) {
|
|
const nsAttrName* attr = mAttrs->GetSafeAttrNameAt(mAttrIdx);
|
|
mAttrIdx++;
|
|
if (attr->NamespaceEquals(kNameSpaceID_None)) {
|
|
mAttrAtom = attr->Atom();
|
|
nsDependentAtomString attrStr(mAttrAtom);
|
|
if (!StringBeginsWith(attrStr, u"aria-"_ns)) continue; // Not ARIA
|
|
|
|
if (mIteratingDefaults) {
|
|
if (mOverriddenAttrs.Contains(mAttrAtom)) {
|
|
continue;
|
|
}
|
|
} else {
|
|
mOverriddenAttrs.Insert(mAttrAtom);
|
|
}
|
|
|
|
// AttrCharacteristicsFor has to search for the entry, so cache it here
|
|
// rather than having to search again later.
|
|
mAttrCharacteristics = aria::AttrCharacteristicsFor(mAttrAtom);
|
|
if (mAttrCharacteristics & ATTR_BYPASSOBJ) {
|
|
continue; // No need to handle exposing as obj attribute here
|
|
}
|
|
|
|
if ((mAttrCharacteristics & ATTR_VALTOKEN) &&
|
|
!nsAccUtils::HasDefinedARIAToken(mAttrs, mAttrAtom)) {
|
|
continue; // only expose token based attributes if they are defined
|
|
}
|
|
|
|
if ((mAttrCharacteristics & ATTR_BYPASSOBJ_IF_FALSE) &&
|
|
mAttrs->AttrValueIs(kNameSpaceID_None, mAttrAtom, nsGkAtoms::_false,
|
|
eCaseMatters)) {
|
|
continue; // only expose token based attribute if value is not 'false'.
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
mAttrCharacteristics = 0;
|
|
mAttrAtom = nullptr;
|
|
|
|
if (const auto* defaults = nsAccUtils::GetARIADefaults(mElement);
|
|
!mIteratingDefaults && defaults) {
|
|
mIteratingDefaults = true;
|
|
mAttrs = defaults;
|
|
mAttrCount = mAttrs->AttrCount();
|
|
mAttrIdx = 0;
|
|
return Next();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
nsAtom* AttrIterator::AttrName() const { return mAttrAtom; }
|
|
|
|
void AttrIterator::AttrValue(nsAString& aAttrValue) const {
|
|
nsAutoString value;
|
|
if (mAttrs->GetAttr(mAttrAtom, value)) {
|
|
if (mAttrCharacteristics & ATTR_VALTOKEN) {
|
|
nsAtom* normalizedValue =
|
|
nsAccUtils::NormalizeARIAToken(mAttrs, mAttrAtom);
|
|
if (normalizedValue) {
|
|
nsDependentAtomString normalizedValueStr(normalizedValue);
|
|
aAttrValue.Assign(normalizedValueStr);
|
|
return;
|
|
}
|
|
}
|
|
aAttrValue.Assign(value);
|
|
}
|
|
}
|
|
|
|
bool AttrIterator::ExposeAttr(AccAttributes* aTargetAttrs) const {
|
|
if (mAttrCharacteristics & ATTR_VALTOKEN) {
|
|
nsAtom* normalizedValue = nsAccUtils::NormalizeARIAToken(mAttrs, mAttrAtom);
|
|
if (normalizedValue) {
|
|
aTargetAttrs->SetAttribute(mAttrAtom, normalizedValue);
|
|
return true;
|
|
}
|
|
} else if (mAttrCharacteristics & ATTR_VALINT) {
|
|
int32_t intVal;
|
|
if (nsCoreUtils::GetUIntAttrValue(mAttrs->GetAttr(mAttrAtom), &intVal)) {
|
|
aTargetAttrs->SetAttribute(mAttrAtom, intVal);
|
|
return true;
|
|
}
|
|
if (mAttrAtom == nsGkAtoms::aria_colcount ||
|
|
mAttrAtom == nsGkAtoms::aria_rowcount) {
|
|
// These attributes allow a value of -1.
|
|
if (mAttrs->AttrValueIs(kNameSpaceID_None, mAttrAtom, u"-1"_ns,
|
|
eCaseMatters)) {
|
|
aTargetAttrs->SetAttribute(mAttrAtom, -1);
|
|
return true;
|
|
}
|
|
}
|
|
return false; // Invalid value.
|
|
}
|
|
nsAutoString value;
|
|
if (mAttrs->GetAttr(mAttrAtom, value)) {
|
|
aTargetAttrs->SetAttribute(mAttrAtom, std::move(value));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|