Title: [295493] trunk/Source/WebKit/UIProcess
Revision
295493
Author
sihui_...@apple.com
Date
2022-06-13 11:20:38 -0700 (Mon, 13 Jun 2022)

Log Message

Start/stop ProcessStateMonitor with ApplicationStateTracker
https://bugs.webkit.org/show_bug.cgi?id=241427

Reviewed by Geoffrey Garen.

We want ProcessStateMonitor to be started when application is in background and to be stopped when application is in
foreground. In r294405, we start/stop ProcessStateMonitor on receiving UIApplicationDidEnterBackgroundNotification and
UIApplicationWillEnterForegroundNotification notifications. However, UIApplicationWillEnterForegroundNotification can be
sent later than UISceneWillEnterForegroundNotification. In ApplicationStateTracke, we start creating foreground activity
for web process on receiving UISceneWillEnterForegroundNotification. At this time,
UIApplicationWillEnterForegroundNotification may not be received yet and ProcessStateMonitor may still be
working. ProcessStateMonitor may forbid creating new activity after it sets process shouldSuspend (see r294405), so we
need to make sure ProcessStateMonitor is stopped before starting new foreground activity.

To achieve that, we now decide when to start/stop ProcessStateMonitor with ApplicationStateTracker. We start
ProcessStateMonitor when all trackers are in the background, and stop it when at least one tracker is in foreground.

* Source/WebKit/UIProcess/ApplicationStateTracker.mm:
(WebKit::allApplicationStateTrackers):
(WebKit::updateApplicationBackgroundState):
(WebKit::ApplicationStateTracker::ApplicationStateTracker):
(WebKit::ApplicationStateTracker::~ApplicationStateTracker):
(WebKit::ApplicationStateTracker::applicationDidEnterBackground):
(WebKit::ApplicationStateTracker::applicationWillEnterForeground):
* Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(WebKit::WebProcessPool::setProcessesShouldSuspend):
* Source/WebKit/UIProcess/ProcessAssertion.h:
* Source/WebKit/UIProcess/WebProcessPool.h:
* Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm:
(-[WKProcessAssertionBackgroundTaskManager _releaseBackgroundTask]):
(-[WKProcessAssertionBackgroundTaskManager setProcessStateMonitorEnabled:]):
(WebKit::ProcessAndUIAssertion::setProcessStateMonitorEnabled):
* Source/WebKit/UIProcess/ios/ProcessStateMonitor.mm:
(WebKit::ProcessStateMonitor::checkRemainingRunTime):
* Source/WebKit/UIProcess/ios/WebProcessProxyIOS.mm:
(WebKit::WebProcessProxy::platformInitialize):

Canonical link: https://commits.webkit.org/251498@main

Modified Paths

Diff

Modified: trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm (295492 => 295493)


--- trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm	2022-06-13 17:16:47 UTC (rev 295492)
+++ trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm	2022-06-13 18:20:38 UTC (rev 295493)
@@ -30,6 +30,7 @@
 
 #import "EndowmentStateTracker.h"
 #import "Logging.h"
+#import "ProcessAssertion.h"
 #import "SandboxUtilities.h"
 #import "UIKitSPI.h"
 #import <wtf/ObjCRuntimeExtras.h>
@@ -50,6 +51,28 @@
 
 namespace WebKit {
 
+static WeakHashSet<ApplicationStateTracker>& allApplicationStateTrackers()
+{
+    static NeverDestroyed<WeakHashSet<ApplicationStateTracker>> trackers;
+    return trackers;
+}
+
+static void updateApplicationBackgroundState()
+{
+    static bool s_isApplicationInBackground = false;
+    auto isAnyStateTrackerInForeground = []() -> bool {
+        return WTF::anyOf(allApplicationStateTrackers(), [](auto& tracker) {
+            return !tracker.isInBackground();
+        });
+    };
+    bool isApplicationInBackground = !isAnyStateTrackerInForeground();
+    if (s_isApplicationInBackground == isApplicationInBackground)
+        return;
+
+    s_isApplicationInBackground = isApplicationInBackground;
+    ProcessAndUIAssertion::setProcessStateMonitorEnabled(isApplicationInBackground);
+}
+
 ApplicationType applicationType(UIWindow *window)
 {
     if (_UIApplicationIsExtension())
@@ -161,6 +184,9 @@
         break;
     }
     }
