Changeset 291570 in webkit


Ignore:
Timestamp:
Mar 21, 2022 11:48:25 AM (4 months ago)
Author:
Tyler Wilcock
Message:

AX: Include display: contents elements in the AX tree
https://bugs.webkit.org/show_bug.cgi?id=237834

Reviewed by Chris Fleizach.

Source/WebCore:

Because display: contents intentionally prevents a render object from being
generated for the element it's applied to, we don't add it to the AX tree as
part of our normal render tree walk, making these elements inaccessible.

This patch includes these elements as part of the DOM walk that
addHiddenChildren (now renamed to addNodeOnlyChildren) already does.

Also, because display: contents moves the affected element's children up a
level in the render tree, this patch also special cases:

  1. AccessibilityRenderObject::parentObject and similar methods to return their display: contents parent instead of their render tree parent
  2. AccessibilityObject::insertChild to only insert display: contents children to their display: contents parent, rather than their render tree parent

Test: accessibility/display-contents-element-roles.html, accessibility/aria-hidden-display-contents-element.html

  • accessibility/AXObjectCache.cpp:

(WebCore::AXObjectCache::getOrCreate):
Allow creation of AX objects from display: contents Nodes.
Also, don't create an object for a renderer that is in the process of
being destroyed (prevents display-contents-element-roles.html from crashing in ITM)

  • accessibility/AccessibilityObject.cpp:

(WebCore::AccessibilityObject::displayContentsParent const):
(WebCore::AccessibilityObject::insertChild):
If an object has a display: contents parent, and that parent isn't
this, return early.

  • accessibility/AccessibilityObject.h:
  • accessibility/AccessibilityRenderObject.cpp:

(WebCore::AccessibilityRenderObject::parentObjectIfExists const):
(WebCore::AccessibilityRenderObject::parentObject const):
(WebCore::AccessibilityRenderObject::parentObjectUnignored const):
If an object has a display: contents parent, return that instead of
its render tree parent.
(WebCore::AccessibilityRenderObject::addNodeOnlyChildren):
Renamed from addHiddenChildren.
(WebCore::AccessibilityRenderObject::addChildren):
Don't clear m_subtreeDirty until after all children have been added.
Necessary to make aria-hidden-display-contents-element.html pass, as
we were clearing this too early, causing display: contents subtrees to
not be updated after aria-hidden changes.
(WebCore::AccessibilityRenderObject::addHiddenChildren):
Renamed to addNodeOnlyChildren.

  • accessibility/AccessibilityRenderObject.h:

LayoutTests:

  • accessibility/aria-hidden-display-contents-element-expected.txt: Added.
  • accessibility/aria-hidden-display-contents-element.html: Added.
  • accessibility/display-contents-element-roles-expected.txt: Added.
  • accessibility/display-contents-element-roles.html: Added.
  • platform/glib/accessibility/aria-hidden-display-contents-element-expected.txt: Added.
  • platform/glib/accessibility/display-contents-element-roles-expected.txt: Added.
  • platform/ios/TestExpectations: Enable new tests.
  • platform/ios/accessibility/aria-hidden-display-contents-element-expected.txt: Added.
  • platform/ios/accessibility/display-contents-element-roles-expected.txt: Added.
  • platform/win/TestExpectations: Skip display-contents-element-roles.html.
  • platform/win/accessibility/aria-hidden-display-contents-element-expected.txt: Added.
