Unreviewed, rolling out r246053.
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Jul 2019 21:59:07 +0000 (21:59 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Jul 2019 21:59:07 +0000 (21:59 +0000)
This changeset caused media playback to break when the hosting app was backgrounded.

* UIProcess/ApplicationStateTracker.mm:
* UIProcess/ios/ProcessAssertionIOS.mm:
(-[WKProcessAssertionBackgroundTaskManager init]):
(-[WKProcessAssertionBackgroundTaskManager _scheduleReleaseTask]):
(-[WKProcessAssertionBackgroundTaskManager _cancelPendingReleaseTask]):
(-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):
(-[WKProcessAssertionBackgroundTaskManager _releaseBackgroundTask]):

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

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ApplicationStateTracker.mm
Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm

index 842920b..02660a9 100644 (file)
@@ -1,3 +1,17 @@
+2019-07-03  Jer Noble  <jer.noble@apple.com>
+
+        Unreviewed, rolling out r246053.
+
+        This changeset caused media playback to break when the hosting app was backgrounded.
+
+        * UIProcess/ApplicationStateTracker.mm:
+        * UIProcess/ios/ProcessAssertionIOS.mm:
+        (-[WKProcessAssertionBackgroundTaskManager init]):
+        (-[WKProcessAssertionBackgroundTaskManager _scheduleReleaseTask]):
+        (-[WKProcessAssertionBackgroundTaskManager _cancelPendingReleaseTask]):
+        (-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):
+        (-[WKProcessAssertionBackgroundTaskManager _releaseBackgroundTask]):
+
 2019-07-03  Alex Christensen  <achristensen@webkit.org>
 
         Use smarter pointers in WKDownloadProgress
index ba8a7a8..507922f 100644 (file)
@@ -142,11 +142,9 @@ ApplicationStateTracker::ApplicationStateTracker(UIView *view, SEL didEnterBackg
         pid_t applicationPID = serviceViewController._hostProcessIdentifier;
         ASSERT(applicationPID);
 
-        {
-            auto applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
-            m_isInBackground = isBackgroundState([applicationStateMonitor mostElevatedApplicationStateForPID:applicationPID]);
-            [applicationStateMonitor invalidate];
-        }
+        auto applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
+        m_isInBackground = isBackgroundState([applicationStateMonitor mostElevatedApplicationStateForPID:applicationPID]);
+        [applicationStateMonitor invalidate];
 
         // Workaround for <rdar://problem/34028921>. If the host application is StoreKitUIService then it is also a ViewService
         // and is always in the background. We need to treat StoreKitUIService as foreground for the purpose of process suspension
index f5d2f64..c149103 100644 (file)
@@ -41,7 +41,6 @@ using WebKit::ProcessAndUIAssertion;
 // 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 @@ static const Seconds maximumBackgroundTaskDuration { 20_s };
     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 @@ static const Seconds maximumBackgroundTaskDuration { 20_s };
     return shared;
 }
 
-static bool isBackgroundState(BKSApplicationState state)
-{
-    return state == BKSApplicationStateBackgroundRunning || state == BKSApplicationStateBackgroundTaskSuspended;
-}
-
 - (instancetype)init
 {
     self = [super init];
@@ -80,30 +73,14 @@ static bool isBackgroundState(BKSApplicationState state)
 
     _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,82 +112,33 @@ static bool isBackgroundState(BKSApplicationState state)
         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;
-}
-
-- (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];
+    RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - _cancelPendingReleaseTask because the application is foreground again", self);
+    dispatch_block_cancel(_pendingTaskReleaseTask);
+    _pendingTaskReleaseTask = nil;
 }
 
 - (void)_updateBackgroundTask
@@ -222,7 +150,7 @@ static bool isBackgroundState(BKSApplicationState state)
         }
         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 @@ static bool isBackgroundState(BKSApplicationState state)
                 });
                 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 @@ static bool isBackgroundState(BKSApplicationState state)
 
     RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - endBackgroundTask", self);
     [[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
-    [self _cancelReleaseTask];
-    [self _cancelTimeoutTask];
     _backgroundTask = UIBackgroundTaskInvalid;
 }