[iOS] Maintain the last Back/Forward cache entry when the application gets suspended
https://bugs.webkit.org/show_bug.cgi?id=203014

Reviewed by Geoffrey Garen.

Previously, we would clear all back/forward cache entries when the application is about to
be suspended. This means that we would lose fast-back when coming back to the application.
To be memory-friendly but maintain the fast-back when coming back to the application, we now
maintain the last back/forward cache entry when the application gets suspended.

* UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(WebKit::WebProcessPool::applicationIsAboutToSuspend):
(WebKit::WebProcessPool::notifyProcessPoolsApplicationIsAboutToSuspend):
* UIProcess/WebBackForwardCache.cpp:
(WebKit::WebBackForwardCache::pruneToSize):
* UIProcess/WebBackForwardCache.h:
* UIProcess/WebProcessPool.h:
* UIProcess/ios/ProcessAssertionIOS.mm:
(-[WKProcessAssertionBackgroundTaskManager init]):
(-[WKProcessAssertionBackgroundTaskManager _releaseBackgroundTask]):

* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeWebProcess):
A WebProcess no longer clears its PageCache on suspension on iOS. We let the UIProcess's
back/forward cache control when PageCache entries should get destroyed. The back/forward
cache will properly wake up a suspended process to clear one of its PageCache entries if
needed.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251174 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 0172a14..d87419c 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,33 @@
+2019-10-15  Chris Dumez  <cdumez@apple.com>
+
+        [iOS] Maintain the last Back/Forward cache entry when the application gets suspended
+        https://bugs.webkit.org/show_bug.cgi?id=203014
+
+        Reviewed by Geoffrey Garen.
+
+        Previously, we would clear all back/forward cache entries when the application is about to
+        be suspended. This means that we would lose fast-back when coming back to the application.
+        To be memory-friendly but maintain the fast-back when coming back to the application, we now
+        maintain the last back/forward cache entry when the application gets suspended.
+
+        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+        (WebKit::WebProcessPool::applicationIsAboutToSuspend):
+        (WebKit::WebProcessPool::notifyProcessPoolsApplicationIsAboutToSuspend):
+        * UIProcess/WebBackForwardCache.cpp:
+        (WebKit::WebBackForwardCache::pruneToSize):
+        * UIProcess/WebBackForwardCache.h:
+        * UIProcess/WebProcessPool.h:
+        * UIProcess/ios/ProcessAssertionIOS.mm:
+        (-[WKProcessAssertionBackgroundTaskManager init]):
+        (-[WKProcessAssertionBackgroundTaskManager _releaseBackgroundTask]):
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::initializeWebProcess):
+        A WebProcess no longer clears its PageCache on suspension on iOS. We let the UIProcess's
+        back/forward cache control when PageCache entries should get destroyed. The back/forward
+        cache will properly wake up a suspended process to clear one of its PageCache entries if
+        needed.
+
 2019-10-15  Andres Gonzalez  <andresg_22@apple.com>
 
         AX: Make AXIsolatedTree compile again
diff --git a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
index 4b92b93..1a41cd1 100644
--- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
+++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm
@@ -37,6 +37,7 @@
 #import "TextChecker.h"
 #import "VersionChecks.h"
 #import "WKBrowsingContextControllerInternal.h"
+#import "WebBackForwardCache.h"
 #import "WebMemoryPressureHandler.h"
 #import "WebPageGroup.h"
 #import "WebPreferencesKeys.h"
@@ -585,11 +586,18 @@
 #if PLATFORM(IOS_FAMILY)
 void WebProcessPool::applicationIsAboutToSuspend()
 {
-    RELEASE_LOG(ProcessSuspension, "Application is about to suspend so we simulate memory pressure to terminate non-critical processes");
-    // Simulate memory pressure handling so free as much memory as possible before suspending.
-    // In particular, this will terminate prewarmed and PageCache processes.
+    RELEASE_LOG(ProcessSuspension, "WebProcessPool::applicationIsAboutToSuspend() Terminating non-critical processes");
+
+    m_backForwardCache->pruneToSize(1);
+    if (m_prewarmedProcess)
+        m_prewarmedProcess->shutDown();
+    m_webProcessCache->clear();
+}
+
+void WebProcessPool::notifyProcessPoolsApplicationIsAboutToSuspend()
+{
     for (auto* processPool : allProcessPools())
-        processPool->handleMemoryPressureWarning(Critical::Yes);
+        processPool->applicationIsAboutToSuspend();
 }
 #endif
 
