Title: [228827] trunk
Revision
228827
Author
n_w...@apple.com
Date
2018-02-20 11:02:25 -0800 (Tue, 20 Feb 2018)

Log Message

AX: AOM: Dispatch accessibleclick event
https://bugs.webkit.org/show_bug.cgi?id=180898
<rdar://problem/36086710>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Accessibility events.
Spec: https://wicg.github.io/aom/spec/phase2.html

This patch allows developers to register event handlers on Elements
for custom accessibility events.

Accessibility events go through a capturing and bubbling phase just
like DOM events, but in the accessibility tree.

Implemented "accessibleclick" event.

Test: accessibility/mac/AOM-events.html

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::press):
(WebCore::AccessibilityObject::dispatchAccessibilityEvent):
* accessibility/AccessibilityObject.h:
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(-[WebAccessibilityObjectWrapper accessibilityPerformAction:]):
* dom/Element.idl:
* dom/EventDispatcher.cpp:
(WebCore::dispatchEventWithType):
(WebCore::EventDispatcher::dispatchEvent):
* dom/EventDispatcher.h:
* dom/EventNames.h:
* dom/EventPath.cpp:
(WebCore::EventPath::EventPath):
* dom/EventPath.h:

Tools:

* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
(WTR::AccessibilityUIElement::syncPress):
* WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::AccessibilityUIElement::syncPress):

LayoutTests:

* accessibility/mac/AOM-events-expected.txt: Added.
* accessibility/mac/AOM-events.html: Added.
* js/dom/dom-static-property-for-in-iteration-expected.txt:
* platform/mac-wk1/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (228826 => 228827)


--- trunk/LayoutTests/ChangeLog	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/LayoutTests/ChangeLog	2018-02-20 19:02:25 UTC (rev 228827)
@@ -1,3 +1,16 @@
+2018-02-20  Nan Wang  <n_w...@apple.com>
+
+        AX: AOM: Dispatch accessibleclick event
+        https://bugs.webkit.org/show_bug.cgi?id=180898
+        <rdar://problem/36086710>
+
+        Reviewed by Ryosuke Niwa.
+
+        * accessibility/mac/AOM-events-expected.txt: Added.
+        * accessibility/mac/AOM-events.html: Added.
+        * js/dom/dom-static-property-for-in-iteration-expected.txt:
+        * platform/mac-wk1/TestExpectations:
+
 2018-02-19  Dean Jackson  <d...@apple.com>
 
         Handle all writing-modes in downcast

Added: trunk/LayoutTests/accessibility/mac/AOM-events-expected.txt (0 => 228827)


--- trunk/LayoutTests/accessibility/mac/AOM-events-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/accessibility/mac/AOM-events-expected.txt	2018-02-20 19:02:25 UTC (rev 228827)
@@ -0,0 +1,28 @@
+Click Click
+Click
+
+Click
+This tests accessibility-specific events.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+onaccessibleclick support
+PASS receivedAXEvent is true
+PASS receivedFallbackEvent is true
+
+Test preventDefault
+PASS receivedAXEvent is true
+PASS receivedFallbackEvent is false
+
+Test event bubbling
+PASS receivedAXEvent is true
+
+Test event capturing and bubbling
+AX capture UL
+AX capture LI
+AX main event listener BUTTON
+AX bubble LI
+AX bubble UL
+

Added: trunk/LayoutTests/accessibility/mac/AOM-events.html (0 => 228827)


