⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 259832 in webkit


Ignore:
Timestamp:
Apr 9, 2020, 2:55:53 PM (6 years ago)
Author:
Andres Gonzalez
Message:

Fix for crash in test accessibility/mac/aria-grid-with-strange-hierarchy.html in isolated tree mode.
https://bugs.webkit.org/show_bug.cgi?id=210295

Reviewed by Chris Fleizach.

Covered by accessibility/mac/aria-grid-with-strange-hierarchy.html.

  • When AXIsolatedTree::applyPendingChanges encounters a change for an

already existing object, the existing object is discarded and the new
object replaces it in the nodes map. The existing and new objects must
have the same platform wrapper. Thus the wrapper needs to be detached
from the existing object about to be discarded, and re-attached to the
new object. We were missing the re-attachment, and hence the crash when
the wrapper tries to access its underlying object.

  • In addition, moved the LockHolder in a couple of intances to before

AXIsolatedTree::nodeForID, because this method accesses a member
variable used in both threads.

  • Added stricter assert checks to catch problems with the management of

objects and wrappers during tree updates.

  • accessibility/isolatedtree/AXIsolatedTree.cpp:

(WebCore::AXIsolatedTree::updateNode):
(WebCore::AXIsolatedTree::updateChildren):
(WebCore::AXIsolatedTree::applyPendingChanges):

  • accessibility/mac/WebAccessibilityObjectWrapperBase.mm:

