Changeset 251976 in webkit


Ignore:
Timestamp:
Nov 3, 2019 12:34:50 PM (4 years ago)
Author:
timothy_horton@apple.com
Message:

WKWebView can get stuck blank (Web Content process thinks the app is backgrounded)
https://bugs.webkit.org/show_bug.cgi?id=203774
<rdar://problem/53399054>

Reviewed by Chris Dumez.

Source/WebKit:

With careful timing, if a WKWebView swaps out its content view in the
background, the incoming view can fail to inform the Web Content process
when the app comes to the foreground, leaving the layer tree frozen.

This occurs because the last-sent state is stored per-WKApplicationStateTrackingView,
and the content view is the WKApplicationStateTrackingView, so it is possible
for e.g. a WKPDFView to be in the hierarchy, keeping the correct state,
with an initialized-but-never-parented WKContentView hanging off the WKWebView.

If it is never parented, WKContentView will think that the current application
state is foreground (_lastObservedStateWasBackground is initialized to NO).

If you go into the background with a WKPDFView as the current content view,
it will inform the Web Content process that the application has backgrounded.

If, still in the background, WKWebView swaps from the WKPDFView to
the WKContentView, and then comes into the foreground, when we get the
notification that the app came to the foreground, we will not forward it
to the Web Content process, because WKContentView's _lastObservedStateWasBackground
remains NO.

To fix this, move _lastObservedStateWasBackground to WebPageProxy, so that
it always tracks the most recently sent state, regardless of which content view
is active.

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::resetState):

  • UIProcess/WebPageProxy.h:

(WebKit::WebPageProxy::lastObservedStateWasBackground const):

  • UIProcess/ios/WKApplicationStateTrackingView.mm:

(-[WKApplicationStateTrackingView willMoveToWindow:]):
(-[WKApplicationStateTrackingView didMoveToWindow]):
(-[WKApplicationStateTrackingView _applicationDidEnterBackground]):
(-[WKApplicationStateTrackingView _applicationWillEnterForeground]):

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::applicationDidEnterBackground):
(WebKit::WebPageProxy::applicationWillEnterForeground):

Tools:

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebKitCocoa/WKPDFView.mm: Added.

(TEST):
(isBackground):
(createHostViewForExtensionIdentifier):

  • TestWebKitAPI/Tests/WebKitCocoa/WKPDFViewResizeCrash.mm: Removed.
  • TestWebKitAPI/Tests/WebKitCocoa/WKPDFViewStablePresentationUpdateCallback.mm: Removed.
  • TestWebKitAPI/cocoa/TestNavigationDelegate.h:
  • TestWebKitAPI/cocoa/TestNavigationDelegate.mm:

(-[WKWebView _test_waitForDidFinishNavigationWithoutPresentationUpdate]):
Merge existing WKPDFView tests into one file, and add one for this bug.

