AX: WebKit not sending AXMenuClosed notification
authorcfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Dec 2013 18:50:47 +0000 (18:50 +0000)
committercfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Dec 2013 18:50:47 +0000 (18:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=125783

Reviewed by Mario Sanchez Prada.

Source/WebCore:

When an object with a role=menu is removed, we need to send out a notification informing that the menu has closed.
This means detecting the right kind of destruction event for an element, because we do not want to
send this notification when the entire cache is being torn down.

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

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::~AXObjectCache):
(WebCore::AXObjectCache::remove):
* accessibility/AXObjectCache.h:
(WebCore::AXObjectCache::document):
* accessibility/AccessibilityNodeObject.cpp:
(WebCore::AccessibilityNodeObject::detach):
* accessibility/AccessibilityNodeObject.h:
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::detach):
* accessibility/AccessibilityObject.h:
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::detach):
* accessibility/AccessibilityRenderObject.h:
* accessibility/AccessibilityScrollView.cpp:
(WebCore::AccessibilityScrollView::detach):
* accessibility/AccessibilityScrollView.h:
* accessibility/mac/AXObjectCacheMac.mm:
(WebCore::AXObjectCache::postPlatformNotification):

LayoutTests:

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

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

15 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac/accessibility/aria-menu-closed-notification-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/accessibility/aria-menu-closed-notification.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AXObjectCache.cpp
Source/WebCore/accessibility/AXObjectCache.h
Source/WebCore/accessibility/AccessibilityNodeObject.cpp
Source/WebCore/accessibility/AccessibilityNodeObject.h
Source/WebCore/accessibility/AccessibilityObject.cpp
Source/WebCore/accessibility/AccessibilityObject.h
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/accessibility/AccessibilityRenderObject.h
Source/WebCore/accessibility/AccessibilityScrollView.cpp
Source/WebCore/accessibility/AccessibilityScrollView.h
Source/WebCore/accessibility/mac/AXObjectCacheMac.mm

index 22077e4..ed09095 100644 (file)
@@ -1,3 +1,13 @@
+2013-12-18  Chris Fleizach  <cfleizach@apple.com>
+
+        AX: WebKit not sending AXMenuClosed notification
+        https://bugs.webkit.org/show_bug.cgi?id=125783
+
+        Reviewed by Mario Sanchez Prada.
+
+        * platform/mac/accessibility/aria-menu-closed-notification-expected.txt: Added.
+        * platform/mac/accessibility/aria-menu-closed-notification.html: Added.
+
 2013-12-18  Tamas Gergely  <tgergely.u-szeged@partner.samsung.com>
 
         Fix ASSERTION FAILED in WebCore::SVGLengthContext::determineViewport