(-[WebAccessibilityObjectWrapperBase attachIsolatedObject:]):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r259830 r259832  
     12020-04-09  Andres Gonzalez  <andresg_22@apple.com>
     2
     3        Fix for crash in test accessibility/mac/aria-grid-with-strange-hierarchy.html in isolated tree mode.
     4        https://bugs.webkit.org/show_bug.cgi?id=210295
     5
     6        Reviewed by Chris Fleizach.
     7
     8        Covered by accessibility/mac/aria-grid-with-strange-hierarchy.html.
     9
     10        - When AXIsolatedTree::applyPendingChanges encounters a change for an
     11        already existing object, the existing object is discarded and the new
     12        object replaces it in the nodes map. The existing and new objects must
     13        have the same platform wrapper. Thus the wrapper needs to be detached
     14        from the existing object about to be discarded, and re-attached to the
     15        new object. We were missing the re-attachment, and hence the crash when
     16        the wrapper tries to access its underlying object.
     17        - In addition, moved the LockHolder in a couple of intances to before
     18        AXIsolatedTree::nodeForID, because this method accesses a member
     19        variable used in both threads.
     20        - Added stricter assert checks to catch problems with the management of
     21        objects and wrappers during tree updates.
     22
     23        * accessibility/isolatedtree/AXIsolatedTree.cpp:
     24        (WebCore::AXIsolatedTree::updateNode):
     25        (WebCore::AXIsolatedTree::updateChildren):
     26        (WebCore::AXIsolatedTree::applyPendingChanges):
     27        * accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
     28        (-[WebAccessibilityObjectWrapperBase attachIsolatedObject:]):
     29
    1302020-04-09  Said Abou-Hallawa  <sabouhallawa@apple.com>
    231
  • trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedTree.cpp

    r258971 r259832  
    187187    AXID parentID = axParent ? axParent->objectID() : InvalidAXID;
    188188
     189    LockHolder locker { m_changeLogLock };
    189190    if (auto object = nodeForID(axID)) {
    190191        ASSERT(object->objectID() == axID);
    191192        auto newObject = AXIsolatedObject::create(axObject, m_treeID, parentID);
    192193
    193         LockHolder locker { m_changeLogLock };
    194194        // The new object should have the same children as the old one.
    195195        newObject->m_childrenIDs = object->m_childrenIDs;
     
    213213    ASSERT(isMainThread());
    214214    AXID axObjectID = axObject.objectID();
     215
     216    LockHolder locker { m_changeLogLock };
    215217    auto object = nodeForID(axObjectID);
    216218    if (!object)
    217219        return; // nothing to update.
    218220
     221    auto removals = object->m_childrenIDs;
     222    locker.unlockEarly();
     223
    219224    const auto& axChildren = axObject.children();
    220225    auto axChildrenIDs = axObject.childrenIDs();
    221 
    222     LockHolder locker { m_changeLogLock };
    223     auto removals = object->m_childrenIDs;
    224     // Make the children IDs of the isolated object to be the same as the AXObject's.
    225     object->m_childrenIDs = axChildrenIDs;
    226     locker.unlockEarly();
    227226
    228227    for (size_t i = 0; i < axChildrenIDs.size(); ++i) {
     
    232231        else {
    233232            // This is a new child, add it to the tree.
    234             generateSubtree(*axChildren[i], axObjectID, false);
     233            generateSubtree(*axChildren[i], axObjectID, true);
    235234        }
    236235    }
     
    240239    for (const AXID& childID : removals)
    241240        removeSubtree(childID);
     241
     242    {
     243        // Lastly, make the children IDs of the isolated object to be the same as the AXObject's.
     244        LockHolder locker { m_changeLogLock };
     245        object->m_childrenIDs = axChildrenIDs;
     246    }
    242247}
    243248
     
    332337
    333338    for (const auto& item : m_pendingAppends) {
    334         ASSERT(item.m_isolatedObject->wrapper() || item.m_wrapper);
     339        // Either the new object has a wrapper already attached, or one is passed to be attached, not both.
     340        ASSERT((item.m_isolatedObject->wrapper() || item.m_wrapper)
     341            && !(item.m_isolatedObject->wrapper() && item.m_wrapper));
    335342        AXID axID = item.m_isolatedObject->objectID();
    336343        if (axID == InvalidAXID)
    337344            continue;
    338345
     346        auto& wrapper = item.m_wrapper ? item.m_wrapper : item.m_isolatedObject->wrapper();
     347
    339348        if (auto object = m_readerThreadNodeMap.get(axID)) {
    340349            if (object != &item.m_isolatedObject.get()
    341                 && (object->wrapper() == item.m_wrapper || object->wrapper() == item.m_isolatedObject->wrapper())) {
     350                && object->wrapper() == wrapper.get()) {
    342351                // The new IsolatedObject is a replacement for an existing object
    343                 // as the result of an update. Thus detach the existing one before
    344                 // adding the new one.
     352                // as the result of an update. Thus detach the wrapper from the
     353                // existing object and attach it to the new one.
    345354                object->detachWrapper(AccessibilityDetachmentType::ElementDestroyed);
     355                item.m_isolatedObject->attachPlatformWrapper(wrapper.get());
    346356            }
    347357            m_readerThreadNodeMap.remove(axID);
    348358        }
    349359
    350         if (m_readerThreadNodeMap.add(axID, item.m_isolatedObject.get()) && item.m_wrapper)
    351             m_readerThreadNodeMap.get(axID)->attachPlatformWrapper(item.m_wrapper.get());
    352 
     360        if (!item.m_isolatedObject->wrapper()) {
     361            // The new object hasn't been attached a wrapper yet, so attach it.
     362            item.m_isolatedObject->attachPlatformWrapper(wrapper.get());
     363        }
     364
     365        auto addResult = m_readerThreadNodeMap.add(axID, item.m_isolatedObject.get());
     366        // The newly added object must have a wrapper.
     367        ASSERT_UNUSED(addResult, addResult.iterator->value->wrapper());
    353368        // The reference count of the just added IsolatedObject must be 2
    354369        // because it is referenced by m_readerThreadNodeMap and m_pendingAppends.
    355370        // When m_pendingAppends is cleared, the object will be held only by m_readerThreadNodeMap.
    356         ASSERT(m_readerThreadNodeMap.get(axID)->refCount() == 2);
     371        ASSERT_UNUSED(addResult, addResult.iterator->value->refCount() == 2);
    357372    }
    358373    m_pendingAppends.clear();
  • trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm

    r258115 r259832  
    305305{
    306306    ASSERT(isolatedObject && (_identifier == InvalidAXID || _identifier == isolatedObject->objectID()));
     307    ASSERT(m_axObject && isolatedObject->objectID() == m_axObject->objectID());
    307308    m_isolatedObject = isolatedObject;
    308309    if (_identifier == InvalidAXID)
Note: See TracChangeset for help on using the changeset viewer.