Bug 637578 - Expose explict-name object attribute, r=tbsaunde

This commit is contained in:
Alexander Surkov 2012-10-17 15:38:16 +09:00
parent aee349a1a3
commit 02b3cceee5
16 changed files with 90 additions and 62 deletions

View File

@ -32,7 +32,7 @@ nsTextEquivUtils::GetNameFromSubtree(Accessible* aAccessible,
return NS_OK;
gInitiatorAcc = aAccessible;
if (GetRoleRule(aAccessible->Role()) == eFromSubtree) {
if (IsNameFromSubtreeAllowed(aAccessible)) {
//XXX: is it necessary to care the accessible is not a document?
if (aAccessible->IsContent()) {
nsAutoString name;

View File

@ -89,6 +89,14 @@ public:
static nsresult AppendTextEquivFromTextContent(nsIContent *aContent,
nsAString *aString);
/**
* Return true if the given accessible allows name from subtree.
*/
static bool IsNameFromSubtreeAllowed(Accessible* aAccessible)
{
return GetRoleRule(aAccessible->Role()) == eFromSubtree;
}
private:
/**
* Iterates accessible children and calculates text equivalent from each

View File

@ -275,7 +275,7 @@ Accessible::Name(nsString& aName)
ENameValueFlag nameFlag = NativeName(aName);
if (!aName.IsEmpty())
return eNameOK;
return nameFlag;
// In the end get the name from tooltip.
if (mContent->IsHTML()) {
@ -288,14 +288,12 @@ Accessible::Name(nsString& aName)
aName.CompressWhitespace();
return eNameFromTooltip;
}
} else {
return eNameOK;
}
if (nameFlag != eNoNameOnPurpose)
aName.SetIsVoid(true);
return eNameOK;
return nameFlag;
}
NS_IMETHODIMP
@ -1055,7 +1053,7 @@ Accessible::TakeFocus()
return NS_OK;
}
void
ENameValueFlag
Accessible::GetHTMLName(nsString& aLabel)
{
Accessible* labelAcc = nullptr;
@ -1066,8 +1064,11 @@ Accessible::GetHTMLName(nsString& aLabel)
aLabel.CompressWhitespace();
}
if (aLabel.IsEmpty())
if (!aLabel.IsEmpty())
return eNameOK;
nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
return aLabel.IsEmpty() ? eNameOK : eNameFromSubtree;
}
/**
@ -1082,7 +1083,7 @@ Accessible::GetHTMLName(nsString& aLabel)
* the control that uses the control="controlID" syntax will use
* the child label for its Name.
*/
void
ENameValueFlag
Accessible::GetXULName(nsString& aName)
{
// CASE #1 (via label attribute) -- great majority of the cases
@ -1125,10 +1126,9 @@ Accessible::GetXULName(nsString& aName)
}
}
// XXX If CompressWhiteSpace worked on nsAString we could avoid a copy
aName.CompressWhitespace();
if (!aName.IsEmpty())
return;
return eNameOK;
// Can get text from title of <toolbaritem> if we're a child of a <toolbaritem>
nsIContent *bindingParent = mContent->GetBindingParent();
@ -1138,12 +1138,13 @@ Accessible::GetXULName(nsString& aName)
if (parent->Tag() == nsGkAtoms::toolbaritem &&
parent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
aName.CompressWhitespace();
return;
return eNameOK;
}
parent = parent->GetParent();
}
nsTextEquivUtils::GetNameFromSubtree(this, aName);
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
}
nsresult
@ -1229,6 +1230,13 @@ Accessible::GetAttributes(nsIPersistentProperties **aAttributes)
if (State() & states::CHECKABLE)
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::checkable, NS_LITERAL_STRING("true"));
// Expose 'explicit-name' attribute.
if (!nsTextEquivUtils::IsNameFromSubtreeAllowed(this) ||
Name(oldValueUnused) != eNameFromSubtree) {
attributes->SetStringProperty(NS_LITERAL_CSTRING("explicit-name"),
NS_LITERAL_STRING("true"), oldValueUnused);
}
// Group attributes (level/setsize/posinset)
GroupPos groupPos = GroupPosition();
nsAccUtils::SetAccGroupAttrs(attributes, groupPos.level,
@ -2420,23 +2428,18 @@ Accessible::Shutdown()
// Accessible protected
void
Accessible::ARIAName(nsAString& aName)
Accessible::ARIAName(nsString& aName)
{
nsAutoString label;
// aria-labelledby now takes precedence over aria-label
nsresult rv = nsTextEquivUtils::
GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, label);
GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, aName);
if (NS_SUCCEEDED(rv)) {
label.CompressWhitespace();
aName = label;
aName.CompressWhitespace();
}
if (label.IsEmpty() &&
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label,
label)) {
label.CompressWhitespace();
aName = label;
if (aName.IsEmpty() &&
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label, aName)) {
aName.CompressWhitespace();
}
}
@ -2445,9 +2448,10 @@ ENameValueFlag
Accessible::NativeName(nsString& aName)
{
if (mContent->IsHTML())
GetHTMLName(aName);
else if (mContent->IsXUL())
GetXULName(aName);
return GetHTMLName(aName);
if (mContent->IsXUL())
return GetXULName(aName);
return eNameOK;
}

