mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-31 19:10:36 +00:00
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
This commit is contained in:
commit
5bf715b6ea
@ -1302,6 +1302,7 @@ static const AttrCharacteristics gWAIUnivAttrMap[] = {
|
||||
{nsGkAtoms::aria_busy, ATTR_VALTOKEN | ATTR_GLOBAL },
|
||||
{nsGkAtoms::aria_checked, ATTR_BYPASSOBJ | ATTR_VALTOKEN }, /* exposes checkable obj attr */
|
||||
{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 },
|
||||
{nsGkAtoms::aria_details, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
||||
{nsGkAtoms::aria_disabled, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
|
||||
@ -1474,6 +1475,15 @@ AttrIterator::Next(nsAString& aAttrName, nsAString& aAttrValue)
|
||||
nsAutoString value;
|
||||
if (mElement->GetAttr(kNameSpaceID_None, attrAtom, value)) {
|
||||
aAttrName.Assign(Substring(attrStr, 5));
|
||||
if (attrFlags & ATTR_VALTOKEN) {
|
||||
nsAtom* normalizedValue =
|
||||
nsAccUtils::NormalizeARIAToken(mElement, attrAtom);
|
||||
if (normalizedValue) {
|
||||
nsDependentAtomString normalizedValueStr(normalizedValue);
|
||||
aAttrValue.Assign(normalizedValueStr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
aAttrValue.Assign(value);
|
||||
return true;
|
||||
}
|
||||
|
@ -225,6 +225,26 @@ nsAccUtils::GetARIAToken(dom::Element* aElement, nsAtom* aAttr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsStaticAtom*
|
||||
nsAccUtils::NormalizeARIAToken(dom::Element* aElement, nsAtom* aAttr)
|
||||
{
|
||||
if (!HasDefinedARIAToken(aElement, aAttr)) {
|
||||
return nsGkAtoms::_empty;
|
||||
}
|
||||
|
||||
if (aAttr== nsGkAtoms::aria_current) {
|
||||
static Element::AttrValuesArray tokens[] =
|
||||
{ nsGkAtoms::page, nsGkAtoms::step, nsGkAtoms::location_,
|
||||
nsGkAtoms::date, nsGkAtoms::time, nsGkAtoms::_true, nullptr};
|
||||
int32_t idx = aElement->FindAttrValueIn(kNameSpaceID_None,
|
||||
aAttr, tokens, eCaseMatters);
|
||||
// If the token is present, return it, otherwise TRUE as per spec.
|
||||
return (idx >= 0) ? tokens[idx] : nsGkAtoms::_true;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Accessible*
|
||||
nsAccUtils::GetSelectableContainer(Accessible* aAccessible, uint64_t aState)
|
||||
{
|
||||
|
@ -104,6 +104,14 @@ public:
|
||||
static nsStaticAtom* GetARIAToken(mozilla::dom::Element* aElement,
|
||||
nsAtom* aAttr);
|
||||
|
||||
/**
|
||||
* If the given ARIA attribute has a specific known token value, return it.
|
||||
* If the specification demands for a fallback value for unknown attribute
|
||||
* values, return that. For all others, return a nullptr.
|
||||
*/
|
||||
static nsStaticAtom* NormalizeARIAToken(mozilla::dom::Element* aElement,
|
||||
nsAtom* aAttr);
|
||||
|
||||
/**
|
||||
* Return document accessible for the given DOM node.
|
||||
*/
|
||||
|
@ -51,6 +51,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
testAttrs("sortOther", {"sort": "other"}, true);
|
||||
testAttrs("roledescr", {"roledescription": "spreadshit"}, true);
|
||||
testAttrs("currentPage", {"current": "page"}, true);
|
||||
testAttrs("currentStep", {"current": "step"}, true);
|
||||
testAttrs("currentLocation", {"current": "location"}, true);
|
||||
testAttrs("currentDate", {"current": "date"}, true);
|
||||
testAttrs("currentTime", {"current": "time"}, true);
|
||||
testAttrs("currentTrue", {"current": "true"}, true);
|
||||
testAttrs("currentOther", {"current": "true"}, true);
|
||||
testAbsentAttrs("currentFalse", {"current": "true"});
|
||||
testAttrs("currentSpan", {"current": "page"}, true);
|
||||
|
||||
// inherited attributes by subdocuments
|
||||
var subdoc = getAccessible("iframe").firstChild;
|
||||
@ -187,6 +195,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
<div id="sortOther" role="columnheader" aria-sort="other"></div>
|
||||
<div id="roledescr" aria-roledescription="spreadshit"></div>
|
||||
<div id="currentPage" aria-current="page"></div>
|
||||
<div id="currentStep" aria-current="step"></div>
|
||||
<div id="currentLocation" aria-current="location"></div>
|
||||
<div id="currentDate" aria-current="date"></div>
|
||||
<div id="currentTime" aria-current="time"></div>
|
||||
<div id="currentTrue" aria-current="true"></div>
|
||||
<div id="currentOther" aria-current="other"></div>
|
||||
<div id="currentFalse" aria-current="false"></div>
|
||||
|
||||
<!-- aria-current on a span which must create an accessible -->
|
||||
<ol>
|
||||
<li><a href="...">Page 1</a></li>
|
||||
<li><a href="...">Page 2</a></li>
|
||||
<li><span id="currentSpan" aria-current="page">This page</span></li>
|
||||
</ol>
|
||||
|
||||
<!-- inherited from iframe -->
|
||||
<iframe id="iframe" src="data:text/html,<html><body></body></html>"
|
||||
|
@ -343,6 +343,39 @@ add_task(async function checkDefaultPermissionState() {
|
||||
Services.prefs.setIntPref("permissions.default.desktop-notification", SitePermissions.UNKNOWN);
|
||||
});
|
||||
|
||||
add_task(async function testTabBehaviour() {
|
||||
// Test tab behaviour inside the permissions setting dialog when site permissions are selected.
|
||||
// Only selected items in the richlistbox should be tabable for accessibility reasons.
|
||||
|
||||
// Force tabfocus for all elements on OSX.
|
||||
SpecialPowers.pushPrefEnv({"set": [["accessibility.tabfocus", 7]]});
|
||||
|
||||
SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
|
||||
let u = Services.io.newURI("http://www.test.com");
|
||||
SitePermissions.set(u, "desktop-notification", SitePermissions.ALLOW);
|
||||
|
||||
await openPermissionsDialog();
|
||||
let doc = sitePermissionsDialog.document;
|
||||
|
||||
EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog);
|
||||
let richlistbox = doc.getElementById("permissionsBox");
|
||||
is(richlistbox, doc.activeElement.closest("#permissionsBox"), "The richlistbox is focused after pressing tab once.");
|
||||
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown", {}, sitePermissionsDialog);
|
||||
EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog);
|
||||
let menulist = doc.getElementById("permissionsBox").children[1].getElementsByTagName("menulist")[0];
|
||||
is(menulist, doc.activeElement, "The menulist inside the selected richlistitem is focused now");
|
||||
|
||||
EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog);
|
||||
let removeButton = doc.getElementById("removePermission");
|
||||
is(removeButton, doc.activeElement, "The focus moves outside the richlistbox and onto the remove button");
|
||||
|
||||
SitePermissions.remove(URI, "desktop-notification");
|
||||
SitePermissions.remove(u, "desktop-notification");
|
||||
|
||||
doc.getElementById("cancel").click();
|
||||
});
|
||||
|
||||
add_task(async function removeTab() {
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
@ -346,6 +346,17 @@ var gSitePermissionsManager = {
|
||||
|
||||
onPermissionSelect() {
|
||||
this._setRemoveButtonState();
|
||||
|
||||
// If any item is selected, it should be the only item tabable
|
||||
// in the richlistbox for accessibility reasons.
|
||||
this._list.children.forEach((item) => {
|
||||
let menulist = item.getElementsByTagName("menulist")[0];
|
||||
if (!item.selected) {
|
||||
menulist.setAttribute("tabindex", -1);
|
||||
} else {
|
||||
menulist.removeAttribute("tabindex");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onPermissionChange(perm, capability) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user