Title: [170035] trunk/Source/WebKit2
Revision
170035
Author
[email protected]
Date
2014-06-16 16:45:27 -0700 (Mon, 16 Jun 2014)

Log Message

[iOS][wk2] Swiping back briefly shows the previous page before loading the new one
https://bugs.webkit.org/show_bug.cgi?id=133885

Reviewed by Simon Fraser.

Remove a race between the UI and Web processes when removing the swipe snapshot.
Previously, it was possible to get a commit from the Web process with layer content
(and render tree size) from the previous page *after* sending the navigation request
to the page, because of the asynchronicity of layer tree commits. This could cause
the snapshot to be removed early (if the previous fully-loaded page had a sufficiently
large render tree size), revealing the old tiles underneath the snapshot.

* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::transactionID):
(WebKit::RemoteLayerTreeTransaction::setTransactionID):
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode):
(WebKit::RemoteLayerTreeTransaction::decode):
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::lastVisibleTransactionID):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers):
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea):
(WebKit::RemoteLayerTreeDrawingArea::flushLayers):
(WebKit::RemoteLayerTreeDrawingArea::didUpdate):
Keep track of an ever-increasing transaction ID in RemoteLayerTreeDrawingArea(Proxy).
It increments in the UI process at didUpdate time, because the Web process cannot
have started on a new layer tree commit until didUpdate is sent.
It increments in the Web process at commit time.

* UIProcess/ios/ViewGestureControllerIOS.mm:
(WebKit::ViewGestureController::endSwipeGesture):
(WebKit::ViewGestureController::setRenderTreeSize):
* UIProcess/mac/ViewGestureController.h:
Adopt transaction IDs; don't remove the snapshot until the commit
that includes the navigation arrives.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (170034 => 170035)


--- trunk/Source/WebKit2/ChangeLog	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/ChangeLog	2014-06-16 23:45:27 UTC (rev 170035)
@@ -1,3 +1,47 @@
+2014-06-16  Timothy Horton  <[email protected]>
+
+        [iOS][wk2] Swiping back briefly shows the previous page before loading the new one
+        https://bugs.webkit.org/show_bug.cgi?id=133885
+
+        Reviewed by Simon Fraser.
+
+        Remove a race between the UI and Web processes when removing the swipe snapshot.
+        Previously, it was possible to get a commit from the Web process with layer content
+        (and render tree size) from the previous page *after* sending the navigation request
+        to the page, because of the asynchronicity of layer tree commits. This could cause
+        the snapshot to be removed early (if the previous fully-loaded page had a sufficiently
+        large render tree size), revealing the old tiles underneath the snapshot.
+
+        * Shared/mac/RemoteLayerTreeTransaction.h:
+        (WebKit::RemoteLayerTreeTransaction::transactionID):
+        (WebKit::RemoteLayerTreeTransaction::setTransactionID):
+        * Shared/mac/RemoteLayerTreeTransaction.mm:
+        (WebKit::RemoteLayerTreeTransaction::encode):
+        (WebKit::RemoteLayerTreeTransaction::decode):
+        * UIProcess/DrawingAreaProxy.h:
+        (WebKit::DrawingAreaProxy::lastVisibleTransactionID):
+        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
+        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers):
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea):
+        (WebKit::RemoteLayerTreeDrawingArea::flushLayers):
+        (WebKit::RemoteLayerTreeDrawingArea::didUpdate):
+        Keep track of an ever-increasing transaction ID in RemoteLayerTreeDrawingArea(Proxy).
+        It increments in the UI process at didUpdate time, because the Web process cannot
+        have started on a new layer tree commit until didUpdate is sent.
+        It increments in the Web process at commit time.
+
+        * UIProcess/ios/ViewGestureControllerIOS.mm:
+        (WebKit::ViewGestureController::endSwipeGesture):
+        (WebKit::ViewGestureController::setRenderTreeSize):
+        * UIProcess/mac/ViewGestureController.h:
+        Adopt transaction IDs; don't remove the snapshot until the commit
+        that includes the navigation arrives.
+
 2014-06-16  Dan Bernstein  <[email protected]>
 
         <rdar://problem/17327707> [Cocoa] Expose WebPreferences::storageBlockingPolicy

Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.h (170034 => 170035)


--- trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.h	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.h	2014-06-16 23:45:27 UTC (rev 170035)
@@ -204,6 +204,9 @@
 
     bool allowsUserScaling() const { return m_allowsUserScaling; }
     void setAllowsUserScaling(bool allowsUserScaling) { m_allowsUserScaling = allowsUserScaling; }
+
+    uint64_t transactionID() const { return m_transactionID; }
+    void setTransactionID(uint64_t transactionID) { m_transactionID = transactionID; }
     
 private:
     WebCore::GraphicsLayer::PlatformLayerID m_rootLayerID;
