Index: third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp |
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp |
index 2dbb8dcc197598d67f259e7e2ed1ef850a66876d..75b25b8888cd937faa0083d4be8df318bb0f68b4 100644 |
--- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp |
+++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp |
@@ -30,6 +30,7 @@ |
#include "modules/accessibility/AXNodeObject.h" |
#include "core/InputTypeNames.h" |
+#include "core/dom/Element.h" |
#include "core/dom/NodeTraversal.h" |
#include "core/dom/Text.h" |
#include "core/dom/shadow/ComposedTreeTraversal.h" |
@@ -1516,6 +1517,15 @@ String AXNodeObject::stringValue() const |
if (isNativeTextControl()) |
return text(); |
+ // Handle other HTML input elements that aren't text controls, like date and time |
+ // controls, by returning the string value, with the exception of checkboxes |
+ // and radio buttons (which would return "on"). |
+ if (isHTMLInputElement(node)) { |
+ HTMLInputElement* input = toHTMLInputElement(node); |
+ if (input->type() != InputTypeNames::checkbox && input->type() != InputTypeNames::radio) |
+ return input->value(); |
+ } |
+ |
// FIXME: We might need to implement a value here for more types |
// FIXME: It would be better not to advertise a value at all for the types for which we don't implement one; |
// this would require subclassing or making accessibilityAttributeNames do something other than return a |
@@ -1925,14 +1935,14 @@ String AXNodeObject::textAlternative(bool recursive, bool inAriaLabelledByTraver |
// Step 2E from: http://www.w3.org/TR/accname-aam-1.1 |
if (recursive && !inAriaLabelledByTraversal && isControl()) { |
// No need to set any name source info in a recursive call. |
- if (roleValue() == TextFieldRole || roleValue() == ComboBoxRole) |
- return text(); |
if (isRange()) { |
const AtomicString& ariaValuetext = getAttribute(aria_valuetextAttr); |
if (!ariaValuetext.isNull()) |
return ariaValuetext.string(); |
return String::number(valueForRange()); |
} |
+ |
+ return stringValue(); |
aboxhall
2015/11/05 17:49:21
I'm not sure how I feel about this. It's calling i
dmazzoni
2015/11/06 00:21:17
The current code only handles the string value of
aboxhall
2015/11/06 01:11:23
Could we possibly pull out the control-related log
dmazzoni
2015/11/06 04:54:06
Good idea!
Done.
|
} |
// Step 2F / 2G from: http://www.w3.org/TR/accname-aam-1.1 |
@@ -1946,6 +1956,8 @@ String AXNodeObject::textAlternative(bool recursive, bool inAriaLabelledByTraver |
Node* node = this->node(); |
if (node && node->isTextNode()) |
textAlternative = toText(node)->wholeText(); |
+ else if (isHTMLBRElement(node)) |
+ textAlternative = String("\n"); |
else |
textAlternative = textFromDescendants(visited); |
@@ -1998,6 +2010,10 @@ String AXNodeObject::textFromDescendants(AXObjectSet& visited) const |
StringBuilder accumulatedText; |
AXObject* previous = nullptr; |
for (AXObject* child = firstChild(); child; child = child->nextSibling()) { |
+ // Skip hidden children |
+ if (child->isInertOrAriaHidden()) |
+ continue; |
+ |
// If we're going between two layoutObjects that are in separate LayoutBoxes, add |
// whitespace if it wasn't there already. Intuitively if you have |
// <span>Hello</span><span>World</span>, those are part of the same LayoutBox |
@@ -2225,6 +2241,9 @@ bool AXNodeObject::canHaveChildren() const |
if (!node() && !isAXLayoutObject()) |
return false; |
+ if (node() && isHTMLMapElement(node())) |
+ return false; |
+ |
// Elements that should not have children |
switch (roleValue()) { |
case ImageRole: |
@@ -2762,8 +2781,8 @@ String AXNodeObject::nativeTextAlternative(AXObjectSet& visited, AXNameFrom& nam |
return textAlternative; |
} |
- // 5.8 img Element |
- if (isHTMLImageElement(node())) { |
+ // 5.8 img or area Element |
+ if (isHTMLImageElement(node()) || isHTMLAreaElement(node()) || (layoutObject() && layoutObject()->isSVGImage())) { |
// alt |
nameFrom = AXNameFromAttribute; |
if (nameSources) { |
@@ -2840,6 +2859,40 @@ String AXNodeObject::nativeTextAlternative(AXObjectSet& visited, AXNameFrom& nam |
return textAlternative; |
} |
+ // Fieldset / legend. |
aboxhall
2015/11/05 17:49:21
Wohoo! You can add http://crbug.com/550663 to the
dmazzoni
2015/11/06 00:21:17
Done.
|
+ if (isHTMLFieldSetElement(node())) { |
+ nameFrom = AXNameFromRelatedElement; |
+ if (nameSources) { |
+ nameSources->append(NameSource(*foundTextAlternative)); |
+ nameSources->last().type = nameFrom; |
+ nameSources->last().nativeSource = AXTextFromNativeHTMLLegend; |
+ } |
+ HTMLElement* legend = toHTMLFieldSetElement(node())->legend(); |
+ if (legend) { |
+ AXObject* legendAXObject = axObjectCache().getOrCreate(legend); |
+ // Avoid an infinite loop |
+ if (legendAXObject && !visited.contains(legendAXObject)) { |
+ textAlternative = recursiveTextAlternative(*legendAXObject, false, visited); |
+ |
+ if (relatedObjects) { |
+ localRelatedObjects.append(new NameSourceRelatedObject(legendAXObject, textAlternative)); |
+ *relatedObjects = localRelatedObjects; |
+ localRelatedObjects.clear(); |
+ } |
+ |
+ if (nameSources) { |
+ NameSource& source = nameSources->last(); |
+ source.relatedObjects = *relatedObjects; |
+ source.text = textAlternative; |
+ source.nativeSource = AXTextFromNativeHTMLLegend; |
aboxhall
2015/11/05 17:49:21
No need to re-set this.
dmazzoni
2015/11/06 00:21:17
Done.
|
+ *foundTextAlternative = true; |
+ } else { |
+ return textAlternative; |
+ } |
+ } |
+ } |
+ } |
+ |
return textAlternative; |
} |
@@ -3019,6 +3072,24 @@ String AXNodeObject::description(AXNameFrom nameFrom, AXDescriptionFrom& descrip |
} |
} |
+ // aria-help. |
+ // FIXME: this is not part of the official standard, but it's needed because the built-in date/time controls use it. |
+ descriptionFrom = AXDescriptionFromAttribute; |
+ if (descriptionSources) { |
+ descriptionSources->append(DescriptionSource(foundDescription, aria_helpAttr)); |
+ descriptionSources->last().type = descriptionFrom; |
+ } |
+ const AtomicString& help = getAttribute(aria_helpAttr); |
+ if (!help.isEmpty()) { |
+ description = help; |
+ if (descriptionSources) { |
+ foundDescription = true; |
+ descriptionSources->last().text = description; |
+ } else { |
+ return description; |
+ } |
+ } |
+ |
descriptionFrom = AXDescriptionFromUninitialized; |
if (foundDescription) { |
@@ -3042,4 +3113,4 @@ DEFINE_TRACE(AXNodeObject) |
AXObject::trace(visitor); |
} |
-} // namespace blink |
+} // namespace blin |