⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 236500 in webkit


Ignore:
Timestamp:
Sep 26, 2018, 5:06:11 AM (8 years ago)
Author:
Antti Koivisto
Message:

REGRESSION (PSON): White or Black flash occurs when process swapping on navigation on iOS
https://bugs.webkit.org/show_bug.cgi?id=189695
<rdar://problem/44551146>

Reviewed by Simon Fraser.

Freeze the layers on UI process side during process swap.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _processWillChange]):

Shared work of _processWillSwap and _processDidExit.

(-[WKWebView _processWillSwap]):
(-[WKWebView _processDidExit]):

Split into two functions. Don't reset scroll position and similar when doing navigation swap.

  • UIProcess/API/Cocoa/WKWebViewInternal.h:
  • UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
  • UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:

(WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
(WebKit::RemoteLayerTreeDrawingAreaProxy::detachRemoteLayerTreeHost):

Add to way to detach RemoteLayerTreeHost from the drawing area. Inert RemoteLayerTreeHost will host
the frozen layers.

(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::updateDebugIndicator):
(WebKit::RemoteLayerTreeDrawingAreaProxy::hideContentUntilPendingUpdate):
(WebKit::RemoteLayerTreeDrawingAreaProxy::hideContentUntilAnyUpdate):
(WebKit::RemoteLayerTreeDrawingAreaProxy::prepareForAppSuspension):
(WebKit::RemoteLayerTreeDrawingAreaProxy::hasVisibleContent const):
(WebKit::RemoteLayerTreeDrawingAreaProxy::layerWithIDForTesting const):

  • UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h:
  • UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm:

(WebKit::RemoteLayerTreeHost::RemoteLayerTreeHost):
(WebKit::RemoteLayerTreeHost::updateLayerTree):
(WebKit::RemoteLayerTreeHost::animationDidStart):
(WebKit::RemoteLayerTreeHost::animationDidEnd):
(WebKit::RemoteLayerTreeHost::detachFromDrawingArea):

Clear the DrawingArea backpointer.

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::continueNavigationInNewProcess):
(WebKit::WebPageProxy::resetState):

Detach and save the current RemoteLayerTreeHost on navigation swap.

  • UIProcess/WebPageProxy.h:
  • UIProcess/ios/PageClientImplIOS.mm:

(WebKit::PageClientImpl::processWillSwap):

Avoid reseting the scroll position.

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::setAcceleratedCompositingRootLayer):

Drop the frozen layers after setting the new root layer.

  • UIProcess/mac/WebPageProxyMac.mm:

(WebKit::WebPageProxy::setAcceleratedCompositingRootLayer):

For completeness do this also on Mac (where remote layers are currently not used).