@@ -221,6 +224,7 @@
     double m_minimumScaleFactor;
     double m_maximumScaleFactor;
     uint64_t m_renderTreeSize;
+    uint64_t m_transactionID;
     bool m_scaleWasSetByUIProcess;
     bool m_allowsUserScaling;
 };

Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm (170034 => 170035)


--- trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm	2014-06-16 23:45:27 UTC (rev 170035)
@@ -461,6 +461,7 @@
     encoder << m_maximumScaleFactor;
 
     encoder << m_renderTreeSize;
+    encoder << m_transactionID;
 
     encoder << m_scaleWasSetByUIProcess;
     encoder << m_allowsUserScaling;
@@ -529,6 +530,9 @@
     if (!decoder.decode(result.m_renderTreeSize))
         return false;
 
+    if (!decoder.decode(result.m_transactionID))
+        return false;
+
     if (!decoder.decode(result.m_scaleWasSetByUIProcess))
         return false;
 

Modified: trunk/Source/WebKit2/UIProcess/DrawingAreaProxy.h (170034 => 170035)


--- trunk/Source/WebKit2/UIProcess/DrawingAreaProxy.h	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/UIProcess/DrawingAreaProxy.h	2014-06-16 23:45:27 UTC (rev 170035)
@@ -85,6 +85,8 @@
     virtual void showDebugIndicator(bool) { }
     virtual bool isShowingDebugIndicator() const { return false; }
 
+    virtual uint64_t lastVisibleTransactionID() const { ASSERT_NOT_REACHED(); return 0; }
+
 protected:
     explicit DrawingAreaProxy(DrawingAreaType, WebPageProxy*);
 

Modified: trunk/Source/WebKit2/UIProcess/ios/ViewGestureControllerIOS.mm (170034 => 170035)


--- trunk/Source/WebKit2/UIProcess/ios/ViewGestureControllerIOS.mm	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/UIProcess/ios/ViewGestureControllerIOS.mm	2014-06-16 23:45:27 UTC (rev 170035)
@@ -127,7 +127,7 @@
     : m_webPageProxy(webPageProxy)
     , m_activeGestureType(ViewGestureType::None)
     , m_swipeWatchdogTimer(this, &ViewGestureController::swipeSnapshotWatchdogTimerFired)
-    , m_targetRenderTreeSize(0)
+    , m_snapshotRemovalTargetRenderTreeSize(0)
 {
 }
 
@@ -225,9 +225,10 @@
     }
 
     ViewSnapshot snapshot;
-    m_targetRenderTreeSize = 0;
+    m_snapshotRemovalTargetRenderTreeSize = 0;
     if (ViewSnapshotStore::shared().getSnapshot(targetItem, snapshot))
-        m_targetRenderTreeSize = snapshot.renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction;
+        m_snapshotRemovalTargetRenderTreeSize = snapshot.renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction;
+    m_snapshotRemovalTargetTransactionID = m_webPageProxy.drawingArea()->lastVisibleTransactionID() + 1;
 
     // We don't want to replace the current back-forward item's snapshot
     // like we normally would when going back or forward, because we are
@@ -236,7 +237,7 @@
     m_webPageProxy.goToBackForwardItem(targetItem);
     ViewSnapshotStore::shared().enableSnapshotting();
     
-    if (!m_targetRenderTreeSize) {
+    if (!m_snapshotRemovalTargetRenderTreeSize) {
         removeSwipeSnapshot();
         return;
     }
@@ -249,7 +250,10 @@
     if (m_activeGestureType != ViewGestureType::Swipe)
         return;
 
-    if (m_targetRenderTreeSize && renderTreeSize > m_targetRenderTreeSize)
+    // Don't remove the swipe snapshot until we get a drawing area transaction more recent than the navigation,
+    // and we hit the render tree size threshold. This avoids potentially removing the snapshot early,
+    // when receiving commits from the previous (pre-navigation) page.
+    if (m_snapshotRemovalTargetRenderTreeSize && renderTreeSize > m_snapshotRemovalTargetRenderTreeSize && m_webPageProxy.drawingArea()->lastVisibleTransactionID() >= m_snapshotRemovalTargetTransactionID)
         removeSwipeSnapshot();
 }
 
@@ -274,7 +278,7 @@
     [m_snapshotView removeFromSuperview];
     m_snapshotView = nullptr;
     
-    m_targetRenderTreeSize = 0;
+    m_snapshotRemovalTargetRenderTreeSize = 0;
     m_activeGestureType = ViewGestureType::None;
 }
 

Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h (170034 => 170035)


--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h	2014-06-16 23:45:27 UTC (rev 170035)
@@ -76,6 +76,8 @@
     
     void sendUpdateGeometry();
 
+    virtual uint64_t lastVisibleTransactionID() const override { return m_lastVisibleTransactionID; }
+
     RemoteLayerTreeHost m_remoteLayerTreeHost;
     bool m_isWaitingForDidUpdateGeometry;
 
