mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1773930: Expose xml-roles object attribute on cached RemoteAccessible. r=morgan
This also changes LocalAccessible::Attributes to ignore the edge case of an empty role attribute when calculating xml-roles. This is consistent with how we handle the role attribute elsewhere (see aria::GetRoleMapIndex) and makes it easier to handle this consistently between local and remote. Differential Revision: https://phabricator.services.mozilla.com/D149594
This commit is contained in:
parent
cbdc83f787
commit
e998d303d0
@ -1088,7 +1088,8 @@ already_AddRefed<AccAttributes> LocalAccessible::Attributes() {
|
||||
// 'xml-roles' attribute coming from ARIA.
|
||||
nsString xmlRoles;
|
||||
if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::role,
|
||||
xmlRoles)) {
|
||||
xmlRoles) &&
|
||||
!xmlRoles.IsEmpty()) {
|
||||
attributes->SetAttribute(nsGkAtoms::xmlroles, std::move(xmlRoles));
|
||||
} else if (nsAtom* landmark = LandmarkRole()) {
|
||||
// 'xml-roles' attribute for landmark.
|
||||
@ -3589,17 +3590,32 @@ already_AddRefed<AccAttributes> LocalAccessible::BundleFieldsForCache(
|
||||
if (mContent && mContent->IsElement()) {
|
||||
fields->SetAttribute(nsGkAtoms::tag, mContent->NodeInfo()->NameAtom());
|
||||
|
||||
dom::Element* el = mContent->AsElement();
|
||||
if (IsTextField() || IsDateTimeField()) {
|
||||
// Cache text input types. Accessible is recreated if this changes,
|
||||
// so it is considered immutable.
|
||||
if (const nsAttrValue* attr =
|
||||
mContent->AsElement()->GetParsedAttr(nsGkAtoms::type)) {
|
||||
if (const nsAttrValue* attr = el->GetParsedAttr(nsGkAtoms::type)) {
|
||||
RefPtr<nsAtom> inputType = attr->GetAsAtom();
|
||||
if (inputType) {
|
||||
fields->SetAttribute(nsGkAtoms::textInputType, inputType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Changing the role attribute currently re-creates the Accessible, so
|
||||
// it's immutable in the cache.
|
||||
if (const nsRoleMapEntry* roleMap = ARIARoleMap()) {
|
||||
// Most of the time, the role attribute is a single, known role. We
|
||||
// already send the map index, so we don't need to double up.
|
||||
if (!el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::role,
|
||||
roleMap->roleAtom, eIgnoreCase)) {
|
||||
// Multiple roles or unknown roles are rare, so just send them as a
|
||||
// string.
|
||||
nsAutoString role;
|
||||
el->GetAttr(kNameSpaceID_None, nsGkAtoms::role, role);
|
||||
fields->SetAttribute(nsGkAtoms::role, std::move(role));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
|
@ -821,6 +821,28 @@ already_AddRefed<AccAttributes> RemoteAccessibleBase<Derived>::Attributes() {
|
||||
if (auto ariaAttrs = GetCachedARIAAttributes()) {
|
||||
ariaAttrs->CopyTo(attributes);
|
||||
}
|
||||
|
||||
nsAutoString role;
|
||||
mCachedFields->GetAttribute(nsGkAtoms::role, role);
|
||||
if (role.IsEmpty()) {
|
||||
bool found = false;
|
||||
if (const nsRoleMapEntry* roleMap = ARIARoleMap()) {
|
||||
if (roleMap->roleAtom != nsGkAtoms::_empty) {
|
||||
// Single, known role.
|
||||
attributes->SetAttribute(nsGkAtoms::xmlroles, roleMap->roleAtom);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (nsAtom* landmark = LandmarkRole()) {
|
||||
// Landmark role from markup; e.g. HTML <main>.
|
||||
attributes->SetAttribute(nsGkAtoms::xmlroles, landmark);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Unknown role or multiple roles.
|
||||
attributes->SetAttribute(nsGkAtoms::xmlroles, std::move(role));
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString name;
|
||||
|
@ -371,3 +371,38 @@ addAccessibleTask(
|
||||
},
|
||||
{ chrome: true, topLevel: true, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
||||
/**
|
||||
* Test support for the xml-roles attribute.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<div id="knownRole" role="main">knownRole</div>
|
||||
<div id="emptyRole" role="">emptyRole</div>
|
||||
<div id="unknownRole" role="foo">unknownRole</div>
|
||||
<div id="multiRole" role="foo main">multiRole</div>
|
||||
<main id="markup">markup</main>
|
||||
<main id="markupWithRole" role="banner">markupWithRole</main>
|
||||
<main id="markupWithEmptyRole" role="">markupWithEmptyRole</main>
|
||||
`,
|
||||
async function(browser, docAcc) {
|
||||
const knownRole = findAccessibleChildByID(docAcc, "knownRole");
|
||||
testAttrs(knownRole, { "xml-roles": "main" }, true);
|
||||
const emptyRole = findAccessibleChildByID(docAcc, "emptyRole");
|
||||
testAbsentAttrs(emptyRole, { "xml-roles": "" });
|
||||
const unknownRole = findAccessibleChildByID(docAcc, "unknownRole");
|
||||
testAttrs(unknownRole, { "xml-roles": "foo" }, true);
|
||||
const multiRole = findAccessibleChildByID(docAcc, "multiRole");
|
||||
testAttrs(multiRole, { "xml-roles": "foo main" }, true);
|
||||
const markup = findAccessibleChildByID(docAcc, "markup");
|
||||
testAttrs(markup, { "xml-roles": "main" }, true);
|
||||
const markupWithRole = findAccessibleChildByID(docAcc, "markupWithRole");
|
||||
testAttrs(markupWithRole, { "xml-roles": "banner" }, true);
|
||||
const markupWithEmptyRole = findAccessibleChildByID(
|
||||
docAcc,
|
||||
"markupWithEmptyRole"
|
||||
);
|
||||
testAttrs(markupWithEmptyRole, { "xml-roles": "main" }, true);
|
||||
},
|
||||
{ chrome: true, topLevel: true, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user