+
+    allApplicationStateTrackers().add(*this);
+    updateApplicationBackgroundState();
 }
 
 ApplicationStateTracker::~ApplicationStateTracker()
@@ -173,11 +199,15 @@
     [notificationCenter removeObserver:m_willEnterForegroundObserver];
     [notificationCenter removeObserver:m_willBeginSnapshotSequenceObserver];
     [notificationCenter removeObserver:m_didCompleteSnapshotSequenceObserver];
+
+    allApplicationStateTrackers().remove(*this);
+    updateApplicationBackgroundState();
 }
 
 void ApplicationStateTracker::applicationDidEnterBackground()
 {
     m_isInBackground = true;
+    updateApplicationBackgroundState();
 
     if (auto view = m_view.get())
         wtfObjCMsgSend<void>(view.get(), m_didEnterBackgroundSelector);
@@ -192,6 +222,7 @@
 void ApplicationStateTracker::applicationWillEnterForeground()
 {
     m_isInBackground = false;
+    updateApplicationBackgroundState();
 
     if (auto view = m_view.get())
         wtfObjCMsgSend<void>(view.get(), m_willEnterForegroundSelector);

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm (295492 => 295493)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2022-06-13 17:16:47 UTC (rev 295492)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2022-06-13 18:20:38 UTC (rev 295493)
@@ -992,8 +992,12 @@
 {
     WEBPROCESSPOOL_RELEASE_LOG(ProcessSuspension, "setProcessesShouldSuspend: Processes should suspend %d", shouldSuspend);
 
+    if (m_processesShouldSuspend == shouldSuspend)
+        return;
+
+    m_processesShouldSuspend = shouldSuspend;
     for (auto& process : m_processes)
-        process->throttler().setAllowsActivities(!shouldSuspend);
+        process->throttler().setAllowsActivities(!m_processesShouldSuspend);
 }
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/ProcessAssertion.h (295492 => 295493)


--- trunk/Source/WebKit/UIProcess/ProcessAssertion.h	2022-06-13 17:16:47 UTC (rev 295492)
+++ trunk/Source/WebKit/UIProcess/ProcessAssertion.h	2022-06-13 18:20:38 UTC (rev 295493)
@@ -124,6 +124,9 @@
     void uiAssertionWillExpireImminently();
 
     void setUIAssertionExpirationHandler(Function<void()>&& handler) { m_uiAssertionExpirationHandler = WTFMove(handler); }
+#if PLATFORM(IOS_FAMILY)
+    static void setProcessStateMonitorEnabled(bool);
+#endif
 
 private:
     ProcessAndUIAssertion(ProcessID, const String& reason, ProcessAssertionType);

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (295492 => 295493)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2022-06-13 17:16:47 UTC (rev 295492)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2022-06-13 18:20:38 UTC (rev 295493)
@@ -515,6 +515,9 @@
     Ref<WebProcessProxy> createNewWebProcess(WebsiteDataStore*, WebProcessProxy::CaptivePortalMode, WebProcessProxy::IsPrewarmed = WebProcessProxy::IsPrewarmed::No, WebCore::CrossOriginMode = WebCore::CrossOriginMode::Shared);
 
     bool hasAudibleMediaActivity() const { return !!m_audibleMediaActivity; }
+#if PLATFORM(IOS_FAMILY)
+    bool processesShouldSuspend() const { return m_processesShouldSuspend; }
+#endif
 
 private:
     void platformInitialize();
@@ -803,6 +806,10 @@
 #if ENABLE(IPC_TESTING_API)
     IPCTester m_ipcTester;
 #endif
+
+#if PLATFORM(IOS_FAMILY)
+    bool m_processesShouldSuspend { false };
+#endif
 };
 
 template<typename T>

Modified: trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm (295492 => 295493)


--- trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm	2022-06-13 17:16:47 UTC (rev 295492)
+++ trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm	2022-06-13 18:20:38 UTC (rev 295493)
@@ -29,6 +29,7 @@
 #if PLATFORM(IOS_FAMILY)
 
 #import "Logging.h"
+#import "ProcessStateMonitor.h"
 #import "RunningBoardServicesSPI.h"
 #import "WebProcessPool.h"
 #import <UIKit/UIApplication.h>
@@ -64,6 +65,7 @@
 
 - (void)addAssertionNeedingBackgroundTask:(ProcessAndUIAssertion&)assertion;
 - (void)removeAssertionNeedingBackgroundTask:(ProcessAndUIAssertion&)assertion;
+- (void)setProcessStateMonitorEnabled:(BOOL)enabled;
 
 @end
 
@@ -73,6 +75,7 @@
     std::atomic<bool> _backgroundTaskWasInvalidated;
     WeakHashSet<ProcessAndUIAssertion> _assertionsNeedingBackgroundTask;
     dispatch_block_t _pendingTaskReleaseTask;
+    std::unique_ptr<WebKit::ProcessStateMonitor> m_processStateMonitor;
 }
 
 + (WKProcessAssertionBackgroundTaskManager *)shared