--- trunk/LayoutTests/accessibility/mac/AOM-events.html	                        (rev 0)
+++ trunk/LayoutTests/accessibility/mac/AOM-events.html	2018-02-20 19:02:25 UTC (rev 228827)
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+
+<button id="button1">Click</button>
+<button id="button2">Click</button>
+<p id="p1">
+<button id="button3">Click</button>
+</p>
+
+<ul id="ul">
+<li id="li">
+<button id="button4">Click</button>
+</li>
+</ul>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+    description("This tests accessibility-specific events.");
+    if (window.accessibilityController) {
+        var node;
+        var axNode;
+        var receivedAXEvent;
+        var receivedFallbackEvent;
+
+        testAccessibleClick();
+        testPreventDefault();
+        testEventBubbling();
+        testEventCapturingAndBubbling();
+    }
+
+    function testAccessibleClick() {
+        debug("\nonaccessibleclick support");
+        node = document.getElementById("button1");
+        axNode = accessibilityController.accessibleElementById("button1");
+
+        receivedAXEvent = false;
+        receivedFallbackEvent = false;
+        node._onaccessibleclick_ = function() {
+            receivedAXEvent = true;
+        };
+        node._onclick_ = function() {
+            receivedFallbackEvent = true;
+        };
+        axNode.syncPress();
+        shouldBeTrue("receivedAXEvent");
+        shouldBeTrue("receivedFallbackEvent");
+    }
+    
+    function testPreventDefault() {
+        debug("\nTest preventDefault");
+        node = document.getElementById("button2");
+        axNode = accessibilityController.accessibleElementById("button2");
+        
+        receivedAXEvent = false;
+        receivedFallbackEvent = false;
+        node._onaccessibleclick_ = function(evt) {
+            receivedAXEvent = true;
+            evt.preventDefault();
+        };
+        node._onclick_ = function() {
+            receivedFallbackEvent = true;
+        };
+        axNode.syncPress();
+        shouldBeTrue("receivedAXEvent");
+        shouldBeFalse("receivedFallbackEvent");
+    }
+    
+    function testEventBubbling() {
+        debug("\nTest event bubbling");
+        node = document.getElementById("p1");
+        axNode = accessibilityController.accessibleElementById("button3");
+
+        node._onaccessibleclick_ = function() {
+            receivedAXEvent = true;
+        };
+        axNode.syncPress();
+        shouldBeTrue("receivedAXEvent");
+    }
+
+    function testEventCapturingAndBubbling() {
+        debug("\nTest event capturing and bubbling");
+        var ul = document.getElementById("ul");
+        var li = document.getElementById("li");
+        var button = document.getElementById("button4");
+        axNode = accessibilityController.accessibleElementById("button4");
+        
+        var seq = [];
+        
+        // Add event listeners to each layer
+        ul.addEventListener("accessibleclick", function() {
+            seq.push("AX capture UL");
+        }, true);
+        ul.addEventListener("accessibleclick", function() {
+            seq.push("AX bubble UL");
+        }, false);
+        li.addEventListener("accessibleclick", function() {
+            seq.push("AX capture LI");
+        }, true);
+        li.addEventListener("accessibleclick", function() {
+            seq.push("AX bubble LI");
+        }, false);
+        button.addEventListener("accessibleclick", function() {
+            seq.push("AX main event listener BUTTON");
+        }, false);
+
+        axNode.syncPress();
+        seq.forEach(function (entry) {
+            debug(entry);
+        });
+    }
+
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt (228826 => 228827)


--- trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt	2018-02-20 19:02:25 UTC (rev 228827)
@@ -134,6 +134,7 @@
 PASS a["clientHeight"] is 0
 PASS a["innerHTML"] is nerget
 PASS a["outerHTML"] is <a id="foo" href=""
+PASS a["onaccessibleclick"] is null
 PASS a["oncopy"] is null
 PASS a["oncut"] is null
 PASS a["onpaste"] is null

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (228826 => 228827)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2018-02-20 19:02:25 UTC (rev 228827)
@@ -486,6 +486,8 @@
 
 webkit.org/b/172044 [ Debug ] imported/w3c/web-platform-tests/IndexedDB/open-request-queue.html [ Pass Timeout ]
 
+webkit.org/b/180898 accessibility/mac/AOM-events.html [ Skip ]
+
 # User-installed fonts test infrastructure is not present in WK1
 webkit.org/b/180062 fast/text/user-installed-fonts [ ImageOnlyFailure ]
 

