<!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>[172635] trunk/Source/WebKit2</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/172635">172635</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2014-08-15 11:42:24 -0700 (Fri, 15 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION (WebKit2 Gestures): White flash when swiping back to cnn.com's homepage from an article
https://bugs.webkit.org/show_bug.cgi?id=135951
&lt;rdar://problem/18006149&gt;

Reviewed by Simon Fraser.

Wait for (the first visually non-empty layout AND the render tree size threshold to be hit),
OR didFinishLoadForFrame, whichever comes first. Once we've done the first visually non-empty layout,
we'll start the watchdog and tear down the snapshot in three seconds no matter what.
Also, force a repaint so we can asynchronously wait for the Web Process to paint and return to us
before removing the snapshot, which improves our chances that something is actually on the screen.

* UIProcess/API/mac/WKView.mm:
(-[WKView _didFirstVisuallyNonEmptyLayoutForMainFrame]):
(-[WKView _didFinishLoadForMainFrame]):
(-[WKView _removeNavigationGestureSnapshot]):
* UIProcess/API/mac/WKViewInternal.h:
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didFinishLoadForFrame):
(WebKit::WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame):
(WebKit::WebPageProxy::removeNavigationGestureSnapshot):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame):
(WebKit::PageClientImpl::didFinishLoadForMainFrame):
* UIProcess/mac/PageClientImpl.h:
* UIProcess/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame):
(WebKit::PageClientImpl::didFinishLoadForMainFrame):
(WebKit::PageClientImpl::removeNavigationGestureSnapshot):
Plumb didFirstVisuallyNonEmptyLayoutForMainFrame and didFinishLoadForMainFrame
through to ViewGestureController from WebPageProxy via the PageClient, etc.

Ditto for removeNavigationGestureSnapshot, though it is called from a
VoidCallback in ViewGestureController instead of from WebFrameLoaderClient and friends.

* UIProcess/mac/ViewGestureController.h:
* UIProcess/mac/ViewGestureControllerMac.mm:
(WebKit::ViewGestureController::ViewGestureController):
(WebKit::ViewGestureController::endSwipeGesture):
When finishing a swipe, we want to wait for both the first visually non-empty layout
and the render tree size threshold being hit.

(WebKit::ViewGestureController::didHitRenderTreeSizeThreshold):
(WebKit::ViewGestureController::didFirstVisuallyNonEmptyLayoutForMainFrame):
When both of these things have happened, remove the swipe snapshot (after forcing a repaint).
For didFirstVisuallyNonEmptyLayoutForMainFrame, we will also start a watchdog
ensuring that we remove the snapshot in three seconds.

(WebKit::ViewGestureController::didFinishLoadForMainFrame):
When didFinishLoadForMainFrame happens, remove the swipe snapshot (after forcing a repaint).

(WebKit::ViewGestureController::swipeSnapshotWatchdogTimerFired):
If the watchdog timer fires, remove the swipe snapshot (after forcing a repaint).

(WebKit::ViewGestureController::removeSwipeSnapshotAfterRepaint):
Force a repaint and wait for the async callback before removing the snapshot.
It is safe to hold on to the WebPageProxy here because it will always
call all of its callbacks before it is destroyed.
Avoid enqueuing multiple force-repaints.

