AX: WebKit is not firing AXMenuItemSelectedNotification
authorcfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Jan 2014 17:03:15 +0000 (17:03 +0000)
committercfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Jan 2014 17:03:15 +0000 (17:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=127081

Reviewed by Mario Sanchez Prada.

Source/WebCore:

Monitor for when a menu item either gains focus() or has aria-selected set,
in which case, we need to fire a specific notification.

Test: platform/mac/accessibility/aria-menu-item-selected-notification.html

* accessibility/AXObjectCache.cpp:
(WebCore::nodeHasRole):
    This method was declared in the header, but never implemented, leading to compilation issues.
(WebCore::AXObjectCache::handleMenuItemSelected):
(WebCore::AXObjectCache::handleFocusedUIElementChanged):
    Allow the core class to handle focus changes first, then pass off to platform
(WebCore::AXObjectCache::selectedChildrenChanged):
* accessibility/AXObjectCache.h:
* accessibility/ios/AXObjectCacheIOS.mm:
(WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
* accessibility/mac/AXObjectCacheMac.mm:
(WebCore::AXObjectCache::postPlatformNotification):
(WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(-[WebAccessibilityObjectWrapper accessibilityAttributeNames]):
    Allow menu items to expose a description attribute.

LayoutTests:

* platform/mac/accessibility/aria-menu-item-selected-notification-expected.txt: Added.
* platform/mac/accessibility/aria-menu-item-selected-notification.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@162130 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/platform/mac/accessibility/aria-menu-item-selected-notification-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/accessibility/aria-menu-item-selected-notification.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AXObjectCache.cpp
Source/WebCore/accessibility/AXObjectCache.h
Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp
Source/WebCore/accessibility/ios/AXObjectCacheIOS.mm
Source/WebCore/accessibility/mac/AXObjectCacheMac.mm
Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm
Source/WebCore/accessibility/win/AXObjectCacheWin.cpp

index 50bb4d8..e8ac946 100644 (file)
@@ -1,3 +1,13 @@
+2014-01-16  Chris Fleizach  <cfleizach@apple.com>
+
+        AX: WebKit is not firing AXMenuItemSelectedNotification
+        https://bugs.webkit.org/show_bug.cgi?id=127081
+
+        Reviewed by Mario Sanchez Prada.
+
+        * platform/mac/accessibility/aria-menu-item-selected-notification-expected.txt: Added.
+        * platform/mac/accessibility/aria-menu-item-selected-notification.html: Added.
+
 2014-01-16  Michał Pakuła vel Rutka  <m.pakula@samsung.com>
 
         Unreviewed EFL gardening
diff --git a/LayoutTests/platform/mac/accessibility/aria-menu-item-selected-notification-expected.txt b/LayoutTests/platform/mac/accessibility/aria-menu-item-selected-notification-expected.txt
new file mode 100644 (file)
index 0000000..201b956
--- /dev/null
@@ -0,0 +1,25 @@
+Menu item 1
+Menu item 2
+Menu item 3
+This tests that a AXMenuItemSelected notification gets fired when a menuitem is focused.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS addedNotification is true
+Received menu item selected notification: AXMenuItemSelected
+Menu item selected element: AXRole: AXMenuItem
+Menu item selected element description: AXDescription: item1
+
+Received menu item selected notification: AXMenuItemSelected
+Menu item selected element: AXRole: AXMenuItem
+Menu item selected element description: AXDescription: item2
+
+Received menu item selected notification: AXMenuItemSelected
+Menu item selected element: AXRole: AXMenuItem
+Menu item selected element description: AXDescription: item3
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/mac/accessibility/aria-menu-item-selected-notification.html b/LayoutTests/platform/mac/accessibility/aria-menu-item-selected-notification.html
new file mode 100644 (file)
index 0000000..c55dd63
--- /dev/null
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body id="body">
+
+<div id="menu" role="menu">
+    <div role="menuitem" id="item1" aria-label="item1" tabindex="0">Menu item 1</div>
+    <div role="menuitemradio" id="item2" aria-label="item2" tabindex="0">Menu item 2</div>
+    <div role="menuitemcheckbox" id="item3" aria-label="item3" tabindex="0">Menu item 3</div>
+</div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+    description("This tests that a AXMenuItemSelected notification gets fired when a menuitem is focused.");
+
+    var element = 0;
+    var notification = 0;
+    var notificationCount = 0;
+    function ariaCallback(element, notification) {
+        if (notification == "AXMenuItemSelected") {
+           notificationCount++;
+
+           debug("Received menu item selected notification: " + notification);
+           debug("Menu item selected element: " + element.role);
+           debug("Menu item selected element description: " + element.description + "\n");
+           if (notificationCount == 3) {
+               accessibilityController.removeNotificationListener();
+               finishJSTest();
+           }
+        }
+    }
+
+    if (window.accessibilityController) {
+        window.jsTestIsAsync = true;
+
+        var addedNotification = accessibilityController.addNotificationListener(ariaCallback);
+        accessibilityController.rootElement;
+
+        shouldBe("addedNotification", "true");
+
+        // Trigger notification through focus.
+        document.getElementById("item1").focus();
+
+        // Trigger notification through aria-selected.
+        document.getElementById("item2").setAttribute("aria-selected", "true");
+
+        // Ensure we don't get a notification when aria-selected is false.
+        document.getElementById("item2").setAttribute("aria-selected", "false");
+
+        // Trigger another notification through focus to ensure we don't
+        document.getElementById("item3").focus();
+    }
+
+</script>
+
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
index 5a1ce70..8f2d480 100644 (file)
@@ -1,3 +1,32 @@
+2014-01-16  Chris Fleizach  <cfleizach@apple.com>
+
+        AX: WebKit is not firing AXMenuItemSelectedNotification
+        https://bugs.webkit.org/show_bug.cgi?id=127081
+
+        Reviewed by Mario Sanchez Prada.
+
+        Monitor for when a menu item either gains focus() or has aria-selected set,
+        in which case, we need to fire a specific notification.
+
+        Test: platform/mac/accessibility/aria-menu-item-selected-notification.html
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::nodeHasRole):
+            This method was declared in the header, but never implemented, leading to compilation issues.
+        (WebCore::AXObjectCache::handleMenuItemSelected):
+        (WebCore::AXObjectCache::handleFocusedUIElementChanged):
+            Allow the core class to handle focus changes first, then pass off to platform
+        (WebCore::AXObjectCache::selectedChildrenChanged):
+        * accessibility/AXObjectCache.h:
+        * accessibility/ios/AXObjectCacheIOS.mm:
+        (WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
+        * accessibility/mac/AXObjectCacheMac.mm:
+        (WebCore::AXObjectCache::postPlatformNotification):
+        (WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeNames]):
+            Allow menu items to expose a description attribute.
+
 2014-01-16  Andy Estes  <aestes@apple.com>
 
         [iOS] Fix build issues with exported headers
index 925ebbb..d625b44 100644 (file)
@@ -239,7 +239,7 @@ bool nodeHasRole(Node* node, const String& role)
     if (!node || !node->isElementNode())
         return false;
 
-    return equalIgnoringCase(toElement(node)->getAttribute(roleAttr), role);
+    return equalIgnoringCase(toElement(node)->fastGetAttribute(roleAttr), role);
 }
 
 static PassRefPtr<AccessibilityObject> createFromRenderer(RenderObject* renderer)
@@ -737,8 +737,30 @@ void AXObjectCache::checkedStateChanged(Node* node)
     postNotification(node, AXObjectCache::AXCheckedStateChanged);
 }
 
