OLD | NEW |
---|---|
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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 #include "core/html/HTMLMediaElement.h" | 43 #include "core/html/HTMLMediaElement.h" |
44 #include "core/html/HTMLMeterElement.h" | 44 #include "core/html/HTMLMeterElement.h" |
45 #include "core/html/HTMLPlugInElement.h" | 45 #include "core/html/HTMLPlugInElement.h" |
46 #include "core/html/HTMLSelectElement.h" | 46 #include "core/html/HTMLSelectElement.h" |
47 #include "core/html/HTMLTableCaptionElement.h" | 47 #include "core/html/HTMLTableCaptionElement.h" |
48 #include "core/html/HTMLTableCellElement.h" | 48 #include "core/html/HTMLTableCellElement.h" |
49 #include "core/html/HTMLTableElement.h" | 49 #include "core/html/HTMLTableElement.h" |
50 #include "core/html/HTMLTableRowElement.h" | 50 #include "core/html/HTMLTableRowElement.h" |
51 #include "core/html/HTMLTableSectionElement.h" | 51 #include "core/html/HTMLTableSectionElement.h" |
52 #include "core/html/HTMLTextAreaElement.h" | 52 #include "core/html/HTMLTextAreaElement.h" |
53 #include "core/html/LabelsNodeList.h" | |
53 #include "core/html/parser/HTMLParserIdioms.h" | 54 #include "core/html/parser/HTMLParserIdioms.h" |
54 #include "core/html/shadow/MediaControlElements.h" | 55 #include "core/html/shadow/MediaControlElements.h" |
55 #include "core/layout/LayoutBlockFlow.h" | 56 #include "core/layout/LayoutBlockFlow.h" |
56 #include "core/layout/LayoutObject.h" | 57 #include "core/layout/LayoutObject.h" |
57 #include "core/svg/SVGElement.h" | 58 #include "core/svg/SVGElement.h" |
58 #include "modules/accessibility/AXObjectCacheImpl.h" | 59 #include "modules/accessibility/AXObjectCacheImpl.h" |
59 #include "platform/UserGestureIndicator.h" | 60 #include "platform/UserGestureIndicator.h" |
60 #include "platform/text/PlatformLocale.h" | 61 #include "platform/text/PlatformLocale.h" |
61 #include "wtf/text/StringBuilder.h" | 62 #include "wtf/text/StringBuilder.h" |
62 | 63 |
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
636 return false; | 637 return false; |
637 | 638 |
638 // An SVG root is focusable by default, but it's probably not interactive, s o don't | 639 // An SVG root is focusable by default, but it's probably not interactive, s o don't |
639 // include it. It can still be made accessible by giving it an ARIA role. | 640 // include it. It can still be made accessible by giving it an ARIA role. |
640 if (roleValue() == SVGRootRole) | 641 if (roleValue() == SVGRootRole) |
641 return false; | 642 return false; |
642 | 643 |
643 return true; | 644 return true; |
644 } | 645 } |
645 | 646 |
646 HTMLLabelElement* AXNodeObject::labelForElement(const Element* element) const | |
647 { | |
648 if (!element->isHTMLElement() || !toHTMLElement(element)->isLabelable()) | |
649 return 0; | |
650 | |
651 const AtomicString& id = element->getIdAttribute(); | |
652 if (!id.isEmpty()) { | |
653 if (HTMLLabelElement* labelFor = element->treeScope().labelElementForId( id)) | |
654 return labelFor; | |
655 } | |
656 | |
657 HTMLLabelElement* labelWrappedElement = Traversal<HTMLLabelElement>::firstAn cestor(*element); | |
658 if (labelWrappedElement && labelWrappedElement->control() == toLabelableElem ent(element)) | |
659 return labelWrappedElement; | |
660 | |
661 return 0; | |
662 } | |
663 | |
664 AXObject* AXNodeObject::menuButtonForMenu() const | 647 AXObject* AXNodeObject::menuButtonForMenu() const |
665 { | 648 { |
666 Element* menuItem = menuItemElementForMenu(); | 649 Element* menuItem = menuItemElementForMenu(); |
667 | 650 |
668 if (menuItem) { | 651 if (menuItem) { |
669 // ARIA just has generic menu items. AppKit needs to know if this is a t op level items like MenuBarButton or MenuBarItem | 652 // ARIA just has generic menu items. AppKit needs to know if this is a t op level items like MenuBarButton or MenuBarItem |
670 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); | 653 AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem); |
671 if (menuItemAX && menuItemAX->isMenuButton()) | 654 if (menuItemAX && menuItemAX->isMenuButton()) |
672 return menuItemAX; | 655 return menuItemAX; |
673 } | 656 } |
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1607 if (nameSources) { | 1590 if (nameSources) { |
1608 foundTextAlternative = true; | 1591 foundTextAlternative = true; |
1609 nameSources->last().text = textAlternative; | 1592 nameSources->last().text = textAlternative; |
1610 } else { | 1593 } else { |
1611 return textAlternative; | 1594 return textAlternative; |
1612 } | 1595 } |
1613 } | 1596 } |
1614 | 1597 |
1615 nameFrom = AXNameFromUninitialized; | 1598 nameFrom = AXNameFromUninitialized; |
1616 | 1599 |
1617 if (foundTextAlternative) { | 1600 if (nameSources && foundTextAlternative) { |
1618 for (size_t i = 0; i < nameSources->size(); ++i) { | 1601 for (size_t i = 0; i < nameSources->size(); ++i) { |
1619 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede d) { | 1602 if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].supersede d) { |
1620 NameSource& nameSource = (*nameSources)[i]; | 1603 NameSource& nameSource = (*nameSources)[i]; |
1621 nameFrom = nameSource.type; | 1604 nameFrom = nameSource.type; |
1622 if (!nameSource.relatedObjects.isEmpty()) | 1605 if (!nameSource.relatedObjects.isEmpty()) |
1623 *relatedObjects = nameSource.relatedObjects; | 1606 *relatedObjects = nameSource.relatedObjects; |
1624 return nameSource.text; | 1607 return nameSource.text; |
1625 } | 1608 } |
1626 } | 1609 } |
1627 } | 1610 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1701 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 | 1684 // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 |
1702 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); | 1685 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); |
1703 if (!ariaLabel.isEmpty()) | 1686 if (!ariaLabel.isEmpty()) |
1704 return false; | 1687 return false; |
1705 | 1688 |
1706 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi ble-name-and-description-calculation | 1689 // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessi ble-name-and-description-calculation |
1707 // 5.1/5.5 Text inputs, Other labelable Elements | 1690 // 5.1/5.5 Text inputs, Other labelable Elements |
1708 HTMLElement* htmlElement = nullptr; | 1691 HTMLElement* htmlElement = nullptr; |
1709 if (getNode()->isHTMLElement()) | 1692 if (getNode()->isHTMLElement()) |
1710 htmlElement = toHTMLElement(getNode()); | 1693 htmlElement = toHTMLElement(getNode()); |
1711 if (htmlElement && htmlElement->isLabelable()) { | 1694 if (htmlElement && isLabelableElement(htmlElement)) { |
1712 HTMLLabelElement* label = labelForElement(htmlElement); | 1695 if (toLabelableElement(htmlElement)->labels() && toLabelableElement(html Element)->labels()->length() > 0) |
1713 if (label) | |
1714 return true; | 1696 return true; |
1715 } | 1697 } |
1716 | 1698 |
1717 return false; | 1699 return false; |
1718 } | 1700 } |
1719 | 1701 |
1720 LayoutRect AXNodeObject::elementRect() const | 1702 LayoutRect AXNodeObject::elementRect() const |
1721 { | 1703 { |
1722 // First check if it has a custom rect, for example if this element is tied to a canvas path. | 1704 // First check if it has a custom rect, for example if this element is tied to a canvas path. |
1723 if (!m_explicitElementRect.isEmpty()) | 1705 if (!m_explicitElementRect.isEmpty()) |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2170 | 2152 |
2171 const HTMLInputElement* inputElement = nullptr; | 2153 const HTMLInputElement* inputElement = nullptr; |
2172 if (isHTMLInputElement(getNode())) | 2154 if (isHTMLInputElement(getNode())) |
2173 inputElement = toHTMLInputElement(getNode()); | 2155 inputElement = toHTMLInputElement(getNode()); |
2174 | 2156 |
2175 // 5.1/5.5 Text inputs, Other labelable Elements | 2157 // 5.1/5.5 Text inputs, Other labelable Elements |
2176 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. | 2158 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. |
2177 HTMLElement* htmlElement = nullptr; | 2159 HTMLElement* htmlElement = nullptr; |
2178 if (getNode()->isHTMLElement()) | 2160 if (getNode()->isHTMLElement()) |
2179 htmlElement = toHTMLElement(getNode()); | 2161 htmlElement = toHTMLElement(getNode()); |
2162 | |
2180 if (htmlElement && htmlElement->isLabelable()) { | 2163 if (htmlElement && htmlElement->isLabelable()) { |
2181 // label | |
2182 nameFrom = AXNameFromRelatedElement; | 2164 nameFrom = AXNameFromRelatedElement; |
2183 if (nameSources) { | 2165 if (nameSources) { |
2184 nameSources->append(NameSource(*foundTextAlternative)); | 2166 nameSources->append(NameSource(*foundTextAlternative)); |
2185 nameSources->last().type = nameFrom; | 2167 nameSources->last().type = nameFrom; |
2186 nameSources->last().nativeSource = AXTextFromNativeHTMLLabel; | 2168 nameSources->last().nativeSource = AXTextFromNativeHTMLLabel; |
2187 } | 2169 } |
2188 HTMLLabelElement* label = labelForElement(htmlElement); | |
2189 if (label) { | |
2190 AXObject* labelAXObject = axObjectCache().getOrCreate(label); | |
2191 // Avoid an infinite loop for label wrapped | |
2192 if (labelAXObject && !visited.contains(labelAXObject)) { | |
2193 textAlternative = recursiveTextAlternative(*labelAXObject, false , visited); | |
2194 | 2170 |
2195 if (relatedObjects) { | 2171 LabelsNodeList* labels = toLabelableElement(htmlElement)->labels(); |
2196 localRelatedObjects.append(new NameSourceRelatedObject(label AXObject, textAlternative)); | 2172 if (labels && labels->length() > 0) { |
2197 *relatedObjects = localRelatedObjects; | 2173 StringBuilder accumulatedText; |
2198 localRelatedObjects.clear(); | 2174 for (unsigned labelIndex = 0; labelIndex < labels->length(); ++label Index) { |
2199 } | 2175 Element* label = labels->item(labelIndex); |
2176 AXObject* labelAXObject = axObjectCache().getOrCreate(label); | |
2177 // Avoid an infinite loop for label wrapped | |
2178 if (labelAXObject && !visited.contains(labelAXObject)) { | |
2179 *foundTextAlternative = true; | |
2180 String result = recursiveTextAlternative(*labelAXObject, fal se, visited); | |
2181 if (!result.isEmpty()) { | |
2182 if (!accumulatedText.isEmpty()) | |
2183 accumulatedText.append(" "); | |
2184 accumulatedText.append(result); | |
2185 } | |
2200 | 2186 |
2201 if (nameSources) { | 2187 if (relatedObjects) { |
aboxhall
2016/05/16 17:19:01
Now that I've had a closer look, this is weird. Se
dmazzoni
2016/06/01 19:53:23
OK, ready for another look. I had this call AXObje
| |
2202 NameSource& source = nameSources->last(); | 2188 localRelatedObjects.append(new NameSourceRelatedObject(l abelAXObject, result)); |
2203 source.relatedObjects = *relatedObjects; | 2189 *relatedObjects = localRelatedObjects; |
2204 source.text = textAlternative; | 2190 } |
2205 if (label->getAttribute(forAttr) == htmlElement->getIdAttrib ute()) | 2191 |
2206 source.nativeSource = AXTextFromNativeHTMLLabelFor; | 2192 if (nameSources) { |
2207 else | 2193 NameSource& source = nameSources->last(); |
2208 source.nativeSource = AXTextFromNativeHTMLLabelWrapped; | 2194 source.relatedObjects = *relatedObjects; |
2209 *foundTextAlternative = true; | 2195 source.text = textAlternative; |
2210 } else { | 2196 if (label->getAttribute(forAttr) == htmlElement->getIdAt tribute()) |
2211 return textAlternative; | 2197 source.nativeSource = AXTextFromNativeHTMLLabelFor; |
2198 else | |
2199 source.nativeSource = AXTextFromNativeHTMLLabelWrapp ed; | |
2200 } | |
2212 } | 2201 } |
2213 } | 2202 } |
2203 | |
2204 if (relatedObjects) | |
2205 localRelatedObjects.clear(); | |
2206 | |
2207 textAlternative = accumulatedText.toString(); | |
2208 if (!nameSources && *foundTextAlternative) | |
2209 return textAlternative; | |
2214 } | 2210 } |
2215 } | 2211 } |
2216 | 2212 |
2217 // 5.2 input type="button", input type="submit" and input type="reset" | 2213 // 5.2 input type="button", input type="submit" and input type="reset" |
2218 if (inputElement && inputElement->isTextButton()) { | 2214 if (inputElement && inputElement->isTextButton()) { |
2219 // value attribue | 2215 // value attribue |
2220 nameFrom = AXNameFromValue; | 2216 nameFrom = AXNameFromValue; |
2221 if (nameSources) { | 2217 if (nameSources) { |
2222 nameSources->append(NameSource(*foundTextAlternative, valueAttr)); | 2218 nameSources->append(NameSource(*foundTextAlternative, valueAttr)); |
2223 nameSources->last().type = nameFrom; | 2219 nameSources->last().type = nameFrom; |
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2792 return placeholder; | 2788 return placeholder; |
2793 } | 2789 } |
2794 | 2790 |
2795 DEFINE_TRACE(AXNodeObject) | 2791 DEFINE_TRACE(AXNodeObject) |
2796 { | 2792 { |
2797 visitor->trace(m_node); | 2793 visitor->trace(m_node); |
2798 AXObject::trace(visitor); | 2794 AXObject::trace(visitor); |
2799 } | 2795 } |
2800 | 2796 |
2801 } // namespace blink | 2797 } // namespace blink |
OLD | NEW |