<!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>[206102] 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/206102">206102</a></dd>
<dt>Author</dt> <dd>n_wang@apple.com</dd>
<dt>Date</dt> <dd>2016-09-19 11:32:21 -0700 (Mon, 19 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>AX: Add accessibility support for details element on iOS
https://bugs.webkit.org/show_bug.cgi?id=162041

Reviewed by Chris Fleizach.

Source/WebCore:

The details and summary elements are poorly supported on iOS.
Two major issues:
    1. Assistive technologies taking focus onto details/summary elements will cause unexpected behavior.
    2. VoiceOver is not speaking the expanded status of the details element.
Fixed them by not setting focus onto elements inside details and exposing the details element's expanded
status to its summary's accessible children.

Test: accessibility/ios-simulator/detail-summary-ios.html

* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(matchedParent):
(-[WebAccessibilityObjectWrapper _accessibilityListAncestor]):
(-[WebAccessibilityObjectWrapper _accessibilityLandmarkAncestor]):
(-[WebAccessibilityObjectWrapper _accessibilityTableAncestor]):
(-[WebAccessibilityObjectWrapper _accessibilityFieldsetAncestor]):
(-[WebAccessibilityObjectWrapper tableCellParent]):
(-[WebAccessibilityObjectWrapper tableParent]):
(-[WebAccessibilityObjectWrapper convertPointToScreenSpace:]):
(-[WebAccessibilityObjectWrapper convertRectToScreenSpace:]):
(-[WebAccessibilityObjectWrapper detailParentForSummaryObject:]):
(-[WebAccessibilityObjectWrapper detailParentForObject:]):
(-[WebAccessibilityObjectWrapper accessibilityElementDidBecomeFocused]):
(-[WebAccessibilityObjectWrapper accessibilitySupportsARIAExpanded]):
(-[WebAccessibilityObjectWrapper accessibilityIsExpanded]):

Tools:

* DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
(AccessibilityUIElement::isExpanded):
* WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
(WTR::AccessibilityUIElement::isExpanded):

LayoutTests:

* accessibility/ios-simulator/detail-summary-ios-expected.txt: Added.
* accessibility/ios-simulator/detail-summary-ios.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityiosWebAccessibilityObjectWrapperIOSmm">trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreeiosAccessibilityUIElementIOSmm">trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleiosAccessibilityUIElementIOSmm">trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilityiossimulatordetailsummaryiosexpectedtxt">trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilityiossimulatordetailsummaryioshtml">trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (206101 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-09-19 17:53:37 UTC (rev 206101)
+++ trunk/LayoutTests/ChangeLog        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-09-19  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: Add accessibility support for details element on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=162041
+
+        Reviewed by Chris Fleizach.
+
+        * accessibility/ios-simulator/detail-summary-ios-expected.txt: Added.
+        * accessibility/ios-simulator/detail-summary-ios.html: Added.
+
</ins><span class="cx"> 2016-09-19  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         ASSERTION FAILED: clipRectsContext.rootLayer == m_clipRectsCache-&gt;m_clipRectsRoot[clipRectsType] while loading guardian.co.uk
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilityiossimulatordetailsummaryiosexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios-expected.txt (0 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios-expected.txt                                (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios-expected.txt        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+Summary1
+
+Detail1
+
+link
+Summary2
+
+This tests the details element on iOS.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS summary1.isExpanded is true
+PASS detail1.isExpanded is false
+PASS summary2.isExpanded is false
+PASS document.getElementById('summary1') === document.activeElement is false
+PASS document.getElementById('details1') === document.activeElement is false
+PASS document.getElementById('link') === document.activeElement is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilityiossimulatordetailsummaryioshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios.html (0 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios.html                                (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/detail-summary-ios.html        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&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 id=&quot;body&quot;&gt;
+
+&lt;details open id=&quot;details1&quot;&gt;
+  &lt;summary id=&quot;summary1&quot;&gt;&lt;p id=&quot;s1&quot;&gt;Summary1&lt;/p&gt;&lt;/summary&gt;
+  &lt;p id=&quot;d1&quot;&gt;Detail1&lt;/p&gt;
+  &lt;a href=&quot;&quot; id=&quot;link&quot;&gt;link&lt;/a&gt;
+&lt;/details&gt;
+
+&lt;details id=&quot;details2&quot;&gt;
+  &lt;summary&gt;&lt;p id=&quot;s2&quot;&gt;Summary2&lt;/p&gt;&lt;/summary&gt;
+  &lt;p&gt;Detail2&lt;/p&gt;
+&lt;/details&gt;
+
+&lt;p id=&quot;description&quot;&gt;&lt;/p&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+
+&lt;script&gt;
+
+    description(&quot;This tests the details element on iOS.&quot;);
+
+    var callbackCount = 0;
+    if (window.accessibilityController) {
+    
+        // Test that we are getting the expanded status for the summary text, but not for the details children.
+        var summary1 = accessibilityController.accessibleElementById(&quot;s1&quot;);
+        var detail1 = accessibilityController.accessibleElementById(&quot;d1&quot;);
+        var summary2 = accessibilityController.accessibleElementById(&quot;s2&quot;);
+        var link = accessibilityController.accessibleElementById(&quot;link&quot;);
+        
+        shouldBeTrue(&quot;summary1.isExpanded&quot;);
+        shouldBeFalse(&quot;detail1.isExpanded&quot;);
+        shouldBeFalse(&quot;summary2.isExpanded&quot;);
+        
+        // Test that VO focus onto the details children won't set focus to the summary/details element or its children.
+        summary1.assistiveTechnologySimulatedFocus();
+        shouldBeFalse(&quot;document.getElementById('summary1') === document.activeElement&quot;);
+        
+        detail1.assistiveTechnologySimulatedFocus();
+        shouldBeFalse(&quot;document.getElementById('details1') === document.activeElement&quot;);
+        
+        link.assistiveTechnologySimulatedFocus();
+        shouldBeFalse(&quot;document.getElementById('link') === document.activeElement&quot;);
+    }
+    
+&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="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206101 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-19 17:53:37 UTC (rev 206101)
+++ trunk/Source/WebCore/ChangeLog        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2016-09-19  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: Add accessibility support for details element on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=162041
+
+        Reviewed by Chris Fleizach.
+
+        The details and summary elements are poorly supported on iOS.
+        Two major issues:
+            1. Assistive technologies taking focus onto details/summary elements will cause unexpected behavior.
+            2. VoiceOver is not speaking the expanded status of the details element.
+        Fixed them by not setting focus onto elements inside details and exposing the details element's expanded
+        status to its summary's accessible children.
+
+        Test: accessibility/ios-simulator/detail-summary-ios.html
+
+        * accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
+        (matchedParent):
+        (-[WebAccessibilityObjectWrapper _accessibilityListAncestor]):
+        (-[WebAccessibilityObjectWrapper _accessibilityLandmarkAncestor]):
+        (-[WebAccessibilityObjectWrapper _accessibilityTableAncestor]):
+        (-[WebAccessibilityObjectWrapper _accessibilityFieldsetAncestor]):
+        (-[WebAccessibilityObjectWrapper tableCellParent]):
+        (-[WebAccessibilityObjectWrapper tableParent]):
+        (-[WebAccessibilityObjectWrapper convertPointToScreenSpace:]):
+        (-[WebAccessibilityObjectWrapper convertRectToScreenSpace:]):
+        (-[WebAccessibilityObjectWrapper detailParentForSummaryObject:]):
+        (-[WebAccessibilityObjectWrapper detailParentForObject:]):
+        (-[WebAccessibilityObjectWrapper accessibilityElementDidBecomeFocused]):
+        (-[WebAccessibilityObjectWrapper accessibilitySupportsARIAExpanded]):
+        (-[WebAccessibilityObjectWrapper accessibilityIsExpanded]):
+
</ins><span class="cx"> 2016-09-19  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         ASSERTION FAILED: clipRectsContext.rootLayer == m_clipRectsCache-&gt;m_clipRectsRoot[clipRectsType] while loading guardian.co.uk
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityiosWebAccessibilityObjectWrapperIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm (206101 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm        2016-09-19 17:53:37 UTC (rev 206101)
+++ trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -131,6 +131,22 @@
</span><span class="cx">     return wrapper;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename MatchFunction&gt;
+static AccessibilityObject* matchedParent(AccessibilityObject* object, bool includeSelf, const MatchFunction&amp; matches)
+{
+    if (!object)
+        return nullptr;
+
+    AccessibilityObject* parent = includeSelf ? object : object-&gt;parentObject();
+    for (; parent; parent = parent-&gt;parentObject()) {
+        if (matches(parent))
+            return parent;
+    }
+    
+    return nullptr;
+}
+
+
</ins><span class="cx"> #pragma mark Accessibility Text Marker
</span><span class="cx"> 
</span><span class="cx"> @interface WebAccessibilityTextMarker : NSObject
</span><span class="lines">@@ -533,42 +549,46 @@
</span><span class="cx"> 
</span><span class="cx"> - (AccessibilityObjectWrapper*)_accessibilityListAncestor
</span><span class="cx"> {
</span><del>-    for (AccessibilityObject* parent = m_object-&gt;parentObject(); parent != nil; parent = parent-&gt;parentObject()) {
-        AccessibilityRole role = parent-&gt;roleValue();
-        if (role == ListRole || role == ListBoxRole)
-            return parent-&gt;wrapper();
-    }
</del><ins>+    auto matchFunc = [] (AccessibilityObject* object) {
+        AccessibilityRole role = object-&gt;roleValue();
+        return role == ListRole || role == ListBoxRole;
+    };
</ins><span class="cx">     
</span><ins>+    if (AccessibilityObject* parent = matchedParent(m_object, false, matchFunc))
+        return parent-&gt;wrapper();
</ins><span class="cx">     return nil;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (AccessibilityObjectWrapper*)_accessibilityLandmarkAncestor
</span><span class="cx"> {
</span><del>-    for (AccessibilityObject* parent = m_object-&gt;parentObject(); parent != nil; parent = parent-&gt;parentObject()) {
-        if ([self _accessibilityIsLandmarkRole:parent-&gt;roleValue()])
-            return parent-&gt;wrapper();
-    }
-
</del><ins>+    auto matchFunc = [self] (AccessibilityObject* object) {
+        return [self _accessibilityIsLandmarkRole:object-&gt;roleValue()];
+    };
+    
+    if (AccessibilityObject* parent = matchedParent(m_object, false, matchFunc))
+        return parent-&gt;wrapper();
</ins><span class="cx">     return nil;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (AccessibilityObjectWrapper*)_accessibilityTableAncestor
</span><span class="cx"> {
</span><del>-    for (AccessibilityObject* parent = m_object-&gt;parentObject(); parent != nil; parent = parent-&gt;parentObject()) {
-        if (parent-&gt;roleValue() == TableRole || parent-&gt;roleValue() == GridRole)
-            return parent-&gt;wrapper();   
-    }
</del><ins>+    auto matchFunc = [] (AccessibilityObject* object) {
+        return object-&gt;roleValue() == TableRole || object-&gt;roleValue() == GridRole;
+    };
</ins><span class="cx">     
</span><ins>+    if (AccessibilityObject* parent = matchedParent(m_object, false, matchFunc))
+        return parent-&gt;wrapper();
</ins><span class="cx">     return nil;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (AccessibilityObjectWrapper*)_accessibilityFieldsetAncestor
</span><span class="cx"> {
</span><del>-    for (AccessibilityObject* parent = m_object-&gt;parentObject(); parent != nil; parent = parent-&gt;parentObject()) {
-        if (parent-&gt;isFieldset())
-            return parent-&gt;wrapper();
-    }
</del><ins>+    auto matchFunc = [] (AccessibilityObject* object) {
+        return object-&gt;isFieldset();
+    };
</ins><span class="cx">     
</span><ins>+    if (AccessibilityObject* parent = matchedParent(m_object, false, matchFunc))
+        return parent-&gt;wrapper();
</ins><span class="cx">     return nil;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1021,27 +1041,25 @@
</span><span class="cx"> - (AccessibilityTableCell*)tableCellParent
</span><span class="cx"> {
</span><span class="cx">     // Find if this element is in a table cell.
</span><del>-    AccessibilityObject* cell = nullptr;
-    for (cell = m_object; cell &amp;&amp; !cell-&gt;isTableCell(); cell = cell-&gt;parentObject()) 
-    { }
</del><ins>+    auto matchFunc = [] (AccessibilityObject* object) {
+        return object-&gt;isTableCell();
+    };
</ins><span class="cx">     
</span><del>-    if (!cell)
-        return nil;
-
-    return static_cast&lt;AccessibilityTableCell*&gt;(cell);
</del><ins>+    if (AccessibilityObject* parent = matchedParent(m_object, true, matchFunc))
+        return static_cast&lt;AccessibilityTableCell*&gt;(parent);
+    return nil;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (AccessibilityTable*)tableParent
</span><span class="cx"> {
</span><span class="cx">     // Find if the parent table for the table cell.
</span><del>-    AccessibilityObject* parentTable = nullptr;
-    for (parentTable = m_object; parentTable &amp;&amp; !(is&lt;AccessibilityTable&gt;(*parentTable) &amp;&amp; downcast&lt;AccessibilityTable&gt;(*parentTable).isExposableThroughAccessibility()); parentTable = parentTable-&gt;parentObject())
-    { }
</del><ins>+    auto matchFunc = [] (AccessibilityObject* object) {
+        return is&lt;AccessibilityTable&gt;(*object) &amp;&amp; downcast&lt;AccessibilityTable&gt;(*object).isExposableThroughAccessibility();
+    };
</ins><span class="cx">     
</span><del>-    if (!parentTable)
-        return nil;
-    
-    return static_cast&lt;AccessibilityTable*&gt;(parentTable);
</del><ins>+    if (AccessibilityObject* parent = matchedParent(m_object, true, matchFunc))
+        return static_cast&lt;AccessibilityTable*&gt;(parent);
+    return nil;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (id)accessibilityTitleElement
</span><span class="lines">@@ -1408,14 +1426,14 @@
</span><span class="cx">     }
</span><span class="cx">     else {
</span><span class="cx">         // Find the appropriate scroll view to use to convert the contents to the window.
</span><ins>+        auto matchFunc = [] (AccessibilityObject* object) {
+            return is&lt;AccessibilityScrollView&gt;(*object);
+        };
+        
</ins><span class="cx">         ScrollView* scrollView = nullptr;
</span><del>-        AccessibilityObject* parent = nullptr;
-        for (parent = m_object-&gt;parentObject(); parent; parent = parent-&gt;parentObject()) {
-            if (is&lt;AccessibilityScrollView&gt;(*parent)) {
-                scrollView = downcast&lt;AccessibilityScrollView&gt;(*parent).scrollView();
-                break;
-            }
-        }
</del><ins>+        AccessibilityObject* parent = matchedParent(m_object, false, matchFunc);
+        if (parent)
+            scrollView = downcast&lt;AccessibilityScrollView&gt;(*parent).scrollView();
</ins><span class="cx">         
</span><span class="cx">         IntPoint intPoint = flooredIntPoint(point);
</span><span class="cx">         if (scrollView)
</span><span class="lines">@@ -1462,14 +1480,14 @@
</span><span class="cx">         
</span><span class="cx">     } else {
</span><span class="cx">         // Find the appropriate scroll view to use to convert the contents to the window.
</span><ins>+        auto matchFunc = [] (AccessibilityObject* object) {
+            return is&lt;AccessibilityScrollView&gt;(*object);
+        };
+
</ins><span class="cx">         ScrollView* scrollView = nullptr;
</span><del>-        AccessibilityObject* parent = nullptr;
-        for (parent = m_object-&gt;parentObject(); parent; parent = parent-&gt;parentObject()) {
-            if (is&lt;AccessibilityScrollView&gt;(*parent)) {
-                scrollView = downcast&lt;AccessibilityScrollView&gt;(*parent).scrollView();
-                break;
-            }
-        }
</del><ins>+        AccessibilityObject* parent = matchedParent(m_object, false, matchFunc);
+        if (parent)
+            scrollView = downcast&lt;AccessibilityScrollView&gt;(*parent).scrollView();
</ins><span class="cx">         
</span><span class="cx">         if (scrollView)
</span><span class="cx">             rect = scrollView-&gt;contentsToRootView(rect);
</span><span class="lines">@@ -1833,6 +1851,31 @@
</span><span class="cx">     return m_object-&gt;scrollVisibleContentRect();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (AccessibilityObject*)detailParentForSummaryObject:(AccessibilityObject*)object
+{
+    // Use this to check if an object is the child of a summary object.
+    // And return the summary's parent, which is the expandable details object.
+    auto matchFunc = [] (AccessibilityObject* object) {
+        return object-&gt;hasTagName(summaryTag);
+    };
+    
+    if (AccessibilityObject* summary = matchedParent(object, true, matchFunc))
+        return summary-&gt;parentObject();
+    return nil;
+}
+
+- (AccessibilityObject*)detailParentForObject:(AccessibilityObject*)object
+{
+    // Use this to check if an object is inside a details object.
+    auto matchFunc = [] (AccessibilityObject* object) {
+        return object-&gt;hasTagName(detailsTag);
+    };
+    
+    if (AccessibilityObject* details = matchedParent(object, true, matchFunc))
+        return details;
+    return nil;
+}
+
</ins><span class="cx"> - (void)accessibilityElementDidBecomeFocused
</span><span class="cx"> {
</span><span class="cx">     if (![self _prepareAccessibilityCall])
</span><span class="lines">@@ -1845,6 +1888,9 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         if (object-&gt;canSetFocusAttribute()) {
</span><ins>+            // webkit.org/b/162041 Taking focus onto elements inside a details node will cause VO focusing onto random items.
+            if ([self detailParentForObject:object])
+                break;
</ins><span class="cx">             object-&gt;setFocused(true);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -2681,6 +2727,11 @@
</span><span class="cx">     if (![self _prepareAccessibilityCall])
</span><span class="cx">         return NO;
</span><span class="cx">     
</span><ins>+    // Since details element is ignored on iOS, we should expose the expanded status on its
+    // summary's accessible children.
+    if (AccessibilityObject* detailParent = [self detailParentForSummaryObject:m_object])
+        return detailParent-&gt;supportsExpanded();
+    
</ins><span class="cx">     return m_object-&gt;supportsExpanded();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2689,6 +2740,11 @@
</span><span class="cx">     if (![self _prepareAccessibilityCall])
</span><span class="cx">         return NO;
</span><span class="cx"> 
</span><ins>+    // Since details element is ignored on iOS, we should expose the expanded status on its
+    // summary's accessible children.
+    if (AccessibilityObject* detailParent = [self detailParentForSummaryObject:m_object])
+        return detailParent-&gt;isExpanded();
+    
</ins><span class="cx">     return m_object-&gt;isExpanded();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (206101 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-09-19 17:53:37 UTC (rev 206101)
+++ trunk/Tools/ChangeLog        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-09-19  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: Add accessibility support for details element on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=162041
+
+        Reviewed by Chris Fleizach.
+
+        * DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
+        (AccessibilityUIElement::isExpanded):
+        * WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
+        (WTR::AccessibilityUIElement::isExpanded):
+
</ins><span class="cx"> 2016-09-18  Gyuyoung Kim  &lt;gyuyoung.kim@navercorp.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] Bump efl library to 1.18.1
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeiosAccessibilityUIElementIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm (206101 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm        2016-09-19 17:53:37 UTC (rev 206101)
+++ trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -97,6 +97,7 @@
</span><span class="cx"> - (id)_accessibilityFieldsetAncestor;
</span><span class="cx"> - (BOOL)_accessibilityHasTouchEventListener;
</span><span class="cx"> - (NSString *)accessibilityExpandedTextValue;
</span><ins>+- (BOOL)accessibilityIsExpanded;
</ins><span class="cx"> 
</span><span class="cx"> // TextMarker related
</span><span class="cx"> - (NSArray *)textMarkerRange;
</span><span class="lines">@@ -824,7 +825,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool AccessibilityUIElement::isExpanded() const
</span><span class="cx"> {
</span><del>-    return false;
</del><ins>+    return [m_element accessibilityIsExpanded];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool AccessibilityUIElement::isChecked() const
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleiosAccessibilityUIElementIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm (206101 => 206102)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm        2016-09-19 17:53:37 UTC (rev 206101)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm        2016-09-19 18:32:21 UTC (rev 206102)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx"> - (id)_accessibilityFieldsetAncestor;
</span><span class="cx"> - (BOOL)_accessibilityHasTouchEventListener;
</span><span class="cx"> - (NSString *)accessibilityExpandedTextValue;
</span><ins>+- (BOOL)accessibilityIsExpanded;
</ins><span class="cx"> 
</span><span class="cx"> // TextMarker related
</span><span class="cx"> - (NSArray *)textMarkerRange;
</span><span class="lines">@@ -568,7 +569,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool AccessibilityUIElement::isExpanded() const
</span><span class="cx"> {
</span><del>-    return false;
</del><ins>+    return [m_element accessibilityIsExpanded];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool AccessibilityUIElement::isChecked() const
</span></span></pre>
</div>
</div>

</body>
</html>