+void AXObjectCache::handleMenuItemSelected(Node* node)
+{
+    if (!node)
+        return;
+    
+    if (!nodeHasRole(node, "menuitem") && !nodeHasRole(node, "menuitemradio") && !nodeHasRole(node, "menuitemcheckbox"))
+        return;
+    
+    if (!toElement(node)->focused() && !equalIgnoringCase(toElement(node)->fastGetAttribute(aria_selectedAttr), "true"))
+        return;
+    
+    postNotification(getOrCreate(node), &document(), AXMenuListItemSelected);
+}
+    
+void AXObjectCache::handleFocusedUIElementChanged(Node* oldNode, Node* newNode)
+{
+    handleMenuItemSelected(newNode);
+    platformHandleFocusedUIElementChanged(oldNode, newNode);
+}
+    
 void AXObjectCache::selectedChildrenChanged(Node* node)
 {
+    handleMenuItemSelected(node);
+    
     // postTarget is TargetObservableParent so that you can pass in any child of an element and it will go up the parent tree
     // to find the container which should send out the notification.
     postNotification(node, AXSelectedChildrenChanged, TargetObservableParent);
@@ -746,6 +768,9 @@ void AXObjectCache::selectedChildrenChanged(Node* node)
 
 void AXObjectCache::selectedChildrenChanged(RenderObject* renderer)
 {
+    if (renderer)
+        handleMenuItemSelected(renderer->node());
+
     // postTarget is TargetObservableParent so that you can pass in any child of an element and it will go up the parent tree
     // to find the container which should send out the notification.
     postNotification(renderer, AXSelectedChildrenChanged, TargetObservableParent);
index 01c27d0..20441d8 100644 (file)
@@ -199,7 +199,6 @@ public:
 
     void frameLoadingEventNotification(Frame*, AXLoadingEvent);
 
-    bool nodeHasRole(Node*, const AtomicString& role);
     void clearTextMarkerNodesInUse(Document*);
 
     void startCachingComputedObjectAttributesUntilTreeMutates();
@@ -211,6 +210,8 @@ public:
     
 protected:
     void postPlatformNotification(AccessibilityObject*, AXNotification);
+    void platformHandleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
+
     void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned offset, const String&);
     void frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent);
     void textChanged(AccessibilityObject*);
