<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[160417] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/160417">160417</a></dd>
<dt>Author</dt> <dd>mario.prada@samsung.com</dd>
<dt>Date</dt> <dd>2013-12-11 02:28:21 -0800 (Wed, 11 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Programmatically-inserted children lack accessibility events
https://bugs.webkit.org/show_bug.cgi?id=100275

Reviewed by Chris Fleizach.

Source/WebCore:

Test: accessibility/children-changed-sends-notification.html

Emit children-changed::add and children-changed::remove whenever
an object has been added/removed to the accessibility hierarchy,
that is, when a new AtkObject is being attached/detached.

* accessibility/AXObjectCache.h: Added new enumeration to know
when we are detaching a wrapper because of the cache or the
element is being destroyed, so we can use that information.
(WebCore::AXObjectCache::detachWrapper): Added a new parameter and
updated all the prototypes in different ports.
* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::~AXObjectCache): Call detachWrapper()
specifying that we do it because the cache is being destroyed.
(WebCore::AXObjectCache::remove): Call detachWrapper() specifying
that we do it because an accessible element is being destroyed.

* accessibility/atk/AXObjectCacheAtk.cpp:
(WebCore::AXObjectCache::detachWrapper): Emit the children-changed
signal when needed. We rely on the cached reference to the parent
AtkObject (using the implementation of atk_object_get_parent from
the AtkObject class) to find the right object to emit the signal
from here, since the accessibility hierarchy from WebCore will no
longer be accessible at this point.
(WebCore::AXObjectCache::attachWrapper): Emit the children-change
signal from here unless we are in the middle of a layout update,
trying to provide as much information (e.g. the offset) as possible.
(WebCore::AXObjectCache::postPlatformNotification): Make sure we
update (touch) the subtree under an accessibility object whenever
we receive AXChildrenChanded from WebCore, to ensure that those
objects will also be visible rightaway to ATs, and that those get
properly notified of the event at that very same moment.

* accessibility/ios/AXObjectCacheIOS.mm:
(WebCore::AXObjectCache::detachWrapper): Updated function signature.
* accessibility/mac/AXObjectCacheMac.mm:
(WebCore::AXObjectCache::detachWrapper): Ditto.
* accessibility/win/AXObjectCacheWin.cpp:
(WebCore::AXObjectCache::detachWrapper): Ditto.

Tools:

Update DRT and WebKitTestRunner to handle the children-changed
signal properly, considering the detail and optional parameters.

* DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp: Updated.
(axObjectEventListener):
* WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp: Updated.

LayoutTests:

Add new test to chack that children-changed signals are properly
emitted when adding/removing elements in the accessibility hierarchy.

* accessibility/children-changed-sends-notification-expected.txt: Added.
* accessibility/children-changed-sends-notification.html: Added.

Update test to filter out unrelated non-loading events.
* accessibility/loading-iframe-sends-notification.html: Updated.