diff --git a/LayoutTests/platform/mac/accessibility/aria-menu-closed-notification-expected.txt b/LayoutTests/platform/mac/accessibility/aria-menu-closed-notification-expected.txt
new file mode 100644 (file)
index 0000000..afa8dc6
--- /dev/null
@@ -0,0 +1,11 @@
+This tests that an AXMenuClosed notification gets fired when an ARIA menu popup closes.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS addedNotification is true
+Received menu closed notification: AXMenuClosed
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/mac/accessibility/aria-menu-closed-notification.html b/LayoutTests/platform/mac/accessibility/aria-menu-closed-notification.html
new file mode 100644 (file)
index 0000000..40c1f52
--- /dev/null
@@ -0,0 +1,49 @@
+<!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" tabindex="0">Menu item 1</div>
+    <div role="menuitem" id="item2" tabindex="0">Menu item 2</div>
+</div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+    description("This tests that an AXMenuClosed notification gets fired when an ARIA menu popup closes.");
+
+    function hideMenu() {
+        document.getElementById("menu").style.display = "none";
+    }
+
+    var webArea = 0;
+    function ariaCallback(notification) {
+        if (notification == "AXMenuClosed") {
+           debug("Received menu closed notification: " + notification);
+           webArea.removeNotificationListener();
+           finishJSTest();
+        }
+    }
+
+    if (window.accessibilityController) {
+        window.jsTestIsAsync = true;
+
+        webArea = accessibilityController.rootElement.childAtIndex(0);
+        var menu = accessibilityController.accessibleElementById("menu");
+
+        var addedNotification = webArea.addNotificationListener(ariaCallback);
+        shouldBe("addedNotification", "true");
+
+        hideMenu(); 
+    }
+
+</script>
+
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
index 76a194f..74715a6 100644 (file)
@@ -1,3 +1,36 @@
+2013-12-18  Chris Fleizach  <cfleizach@apple.com>
+
+        AX: WebKit not sending AXMenuClosed notification
+        https://bugs.webkit.org/show_bug.cgi?id=125783
+
+        Reviewed by Mario Sanchez Prada.
+
+        When an object with a role=menu is removed, we need to send out a notification informing that the menu has closed.
+        This means detecting the right kind of destruction event for an element, because we do not want to 
+        send this notification when the entire cache is being torn down.
+
+        Test: platform/mac/accessibility/aria-menu-closed-notification.html
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::~AXObjectCache):
+        (WebCore::AXObjectCache::remove):
+        * accessibility/AXObjectCache.h:
+        (WebCore::AXObjectCache::document):
+        * accessibility/AccessibilityNodeObject.cpp:
+        (WebCore::AccessibilityNodeObject::detach):
+        * accessibility/AccessibilityNodeObject.h:
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::detach):
+        * accessibility/AccessibilityObject.h:
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::detach):
+        * accessibility/AccessibilityRenderObject.h:
+        * accessibility/AccessibilityScrollView.cpp:
+        (WebCore::AccessibilityScrollView::detach):
+        * accessibility/AccessibilityScrollView.h:
+        * accessibility/mac/AXObjectCacheMac.mm:
+        (WebCore::AXObjectCache::postPlatformNotification):
+
 2013-12-18  Eric Carlson  <eric.carlson@apple.com>
 
         Do not create cue subtree just to delete it
index 3c4c59b..d35cf20 100644 (file)
@@ -122,7 +122,7 @@ AXObjectCache::~AXObjectCache()
     for (HashMap<AXID, RefPtr<AccessibilityObject>>::iterator it = m_objects.begin(); it != end; ++it) {
         AccessibilityObject* obj = (*it).value.get();
         detachWrapper(obj);
-        obj->detach();
+        obj->detach(CacheDestroyed);
         removeAXID(obj);
     }
 }
@@ -494,7 +494,7 @@ void AXObjectCache::remove(AXID axID)
         return;
     
     detachWrapper(obj);
-    obj->detach();
+    obj->detach(ElementDestroyed, this);
     removeAXID(obj);
     
     // finally remove the object
index e2e8972..a8977cc 100644 (file)
@@ -169,6 +169,7 @@ public:
         AXLiveRegionChanged,
         AXMenuListItemSelected,
         AXMenuListValueChanged,
+        AXMenuClosed,
         AXRowCountChanged,
         AXRowCollapsed,
         AXRowExpanded,
@@ -206,6 +207,8 @@ public:
 
     AXComputedObjectAttributeCache* computedObjectAttributeCache() { return m_computedObjectAttributeCache.get(); }
 
+    Document& document() const { return m_document; }
+    
 protected:
     void postPlatformNotification(AccessibilityObject*, AXNotification);
     void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned offset, const String&);
index 4284728..a6d013f 100644 (file)
@@ -120,10 +120,10 @@ PassRefPtr<AccessibilityNodeObject> AccessibilityNodeObject::create(Node* node)
     return adoptRef(new AccessibilityNodeObject(node));
 }
 
-void AccessibilityNodeObject::detach()
+void AccessibilityNodeObject::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
 {
-    clearChildren();
-    AccessibilityObject::detach();
+    // AccessibilityObject calls clearChildren.
+    AccessibilityObject::detach(detachmentType, cache);
     m_node = 0;
 }
 
index 82742f8..dfa79fd 100644 (file)
@@ -144,7 +144,7 @@ public:
     virtual AccessibilityObject* parentObject() const OVERRIDE;
     virtual AccessibilityObject* parentObjectIfExists() const OVERRIDE;
 