Location:
trunk
Files:
9 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r291555 r291570  
     12022-03-21  Tyler Wilcock  <tyler_w@apple.com>
     2
     3        AX: Include display: contents elements in the AX tree
     4        https://bugs.webkit.org/show_bug.cgi?id=237834
     5
     6        Reviewed by Chris Fleizach.
     7
     8        * accessibility/aria-hidden-display-contents-element-expected.txt: Added.
     9        * accessibility/aria-hidden-display-contents-element.html: Added.
     10        * accessibility/display-contents-element-roles-expected.txt: Added.
     11        * accessibility/display-contents-element-roles.html: Added.
     12        * platform/glib/accessibility/aria-hidden-display-contents-element-expected.txt: Added.
     13        * platform/glib/accessibility/display-contents-element-roles-expected.txt: Added.
     14        * platform/ios/TestExpectations: Enable new tests.
     15        * platform/ios/accessibility/aria-hidden-display-contents-element-expected.txt: Added.
     16        * platform/ios/accessibility/display-contents-element-roles-expected.txt: Added.
     17        * platform/win/TestExpectations: Skip display-contents-element-roles.html.
     18        * platform/win/accessibility/aria-hidden-display-contents-element-expected.txt: Added.
     19
    1202022-03-21  Ziran Sun  <zsun@igalia.com>
    221
  • trunk/LayoutTests/platform/ios/TestExpectations

    r291552 r291570  
    20892089fast/dom/linkify-phone-numbers.html [ Pass ]
    20902090
     2091accessibility/aria-hidden-display-contents-element.html [ Pass ]
     2092accessibility/display-contents-element-roles.html [ Pass ]
    20912093accessibility/video-element-url-attribute.html [ Pass ]
    20922094accessibility/visible-character-range.html [ Pass ]
  • trunk/LayoutTests/platform/win/TestExpectations

    r291435 r291570  
    15401540##################        Accessibility Issues              ####################
    15411541################################################################################
     1542
     1543accessibility/display-contents-element-roles.html [ Skip ]
    15421544
    15431545# Missing 'press' support
  • trunk/Source/WebCore/ChangeLog

    r291568 r291570  
     12022-03-21  Tyler Wilcock  <tyler_w@apple.com>
     2
     3        AX: Include display: contents elements in the AX tree
     4        https://bugs.webkit.org/show_bug.cgi?id=237834
     5
     6        Reviewed by Chris Fleizach.
     7
     8        Because display: contents intentionally prevents a render object from being
     9        generated for the element it's applied to, we don't add it to the AX tree as
     10        part of our normal render tree walk, making these elements inaccessible.
     11
     12        This patch includes these elements as part of the DOM walk that
     13        addHiddenChildren (now renamed to addNodeOnlyChildren) already does.
     14
     15        Also, because display: contents moves the affected element's children up a
     16        level in the render tree, this patch also special cases:
     17
     18          1. AccessibilityRenderObject::parentObject and similar methods to
     19          return their display: contents parent instead of their render tree
     20          parent
     21          2. AccessibilityObject::insertChild to only insert display: contents
     22          children to their display: contents parent, rather than their render
     23          tree parent
     24
     25        Test: accessibility/display-contents-element-roles.html, accessibility/aria-hidden-display-contents-element.html
     26
     27        * accessibility/AXObjectCache.cpp:
     28        (WebCore::AXObjectCache::getOrCreate):
     29        Allow creation of AX objects from display: contents `Node`s.
     30        Also, don't create an object for a renderer that is in the process of
     31        being destroyed (prevents display-contents-element-roles.html from crashing in ITM)
     32        * accessibility/AccessibilityObject.cpp:
     33        (WebCore::AccessibilityObject::displayContentsParent const):
     34        (WebCore::AccessibilityObject::insertChild):
     35        If an object has a display: contents parent, and that parent isn't
     36        `this`, return early.
     37        * accessibility/AccessibilityObject.h:
     38        * accessibility/AccessibilityRenderObject.cpp:
     39        (WebCore::AccessibilityRenderObject::parentObjectIfExists const):
     40        (WebCore::AccessibilityRenderObject::parentObject const):
     41        (WebCore::AccessibilityRenderObject::parentObjectUnignored const):
     42        If an object has a display: contents parent, return that instead of
     43        its render tree parent.
     44        (WebCore::AccessibilityRenderObject::addNodeOnlyChildren):
     45        Renamed from addHiddenChildren.
     46        (WebCore::AccessibilityRenderObject::addChildren):
     47        Don't clear m_subtreeDirty until after all children have been added.
     48        Necessary to make aria-hidden-display-contents-element.html pass, as
     49        we were clearing this too early, causing display: contents subtrees to
     50        not be updated after aria-hidden changes.
     51        (WebCore::AccessibilityRenderObject::addHiddenChildren):
     52        Renamed to addNodeOnlyChildren.
     53        * accessibility/AccessibilityRenderObject.h:
     54
    1552022-03-21  Oriol Brufau  <obrufau@igalia.com>
    256
  • trunk/Source/WebCore/accessibility/AXObjectCache.cpp

    r291481 r291570  
    721721    }
    722722
    723     // It's only allowed to create an AccessibilityObject from a Node if it's in a canvas subtree.
    724     // Or if it's a hidden element, but we still want to expose it because of other ARIA attributes.
    725723    bool inCanvasSubtree = lineageOfType<HTMLCanvasElement>(*node->parentElement()).first();
    726     bool isHidden = isNodeAriaVisible(node);
    727 
    728724    bool insideMeterElement = is<HTMLMeterElement>(*node->parentElement());
    729    
    730     if (!inCanvasSubtree && !isHidden && !insideMeterElement)
     725    bool hasDisplayContents = is<Element>(*node) && downcast<Element>(*node).hasDisplayContents();
     726    if (!inCanvasSubtree && !insideMeterElement && !hasDisplayContents && !isNodeAriaVisible(node))
    731727        return nullptr;
    732728
     
    761757        return obj;
    762758
     759    // Don't create an object for this renderer if it's being destroyed.
     760    if (renderer->beingDestroyed())
     761        return nullptr;
    763762    RefPtr<AccessibilityObject> newObj = createFromRenderer(renderer);
    764763
  • trunk/Source/WebCore/accessibility/AccessibilityObject.cpp

    r290630 r291570  
    449449}
    450450
     451AccessibilityObject* AccessibilityObject::displayContentsParent() const
     452{
     453    auto* parentNode = node() ? node()->parentNode() : nullptr;
     454    if (!is<Element>(parentNode) || !downcast<Element>(parentNode)->hasDisplayContents())
     455        return nullptr;
     456
     457    auto* cache = axObjectCache();
     458    return cache ? cache->getOrCreate(parentNode) : nullptr;
     459}
     460
    451461AccessibilityObject* AccessibilityObject::previousSiblingUnignored(int limit) const
    452462{
     
    576586    if (!newChild)
    577587        return;
    578    
     588
    579589    ASSERT(is<AccessibilityObject>(newChild));
    580590    if (!is<AccessibilityObject>(newChild))
     
    601611        }
    602612    }
    603    
     613
     614    auto* displayContentsParent = child->displayContentsParent();
     615    // To avoid double-inserting a child of a `display: contents` element, only insert if `this` is the rightful parent.
     616    if (displayContentsParent && displayContentsParent != this)
     617        return;
     618
    604619    auto thisAncestorFlags = computeAncestorFlags();
    605620    child->initializeAncestorFlags(thisAncestorFlags);
     
    626641        // Table component child-parent relationships often don't line up properly, hence the need for methods
    627642        // like parentTable() and parentRow(). Exclude them from this ASSERT.
    628         ASSERT((!isTableComponent(*child) && !isTableComponent(*this)) ? child->parentObject() == this : true);
     643        ASSERT(isTableComponent(*child) || isTableComponent(*this) || child->parentObject() == this);
    629644        m_children.insert(index, child);
    630645    }
  • trunk/Source/WebCore/accessibility/AccessibilityObject.h

    r291237 r291570  
    374374    AccessibilityObject* previousSiblingUnignored(int limit) const override;
    375375    AccessibilityObject* parentObject() const override { return nullptr; }
     376    AccessibilityObject* displayContentsParent() const;
    376377    AXCoreObject* parentObjectUnignored() const override;
    377378    AccessibilityObject* parentObjectIfExists() const override { return nullptr; }
  • trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp

    r291501 r291570  
    492492        return cache->get(&m_renderer->view().frameView());
    493493
     494    if (auto* displayContentsParent = this->displayContentsParent())
     495        return displayContentsParent;
     496
    494497    return cache->get(renderParentObject());
    495498}
     
    497500AccessibilityObject* AccessibilityRenderObject::parentObject() const
    498501{
     502    if (auto* displayContentsParent = this->displayContentsParent())
     503        return displayContentsParent;
     504
    499505    if (!m_renderer)
    500506        return nullptr;
     
    509515            return parent;
    510516    }
    511    
     517
    512518    AXObjectCache* cache = axObjectCache();
    513519    if (!cache)
    514520        return nullptr;
    515    
    516     RenderObject* parentObj = renderParentObject();
    517     if (parentObj)
    518         return cache->getOrCreate(parentObj);
     521
     522    if (auto* parentObject = renderParentObject())
     523        return cache->getOrCreate(parentObject);
    519524   
    520525    // WebArea's parent should be the scroll view containing it.
     
    538543#endif
    539544
    540     return AccessibilityNodeObject::parentObjectUnignored();
     545    return AccessibilityObject::parentObjectUnignored();
    541546}
    542547
     
    31993204#endif
    32003205
    3201 // Hidden children are those that are not rendered or visible, but are specifically marked as aria-hidden=false,
    3202 // meaning that they should be exposed to the AX hierarchy.
    3203 void AccessibilityRenderObject::addHiddenChildren()
     3206// Some elements don't have an associated render object, meaning they won't be picked up by a walk of the render tree.
     3207// For example, nodes that are `aria-hidden="false"` and `hidden`, or elements with `display: contents`.
     3208// This function will find and add these elements to the AX tree.
     3209void AccessibilityRenderObject::addNodeOnlyChildren()
    32043210{
    32053211    Node* node = this->node();
    32063212    if (!node)
    32073213        return;
    3208    
    3209     // First do a quick run through to determine if we have any hidden nodes (most often we will not).
    3210     // If we do have hidden nodes, we need to determine where to insert them so they match DOM order as close as possible.
    3211     bool shouldInsertHiddenNodes = false;
     3214
     3215    auto nodeHasDisplayContents = [] (Node& node) {
     3216        return is<Element>(node) && downcast<Element>(node).hasDisplayContents();
     3217    };
     3218    // First do a quick run through to determine if we have any interesting nodes (most often we will not).
     3219    // If we do have any interesting nodes, we need to determine where to insert them so they match DOM order as close as possible.
     3220    bool hasNodeOnlyChildren = false;
    32123221    for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
    3213         if (!child->renderer() && isNodeAriaVisible(child)) {
    3214             shouldInsertHiddenNodes = true;
     3222        if (child->renderer())
     3223            continue;
     3224
     3225        if (nodeHasDisplayContents(*child) || isNodeAriaVisible(child)) {
     3226            hasNodeOnlyChildren = true;
    32153227            break;
    32163228        }
    32173229    }
    32183230   
    3219     if (!shouldInsertHiddenNodes)
     3231    if (!hasNodeOnlyChildren)
    32203232        return;
    32213233   
    32223234    // Iterate through all of the children, including those that may have already been added, and
    3223     // try to insert hidden nodes in the correct place in the DOM order.
     3235    // try to insert the nodes in the correct place in the DOM order.
    32243236    unsigned insertionIndex = 0;
    32253237    for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
     
    32403252        }
    32413253
    3242         if (!isNodeAriaVisible(child))
     3254        if (!nodeHasDisplayContents(*child) && !isNodeAriaVisible(child))
    32433255            continue;
    32443256       
     
    33123324        addChildIfNeeded(*object);
    33133325
    3314     m_subtreeDirty = false;
    3315    
    3316     addHiddenChildren();
     3326    addNodeOnlyChildren();
    33173327    addAttachmentChildren();
    33183328    addImageMapChildren();
     
    33233333    addListItemMarker();
    33243334#endif
    3325 
    33263335#if PLATFORM(COCOA)
    33273336    updateAttachmentViewParents();
    33283337#endif
    3329    
     3338
     3339    m_subtreeDirty = false;
    33303340    updateRoleAfterChildrenCreation();
    33313341}
  • trunk/Source/WebCore/accessibility/AccessibilityRenderObject.h

    r290553 r291570  
    249249    bool supportsPath() const override;
    250250
    251     void addHiddenChildren();
     251    void addNodeOnlyChildren();
    252252    void addTextFieldChildren();
    253253    void addImageMapChildren();
Note: See TracChangeset for help on using the changeset viewer.