| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple 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 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 } | 585 } |
| 586 | 586 |
| 587 // TODO: we should refactor this - but right now this is necessary to make | 587 // TODO: we should refactor this - but right now this is necessary to make |
| 588 // sure scroll areas stay in the tree. | 588 // sure scroll areas stay in the tree. |
| 589 if (isAttachment()) | 589 if (isAttachment()) |
| 590 return false; | 590 return false; |
| 591 | 591 |
| 592 // find out if this element is inside of a label element. | 592 // find out if this element is inside of a label element. |
| 593 // if so, it may be ignored because it's the label for a checkbox or radio b
utton | 593 // if so, it may be ignored because it's the label for a checkbox or radio b
utton |
| 594 AXObject* controlObject = correspondingControlForLabelElement(); | 594 AXObject* controlObject = correspondingControlForLabelElement(); |
| 595 if (controlObject && !controlObject->deprecatedExposesTitleUIElement() && co
ntrolObject->isCheckboxOrRadio()) { | 595 if (controlObject && controlObject->isCheckboxOrRadio()) { |
| 596 if (ignoredReasons) { | 596 AXNameFrom controlNameFrom; |
| 597 HTMLLabelElement* label = labelElementContainer(); | 597 AXObject::AXObjectVector controlNameObjects; |
| 598 if (label && !label->isSameNode(node())) { | 598 controlObject->name(controlNameFrom, &controlNameObjects); |
| 599 AXObject* labelAXObject = axObjectCache().getOrCreate(label); | 599 if (controlNameFrom == AXNameFromRelatedElement) { |
| 600 ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXOb
ject)); | 600 if (ignoredReasons) { |
| 601 HTMLLabelElement* label = labelElementContainer(); |
| 602 if (label && !label->isSameNode(node())) { |
| 603 AXObject* labelAXObject = axObjectCache().getOrCreate(label)
; |
| 604 ignoredReasons->append(IgnoredReason(AXLabelContainer, label
AXObject)); |
| 605 } |
| 606 |
| 607 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject))
; |
| 601 } | 608 } |
| 602 | 609 return true; |
| 603 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); | |
| 604 } | 610 } |
| 605 return true; | |
| 606 } | 611 } |
| 607 | 612 |
| 608 if (m_layoutObject->isBR()) | 613 if (m_layoutObject->isBR()) |
| 609 return false; | 614 return false; |
| 610 | 615 |
| 611 if (m_layoutObject->isText()) { | 616 if (m_layoutObject->isText()) { |
| 612 // static text beneath MenuItems and MenuButtons are just reported along
with the menu item, so it's ignored on an individual level | 617 // static text beneath MenuItems and MenuButtons are just reported along
with the menu item, so it's ignored on an individual level |
| 613 AXObject* parent = parentObjectUnignored(); | 618 AXObject* parent = parentObjectUnignored(); |
| 614 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ar
iaRoleAttribute() == MenuButtonRole)) { | 619 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ar
iaRoleAttribute() == MenuButtonRole)) { |
| 615 if (ignoredReasons) | 620 if (ignoredReasons) |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 } | 1086 } |
| 1082 } | 1087 } |
| 1083 | 1088 |
| 1084 String AXLayoutObject::stringValue() const | 1089 String AXLayoutObject::stringValue() const |
| 1085 { | 1090 { |
| 1086 if (!m_layoutObject) | 1091 if (!m_layoutObject) |
| 1087 return String(); | 1092 return String(); |
| 1088 | 1093 |
| 1089 LayoutBoxModelObject* cssBox = layoutBoxModelObject(); | 1094 LayoutBoxModelObject* cssBox = layoutBoxModelObject(); |
| 1090 | 1095 |
| 1091 if (ariaRoleAttribute() == StaticTextRole) { | |
| 1092 String staticText = text(); | |
| 1093 if (!staticText.length()) | |
| 1094 staticText = deprecatedTextUnderElement(TextUnderElementAll); | |
| 1095 return staticText; | |
| 1096 } | |
| 1097 | |
| 1098 if (m_layoutObject->isText()) | |
| 1099 return deprecatedTextUnderElement(TextUnderElementAll); | |
| 1100 | |
| 1101 if (cssBox && cssBox->isMenuList()) { | 1096 if (cssBox && cssBox->isMenuList()) { |
| 1102 // LayoutMenuList will go straight to the text() of its selected item. | 1097 // LayoutMenuList will go straight to the text() of its selected item. |
| 1103 // This has to be overridden in the case where the selected item has an
ARIA label. | 1098 // This has to be overridden in the case where the selected item has an
ARIA label. |
| 1104 HTMLSelectElement* selectElement = toHTMLSelectElement(m_layoutObject->n
ode()); | 1099 HTMLSelectElement* selectElement = toHTMLSelectElement(m_layoutObject->n
ode()); |
| 1105 int selectedIndex = selectElement->selectedIndex(); | 1100 int selectedIndex = selectElement->selectedIndex(); |
| 1106 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = sel
ectElement->listItems(); | 1101 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = sel
ectElement->listItems(); |
| 1107 if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems
.size()) { | 1102 if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems
.size()) { |
| 1108 const AtomicString& overriddenDescription = listItems[selectedIndex]
->fastGetAttribute(aria_labelAttr); | 1103 const AtomicString& overriddenDescription = listItems[selectedIndex]
->fastGetAttribute(aria_labelAttr); |
| 1109 if (!overriddenDescription.isNull()) | 1104 if (!overriddenDescription.isNull()) |
| 1110 return overriddenDescription; | 1105 return overriddenDescription; |
| 1111 } | 1106 } |
| 1112 return toLayoutMenuList(m_layoutObject)->text(); | 1107 return toLayoutMenuList(m_layoutObject)->text(); |
| 1113 } | 1108 } |
| 1114 | 1109 |
| 1115 if (m_layoutObject->isListMarker()) | |
| 1116 return toLayoutListMarker(m_layoutObject)->text(); | |
| 1117 | |
| 1118 if (isWebArea()) { | 1110 if (isWebArea()) { |
| 1119 // FIXME: Why would a layoutObject exist when the Document isn't attache
d to a frame? | 1111 // FIXME: Why would a layoutObject exist when the Document isn't attache
d to a frame? |
| 1120 if (m_layoutObject->frame()) | 1112 if (m_layoutObject->frame()) |
| 1121 return String(); | 1113 return String(); |
| 1122 | 1114 |
| 1123 ASSERT_NOT_REACHED(); | 1115 ASSERT_NOT_REACHED(); |
| 1124 } | 1116 } |
| 1125 | 1117 |
| 1126 if (isTextControl()) | 1118 if (isTextControl()) |
| 1127 return text(); | 1119 return text(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1138 return input->value(); | 1130 return input->value(); |
| 1139 } | 1131 } |
| 1140 | 1132 |
| 1141 // FIXME: We might need to implement a value here for more types | 1133 // FIXME: We might need to implement a value here for more types |
| 1142 // FIXME: It would be better not to advertise a value at all for the types f
or which we don't implement one; | 1134 // FIXME: It would be better not to advertise a value at all for the types f
or which we don't implement one; |
| 1143 // this would require subclassing or making accessibilityAttributeNames do s
omething other than return a | 1135 // this would require subclassing or making accessibilityAttributeNames do s
omething other than return a |
| 1144 // single static array. | 1136 // single static array. |
| 1145 return String(); | 1137 return String(); |
| 1146 } | 1138 } |
| 1147 | 1139 |
| 1140 String AXLayoutObject::textAlternative(bool recursive, bool inAriaLabelledByTrav
ersal, AXObjectSet& visited, AXNameFrom& nameFrom, AXRelatedObjectVector* relate
dObjects, NameSources* nameSources) const |
| 1141 { |
| 1142 if (m_layoutObject) { |
| 1143 String textAlternative; |
| 1144 bool foundTextAlternative = false; |
| 1145 |
| 1146 if (m_layoutObject->isBR()) { |
| 1147 textAlternative = String("\n"); |
| 1148 foundTextAlternative = true; |
| 1149 } else if (m_layoutObject->isText() && (!recursive || !m_layoutObject->i
sCounter())) { |
| 1150 LayoutText* layoutText = toLayoutText(m_layoutObject); |
| 1151 String result = layoutText->plainText(); |
| 1152 if (!result.isEmpty() || layoutText->isAllCollapsibleWhitespace()) |
| 1153 textAlternative = result; |
| 1154 else |
| 1155 textAlternative = layoutText->text(); |
| 1156 foundTextAlternative = true; |
| 1157 } else if (m_layoutObject->isListMarker() && !recursive) { |
| 1158 textAlternative = toLayoutListMarker(m_layoutObject)->text(); |
| 1159 foundTextAlternative = true; |
| 1160 } |
| 1161 |
| 1162 if (foundTextAlternative) { |
| 1163 nameFrom = AXNameFromContents; |
| 1164 if (nameSources) { |
| 1165 nameSources->append(NameSource(false)); |
| 1166 nameSources->last().type = nameFrom; |
| 1167 nameSources->last().text = textAlternative; |
| 1168 } |
| 1169 return textAlternative; |
| 1170 } |
| 1171 } |
| 1172 |
| 1173 return AXNodeObject::textAlternative(recursive, inAriaLabelledByTraversal, v
isited, nameFrom, relatedObjects, nameSources); |
| 1174 } |
| 1175 |
| 1148 // | 1176 // |
| 1149 // ARIA attributes. | 1177 // ARIA attributes. |
| 1150 // | 1178 // |
| 1151 | 1179 |
| 1152 AXObject* AXLayoutObject::activeDescendant() const | 1180 AXObject* AXLayoutObject::activeDescendant() const |
| 1153 { | 1181 { |
| 1154 if (!m_layoutObject) | 1182 if (!m_layoutObject) |
| 1155 return 0; | 1183 return 0; |
| 1156 | 1184 |
| 1157 if (m_layoutObject->node() && !m_layoutObject->node()->isElementNode()) | 1185 if (m_layoutObject->node() && !m_layoutObject->node()->isElementNode()) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1181 void AXLayoutObject::ariaFlowToElements(AXObjectVector& flowTo) const | 1209 void AXLayoutObject::ariaFlowToElements(AXObjectVector& flowTo) const |
| 1182 { | 1210 { |
| 1183 accessibilityChildrenFromAttribute(aria_flowtoAttr, flowTo); | 1211 accessibilityChildrenFromAttribute(aria_flowtoAttr, flowTo); |
| 1184 } | 1212 } |
| 1185 | 1213 |
| 1186 void AXLayoutObject::ariaControlsElements(AXObjectVector& controls) const | 1214 void AXLayoutObject::ariaControlsElements(AXObjectVector& controls) const |
| 1187 { | 1215 { |
| 1188 accessibilityChildrenFromAttribute(aria_controlsAttr, controls); | 1216 accessibilityChildrenFromAttribute(aria_controlsAttr, controls); |
| 1189 } | 1217 } |
| 1190 | 1218 |
| 1191 void AXLayoutObject::deprecatedAriaDescribedbyElements(AXObjectVector& described
by) const | |
| 1192 { | |
| 1193 accessibilityChildrenFromAttribute(aria_describedbyAttr, describedby); | |
| 1194 } | |
| 1195 | |
| 1196 void AXLayoutObject::deprecatedAriaLabelledbyElements(AXObjectVector& labelledby
) const | |
| 1197 { | |
| 1198 accessibilityChildrenFromAttribute(aria_labelledbyAttr, labelledby); | |
| 1199 } | |
| 1200 | |
| 1201 void AXLayoutObject::ariaOwnsElements(AXObjectVector& owns) const | 1219 void AXLayoutObject::ariaOwnsElements(AXObjectVector& owns) const |
| 1202 { | 1220 { |
| 1203 accessibilityChildrenFromAttribute(aria_ownsAttr, owns); | 1221 accessibilityChildrenFromAttribute(aria_ownsAttr, owns); |
| 1204 } | 1222 } |
| 1205 | 1223 |
| 1224 void AXLayoutObject::ariaDescribedbyElements(AXObjectVector& describedby) const |
| 1225 { |
| 1226 accessibilityChildrenFromAttribute(aria_describedbyAttr, describedby); |
| 1227 } |
| 1228 |
| 1229 void AXLayoutObject::ariaLabelledbyElements(AXObjectVector& labelledby) const |
| 1230 { |
| 1231 accessibilityChildrenFromAttribute(aria_labelledbyAttr, labelledby); |
| 1232 } |
| 1233 |
| 1206 bool AXLayoutObject::ariaHasPopup() const | 1234 bool AXLayoutObject::ariaHasPopup() const |
| 1207 { | 1235 { |
| 1208 return elementAttributeValue(aria_haspopupAttr); | 1236 return elementAttributeValue(aria_haspopupAttr); |
| 1209 } | 1237 } |
| 1210 | 1238 |
| 1211 bool AXLayoutObject::ariaRoleHasPresentationalChildren() const | 1239 bool AXLayoutObject::ariaRoleHasPresentationalChildren() const |
| 1212 { | 1240 { |
| 1213 switch (m_ariaRole) { | 1241 switch (m_ariaRole) { |
| 1214 case ButtonRole: | 1242 case ButtonRole: |
| 1215 case SliderRole: | 1243 case SliderRole: |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 return true; | 1371 return true; |
| 1344 return elementAttributeValue(aria_atomicAttr); | 1372 return elementAttributeValue(aria_atomicAttr); |
| 1345 } | 1373 } |
| 1346 | 1374 |
| 1347 bool AXLayoutObject::liveRegionBusy() const | 1375 bool AXLayoutObject::liveRegionBusy() const |
| 1348 { | 1376 { |
| 1349 return elementAttributeValue(aria_busyAttr); | 1377 return elementAttributeValue(aria_busyAttr); |
| 1350 } | 1378 } |
| 1351 | 1379 |
| 1352 // | 1380 // |
| 1353 // Accessibility Text. | |
| 1354 // | |
| 1355 | |
| 1356 String AXLayoutObject::deprecatedTextUnderElement(TextUnderElementMode mode) con
st | |
| 1357 { | |
| 1358 if (!m_layoutObject) | |
| 1359 return String(); | |
| 1360 | |
| 1361 if (m_layoutObject->isBR()) | |
| 1362 return String("\n"); | |
| 1363 | |
| 1364 if (m_layoutObject->isFileUploadControl()) | |
| 1365 return toLayoutFileUploadControl(m_layoutObject)->buttonValue(); | |
| 1366 | |
| 1367 if (m_layoutObject->isText()) { | |
| 1368 LayoutText* layoutText = toLayoutText(m_layoutObject); | |
| 1369 String result = layoutText->plainText(); | |
| 1370 if (!result.isEmpty() || layoutText->isAllCollapsibleWhitespace()) | |
| 1371 return result; | |
| 1372 return layoutText->text(); | |
| 1373 } | |
| 1374 | |
| 1375 return AXNodeObject::deprecatedTextUnderElement(mode); | |
| 1376 } | |
| 1377 | |
| 1378 // | |
| 1379 // Accessibility Text - (To be deprecated). | |
| 1380 // | |
| 1381 | |
| 1382 String AXLayoutObject::deprecatedHelpText() const | |
| 1383 { | |
| 1384 if (!m_layoutObject) | |
| 1385 return String(); | |
| 1386 | |
| 1387 const AtomicString& ariaHelp = getAttribute(aria_helpAttr); | |
| 1388 if (!ariaHelp.isEmpty()) | |
| 1389 return ariaHelp; | |
| 1390 | |
| 1391 String describedBy = ariaDescribedByAttribute(); | |
| 1392 if (!describedBy.isEmpty()) | |
| 1393 return describedBy; | |
| 1394 | |
| 1395 String description = deprecatedAccessibilityDescription(); | |
| 1396 for (LayoutObject* curr = m_layoutObject; curr; curr = curr->parent()) { | |
| 1397 if (curr->node() && curr->node()->isHTMLElement()) { | |
| 1398 const AtomicString& summary = toElement(curr->node())->getAttribute(
summaryAttr); | |
| 1399 if (!summary.isEmpty()) | |
| 1400 return summary; | |
| 1401 | |
| 1402 // The title attribute should be used as help text unless it is alre
ady being used as descriptive text. | |
| 1403 const AtomicString& title = toElement(curr->node())->getAttribute(ti
tleAttr); | |
| 1404 if (!title.isEmpty() && description != title) | |
| 1405 return title; | |
| 1406 } | |
| 1407 | |
| 1408 // Only take help text from an ancestor element if its a group or an unk
nown role. If help was | |
| 1409 // added to those kinds of elements, it is likely it was meant for a chi
ld element. | |
| 1410 AXObject* axObj = axObjectCache().getOrCreate(curr); | |
| 1411 if (axObj) { | |
| 1412 AccessibilityRole role = axObj->roleValue(); | |
| 1413 if (role != GroupRole && role != UnknownRole) | |
| 1414 break; | |
| 1415 } | |
| 1416 } | |
| 1417 | |
| 1418 return String(); | |
| 1419 } | |
| 1420 | |
| 1421 // | |
| 1422 // Position and size. | 1381 // Position and size. |
| 1423 // | 1382 // |
| 1424 | 1383 |
| 1425 void AXLayoutObject::checkCachedElementRect() const | 1384 void AXLayoutObject::checkCachedElementRect() const |
| 1426 { | 1385 { |
| 1427 if (m_cachedElementRectDirty) | 1386 if (m_cachedElementRectDirty) |
| 1428 return; | 1387 return; |
| 1429 | 1388 |
| 1430 if (!m_layoutObject) | 1389 if (!m_layoutObject) |
| 1431 return; | 1390 return; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1528 | 1487 |
| 1529 LayoutObject* obj = node->layoutObject(); | 1488 LayoutObject* obj = node->layoutObject(); |
| 1530 if (!obj) | 1489 if (!obj) |
| 1531 return 0; | 1490 return 0; |
| 1532 | 1491 |
| 1533 AXObject* result = axObjectCache().getOrCreate(obj); | 1492 AXObject* result = axObjectCache().getOrCreate(obj); |
| 1534 result->updateChildrenIfNecessary(); | 1493 result->updateChildrenIfNecessary(); |
| 1535 | 1494 |
| 1536 // Allow the element to perform any hit-testing it might need to do to reach
non-layout children. | 1495 // Allow the element to perform any hit-testing it might need to do to reach
non-layout children. |
| 1537 result = result->elementAccessibilityHitTest(point); | 1496 result = result->elementAccessibilityHitTest(point); |
| 1538 | |
| 1539 if (result && result->accessibilityIsIgnored()) { | 1497 if (result && result->accessibilityIsIgnored()) { |
| 1540 // If this element is the label of a control, a hit test should return t
he control. | 1498 // If this element is the label of a control, a hit test should return t
he control. |
| 1541 if (result->isAXLayoutObject()) { | 1499 if (result->isAXLayoutObject()) { |
| 1542 AXObject* controlObject = toAXLayoutObject(result)->correspondingCon
trolForLabelElement(); | 1500 AXObject* controlObject = toAXLayoutObject(result)->correspondingCon
trolForLabelElement(); |
| 1543 if (controlObject && !controlObject->deprecatedExposesTitleUIElement
()) | 1501 if (controlObject) { |
| 1544 return controlObject; | 1502 AXNameFrom controlNameFrom; |
| 1503 AXObject::AXObjectVector controlNameObjects; |
| 1504 controlObject->name(controlNameFrom, &controlNameObjects); |
| 1505 if (controlObject && controlNameFrom == AXNameFromRelatedElement
) |
| 1506 return controlObject; |
| 1507 } |
| 1545 } | 1508 } |
| 1546 | 1509 |
| 1547 result = result->parentObjectUnignored(); | 1510 result = result->parentObjectUnignored(); |
| 1548 } | 1511 } |
| 1549 | 1512 |
| 1550 return result; | 1513 return result; |
| 1551 } | 1514 } |
| 1552 | 1515 |
| 1553 AXObject* AXLayoutObject::elementAccessibilityHitTest(const IntPoint& point) con
st | 1516 AXObject* AXLayoutObject::elementAccessibilityHitTest(const IntPoint& point) con
st |
| 1554 { | 1517 { |
| (...skipping 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2590 if (label && label->layoutObject()) { | 2553 if (label && label->layoutObject()) { |
| 2591 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); | 2554 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); |
| 2592 result.unite(labelRect); | 2555 result.unite(labelRect); |
| 2593 } | 2556 } |
| 2594 } | 2557 } |
| 2595 | 2558 |
| 2596 return result; | 2559 return result; |
| 2597 } | 2560 } |
| 2598 | 2561 |
| 2599 } // namespace blink | 2562 } // namespace blink |
| OLD | NEW |