Modified: trunk/Source/WebCore/ChangeLog (228826 => 228827)


--- trunk/Source/WebCore/ChangeLog	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/ChangeLog	2018-02-20 19:02:25 UTC (rev 228827)
@@ -1,3 +1,40 @@
+2018-02-20  Nan Wang  <n_w...@apple.com>
+
+        AX: AOM: Dispatch accessibleclick event
+        https://bugs.webkit.org/show_bug.cgi?id=180898
+        <rdar://problem/36086710>
+
+        Reviewed by Ryosuke Niwa.
+
+        Accessibility events.
+        Spec: https://wicg.github.io/aom/spec/phase2.html
+
+        This patch allows developers to register event handlers on Elements
+        for custom accessibility events.
+
+        Accessibility events go through a capturing and bubbling phase just
+        like DOM events, but in the accessibility tree.
+
+        Implemented "accessibleclick" event.
+
+        Test: accessibility/mac/AOM-events.html
+
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::press):
+        (WebCore::AccessibilityObject::dispatchAccessibilityEvent):
+        * accessibility/AccessibilityObject.h:
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+        (-[WebAccessibilityObjectWrapper accessibilityPerformAction:]):
+        * dom/Element.idl:
+        * dom/EventDispatcher.cpp:
+        (WebCore::dispatchEventWithType):
+        (WebCore::EventDispatcher::dispatchEvent):
+        * dom/EventDispatcher.h:
+        * dom/EventNames.h:
+        * dom/EventPath.cpp:
+        (WebCore::EventPath::EventPath):
+        * dom/EventPath.h:
+
 2018-02-20  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [iOS 11.3 Beta] Can't copy a URL from Safari and paste it into the Gmail app

Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (228826 => 228827)


--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2018-02-20 19:02:25 UTC (rev 228827)
@@ -37,6 +37,8 @@
 #include "Editing.h"
 #include "Editor.h"
 #include "ElementIterator.h"
+#include "Event.h"
+#include "EventDispatcher.h"
 #include "EventHandler.h"
 #include "FloatRect.h"
 #include "FocusController.h"
@@ -991,6 +993,16 @@
     if (hitTestElement && hitTestElement->isDescendantOf(*pressElement))
         pressElement = hitTestElement;
     
+    // dispatch accessibleclick event
+    if (auto* cache = axObjectCache()) {
+        if (auto* pressObject = cache->getOrCreate(pressElement)) {
+            auto event = Event::create(eventNames().accessibleclickEvent, true, true);
+            pressObject->dispatchAccessibilityEvent(event);
+            if (event->defaultPrevented())
+                return true;
+        }
+    }
+    
     UserGestureIndicator gestureIndicator(ProcessingUserGesture, document);
     
     bool dispatchedTouchEvent = false;
@@ -2141,6 +2153,17 @@
     return nullAtom();
 }
 