Location:
trunk
Files:
1 added
2 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r251963 r251976  
     12019-11-03  Tim Horton  <timothy_horton@apple.com>
     2
     3        WKWebView can get stuck blank (Web Content process thinks the app is backgrounded)
     4        https://bugs.webkit.org/show_bug.cgi?id=203774
     5        <rdar://problem/53399054>
     6
     7        Reviewed by Chris Dumez.
     8
     9        With careful timing, if a WKWebView swaps out its content view in the
     10        background, the incoming view can fail to inform the Web Content process
     11        when the app comes to the foreground, leaving the layer tree frozen.
     12
     13        This occurs because the last-sent state is stored per-WKApplicationStateTrackingView,
     14        and the content view is the WKApplicationStateTrackingView, so it is possible
     15        for e.g. a WKPDFView to be in the hierarchy, keeping the correct state,
     16        with an initialized-but-never-parented WKContentView hanging off the WKWebView.
     17
     18        If it is never parented, WKContentView will think that the current application
     19        state is foreground (_lastObservedStateWasBackground is initialized to NO).
     20
     21        If you go into the background with a WKPDFView as the current content view,
     22        it will inform the Web Content process that the application has backgrounded.
     23
     24        If, still in the background, WKWebView swaps from the WKPDFView to
     25        the WKContentView, and then comes into the foreground, when we get the
     26        notification that the app came to the foreground, we will not forward it
     27        to the Web Content process, because WKContentView's _lastObservedStateWasBackground
     28        remains NO.
     29
     30        To fix this, move _lastObservedStateWasBackground to WebPageProxy, so that
     31        it always tracks the most recently sent state, regardless of which content view
     32        is active.
     33
     34        * UIProcess/WebPageProxy.cpp:
     35        (WebKit::WebPageProxy::resetState):
     36        * UIProcess/WebPageProxy.h:
     37        (WebKit::WebPageProxy::lastObservedStateWasBackground const):
     38        * UIProcess/ios/WKApplicationStateTrackingView.mm:
     39        (-[WKApplicationStateTrackingView willMoveToWindow:]):
     40        (-[WKApplicationStateTrackingView didMoveToWindow]):
     41        (-[WKApplicationStateTrackingView _applicationDidEnterBackground]):
     42        (-[WKApplicationStateTrackingView _applicationWillEnterForeground]):
     43        * UIProcess/ios/WebPageProxyIOS.mm:
     44        (WebKit::WebPageProxy::applicationDidEnterBackground):
     45        (WebKit::WebPageProxy::applicationWillEnterForeground):
     46
    1472019-11-02  Devin Rousso  <drousso@apple.com>
    248
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r251787 r251976  
    71607160    m_isKeyboardAnimatingIn = false;
    71617161    m_isScrollingOrZooming = false;
     7162    m_lastObservedStateWasBackground = false;
    71627163#endif
    71637164
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r251787 r251976  
    737737    void applicationDidFinishSnapshottingAfterEnteringBackground();
    738738    void applicationWillEnterForeground();
     739    bool lastObservedStateWasBackground() const { return m_lastObservedStateWasBackground; }
    739740    void applicationWillResignActive();
    740741    void applicationDidBecomeActive();
     
    25432544    double m_viewportConfigurationMinimumEffectiveDeviceWidth { 0 };
    25442545    WebCore::FloatSize m_maximumUnobscuredSize;
     2546    bool m_lastObservedStateWasBackground { false };
    25452547#endif
    25462548
  • trunk/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm

    r251166 r251976  
    3939    WeakObjCPtr<WKWebView> _webViewToTrack;
    4040    std::unique_ptr<WebKit::ApplicationStateTracker> _applicationStateTracker;
    41     BOOL _lastObservedStateWasBackground;
    4241}
    4342
     
    5655        return;
    5756
    58     _lastObservedStateWasBackground = [self isBackground];
    59 
    6057    auto page = [_webViewToTrack _page];
    61     RELEASE_LOG(ViewState, "%p - WKApplicationStateTrackingView: View with page [%p, pageProxyID: %" PRIu64 "] was removed from a window, _lastObservedStateWasBackground: %d", self, page, page ? page->identifier().toUInt64() : 0, _lastObservedStateWasBackground);
     58    RELEASE_LOG(ViewState, "%p - WKApplicationStateTrackingView: View with page [%p, pageProxyID: %" PRIu64 "] was removed from a window, _lastObservedStateWasBackground: %d", self, page, page ? page->identifier().toUInt64() : 0, page ? page->lastObservedStateWasBackground() : false);
    6259    ASSERT(_applicationStateTracker);
    6360    _applicationStateTracker = nullptr;
     
    7067
    7168    auto page = [_webViewToTrack _page];
     69    bool lastObservedStateWasBackground = page ? page->lastObservedStateWasBackground() : false;
     70
    7271    _applicationStateTracker = makeUnique<WebKit::ApplicationStateTracker>(self, @selector(_applicationDidEnterBackground), @selector(_applicationDidFinishSnapshottingAfterEnteringBackground), @selector(_applicationWillEnterForeground));
    73     RELEASE_LOG(ViewState, "%p - WKApplicationStateTrackingView: View with page [%p, pageProxyID: %" PRIu64 "] was added to a window, _lastObservedStateWasBackground: %d, isNowBackground: %d", self, page, page ? page->identifier().toUInt64() : 0, _lastObservedStateWasBackground, [self isBackground]);
     72    RELEASE_LOG(ViewState, "%p - WKApplicationStateTrackingView: View with page [%p, pageProxyID: %" PRIu64 "] was added to a window, _lastObservedStateWasBackground: %d, isNowBackground: %d", self, page, page ? page->identifier().toUInt64() : 0, lastObservedStateWasBackground, [self isBackground]);
    7473
    75     if (_lastObservedStateWasBackground && ![self isBackground])
     74    if (lastObservedStateWasBackground && ![self isBackground])
    7675        [self _applicationWillEnterForeground];
    77     else if (!_lastObservedStateWasBackground && [self isBackground])
     76    else if (!lastObservedStateWasBackground && [self isBackground])
    7877        [self _applicationDidEnterBackground];
    7978}
     
    8584        return;
    8685
    87     _lastObservedStateWasBackground = YES;
    8886    page->applicationDidEnterBackground();
    8987    page->activityStateDidChange(WebCore::ActivityState::allFlags() - WebCore::ActivityState::IsInWindow);
     
    102100        return;
    103101
    104     _lastObservedStateWasBackground = NO;
    105102    page->applicationWillEnterForeground();
    106103    page->activityStateDidChange(WebCore::ActivityState::allFlags() - WebCore::ActivityState::IsInWindow, true, WebKit::WebPageProxy::ActivityStateChangeDispatchMode::Immediate);
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r251778 r251976  
    650650void WebPageProxy::applicationDidEnterBackground()
    651651{
     652    m_lastObservedStateWasBackground = true;
     653
    652654    bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
    653655   
     
    679681void WebPageProxy::applicationWillEnterForeground()
    680682{
     683    m_lastObservedStateWasBackground = false;
     684
    681685    bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
    682686    RELEASE_LOG_IF_ALLOWED(ViewState, "applicationWillEnterForeground: isSuspendedUnderLock? %d", isSuspendedUnderLock);
  • trunk/Tools/ChangeLog

    r251963 r251976  
     12019-11-03  Tim Horton  <timothy_horton@apple.com>
     2
     3        WKWebView can get stuck blank (Web Content process thinks the app is backgrounded)
     4        https://bugs.webkit.org/show_bug.cgi?id=203774
     5        <rdar://problem/53399054>
     6
     7        Reviewed by Chris Dumez.
     8
     9        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     10        * TestWebKitAPI/Tests/WebKitCocoa/WKPDFView.mm: Added.
     11        (TEST):
     12        (isBackground):
     13        (createHostViewForExtensionIdentifier):
     14        * TestWebKitAPI/Tests/WebKitCocoa/WKPDFViewResizeCrash.mm: Removed.
     15        * TestWebKitAPI/Tests/WebKitCocoa/WKPDFViewStablePresentationUpdateCallback.mm: Removed.
     16        * TestWebKitAPI/cocoa/TestNavigationDelegate.h:
     17        * TestWebKitAPI/cocoa/TestNavigationDelegate.mm:
     18        (-[WKWebView _test_waitForDidFinishNavigationWithoutPresentationUpdate]):
     19        Merge existing WKPDFView tests into one file, and add one for this bug.
     20
    1212019-11-02  Devin Rousso  <drousso@apple.com>
    222
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r251787 r251976  
    123123                290F4275172A221C00939FF0 /* custom-protocol-sync-xhr.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 290F4274172A1FDE00939FF0 /* custom-protocol-sync-xhr.html */; };
    124124                297234B7173AFAC700983601 /* CustomProtocolsInvalidScheme_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 297234B5173AFAC700983601 /* CustomProtocolsInvalidScheme_Bundle.cpp */; };
    125                 2D00065F1C1F589A0088E6A7 /* WKPDFViewResizeCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D00065D1C1F58940088E6A7 /* WKPDFViewResizeCrash.mm */; };
     125                2D00065F1C1F589A0088E6A7 /* WKPDFView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D00065D1C1F58940088E6A7 /* WKPDFView.mm */; };
    126126                2D01D06E23218FEE0039AA3A /* WKWebViewPrintFormatter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D01D06D23218FEE0039AA3A /* WKWebViewPrintFormatter.mm */; };
    127127                2D08E9372267D0F4002518DA /* ReparentWebViewTimeout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D08E9362267D0F3002518DA /* ReparentWebViewTimeout.mm */; };
    128128                2D1646E21D1862CD00015A1A /* DeferredViewInWindowStateChange.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D1646E11D1862CD00015A1A /* DeferredViewInWindowStateChange.mm */; };
    129                 2D21FE591F04642900B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D21FE581F04642800B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm */; };
    130129                2D2BEB2D22324E5F005544CA /* RequestTextInputContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2BEB2C22324E5F005544CA /* RequestTextInputContext.mm */; };
    131130                2D2D13B3229F408B005068AF /* DeviceManagementRestrictions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2D13B2229F408B005068AF /* DeviceManagementRestrictions.mm */; };
     
    14601459                                57663DEC234F1F9300E85E09 /* web-authentication-get-assertion-hid.html in Copy Resources */,
    14611460                                579833922368FA37008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */,
    1462                                 5798337C235EB689008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */,
    14631461                                57663DEA234EA66D00E85E09 /* web-authentication-get-assertion-nfc.html in Copy Resources */,
    14641462                                577454D22359BB01008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html in Copy Resources */,
     
    16061604                29AB8AA2164C7A9300D49BEC /* TestBrowsingContextLoadDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestBrowsingContextLoadDelegate.mm; sourceTree = "<group>"; };
    16071605                29AB8AA3164C7A9300D49BEC /* TestBrowsingContextLoadDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestBrowsingContextLoadDelegate.h; sourceTree = "<group>"; };
    1608                 2D00065D1C1F58940088E6A7 /* WKPDFViewResizeCrash.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKPDFViewResizeCrash.mm; sourceTree = "<group>"; };
     1606                2D00065D1C1F58940088E6A7 /* WKPDFView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKPDFView.mm; sourceTree = "<group>"; };
    16091607                2D01D06D23218FEE0039AA3A /* WKWebViewPrintFormatter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewPrintFormatter.mm; sourceTree = "<group>"; };
    16101608                2D08E9362267D0F3002518DA /* ReparentWebViewTimeout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ReparentWebViewTimeout.mm; sourceTree = "<group>"; };
     
    16131611                2D1C04A61D76298B000A6816 /* TestNavigationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestNavigationDelegate.mm; path = cocoa/TestNavigationDelegate.mm; sourceTree = "<group>"; };
    16141612                2D1FE0AF1AD465C1006CD9E6 /* FixedLayoutSize.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FixedLayoutSize.mm; sourceTree = "<group>"; };
    1615                 2D21FE581F04642800B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKPDFViewStablePresentationUpdateCallback.mm; sourceTree = "<group>"; };
    16161613                2D2BEB2C22324E5F005544CA /* RequestTextInputContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RequestTextInputContext.mm; sourceTree = "<group>"; };
    16171614                2D2D13B2229F408B005068AF /* DeviceManagementRestrictions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DeviceManagementRestrictions.mm; sourceTree = "<group>"; };
     
    29922989                                375E0E151D66674400EFEC2C /* WKNSNumber.mm */,
    29932990                                37B47E2E1D64E7CA005F4EFF /* WKObject.mm */,
    2994                                 2D00065D1C1F58940088E6A7 /* WKPDFViewResizeCrash.mm */,
    2995                                 2D21FE581F04642800B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm */,
     2991                                2D00065D1C1F58940088E6A7 /* WKPDFView.mm */,
    29962992                                3781746C2198AE2400062C26 /* WKProcessPoolConfiguration.mm */,
    29972993                                44817A2E1F0486BF00003810 /* WKRequestActivatedElementInfo.mm */,
     
    49244920                                7CCE7F1F1A411AE600447C4C /* WKPageGetScaleFactorNotZero.cpp in Sources */,
    49254921                                7CCE7F201A411AE600447C4C /* WKPageIsPlayingAudio.cpp in Sources */,
    4926                                 2D00065F1C1F589A0088E6A7 /* WKPDFViewResizeCrash.mm in Sources */,
    4927                                 2D21FE591F04642900B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm in Sources */,
     4922                                2D00065F1C1F589A0088E6A7 /* WKPDFView.mm in Sources */,
    49284923                                7CCE7F211A411AE600447C4C /* WKPreferences.cpp in Sources */,
    49294924                                3781746D2198AE4600062C26 /* WKProcessPoolConfiguration.mm in Sources */,
  • trunk/Tools/TestWebKitAPI/cocoa/TestNavigationDelegate.h

    r249684 r251976  
    4949- (void)_test_waitForDidStartProvisionalNavigation;
    5050- (void)_test_waitForDidFinishNavigation;
     51- (void)_test_waitForDidFinishNavigationWithoutPresentationUpdate;
    5152@end
  • trunk/Tools/TestWebKitAPI/cocoa/TestNavigationDelegate.mm

    r249684 r251976  
    141141}
    142142
     143- (void)_test_waitForDidFinishNavigationWithoutPresentationUpdate
     144{
     145    EXPECT_FALSE(self.navigationDelegate);
     146
     147    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
     148    self.navigationDelegate = navigationDelegate.get();
     149    [navigationDelegate waitForDidFinishNavigation];
     150
     151    self.navigationDelegate = nil;
     152}
     153
    143154- (void)_test_waitForDidFinishNavigation
    144155{
Note: See TracChangeset for help on using the changeset viewer.