View File

@ -58,6 +58,11 @@ enum ENameValueFlag {
*/
eNoNameOnPurpose,
/**
* Name was computed from the subtree.
*/
eNameFromSubtree,
/**
* Tooltip was used as a name.
*/
@ -805,13 +810,13 @@ protected:
/**
* Returns the accessible name specified by ARIA.
*/
void ARIAName(nsAString& aName);
void ARIAName(nsString& aName);
/**
* Compute the name of HTML/XUL node.
*/
void GetHTMLName(nsString& aName);
void GetXULName(nsString& aName);
mozilla::a11y::ENameValueFlag GetHTMLName(nsString& aName);
mozilla::a11y::ENameValueFlag GetXULName(nsString& aName);
// helper method to verify frames
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);

View File

@ -1953,12 +1953,14 @@ HyperTextAccessible::ScrollSubstringToPoint(int32_t aStartIndex,
ENameValueFlag
HyperTextAccessible::NativeName(nsString& aName)
{
AccessibleWrap::NativeName(aName);
ENameValueFlag nameFlag = AccessibleWrap::NativeName(aName);
if (!aName.IsEmpty())
return nameFlag;
// Get name from title attribute for HTML abbr and acronym elements making it
// a valid name from markup. Otherwise their name isn't picked up by recursive
// name computation algorithm. See NS_OK_NAME_FROM_TOOLTIP.
if (aName.IsEmpty() && IsAbbreviation() &&
if (IsAbbreviation() &&
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName))
aName.CompressWhitespace();

View File

@ -77,16 +77,15 @@ ImageAccessible::NativeName(nsString& aName)
if (!aName.IsEmpty())
return eNameOK;
Accessible::NativeName(aName);
if (aName.IsEmpty() && hasAltAttrib) {
ENameValueFlag nameFlag = Accessible::NativeName(aName);
if (!aName.IsEmpty())
return nameFlag;
// No accessible name but empty 'alt' attribute is present. If further name
// computation algorithm doesn't provide non empty name then it means
// an empty 'alt' attribute was used to indicate a decorative image (see
// nsIAccessible::name attribute for details).
return eNoNameOnPurpose;
}
return eNameOK;
// Accessible::Name() method for details).
return hasAltAttrib ? eNoNameOnPurpose : eNameOK;
}
role

View File

@ -58,7 +58,7 @@ ENameValueFlag
HTMLLabelAccessible::NativeName(nsString& aName)
{
nsTextEquivUtils::GetNameFromSubtree(this, aName);
return eNameOK;
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
}
role

View File

@ -259,13 +259,13 @@ HTMLButtonAccessible::NativeRole()
ENameValueFlag
HTMLButtonAccessible::NativeName(nsString& aName)
{
Accessible::NativeName(aName);
ENameValueFlag nameFlag = Accessible::NativeName(aName);
if (!aName.IsEmpty() || mContent->Tag() != nsGkAtoms::input)
return eNameOK;
return nameFlag;
// No name from HTML or ARIA
if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName) &&
!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) {
// Note: No need to check @value attribute since it results in anonymous text
// node. The name is calculated from subtree in this case.
if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) {
// Use the button's (default) label if nothing else works
nsIFrame* frame = GetFrame();
if (frame) {
@ -323,9 +323,9 @@ HTMLTextFieldAccessible::NativeRole()
ENameValueFlag
HTMLTextFieldAccessible::NativeName(nsString& aName)
{
Accessible::NativeName(aName);
ENameValueFlag nameFlag = Accessible::NativeName(aName);
if (!aName.IsEmpty())
return eNameOK;
return nameFlag;
if (mContent->GetBindingParent()) {
// XXX: bug 459640
@ -613,9 +613,9 @@ HTMLGroupboxAccessible::GetLegend()
ENameValueFlag
HTMLGroupboxAccessible::NativeName(nsString& aName)
{
Accessible::NativeName(aName);
ENameValueFlag nameFlag = Accessible::NativeName(aName);
if (!aName.IsEmpty())
return eNameOK;
return nameFlag;
nsIContent* legendContent = GetLegend();
if (legendContent)
@ -696,9 +696,9 @@ HTMLFigureAccessible::NativeRole()
ENameValueFlag
HTMLFigureAccessible::NativeName(nsString& aName)
{
HyperTextAccessibleWrap::NativeName(aName);
ENameValueFlag nameFlag = HyperTextAccessibleWrap::NativeName(aName);
if (!aName.IsEmpty())
return eNameOK;
return nameFlag;
nsIContent* captionContent = Caption();
if (captionContent)

View File

@ -163,9 +163,9 @@ HTMLAreaAccessible::
ENameValueFlag
HTMLAreaAccessible::NativeName(nsString& aName)
{
Accessible::NativeName(aName);
ENameValueFlag nameFlag = Accessible::NativeName(aName);
if (!aName.IsEmpty())
return eNameOK;
return nameFlag;
if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
GetValue(aName);

View File

@ -200,6 +200,7 @@ HTMLSelectOptionAccessible::NativeName(nsString& aName)
if (text && text->IsNodeOfType(nsINode::eTEXT)) {
nsTextEquivUtils::AppendTextEquivFromTextContent(text, &aName);
aName.CompressWhitespace();
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
}
return eNameOK;

View File

@ -388,9 +388,9 @@ HTMLTableAccessible::NativeState()
ENameValueFlag
HTMLTableAccessible::NativeName(nsString& aName)
{
Accessible::NativeName(aName);
ENameValueFlag nameFlag = Accessible::NativeName(aName);
if (!aName.IsEmpty())
return eNameOK;
return nameFlag;
// Use table caption as a name.
Accessible* caption = Caption();

View File

@ -125,10 +125,11 @@ ENameValueFlag
XULLinkAccessible::NativeName(nsString& aName)
{
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
if (aName.IsEmpty())
nsTextEquivUtils::GetNameFromSubtree(this, aName);
if (!aName.IsEmpty())
return eNameOK;
nsTextEquivUtils::GetNameFromSubtree(this, aName);
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
}
role

View File

@ -634,8 +634,7 @@ XULListitemAccessible::NativeName(nsString& aName)
}
}
GetXULName(aName);
return eNameOK;
return GetXULName(aName);
}
role

View File

@ -188,6 +188,11 @@ function testNameForAttrRule(aElm, aRule)
var msg = "Attribute '" + attr + "' test. ";
testName(aElm, name, msg);
if (aRule.getAttribute("explict-name") != "false")
testAttrs(aElm, {"explicit-name" : "true"}, true);
else
testAbsentAttrs(aElm, {"explicit-name" : "true"});
aElm.removeAttribute(attr);
gTestIterator.iterateNext();
@ -235,6 +240,7 @@ function testNameForElmRule(aElm, aRule)
var msg = "Element '" + tagname + "' test.";
testName(aElm, labelElm.getAttribute("a11yname"), msg);
testAttrs(aElm, {"explicit-name" : "true"}, true);
var parentNode = labelElm.parentNode;
@ -252,6 +258,7 @@ function testNameForSubtreeRule(aElm, aRule)
{
var msg = "From subtree test.";
testName(aElm, aElm.getAttribute("a11yname"), msg);
testAbsentAttrs(aElm, {"explicit-name" : "true"});
if (gDumpToConsole) {
dump("\nProcessed from subtree rule. Wait for reorder event on " +

View File

@ -125,7 +125,7 @@
<!-- specific -->
<ruleset id="htmlinputbutton">
<ruleset ref="htmlelm_start"/>
<rule attr="value" type="string"/>
<rule attr="value" type="string" explict-name="false"/>
<rule attr="alt" type="string"/>
<rule attr="src" type="string"/>
<rule attr="data" type="string"/>

View File

@ -13,6 +13,8 @@
src="../events.js"></script>
<script type="application/javascript"
src="../name.js"></script>
<script type="application/javascript"
src="../attributes.js"></script>
<script type="application/javascript"
src="markup.js"></script>