Modified: trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm (247108 => 247109)
--- trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm 2019-07-03 21:43:31 UTC (rev 247108)
+++ trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm 2019-07-03 21:59:07 UTC (rev 247109)
@@ -41,7 +41,6 @@
// the background task before the UIKit timeout (We get killed if we do not release the background task within 5 seconds
// on the expiration handler getting called).
static const Seconds releaseBackgroundTaskAfterExpirationDelay { 2_s };
-static const Seconds maximumBackgroundTaskDuration { 20_s };
@interface WKProcessAssertionBackgroundTaskManager : NSObject
@@ -57,8 +56,7 @@
UIBackgroundTaskIdentifier _backgroundTask;
HashSet<ProcessAndUIAssertion*> _assertionsNeedingBackgroundTask;
BOOL _applicationIsBackgrounded;
- dispatch_block_t _releaseTask;
- dispatch_block_t _timeoutTask;
+ dispatch_block_t _pendingTaskReleaseTask;
}
+ (WKProcessAssertionBackgroundTaskManager *)shared
@@ -67,11 +65,6 @@
return shared;
}
-static bool isBackgroundState(BKSApplicationState state)
-{
- return state == BKSApplicationStateBackgroundRunning || state == BKSApplicationStateBackgroundTaskSuspended;
-}
-
- (instancetype)init
{
self = [super init];
@@ -80,30 +73,14 @@
_backgroundTask = UIBackgroundTaskInvalid;
- {
- auto applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
- _applicationIsBackgrounded = isBackgroundState([applicationStateMonitor mostElevatedApplicationStateForPID:getpid()]);
- [applicationStateMonitor invalidate];
- }
-
- NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
- UIApplication *application = [UIApplication sharedApplication];
-
- [notificationCenter addObserverForName:UIApplicationWillEnterForegroundNotification object:application queue:nil usingBlock:^(NSNotification *) {
- RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager: Application will enter foreground", self);
+ [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication] queue:nil usingBlock:^(NSNotification *) {
_applicationIsBackgrounded = NO;
- [self _cancelReleaseTask];
- [self _cancelTimeoutTask];
+ [self _cancelPendingReleaseTask];
[self _updateBackgroundTask];
}];
- [notificationCenter addObserverForName:UIApplicationDidEnterBackgroundNotification object:application queue:nil usingBlock:^(NSNotification *) {
- RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager: Application did enter background", self);
+ [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication] queue:nil usingBlock:^(NSNotification *) {
_applicationIsBackgrounded = YES;
-
- // We do not want to keep the app awake for more than 20 seconds after it gets backgrounded, so start the timeout timer now.
- if (_backgroundTask != UIBackgroundTaskInvalid)
- [self _scheduleTimeoutTask];
}];
return self;
@@ -135,84 +112,35 @@
assertion->uiAssertionWillExpireImminently();
}
-- (void)_scheduleTimeoutTask
-{
- ASSERT(_backgroundTask != UIBackgroundTaskInvalid);
- if (_timeoutTask)
- return;
-
- RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - _scheduleTimeoutTask", self);
- _timeoutTask = dispatch_block_create((dispatch_block_flags_t)0, ^{
- _timeoutTask = nil;
- RELEASE_LOG_ERROR(ProcessSuspension, "Background task was running for too long so WebKit will end it shortly.");
- [self _backgroundTaskExpired];
- });
-
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, maximumBackgroundTaskDuration.value() * NSEC_PER_SEC), dispatch_get_main_queue(), _timeoutTask);
-#if !__has_feature(objc_arc)
- // dispatch_async() does a Block_copy() / Block_release() on behalf of the caller.
- Block_release(_timeoutTask);
-#endif
-}
-
-- (void)_cancelTimeoutTask
-{
- if (!_timeoutTask)
- return;
-
- RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - _cancelTimeoutTask", self);
- dispatch_block_cancel(_timeoutTask);
- _timeoutTask = nil;
-}
-
- (void)_scheduleReleaseTask
{
- ASSERT(!_releaseTask);
- if (_releaseTask)
+ ASSERT(!_pendingTaskReleaseTask);
+ if (_pendingTaskReleaseTask)
return;
RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - _scheduleReleaseTask because the expiration handler has been called", self);
- _releaseTask = dispatch_block_create((dispatch_block_flags_t)0, ^{
- _releaseTask = nil;
+ _pendingTaskReleaseTask = dispatch_block_create((dispatch_block_flags_t)0, ^{
+ _pendingTaskReleaseTask = nil;
[self _releaseBackgroundTask];
});
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, releaseBackgroundTaskAfterExpirationDelay.value() * NSEC_PER_SEC), dispatch_get_main_queue(), _releaseTask);
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, releaseBackgroundTaskAfterExpirationDelay.value() * NSEC_PER_SEC), dispatch_get_main_queue(), _pendingTaskReleaseTask);
#if !__has_feature(objc_arc)
// dispatch_async() does a Block_copy() / Block_release() on behalf of the caller.
- Block_release(_releaseTask);
+ Block_release(_pendingTaskReleaseTask);
#endif
}
-- (void)_cancelReleaseTask
+- (void)_cancelPendingReleaseTask
{
- if (!_releaseTask)
+ if (!_pendingTaskReleaseTask)
return;
- RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - _cancelReleaseTask because the application is foreground again", self);
- dispatch_block_cancel(_releaseTask);
- _releaseTask = nil;
+ RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - _cancelPendingReleaseTask because the application is foreground again", self);
+ dispatch_block_cancel(_pendingTaskReleaseTask);
+ _pendingTaskReleaseTask = nil;
}
-- (void)_backgroundTaskExpired
-{
- RELEASE_LOG_ERROR(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - _backgroundTaskExpired", self);
- ASSERT(_applicationIsBackgrounded);
- [self _cancelTimeoutTask];
-
- // Tell our child processes they will suspend imminently.
- if (RunLoop::isMain())
- [self _notifyAssertionsOfImminentSuspension];
- else {
- // The expiration handler gets called on a non-main thread when the underlying assertion could not be taken (rdar://problem/27278419).
- dispatch_sync(dispatch_get_main_queue(), ^{
- [self _notifyAssertionsOfImminentSuspension];
- });
- }
-
- [self _scheduleReleaseTask];
-}
-
- (void)_updateBackgroundTask
{
if (!_assertionsNeedingBackgroundTask.isEmpty() && _backgroundTask == UIBackgroundTaskInvalid) {
@@ -222,7 +150,7 @@
}
RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - beginBackgroundTaskWithName", self);
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"com.apple.WebKit.ProcessAssertion" expirationHandler:^{
- RELEASE_LOG_ERROR(ProcessSuspension, "Background task expired while holding WebKit ProcessAssertion (isMainThread? %d, _applicationIsBackgrounded? %d).", RunLoop::isMain(), _applicationIsBackgrounded);
+ RELEASE_LOG_ERROR(ProcessSuspension, "Background task expired while holding WebKit ProcessAssertion (isMainThread? %d).", RunLoop::isMain());
if (!_applicationIsBackgrounded) {
// We've received the invalidation warning after the app has become foreground again. In this case, we should not
// warn clients of imminent suspension. To be safe (avoid potential killing), we end the task right away and call
@@ -233,8 +161,17 @@
});
return;
}
-
- [self _backgroundTaskExpired];
+
+ // The expiration handler gets called on a non-main thread when the underlying assertion could not be taken (rdar://problem/27278419).
+ if (RunLoop::isMain())
+ [self _notifyAssertionsOfImminentSuspension];
+ else {
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ [self _notifyAssertionsOfImminentSuspension];
+ });
+ }
+
+ [self _scheduleReleaseTask];
}];
} else if (_assertionsNeedingBackgroundTask.isEmpty())
[self _releaseBackgroundTask];
@@ -247,8 +184,6 @@
RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - endBackgroundTask", self);
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
- [self _cancelReleaseTask];
- [self _cancelTimeoutTask];
_backgroundTask = UIBackgroundTaskInvalid;
}