<!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>[174642] trunk/Tools</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/174642">174642</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2014-10-12 14:48:16 -0700 (Sun, 12 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Page not fully rendered in iOS DRT snapshots
https://bugs.webkit.org/show_bug.cgi?id=137638

Reviewed by Tim Horton.

In iOS DumpRenderTree, we need to wait for a cycle of the WebThread runloop
to ensure that the page has laid out and is rendered by the time we take
the snapshot.

* DumpRenderTree/mac/DumpRenderTree.mm:
(-[DumpRenderTree _webThreadEventLoopHasRun]): Moved.
(-[DumpRenderTree _webThreadInvoked]): Moved.
(-[DumpRenderTree _waitForWebThreadThenDump]):
(dump): Use a performSelectorOnMainThread:withObject:waitUntilDone:NO to wait
for a cycle of the WebThrewd runloop. We can't just call _waitForWebThread because
that blocks on a delegate callback, and we can't dispatch_async because _waitForWebThread
relies on dispatch_async too, and the inner block won't complete until the outer block
has completed.
(dumpTestResults): Move the guts of dump() here.
(runTest): Whitespace.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreemacDumpRenderTreemm">trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (174641 => 174642)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2014-10-12 18:48:12 UTC (rev 174641)
+++ trunk/Tools/ChangeLog        2014-10-12 21:48:16 UTC (rev 174642)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2014-10-12  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        Page not fully rendered in iOS DRT snapshots
+        https://bugs.webkit.org/show_bug.cgi?id=137638
+
+        Reviewed by Tim Horton.
+        
+        In iOS DumpRenderTree, we need to wait for a cycle of the WebThread runloop
+        to ensure that the page has laid out and is rendered by the time we take
+        the snapshot.
+
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (-[DumpRenderTree _webThreadEventLoopHasRun]): Moved.
+        (-[DumpRenderTree _webThreadInvoked]): Moved.
+        (-[DumpRenderTree _waitForWebThreadThenDump]):
+        (dump): Use a performSelectorOnMainThread:withObject:waitUntilDone:NO to wait
+        for a cycle of the WebThrewd runloop. We can't just call _waitForWebThread because
+        that blocks on a delegate callback, and we can't dispatch_async because _waitForWebThread
+        relies on dispatch_async too, and the inner block won't complete until the outer block
+        has completed.
+        (dumpTestResults): Move the guts of dump() here.
+        (runTest): Whitespace.
+
</ins><span class="cx"> 2014-10-12  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Adding svn:ignore so that .pyc files don't show up as new.
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreemacDumpRenderTreemm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (174641 => 174642)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm        2014-10-12 18:48:12 UTC (rev 174641)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm        2014-10-12 21:48:16 UTC (rev 174642)
</span><span class="lines">@@ -155,6 +155,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> static void runTest(const string&amp; testPathOrURL);
</span><ins>+static void dumpTestResults();
</ins><span class="cx"> 
</span><span class="cx"> // Deciding when it's OK to dump out the state is a bit tricky.  All these must be true:
</span><span class="cx"> // - There is no load in progress
</span><span class="lines">@@ -1216,20 +1217,6 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)_webThreadEventLoopHasRun
-{
-    ASSERT(!WebThreadIsCurrent());
-    _hasFlushedWebThreadRunQueue = YES;
-}
-
-- (void)_webThreadInvoked
-{
-    ASSERT(WebThreadIsCurrent());
-    dispatch_async(dispatch_get_main_queue(), ^{
-        [self _webThreadEventLoopHasRun];
-    });
-}
-
</del><span class="cx"> - (void)applicationDidEnterBackground:(UIApplication *)application
</span><span class="cx"> {
</span><span class="cx">     /* Apps will get suspended or killed some time after entering the background state but we want to be able to run multiple copies of DumpRenderTree. Periodically check to see if our remaining background time dips below a threshold and create a new background task.
</span><span class="lines">@@ -1253,6 +1240,20 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_webThreadEventLoopHasRun
+{
+    ASSERT(!WebThreadIsCurrent());
+    _hasFlushedWebThreadRunQueue = YES;
+}
+
+- (void)_webThreadInvoked
+{
+    ASSERT(WebThreadIsCurrent());
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [self _webThreadEventLoopHasRun];
+    });
+}
+
</ins><span class="cx"> // The test can end in response to a delegate callback while there are still methods queued on the Web Thread.
</span><span class="cx"> // If we do not ensure the Web Thread has been run, the callback can be done on a WebView that no longer exists.
</span><span class="cx"> // To avoid this, _waitForWebThread dispatches a call to the WebThread event loop, actively processing the delegate
</span><span class="lines">@@ -1271,6 +1272,12 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_waitForWebThreadThenDump
+{
+    [self _waitForWebThread];
+    dumpTestResults();
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -1561,6 +1568,19 @@
</span><span class="cx">         [(DumpRenderTree *)UIApp _deferDumpToMainThread];
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+
+    // Allow the web thread to run before dumping. We can't call -_waitForWebThread directly since we may
+    // be inside a delegate callback.
+    [UIApp performSelectorOnMainThread:@selector(_waitForWebThreadThenDump) withObject:nil waitUntilDone:NO];
+    return;
+#endif
+
+    dumpTestResults();
+}
+
+void dumpTestResults()
+{
+#if PLATFORM(IOS)
</ins><span class="cx">     WebThreadLock();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -1831,6 +1851,7 @@
</span><span class="cx"> 
</span><span class="cx">     if ([WebHistory optionalSharedHistory])
</span><span class="cx">         [WebHistory setOptionalSharedHistory:nil];
</span><ins>+
</ins><span class="cx">     lastMousePosition = NSZeroPoint;
</span><span class="cx">     lastClickPosition = NSZeroPoint;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>