Skip the test on the Mac as it does not expose these kind of
notifications when children are being added or removed.
* platform/mac/TestExpectations: Skip newly added test.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsaccessibilityloadingiframesendsnotificationhtml">trunk/LayoutTests/accessibility/loading-iframe-sends-notification.html</a></li>
<li><a href="#trunkLayoutTestsplatformmacTestExpectations">trunk/LayoutTests/platform/mac/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXObjectCachecpp">trunk/Source/WebCore/accessibility/AXObjectCache.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXObjectCacheh">trunk/Source/WebCore/accessibility/AXObjectCache.h</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityatkAXObjectCacheAtkcpp">trunk/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityiosAXObjectCacheIOSmm">trunk/Source/WebCore/accessibility/ios/AXObjectCacheIOS.mm</a></li>
<li><a href="#trunkSourceWebCoreaccessibilitymacAXObjectCacheMacmm">trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm</a></li>
<li><a href="#trunkSourceWebCoreaccessibilitywinAXObjectCacheWincpp">trunk/Source/WebCore/accessibility/win/AXObjectCacheWin.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreeatkAccessibilityCallbacksAtkcpp">trunk/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleatkAccessibilityNotificationHandlerAtkcpp">trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilitychildrenchangedsendsnotificationexpectedtxt">trunk/LayoutTests/accessibility/children-changed-sends-notification-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitychildrenchangedsendsnotificationhtml">trunk/LayoutTests/accessibility/children-changed-sends-notification.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/LayoutTests/ChangeLog        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2013-12-11  Mario Sanchez Prada  &lt;mario.prada@samsung.com&gt;
+
+        Programmatically-inserted children lack accessibility events
+        https://bugs.webkit.org/show_bug.cgi?id=100275
+
+        Reviewed by Chris Fleizach.
+
+        Add new test to chack that children-changed signals are properly
+        emitted when adding/removing elements in the accessibility hierarchy.
+
+        * accessibility/children-changed-sends-notification-expected.txt: Added.
+        * accessibility/children-changed-sends-notification.html: Added.
+
+        Update test to filter out unrelated non-loading events.
+        * accessibility/loading-iframe-sends-notification.html: Updated.
+
+        Skip the test on the Mac as it does not expose these kind of
+        notifications when children are being added or removed.
+        * platform/mac/TestExpectations: Skip newly added test.
+
</ins><span class="cx"> 2013-12-10  Gurpreet Kaur  &lt;k.gurpreet@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         top and bottom black background line not getting displayed
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitychildrenchangedsendsnotificationexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/children-changed-sends-notification-expected.txt (0 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/children-changed-sends-notification-expected.txt                                (rev 0)
+++ trunk/LayoutTests/accessibility/children-changed-sends-notification-expected.txt        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+This test ensures that a notification is being emitted when children are added or removed for an accessibility object
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Plain text paragraph 
+
+End of test
+PARAGRAPH notification: AXChildrenAdded
+GLOBAL notification: AXChildrenAdded on element with role AXRole: AXParagraph
+PARAGRAPH notification: AXChildrenRemoved
+GLOBAL notification: AXChildrenRemoved on element with role AXRole: AXParagraph
+PASS paragraphNotificationCount is globalNotificationCount
+PASS globalNotificationCount is 2
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitychildrenchangedsendsnotificationhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/children-changed-sends-notification.html (0 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/children-changed-sends-notification.html                                (rev 0)
+++ trunk/LayoutTests/accessibility/children-changed-sends-notification.html        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+
+&lt;p id=&quot;description&quot;&gt;&lt;/p&gt;
+&lt;p id=&quot;paragraph&quot;&gt;Plain text paragraph &lt;a id=&quot;testLink&quot; href=&quot;#&quot;&gt;with a link at the end&lt;/a&gt;&lt;/p&gt;
+&lt;div&gt;End of test&lt;/div&gt;
+
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+
+&lt;script&gt;
+window.jsTestIsAsync = true;
+
+description(&quot;This test ensures that a notification is being emitted when children are added or removed for an accessibility object&quot;);
+
+function touchAccessibilityTree(accessibilityObject) {
+    if (accessibilityObject.stringValue.indexOf('End of test') &gt;= 0)
+        return false;
+
+    var count = accessibilityObject.childrenCount;
+    for (var i = 0; i &lt; count; ++i) {
+        if (!touchAccessibilityTree(accessibilityObject.childAtIndex(i)))
+            return false;
+    }
+
+    return true;
+}
+
+function runTest() {
+    window.paragraphNotificationCount = 0;
+    window.globalNotificationCount = 0;
+
+    if (window.accessibilityController) {
+        var axWebArea = accessibilityController.rootElement.childAtIndex(0);
+
+        // Ensure the accessibility hierarchy is generated.
+        touchAccessibilityTree(axWebArea);
+
+        window.paragraph = axWebArea.childAtIndex(1);
+        paragraph.addNotificationListener(function(notification) {
+            paragraphNotificationCount++;
+            debug(&quot;PARAGRAPH notification: &quot; + notification);
+        });
+
+        accessibilityController.addNotificationListener(function(element, notification) {
+            if (!element.isEqual(paragraph))
+                return;
+
+            globalNotificationCount++;
+            debug(&quot;GLOBAL notification: &quot; + notification + &quot; on element with role &quot; + element.role);
+        });
+    }
+
+    var par = document.getElementById('paragraph');
+    window.newChild = document.createElement('button');
+    par.appendChild(newChild);
+
+    window.setTimeout(function() {
+        var link = document.getElementById('testLink');
+        link.style.display = 'none';
+
+        // Ensure the accessibility hierarchy is regenerated.
+        touchAccessibilityTree(axWebArea);
+
+        shouldBe(&quot;paragraphNotificationCount&quot;, &quot;globalNotificationCount&quot;);
+        shouldBe(&quot;globalNotificationCount&quot;, &quot;2&quot;);
+
+        if (window.accessibilityController) {
+            paragraph.removeNotificationListener();
+            accessibilityController.removeNotificationListener();
+        }
+
+        finishJSTest();
+    }, 0);
+}
+
+runTest();
+&lt;/script&gt;
+
+&lt;script src=&quot;../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilityloadingiframesendsnotificationhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/loading-iframe-sends-notification.html (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/loading-iframe-sends-notification.html        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/LayoutTests/accessibility/loading-iframe-sends-notification.html        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -53,8 +53,9 @@
</span><span class="cx">             shouldBeFalse(&quot;findByAccessibleTitleSubstring(root, 'InnerButton') != null&quot;);
</span><span class="cx"> 
</span><span class="cx">             window.accessibilityController.addNotificationListener(function (target, notification) {
</span><del>-                // Ignore this notification if it's not on the iframe.
-                if (target.description.indexOf(&quot;InnerFrame&quot;) == -1)
</del><ins>+                // Ignore this notification if it's not on the iframe or not about the iframe being loaded.
+                if (target.description.indexOf(&quot;InnerFrame&quot;) == -1
+                    || (notification != &quot;AXLoadComplete&quot; &amp;&amp; notification != &quot;AXLayoutComplete&quot;))
</ins><span class="cx">                     return;
</span><span class="cx"> 
</span><span class="cx">                 debug(&quot;Got notification on iframe.&quot;);
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/TestExpectations (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/TestExpectations        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/LayoutTests/platform/mac/TestExpectations        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> 
</span><span class="cx"> # Accessibility tests for notifications that don't exist or aren't needed on Mac OS X.
</span><span class="cx"> accessibility/aria-checkbox-sends-notification.html
</span><ins>+accessibility/children-changed-sends-notification.html
</ins><span class="cx"> accessibility/menu-list-sends-change-notification.html
</span><span class="cx"> accessibility/multiselect-list-reports-active-option.html
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Source/WebCore/ChangeLog        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2013-12-11  Mario Sanchez Prada  &lt;mario.prada@samsung.com&gt;
+
+        Programmatically-inserted children lack accessibility events
+        https://bugs.webkit.org/show_bug.cgi?id=100275
+
+        Reviewed by Chris Fleizach.
+
+        Test: accessibility/children-changed-sends-notification.html
+
+        Emit children-changed::add and children-changed::remove whenever
+        an object has been added/removed to the accessibility hierarchy,
+        that is, when a new AtkObject is being attached/detached.
+
+        * accessibility/AXObjectCache.h: Added new enumeration to know
+        when we are detaching a wrapper because of the cache or the
+        element is being destroyed, so we can use that information.
+        (WebCore::AXObjectCache::detachWrapper): Added a new parameter and
+        updated all the prototypes in different ports.
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::~AXObjectCache): Call detachWrapper()
+        specifying that we do it because the cache is being destroyed.
+        (WebCore::AXObjectCache::remove): Call detachWrapper() specifying
+        that we do it because an accessible element is being destroyed.
+
+        * accessibility/atk/AXObjectCacheAtk.cpp:
+        (WebCore::AXObjectCache::detachWrapper): Emit the children-changed
+        signal when needed. We rely on the cached reference to the parent
+        AtkObject (using the implementation of atk_object_get_parent from
+        the AtkObject class) to find the right object to emit the signal
+        from here, since the accessibility hierarchy from WebCore will no
+        longer be accessible at this point.
+        (WebCore::AXObjectCache::attachWrapper): Emit the children-change
+        signal from here unless we are in the middle of a layout update,
+        trying to provide as much information (e.g. the offset) as possible.
+        (WebCore::AXObjectCache::postPlatformNotification): Make sure we
+        update (touch) the subtree under an accessibility object whenever
+        we receive AXChildrenChanded from WebCore, to ensure that those
+        objects will also be visible rightaway to ATs, and that those get
+        properly notified of the event at that very same moment.
+
+        * accessibility/ios/AXObjectCacheIOS.mm:
+        (WebCore::AXObjectCache::detachWrapper): Updated function signature.
+        * accessibility/mac/AXObjectCacheMac.mm:
+        (WebCore::AXObjectCache::detachWrapper): Ditto.
+        * accessibility/win/AXObjectCacheWin.cpp:
+        (WebCore::AXObjectCache::detachWrapper): Ditto.
+
</ins><span class="cx"> 2013-12-11  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r160389): SVG test assertion extravaganza.
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -121,7 +121,7 @@
</span><span class="cx">     HashMap&lt;AXID, RefPtr&lt;AccessibilityObject&gt;&gt;::iterator end = m_objects.end();
</span><span class="cx">     for (HashMap&lt;AXID, RefPtr&lt;AccessibilityObject&gt;&gt;::iterator it = m_objects.begin(); it != end; ++it) {
</span><span class="cx">         AccessibilityObject* obj = (*it).value.get();
</span><del>-        detachWrapper(obj);
</del><ins>+        detachWrapper(obj, CacheDestroyed);
</ins><span class="cx">         obj-&gt;detach();
</span><span class="cx">         removeAXID(obj);
</span><span class="cx">     }
</span><span class="lines">@@ -493,7 +493,7 @@
</span><span class="cx">     if (!obj)
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    detachWrapper(obj);
</del><ins>+    detachWrapper(obj, ElementDestroyed);
</ins><span class="cx">     obj-&gt;detach();
</span><span class="cx">     removeAXID(obj);
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.h        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -71,6 +71,8 @@
</span><span class="cx"> 
</span><span class="cx"> enum PostType { PostSynchronously, PostAsynchronously };
</span><span class="cx"> 
</span><ins>+enum DetachmentType { CacheDestroyed, ElementDestroyed };
+
</ins><span class="cx"> class AXObjectCache {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(AXObjectCache); WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -102,7 +104,7 @@
</span><span class="cx">     void remove(Widget*);
</span><span class="cx">     void remove(AXID);
</span><span class="cx"> 
</span><del>-    void detachWrapper(AccessibilityObject*);
</del><ins>+    void detachWrapper(AccessibilityObject*, DetachmentType);
</ins><span class="cx">     void attachWrapper(AccessibilityObject*);
</span><span class="cx">     void childrenChanged(Node*);
</span><span class="cx">     void childrenChanged(RenderObject*);
</span><span class="lines">@@ -284,7 +286,7 @@
</span><span class="cx"> inline void AXObjectCache::textChanged(Node*) { }
</span><span class="cx"> inline void AXObjectCache::textChanged(AccessibilityObject*) { }
</span><span class="cx"> inline void AXObjectCache::updateCacheAfterNodeIsAttached(Node*) { }
</span><del>-inline void AXObjectCache::detachWrapper(AccessibilityObject*) { }
</del><ins>+inline void AXObjectCache::detachWrapper(AccessibilityObject*, DetachmentType) { }
</ins><span class="cx"> inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { }
</span><span class="cx"> inline void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent) { }
</span><span class="cx"> inline void AXObjectCache::handleActiveDescendantChanged(Node*) { }
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityatkAXObjectCacheAtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -31,13 +31,37 @@
</span><span class="cx"> #include &quot;TextIterator.h&quot;
</span><span class="cx"> #include &quot;WebKitAccessibleWrapperAtk.h&quot;
</span><span class="cx"> #include &lt;wtf/gobject/GOwnPtr.h&gt;
</span><ins>+#include &lt;wtf/gobject/GRefPtr.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-void AXObjectCache::detachWrapper(AccessibilityObject* obj)
</del><ins>+void AXObjectCache::detachWrapper(AccessibilityObject* obj, DetachmentType detachmentType)
</ins><span class="cx"> {
</span><del>-    webkitAccessibleDetach(WEBKIT_ACCESSIBLE(obj-&gt;wrapper()));
</del><ins>+    AtkObject* wrapper = obj-&gt;wrapper();
+    ASSERT(wrapper);
+
+    // If an object is being detached NOT because of the AXObjectCache being destroyed,
+    // then it's being removed from the accessibility tree and we should emit a signal.
+    if (detachmentType != CacheDestroyed) {
+        if (obj-&gt;document()) {
+            // Look for the right object to emit the signal from, but using the implementation
+            // of atk_object_get_parent from AtkObject class (which uses a cached pointer if set)
+            // since the accessibility hierarchy in WebCore will no longer be navigable.
+            gpointer webkitAccessibleClass = g_type_class_peek_parent(WEBKIT_ACCESSIBLE_GET_CLASS(wrapper));
+            gpointer atkObjectClass = g_type_class_peek_parent(webkitAccessibleClass);
+            AtkObject* atkParent = ATK_OBJECT_CLASS(atkObjectClass)-&gt;get_parent(ATK_OBJECT(wrapper));
+
+            // We don't want to emit any signal from an object outside WebKit's world.
+            if (WEBKIT_IS_ACCESSIBLE(atkParent)) {
+                // The accessibility hierarchy is already invalid, so the parent-children relationships
+                // in the AccessibilityObject tree are not there anymore, so we can't know the offset.
+                g_signal_emit_by_name(atkParent, &quot;children-changed::remove&quot;, -1, wrapper);
+            }
+        }
+    }
+
+    webkitAccessibleDetach(WEBKIT_ACCESSIBLE(wrapper));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AXObjectCache::attachWrapper(AccessibilityObject* obj)
</span><span class="lines">@@ -45,6 +69,25 @@
</span><span class="cx">     AtkObject* atkObj = ATK_OBJECT(webkitAccessibleNew(obj));
</span><span class="cx">     obj-&gt;setWrapper(atkObj);
</span><span class="cx">     g_object_unref(atkObj);
</span><ins>+
+    // If an object is being attached and we are not in the middle of a layout update, then
+    // we should report ATs by emitting the children-changed::add signal from the parent.
+    Document* document = obj-&gt;document();
+    if (!document || document-&gt;childNeedsStyleRecalc())
+        return;
+
+    // Don't emit the signal for objects that we already know won't be exposed directly.
+    AccessibilityObject* coreParent = obj-&gt;parentObjectUnignored();
+    if (!coreParent || coreParent-&gt;accessibilityIsIgnoredByDefault())
+        return;
+
+    // Look for the right object to emit the signal from.
+    AtkObject* atkParent = coreParent ? coreParent-&gt;wrapper() : 0;
+    if (!atkParent)
+        return;
+
+    size_t index = coreParent-&gt;children().find(obj);
+    g_signal_emit_by_name(atkParent, &quot;children-changed::add&quot;, index, atkObj);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static AccessibilityObject* getListObject(AccessibilityObject* object)
</span><span class="lines">@@ -143,29 +186,50 @@
</span><span class="cx">     if (!axObject)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (notification == AXCheckedStateChanged) {
</del><ins>+    switch (notification) {
+    case AXCheckedStateChanged:
</ins><span class="cx">         if (!coreObject-&gt;isCheckboxOrRadio())
</span><span class="cx">             return;
</span><span class="cx">         atk_object_notify_state_change(axObject, ATK_STATE_CHECKED, coreObject-&gt;isChecked());
</span><del>-    } else if (notification == AXSelectedChildrenChanged || notification == AXMenuListValueChanged) {
</del><ins>+        break;
+
+    case AXChildrenChanged:
+        // We need to make sure that the children AtkObjects are created at this moment,
+        // so the children-changed::add signal gets properly emitted in attachWrapper().
+        if (int numOfChildren = atk_object_get_n_accessible_children(axObject)) {
+            for (int i = 0; i &lt; numOfChildren; ++i)
+                GRefPtr&lt;AtkObject&gt; child(atk_object_ref_accessible_child(axObject, i));
+        }
+        break;
+
+    case AXSelectedChildrenChanged:
+    case AXMenuListValueChanged:
</ins><span class="cx">         if (notification == AXMenuListValueChanged &amp;&amp; coreObject-&gt;isMenuList()) {
</span><span class="cx">             g_signal_emit_by_name(axObject, &quot;focus-event&quot;, true);
</span><span class="cx">             atk_object_notify_state_change(axObject, ATK_STATE_FOCUSED, true);
</span><span class="cx">         }
</span><span class="cx">         notifyChildrenSelectionChange(coreObject);
</span><del>-    } else if (notification == AXValueChanged) {
-        if (!ATK_IS_VALUE(axObject))
-            return;
</del><ins>+        break;
</ins><span class="cx"> 
</span><del>-        AtkPropertyValues propertyValues;
-        propertyValues.property_name = &quot;accessible-value&quot;;
</del><ins>+    case AXValueChanged:
+        if (ATK_IS_VALUE(axObject)) {
+            AtkPropertyValues propertyValues;
+            propertyValues.property_name = &quot;accessible-value&quot;;
</ins><span class="cx"> 
</span><del>-        memset(&amp;propertyValues.new_value,  0, sizeof(GValue));
-        atk_value_get_current_value(ATK_VALUE(axObject), &amp;propertyValues.new_value);
</del><ins>+            memset(&amp;propertyValues.new_value,  0, sizeof(GValue));
+            atk_value_get_current_value(ATK_VALUE(axObject), &amp;propertyValues.new_value);
</ins><span class="cx"> 
</span><del>-        g_signal_emit_by_name(ATK_OBJECT(axObject), &quot;property-change::accessible-value&quot;, &amp;propertyValues, NULL);
-    } else if (notification == AXInvalidStatusChanged)
</del><ins>+            g_signal_emit_by_name(ATK_OBJECT(axObject), &quot;property-change::accessible-value&quot;, &amp;propertyValues, NULL);
+        }
+        break;
+
+    case AXInvalidStatusChanged:
</ins><span class="cx">         atk_object_notify_state_change(axObject, ATK_STATE_INVALID_ENTRY, coreObject-&gt;invalidStatus() != &quot;false&quot;);
</span><ins>+        break;
+
+    default:
+        break;
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject* object, AXTextChange textChange, unsigned offset, const String&amp; text)
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityiosAXObjectCacheIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/ios/AXObjectCacheIOS.mm (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/ios/AXObjectCacheIOS.mm        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Source/WebCore/accessibility/ios/AXObjectCacheIOS.mm        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx">     
</span><del>-void AXObjectCache::detachWrapper(AccessibilityObject* obj)
</del><ins>+void AXObjectCache::detachWrapper(AccessibilityObject* obj, DetachmentType)
</ins><span class="cx"> {
</span><span class="cx">     [obj-&gt;wrapper() detach];
</span><span class="cx">     obj-&gt;setWrapper(0);
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilitymacAXObjectCacheMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-void AXObjectCache::detachWrapper(AccessibilityObject* obj)
</del><ins>+void AXObjectCache::detachWrapper(AccessibilityObject* obj, DetachmentType)
</ins><span class="cx"> {
</span><span class="cx">     [obj-&gt;wrapper() detach];
</span><span class="cx">     obj-&gt;setWrapper(0);
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilitywinAXObjectCacheWincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/win/AXObjectCacheWin.cpp (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/win/AXObjectCacheWin.cpp        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Source/WebCore/accessibility/win/AXObjectCacheWin.cpp        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-void AXObjectCache::detachWrapper(AccessibilityObject* obj)
</del><ins>+void AXObjectCache::detachWrapper(AccessibilityObject* obj, DetachmentType)
</ins><span class="cx"> {
</span><span class="cx">     // On Windows, AccessibilityObjects are created when get_accChildCount is
</span><span class="cx">     // called, but they are not wrapped until get_accChild is called, so this
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Tools/ChangeLog        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2013-12-11  Mario Sanchez Prada  &lt;mario.prada@samsung.com&gt;
+
+        Programmatically-inserted children lack accessibility events
+        https://bugs.webkit.org/show_bug.cgi?id=100275
+
+        Reviewed by Chris Fleizach.
+
+        Update DRT and WebKitTestRunner to handle the children-changed
+        signal properly, considering the detail and optional parameters.
+
+        * DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp: Updated.
+        (axObjectEventListener):
+        * WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp: Updated.
+
</ins><span class="cx"> 2013-12-03  Mark Rowe  &lt;mrowe@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         &lt;https://webkit.org/b/125139&gt; Modernize the WebKit API headers
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeatkAccessibilityCallbacksAtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -113,8 +113,10 @@
</span><span class="cx">         if (g_value_get_boolean(&amp;paramValues[1]))
</span><span class="cx">             notificationName = &quot;AXFocusedUIElementChanged&quot;;
</span><span class="cx">     } else if (!g_strcmp0(signalQuery.signal_name, &quot;children-changed&quot;)) {
</span><del>-        signalName.set(g_strdup(&quot;children-changed&quot;));
</del><ins>+        const gchar* childrenChangedDetail = g_quark_to_string(signalHint-&gt;detail);
+        signalName.set(g_strdup_printf(&quot;children-changed:%s&quot;, childrenChangedDetail));
</ins><span class="cx">         signalValue.set(g_strdup_printf(&quot;%d&quot;, g_value_get_uint(&amp;paramValues[1])));
</span><ins>+        notificationName = !g_strcmp0(childrenChangedDetail, &quot;add&quot;) ? &quot;AXChildrenAdded&quot; : &quot;AXChildrenRemoved&quot;;
</ins><span class="cx">     } else if (!g_strcmp0(signalQuery.signal_name, &quot;property-change&quot;)) {
</span><span class="cx">         signalName.set(g_strdup_printf(&quot;property-change:%s&quot;, g_quark_to_string(signalHint-&gt;detail)));
</span><span class="cx">         if (!g_strcmp0(g_quark_to_string(signalHint-&gt;detail), &quot;accessible-value&quot;))
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleatkAccessibilityNotificationHandlerAtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp (160416 => 160417)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp        2013-12-11 10:00:59 UTC (rev 160416)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp        2013-12-11 10:28:21 UTC (rev 160417)
</span><span class="lines">@@ -102,8 +102,10 @@
</span><span class="cx">         if (g_value_get_boolean(&amp;paramValues[1]))
</span><span class="cx">             notificationName = &quot;AXFocusedUIElementChanged&quot;;
</span><span class="cx">     } else if (!g_strcmp0(signalQuery.signal_name, &quot;children-changed&quot;)) {
</span><del>-        signalName.set(g_strdup(&quot;children-changed&quot;));
</del><ins>+        const gchar* childrenChangedDetail = g_quark_to_string(signalHint-&gt;detail);
+        signalName.set(g_strdup_printf(&quot;children-changed:%s&quot;, childrenChangedDetail));
</ins><span class="cx">         signalValue.set(g_strdup_printf(&quot;%d&quot;, g_value_get_uint(&amp;paramValues[1])));
</span><ins>+        notificationName = !g_strcmp0(childrenChangedDetail, &quot;add&quot;) ? &quot;AXChildrenAdded&quot; : &quot;AXChildrenRemoved&quot;;
</ins><span class="cx">     } else if (!g_strcmp0(signalQuery.signal_name, &quot;property-change&quot;)) {
</span><span class="cx">         signalName.set(g_strdup_printf(&quot;property-change:%s&quot;, g_quark_to_string(signalHint-&gt;detail)));
</span><span class="cx">         if (!g_strcmp0(g_quark_to_string(signalHint-&gt;detail), &quot;accessible-value&quot;))
</span></span></pre>
</div>
</div>

</body>
</html>