@@ -237,6 +238,7 @@ private:
     Timer<AXObjectCache> m_notificationPostTimer;
     Vector<std::pair<RefPtr<AccessibilityObject>, AXNotification>> m_notificationsToPost;
     void notificationPostTimerFired(Timer<AXObjectCache>&);
+    void handleMenuItemSelected(Node*);
     
     static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
     
index 1633fc3..61552fe 100644 (file)
@@ -302,7 +302,7 @@ void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject* o
     }
 }
 
-void AXObjectCache::handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode)
+void AXObjectCache::platformHandleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode)
 {
     RefPtr<AccessibilityObject> oldObject = getOrCreate(oldFocusedNode);
     if (oldObject) {
index aa7f232..66b1112 100644 (file)
@@ -98,7 +98,7 @@ void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*,
 {
 }
 
-void AXObjectCache::handleFocusedUIElementChanged(Node*, Node* newNode)
+void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node* newNode)
 {
     postNotification(newNode, AXFocusedUIElementChanged, TargetElement, PostAsynchronously);
 }
index e855628..829fa07 100644 (file)
@@ -121,6 +121,9 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotific
         case AXMenuClosed:
             macNotification = (id)kAXMenuClosedNotification;
             break;
+        case AXMenuListItemSelected:
+            macNotification = (id)kAXMenuItemSelectedNotification;
+            break;
         case AXCheckedStateChanged:
             // Does not exist on Mac.
         default:
@@ -145,7 +148,7 @@ void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*,
 {
 }
 
-void AXObjectCache::handleFocusedUIElementChanged(Node*, Node*)
+void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node*)
 {
     wkAccessibilityHandleFocusChanged();
 }
index d926844..a7f650f 100644 (file)
@@ -1289,6 +1289,7 @@ static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosit
     if (menuItemAttrs == nil) {
         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
         [tempArray addObject:NSAccessibilityTitleAttribute];
+        [tempArray addObject:NSAccessibilityDescriptionAttribute];
         [tempArray addObject:NSAccessibilityHelpAttribute];
         [tempArray addObject:NSAccessibilitySelectedAttribute];
         [tempArray addObject:NSAccessibilityValueAttribute];
index bb9dc26..08e30bb 100644 (file)
@@ -166,7 +166,7 @@ AXID AXObjectCache::platformGenerateAXID() const
     return objID;
 }
 
-void AXObjectCache::handleFocusedUIElementChanged(Node*, Node* newFocusedNode)
+void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node* newFocusedNode)
 {
     if (!newFocusedNode)
         return;