@@ -242,8 +245,11 @@
         return;
 
     RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager: endBackgroundTask", self);
-    if (processHasActiveRunTimeLimitation())
+    if (processHasActiveRunTimeLimitation()) {
         WebKit::WebProcessPool::notifyProcessPoolsApplicationIsAboutToSuspend();
+        if (m_processStateMonitor)
+            m_processStateMonitor->processWillBeSuspendedImmediately();
+    }
 
     [_backgroundTask removeObserver:self];
     [_backgroundTask invalidate];
@@ -250,6 +256,21 @@
     _backgroundTask = nullptr;
 }
 
+- (void)setProcessStateMonitorEnabled:(BOOL)enabled
+{
+    if (!enabled) {
+        m_processStateMonitor = nullptr;
+        return;
+    }
+
+    if (!m_processStateMonitor) {
+        m_processStateMonitor = makeUnique<WebKit::ProcessStateMonitor>([](bool suspended) {
+            for (auto& processPool : WebKit::WebProcessPool::allProcessPools())
+                processPool->setProcessesShouldSuspend(suspended);
+        });
+    }
+}
+
 @end
 
 typedef void(^RBSAssertionInvalidationCallbackType)();
@@ -454,6 +475,11 @@
     updateRunInBackgroundCount();
 }
 
+void ProcessAndUIAssertion::setProcessStateMonitorEnabled(bool enabled)
+{
+    [[WKProcessAssertionBackgroundTaskManager shared] setProcessStateMonitorEnabled:enabled];
+}
+
 ProcessAndUIAssertion::~ProcessAndUIAssertion()
 {
     if (m_isHoldingBackgroundTask)

Modified: trunk/Source/WebKit/UIProcess/ios/ProcessStateMonitor.mm (295492 => 295493)


--- trunk/Source/WebKit/UIProcess/ios/ProcessStateMonitor.mm	2022-06-13 17:16:47 UTC (rev 295492)
+++ trunk/Source/WebKit/UIProcess/ios/ProcessStateMonitor.mm	2022-06-13 18:20:38 UTC (rev 295493)
@@ -117,6 +117,8 @@
 
 void ProcessStateMonitor::checkRemainingRunTime()
 {
+#if !PLATFORM(IOS_FAMILY_SIMULATOR)
+    // runTime is meaningful only on device.
     double remainingRunTime = [[[RBSProcessHandle currentProcess] activeLimitations] runTime];
     if (remainingRunTime == RBSProcessTimeLimitationNone)
         return processDidBecomeRunning();
@@ -125,6 +127,7 @@
         return processWillBeSuspendedImmediately();
 
     processWillBeSuspended(Seconds(remainingRunTime - maxPrepareForSuspensionDelayInSecond));
+#endif
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/ios/WebProcessProxyIOS.mm (295492 => 295493)


--- trunk/Source/WebKit/UIProcess/ios/WebProcessProxyIOS.mm	2022-06-13 17:16:47 UTC (rev 295492)
+++ trunk/Source/WebKit/UIProcess/ios/WebProcessProxyIOS.mm	2022-06-13 18:20:38 UTC (rev 295493)
@@ -44,6 +44,8 @@
 #if HAVE(STYLUS_DEVICE_OBSERVATION)
     [[WKStylusDeviceObserver sharedInstance] start];
 #endif
+
+    m_throttler.setAllowsActivities(!m_processPool->processesShouldSuspend());
 }
 
 void WebProcessProxy::platformDestroy()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to