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

Side by Side Diff: third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp

Issue 1939303002: Enable accessible name of a control to include multiple <label> elements. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't modify visited set when computing aria-labelledby Created 4 years, 6 months 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012, Google Inc. All rights reserved. 2 * Copyright (C) 2012, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 #include "core/html/HTMLMediaElement.h" 45 #include "core/html/HTMLMediaElement.h"
46 #include "core/html/HTMLMeterElement.h" 46 #include "core/html/HTMLMeterElement.h"
47 #include "core/html/HTMLPlugInElement.h" 47 #include "core/html/HTMLPlugInElement.h"
48 #include "core/html/HTMLSelectElement.h" 48 #include "core/html/HTMLSelectElement.h"
49 #include "core/html/HTMLTableCaptionElement.h" 49 #include "core/html/HTMLTableCaptionElement.h"
50 #include "core/html/HTMLTableCellElement.h" 50 #include "core/html/HTMLTableCellElement.h"
51 #include "core/html/HTMLTableElement.h" 51 #include "core/html/HTMLTableElement.h"
52 #include "core/html/HTMLTableRowElement.h" 52 #include "core/html/HTMLTableRowElement.h"
53 #include "core/html/HTMLTableSectionElement.h" 53 #include "core/html/HTMLTableSectionElement.h"
54 #include "core/html/HTMLTextAreaElement.h" 54 #include "core/html/HTMLTextAreaElement.h"
55 #include "core/html/LabelsNodeList.h"
55 #include "core/html/parser/HTMLParserIdioms.h" 56 #include "core/html/parser/HTMLParserIdioms.h"
56 #include "core/html/shadow/MediaControlElements.h" 57 #include "core/html/shadow/MediaControlElements.h"
57 #include "core/layout/LayoutBlockFlow.h" 58 #include "core/layout/LayoutBlockFlow.h"
58 #include "core/layout/LayoutObject.h" 59 #include "core/layout/LayoutObject.h"
59 #include "core/svg/SVGElement.h" 60 #include "core/svg/SVGElement.h"
60 #include "modules/accessibility/AXObjectCacheImpl.h" 61 #include "modules/accessibility/AXObjectCacheImpl.h"
61 #include "platform/UserGestureIndicator.h" 62 #include "platform/UserGestureIndicator.h"
62 #include "platform/text/PlatformLocale.h" 63 #include "platform/text/PlatformLocale.h"
63 #include "wtf/text/StringBuilder.h" 64 #include "wtf/text/StringBuilder.h"
64 65
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 return false; 639 return false;
639 640
640 // An SVG root is focusable by default, but it's probably not interactive, s o don't 641 // An SVG root is focusable by default, but it's probably not interactive, s o don't
641 // include it. It can still be made accessible by giving it an ARIA role. 642 // include it. It can still be made accessible by giving it an ARIA role.
642 if (roleValue() == SVGRootRole) 643 if (roleValue() == SVGRootRole)
643 return false; 644 return false;
644 645
645 return true; 646 return true;
646 } 647 }
647 648
648 HTMLLabelElement* AXNodeObject::labelForElement(const Element* element) const
649 {
650 if (!element->isHTMLElement() || !toHTMLElement(element)->isLabelable())
651 return 0;
652
653 const AtomicString& id = element->getIdAttribute();
654 if (!id.isEmpty()) {
655 if (HTMLLabelElement* labelFor = element->treeScope().labelElementForId( id))
656 return labelFor;
657 }
658
659 HTMLLabelElement* labelWrappedElement = Traversal<HTMLLabelElement>::firstAn cestor(*element);
660 if (labelWrappedElement && labelWrappedElement->control() == toLabelableElem ent(element))
661 return labelWrappedElement;
662
663 return 0;
664 }
665
666 AXObject* AXNodeObject::menuButtonForMenu() const 649 AXObject* AXNodeObject::menuButtonForMenu() const
667 { 650 {
668 Element* menuItem = menuItemElementForMenu(); 651 Element* menuItem = menuItemElementForMenu();
669 652
670 if (menuItem) { 653 if (menuItem) {
671 // ARIA just has generic menu items. AppKit needs to know if this is a t op level items like MenuBarButton or MenuBarItem 654 // ARIA just has generic menu items. AppKit needs to know if this is a t op level items like MenuBarButton or MenuBarItem
672 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); 655 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem);
673 if (menuItemAX && menuItemAX->isMenuButton()) 656 if (menuItemAX && menuItemAX->isMenuButton())
674 return menuItemAX; 657 return menuItemAX;
675 } 658 }
(...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 if (nameSources) { 1645 if (nameSources) {
1663 foundTextAlternative = true; 1646 foundTextAlternative = true;
1664 nameSources->last().text = textAlternative; 1647 nameSources->last().text = textAlternative;
1665 } else { 1648 } else {
1666 return textAlternative; 1649 return textAlternative;
1667 } 1650 }
1668 } 1651 }
1669 1652
1670 nameFrom = AXNameFromUninitialized; 1653 nameFrom = AXNameFromUninitialized;
1671 1654
1672 if (foundTextAlternative) { 1655 if (nameSources && foundTextAlternative) {
1673 for (size_t i = 0; i < nameSources->size(); ++i) { 1656 for (size_t i = 0; i < nameSources->size(); ++i) {
1674 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede d) { 1657 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede d) {
1675 NameSource& nameSource = (*nameSources)[i]; 1658 NameSource& nameSource = (*nameSources)[i];
1676 nameFrom = nameSource.type; 1659 nameFrom = nameSource.type;
1677 if (!nameSource.relatedObjects.isEmpty()) 1660 if (!nameSource.relatedObjects.isEmpty())
1678 *relatedObjects = nameSource.relatedObjects; 1661 *relatedObjects = nameSource.relatedObjects;
1679 return nameSource.text; 1662 return nameSource.text;
1680 } 1663 }
1681 } 1664 }
1682 } 1665 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1756 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 1739 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1
1757 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); 1740 const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
1758 if (!ariaLabel.isEmpty()) 1741 if (!ariaLabel.isEmpty())
1759 return false; 1742 return false;
1760 1743
1761 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi ble-name-and-description-calculation 1744 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi ble-name-and-description-calculation
1762 // 5.1/5.5 Text inputs, Other labelable Elements 1745 // 5.1/5.5 Text inputs, Other labelable Elements
1763 HTMLElement* htmlElement = nullptr; 1746 HTMLElement* htmlElement = nullptr;
1764 if (getNode()->isHTMLElement()) 1747 if (getNode()->isHTMLElement())
1765 htmlElement = toHTMLElement(getNode()); 1748 htmlElement = toHTMLElement(getNode());
1766 if (htmlElement && htmlElement->isLabelable()) { 1749 if (htmlElement && isLabelableElement(htmlElement)) {
1767 HTMLLabelElement* label = labelForElement(htmlElement); 1750 if (toLabelableElement(htmlElement)->labels() && toLabelableElement(html Element)->labels()->length() > 0)
1768 if (label)
1769 return true; 1751 return true;
1770 } 1752 }
1771 1753
1772 return false; 1754 return false;
1773 } 1755 }
1774 1756
1775 LayoutRect AXNodeObject::elementRect() const 1757 LayoutRect AXNodeObject::elementRect() const
1776 { 1758 {
1777 // First check if it has a custom rect, for example if this element is tied to a canvas path. 1759 // First check if it has a custom rect, for example if this element is tied to a canvas path.
1778 if (!m_explicitElementRect.isEmpty()) 1760 if (!m_explicitElementRect.isEmpty())
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
2225 2207
2226 const HTMLInputElement* inputElement = nullptr; 2208 const HTMLInputElement* inputElement = nullptr;
2227 if (isHTMLInputElement(getNode())) 2209 if (isHTMLInputElement(getNode()))
2228 inputElement = toHTMLInputElement(getNode()); 2210 inputElement = toHTMLInputElement(getNode());
2229 2211
2230 // 5.1/5.5 Text inputs, Other labelable Elements 2212 // 5.1/5.5 Text inputs, Other labelable Elements
2231 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. 2213 // If you change this logic, update AXNodeObject::nameFromLabelElement, too.
2232 HTMLElement* htmlElement = nullptr; 2214 HTMLElement* htmlElement = nullptr;
2233 if (getNode()->isHTMLElement()) 2215 if (getNode()->isHTMLElement())
2234 htmlElement = toHTMLElement(getNode()); 2216 htmlElement = toHTMLElement(getNode());
2217
2235 if (htmlElement && htmlElement->isLabelable()) { 2218 if (htmlElement && htmlElement->isLabelable()) {
2236 // label
2237 nameFrom = AXNameFromRelatedElement; 2219 nameFrom = AXNameFromRelatedElement;
2238 if (nameSources) { 2220 if (nameSources) {
2239 nameSources->append(NameSource(*foundTextAlternative)); 2221 nameSources->append(NameSource(*foundTextAlternative));
2240 nameSources->last().type = nameFrom; 2222 nameSources->last().type = nameFrom;
2241 nameSources->last().nativeSource = AXTextFromNativeHTMLLabel; 2223 nameSources->last().nativeSource = AXTextFromNativeHTMLLabel;
2242 } 2224 }
2243 HTMLLabelElement* label = labelForElement(htmlElement);
2244 if (label) {
2245 AXObject* labelAXObject = axObjectCache().getOrCreate(label);
2246 // Avoid an infinite loop for label wrapped
2247 if (labelAXObject && !visited.contains(labelAXObject)) {
2248 textAlternative = recursiveTextAlternative(*labelAXObject, false , visited);
2249 2225
2250 if (relatedObjects) { 2226 LabelsNodeList* labels = toLabelableElement(htmlElement)->labels();
2251 localRelatedObjects.append(new NameSourceRelatedObject(label AXObject, textAlternative)); 2227 if (labels && labels->length() > 0) {
2252 *relatedObjects = localRelatedObjects; 2228 HeapVector<Member<Element>> labelElements;
2253 localRelatedObjects.clear(); 2229 for (unsigned labelIndex = 0; labelIndex < labels->length(); ++label Index) {
2230 Element* label = labels->item(labelIndex);
2231 if (nameSources) {
2232 if (label->getAttribute(forAttr) == htmlElement->getIdAttrib ute())
2233 nameSources->last().nativeSource = AXTextFromNativeHTMLL abelFor;
2234 else
2235 nameSources->last().nativeSource = AXTextFromNativeHTMLL abelWrapped;
2254 } 2236 }
2237 labelElements.append(label);
2238 }
2255 2239
2240 textAlternative = textFromElements(false, visited, labelElements, re latedObjects);
2241 if (!textAlternative.isNull()) {
2242 *foundTextAlternative = true;
2256 if (nameSources) { 2243 if (nameSources) {
2257 NameSource& source = nameSources->last(); 2244 NameSource& source = nameSources->last();
2258 source.relatedObjects = *relatedObjects; 2245 source.relatedObjects = *relatedObjects;
2259 source.text = textAlternative; 2246 source.text = textAlternative;
2260 if (label->getAttribute(forAttr) == htmlElement->getIdAttrib ute())
2261 source.nativeSource = AXTextFromNativeHTMLLabelFor;
2262 else
2263 source.nativeSource = AXTextFromNativeHTMLLabelWrapped;
2264 *foundTextAlternative = true;
2265 } else { 2247 } else {
2266 return textAlternative; 2248 return textAlternative;
2267 } 2249 }
2250 } else if (nameSources) {
2251 nameSources->last().invalid = true;
2268 } 2252 }
2269 } 2253 }
2270 } 2254 }
2271 2255
2272 // 5.2 input type="button", input type="submit" and input type="reset" 2256 // 5.2 input type="button", input type="submit" and input type="reset"
2273 if (inputElement && inputElement->isTextButton()) { 2257 if (inputElement && inputElement->isTextButton()) {
2274 // value attribue 2258 // value attribue
2275 nameFrom = AXNameFromValue; 2259 nameFrom = AXNameFromValue;
2276 if (nameSources) { 2260 if (nameSources) {
2277 nameSources->append(NameSource(*foundTextAlternative, valueAttr)); 2261 nameSources->append(NameSource(*foundTextAlternative, valueAttr));
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
2847 return placeholder; 2831 return placeholder;
2848 } 2832 }
2849 2833
2850 DEFINE_TRACE(AXNodeObject) 2834 DEFINE_TRACE(AXNodeObject)
2851 { 2835 {
2852 visitor->trace(m_node); 2836 visitor->trace(m_node);
2853 AXObject::trace(visitor); 2837 AXObject::trace(visitor);
2854 } 2838 }
2855 2839
2856 } // namespace blink 2840 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698