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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 } | 293 } |
294 | 294 |
295 ignored_reasons->push_back(IgnoredReason(kAXLabelFor, control_object)); | 295 ignored_reasons->push_back(IgnoredReason(kAXLabelFor, control_object)); |
296 } | 296 } |
297 return true; | 297 return true; |
298 } | 298 } |
299 | 299 |
300 Element* element = GetNode()->IsElementNode() ? ToElement(GetNode()) | 300 Element* element = GetNode()->IsElementNode() ? ToElement(GetNode()) |
301 : GetNode()->parentElement(); | 301 : GetNode()->parentElement(); |
302 if (!GetLayoutObject() && (!element || !element->IsInCanvasSubtree()) && | 302 if (!GetLayoutObject() && (!element || !element->IsInCanvasSubtree()) && |
303 !EqualIgnoringASCIICase(GetAttribute(aria_hiddenAttr), "false")) { | 303 !AOMPropertyOrARIAAttributeIsFalse(AOMBooleanProperty::kHidden)) { |
304 if (ignored_reasons) | 304 if (ignored_reasons) |
305 ignored_reasons->push_back(IgnoredReason(kAXNotRendered)); | 305 ignored_reasons->push_back(IgnoredReason(kAXNotRendered)); |
306 return true; | 306 return true; |
307 } | 307 } |
308 | 308 |
309 if (role_ == kUnknownRole) { | 309 if (role_ == kUnknownRole) { |
310 if (ignored_reasons) | 310 if (ignored_reasons) |
311 ignored_reasons->push_back(IgnoredReason(kAXUninteresting)); | 311 ignored_reasons->push_back(IgnoredReason(kAXUninteresting)); |
312 return true; | 312 return true; |
313 } | 313 } |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 } | 818 } |
819 | 819 |
820 static Element* SiblingWithAriaRole(String role, Node* node) { | 820 static Element* SiblingWithAriaRole(String role, Node* node) { |
821 Node* parent = node->parentNode(); | 821 Node* parent = node->parentNode(); |
822 if (!parent) | 822 if (!parent) |
823 return 0; | 823 return 0; |
824 | 824 |
825 for (Element* sibling = ElementTraversal::FirstChild(*parent); sibling; | 825 for (Element* sibling = ElementTraversal::FirstChild(*parent); sibling; |
826 sibling = ElementTraversal::NextSibling(*sibling)) { | 826 sibling = ElementTraversal::NextSibling(*sibling)) { |
827 const AtomicString& sibling_aria_role = | 827 const AtomicString& sibling_aria_role = |
828 AccessibleNode::GetProperty(sibling, AOMStringProperty::kRole); | 828 AccessibleNode::GetPropertyOrARIAAttribute(sibling, |
| 829 AOMStringProperty::kRole); |
829 if (EqualIgnoringASCIICase(sibling_aria_role, role)) | 830 if (EqualIgnoringASCIICase(sibling_aria_role, role)) |
830 return sibling; | 831 return sibling; |
831 } | 832 } |
832 | 833 |
833 return 0; | 834 return 0; |
834 } | 835 } |
835 | 836 |
836 Element* AXNodeObject::MenuItemElementForMenu() const { | 837 Element* AXNodeObject::MenuItemElementForMenu() const { |
837 if (AriaRoleAttribute() != kMenuRole) | 838 if (AriaRoleAttribute() != kMenuRole) |
838 return 0; | 839 return 0; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1039 | 1040 |
1040 bool AXNodeObject::IsMenuButton() const { | 1041 bool AXNodeObject::IsMenuButton() const { |
1041 return RoleValue() == kMenuButtonRole; | 1042 return RoleValue() == kMenuButtonRole; |
1042 } | 1043 } |
1043 | 1044 |
1044 bool AXNodeObject::IsMeter() const { | 1045 bool AXNodeObject::IsMeter() const { |
1045 return RoleValue() == kMeterRole; | 1046 return RoleValue() == kMeterRole; |
1046 } | 1047 } |
1047 | 1048 |
1048 bool AXNodeObject::IsMultiSelectable() const { | 1049 bool AXNodeObject::IsMultiSelectable() const { |
1049 const AtomicString& aria_multi_selectable = | 1050 bool multiselectable = false; |
1050 GetAttribute(aria_multiselectableAttr); | 1051 if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kMultiselectable, |
1051 if (EqualIgnoringASCIICase(aria_multi_selectable, "true")) | 1052 multiselectable)) { |
1052 return true; | 1053 return multiselectable; |
1053 if (EqualIgnoringASCIICase(aria_multi_selectable, "false")) | 1054 } |
1054 return false; | |
1055 | 1055 |
1056 return isHTMLSelectElement(GetNode()) && | 1056 return isHTMLSelectElement(GetNode()) && |
1057 toHTMLSelectElement(*GetNode()).IsMultiple(); | 1057 toHTMLSelectElement(*GetNode()).IsMultiple(); |
1058 } | 1058 } |
1059 | 1059 |
1060 bool AXNodeObject::IsNativeCheckboxOrRadio() const { | 1060 bool AXNodeObject::IsNativeCheckboxOrRadio() const { |
1061 Node* node = this->GetNode(); | 1061 Node* node = this->GetNode(); |
1062 if (!isHTMLInputElement(node)) | 1062 if (!isHTMLInputElement(node)) |
1063 return false; | 1063 return false; |
1064 | 1064 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 | 1177 |
1178 AccessibilityExpanded AXNodeObject::IsExpanded() const { | 1178 AccessibilityExpanded AXNodeObject::IsExpanded() const { |
1179 if (GetNode() && isHTMLSummaryElement(*GetNode())) { | 1179 if (GetNode() && isHTMLSummaryElement(*GetNode())) { |
1180 if (GetNode()->parentNode() && | 1180 if (GetNode()->parentNode() && |
1181 isHTMLDetailsElement(GetNode()->parentNode())) | 1181 isHTMLDetailsElement(GetNode()->parentNode())) |
1182 return ToElement(GetNode()->parentNode())->hasAttribute(openAttr) | 1182 return ToElement(GetNode()->parentNode())->hasAttribute(openAttr) |
1183 ? kExpandedExpanded | 1183 ? kExpandedExpanded |
1184 : kExpandedCollapsed; | 1184 : kExpandedCollapsed; |
1185 } | 1185 } |
1186 | 1186 |
1187 const AtomicString& expanded = GetAttribute(aria_expandedAttr); | 1187 bool expanded = false; |
1188 if (EqualIgnoringASCIICase(expanded, "true")) | 1188 if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kExpanded, expanded)) { |
1189 return kExpandedExpanded; | 1189 return expanded ? kExpandedExpanded : kExpandedCollapsed; |
1190 if (EqualIgnoringASCIICase(expanded, "false")) | 1190 } |
1191 return kExpandedCollapsed; | |
1192 | 1191 |
1193 return kExpandedUndefined; | 1192 return kExpandedUndefined; |
1194 } | 1193 } |
1195 | 1194 |
1196 bool AXNodeObject::IsModal() const { | 1195 bool AXNodeObject::IsModal() const { |
1197 if (RoleValue() != kDialogRole && RoleValue() != kAlertDialogRole) | 1196 if (RoleValue() != kDialogRole && RoleValue() != kAlertDialogRole) |
1198 return false; | 1197 return false; |
1199 | 1198 |
1200 if (HasAttribute(aria_modalAttr)) { | 1199 bool modal = false; |
1201 const AtomicString& modal = GetAttribute(aria_modalAttr); | 1200 if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kModal, modal)) |
1202 if (EqualIgnoringASCIICase(modal, "true")) | 1201 return modal; |
1203 return true; | |
1204 if (EqualIgnoringASCIICase(modal, "false")) | |
1205 return false; | |
1206 } | |
1207 | 1202 |
1208 if (GetNode() && isHTMLDialogElement(*GetNode())) | 1203 if (GetNode() && isHTMLDialogElement(*GetNode())) |
1209 return ToElement(GetNode())->IsInTopLayer(); | 1204 return ToElement(GetNode())->IsInTopLayer(); |
1210 | 1205 |
1211 return false; | 1206 return false; |
1212 } | 1207 } |
1213 | 1208 |
1214 bool AXNodeObject::IsPressed() const { | 1209 bool AXNodeObject::IsPressed() const { |
1215 if (!IsButton()) | 1210 if (!IsButton()) |
1216 return false; | 1211 return false; |
(...skipping 30 matching lines...) Expand all Loading... |
1247 | 1242 |
1248 return !HasEditableStyle(*node); | 1243 return !HasEditableStyle(*node); |
1249 } | 1244 } |
1250 | 1245 |
1251 bool AXNodeObject::IsRequired() const { | 1246 bool AXNodeObject::IsRequired() const { |
1252 Node* n = this->GetNode(); | 1247 Node* n = this->GetNode(); |
1253 if (n && (n->IsElementNode() && ToElement(n)->IsFormControlElement()) && | 1248 if (n && (n->IsElementNode() && ToElement(n)->IsFormControlElement()) && |
1254 HasAttribute(requiredAttr)) | 1249 HasAttribute(requiredAttr)) |
1255 return ToHTMLFormControlElement(n)->IsRequired(); | 1250 return ToHTMLFormControlElement(n)->IsRequired(); |
1256 | 1251 |
1257 if (EqualIgnoringASCIICase(GetAttribute(aria_requiredAttr), "true")) | 1252 if (AOMPropertyOrARIAAttributeIsTrue(AOMBooleanProperty::kRequired)) |
1258 return true; | 1253 return true; |
1259 | 1254 |
1260 return false; | 1255 return false; |
1261 } | 1256 } |
1262 | 1257 |
1263 bool AXNodeObject::CanSetFocusAttribute() const { | 1258 bool AXNodeObject::CanSetFocusAttribute() const { |
1264 Node* node = GetNode(); | 1259 Node* node = GetNode(); |
1265 if (!node) | 1260 if (!node) |
1266 return false; | 1261 return false; |
1267 | 1262 |
1268 if (IsWebArea()) | 1263 if (IsWebArea()) |
1269 return true; | 1264 return true; |
1270 | 1265 |
1271 // Children of elements with an aria-activedescendant attribute should be | 1266 // Children of elements with an aria-activedescendant attribute should be |
1272 // focusable if they have a (non-presentational) ARIA role. | 1267 // focusable if they have a (non-presentational) ARIA role. |
1273 if (!IsPresentational() && AriaRoleAttribute() != kUnknownRole && | 1268 if (!IsPresentational() && AriaRoleAttribute() != kUnknownRole && |
1274 AncestorExposesActiveDescendant()) | 1269 AncestorExposesActiveDescendant()) |
1275 return true; | 1270 return true; |
1276 | 1271 |
1277 // NOTE: It would be more accurate to ask the document whether | 1272 // NOTE: It would be more accurate to ask the document whether |
1278 // setFocusedNode() would do anything. For example, setFocusedNode() will do | 1273 // setFocusedNode() would do anything. For example, setFocusedNode() will do |
1279 // nothing if the current focused node will not relinquish the focus. | 1274 // nothing if the current focused node will not relinquish the focus. |
1280 if (IsDisabledFormControl(node)) | 1275 if (IsDisabledFormControl(node)) |
1281 return false; | 1276 return false; |
1282 | 1277 |
1283 return node->IsElementNode() && ToElement(node)->SupportsFocus(); | 1278 return node->IsElementNode() && ToElement(node)->SupportsFocus(); |
1284 } | 1279 } |
1285 | 1280 |
1286 bool AXNodeObject::CanSetValueAttribute() const { | 1281 bool AXNodeObject::CanSetValueAttribute() const { |
1287 if (EqualIgnoringASCIICase(GetAttribute(aria_readonlyAttr), "true")) | 1282 if (AOMPropertyOrARIAAttributeIsTrue(AOMBooleanProperty::kReadOnly)) |
1288 return false; | 1283 return false; |
1289 | 1284 |
1290 if (IsProgressIndicator() || IsSlider()) | 1285 if (IsProgressIndicator() || IsSlider()) |
1291 return true; | 1286 return true; |
1292 | 1287 |
1293 if (IsTextControl() && !IsNativeTextControl()) | 1288 if (IsTextControl() && !IsNativeTextControl()) |
1294 return true; | 1289 return true; |
1295 | 1290 |
1296 // Any node could be contenteditable, so isReadOnly should be relied upon | 1291 // Any node could be contenteditable, so isReadOnly should be relied upon |
1297 // for this information for all elements. | 1292 // for this information for all elements. |
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1949 } | 1944 } |
1950 for (const auto& owned_child : owned_children) | 1945 for (const auto& owned_child : owned_children) |
1951 children.push_back(owned_child); | 1946 children.push_back(owned_child); |
1952 | 1947 |
1953 for (AXObjectImpl* child : children) { | 1948 for (AXObjectImpl* child : children) { |
1954 // Don't recurse into children that are explicitly marked as aria-hidden. | 1949 // Don't recurse into children that are explicitly marked as aria-hidden. |
1955 // Note that we don't call isInertOrAriaHidden because that would return | 1950 // Note that we don't call isInertOrAriaHidden because that would return |
1956 // true if any ancestor is hidden, but we need to be able to compute the | 1951 // true if any ancestor is hidden, but we need to be able to compute the |
1957 // accessible name of object inside hidden subtrees (for example, if | 1952 // accessible name of object inside hidden subtrees (for example, if |
1958 // aria-labelledby points to an object that's hidden). | 1953 // aria-labelledby points to an object that's hidden). |
1959 if (EqualIgnoringASCIICase(child->GetAttribute(aria_hiddenAttr), "true")) | 1954 if (child->AOMPropertyOrARIAAttributeIsTrue(AOMBooleanProperty::kHidden)) |
1960 continue; | 1955 continue; |
1961 | 1956 |
1962 // If we're going between two layoutObjects that are in separate | 1957 // If we're going between two layoutObjects that are in separate |
1963 // LayoutBoxes, add whitespace if it wasn't there already. Intuitively if | 1958 // LayoutBoxes, add whitespace if it wasn't there already. Intuitively if |
1964 // you have <span>Hello</span><span>World</span>, those are part of the same | 1959 // you have <span>Hello</span><span>World</span>, those are part of the same |
1965 // LayoutBox so we should return "HelloWorld", but given | 1960 // LayoutBox so we should return "HelloWorld", but given |
1966 // <div>Hello</div><div>World</div> the strings are in separate boxes so we | 1961 // <div>Hello</div><div>World</div> the strings are in separate boxes so we |
1967 // should return "Hello World". | 1962 // should return "Hello World". |
1968 if (previous && accumulated_text.length() && | 1963 if (previous && accumulated_text.length() && |
1969 !IsHTMLSpace(accumulated_text[accumulated_text.length() - 1])) { | 1964 !IsHTMLSpace(accumulated_text[accumulated_text.length() - 1])) { |
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2941 if (IsWebArea()) { | 2936 if (IsWebArea()) { |
2942 Document* document = this->GetDocument(); | 2937 Document* document = this->GetDocument(); |
2943 if (document) { | 2938 if (document) { |
2944 name_from = kAXNameFromAttribute; | 2939 name_from = kAXNameFromAttribute; |
2945 if (name_sources) { | 2940 if (name_sources) { |
2946 name_sources->push_back( | 2941 name_sources->push_back( |
2947 NameSource(found_text_alternative, aria_labelAttr)); | 2942 NameSource(found_text_alternative, aria_labelAttr)); |
2948 name_sources->back().type = name_from; | 2943 name_sources->back().type = name_from; |
2949 } | 2944 } |
2950 if (Element* document_element = document->documentElement()) { | 2945 if (Element* document_element = document->documentElement()) { |
2951 const AtomicString& aria_label = AccessibleNode::GetProperty( | 2946 const AtomicString& aria_label = |
2952 document_element, AOMStringProperty::kLabel); | 2947 AccessibleNode::GetPropertyOrARIAAttribute( |
| 2948 document_element, AOMStringProperty::kLabel); |
2953 if (!aria_label.IsEmpty()) { | 2949 if (!aria_label.IsEmpty()) { |
2954 text_alternative = aria_label; | 2950 text_alternative = aria_label; |
2955 | 2951 |
2956 if (name_sources) { | 2952 if (name_sources) { |
2957 NameSource& source = name_sources->back(); | 2953 NameSource& source = name_sources->back(); |
2958 source.text = text_alternative; | 2954 source.text = text_alternative; |
2959 source.attribute_value = aria_label; | 2955 source.attribute_value = aria_label; |
2960 *found_text_alternative = true; | 2956 *found_text_alternative = true; |
2961 } else { | 2957 } else { |
2962 return text_alternative; | 2958 return text_alternative; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3230 return String(); | 3226 return String(); |
3231 return ToTextControlElement(node)->StrippedPlaceholder(); | 3227 return ToTextControlElement(node)->StrippedPlaceholder(); |
3232 } | 3228 } |
3233 | 3229 |
3234 DEFINE_TRACE(AXNodeObject) { | 3230 DEFINE_TRACE(AXNodeObject) { |
3235 visitor->Trace(node_); | 3231 visitor->Trace(node_); |
3236 AXObjectImpl::Trace(visitor); | 3232 AXObjectImpl::Trace(visitor); |
3237 } | 3233 } |
3238 | 3234 |
3239 } // namespace blink | 3235 } // namespace blink |
OLD | NEW |