-    virtual void detach() OVERRIDE;
+    virtual void detach(AccessibilityDetachmentType, AXObjectCache*) OVERRIDE;
     virtual void childrenChanged() OVERRIDE;
     virtual void updateAccessibilityRole() OVERRIDE;
 
index dd3ee5c..f7e7622 100644 (file)
@@ -88,8 +88,12 @@ AccessibilityObject::~AccessibilityObject()
     ASSERT(isDetached());
 }
 
-void AccessibilityObject::detach()
+void AccessibilityObject::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
 {
+    // Menu close events need to notify the platform. No element is used in the notification because it's a destruction event.
+    if (detachmentType == ElementDestroyed && roleValue() == MenuRole && cache)
+        cache->postNotification(nullptr, &cache->document(), AXObjectCache::AXMenuClosed);
+    
     // Clear any children and call detachFromParent on them so that
     // no children are left with dangling pointers to their parent.
     clearChildren();
index 7b7379d..0383eff 100644 (file)
@@ -351,6 +351,8 @@ struct AccessibilitySearchCriteria {
     , visibleOnly(visibleOnly)
     { }
 };
+    
+enum AccessibilityDetachmentType { CacheDestroyed, ElementDestroyed };
 
 struct VisiblePositionRange {
 
@@ -400,7 +402,7 @@ public:
 
     // When the corresponding WebCore object that this AccessibilityObject
     // wraps is deleted, it must be detached.
-    virtual void detach();
+    virtual void detach(AccessibilityDetachmentType, AXObjectCache* cache = nullptr);
     virtual bool isDetached() const;
 
     typedef Vector<RefPtr<AccessibilityObject>> AccessibilityChildrenVector;
index 717534a..620d7f4 100644 (file)
@@ -131,9 +131,9 @@ PassRefPtr<AccessibilityRenderObject> AccessibilityRenderObject::create(RenderOb
     return adoptRef(new AccessibilityRenderObject(renderer));
 }
 
-void AccessibilityRenderObject::detach()
+void AccessibilityRenderObject::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
 {
-    AccessibilityNodeObject::detach();
+    AccessibilityNodeObject::detach(detachmentType, cache);
     
     detachRemoteSVGRoot();
     
index 909d6f3..11f9975 100644 (file)
@@ -161,7 +161,7 @@ public:
     virtual void setSelectedRows(AccessibilityChildrenVector&) OVERRIDE;
     virtual AccessibilityOrientation orientation() const OVERRIDE;
     
-    virtual void detach() OVERRIDE;
+    virtual void detach(AccessibilityDetachmentType, AXObjectCache*) OVERRIDE;
     virtual void textChanged() OVERRIDE;
     virtual void addChildren() OVERRIDE;
     virtual bool canHaveChildren() const OVERRIDE;
index 92e81ca..f158506 100644 (file)
@@ -48,9 +48,9 @@ AccessibilityScrollView::~AccessibilityScrollView()
     ASSERT(isDetached());
 }
 
-void AccessibilityScrollView::detach()
+void AccessibilityScrollView::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache)
 {
-    AccessibilityObject::detach();
+    AccessibilityObject::detach(detachmentType, cache);
     m_scrollView = 0;
 }
 
index e705de3..59b3de3 100644 (file)
@@ -41,7 +41,7 @@ public:
     ScrollView* scrollView() const { return m_scrollView; }
 
     virtual ~AccessibilityScrollView();
-    virtual void detach() OVERRIDE;
+    virtual void detach(AccessibilityDetachmentType, AXObjectCache*) OVERRIDE;
 
 protected:
     virtual ScrollableArea* getScrollableAreaIfScrollable() const OVERRIDE;
index 9aa07fc..e4d5fff 100644 (file)
@@ -118,6 +118,9 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotific
         case AXElementBusyChanged:
             macNotification = @"AXElementBusyChanged";
             break;
+        case AXMenuClosed:
+            macNotification = (id)kAXMenuClosedNotification;
+            break;
         case AXCheckedStateChanged:
             // Does not exist on Mac.
         default: