Changeset 96340 in webkit
- Timestamp:
- Sep 29, 2011 10:46:14 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r96336 r96340 1 2011-09-29 Chris Fleizach <cfleizach@apple.com> 2 3 ARIA live regions don't trigger notifications for elements that aren't in the AX tree 4 https://bugs.webkit.org/show_bug.cgi?id=62289 5 6 Reviewed by Darin Adler. 7 8 * platform/mac/accessibility/aria-liveregion-without-element-access-expected.txt: Added. 9 * platform/mac/accessibility/aria-liveregion-without-element-access.html: Added. 10 1 11 2011-09-29 David Reveman <reveman@chromium.org> 2 12 -
trunk/Source/WebCore/ChangeLog
r96339 r96340 1 2011-09-29 Chris Fleizach <cfleizach@apple.com> 2 3 ARIA live regions don't trigger notifications for elements that aren't in the AX tree 4 https://bugs.webkit.org/show_bug.cgi?id=62289 5 6 If an ARIA Live region udpates an element that is not in the AX object cache, then the Live region 7 notification is not sent. To fix this, the childrenChanged() method needs to actually create 8 the appropriate objects, but since that method gets called during a render tree update, we've learned 9 that it's generally not safe to create objects. 10 11 Instead a one shot timer can be fired that will update and create the necessary objects so that the 12 correct notification can be sent. 13 14 Reviewed by Darin Adler. 15 16 Test: platform/mac/accessibility/aria-liveregion-without-element-access.html 17 18 * accessibility/AXObjectCache.cpp: 19 (WebCore::AXObjectCache::AXObjectCache): 20 (WebCore::AXObjectCache::~AXObjectCache): 21 (WebCore::AXObjectCache::remove): 22 (WebCore::AXObjectCache::childrenUpdateTimerFired): 23 (WebCore::AXObjectCache::childrenChanged): 24 * accessibility/AXObjectCache.h: 25 * accessibility/AccessibilityMenuList.cpp: 26 (WebCore::AccessibilityMenuList::childrenChanged): 27 * accessibility/AccessibilityMenuList.h: 28 * accessibility/AccessibilityMenuListPopup.cpp: 29 (WebCore::AccessibilityMenuListPopup::childrenChanged): 30 * accessibility/AccessibilityMenuListPopup.h: 31 * accessibility/AccessibilityObject.h: 32 (WebCore::AccessibilityObject::childrenChanged): 33 * accessibility/AccessibilityRenderObject.cpp: 34 (WebCore::startOfContinuations): 35 (WebCore::AccessibilityRenderObject::updateAccessibilityRole): 36 (WebCore::AccessibilityRenderObject::childrenChanged): 37 * accessibility/AccessibilityRenderObject.h: 38 * rendering/RenderObject.cpp: 39 (WebCore::RenderObject::willBeDestroyed): 40 1 41 2011-09-29 Martin Robinson <mrobinson@igalia.com> 2 42 -
trunk/Source/WebCore/accessibility/AXObjectCache.cpp
r95901 r96340 83 83 AXObjectCache::AXObjectCache(const Document* doc) 84 84 : m_notificationPostTimer(this, &AXObjectCache::notificationPostTimerFired) 85 , m_childrenUpdateTimer(this, &AXObjectCache::childrenUpdateTimerFired) 85 86 { 86 87 m_document = const_cast<Document*>(doc); … … 89 90 AXObjectCache::~AXObjectCache() 90 91 { 92 m_childrenUpdateTimer.stop(); 93 m_notificationPostTimer.stop(); 94 91 95 HashMap<AXID, RefPtr<AccessibilityObject> >::iterator end = m_objects.end(); 92 96 for (HashMap<AXID, RefPtr<AccessibilityObject> >::iterator it = m_objects.begin(); it != end; ++it) { … … 368 372 remove(axID); 369 373 m_renderObjectMapping.remove(renderer); 374 m_childrenToUpdate.remove(renderer); 370 375 } 371 376 … … 437 442 } 438 443 #endif 444 445 void AXObjectCache::childrenUpdateTimerFired(Timer<AXObjectCache>*) 446 { 447 if (m_childrenToUpdate.isEmpty()) 448 return; 449 450 // Make a local copy in case childrenChanged() alters m_childrenToUpdate 451 // (which might happen if the client asks to update the render tree). 452 HashSet<RenderObject*> updateChildren; 453 m_childrenToUpdate.swap(updateChildren); 454 m_childrenToUpdate.clear(); 455 456 HashSet<RenderObject*>::iterator end = updateChildren.end(); 457 for (HashSet<RenderObject*>::iterator it = updateChildren.begin(); it != end; ++it) { 458 if (AccessibilityObject* object = getOrCreate(*it)) 459 object->childrenChanged(AccessibilityObject::CreateParentObjects); 460 } 461 } 439 462 440 463 void AXObjectCache::childrenChanged(RenderObject* renderer) … … 444 467 445 468 AXID axID = m_renderObjectMapping.get(renderer); 446 if (!axID) 447 return; 448 449 AccessibilityObject* obj = m_objects.get(axID).get(); 450 if (obj) 451 obj->childrenChanged(); 469 if (!axID) { 470 // If there's no AX object, creating one right now can be dangerous (because we're in the middle of adding/destroying a tree). 471 // Instead the update should be postponed and updated later. 472 m_childrenToUpdate.add(renderer); 473 474 if (!m_childrenUpdateTimer.isActive()) 475 m_childrenUpdateTimer.startOneShot(0); 476 } else { 477 if (AccessibilityObject* object = m_objects.get(axID).get()) 478 object->childrenChanged(AccessibilityObject::DoNotCreateParentObjects); 479 } 480 452 481 } 453 482 -
trunk/Source/WebCore/accessibility/AXObjectCache.h
r91219 r96340 168 168 Vector<pair<RefPtr<AccessibilityObject>, AXNotification> > m_notificationsToPost; 169 169 void notificationPostTimerFired(Timer<AXObjectCache>*); 170 170 171 Timer<AXObjectCache> m_childrenUpdateTimer; 172 HashSet<RenderObject*> m_childrenToUpdate; 173 void childrenUpdateTimerFired(Timer<AXObjectCache>*); 174 171 175 static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*); 172 176 -
trunk/Source/WebCore/accessibility/AccessibilityMenuList.cpp
r95901 r96340 69 69 } 70 70 71 void AccessibilityMenuList::childrenChanged( )71 void AccessibilityMenuList::childrenChanged(ChildrenChangeOptions options) 72 72 { 73 73 if (m_children.isEmpty()) … … 75 75 76 76 ASSERT(m_children.size() == 1); 77 m_children[0]->childrenChanged( );77 m_children[0]->childrenChanged(options); 78 78 } 79 79 -
trunk/Source/WebCore/accessibility/AccessibilityMenuList.h
r95901 r96340 54 54 55 55 virtual void addChildren(); 56 virtual void childrenChanged( );56 virtual void childrenChanged(ChildrenChangeOptions); 57 57 }; 58 58 -
trunk/Source/WebCore/accessibility/AccessibilityMenuListPopup.cpp
r95901 r96340 104 104 } 105 105 106 void AccessibilityMenuListPopup::childrenChanged( )106 void AccessibilityMenuListPopup::childrenChanged(ChildrenChangeOptions) 107 107 { 108 108 for (size_t i = m_children.size(); i > 0 ; --i) { -
trunk/Source/WebCore/accessibility/AccessibilityMenuListPopup.h
r95901 r96340 60 60 virtual bool press() const; 61 61 virtual void addChildren(); 62 virtual void childrenChanged( );62 virtual void childrenChanged(ChildrenChangeOptions); 63 63 64 64 AccessibilityMenuListOption* menuListOptionAccessibilityObject(HTMLElement*) const; -
trunk/Source/WebCore/accessibility/AccessibilityObject.h
r95901 r96340 551 551 virtual void decrement() { } 552 552 553 virtual void childrenChanged() { } 553 enum ChildrenChangeOptions { DoNotCreateParentObjects, CreateParentObjects }; 554 virtual void childrenChanged(ChildrenChangeOptions) { } 554 555 virtual void contentChanged() { } 555 556 virtual const AccessibilityChildrenVector& children() { return m_children; } -
trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
r95901 r96340 224 224 static inline RenderInline* startOfContinuations(RenderObject* r) 225 225 { 226 if (r->isInlineElementContinuation() )226 if (r->isInlineElementContinuation() && r->node()->renderer() && r->isRenderInline()) 227 227 return toRenderInline(r->node()->renderer()); 228 228 … … 3088 3088 // The AX hierarchy only needs to be updated if the ignored status of an element has changed. 3089 3089 if (ignoredStatus != accessibilityIsIgnored()) 3090 childrenChanged( );3090 childrenChanged(DoNotCreateParentObjects); 3091 3091 } 3092 3092 … … 3371 3371 } 3372 3372 3373 void AccessibilityRenderObject::childrenChanged( )3373 void AccessibilityRenderObject::childrenChanged(ChildrenChangeOptions options) 3374 3374 { 3375 3375 // This method is meant as a quick way of marking a portion of the accessibility tree dirty. … … 3383 3383 // If AX elements are created now, they could interrogate the render tree while it's in a funky state. 3384 3384 // At the same time, process ARIA live region changes. 3385 for (AccessibilityObject* parent = this; parent; parent = parent->parentObjectIfExists()) {3385 for (AccessibilityObject* parent = this; parent; parent = (options == CreateParentObjects) ? parent->parentObject() : parent->parentObjectIfExists()) { 3386 3386 if (!parent->isAccessibilityRenderObject()) 3387 3387 continue; -
trunk/Source/WebCore/accessibility/AccessibilityRenderObject.h
r95901 r96340 216 216 217 217 virtual void detach(); 218 virtual void childrenChanged( );218 virtual void childrenChanged(ChildrenChangeOptions); 219 219 virtual void contentChanged(); 220 220 virtual void addChildren(); -
trunk/Source/WebCore/rendering/RenderObject.cpp
r96187 r96340 2177 2177 frame()->eventHandler()->stopAutoscrollTimer(true); 2178 2178 2179 if (AXObjectCache::accessibilityEnabled()) {2180 document()->axObjectCache()->childrenChanged(this->parent());2181 document()->axObjectCache()->remove(this);2182 }2183 2179 animation()->cancelAnimations(this); 2184 2180 … … 2198 2194 setHasLayer(false); 2199 2195 toRenderBoxModelObject(this)->destroyLayer(); 2196 } 2197 2198 // Update accessibility at the end, so that all children nodes have been disassociated first. 2199 // This ordering allows us to call childrenChanged() on the parent without worrying that the parent has been destroyed. 2200 if (AXObjectCache::accessibilityEnabled()) { 2201 document()->axObjectCache()->childrenChanged(this->parent()); 2202 document()->axObjectCache()->remove(this); 2200 2203 } 2201 2204 }
Note: See TracChangeset
for help on using the changeset viewer.