| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2014, Google Inc. All rights reserved. | 2 * Copyright (C) 2014, 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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 m_hasBeenDisposed = true; | 119 m_hasBeenDisposed = true; |
| 120 #endif | 120 #endif |
| 121 } | 121 } |
| 122 | 122 |
| 123 AXObject* AXObjectCacheImpl::root() { | 123 AXObject* AXObjectCacheImpl::root() { |
| 124 return getOrCreate(m_document); | 124 return getOrCreate(m_document); |
| 125 } | 125 } |
| 126 | 126 |
| 127 AXObject* AXObjectCacheImpl::focusedImageMapUIElement( | 127 AXObject* AXObjectCacheImpl::focusedImageMapUIElement( |
| 128 HTMLAreaElement* areaElement) { | 128 HTMLAreaElement* areaElement) { |
| 129 // Find the corresponding accessibility object for the HTMLAreaElement. This s
hould be | 129 // Find the corresponding accessibility object for the HTMLAreaElement. This |
| 130 // in the list of children for its corresponding image. | 130 // should be in the list of children for its corresponding image. |
| 131 if (!areaElement) | 131 if (!areaElement) |
| 132 return 0; | 132 return 0; |
| 133 | 133 |
| 134 HTMLImageElement* imageElement = areaElement->imageElement(); | 134 HTMLImageElement* imageElement = areaElement->imageElement(); |
| 135 if (!imageElement) | 135 if (!imageElement) |
| 136 return 0; | 136 return 0; |
| 137 | 137 |
| 138 AXObject* axLayoutImage = getOrCreate(imageElement); | 138 AXObject* axLayoutImage = getOrCreate(imageElement); |
| 139 if (!axLayoutImage) | 139 if (!axLayoutImage) |
| 140 return 0; | 140 return 0; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 if (Element* focusedElementInPopup = | 173 if (Element* focusedElementInPopup = |
| 174 axPopup->getDocument()->focusedElement()) | 174 axPopup->getDocument()->focusedElement()) |
| 175 focusedNode = focusedElementInPopup; | 175 focusedNode = focusedElementInPopup; |
| 176 } | 176 } |
| 177 } | 177 } |
| 178 | 178 |
| 179 AXObject* obj = getOrCreate(focusedNode); | 179 AXObject* obj = getOrCreate(focusedNode); |
| 180 if (!obj) | 180 if (!obj) |
| 181 return nullptr; | 181 return nullptr; |
| 182 | 182 |
| 183 // the HTML element, for example, is focusable but has an AX object that is ig
nored | 183 // the HTML element, for example, is focusable but has an AX object that is |
| 184 // ignored |
| 184 if (obj->accessibilityIsIgnored()) | 185 if (obj->accessibilityIsIgnored()) |
| 185 obj = obj->parentObjectUnignored(); | 186 obj = obj->parentObjectUnignored(); |
| 186 | 187 |
| 187 return obj; | 188 return obj; |
| 188 } | 189 } |
| 189 | 190 |
| 190 AXObject* AXObjectCacheImpl::get(LayoutObject* layoutObject) { | 191 AXObject* AXObjectCacheImpl::get(LayoutObject* layoutObject) { |
| 191 if (!layoutObject) | 192 if (!layoutObject) |
| 192 return 0; | 193 return 0; |
| 193 | 194 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 208 if (!select) | 209 if (!select) |
| 209 return false; | 210 return false; |
| 210 LayoutObject* layoutObject = select->layoutObject(); | 211 LayoutObject* layoutObject = select->layoutObject(); |
| 211 return layoutObject && layoutObject->isMenuList(); | 212 return layoutObject && layoutObject->isMenuList(); |
| 212 } | 213 } |
| 213 | 214 |
| 214 AXObject* AXObjectCacheImpl::get(Node* node) { | 215 AXObject* AXObjectCacheImpl::get(Node* node) { |
| 215 if (!node) | 216 if (!node) |
| 216 return 0; | 217 return 0; |
| 217 | 218 |
| 218 // Menu list option and HTML area elements are indexed by DOM node, never by l
ayout object. | 219 // Menu list option and HTML area elements are indexed by DOM node, never by |
| 220 // layout object. |
| 219 LayoutObject* layoutObject = node->layoutObject(); | 221 LayoutObject* layoutObject = node->layoutObject(); |
| 220 if (isMenuListOption(node) || isHTMLAreaElement(node)) | 222 if (isMenuListOption(node) || isHTMLAreaElement(node)) |
| 221 layoutObject = nullptr; | 223 layoutObject = nullptr; |
| 222 | 224 |
| 223 AXID layoutID = layoutObject ? m_layoutObjectMapping.get(layoutObject) : 0; | 225 AXID layoutID = layoutObject ? m_layoutObjectMapping.get(layoutObject) : 0; |
| 224 ASSERT(!HashTraits<AXID>::isDeletedValue(layoutID)); | 226 ASSERT(!HashTraits<AXID>::isDeletedValue(layoutID)); |
| 225 | 227 |
| 226 AXID nodeID = m_nodeObjectMapping.get(node); | 228 AXID nodeID = m_nodeObjectMapping.get(node); |
| 227 ASSERT(!HashTraits<AXID>::isDeletedValue(nodeID)); | 229 ASSERT(!HashTraits<AXID>::isDeletedValue(nodeID)); |
| 228 | 230 |
| 229 if (layoutObject && nodeID && !layoutID) { | 231 if (layoutObject && nodeID && !layoutID) { |
| 230 // This can happen if an AXNodeObject is created for a node that's not | 232 // This can happen if an AXNodeObject is created for a node that's not |
| 231 // laid out, but later something changes and it gets a layoutObject (like if
it's | 233 // laid out, but later something changes and it gets a layoutObject (like if |
| 232 // reparented). | 234 // it's reparented). |
| 233 remove(nodeID); | 235 remove(nodeID); |
| 234 return 0; | 236 return 0; |
| 235 } | 237 } |
| 236 | 238 |
| 237 if (layoutID) | 239 if (layoutID) |
| 238 return m_objects.get(layoutID); | 240 return m_objects.get(layoutID); |
| 239 | 241 |
| 240 if (!nodeID) | 242 if (!nodeID) |
| 241 return 0; | 243 return 0; |
| 242 | 244 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 return AXInlineTextBox::create(inlineTextBox, *this); | 343 return AXInlineTextBox::create(inlineTextBox, *this); |
| 342 } | 344 } |
| 343 | 345 |
| 344 AXObject* AXObjectCacheImpl::getOrCreate(Node* node) { | 346 AXObject* AXObjectCacheImpl::getOrCreate(Node* node) { |
| 345 if (!node) | 347 if (!node) |
| 346 return 0; | 348 return 0; |
| 347 | 349 |
| 348 if (AXObject* obj = get(node)) | 350 if (AXObject* obj = get(node)) |
| 349 return obj; | 351 return obj; |
| 350 | 352 |
| 351 // If the node has a layout object, prefer using that as the primary key for t
he AXObject, | 353 // If the node has a layout object, prefer using that as the primary key for |
| 352 // with the exception of an HTMLAreaElement, which is created based on its nod
e. | 354 // the AXObject, with the exception of an HTMLAreaElement, which is created |
| 355 // based on its node. |
| 353 if (node->layoutObject() && !isHTMLAreaElement(node)) | 356 if (node->layoutObject() && !isHTMLAreaElement(node)) |
| 354 return getOrCreate(node->layoutObject()); | 357 return getOrCreate(node->layoutObject()); |
| 355 | 358 |
| 356 if (!node->parentElement()) | 359 if (!node->parentElement()) |
| 357 return 0; | 360 return 0; |
| 358 | 361 |
| 359 if (isHTMLHeadElement(node)) | 362 if (isHTMLHeadElement(node)) |
| 360 return 0; | 363 return 0; |
| 361 | 364 |
| 362 AXObject* newObj = createFromNode(node); | 365 AXObject* newObj = createFromNode(node); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 for (size_t i = 0; i < childAXIDs.size(); ++i) | 568 for (size_t i = 0; i < childAXIDs.size(); ++i) |
| 566 m_ariaOwnedChildToOwnerMapping.remove(childAXIDs[i]); | 569 m_ariaOwnedChildToOwnerMapping.remove(childAXIDs[i]); |
| 567 m_ariaOwnerToChildrenMapping.remove(objID); | 570 m_ariaOwnerToChildrenMapping.remove(objID); |
| 568 } | 571 } |
| 569 m_ariaOwnedChildToOwnerMapping.remove(objID); | 572 m_ariaOwnedChildToOwnerMapping.remove(objID); |
| 570 m_ariaOwnedChildToRealParentMapping.remove(objID); | 573 m_ariaOwnedChildToRealParentMapping.remove(objID); |
| 571 m_ariaOwnerToIdsMapping.remove(objID); | 574 m_ariaOwnerToIdsMapping.remove(objID); |
| 572 } | 575 } |
| 573 | 576 |
| 574 void AXObjectCacheImpl::selectionChanged(Node* node) { | 577 void AXObjectCacheImpl::selectionChanged(Node* node) { |
| 575 // Find the nearest ancestor that already has an accessibility object, since w
e | 578 // Find the nearest ancestor that already has an accessibility object, since |
| 576 // might be in the middle of a layout. | 579 // we might be in the middle of a layout. |
| 577 while (node) { | 580 while (node) { |
| 578 if (AXObject* obj = get(node)) { | 581 if (AXObject* obj = get(node)) { |
| 579 obj->selectionChanged(); | 582 obj->selectionChanged(); |
| 580 return; | 583 return; |
| 581 } | 584 } |
| 582 node = node->parentNode(); | 585 node = node->parentNode(); |
| 583 } | 586 } |
| 584 } | 587 } |
| 585 | 588 |
| 586 void AXObjectCacheImpl::textChanged(Node* node) { | 589 void AXObjectCacheImpl::textChanged(Node* node) { |
| 587 textChanged(getOrCreate(node)); | 590 textChanged(getOrCreate(node)); |
| 588 } | 591 } |
| 589 | 592 |
| 590 void AXObjectCacheImpl::textChanged(LayoutObject* layoutObject) { | 593 void AXObjectCacheImpl::textChanged(LayoutObject* layoutObject) { |
| 591 textChanged(getOrCreate(layoutObject)); | 594 textChanged(getOrCreate(layoutObject)); |
| 592 } | 595 } |
| 593 | 596 |
| 594 void AXObjectCacheImpl::textChanged(AXObject* obj) { | 597 void AXObjectCacheImpl::textChanged(AXObject* obj) { |
| 595 if (!obj) | 598 if (!obj) |
| 596 return; | 599 return; |
| 597 | 600 |
| 598 bool parentAlreadyExists = obj->parentObjectIfExists(); | 601 bool parentAlreadyExists = obj->parentObjectIfExists(); |
| 599 obj->textChanged(); | 602 obj->textChanged(); |
| 600 postNotification(obj, AXObjectCacheImpl::AXTextChanged); | 603 postNotification(obj, AXObjectCacheImpl::AXTextChanged); |
| 601 if (parentAlreadyExists) | 604 if (parentAlreadyExists) |
| 602 obj->notifyIfIgnoredValueChanged(); | 605 obj->notifyIfIgnoredValueChanged(); |
| 603 } | 606 } |
| 604 | 607 |
| 605 void AXObjectCacheImpl::updateCacheAfterNodeIsAttached(Node* node) { | 608 void AXObjectCacheImpl::updateCacheAfterNodeIsAttached(Node* node) { |
| 606 // Calling get() will update the AX object if we had an AXNodeObject but now w
e need | 609 // Calling get() will update the AX object if we had an AXNodeObject but now |
| 607 // an AXLayoutObject, because it was reparented to a location outside of a can
vas. | 610 // we need an AXLayoutObject, because it was reparented to a location outside |
| 611 // of a canvas. |
| 608 get(node); | 612 get(node); |
| 609 if (node->isElementNode()) | 613 if (node->isElementNode()) |
| 610 updateTreeIfElementIdIsAriaOwned(toElement(node)); | 614 updateTreeIfElementIdIsAriaOwned(toElement(node)); |
| 611 } | 615 } |
| 612 | 616 |
| 613 void AXObjectCacheImpl::childrenChanged(Node* node) { | 617 void AXObjectCacheImpl::childrenChanged(Node* node) { |
| 614 childrenChanged(get(node)); | 618 childrenChanged(get(node)); |
| 615 } | 619 } |
| 616 | 620 |
| 617 void AXObjectCacheImpl::childrenChanged(LayoutObject* layoutObject) { | 621 void AXObjectCacheImpl::childrenChanged(LayoutObject* layoutObject) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 AXObject* AXObjectCacheImpl::getAriaOwnedParent(const AXObject* child) const { | 700 AXObject* AXObjectCacheImpl::getAriaOwnedParent(const AXObject* child) const { |
| 697 return objectFromAXID( | 701 return objectFromAXID( |
| 698 m_ariaOwnedChildToOwnerMapping.get(child->axObjectID())); | 702 m_ariaOwnedChildToOwnerMapping.get(child->axObjectID())); |
| 699 } | 703 } |
| 700 | 704 |
| 701 void AXObjectCacheImpl::updateAriaOwns( | 705 void AXObjectCacheImpl::updateAriaOwns( |
| 702 const AXObject* owner, | 706 const AXObject* owner, |
| 703 const Vector<String>& idVector, | 707 const Vector<String>& idVector, |
| 704 HeapVector<Member<AXObject>>& ownedChildren) { | 708 HeapVector<Member<AXObject>>& ownedChildren) { |
| 705 // | 709 // |
| 706 // Update the map from the AXID of this element to the ids of the owned childr
en, | 710 // Update the map from the AXID of this element to the ids of the owned |
| 707 // and the reverse map from ids to possible AXID owners. | 711 // children, and the reverse map from ids to possible AXID owners. |
| 708 // | 712 // |
| 709 | 713 |
| 710 HashSet<String> currentIds = m_ariaOwnerToIdsMapping.get(owner->axObjectID()); | 714 HashSet<String> currentIds = m_ariaOwnerToIdsMapping.get(owner->axObjectID()); |
| 711 HashSet<String> newIds; | 715 HashSet<String> newIds; |
| 712 bool idsChanged = false; | 716 bool idsChanged = false; |
| 713 for (const String& id : idVector) { | 717 for (const String& id : idVector) { |
| 714 newIds.add(id); | 718 newIds.add(id); |
| 715 if (!currentIds.contains(id)) { | 719 if (!currentIds.contains(id)) { |
| 716 idsChanged = true; | 720 idsChanged = true; |
| 717 HashSet<AXID>* owners = m_idToAriaOwnersMapping.get(id); | 721 HashSet<AXID>* owners = m_idToAriaOwnersMapping.get(id); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 748 for (const String& idName : idVector) { | 752 for (const String& idName : idVector) { |
| 749 Element* element = scope.getElementById(AtomicString(idName)); | 753 Element* element = scope.getElementById(AtomicString(idName)); |
| 750 if (!element) | 754 if (!element) |
| 751 continue; | 755 continue; |
| 752 | 756 |
| 753 AXObject* child = getOrCreate(element); | 757 AXObject* child = getOrCreate(element); |
| 754 if (!child) | 758 if (!child) |
| 755 continue; | 759 continue; |
| 756 | 760 |
| 757 // If this child is already aria-owned by a different owner, continue. | 761 // If this child is already aria-owned by a different owner, continue. |
| 758 // It's an author error if this happens and we don't worry about which of th
e | 762 // It's an author error if this happens and we don't worry about which of |
| 759 // two owners wins ownership of the child, as long as only one of them does. | 763 // the two owners wins ownership of the child, as long as only one of them |
| 764 // does. |
| 760 if (isAriaOwned(child) && getAriaOwnedParent(child) != owner) | 765 if (isAriaOwned(child) && getAriaOwnedParent(child) != owner) |
| 761 continue; | 766 continue; |
| 762 | 767 |
| 763 // You can't own yourself! | 768 // You can't own yourself! |
| 764 if (child == owner) | 769 if (child == owner) |
| 765 continue; | 770 continue; |
| 766 | 771 |
| 767 // Walk up the parents of the owner object, make sure that this child doesn'
t appear | 772 // Walk up the parents of the owner object, make sure that this child |
| 768 // there, as that would create a cycle. | 773 // doesn't appear there, as that would create a cycle. |
| 769 bool foundCycle = false; | 774 bool foundCycle = false; |
| 770 for (AXObject* parent = owner->parentObject(); parent && !foundCycle; | 775 for (AXObject* parent = owner->parentObject(); parent && !foundCycle; |
| 771 parent = parent->parentObject()) { | 776 parent = parent->parentObject()) { |
| 772 if (parent == child) | 777 if (parent == child) |
| 773 foundCycle = true; | 778 foundCycle = true; |
| 774 } | 779 } |
| 775 if (foundCycle) | 780 if (foundCycle) |
| 776 continue; | 781 continue; |
| 777 | 782 |
| 778 newChildAXIDs.append(child->axObjectID()); | 783 newChildAXIDs.append(child->axObjectID()); |
| 779 ownedChildren.append(child); | 784 ownedChildren.append(child); |
| 780 } | 785 } |
| 781 | 786 |
| 782 // Compare this to the current list of owned children, and exit early if there
are no changes. | 787 // Compare this to the current list of owned children, and exit early if there |
| 788 // are no changes. |
| 783 Vector<AXID> currentChildAXIDs = | 789 Vector<AXID> currentChildAXIDs = |
| 784 m_ariaOwnerToChildrenMapping.get(owner->axObjectID()); | 790 m_ariaOwnerToChildrenMapping.get(owner->axObjectID()); |
| 785 bool same = true; | 791 bool same = true; |
| 786 if (currentChildAXIDs.size() != newChildAXIDs.size()) { | 792 if (currentChildAXIDs.size() != newChildAXIDs.size()) { |
| 787 same = false; | 793 same = false; |
| 788 } else { | 794 } else { |
| 789 for (size_t i = 0; i < currentChildAXIDs.size() && same; ++i) { | 795 for (size_t i = 0; i < currentChildAXIDs.size() && same; ++i) { |
| 790 if (currentChildAXIDs[i] != newChildAXIDs[i]) | 796 if (currentChildAXIDs[i] != newChildAXIDs[i]) |
| 791 same = false; | 797 same = false; |
| 792 } | 798 } |
| 793 } | 799 } |
| 794 if (same) | 800 if (same) |
| 795 return; | 801 return; |
| 796 | 802 |
| 797 // The list of owned children has changed. Even if they were just reordered, t
o be safe | 803 // The list of owned children has changed. Even if they were just reordered, |
| 798 // and handle all cases we remove all of the current owned children and add th
e new list | 804 // to be safe and handle all cases we remove all of the current owned children |
| 799 // of owned children. | 805 // and add the new list of owned children. |
| 800 for (size_t i = 0; i < currentChildAXIDs.size(); ++i) { | 806 for (size_t i = 0; i < currentChildAXIDs.size(); ++i) { |
| 801 // Find the AXObject for the child that this owner no longer owns. | 807 // Find the AXObject for the child that this owner no longer owns. |
| 802 AXID removedChildID = currentChildAXIDs[i]; | 808 AXID removedChildID = currentChildAXIDs[i]; |
| 803 AXObject* removedChild = objectFromAXID(removedChildID); | 809 AXObject* removedChild = objectFromAXID(removedChildID); |
| 804 | 810 |
| 805 // It's possible that this child has already been owned by some other owner, | 811 // It's possible that this child has already been owned by some other owner, |
| 806 // in which case we don't need to do anything. | 812 // in which case we don't need to do anything. |
| 807 if (removedChild && getAriaOwnedParent(removedChild) != owner) | 813 if (removedChild && getAriaOwnedParent(removedChild) != owner) |
| 808 continue; | 814 continue; |
| 809 | 815 |
| 810 // Remove it from the child -> owner mapping so it's not owned by this owner
anymore. | 816 // Remove it from the child -> owner mapping so it's not owned by this owner |
| 817 // anymore. |
| 811 m_ariaOwnedChildToOwnerMapping.remove(removedChildID); | 818 m_ariaOwnedChildToOwnerMapping.remove(removedChildID); |
| 812 | 819 |
| 813 if (removedChild) { | 820 if (removedChild) { |
| 814 // If the child still exists, find its "real" parent, and reparent it back
to | 821 // If the child still exists, find its "real" parent, and reparent it back |
| 815 // its real parent in the tree by detaching it from its current parent and | 822 // to its real parent in the tree by detaching it from its current parent |
| 816 // calling childrenChanged on its real parent. | 823 // and calling childrenChanged on its real parent. |
| 817 removedChild->detachFromParent(); | 824 removedChild->detachFromParent(); |
| 818 AXID realParentID = | 825 AXID realParentID = |
| 819 m_ariaOwnedChildToRealParentMapping.get(removedChildID); | 826 m_ariaOwnedChildToRealParentMapping.get(removedChildID); |
| 820 AXObject* realParent = objectFromAXID(realParentID); | 827 AXObject* realParent = objectFromAXID(realParentID); |
| 821 childrenChanged(realParent); | 828 childrenChanged(realParent); |
| 822 } | 829 } |
| 823 | 830 |
| 824 // Remove the child -> original parent mapping too since this object has now
been | 831 // Remove the child -> original parent mapping too since this object has now |
| 825 // reparented back to its original parent. | 832 // been reparented back to its original parent. |
| 826 m_ariaOwnedChildToRealParentMapping.remove(removedChildID); | 833 m_ariaOwnedChildToRealParentMapping.remove(removedChildID); |
| 827 } | 834 } |
| 828 | 835 |
| 829 for (size_t i = 0; i < newChildAXIDs.size(); ++i) { | 836 for (size_t i = 0; i < newChildAXIDs.size(); ++i) { |
| 830 // Find the AXObject for the child that will now be a child of this owner. | 837 // Find the AXObject for the child that will now be a child of this owner. |
| 831 AXID addedChildID = newChildAXIDs[i]; | 838 AXID addedChildID = newChildAXIDs[i]; |
| 832 AXObject* addedChild = objectFromAXID(addedChildID); | 839 AXObject* addedChild = objectFromAXID(addedChildID); |
| 833 | 840 |
| 834 // Add this child to the mapping from child to owner. | 841 // Add this child to the mapping from child to owner. |
| 835 m_ariaOwnedChildToOwnerMapping.set(addedChildID, owner->axObjectID()); | 842 m_ariaOwnedChildToOwnerMapping.set(addedChildID, owner->axObjectID()); |
| 836 | 843 |
| 837 // Add its parent object to a mapping from child to real parent. If later th
is owner | 844 // Add its parent object to a mapping from child to real parent. If later |
| 838 // doesn't own this child anymore, we need to return it to its original pare
nt. | 845 // this owner doesn't own this child anymore, we need to return it to its |
| 846 // original parent. |
| 839 AXObject* originalParent = addedChild->parentObject(); | 847 AXObject* originalParent = addedChild->parentObject(); |
| 840 m_ariaOwnedChildToRealParentMapping.set(addedChildID, | 848 m_ariaOwnedChildToRealParentMapping.set(addedChildID, |
| 841 originalParent->axObjectID()); | 849 originalParent->axObjectID()); |
| 842 | 850 |
| 843 // Now detach the object from its original parent and call childrenChanged o
n the | 851 // Now detach the object from its original parent and call childrenChanged |
| 844 // original parent so that it can recompute its list of children. | 852 // on the original parent so that it can recompute its list of children. |
| 845 addedChild->detachFromParent(); | 853 addedChild->detachFromParent(); |
| 846 childrenChanged(originalParent); | 854 childrenChanged(originalParent); |
| 847 } | 855 } |
| 848 | 856 |
| 849 // Finally, update the mapping from the owner to the list of child IDs. | 857 // Finally, update the mapping from the owner to the list of child IDs. |
| 850 m_ariaOwnerToChildrenMapping.set(owner->axObjectID(), newChildAXIDs); | 858 m_ariaOwnerToChildrenMapping.set(owner->axObjectID(), newChildAXIDs); |
| 851 } | 859 } |
| 852 | 860 |
| 853 void AXObjectCacheImpl::updateTreeIfElementIdIsAriaOwned(Element* element) { | 861 void AXObjectCacheImpl::updateTreeIfElementIdIsAriaOwned(Element* element) { |
| 854 if (!element->hasID()) | 862 if (!element->hasID()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 865 | 873 |
| 866 // If it's already owned, call childrenChanged on the owner to make sure it's | 874 // If it's already owned, call childrenChanged on the owner to make sure it's |
| 867 // still an owner. | 875 // still an owner. |
| 868 if (isAriaOwned(axElement)) { | 876 if (isAriaOwned(axElement)) { |
| 869 AXObject* ownedParent = getAriaOwnedParent(axElement); | 877 AXObject* ownedParent = getAriaOwnedParent(axElement); |
| 870 ASSERT(ownedParent); | 878 ASSERT(ownedParent); |
| 871 childrenChanged(ownedParent); | 879 childrenChanged(ownedParent); |
| 872 return; | 880 return; |
| 873 } | 881 } |
| 874 | 882 |
| 875 // If it's not already owned, check the possible owners based on our mapping f
rom | 883 // If it's not already owned, check the possible owners based on our mapping |
| 876 // ids to elements that have that id listed in their aria-owns attribute. | 884 // from ids to elements that have that id listed in their aria-owns attribute. |
| 877 for (const auto& axID : *owners) { | 885 for (const auto& axID : *owners) { |
| 878 AXObject* owner = objectFromAXID(axID); | 886 AXObject* owner = objectFromAXID(axID); |
| 879 if (owner) | 887 if (owner) |
| 880 childrenChanged(owner); | 888 childrenChanged(owner); |
| 881 } | 889 } |
| 882 } | 890 } |
| 883 | 891 |
| 884 void AXObjectCacheImpl::checkedStateChanged(Node* node) { | 892 void AXObjectCacheImpl::checkedStateChanged(Node* node) { |
| 885 postNotification(node, AXObjectCacheImpl::AXCheckedStateChanged); | 893 postNotification(node, AXObjectCacheImpl::AXCheckedStateChanged); |
| 886 } | 894 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 901 | 909 |
| 902 toAXListBox(obj)->activeIndexChanged(); | 910 toAXListBox(obj)->activeIndexChanged(); |
| 903 } | 911 } |
| 904 | 912 |
| 905 void AXObjectCacheImpl::radiobuttonRemovedFromGroup( | 913 void AXObjectCacheImpl::radiobuttonRemovedFromGroup( |
| 906 HTMLInputElement* groupMember) { | 914 HTMLInputElement* groupMember) { |
| 907 AXObject* obj = get(groupMember); | 915 AXObject* obj = get(groupMember); |
| 908 if (!obj || !obj->isAXRadioInput()) | 916 if (!obj || !obj->isAXRadioInput()) |
| 909 return; | 917 return; |
| 910 | 918 |
| 911 // The 'posInSet' and 'setSize' attributes should be updated from the first no
de, | 919 // The 'posInSet' and 'setSize' attributes should be updated from the first |
| 912 // as the removed node is already detached from tree. | 920 // node, as the removed node is already detached from tree. |
| 913 HTMLInputElement* firstRadio = | 921 HTMLInputElement* firstRadio = |
| 914 toAXRadioInput(obj)->findFirstRadioButtonInGroup(groupMember); | 922 toAXRadioInput(obj)->findFirstRadioButtonInGroup(groupMember); |
| 915 AXObject* firstObj = get(firstRadio); | 923 AXObject* firstObj = get(firstRadio); |
| 916 if (!firstObj || !firstObj->isAXRadioInput()) | 924 if (!firstObj || !firstObj->isAXRadioInput()) |
| 917 return; | 925 return; |
| 918 | 926 |
| 919 toAXRadioInput(firstObj)->updatePosAndSetSize(1); | 927 toAXRadioInput(firstObj)->updatePosAndSetSize(1); |
| 920 postNotification(firstObj, AXAriaAttributeChanged); | 928 postNotification(firstObj, AXAriaAttributeChanged); |
| 921 toAXRadioInput(firstObj)->requestUpdateToNextNode(true); | 929 toAXRadioInput(firstObj)->requestUpdateToNextNode(true); |
| 922 } | 930 } |
| 923 | 931 |
| 924 void AXObjectCacheImpl::handleLayoutComplete(LayoutObject* layoutObject) { | 932 void AXObjectCacheImpl::handleLayoutComplete(LayoutObject* layoutObject) { |
| 925 if (!layoutObject) | 933 if (!layoutObject) |
| 926 return; | 934 return; |
| 927 | 935 |
| 928 m_modificationCount++; | 936 m_modificationCount++; |
| 929 | 937 |
| 930 // Create the AXObject if it didn't yet exist - that's always safe at the end
of a layout, and it | 938 // Create the AXObject if it didn't yet exist - that's always safe at the end |
| 931 // allows an AX notification to be sent when a page has its first layout, rath
er than when the | 939 // of a layout, and it allows an AX notification to be sent when a page has |
| 932 // document first loads. | 940 // its first layout, rather than when the document first loads. |
| 933 if (AXObject* obj = getOrCreate(layoutObject)) | 941 if (AXObject* obj = getOrCreate(layoutObject)) |
| 934 postNotification(obj, AXLayoutComplete); | 942 postNotification(obj, AXLayoutComplete); |
| 935 } | 943 } |
| 936 | 944 |
| 937 void AXObjectCacheImpl::handleClicked(Node* node) { | 945 void AXObjectCacheImpl::handleClicked(Node* node) { |
| 938 if (AXObject* obj = getOrCreate(node)) | 946 if (AXObject* obj = getOrCreate(node)) |
| 939 postNotification(obj, AXClicked); | 947 postNotification(obj, AXClicked); |
| 940 } | 948 } |
| 941 | 949 |
| 942 void AXObjectCacheImpl::handleAriaExpandedChange(Node* node) { | 950 void AXObjectCacheImpl::handleAriaExpandedChange(Node* node) { |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1247 visitor->trace(m_document); | 1255 visitor->trace(m_document); |
| 1248 visitor->trace(m_nodeObjectMapping); | 1256 visitor->trace(m_nodeObjectMapping); |
| 1249 | 1257 |
| 1250 visitor->trace(m_objects); | 1258 visitor->trace(m_objects); |
| 1251 visitor->trace(m_notificationsToPost); | 1259 visitor->trace(m_notificationsToPost); |
| 1252 | 1260 |
| 1253 AXObjectCache::trace(visitor); | 1261 AXObjectCache::trace(visitor); |
| 1254 } | 1262 } |
| 1255 | 1263 |
| 1256 } // namespace blink | 1264 } // namespace blink |
| OLD | NEW |