Webview's drawing area may stay frozen on cross-site back/forward navigation
https://bugs.webkit.org/show_bug.cgi?id=203004

Reviewed by Tim Horton.

Whenever the UIScene becomes foreground / background, the WebPageProxy notifies its currently associated
WebPage in the committed WebProcess so that it can freeze / unfreeze its layer tree with the
BackgroundApplication reason. The issue is that if a WebPage gets suspended on cross-site navigation
(because the UIScene is in the background when the load commits), then the suspended WebPage kept its
a BackgroundApplication freeze. When the UIScene becomes foreground, the WebPage only notifies its
committed page so the suspended page keeps its BackgroundApplication freeze still. If the user now
navigates back, it will restore the suspended WebPage and the view will stay frozen.

To address the issue, we now have the WebPage drop its BackgroundApplication freeze reason, whenever
it transitions from committed to suspended.

* UIProcess/ios/WKApplicationStateTrackingView.mm:
(-[WKApplicationStateTrackingView didMoveToWindow]):
Fix logging, [self isBackground] needs to be called *after* _applicationStateTracker has been
initialized, or it will return YES unconditionally.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::setIsSuspended):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251166 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 327753a..5bec270 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,29 @@
+2019-10-15  Chris Dumez  <cdumez@apple.com>
+
+        Webview's drawing area may stay frozen on cross-site back/forward navigation
+        https://bugs.webkit.org/show_bug.cgi?id=203004
+
+        Reviewed by Tim Horton.
+
+        Whenever the UIScene becomes foreground / background, the WebPageProxy notifies its currently associated
+        WebPage in the committed WebProcess so that it can freeze / unfreeze its layer tree with the
+        BackgroundApplication reason. The issue is that if a WebPage gets suspended on cross-site navigation
+        (because the UIScene is in the background when the load commits), then the suspended WebPage kept its
+        a BackgroundApplication freeze. When the UIScene becomes foreground, the WebPage only notifies its
+        committed page so the suspended page keeps its BackgroundApplication freeze still. If the user now
+        navigates back, it will restore the suspended WebPage and the view will stay frozen.
+
+        To address the issue, we now have the WebPage drop its BackgroundApplication freeze reason, whenever
+        it transitions from committed to suspended.
+
+        * UIProcess/ios/WKApplicationStateTrackingView.mm:
+        (-[WKApplicationStateTrackingView didMoveToWindow]):
+        Fix logging, [self isBackground] needs to be called *after* _applicationStateTracker has been
+        initialized, or it will return YES unconditionally.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::setIsSuspended):
+
 2019-10-15  Peng Liu  <peng.liu6@apple.com>
 
         [Picture-in-Picture Web API] Implement HTMLVideoElement.requestPictureInPicture() / Document.exitPictureInPicture()
diff --git a/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm b/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm
index 5a49e9d..6c8b43f 100644
--- a/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm
+++ b/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm
@@ -69,9 +69,9 @@
         return;
 
     auto page = [_webViewToTrack _page];
-    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]);
     _applicationStateTracker = makeUnique<WebKit::ApplicationStateTracker>(self, @selector(_applicationDidEnterBackground), @selector(_applicationDidFinishSnapshottingAfterEnteringBackground), @selector(_applicationWillEnterForeground));
-    
+    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]);
+
     if (_lastObservedStateWasBackground && ![self isBackground])
         [self _applicationWillEnterForeground];
     else if (!_lastObservedStateWasBackground && [self isBackground])
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
index 6ca57ce..98d52b0 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
@@ -6499,6 +6499,10 @@
     // Unfrozen on drawing area reset.
     freezeLayerTree(LayerTreeFreezeReason::PageSuspended);
 
+    // Only the committed WebPage gets application visibility notifications from the UIProcess, so make sure
+    // we don't hold a BackgroundApplication freeze reason when transitioning from committed to suspended.
+    unfreezeLayerTree(LayerTreeFreezeReason::BackgroundApplication);
+
     WebProcess::singleton().sendPrewarmInformation(mainWebFrame()->url());
 
     suspendForProcessSwap();