| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009, 2011 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 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 | 381 |
| 382 ax_object_cache_ = nullptr; | 382 ax_object_cache_ = nullptr; |
| 383 } | 383 } |
| 384 | 384 |
| 385 bool AXObjectImpl::IsDetached() const { | 385 bool AXObjectImpl::IsDetached() const { |
| 386 return !ax_object_cache_; | 386 return !ax_object_cache_; |
| 387 } | 387 } |
| 388 | 388 |
| 389 const AtomicString& AXObjectImpl::GetAOMPropertyOrARIAAttribute( | 389 const AtomicString& AXObjectImpl::GetAOMPropertyOrARIAAttribute( |
| 390 AOMStringProperty property) const { | 390 AOMStringProperty property) const { |
| 391 Node* node = this->GetNode(); | 391 if (Element* element = this->GetElement()) |
| 392 if (!node || !node->IsElementNode()) | 392 return AccessibleNode::GetPropertyOrARIAAttribute(element, property); |
| 393 return g_null_atom; | 393 return g_null_atom; |
| 394 } |
| 394 | 395 |
| 395 return AccessibleNode::GetPropertyOrARIAAttribute(ToElement(node), property); | 396 bool AXObjectImpl::HasAOMPropertyOrARIAAttribute(AOMBooleanProperty property, |
| 397 bool& result) const { |
| 398 Element* element = this->GetElement(); |
| 399 if (!element) |
| 400 return false; |
| 401 |
| 402 bool is_null = true; |
| 403 result = |
| 404 AccessibleNode::GetPropertyOrARIAAttribute(element, property, is_null); |
| 405 return !is_null; |
| 406 } |
| 407 |
| 408 bool AXObjectImpl::AOMPropertyOrARIAAttributeIsTrue( |
| 409 AOMBooleanProperty property) const { |
| 410 bool result; |
| 411 if (HasAOMPropertyOrARIAAttribute(property, result)) |
| 412 return result; |
| 413 return false; |
| 414 } |
| 415 |
| 416 bool AXObjectImpl::AOMPropertyOrARIAAttributeIsFalse( |
| 417 AOMBooleanProperty property) const { |
| 418 bool result; |
| 419 if (HasAOMPropertyOrARIAAttribute(property, result)) |
| 420 return !result; |
| 421 return false; |
| 396 } | 422 } |
| 397 | 423 |
| 398 bool AXObjectImpl::IsARIATextControl() const { | 424 bool AXObjectImpl::IsARIATextControl() const { |
| 399 return AriaRoleAttribute() == kTextFieldRole || | 425 return AriaRoleAttribute() == kTextFieldRole || |
| 400 AriaRoleAttribute() == kSearchBoxRole || | 426 AriaRoleAttribute() == kSearchBoxRole || |
| 401 AriaRoleAttribute() == kComboBoxRole; | 427 AriaRoleAttribute() == kComboBoxRole; |
| 402 } | 428 } |
| 403 | 429 |
| 404 bool AXObjectImpl::IsButton() const { | 430 bool AXObjectImpl::IsButton() const { |
| 405 AccessibilityRole role = RoleValue(); | 431 AccessibilityRole role = RoleValue(); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 | 690 |
| 665 return parent->LeafNodeAncestor(); | 691 return parent->LeafNodeAncestor(); |
| 666 } | 692 } |
| 667 | 693 |
| 668 return 0; | 694 return 0; |
| 669 } | 695 } |
| 670 | 696 |
| 671 const AXObjectImpl* AXObjectImpl::AriaHiddenRoot() const { | 697 const AXObjectImpl* AXObjectImpl::AriaHiddenRoot() const { |
| 672 for (const AXObjectImpl* object = this; object; | 698 for (const AXObjectImpl* object = this; object; |
| 673 object = object->ParentObject()) { | 699 object = object->ParentObject()) { |
| 674 if (EqualIgnoringASCIICase(object->GetAttribute(aria_hiddenAttr), "true")) | 700 if (object->AOMPropertyOrARIAAttributeIsTrue(AOMBooleanProperty::kHidden)) |
| 675 return object; | 701 return object; |
| 676 } | 702 } |
| 677 | 703 |
| 678 return 0; | 704 return 0; |
| 679 } | 705 } |
| 680 | 706 |
| 681 bool AXObjectImpl::IsDescendantOfDisabledNode() const { | 707 bool AXObjectImpl::IsDescendantOfDisabledNode() const { |
| 682 UpdateCachedAttributeValuesIfNeeded(); | 708 UpdateCachedAttributeValuesIfNeeded(); |
| 683 return cached_is_descendant_of_disabled_node_; | 709 return cached_is_descendant_of_disabled_node_; |
| 684 } | 710 } |
| 685 | 711 |
| 686 const AXObjectImpl* AXObjectImpl::DisabledAncestor() const { | 712 const AXObjectImpl* AXObjectImpl::DisabledAncestor() const { |
| 687 const AtomicString& disabled = GetAttribute(aria_disabledAttr); | 713 bool disabled = false; |
| 688 if (EqualIgnoringASCIICase(disabled, "true")) | 714 if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kDisabled, disabled)) { |
| 689 return this; | 715 if (disabled) |
| 690 if (EqualIgnoringASCIICase(disabled, "false")) | 716 return this; |
| 691 return 0; | 717 return nullptr; |
| 718 } |
| 692 | 719 |
| 693 if (AXObjectImpl* parent = ParentObject()) | 720 if (AXObjectImpl* parent = ParentObject()) |
| 694 return parent->DisabledAncestor(); | 721 return parent->DisabledAncestor(); |
| 695 | 722 |
| 696 return 0; | 723 return nullptr; |
| 697 } | 724 } |
| 698 | 725 |
| 699 bool AXObjectImpl::LastKnownIsIgnoredValue() { | 726 bool AXObjectImpl::LastKnownIsIgnoredValue() { |
| 700 if (last_known_is_ignored_value_ == kDefaultBehavior) { | 727 if (last_known_is_ignored_value_ == kDefaultBehavior) { |
| 701 last_known_is_ignored_value_ = | 728 last_known_is_ignored_value_ = |
| 702 AccessibilityIsIgnored() ? kIgnoreObject : kIncludeObject; | 729 AccessibilityIsIgnored() ? kIgnoreObject : kIncludeObject; |
| 703 } | 730 } |
| 704 | 731 |
| 705 return last_known_is_ignored_value_ == kIgnoreObject; | 732 return last_known_is_ignored_value_ == kIgnoreObject; |
| 706 } | 733 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 AXObjectSet& visited) { | 820 AXObjectSet& visited) { |
| 794 if (visited.Contains(&ax_obj) && !in_aria_labelled_by_traversal) | 821 if (visited.Contains(&ax_obj) && !in_aria_labelled_by_traversal) |
| 795 return String(); | 822 return String(); |
| 796 | 823 |
| 797 AXNameFrom tmp_name_from; | 824 AXNameFrom tmp_name_from; |
| 798 return ax_obj.TextAlternative(true, in_aria_labelled_by_traversal, visited, | 825 return ax_obj.TextAlternative(true, in_aria_labelled_by_traversal, visited, |
| 799 tmp_name_from, nullptr, nullptr); | 826 tmp_name_from, nullptr, nullptr); |
| 800 } | 827 } |
| 801 | 828 |
| 802 bool AXObjectImpl::IsHiddenForTextAlternativeCalculation() const { | 829 bool AXObjectImpl::IsHiddenForTextAlternativeCalculation() const { |
| 803 if (EqualIgnoringASCIICase(GetAttribute(aria_hiddenAttr), "false")) | 830 if (AOMPropertyOrARIAAttributeIsFalse(AOMBooleanProperty::kHidden)) |
| 804 return false; | 831 return false; |
| 805 | 832 |
| 806 if (GetLayoutObject()) | 833 if (GetLayoutObject()) |
| 807 return GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible; | 834 return GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible; |
| 808 | 835 |
| 809 // This is an obscure corner case: if a node has no LayoutObject, that means | 836 // This is an obscure corner case: if a node has no LayoutObject, that means |
| 810 // it's not rendered, but we still may be exploring it as part of a text | 837 // it's not rendered, but we still may be exploring it as part of a text |
| 811 // alternative calculation, for example if it was explicitly referenced by | 838 // alternative calculation, for example if it was explicitly referenced by |
| 812 // aria-labelledby. So we need to explicitly call the style resolver to check | 839 // aria-labelledby. So we need to explicitly call the style resolver to check |
| 813 // whether it's invisible or display:none, rather than relying on the style | 840 // whether it's invisible or display:none, rather than relying on the style |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 | 1067 |
| 1041 if (isHTMLTextAreaElement(*node)) | 1068 if (isHTMLTextAreaElement(*node)) |
| 1042 return true; | 1069 return true; |
| 1043 | 1070 |
| 1044 if (HasEditableStyle(*node)) | 1071 if (HasEditableStyle(*node)) |
| 1045 return true; | 1072 return true; |
| 1046 | 1073 |
| 1047 if (!IsNativeTextControl() && !IsNonNativeTextControl()) | 1074 if (!IsNativeTextControl() && !IsNonNativeTextControl()) |
| 1048 return false; | 1075 return false; |
| 1049 | 1076 |
| 1050 return EqualIgnoringASCIICase(GetAttribute(aria_multilineAttr), "true"); | 1077 return AOMPropertyOrARIAAttributeIsTrue(AOMBooleanProperty::kMultiline); |
| 1051 } | 1078 } |
| 1052 | 1079 |
| 1053 bool AXObjectImpl::AriaPressedIsPresent() const { | 1080 bool AXObjectImpl::AriaPressedIsPresent() const { |
| 1054 return !GetAttribute(aria_pressedAttr).IsEmpty(); | 1081 return !GetAttribute(aria_pressedAttr).IsEmpty(); |
| 1055 } | 1082 } |
| 1056 | 1083 |
| 1057 bool AXObjectImpl::SupportsActiveDescendant() const { | 1084 bool AXObjectImpl::SupportsActiveDescendant() const { |
| 1058 // According to the ARIA Spec, all ARIA composite widgets, ARIA text boxes | 1085 // According to the ARIA Spec, all ARIA composite widgets, ARIA text boxes |
| 1059 // and ARIA groups should be able to expose an active descendant. | 1086 // and ARIA groups should be able to expose an active descendant. |
| 1060 // Implicitly, <input> and <textarea> elements should also have this ability. | 1087 // Implicitly, <input> and <textarea> elements should also have this ability. |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 | 1245 |
| 1219 void AXObjectImpl::ClearChildren() { | 1246 void AXObjectImpl::ClearChildren() { |
| 1220 // Detach all weak pointers from objects to their parents. | 1247 // Detach all weak pointers from objects to their parents. |
| 1221 for (const auto& child : children_) | 1248 for (const auto& child : children_) |
| 1222 child->DetachFromParent(); | 1249 child->DetachFromParent(); |
| 1223 | 1250 |
| 1224 children_.clear(); | 1251 children_.clear(); |
| 1225 have_children_ = false; | 1252 have_children_ = false; |
| 1226 } | 1253 } |
| 1227 | 1254 |
| 1255 Element* AXObjectImpl::GetElement() const { |
| 1256 Node* node = GetNode(); |
| 1257 return node && node->IsElementNode() ? ToElement(node) : nullptr; |
| 1258 } |
| 1259 |
| 1228 Document* AXObjectImpl::GetDocument() const { | 1260 Document* AXObjectImpl::GetDocument() const { |
| 1229 FrameView* frame_view = DocumentFrameView(); | 1261 FrameView* frame_view = DocumentFrameView(); |
| 1230 if (!frame_view) | 1262 if (!frame_view) |
| 1231 return 0; | 1263 return 0; |
| 1232 | 1264 |
| 1233 return frame_view->GetFrame().GetDocument(); | 1265 return frame_view->GetFrame().GetDocument(); |
| 1234 } | 1266 } |
| 1235 | 1267 |
| 1236 FrameView* AXObjectImpl::DocumentFrameView() const { | 1268 FrameView* AXObjectImpl::DocumentFrameView() const { |
| 1237 const AXObjectImpl* object = this; | 1269 const AXObjectImpl* object = this; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1257 Document* doc = GetDocument(); | 1289 Document* doc = GetDocument(); |
| 1258 if (doc) | 1290 if (doc) |
| 1259 return doc->ContentLanguage(); | 1291 return doc->ContentLanguage(); |
| 1260 return g_null_atom; | 1292 return g_null_atom; |
| 1261 } | 1293 } |
| 1262 | 1294 |
| 1263 return parent->Language(); | 1295 return parent->Language(); |
| 1264 } | 1296 } |
| 1265 | 1297 |
| 1266 bool AXObjectImpl::HasAttribute(const QualifiedName& attribute) const { | 1298 bool AXObjectImpl::HasAttribute(const QualifiedName& attribute) const { |
| 1267 Node* element_node = GetNode(); | 1299 if (Element* element = GetElement()) |
| 1268 if (!element_node) | 1300 return element->FastHasAttribute(attribute); |
| 1269 return false; | 1301 return false; |
| 1270 | |
| 1271 if (!element_node->IsElementNode()) | |
| 1272 return false; | |
| 1273 | |
| 1274 Element* element = ToElement(element_node); | |
| 1275 return element->FastHasAttribute(attribute); | |
| 1276 } | 1302 } |
| 1277 | 1303 |
| 1278 const AtomicString& AXObjectImpl::GetAttribute( | 1304 const AtomicString& AXObjectImpl::GetAttribute( |
| 1279 const QualifiedName& attribute) const { | 1305 const QualifiedName& attribute) const { |
| 1280 Node* element_node = GetNode(); | 1306 if (Element* element = GetElement()) |
| 1281 if (!element_node) | 1307 return element->FastGetAttribute(attribute); |
| 1282 return g_null_atom; | 1308 return g_null_atom; |
| 1283 | |
| 1284 if (!element_node->IsElementNode()) | |
| 1285 return g_null_atom; | |
| 1286 | |
| 1287 Element* element = ToElement(element_node); | |
| 1288 return element->FastGetAttribute(attribute); | |
| 1289 } | 1309 } |
| 1290 | 1310 |
| 1291 // | 1311 // |
| 1292 // Scrollable containers. | 1312 // Scrollable containers. |
| 1293 // | 1313 // |
| 1294 | 1314 |
| 1295 bool AXObjectImpl::IsScrollableContainer() const { | 1315 bool AXObjectImpl::IsScrollableContainer() const { |
| 1296 return !!GetScrollableAreaIfScrollable(); | 1316 return !!GetScrollableAreaIfScrollable(); |
| 1297 } | 1317 } |
| 1298 | 1318 |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 case kTreeItemRole: | 1853 case kTreeItemRole: |
| 1834 case kUserInterfaceTooltipRole: | 1854 case kUserInterfaceTooltipRole: |
| 1835 return true; | 1855 return true; |
| 1836 case kRowRole: { | 1856 case kRowRole: { |
| 1837 // Spec says we should always expose the name on rows, | 1857 // Spec says we should always expose the name on rows, |
| 1838 // but for performance reasons we only do it | 1858 // but for performance reasons we only do it |
| 1839 // if the row might receive focus | 1859 // if the row might receive focus |
| 1840 if (AncestorExposesActiveDescendant()) { | 1860 if (AncestorExposesActiveDescendant()) { |
| 1841 return true; | 1861 return true; |
| 1842 } | 1862 } |
| 1843 const Node* node = this->GetNode(); | 1863 const Element* element = this->GetElement(); |
| 1844 return node && node->IsElementNode() && ToElement(node)->IsFocusable(); | 1864 return element && element->IsFocusable(); |
| 1845 } | 1865 } |
| 1846 default: | 1866 default: |
| 1847 return false; | 1867 return false; |
| 1848 } | 1868 } |
| 1849 } | 1869 } |
| 1850 | 1870 |
| 1851 AccessibilityRole AXObjectImpl::ButtonRoleType() const { | 1871 AccessibilityRole AXObjectImpl::ButtonRoleType() const { |
| 1852 // If aria-pressed is present, then it should be exposed as a toggle button. | 1872 // If aria-pressed is present, then it should be exposed as a toggle button. |
| 1853 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed | 1873 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed |
| 1854 if (AriaPressedIsPresent()) | 1874 if (AriaPressedIsPresent()) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1875 } | 1895 } |
| 1876 | 1896 |
| 1877 DEFINE_TRACE(AXObjectImpl) { | 1897 DEFINE_TRACE(AXObjectImpl) { |
| 1878 visitor->Trace(children_); | 1898 visitor->Trace(children_); |
| 1879 visitor->Trace(parent_); | 1899 visitor->Trace(parent_); |
| 1880 visitor->Trace(cached_live_region_root_); | 1900 visitor->Trace(cached_live_region_root_); |
| 1881 visitor->Trace(ax_object_cache_); | 1901 visitor->Trace(ax_object_cache_); |
| 1882 } | 1902 } |
| 1883 | 1903 |
| 1884 } // namespace blink | 1904 } // namespace blink |
| OLD | NEW |