+void AccessibilityObject::dispatchAccessibilityEvent(Event& event)
+{
+    Vector<Element*> eventPath;
+    for (auto* parentObject = this; parentObject; parentObject = parentObject->parentObject()) {
+        if (auto* parentElement = parentObject->element())
+            eventPath.append(parentElement);
+    }
+    
+    EventDispatcher::dispatchEvent(eventPath, event);
+}
+
 // Lacking concrete evidence of orientation, horizontal means width > height. vertical is height > width;
 AccessibilityOrientation AccessibilityObject::orientation() const
 {

Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (228826 => 228827)


--- trunk/Source/WebCore/accessibility/AccessibilityObject.h	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h	2018-02-20 19:02:25 UTC (rev 228827)
@@ -90,8 +90,6 @@
 class ScrollView;
 class Widget;
 
-enum class AXPropertyName;
-
 typedef unsigned AXID;
 
 enum class AccessibilityRole {
@@ -896,15 +894,9 @@
     bool hasAttribute(const QualifiedName&) const;
     const AtomicString& getAttribute(const QualifiedName&) const;
     bool hasTagName(const QualifiedName&) const;
+    
+    void dispatchAccessibilityEvent(Event&);
 
-    bool hasProperty(AXPropertyName) const;
-    const String stringValueForProperty(AXPropertyName) const;
-    std::optional<bool> boolValueForProperty(AXPropertyName) const;
-    int intValueForProperty(AXPropertyName) const;
-    unsigned unsignedValueForProperty(AXPropertyName) const;
-    double doubleValueForProperty(AXPropertyName) const;
-    Element* elementValueForProperty(AXPropertyName) const;
-
     virtual VisiblePositionRange visiblePositionRange() const { return VisiblePositionRange(); }
     virtual VisiblePositionRange visiblePositionRangeForLine(unsigned) const { return VisiblePositionRange(); }
     

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (228826 => 228827)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2018-02-20 19:02:25 UTC (rev 228827)
@@ -3577,6 +3577,10 @@
     if ([action isEqualToString:NSAccessibilityPressAction])
         [self accessibilityPerformPressAction];
     
+    // Used in layout tests, so that we don't have to wait for the async press action.
+    else if ([action isEqualToString:@"AXSyncPressAction"])
+        [self _accessibilityPerformPressAction];
+    
     else if ([action isEqualToString:NSAccessibilityShowMenuAction])
         [self accessibilityPerformShowMenuAction];
     

Modified: trunk/Source/WebCore/dom/Element.idl (228826 => 228827)


--- trunk/Source/WebCore/dom/Element.idl	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/dom/Element.idl	2018-02-20 19:02:25 UTC (rev 228827)
@@ -140,6 +140,9 @@
 
     // Non standard event handler (https://developer.apple.com/reference/webkitjs/element/1629580-onwebkitplaybacktargetavailabili).
     [NotEnumerable, Conditional=WIRELESS_PLAYBACK_TARGET] attribute EventHandler onwebkitplaybacktargetavailabilitychanged;
+
+    // Accessibility events.
+    [EnabledAtRuntime=AccessibilityObjectModel] attribute EventHandler onaccessibleclick;
 };
 
 dictionary ShadowRootInit {

Modified: trunk/Source/WebCore/dom/EventDispatcher.cpp (228826 => 228827)


--- trunk/Source/WebCore/dom/EventDispatcher.cpp	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/dom/EventDispatcher.cpp	2018-02-20 19:02:25 UTC (rev 228827)
@@ -177,7 +177,8 @@
     }
 }
 
-void EventDispatcher::dispatchEvent(const Vector<EventTarget*>& targets, Event& event)
+template<typename T>
+static void dispatchEventWithType(const Vector<T*>& targets, Event& event)
 {
     ASSERT(targets.size() >= 1);
     ASSERT(*targets.begin());
@@ -190,4 +191,14 @@
     event.resetAfterDispatch();
 }
 
+void EventDispatcher::dispatchEvent(const Vector<EventTarget*>& targets, Event& event)
+{
+    dispatchEventWithType<EventTarget>(targets, event);
 }
+
+void EventDispatcher::dispatchEvent(const Vector<Element*>& targets, Event& event)
+{
+    dispatchEventWithType<Element>(targets, event);
+}
+
+}

Modified: trunk/Source/WebCore/dom/EventDispatcher.h (228826 => 228827)