diff --git a/Source/WebKit/UIProcess/WebBackForwardCache.cpp b/Source/WebKit/UIProcess/WebBackForwardCache.cpp
index e75a896..698504d 100644
--- a/Source/WebKit/UIProcess/WebBackForwardCache.cpp
+++ b/Source/WebKit/UIProcess/WebBackForwardCache.cpp
@@ -164,4 +164,11 @@
         item->setBackForwardCacheEntry(nullptr);
 }
 
+void WebBackForwardCache::pruneToSize(unsigned newSize)
+{
+    RELEASE_LOG(BackForwardCache, "WebBackForwardCache::pruneToSize(%u)", newSize);
+    while (size() > newSize)
+        removeOldestEntry();
+}
+
 } // namespace WebKit.
diff --git a/Source/WebKit/UIProcess/WebBackForwardCache.h b/Source/WebKit/UIProcess/WebBackForwardCache.h
index c1e115a..be4bc4e 100644
--- a/Source/WebKit/UIProcess/WebBackForwardCache.h
+++ b/Source/WebKit/UIProcess/WebBackForwardCache.h
@@ -50,6 +50,7 @@
     unsigned size() const { return m_itemsWithCachedPage.size(); }
 
     void clear();
+    void pruneToSize(unsigned);
     void removeEntriesForProcess(WebProcessProxy&);
     void removeEntriesForPage(WebPageProxy&);
     void removeEntriesForSession(PAL::SessionID);
diff --git a/Source/WebKit/UIProcess/WebProcessPool.h b/Source/WebKit/UIProcess/WebProcessPool.h
index 78bdc04..c6ba0fc 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.h
+++ b/Source/WebKit/UIProcess/WebProcessPool.h
@@ -230,7 +230,8 @@
     void populateVisitedLinks();
 
 #if PLATFORM(IOS_FAMILY)
-    static void applicationIsAboutToSuspend();
+    void applicationIsAboutToSuspend();
+    static void notifyProcessPoolsApplicationIsAboutToSuspend();
 #endif
 
     void handleMemoryPressureWarning(Critical);
diff --git a/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm b/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm
index 32fcf36..37a6982 100644
--- a/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm
+++ b/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm
@@ -84,7 +84,7 @@
         _applicationIsBackgrounded = YES;
         
         if (_backgroundTask == UIBackgroundTaskInvalid)
-            WebKit::WebProcessPool::applicationIsAboutToSuspend();
+            WebKit::WebProcessPool::notifyProcessPoolsApplicationIsAboutToSuspend();
     }];
 
     return self;
@@ -188,7 +188,7 @@
 
     RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - endBackgroundTask", self);
     if (_applicationIsBackgrounded)
-        WebKit::WebProcessPool::applicationIsAboutToSuspend();
+        WebKit::WebProcessPool::notifyProcessPoolsApplicationIsAboutToSuspend();
     [[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
     _backgroundTask = UIBackgroundTaskInvalid;
 }
diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp
index accd337..c66c805d 100644
--- a/Source/WebKit/WebProcess/WebProcess.cpp
+++ b/Source/WebKit/WebProcess/WebProcess.cpp
@@ -306,7 +306,7 @@
             }
 #endif
 
-            auto maintainPageCache = m_isSuspending && hasPageRequiringPageCacheWhileSuspended() ? WebCore::MaintainPageCache::Yes : WebCore::MaintainPageCache::No;
+            auto maintainPageCache = m_isSuspending ? WebCore::MaintainPageCache::Yes : WebCore::MaintainPageCache::No;
             auto maintainMemoryCache = m_isSuspending && m_hasSuspendedPageProxy ? WebCore::MaintainMemoryCache::Yes : WebCore::MaintainMemoryCache::No;
             WebCore::releaseMemory(critical, synchronous, maintainPageCache, maintainMemoryCache);
         });