Title: [271796] trunk
Revision
271796
Author
andresg...@apple.com
Date
2021-01-25 08:52:52 -0800 (Mon, 25 Jan 2021)

Log Message

AX: @alt and bounds ignored when using img[src] points to an inaccessible SVG
https://bugs.webkit.org/show_bug.cgi?id=160705
<rdar://problem/27771579>

Reviewed by Chris Fleizach and Darin Adler.

Source/WebCore:

Tests: accessibility/img-with-svg-source.html
       accessibility/ios-simulator/img-with-svg-source.html

The problem was caused by AccessibilityRenderObject::determineAccessibilityRole
that was returning AccessibilityRole::SVGRoot for all images with a remote
SVG source, regardless whether the SVG hierarchy contained some accessibility
data or not. This resulted in VoiceOver reading the image like an empty
group on Mac, or completely ignoring the image on iOS.
The solution in this patch is to only return AccessibilityRole::SVGRoot
if the SVG has some accessibility conveyable data. Added the method
AccessibilitySVGRoot::hasAccessibleContent for this purpose.

* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::determineAccessibilityRole):
(WebCore::AccessibilityRenderObject::remoteSVGRootElement const):
Comment was missplaced, moved it to the right place.
(WebCore::AccessibilityRenderObject::addRemoteSVGChildren):
* accessibility/AccessibilitySVGRoot.cpp:
(WebCore::AccessibilitySVGRoot::hasAccessibleContent const):
* accessibility/AccessibilitySVGRoot.h:

LayoutTests:

* accessibility/img-with-svg-source-expected.txt: Added.
* accessibility/img-with-svg-source.html: Added.
* accessibility/ios-simulator/img-with-svg-source-expected.txt: Added.
* accessibility/ios-simulator/img-with-svg-source.html: Added.
* accessibility/svg-shape-labelled-expected.txt:
* accessibility/svg-shape-labelled.html:
Removed the <img> test cases since they are covered correctly in the new
test img-with-svg-source.html.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (271795 => 271796)


--- trunk/LayoutTests/ChangeLog	2021-01-25 16:31:48 UTC (rev 271795)
+++ trunk/LayoutTests/ChangeLog	2021-01-25 16:52:52 UTC (rev 271796)
@@ -1,3 +1,20 @@
+2021-01-25  Andres Gonzalez  <andresg...@apple.com>
+
+        AX: @alt and bounds ignored when using img[src] points to an inaccessible SVG
+        https://bugs.webkit.org/show_bug.cgi?id=160705
+        <rdar://problem/27771579>
+
+        Reviewed by Chris Fleizach and Darin Adler.
+
+        * accessibility/img-with-svg-source-expected.txt: Added.
+        * accessibility/img-with-svg-source.html: Added.
+        * accessibility/ios-simulator/img-with-svg-source-expected.txt: Added.
+        * accessibility/ios-simulator/img-with-svg-source.html: Added.
+        * accessibility/svg-shape-labelled-expected.txt:
+        * accessibility/svg-shape-labelled.html:
+        Removed the <img> test cases since they are covered correctly in the new
+        test img-with-svg-source.html.
+
 2021-01-25  Sihui Liu  <sihui_...@appe.com>
 
         Nullptr dereference in SpeechRecognition::stop()

Added: trunk/LayoutTests/accessibility/img-with-svg-source-expected.txt (0 => 271796)


--- trunk/LayoutTests/accessibility/img-with-svg-source-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/accessibility/img-with-svg-source-expected.txt	2021-01-25 16:52:52 UTC (rev 271796)
@@ -0,0 +1,28 @@
+
+This tests that images with SVG source are indeed exposed as images and not as SVG groups, if the SVG source is not accessible.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS image.role is 'AXRole: AXImage'
+AXDescription:
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 2. svg image with alt text
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 3. svg image with role img
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 4. svg image in an anchor
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 5. svg image with role img in an anchor
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 6. svg image with aria label
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 7. svg image with role img and aria label
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 8. svg image with size set
+PASS image.role is 'AXRole: AXImage'
+AXDescription: 9. svg image with role img and size set
+

Added: trunk/LayoutTests/accessibility/img-with-svg-source.html (0 => 271796)


