<!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>[160903] 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/160903">160903</a></dd>
<dt>Author</dt> <dd>mario.prada@samsung.com</dd>
<dt>Date</dt> <dd>2013-12-20 03:52:17 -0800 (Fri, 20 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:
(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.

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::children): Add the option ot
request the AccessibilityChildrenVector without updating it if
needed, to avoid maybe recreating the child subtree when trying to
get the offset of a newly attached element from attachWrapper.
* accessibility/AccessibilityObject.h:

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="#trunkSourceWebCoreaccessibilityAccessibilityObjectcpp">trunk/Source/WebCore/accessibility/AccessibilityObject.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityObjecth">trunk/Source/WebCore/accessibility/AccessibilityObject.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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/LayoutTests/ChangeLog        2013-12-20 11:52:17 UTC (rev 160903)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2013-12-20  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-19  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r160847): fast/events/overflowchanged-inside-selection-collapse-crash.html fails
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitychildrenchangedsendsnotificationexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/children-changed-sends-notification-expected.txt (0 => 160903)</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-20 11:52:17 UTC (rev 160903)
</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 => 160903)</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-20 11:52:17 UTC (rev 160903)
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/loading-iframe-sends-notification.html        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/LayoutTests/accessibility/loading-iframe-sends-notification.html        2013-12-20 11:52:17 UTC (rev 160903)
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/TestExpectations        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/LayoutTests/platform/mac/TestExpectations        2013-12-20 11:52:17 UTC (rev 160903)
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/ChangeLog        2013-12-20 11:52:17 UTC (rev 160903)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2013-12-20  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:
+        (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.
+
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::children): Add the option ot
+        request the AccessibilityChildrenVector without updating it if
+        needed, to avoid maybe recreating the child subtree when trying to
+        get the offset of a newly attached element from attachWrapper.
+        * accessibility/AccessibilityObject.h:
+
</ins><span class="cx"> 2013-12-20  Laszlo Vidacs  &lt;lvidacs.u-szeged@partner.samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move function calls outside loop in dom
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2013-12-20 11:52:17 UTC (rev 160903)
</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(CacheDestroyed);
</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(ElementDestroyed, this);
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.h        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h        2013-12-20 11:52:17 UTC (rev 160903)
</span><span class="lines">@@ -102,7 +102,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*, AccessibilityDetachmentType);
</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">@@ -287,7 +287,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*, AccessibilityDetachmentType) { }
</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="trunkSourceWebCoreaccessibilityAccessibilityObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp        2013-12-20 11:52:17 UTC (rev 160903)
</span><span class="lines">@@ -1263,9 +1263,10 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if HAVE(ACCESSIBILITY)
</span><del>-const AccessibilityObject::AccessibilityChildrenVector&amp; AccessibilityObject::children()
</del><ins>+const AccessibilityObject::AccessibilityChildrenVector&amp; AccessibilityObject::children(bool updateChildrenIfNeeded)
</ins><span class="cx"> {
</span><del>-    updateChildrenIfNecessary();
</del><ins>+    if (updateChildrenIfNeeded)
+        updateChildrenIfNecessary();
</ins><span class="cx"> 
</span><span class="cx">     return m_children;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityObject.h        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h        2013-12-20 11:52:17 UTC (rev 160903)
</span><span class="lines">@@ -691,7 +691,7 @@
</span><span class="cx">     virtual void childrenChanged() { }
</span><span class="cx">     virtual void textChanged() { }
</span><span class="cx">     virtual void updateAccessibilityRole() { }
</span><del>-    const AccessibilityChildrenVector&amp; children();
</del><ins>+    const AccessibilityChildrenVector&amp; children(bool updateChildrenIfNeeded = true);
</ins><span class="cx">     virtual void addChildren() { }
</span><span class="cx">     virtual void addChild(AccessibilityObject*) { }
</span><span class="cx">     virtual void insertChild(AccessibilityObject*, unsigned) { }
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityatkAXObjectCacheAtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp        2013-12-20 11:52:17 UTC (rev 160903)
</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, AccessibilityDetachmentType 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-&gt;wrapper();
+    if (!atkParent)
+        return;
+
+    size_t index = coreParent-&gt;children(false).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,51 @@
</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().
+        {
+            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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/ios/AXObjectCacheIOS.mm        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/ios/AXObjectCacheIOS.mm        2013-12-20 11:52:17 UTC (rev 160903)
</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, AccessibilityDetachmentType)
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm        2013-12-20 11:52:17 UTC (rev 160903)
</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, AccessibilityDetachmentType)
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/win/AXObjectCacheWin.cpp        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Source/WebCore/accessibility/win/AXObjectCacheWin.cpp        2013-12-20 11:52:17 UTC (rev 160903)
</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, AccessibilityDetachmentType)
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Tools/ChangeLog        2013-12-20 11:52:17 UTC (rev 160903)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2013-12-20  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-20  Peter Molnar  &lt;pmolnar.u-szeged@partner.samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Removed unused BUILDER_BASE_URL.
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeatkAccessibilityCallbacksAtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp        2013-12-20 11:52:17 UTC (rev 160903)
</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 (160902 => 160903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp        2013-12-20 11:28:40 UTC (rev 160902)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp        2013-12-20 11:52:17 UTC (rev 160903)
</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>