Background tabs are not fully reactivated after a link is opened from an external...
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Apr 2019 16:32:30 +0000 (16:32 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Apr 2019 16:32:30 +0000 (16:32 +0000)
<rdar://problem/49533278> and https://bugs.webkit.org/show_bug.cgi?id=196705

Reviewed by Chris Dumez.

If an app unparents a WKWebView right after activation but before the "applicationWillEnterForeground" notification
is dispatched, then that WKWebView is in a broken state with a frozen layer tree.

The WKApplicationStateTrackingView logic needs to be a little more resilient.

* UIProcess/ios/WKApplicationStateTrackingView.mm:
(-[WKApplicationStateTrackingView willMoveToWindow:]): When clearing the window, remember the current background state.
(-[WKApplicationStateTrackingView didMoveToWindow]): If our last observed background state doesn't match the current
  background state then fake the relevant notification.
(-[WKApplicationStateTrackingView _applicationDidEnterBackground]): Remember that we've observed a backgrounding.
(-[WKApplicationStateTrackingView _applicationWillEnterForeground]): Remember that we've observed a foregrounding.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244113 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm

index 1a9b454..d7eb374 100644 (file)
@@ -1,3 +1,22 @@
+2019-04-10  Brady Eidson  <beidson@apple.com>
+
+        Background tabs are not fully reactivated after a link is opened from an external application.
+        <rdar://problem/49533278> and https://bugs.webkit.org/show_bug.cgi?id=196705
+
+        Reviewed by Chris Dumez.
+
+        If an app unparents a WKWebView right after activation but before the "applicationWillEnterForeground" notification
+        is dispatched, then that WKWebView is in a broken state with a frozen layer tree.
+
+        The WKApplicationStateTrackingView logic needs to be a little more resilient.
+
+        * UIProcess/ios/WKApplicationStateTrackingView.mm:
+        (-[WKApplicationStateTrackingView willMoveToWindow:]): When clearing the window, remember the current background state.
+        (-[WKApplicationStateTrackingView didMoveToWindow]): If our last observed background state doesn't match the current
+          background state then fake the relevant notification.
+        (-[WKApplicationStateTrackingView _applicationDidEnterBackground]): Remember that we've observed a backgrounding.
+        (-[WKApplicationStateTrackingView _applicationWillEnterForeground]): Remember that we've observed a foregrounding.
+
 2019-04-10  Diego Pino Garcia  <dpino@igalia.com>
 
         Unreviewed, build fix for r244097
index 8c1b869..12a2b3a 100644 (file)
@@ -37,6 +37,7 @@
 @implementation WKApplicationStateTrackingView {
     WeakObjCPtr<WKWebView> _webViewToTrack;
     std::unique_ptr<WebKit::ApplicationStateTracker> _applicationStateTracker;
+    BOOL _lastObservedStateWasBackground;
 }
 
 - (instancetype)initWithFrame:(CGRect)frame webView:(WKWebView *)webView
@@ -53,6 +54,8 @@
     if (!self._contentView.window || newWindow)
         return;
 
+    _lastObservedStateWasBackground = [self isBackground];
+
     ASSERT(_applicationStateTracker);
     _applicationStateTracker = nullptr;
 }
 
     ASSERT(!_applicationStateTracker);
     _applicationStateTracker = std::make_unique<WebKit::ApplicationStateTracker>(self, @selector(_applicationDidEnterBackground), @selector(_applicationDidFinishSnapshottingAfterEnteringBackground), @selector(_applicationWillEnterForeground));
+    
+    if (_lastObservedStateWasBackground && ![self isBackground])
+        [self _applicationWillEnterForeground];
+    else if (!_lastObservedStateWasBackground && [self isBackground])
+        [self _applicationDidEnterBackground];
 }
 
 - (void)_applicationDidEnterBackground
@@ -72,6 +80,7 @@
     if (!page)
         return;
 
+    _lastObservedStateWasBackground = YES;
     page->applicationDidEnterBackground();
     page->activityStateDidChange(WebCore::ActivityState::allFlags() - WebCore::ActivityState::IsInWindow);
 }
@@ -88,6 +97,7 @@
     if (!page)
         return;
 
+    _lastObservedStateWasBackground = NO;
     page->applicationWillEnterForeground();
     page->activityStateDidChange(WebCore::ActivityState::allFlags() - WebCore::ActivityState::IsInWindow, true, WebKit::WebPageProxy::ActivityStateChangeDispatchMode::Immediate);
 }