Location:
trunk/Source/WebKit
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r236497 r236500  
     12018-09-26  Antti Koivisto  <antti@apple.com>
     2
     3        REGRESSION (PSON): White or Black flash occurs when process swapping on navigation on iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=189695
     5        <rdar://problem/44551146>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Freeze the layers on UI process side during process swap.
     10
     11        * UIProcess/API/Cocoa/WKWebView.mm:
     12        (-[WKWebView _processWillChange]):
     13
     14        Shared work of _processWillSwap and _processDidExit.
     15
     16        (-[WKWebView _processWillSwap]):
     17        (-[WKWebView _processDidExit]):
     18
     19        Split into two functions. Don't reset scroll position and similar when doing navigation swap.
     20
     21        * UIProcess/API/Cocoa/WKWebViewInternal.h:
     22        * UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
     23        * UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:
     24        (WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
     25        (WebKit::RemoteLayerTreeDrawingAreaProxy::detachRemoteLayerTreeHost):
     26
     27        Add to way to detach RemoteLayerTreeHost from the drawing area. Inert RemoteLayerTreeHost will host
     28        the frozen layers.
     29
     30        (WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
     31        (WebKit::RemoteLayerTreeDrawingAreaProxy::updateDebugIndicator):
     32        (WebKit::RemoteLayerTreeDrawingAreaProxy::hideContentUntilPendingUpdate):
     33        (WebKit::RemoteLayerTreeDrawingAreaProxy::hideContentUntilAnyUpdate):
     34        (WebKit::RemoteLayerTreeDrawingAreaProxy::prepareForAppSuspension):
     35        (WebKit::RemoteLayerTreeDrawingAreaProxy::hasVisibleContent const):
     36        (WebKit::RemoteLayerTreeDrawingAreaProxy::layerWithIDForTesting const):
     37        * UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h:
     38        * UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm:
     39        (WebKit::RemoteLayerTreeHost::RemoteLayerTreeHost):
     40        (WebKit::RemoteLayerTreeHost::updateLayerTree):
     41        (WebKit::RemoteLayerTreeHost::animationDidStart):
     42        (WebKit::RemoteLayerTreeHost::animationDidEnd):
     43        (WebKit::RemoteLayerTreeHost::detachFromDrawingArea):
     44
     45        Clear the DrawingArea backpointer.
     46
     47        * UIProcess/WebPageProxy.cpp:
     48        (WebKit::WebPageProxy::continueNavigationInNewProcess):
     49        (WebKit::WebPageProxy::resetState):
     50
     51        Detach and save the current RemoteLayerTreeHost on navigation swap.
     52
     53        * UIProcess/WebPageProxy.h:
     54        * UIProcess/ios/PageClientImplIOS.mm:
     55        (WebKit::PageClientImpl::processWillSwap):
     56
     57        Avoid reseting the scroll position.
     58
     59        * UIProcess/ios/WebPageProxyIOS.mm:
     60        (WebKit::WebPageProxy::setAcceleratedCompositingRootLayer):
     61
     62        Drop the frozen layers after setting the new root layer.
     63
     64        * UIProcess/mac/WebPageProxyMac.mm:
     65        (WebKit::WebPageProxy::setAcceleratedCompositingRootLayer):
     66
     67        For completeness do this also on Mac (where remote layers are currently not used).
     68
    1692018-09-25  Ryosuke Niwa  <rniwa@webkit.org>
    270
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r236086 r236500  
    16551655}
    16561656
    1657 - (void)_processDidExit
    1658 {
    1659     RELEASE_LOG_IF_ALLOWED("%p -[WKWebView _processDidExit]", self);
     1657- (void)_processWillSwapOrDidExit
     1658{
     1659    // FIXME: Which ones of these need to be done in the process swap case and which ones in the exit case?
    16601660    [self _hidePasswordView];
    16611661    [self _cancelAnimatedResize];
    1662     [_contentView setFrame:self.bounds];
    1663     [_scrollView setBackgroundColor:[UIColor whiteColor]];
    1664     [_scrollView setContentOffset:[self _initialContentOffsetForScrollView]];
    1665     [_scrollView setZoomScale:1];
    16661662
    16671663    _viewportMetaTagWidth = WebCore::ViewportArguments::ValueAuto;
     
    16941690
    16951691    _avoidsUnsafeArea = YES;
     1692}
     1693
     1694- (void)_processWillSwap
     1695{
     1696    RELEASE_LOG_IF_ALLOWED("%p -[WKWebView _processWillSwap]", self);
     1697    [self _processWillSwapOrDidExit];
     1698}
     1699
     1700- (void)_processDidExit
     1701{
     1702    RELEASE_LOG_IF_ALLOWED("%p -[WKWebView _processDidExit]", self);
     1703
     1704    [self _processWillSwapOrDidExit];
     1705
     1706    [_contentView setFrame:self.bounds];
     1707    [_scrollView setBackgroundColor:[UIColor whiteColor]];
     1708    [_scrollView setContentOffset:[self _initialContentOffsetForScrollView]];
     1709    [_scrollView setZoomScale:1];
     1710   
    16961711}
    16971712
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h

    r235925 r236500  
    8383#if PLATFORM(IOS)
    8484- (void)_processDidExit;
     85- (void)_processWillSwap;
    8586- (void)_didRelaunchProcess;
    8687
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h

    r233781 r236500  
    4444    virtual ~RemoteLayerTreeDrawingAreaProxy();
    4545
    46     const RemoteLayerTreeHost& remoteLayerTreeHost() const { return m_remoteLayerTreeHost; }
     46    const RemoteLayerTreeHost& remoteLayerTreeHost() const { return *m_remoteLayerTreeHost; }
     47    std::unique_ptr<RemoteLayerTreeHost> detachRemoteLayerTreeHost();
    4748
    4849    void acceleratedAnimationDidStart(uint64_t layerID, const String& key, MonotonicTime startTime);
     
    101102    void sendUpdateGeometry();
    102103
    103     RemoteLayerTreeHost m_remoteLayerTreeHost;
     104    std::unique_ptr<RemoteLayerTreeHost> m_remoteLayerTreeHost;
    104105    bool m_isWaitingForDidUpdateGeometry { false };
    105106    enum DidUpdateMessageState { DoesNotNeedDidUpdate, NeedsDidUpdate, MissedCommit };
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm

    r235265 r236500  
    108108RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy(WebPageProxy& webPageProxy)
    109109    : DrawingAreaProxy(DrawingAreaTypeRemoteLayerTree, webPageProxy)
    110     , m_remoteLayerTreeHost(*this)
     110    , m_remoteLayerTreeHost(std::make_unique<RemoteLayerTreeHost>(*this))
    111111{
    112112#if HAVE(IOSURFACE)
     
    132132}
    133133
     134
     135std::unique_ptr<RemoteLayerTreeHost> RemoteLayerTreeDrawingAreaProxy::detachRemoteLayerTreeHost()
     136{
     137    m_remoteLayerTreeHost->detachFromDrawingArea();
     138    return WTFMove(m_remoteLayerTreeHost);
     139}
     140
     141
    134142#if PLATFORM(IOS)
    135143WKOneShotDisplayLinkHandler *RemoteLayerTreeDrawingAreaProxy::displayLinkHandler()
     
    195203        m_webPageProxy.editorStateChanged(layerTreeTransaction.editorState());
    196204
    197     if (m_remoteLayerTreeHost.updateLayerTree(layerTreeTransaction)) {
     205    if (m_remoteLayerTreeHost->updateLayerTree(layerTreeTransaction)) {
    198206        if (layerTreeTransaction.transactionID() >= m_transactionIDForUnhidingContent)
    199             m_webPageProxy.setAcceleratedCompositingRootLayer(m_remoteLayerTreeHost.rootLayer());
     207            m_webPageProxy.setAcceleratedCompositingRootLayer(m_remoteLayerTreeHost->rootLayer());
    200208        else
    201             m_remoteLayerTreeHost.detachRootLayer();
     209            m_remoteLayerTreeHost->detachRootLayer();
    202210    }
    203211
     
    330338{
    331339    // Make sure we're the last sublayer.
    332     CALayer *rootLayer = asLayer(m_remoteLayerTreeHost.rootLayer());
     340    CALayer *rootLayer = asLayer(m_remoteLayerTreeHost->rootLayer());
    333341    [m_tileMapHostLayer removeFromSuperlayer];
    334342    [rootLayer addSublayer:m_tileMapHostLayer.get()];
     
    470478{
    471479    m_transactionIDForUnhidingContent = nextLayerTreeTransactionID();
    472     m_remoteLayerTreeHost.detachRootLayer();
     480    m_remoteLayerTreeHost->detachRootLayer();
    473481}
    474482
    475483void RemoteLayerTreeDrawingAreaProxy::hideContentUntilAnyUpdate()
    476484{
    477     m_remoteLayerTreeHost.detachRootLayer();
     485    m_remoteLayerTreeHost->detachRootLayer();
    478486}
    479487
    480488void RemoteLayerTreeDrawingAreaProxy::prepareForAppSuspension()
    481489{
    482     m_remoteLayerTreeHost.mapAllIOSurfaceBackingStore();
     490    m_remoteLayerTreeHost->mapAllIOSurfaceBackingStore();
    483491}
    484492
    485493bool RemoteLayerTreeDrawingAreaProxy::hasVisibleContent() const
    486494{
    487     return m_remoteLayerTreeHost.rootLayer();
     495    return m_remoteLayerTreeHost->rootLayer();
    488496}
    489497
     
    495503LayerOrView* RemoteLayerTreeDrawingAreaProxy::layerWithIDForTesting(uint64_t layerID) const
    496504{
    497     return m_remoteLayerTreeHost.layerWithIDForTesting(layerID);
     505    return m_remoteLayerTreeHost->layerWithIDForTesting(layerID);
    498506}
    499507
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h

    r229174 r236500  
    6262    void animationDidEnd(WebCore::GraphicsLayer::PlatformLayerID, CAAnimation *);
    6363
     64    void detachFromDrawingArea();
    6465    void clearLayers();
    6566
     
    7980    void layerWillBeRemoved(WebCore::GraphicsLayer::PlatformLayerID);
    8081
    81     RemoteLayerTreeDrawingAreaProxy& m_drawingArea;
    82     LayerOrView *m_rootLayer;
     82    RemoteLayerTreeDrawingAreaProxy* m_drawingArea { nullptr };
     83    LayerOrView *m_rootLayer { nullptr };
    8384    HashMap<WebCore::GraphicsLayer::PlatformLayerID, RetainPtr<LayerOrView>> m_layers;
    8485    HashMap<WebCore::GraphicsLayer::PlatformLayerID, RetainPtr<WKAnimationDelegate>> m_animationDelegates;
    85     bool m_isDebugLayerTreeHost;
     86    bool m_isDebugLayerTreeHost { false };
    8687};
    8788
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm

    r235365 r236500  
    5050using namespace WebCore;
    5151
    52 #define RELEASE_LOG_IF_ALLOWED(...) RELEASE_LOG_IF(m_drawingArea.isAlwaysOnLoggingAllowed(), ViewState, __VA_ARGS__)
     52#define RELEASE_LOG_IF_ALLOWED(...) RELEASE_LOG_IF(m_drawingArea && m_drawingArea->isAlwaysOnLoggingAllowed(), ViewState, __VA_ARGS__)
    5353
    5454RemoteLayerTreeHost::RemoteLayerTreeHost(RemoteLayerTreeDrawingAreaProxy& drawingArea)
    55     : m_drawingArea(drawingArea)
    56     , m_rootLayer(nullptr)
    57     , m_isDebugLayerTreeHost(false)
     55    : m_drawingArea(&drawingArea)
    5856{
    5957}
     
    6967bool RemoteLayerTreeHost::updateLayerTree(const RemoteLayerTreeTransaction& transaction, float indicatorScaleFactor)
    7068{
     69    if (!m_drawingArea)
     70        return false;
     71
    7172    for (const auto& createdLayer : transaction.createdLayers()) {
    7273        const RemoteLayerTreeTransaction::LayerProperties* properties = transaction.changedLayerProperties().get(createdLayer.layerID);
     
    9293    auto layerContentsType = RemoteLayerBackingStore::LayerContentsType::IOSurface;
    9394#else
    94     auto layerContentsType = m_drawingArea.hasDebugIndicator() ? RemoteLayerBackingStore::LayerContentsType::IOSurface : RemoteLayerBackingStore::LayerContentsType::CAMachPort;
     95    auto layerContentsType = m_drawingArea->hasDebugIndicator() ? RemoteLayerBackingStore::LayerContentsType::IOSurface : RemoteLayerBackingStore::LayerContentsType::CAMachPort;
    9596#endif
    9697   
     
    161162void RemoteLayerTreeHost::animationDidStart(WebCore::GraphicsLayer::PlatformLayerID layerID, CAAnimation *animation, MonotonicTime startTime)
    162163{
     164    if (!m_drawingArea)
     165        return;
     166
    163167    CALayer *layer = asLayer(getLayer(layerID));
    164168    if (!layer)
     
    174178
    175179    if (!animationKey.isEmpty())
    176         m_drawingArea.acceleratedAnimationDidStart(layerID, animationKey, startTime);
     180        m_drawingArea->acceleratedAnimationDidStart(layerID, animationKey, startTime);
    177181}
    178182
    179183void RemoteLayerTreeHost::animationDidEnd(WebCore::GraphicsLayer::PlatformLayerID layerID, CAAnimation *animation)
    180184{
     185    if (!m_drawingArea)
     186        return;
     187
    181188    CALayer *layer = asLayer(getLayer(layerID));
    182189    if (!layer)
     
    192199
    193200    if (!animationKey.isEmpty())
    194         m_drawingArea.acceleratedAnimationDidEnd(layerID, animationKey);
     201        m_drawingArea->acceleratedAnimationDidEnd(layerID, animationKey);
     202}
     203
     204void RemoteLayerTreeHost::detachFromDrawingArea()
     205{
     206    m_drawingArea = nullptr;
    195207}
    196208
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r236494 r236500  
    25082508        m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
    25092509
    2510         auto itemStates = m_backForwardList-> filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
     2510        auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
    25112511            if (auto* page = item.suspendedPage()) {
    25122512                if (page->process() == m_process.ptr())
     
    60186018    m_scrollingPerformanceData = nullptr;
    60196019#endif
    6020     m_drawingArea = nullptr;
     6020
     6021    if (m_drawingArea) {
     6022#if PLATFORM(COCOA)
     6023        if (resetStateReason == ResetStateReason::NavigationSwap && is<RemoteLayerTreeDrawingAreaProxy>(*m_drawingArea)) {
     6024            // Keep layers around in frozen state to avoid flashing during process swaps.
     6025            m_frozenRemoteLayerTreeHost = downcast<RemoteLayerTreeDrawingAreaProxy>(*m_drawingArea).detachRemoteLayerTreeHost();
     6026        }
     6027#endif
     6028        m_drawingArea = nullptr;
     6029    }
    60216030    closeOverlayedViews();
    60226031
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r236485 r236500  
    224224class NativeWebWheelEvent;
    225225class PageClient;
     226class RemoteLayerTreeHost;
    226227class RemoteLayerTreeScrollingPerformanceData;
    227228class RemoteLayerTreeTransaction;
     
    18621863
    18631864    std::unique_ptr<DrawingAreaProxy> m_drawingArea;
    1864 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
     1865#if PLATFORM(COCOA)
     1866    std::unique_ptr<RemoteLayerTreeHost> m_frozenRemoteLayerTreeHost;
     1867#if ENABLE(ASYNC_SCROLLING)
    18651868    std::unique_ptr<RemoteScrollingCoordinatorProxy> m_scrollingCoordinatorProxy;
    18661869#endif
    1867 
     1870#endif
    18681871    Ref<WebProcessProxy> m_process;
    18691872    Ref<WebPageGroup> m_pageGroup;
  • trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm

    r236257 r236500  
    212212void PageClientImpl::processWillSwap()
    213213{
    214     // FIXME: It didn't really exit.
    215     processDidExit();
     214    [m_contentView _processWillSwap];
     215    [m_webView _processWillSwap];
    216216}
    217217
  • trunk/Source/WebKit/UIProcess/ios/WKContentView.h

    r230383 r236500  
    8686- (std::unique_ptr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy;
    8787- (void)_processDidExit;
     88- (void)_processWillSwap;
    8889- (void)_didRelaunchProcess;
    8990- (void)_setAcceleratedCompositingRootView:(UIView *)rootView;
  • trunk/Source/WebKit/UIProcess/ios/WKContentView.mm

    r233723 r236500  
    522522}
    523523
     524- (void)_processWillSwap
     525{
     526    // FIXME: Should we do something differently?
     527    [self _processDidExit];
     528}
     529
    524530- (void)_didRelaunchProcess
    525531{
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r236154 r236500  
    994994{
    995995    pageClient().setAcceleratedCompositingRootLayer(rootLayer);
     996    m_frozenRemoteLayerTreeHost = nullptr;
    996997}
    997998
  • trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm

    r235903 r236500  
    4141#import "PageClientImplMac.h"
    4242#import "PluginComplexTextInputState.h"
     43#import "RemoteLayerTreeHost.h"
    4344#import "StringUtilities.h"
    4445#import "TextChecker.h"
     
    459460{
    460461    pageClient().setAcceleratedCompositingRootLayer(rootLayer);
     462    m_frozenRemoteLayerTreeHost = nullptr;
    461463}
    462464
Note: See TracChangeset for help on using the changeset viewer.