Bug 139142 - AX: display:none content exposed to accessibility when aria-hidden is toggled on ancestor element
Summary: AX: display:none content exposed to accessibility when aria-hidden is toggled...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Accessibility (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: chris fleizach
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2014-12-01 12:40 PST by James Craig
Modified: 2015-05-26 17:55 PDT (History)
9 users (show)

See Also:


Attachments
test case (6.23 KB, text/html)
2014-12-01 12:40 PST, James Craig
no flags Details
patch (9.09 KB, patch)
2015-05-21 17:18 PDT, chris fleizach
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description James Craig 2014-12-01 12:40:08 PST
Created attachment 242330 [details]
test case

AX: display:none content exposed to accessibility when aria-hidden is toggled on ancestor element

Repro: 

1. Open test case.
2. Navigate to the list with VoiceOver and verify there are only two links.
3. Hide and then show the section.
4. Navigate to the list with VoiceOver and notice there are now three links.

aria-hidden=false should only override display:none on the current element, not on descendant elements.

<rdar://problem/19093687>
Comment 1 James Craig 2014-12-09 20:07:42 PST
Chris, what do you think of this (proposed) edit to disambiguate the hidden state? I might need to update the test case but I think it's much more clear.

http://rawgit.com/w3c/aria/issue-688/aria/aria.html#aria-hidden
Comment 3 James Craig 2015-03-09 19:42:13 PDT
The important point for this bug is:

- The previous was boolean with false as the default. The new version is true/false/undefined where undefined defers to the renderer. 

WebKit should now check per element:

- If element is rendered and aria-hidden is not true on current element or any ancestor: expose to accessibility API.
- If element is not rendered and aria-hidden=false, walk up the ancestor chain making sure every ancestor element is either rendered or explicitly set as aria-hidden=false. If so, expose the current element to the accessibility API.
- Text nodes should always inherit their parent element's level of exposure.
Comment 4 chris fleizach 2015-05-21 17:18:44 PDT
Created attachment 253559 [details]
patch
Comment 5 Darin Adler 2015-05-26 11:38:10 PDT
Comment on attachment 253559 [details]
patch

View in context: https://bugs.webkit.org/attachment.cgi?id=253559&action=review

> Source/WebCore/accessibility/AXObjectCache.cpp:1310
> +    bool requiresAriaHiddenFalse = !node->renderer();

Checking the renderer for null is only safe if we know that style is up to date. The rest of what this does is DOM-only and does not depend on style/renderers. Does the caller update style?

> Source/WebCore/accessibility/AXObjectCache.cpp:1320
> +            if (!testNode->renderer() && !equalIgnoringCase(ariaHiddenValue, "false"))
> +                return false;
> +            if (equalIgnoringCase(ariaHiddenValue, "false"))
> +                ariaHiddenFalsePresent = true;

It’s not great to call ariaHiddenFalsePresent twice. Should refactor and only do it once.

> Source/WebCore/accessibility/AXObjectCache.cpp:1327
> +    if (requiresAriaHiddenFalse && !ariaHiddenFalsePresent)
> +        return false;
> +    
> +    return true;

If this is the clearest way to write it, I am OK, but it could also be:

    return !requiresAriaHiddenFalse || ariaHiddenFalsePresent;
Comment 6 chris fleizach 2015-05-26 17:38:28 PDT
(In reply to comment #5)
> Comment on attachment 253559 [details]
> patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=253559&action=review
> 
> > Source/WebCore/accessibility/AXObjectCache.cpp:1310
> > +    bool requiresAriaHiddenFalse = !node->renderer();
> 
> Checking the renderer for null is only safe if we know that style is up to
> date. The rest of what this does is DOM-only and does not depend on
> style/renderers. Does the caller update style?
> 

Yes, it looks like the callers of this method are used when adding children, where we always update the style first

> > Source/WebCore/accessibility/AXObjectCache.cpp:1320
> > +            if (!testNode->renderer() && !equalIgnoringCase(ariaHiddenValue, "false"))
> > +                return false;
> > +            if (equalIgnoringCase(ariaHiddenValue, "false"))
> > +                ariaHiddenFalsePresent = true;
> 
> It’s not great to call ariaHiddenFalsePresent twice. Should refactor and
> only do it once.
> 

Ok

> > Source/WebCore/accessibility/AXObjectCache.cpp:1327
> > +    if (requiresAriaHiddenFalse && !ariaHiddenFalsePresent)
> > +        return false;
> > +    
> > +    return true;
> 
> If this is the clearest way to write it, I am OK, but it could also be:
> 
>     return !requiresAriaHiddenFalse || ariaHiddenFalsePresent;

Good idea

Thanks
Comment 7 chris fleizach 2015-05-26 17:53:32 PDT
http://trac.webkit.org/changeset/184890
Comment 8 chris fleizach 2015-05-26 17:55:26 PDT
http://trac.webkit.org/changeset/184891