Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(633)

Unified Diff: third_party/WebKit/Source/modules/accessibility/AXObject.cpp

Issue 1435113003: Make use of new AX name calc in Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix issue with ariaTextAlternative Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/accessibility/AXObject.cpp
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
index a42851d0de31cac768b73194897a01fab759e9e3..5dd1f4cdf24a955960b99b94f821d2d4921cc735 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -676,6 +676,13 @@ bool AXObject::isPresentationalChild() const
return m_cachedIsPresentationalChild;
}
+String AXObject::computedName() const
+{
+ AXNameFrom nameFrom;
+ AXObject::AXObjectVector nameObjects;
+ return name(nameFrom, &nameObjects);
+}
+
String AXObject::name(AXNameFrom& nameFrom, AXObject::AXObjectVector* nameObjects) const
{
HeapHashSet<Member<const AXObject>> visited;
@@ -683,7 +690,7 @@ String AXObject::name(AXNameFrom& nameFrom, AXObject::AXObjectVector* nameObject
String text = textAlternative(false, false, visited, nameFrom, &relatedObjects, nullptr);
if (!node() || !isHTMLBRElement(node()))
- text = text.simplifyWhiteSpace(isHTMLSpace<UChar>);
+ text = text.simplifyWhiteSpace(isHTMLSpace<UChar>, WTF::DoNotStripWhiteSpace);
if (nameObjects) {
nameObjects->clear();
@@ -709,6 +716,154 @@ String AXObject::recursiveTextAlternative(const AXObject& axObj, bool inAriaLabe
return axObj.textAlternative(true, inAriaLabelledByTraversal, visited, tmpNameFrom, nullptr, nullptr);
}
+String AXObject::ariaTextAlternative(bool recursive, bool inAriaLabelledByTraversal, AXObjectSet& visited, AXNameFrom& nameFrom, AXRelatedObjectVector* relatedObjects, NameSources* nameSources, bool* foundTextAlternative) const
+{
+ String textAlternative;
+ bool alreadyVisited = visited.contains(this);
+ visited.add(this);
+
+ // Step 2A from: http://www.w3.org/TR/accname-aam-1.1
+ if (!recursive && layoutObject()
+ && layoutObject()->style()->visibility() != VISIBLE
+ && !equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) {
+ return String();
+ }
+
+ // Step 2B from: http://www.w3.org/TR/accname-aam-1.1
+ if (!inAriaLabelledByTraversal && !alreadyVisited) {
+ const QualifiedName& attr = hasAttribute(aria_labeledbyAttr) && !hasAttribute(aria_labelledbyAttr) ? aria_labeledbyAttr : aria_labelledbyAttr;
+ nameFrom = AXNameFromRelatedElement;
+ if (nameSources) {
+ nameSources->append(NameSource(*foundTextAlternative, attr));
+ nameSources->last().type = nameFrom;
+ }
+
+ const AtomicString& ariaLabelledby = getAttribute(attr);
+ if (!ariaLabelledby.isNull()) {
+ if (nameSources)
+ nameSources->last().attributeValue = ariaLabelledby;
+
+ textAlternative = textFromAriaLabelledby(visited, relatedObjects);
+
+ if (!textAlternative.isNull()) {
+ if (nameSources) {
+ NameSource& source = nameSources->last();
+ source.type = nameFrom;
+ source.relatedObjects = *relatedObjects;
+ source.text = textAlternative;
+ *foundTextAlternative = true;
+ } else {
+ *foundTextAlternative = true;
+ return textAlternative;
+ }
+ } else if (nameSources) {
+ nameSources->last().invalid = true;
+ }
+ }
+ }
+
+ // Step 2C from: http://www.w3.org/TR/accname-aam-1.1
+ nameFrom = AXNameFromAttribute;
+ if (nameSources) {
+ nameSources->append(NameSource(*foundTextAlternative, aria_labelAttr));
+ nameSources->last().type = nameFrom;
+ }
+ const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
+ if (!ariaLabel.isEmpty()) {
+ textAlternative = ariaLabel;
+
+ if (nameSources) {
+ NameSource& source = nameSources->last();
+ source.text = textAlternative;
+ source.attributeValue = ariaLabel;
+ *foundTextAlternative = true;
+ } else {
+ *foundTextAlternative = true;
+ return textAlternative;
+ }
+ }
+
+ return textAlternative;
+}
+
+String AXObject::textFromElements(bool inAriaLabelledbyTraversal, AXObjectSet& visited, WillBeHeapVector<RawPtrWillBeMember<Element>>& elements, AXRelatedObjectVector* relatedObjects) const
+{
+ StringBuilder accumulatedText;
+ bool foundValidElement = false;
+ AXRelatedObjectVector localRelatedObjects;
+
+ for (const auto& element : elements) {
+ AXObject* axElement = axObjectCache().getOrCreate(element);
+ if (axElement) {
+ foundValidElement = true;
+
+ String result = recursiveTextAlternative(*axElement, inAriaLabelledbyTraversal, visited);
+ localRelatedObjects.append(new NameSourceRelatedObject(axElement, result));
+ if (!result.isEmpty()) {
+ if (!accumulatedText.isEmpty())
+ accumulatedText.append(" ");
+ accumulatedText.append(result);
+ }
+ }
+ }
+ if (!foundValidElement)
+ return String();
+ if (relatedObjects)
+ *relatedObjects = localRelatedObjects;
+ return accumulatedText.toString();
+}
+
+void AXObject::tokenVectorFromAttribute(Vector<String>& tokens, const QualifiedName& attribute) const
+{
+ Node* node = this->node();
+ if (!node || !node->isElementNode())
+ return;
+
+ String attributeValue = getAttribute(attribute).string();
+ if (attributeValue.isEmpty())
+ return;
+
+ attributeValue.simplifyWhiteSpace();
+ attributeValue.split(' ', tokens);
+}
+
+void AXObject::elementsFromAttribute(WillBeHeapVector<RawPtrWillBeMember<Element>>& elements, const QualifiedName& attribute) const
+{
+ Vector<String> ids;
+ tokenVectorFromAttribute(ids, attribute);
+ if (ids.isEmpty())
+ return;
+
+ TreeScope& scope = node()->treeScope();
+ for (const auto& id : ids) {
+ if (Element* idElement = scope.getElementById(AtomicString(id)))
+ elements.append(idElement);
+ }
+}
+
+void AXObject::ariaLabelledbyElementVector(WillBeHeapVector<RawPtrWillBeMember<Element>>& elements) const
+{
+ // Try both spellings, but prefer aria-labelledby, which is the official spec.
+ elementsFromAttribute(elements, aria_labelledbyAttr);
+ if (!elements.size())
+ elementsFromAttribute(elements, aria_labeledbyAttr);
+}
+
+String AXObject::textFromAriaLabelledby(AXObjectSet& visited, AXRelatedObjectVector* relatedObjects) const
+{
+ WillBeHeapVector<RawPtrWillBeMember<Element>> elements;
+ ariaLabelledbyElementVector(elements);
+ return textFromElements(true, visited, elements, relatedObjects);
+}
+
+String AXObject::textFromAriaDescribedby(AXRelatedObjectVector* relatedObjects) const
+{
+ AXObjectSet visited;
+ WillBeHeapVector<RawPtrWillBeMember<Element>> elements;
+ elementsFromAttribute(elements, aria_describedbyAttr);
+ return textFromElements(true, visited, elements, relatedObjects);
+}
+
AccessibilityOrientation AXObject::orientation() const
{
// In ARIA 1.1, the default value for aria-orientation changed from
@@ -1480,13 +1635,13 @@ bool AXObject::nameFromContents() const
case MenuItemCheckBoxRole:
case MenuItemRadioRole:
case MenuListOptionRole:
+ case PopUpButtonRole:
case RadioButtonRole:
case StaticTextRole:
case StatusRole:
case SwitchRole:
case TabRole:
case ToggleButtonRole:
- case TreeItemRole:
return true;
default:
return false;

Powered by Google App Engine
This is Rietveld 408576698