--- trunk/LayoutTests/accessibility/img-with-svg-source.html	                        (rev 0)
+++ trunk/LayoutTests/accessibility/img-with-svg-source.html	2021-01-25 16:52:52 UTC (rev 271796)
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<style>img {background-color: #000;}</style>
+<script src=""
+<script src=""
+</head>
+
+<!-- This test must run when all remote resources (SVG images) are loaded.
+    Thus add an onload event listener to body and run the test there. -->
+<body _onload_="runTest()">
+
+<img id="image1" src=""
+<img id="image2" src="" alt="2. svg image with alt text">
+<img id="image3" role="img" src="" alt="3. svg image with role img" and alt text">
+<a href="" id="image4" src="" alt="4. svg image in an anchor"></a>
+<a href="" id="image5" role="img" src="" alt="5. svg image with role img in an anchor"></a>
+<img id="image6" src="" aria-label="6. svg image with aria label">
+<img id="image7" role="img" src="" aria-label="7. svg image with role img and aria label">
+<img id="image8" src="" alt="8. svg image with size set" style="height: 200px; width: 200px;">
+<img id="image9" role="img" src="" alt="9. svg image with role img and size set" style="height: 200px; width: 200px;">
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+    description("This tests that images with SVG source are indeed exposed as images and not as SVG groups, if the SVG source is not accessible.");
+
+    function runTest() {
+        if (window.accessibilityController) {
+            for (i = 1; i < 10; ++i) {
+                image = accessibilityController.accessibleElementById("image" + i);
+                shouldBe("image.role", "'AXRole: AXImage'");
+                debug(image.description);
+            }
+        }
+    }
+</script>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/accessibility/ios-simulator/img-with-svg-source-expected.txt (0 => 271796)


--- trunk/LayoutTests/accessibility/ios-simulator/img-with-svg-source-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/img-with-svg-source-expected.txt	2021-01-25 16:52:52 UTC (rev 271796)
@@ -0,0 +1,19 @@
+
+This tests that images with SVG source are indeed exposed as images and not as SVG groups, if the SVG source is not accessible.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS image.traits is pngImage1.traits
+PASS image.traits is pngImage1.traits
+PASS image.traits is pngImage1.traits
+PASS image.traits is pngImage2.traits
+PASS image.traits is pngImage2.traits
+PASS image.traits is pngImage1.traits
+PASS image.traits is pngImage1.traits
+PASS image.traits is pngImage1.traits
+PASS image.traits is pngImage1.traits
+

Added: trunk/LayoutTests/accessibility/ios-simulator/img-with-svg-source.html (0 => 271796)


--- trunk/LayoutTests/accessibility/ios-simulator/img-with-svg-source.html	                        (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/img-with-svg-source.html	2021-01-25 16:52:52 UTC (rev 271796)
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<style>img {background-color: #000;}</style>
+<script src=""
+<script src=""
+</head>
+
+<!-- This test must run when all remote resources (SVG images) are loaded.
+    Thus add an onload event listener to body and run the test there. -->
+<body _onload_="runTest()">
+
+<!-- Used as baseline for an image traits. -->
+<img id="pngImage1" src="" alt="1. png image">
+<!-- Used as baseline for an image in an anchor traits. -->
+<a href="" id="pngImage2" src="" alt="2. png image"></a>
+
+<img id="image1" src=""
+<img id="image2" src="" alt="2. svg image with alt text">
+<img id="image3" role="img" src="" alt="3. svg image with role img" and alt text">
+<a href="" id="image4" src="" alt="4. svg image in an anchor"></a>
+<a href="" id="image5" role="img" src="" alt="5. svg image with role img in an anchor"></a>
+<img id="image6" src="" aria-label="6. svg image with aria label">
+<img id="image7" role="img" src="" aria-label="7. svg image with role img and aria label">
+<img id="image8" src="" alt="8. svg image with size set" style="height: 200px; width: 200px;">
+<img id="image9" role="img" src="" alt="9. svg image with role img and size set" style="height: 200px; width: 200px;">
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+    description("This tests that images with SVG source are indeed exposed as images and not as SVG groups, if the SVG source is not accessible.");
+
+    function runTest() {
+        if (window.accessibilityController) {
+            pngImage1 = accessibilityController.accessibleElementById("pngImage1");
+            pngImage2 = accessibilityController.accessibleElementById("pngImage2");
+
+            for (i = 1; i < 10; ++i) {
+                image = accessibilityController.accessibleElementById("image" + i);
+                if (i < 4 || i > 5)
+                    shouldBe("image.traits", "pngImage1.traits");
+                else
+                    shouldBe("image.traits", "pngImage2.traits");
+            }
+        }
+    }
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/accessibility/svg-shape-labelled-expected.txt (271795 => 271796)


--- trunk/LayoutTests/accessibility/svg-shape-labelled-expected.txt	2021-01-25 16:31:48 UTC (rev 271795)
+++ trunk/LayoutTests/accessibility/svg-shape-labelled-expected.txt	2021-01-25 16:52:52 UTC (rev 271796)
@@ -7,9 +7,6 @@
 circle1: AXRole: AXImage
 circle2: AXRole: AXImage
 circle3: Element not exposed
-PASS !image1 is true
-PASS image2.role is 'AXRole: AXImage'
-PASS image3.role is 'AXRole: AXImage'
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/accessibility/svg-shape-labelled.html (271795 => 271796)


--- trunk/LayoutTests/accessibility/svg-shape-labelled.html	2021-01-25 16:31:48 UTC (rev 271795)
+++ trunk/LayoutTests/accessibility/svg-shape-labelled.html	2021-01-25 16:52:52 UTC (rev 271796)
@@ -19,17 +19,10 @@
     <circle id="circle3" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
 </svg>
 
-<img id="test1" src=""
-
-<img id="test2" src="" alt="hello" />
-
-<img id="test3" alt="Apple logo" src="" />
-
 <p id="description"></p>
 <div id="console"></div>
 
 <script>
-
     description("This tests that SVG shapes are exposed to ax tree as images if there are labels describing them.");
 
     if (window.accessibilityController) {
@@ -41,19 +34,8 @@
 
         var circle3 = accessibilityController.accessibleElementById("circle3");
         debug("circle3: " + (circle3 ? circle3.role : "Element not exposed"));
-
-        var image1 = accessibilityController.accessibleElementById("test1");
-        shouldBeTrue("!image1");
-
-        var image2 = accessibilityController.accessibleElementById("test2");
-        shouldBe("image2.role", "'AXRole: AXImage'");
-
-        var image3 = accessibilityController.accessibleElementById("test3");
-        shouldBe("image3.role", "'AXRole: AXImage'");
     }
-
 </script>
-
 <script src=""
 </body>
 </html>

Modified: trunk/Source/WebCore/ChangeLog (271795 => 271796)


--- trunk/Source/WebCore/ChangeLog	2021-01-25 16:31:48 UTC (rev 271795)
+++ trunk/Source/WebCore/ChangeLog	2021-01-25 16:52:52 UTC (rev 271796)
@@ -1,3 +1,32 @@
+2021-01-25  Andres Gonzalez  <andresg...@apple.com>
+
+        AX: @alt and bounds ignored when using img[src] points to an inaccessible SVG
+        https://bugs.webkit.org/show_bug.cgi?id=160705
+        <rdar://problem/27771579>
+
+        Reviewed by Chris Fleizach and Darin Adler.
+
+        Tests: accessibility/img-with-svg-source.html
+               accessibility/ios-simulator/img-with-svg-source.html
+
+        The problem was caused by AccessibilityRenderObject::determineAccessibilityRole
+        that was returning AccessibilityRole::SVGRoot for all images with a remote
+        SVG source, regardless whether the SVG hierarchy contained some accessibility
+        data or not. This resulted in VoiceOver reading the image like an empty
+        group on Mac, or completely ignoring the image on iOS.
+        The solution in this patch is to only return AccessibilityRole::SVGRoot
+        if the SVG has some accessibility conveyable data. Added the method
+        AccessibilitySVGRoot::hasAccessibleContent for this purpose.
+
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::determineAccessibilityRole):
+        (WebCore::AccessibilityRenderObject::remoteSVGRootElement const):
+        Comment was missplaced, moved it to the right place.
+        (WebCore::AccessibilityRenderObject::addRemoteSVGChildren):
+        * accessibility/AccessibilitySVGRoot.cpp:
+        (WebCore::AccessibilitySVGRoot::hasAccessibleContent const):
+        * accessibility/AccessibilitySVGRoot.h:
+
 2021-01-25  Sihui Liu  <sihui_...@appe.com>
 
         Nullptr dereference in SpeechRecognition::stop()

Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (271795 => 271796)


--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp	2021-01-25 16:31:48 UTC (rev 271795)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp	2021-01-25 16:52:52 UTC (rev 271796)
@@ -2797,8 +2797,12 @@
     if (cssBox && cssBox->isImage()) {
         if (is<HTMLInputElement>(node))
             return hasPopup() ? AccessibilityRole::PopUpButton : AccessibilityRole::Button;
-        if (isSVGImage())
-            return AccessibilityRole::SVGRoot;
+
+        if (auto* svgRoot = remoteSVGRootElement(Create)) {
+            if (svgRoot->hasAccessibleContent())
+                return AccessibilityRole::SVGRoot;
+        }
+
         return AccessibilityRole::Image;
     }
     
@@ -3250,8 +3254,6 @@
         return nullptr;
     AccessibilityObject* rootSVGObject = createIfNecessary == Create ? cache->getOrCreate(rendererRoot) : cache->get(rendererRoot);
 
-    // In order to connect the AX hierarchy from the SVG root element from the loaded resource
-    // the parent must be set, because there's no other way to get back to who created the image.
     ASSERT(!createIfNecessary || rootSVGObject);
     if (!is<AccessibilitySVGRoot>(rootSVGObject))
         return nullptr;
@@ -3265,6 +3267,8 @@
     if (!root)
         return;
     
+    // In order to connect the AX hierarchy from the SVG root element from the loaded resource
+    // the parent must be set, because there's no other way to get back to who created the image.
     root->setParent(this);
     
     if (root->accessibilityIsIgnored()) {

Modified: trunk/Source/WebCore/accessibility/AccessibilitySVGRoot.cpp (271795 => 271796)


--- trunk/Source/WebCore/accessibility/AccessibilitySVGRoot.cpp	2021-01-25 16:31:48 UTC (rev 271795)
+++ trunk/Source/WebCore/accessibility/AccessibilitySVGRoot.cpp	2021-01-25 16:52:52 UTC (rev 271796)
@@ -68,5 +68,44 @@
 
     return AccessibilityRole::Group;
 }
-    
+
+bool AccessibilitySVGRoot::hasAccessibleContent() const
+{
+    auto* rootElement = this->element();
+    if (!rootElement)
+        return false;
+
+    auto isAccessibleSVGElement = [] (const Element& element) -> bool {
+        if (!is<SVGElement>(element))
+            return false;
+
+        // The presence of an SVGTitle or SVGDesc element is enough to deem the SVG hierarchy as accessible.
+        if (is<SVGTitleElement>(element)
+            || is<SVGDescElement>(element))
+            return true;
+
+        // Text content is accessible.
+        if (downcast<SVGElement>(element).isTextContent())
+            return true;
+
+        // If the role or aria-label attributes are specified, this is accessible.
+        if (!element.attributeWithoutSynchronization(roleAttr).isEmpty()
+            || !element.attributeWithoutSynchronization(aria_labelAttr).isEmpty())
+            return true;
+
+        return false;
+    };
+
+    if (isAccessibleSVGElement(*rootElement))
+        return true;
+
+    // This SVG hierarchy is accessible if any of its descendants is accessible.
+    for (const auto& descendant : descendantsOfType<SVGElement>(*rootElement)) {
+        if (isAccessibleSVGElement(descendant))
+            return true;
+    }
+
+    return false;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/accessibility/AccessibilitySVGRoot.h (271795 => 271796)


--- trunk/Source/WebCore/accessibility/AccessibilitySVGRoot.h	2021-01-25 16:31:48 UTC (rev 271795)
+++ trunk/Source/WebCore/accessibility/AccessibilitySVGRoot.h	2021-01-25 16:52:52 UTC (rev 271796)
@@ -37,19 +37,19 @@
 public:
     static Ref<AccessibilitySVGRoot> create(RenderObject*);
     virtual ~AccessibilitySVGRoot();
-    
+
     void setParent(AccessibilityRenderObject*);
-
+    bool hasAccessibleContent() const;
 private:
     explicit AccessibilitySVGRoot(RenderObject*);
-    
+
     AccessibilityObject* parentObject() const override;
     bool isAccessibilitySVGRoot() const override { return true; }
+    AccessibilityRole roleValue() const override;
 
     WeakPtr<AccessibilityRenderObject> m_parent;
-    AccessibilityRole roleValue() const override;
 };
-    
+
 } // namespace WebCore 
 
 SPECIALIZE_TYPE_TRAITS_ACCESSIBILITY(AccessibilitySVGRoot, isAccessibilitySVGRoot())
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to