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 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2592 if (label && label->layoutObject()) { | 2555 if (label && label->layoutObject()) { |
2593 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); | 2556 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); |
2594 result.unite(labelRect); | 2557 result.unite(labelRect); |
2595 } | 2558 } |
2596 } | 2559 } |
2597 | 2560 |
2598 return result; | 2561 return result; |
2599 } | 2562 } |
2600 | 2563 |
2601 } // namespace blink | 2564 } // namespace blink |
OLD | NEW |