(WebKit::ViewGestureController::removeSwipeSnapshot):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacWKViewmm">trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacWKViewInternalh">trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageClienth">trunk/Source/WebKit2/UIProcess/PageClient.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosPageClientImplIOSh">trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosPageClientImplIOSmm">trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacPageClientImplh">trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacPageClientImplmm">trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacViewGestureControllerh">trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacViewGestureControllerMacmm">trunk/Source/WebKit2/UIProcess/mac/ViewGestureControllerMac.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/ChangeLog        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -1,3 +1,70 @@
</span><ins>+2014-08-15  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        REGRESSION (WebKit2 Gestures): White flash when swiping back to cnn.com's homepage from an article
+        https://bugs.webkit.org/show_bug.cgi?id=135951
+        &lt;rdar://problem/18006149&gt;
+
+        Reviewed by Simon Fraser.
+
+        Wait for (the first visually non-empty layout AND the render tree size threshold to be hit),
+        OR didFinishLoadForFrame, whichever comes first. Once we've done the first visually non-empty layout,
+        we'll start the watchdog and tear down the snapshot in three seconds no matter what.
+        Also, force a repaint so we can asynchronously wait for the Web Process to paint and return to us
+        before removing the snapshot, which improves our chances that something is actually on the screen.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView _didFirstVisuallyNonEmptyLayoutForMainFrame]):
+        (-[WKView _didFinishLoadForMainFrame]):
+        (-[WKView _removeNavigationGestureSnapshot]):
+        * UIProcess/API/mac/WKViewInternal.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didFinishLoadForFrame):
+        (WebKit::WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame):
+        (WebKit::WebPageProxy::removeNavigationGestureSnapshot):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame):
+        (WebKit::PageClientImpl::didFinishLoadForMainFrame):
+        * UIProcess/mac/PageClientImpl.h:
+        * UIProcess/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame):
+        (WebKit::PageClientImpl::didFinishLoadForMainFrame):
+        (WebKit::PageClientImpl::removeNavigationGestureSnapshot):
+        Plumb didFirstVisuallyNonEmptyLayoutForMainFrame and didFinishLoadForMainFrame
+        through to ViewGestureController from WebPageProxy via the PageClient, etc.
+
+        Ditto for removeNavigationGestureSnapshot, though it is called from a
+        VoidCallback in ViewGestureController instead of from WebFrameLoaderClient and friends.
+
+        * UIProcess/mac/ViewGestureController.h:
+        * UIProcess/mac/ViewGestureControllerMac.mm:
+        (WebKit::ViewGestureController::ViewGestureController):
+        (WebKit::ViewGestureController::endSwipeGesture):
+        When finishing a swipe, we want to wait for both the first visually non-empty layout
+        and the render tree size threshold being hit.
+
+        (WebKit::ViewGestureController::didHitRenderTreeSizeThreshold):
+        (WebKit::ViewGestureController::didFirstVisuallyNonEmptyLayoutForMainFrame):
+        When both of these things have happened, remove the swipe snapshot (after forcing a repaint).
+        For didFirstVisuallyNonEmptyLayoutForMainFrame, we will also start a watchdog
+        ensuring that we remove the snapshot in three seconds.
+
+        (WebKit::ViewGestureController::didFinishLoadForMainFrame):
+        When didFinishLoadForMainFrame happens, remove the swipe snapshot (after forcing a repaint).
+
+        (WebKit::ViewGestureController::swipeSnapshotWatchdogTimerFired):
+        If the watchdog timer fires, remove the swipe snapshot (after forcing a repaint).
+
+        (WebKit::ViewGestureController::removeSwipeSnapshotAfterRepaint):
+        Force a repaint and wait for the async callback before removing the snapshot.
+        It is safe to hold on to the WebPageProxy here because it will always
+        call all of its callbacks before it is destroyed.
+        Avoid enqueuing multiple force-repaints.
+
+        (WebKit::ViewGestureController::removeSwipeSnapshot):
+
</ins><span class="cx"> 2014-08-15  Gavin Barraclough  &lt;barraclough@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix plugin visibility initialization
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacWKViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -3598,6 +3598,24 @@
</span><span class="cx"> 
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+- (void)_didFirstVisuallyNonEmptyLayoutForMainFrame
+{
+    if (_data-&gt;_gestureController)
+        _data-&gt;_gestureController-&gt;didFirstVisuallyNonEmptyLayoutForMainFrame();
+}
+
+- (void)_didFinishLoadForMainFrame
+{
+    if (_data-&gt;_gestureController)
+        _data-&gt;_gestureController-&gt;didFinishLoadForMainFrame();
+}
+
+- (void)_removeNavigationGestureSnapshot
+{
+    if (_data-&gt;_gestureController)
+        _data-&gt;_gestureController-&gt;removeSwipeSnapshot();
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @implementation WKView (Private)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacWKViewInternalh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -107,6 +107,10 @@
</span><span class="cx"> - (void)_setSuppressVisibilityUpdates:(BOOL)suppressVisibilityUpdates;
</span><span class="cx"> - (BOOL)_suppressVisibilityUpdates;
</span><span class="cx"> 
</span><ins>+- (void)_didFirstVisuallyNonEmptyLayoutForMainFrame;
+- (void)_didFinishLoadForMainFrame;
+- (void)_removeNavigationGestureSnapshot;
+
</ins><span class="cx"> #if WK_API_ENABLED
</span><span class="cx"> @property (nonatomic, setter=_setThumbnailView:) _WKThumbnailView *_thumbnailView;
</span><span class="cx"> - (void)_reparentLayerTreeInThumbnailView;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageClient.h        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -229,6 +229,7 @@
</span><span class="cx">     virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText) = 0;
</span><span class="cx">     virtual void recordAutocorrectionResponse(WebCore::AutocorrectionResponseType, const String&amp; replacedString, const String&amp; replacementString) = 0;
</span><span class="cx">     virtual void recommendedScrollbarStyleDidChange(int32_t newStyle) = 0;
</span><ins>+    virtual void removeNavigationGestureSnapshot() = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual ColorSpaceData colorSpace() = 0;
</span><span class="cx"> 
</span><span class="lines">@@ -301,6 +302,9 @@
</span><span class="cx">     virtual void navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem&amp;) = 0;
</span><span class="cx">     virtual void navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem&amp;) = 0;
</span><span class="cx">     virtual void willRecordNavigationSnapshot(WebBackForwardListItem&amp;) = 0;
</span><ins>+
+    virtual void didFirstVisuallyNonEmptyLayoutForMainFrame() = 0;
+    virtual void didFinishLoadForMainFrame() = 0;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -2654,13 +2654,17 @@
</span><span class="cx"> 
</span><span class="cx">     auto transaction = m_pageLoadState.transaction();
</span><span class="cx"> 
</span><del>-    if (frame-&gt;isMainFrame())
</del><ins>+    bool isMainFrame = frame-&gt;isMainFrame();
+    if (isMainFrame)
</ins><span class="cx">         m_pageLoadState.didFinishLoad(transaction);
</span><span class="cx"> 
</span><span class="cx">     frame-&gt;didFinishLoad();
</span><span class="cx"> 
</span><span class="cx">     m_pageLoadState.commitChanges();
</span><span class="cx">     m_loaderClient-&gt;didFinishLoadForFrame(this, frame, navigationID, userData.get());
</span><ins>+
+    if (isMainFrame)
+        m_pageClient.didFinishLoadForMainFrame();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError&amp; error, IPC::MessageDecoder&amp; decoder)
</span><span class="lines">@@ -2754,6 +2758,9 @@
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx"> 
</span><span class="cx">     m_loaderClient-&gt;didFirstVisuallyNonEmptyLayoutForFrame(this, frame, userData.get());
</span><ins>+
+    if (frame-&gt;isMainFrame())
+        m_pageClient.didFirstVisuallyNonEmptyLayoutForMainFrame();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didLayout(uint32_t layoutMilestones, IPC::MessageDecoder&amp; decoder)
</span><span class="lines">@@ -5174,4 +5181,9 @@
</span><span class="cx">     recordNavigationSnapshot();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::removeNavigationGestureSnapshot()
+{
+    m_pageClient.removeNavigationGestureSnapshot();
+}
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -910,6 +910,7 @@
</span><span class="cx">     void willRecordNavigationSnapshot(WebBackForwardListItem&amp;);
</span><span class="cx"> 
</span><span class="cx">     bool isShowingNavigationGestureSnapshot() const { return m_isShowingNavigationGestureSnapshot; }
</span><ins>+    void removeNavigationGestureSnapshot();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     WebPageProxy(PageClient&amp;, WebProcessProxy&amp;, uint64_t pageID, const WebPageConfiguration&amp;);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosPageClientImplIOSh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -175,6 +175,9 @@
</span><span class="cx">     virtual void navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem&amp;) override;
</span><span class="cx">     virtual void willRecordNavigationSnapshot(WebBackForwardListItem&amp;) override;
</span><span class="cx"> 
</span><ins>+    virtual void didFirstVisuallyNonEmptyLayoutForMainFrame() override;
+    virtual void didFinishLoadForMainFrame() override;
+
</ins><span class="cx">     WKContentView *m_contentView;
</span><span class="cx">     WKWebView *m_webView;
</span><span class="cx">     RetainPtr&lt;WKEditorUndoTargetObjC&gt; m_undoTarget;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosPageClientImplIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -682,6 +682,14 @@
</span><span class="cx">     NavigationState::fromWebPage(*m_webView-&gt;_page).willRecordNavigationSnapshot(item);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
+{
+}
+
+void PageClientImpl::didFinishLoadForMainFrame()
+{
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // PLATFORM(IOS)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacPageClientImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -179,6 +179,10 @@
</span><span class="cx"> 
</span><span class="cx">     NSView *activeView() const;
</span><span class="cx"> 
</span><ins>+    virtual void didFirstVisuallyNonEmptyLayoutForMainFrame() override;
+    virtual void didFinishLoadForMainFrame() override;
+    virtual void removeNavigationGestureSnapshot() override;
+
</ins><span class="cx">     WKView *m_wkView;
</span><span class="cx">     WKWebView *m_webView;
</span><span class="cx">     RetainPtr&lt;WKEditorUndoTargetObjC&gt; m_undoTarget;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacPageClientImplmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -722,6 +722,21 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
+{
+    [m_wkView _didFirstVisuallyNonEmptyLayoutForMainFrame];
+}
+
+void PageClientImpl::didFinishLoadForMainFrame()
+{
+    [m_wkView _didFinishLoadForMainFrame];
+}
+
+void PageClientImpl::removeNavigationGestureSnapshot()
+{
+    [m_wkView _removeNavigationGestureSnapshot];
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // PLATFORM(MAC)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacViewGestureControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -104,6 +104,9 @@
</span><span class="cx"> 
</span><span class="cx">     bool shouldIgnorePinnedState() { return m_shouldIgnorePinnedState; }
</span><span class="cx">     void setShouldIgnorePinnedState(bool ignore) { m_shouldIgnorePinnedState = ignore; }
</span><ins>+
+    void didFirstVisuallyNonEmptyLayoutForMainFrame();
+    void didFinishLoadForMainFrame();
</ins><span class="cx"> #else
</span><span class="cx">     void installSwipeHandler(UIView *gestureRecognizerView, UIView *swipingView);
</span><span class="cx">     void setAlternateBackForwardListSourceView(WKWebView *);
</span><span class="lines">@@ -114,11 +117,12 @@
</span><span class="cx">     void setRenderTreeSize(uint64_t);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    void removeSwipeSnapshot();
+
</ins><span class="cx"> private:
</span><span class="cx">     // IPC::MessageReceiver.
</span><span class="cx">     virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&amp;) override;
</span><del>-    
-    void removeSwipeSnapshot();
</del><ins>+
</ins><span class="cx">     void swipeSnapshotWatchdogTimerFired();
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="lines">@@ -126,6 +130,7 @@
</span><span class="cx">     void didCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds, bool frameHandlesMagnificationGesture);
</span><span class="cx">     void didCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool isReplacedElement, double viewportMinimumScale, double viewportMaximumScale);
</span><span class="cx">     void didHitRenderTreeSizeThreshold();
</span><ins>+    void removeSwipeSnapshotAfterRepaint();
</ins><span class="cx"> 
</span><span class="cx">     void endMagnificationGesture();
</span><span class="cx">     WebCore::FloatPoint scaledMagnificationOrigin(WebCore::FloatPoint origin, double scale);
</span><span class="lines">@@ -145,7 +150,7 @@
</span><span class="cx"> 
</span><span class="cx">     WebPageProxy&amp; m_webPageProxy;
</span><span class="cx">     ViewGestureType m_activeGestureType;
</span><del>-    
</del><ins>+
</ins><span class="cx">     RunLoop::Timer&lt;ViewGestureController&gt; m_swipeWatchdogTimer;
</span><span class="cx"> 
</span><span class="cx"> #if USE(IOSURFACE)
</span><span class="lines">@@ -181,6 +186,10 @@
</span><span class="cx">     WebCore::FloatSize m_cumulativeDeltaForPendingSwipe;
</span><span class="cx"> 
</span><span class="cx">     bool m_shouldIgnorePinnedState;
</span><ins>+
+    bool m_swipeWaitingForVisuallyNonEmptyLayout;
+    bool m_swipeWaitingForRenderTreeSizeThreshold;
+    bool m_swipeWaitingForRepaint;
</ins><span class="cx"> #else    
</span><span class="cx">     UIView *m_liveSwipeView;
</span><span class="cx">     RetainPtr&lt;UIView&gt; m_liveSwipeViewClippingView;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacViewGestureControllerMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureControllerMac.mm (172634 => 172635)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureControllerMac.mm        2014-08-15 18:26:34 UTC (rev 172634)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureControllerMac.mm        2014-08-15 18:42:24 UTC (rev 172635)
</span><span class="lines">@@ -105,6 +105,9 @@
</span><span class="cx">     , m_customSwipeViewsTopContentInset(0)
</span><span class="cx">     , m_pendingSwipeReason(PendingSwipeReason::None)
</span><span class="cx">     , m_shouldIgnorePinnedState(false)
</span><ins>+    , m_swipeWaitingForVisuallyNonEmptyLayout(false)
+    , m_swipeWaitingForRenderTreeSizeThreshold(false)
+    , m_swipeWaitingForRepaint(false)
</ins><span class="cx"> {
</span><span class="cx">     m_webPageProxy.process().addMessageReceiver(Messages::ViewGestureController::messageReceiverName(), m_webPageProxy.pageID(), *this);
</span><span class="cx"> }
</span><span class="lines">@@ -641,29 +644,70 @@
</span><span class="cx"> 
</span><span class="cx">     m_webPageProxy.process().send(Messages::ViewGestureGeometryCollector::SetRenderTreeSizeNotificationThreshold(renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction), m_webPageProxy.pageID());
</span><span class="cx"> 
</span><ins>+    m_swipeWaitingForVisuallyNonEmptyLayout = true;
+    m_swipeWaitingForRenderTreeSizeThreshold = true;
+
</ins><span class="cx">     m_webPageProxy.navigationGestureDidEnd(true, *targetItem);
</span><span class="cx">     m_webPageProxy.goToBackForwardItem(targetItem);
</span><ins>+}
</ins><span class="cx"> 
</span><del>-    if (!renderTreeSize) {
-        removeSwipeSnapshot();
</del><ins>+void ViewGestureController::didHitRenderTreeSizeThreshold()
+{
+    if (m_activeGestureType != ViewGestureType::Swipe)
</ins><span class="cx">         return;
</span><del>-    }
</del><span class="cx"> 
</span><del>-    m_swipeWatchdogTimer.startOneShot(swipeSnapshotRemovalWatchdogDuration.count());
</del><ins>+    m_swipeWaitingForRenderTreeSizeThreshold = false;
+
+    if (!m_swipeWaitingForVisuallyNonEmptyLayout)
+        removeSwipeSnapshotAfterRepaint();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ViewGestureController::didHitRenderTreeSizeThreshold()
</del><ins>+void ViewGestureController::didFirstVisuallyNonEmptyLayoutForMainFrame()
</ins><span class="cx"> {
</span><del>-    removeSwipeSnapshot();
</del><ins>+    if (m_activeGestureType != ViewGestureType::Swipe)
+        return;
+
+    m_swipeWaitingForVisuallyNonEmptyLayout = false;
+
+    if (!m_swipeWaitingForRenderTreeSizeThreshold)
+        removeSwipeSnapshotAfterRepaint();
+    else
+        m_swipeWatchdogTimer.startOneShot(swipeSnapshotRemovalWatchdogDuration.count());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ViewGestureController::didFinishLoadForMainFrame()
+{
+    if (m_activeGestureType != ViewGestureType::Swipe)
+        return;
+
+    removeSwipeSnapshotAfterRepaint();
+}
+
</ins><span class="cx"> void ViewGestureController::swipeSnapshotWatchdogTimerFired()
</span><span class="cx"> {
</span><del>-    removeSwipeSnapshot();
</del><ins>+    removeSwipeSnapshotAfterRepaint();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ViewGestureController::removeSwipeSnapshotAfterRepaint()
+{
+    if (m_activeGestureType != ViewGestureType::Swipe)
+        return;
+
+    if (m_swipeWaitingForRepaint)
+        return;
+
+    m_swipeWaitingForRepaint = true;
+
+    WebPageProxy* webPageProxy = &amp;m_webPageProxy;
+    m_webPageProxy.forceRepaint(VoidCallback::create([webPageProxy] (CallbackBase::Error error) {
+        webPageProxy-&gt;removeNavigationGestureSnapshot();
+    }));
+}
+
</ins><span class="cx"> void ViewGestureController::removeSwipeSnapshot()
</span><span class="cx"> {
</span><ins>+    m_swipeWaitingForRepaint = false;
+
</ins><span class="cx">     m_swipeWatchdogTimer.stop();
</span><span class="cx"> 
</span><span class="cx">     if (m_activeGestureType != ViewGestureType::Swipe)
</span></span></pre>
</div>
</div>

</body>
</html>