--- trunk/Source/WebCore/dom/EventDispatcher.h	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/dom/EventDispatcher.h	2018-02-20 19:02:25 UTC (rev 228827)
@@ -24,6 +24,7 @@
 
 namespace WebCore {
 
+class Element;
 class Event;
 class EventTarget;
 class Node;
@@ -32,6 +33,7 @@
 
 void dispatchEvent(Node&, Event&);
 void dispatchEvent(const Vector<EventTarget*>&, Event&);
+void dispatchEvent(const Vector<Element*>&, Event&);
 
 void dispatchScopedEvent(Node&, Event&);
 

Modified: trunk/Source/WebCore/dom/EventNames.h (228826 => 228827)


--- trunk/Source/WebCore/dom/EventNames.h	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/dom/EventNames.h	2018-02-20 19:02:25 UTC (rev 228827)
@@ -45,6 +45,7 @@
     macro(DOMNodeRemovedFromDocument) \
     macro(DOMSubtreeModified) \
     macro(abort) \
+    macro(accessibleclick) \
     macro(activate) \
     macro(active) \
     macro(addsourcebuffer) \

Modified: trunk/Source/WebCore/dom/EventPath.cpp (228826 => 228827)


--- trunk/Source/WebCore/dom/EventPath.cpp	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/dom/EventPath.cpp	2018-02-20 19:02:25 UTC (rev 228827)
@@ -270,6 +270,16 @@
     return path;
 }
 
+EventPath::EventPath(const Vector<Element*>& targets)
+{
+    for (auto* target : targets) {
+        ASSERT(target);
+        Node* origin = *targets.begin();
+        if (!target->isClosedShadowHidden(*origin))
+            m_path.append(std::make_unique<EventContext>(target, target, origin));
+    }
+}
+
 EventPath::EventPath(const Vector<EventTarget*>& targets)
 {
     for (auto* target : targets) {

Modified: trunk/Source/WebCore/dom/EventPath.h (228826 => 228827)


--- trunk/Source/WebCore/dom/EventPath.h	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Source/WebCore/dom/EventPath.h	2018-02-20 19:02:25 UTC (rev 228827)
@@ -33,6 +33,7 @@
 public:
     EventPath(Node& origin, Event&);
     explicit EventPath(const Vector<EventTarget*>&);
+    explicit EventPath(const Vector<Element*>&);
 
     bool isEmpty() const { return m_path.isEmpty(); }
     size_t size() const { return m_path.size(); }

Modified: trunk/Tools/ChangeLog (228826 => 228827)


--- trunk/Tools/ChangeLog	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Tools/ChangeLog	2018-02-20 19:02:25 UTC (rev 228827)
@@ -1,3 +1,17 @@
+2018-02-20  Nan Wang  <n_w...@apple.com>
+
+        AX: AOM: Dispatch accessibleclick event
+        https://bugs.webkit.org/show_bug.cgi?id=180898
+        <rdar://problem/36086710>
+
+        Reviewed by Ryosuke Niwa.
+
+        * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+        (WTR::AccessibilityUIElement::syncPress):
+        * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+        (WTR::AccessibilityUIElement::syncPress):
+
 2018-02-20  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [iOS 11.3 Beta] Can't copy a URL from Safari and paste it into the Gmail app

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h (228826 => 228827)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2018-02-20 19:02:25 UTC (rev 228827)
@@ -97,6 +97,11 @@
     void decrement();
     void showMenu();
     void press();
+#if PLATFORM(MAC)
+    void syncPress();
+#else
+    void syncPress() { press(); }
+#endif
 
     // Attributes - platform-independent implementations
     JSRetainPtr<JSStringRef> stringAttributeValue(JSStringRef attribute);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl (228826 => 228827)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl	2018-02-20 19:02:25 UTC (rev 228827)
@@ -116,6 +116,7 @@
     void increment();
     void decrement();
     void press();
+    void syncPress();
     void showMenu();
 
     // Attribute info.

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm (228826 => 228827)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm	2018-02-20 18:46:10 UTC (rev 228826)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm	2018-02-20 19:02:25 UTC (rev 228827)
@@ -1432,6 +1432,13 @@
     END_AX_OBJC_EXCEPTIONS
 }
 
+void AccessibilityUIElement::syncPress()
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    [m_element accessibilityPerformAction:@"AXSyncPressAction"];
+    END_AX_OBJC_EXCEPTIONS
+}
+
 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
 {
     BEGIN_AX_OBJC_EXCEPTIONS
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to