@@ -87,6 +89,9 @@
     RetainPtr<CALayer> m_exposedRectIndicatorLayer;
 
     std::unique_ptr<WebCore::RunLoopObserver> m_layerCommitObserver;
+
+    uint64_t m_lastVisibleTransactionID;
+    uint64_t m_transactionIDForPendingCACommit;
 };
 
 DRAWING_AREA_PROXY_TYPE_CASTS(RemoteLayerTreeDrawingAreaProxy, type() == DrawingAreaTypeRemoteLayerTree);

Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm (170034 => 170035)


--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm	2014-06-16 23:45:27 UTC (rev 170035)
@@ -47,6 +47,7 @@
     : DrawingAreaProxy(DrawingAreaTypeRemoteLayerTree, webPageProxy)
     , m_remoteLayerTreeHost(*this)
     , m_isWaitingForDidUpdateGeometry(false)
+    , m_lastVisibleTransactionID(0)
 {
 #if USE(IOSURFACE)
     // We don't want to pool surfaces in the UI process.
@@ -119,6 +120,9 @@
     LOG(RemoteLayerTree, "%s", layerTreeTransaction.description().data());
     LOG(RemoteLayerTree, "%s", scrollingTreeTransaction.description().data());
 
+    ASSERT(layerTreeTransaction.transactionID() == m_lastVisibleTransactionID + 1);
+    m_transactionIDForPendingCACommit = layerTreeTransaction.transactionID();
+
     if (m_remoteLayerTreeHost.updateLayerTree(layerTreeTransaction))
         m_webPageProxy->setAcceleratedCompositingRootLayer(m_remoteLayerTreeHost.rootLayer());
 
@@ -305,6 +309,8 @@
     // using our backing store. We can improve this by waiting for the render server to commit
     // if we find API to do so, but for now we will make extra buffers if need be.
     m_webPageProxy->process().send(Messages::DrawingArea::DidUpdate(), m_webPageProxy->pageID());
+
+    m_lastVisibleTransactionID = m_transactionIDForPendingCACommit;
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h (170034 => 170035)


--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h	2014-06-16 23:45:27 UTC (rev 170035)
@@ -183,7 +183,8 @@
     RetainPtr<UIView> m_snapshotView;
     RetainPtr<UIView> m_transitionContainerView;
     RetainPtr<WKSwipeTransitionController> m_swipeInteractiveTransitionDelegate;
-    uint64_t m_targetRenderTreeSize;
+    uint64_t m_snapshotRemovalTargetRenderTreeSize;
+    uint64_t m_snapshotRemovalTargetTransactionID;
 #endif
 };
 

Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h (170034 => 170035)


--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h	2014-06-16 23:45:27 UTC (rev 170035)
@@ -107,6 +107,8 @@
 
     WebCore::TiledBacking* mainFrameTiledBacking() const;
 
+    uint64_t takeNextTransactionID() { return ++m_currentTransactionID; }
+
     class BackingStoreFlusher : public ThreadSafeRefCounted<BackingStoreFlusher> {
     public:
         static PassRefPtr<BackingStoreFlusher> create(IPC::Connection*, std::unique_ptr<IPC::MessageEncoder>, Vector<RetainPtr<CGContextRef>>);
@@ -144,6 +146,8 @@
 
     HashSet<RemoteLayerTreeDisplayRefreshMonitor*> m_displayRefreshMonitors;
     HashSet<RemoteLayerTreeDisplayRefreshMonitor*>* m_displayRefreshMonitorsToNotify;
+
+    uint64_t m_currentTransactionID;
 };
 
 DRAWING_AREA_TYPE_CASTS(RemoteLayerTreeDrawingArea, type() == DrawingAreaTypeRemoteLayerTree);

Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm (170034 => 170035)


--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm	2014-06-16 23:19:29 UTC (rev 170034)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm	2014-06-16 23:45:27 UTC (rev 170035)
@@ -62,6 +62,7 @@
     , m_waitingForBackingStoreSwap(false)
     , m_hadFlushDeferredWhileWaitingForBackingStoreSwap(false)
     , m_displayRefreshMonitorsToNotify(nullptr)
+    , m_currentTransactionID(0)
 {
     webPage->corePage()->settings().setForceCompositingMode(true);
 #if PLATFORM(IOS)
@@ -275,6 +276,7 @@
 
     // FIXME: Minimize these transactions if nothing changed.
     RemoteLayerTreeTransaction layerTransaction;
+    layerTransaction.setTransactionID(takeNextTransactionID());
     m_remoteLayerTreeContext->buildTransaction(layerTransaction, *toGraphicsLayerCARemote(m_rootLayer.get())->platformCALayer());
     backingStoreCollection.willCommitLayerTree(layerTransaction);
     m_webPage->willCommitLayerTree(layerTransaction);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to