| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #if !defined(NDEBUG) |
| 6 |
| 7 #import "ios/chrome/app/UIApplication+ExitsOnSuspend.h" |
| 8 |
| 9 #include "base/ios/block_types.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/threading/thread_restrictions.h" |
| 12 |
| 13 NSString* const kExitsOnSuspend = @"EnableExitsOnSuspend"; |
| 14 |
| 15 namespace { |
| 16 int backgroundTasksCount = 0; |
| 17 UIBackgroundTaskIdentifier countTaskIdentifier = UIBackgroundTaskInvalid; |
| 18 |
| 19 // Perform a block on the main thread. Asynchronously if the thread is not the |
| 20 // main thread, synchronously if the thread is the main thread. |
| 21 void ExecuteBlockOnMainThread(ProceduralBlock block) { |
| 22 if ([NSThread isMainThread]) |
| 23 block(); |
| 24 else |
| 25 dispatch_async(dispatch_get_main_queue(), block); |
| 26 } |
| 27 } // namespace |
| 28 |
| 29 // Category defining interposing methods. These methods keep a tally of the |
| 30 // background tasks count. |
| 31 @implementation UIApplication (BackgroundTasksCounter) |
| 32 |
| 33 // Method to replace -beginBackgroundTaskWithExpirationHandler:. The original |
| 34 // method is called within. |
| 35 - (UIBackgroundTaskIdentifier) |
| 36 cr_interpose_beginBackgroundTaskWithExpirationHandler: |
| 37 (ProceduralBlock)handler { |
| 38 UIBackgroundTaskIdentifier identifier = |
| 39 [self cr_interpose_beginBackgroundTaskWithExpirationHandler:handler]; |
| 40 if (identifier != UIBackgroundTaskInvalid) { |
| 41 ExecuteBlockOnMainThread(^{ |
| 42 backgroundTasksCount++; |
| 43 }); |
| 44 } |
| 45 return identifier; |
| 46 } |
| 47 |
| 48 // Method to replace -endBackgroundTask:. The original method is called within. |
| 49 - (void)cr_interpose_endBackgroundTask:(UIBackgroundTaskIdentifier)identifier { |
| 50 if (identifier != UIBackgroundTaskInvalid) |
| 51 ExecuteBlockOnMainThread(^{ |
| 52 backgroundTasksCount--; |
| 53 }); |
| 54 [self cr_interpose_endBackgroundTask:identifier]; |
| 55 } |
| 56 |
| 57 @end |
| 58 |
| 59 @interface UIApplication (ExitsOnSuspend_Private) |
| 60 // Terminate the app immediately. exit(0) is used. |
| 61 - (void)cr_terminateImmediately; |
| 62 // Terminate the app via -cr_terminateImmediately when the background tasks |
| 63 // count is one. The remaining task is the count observation task. |
| 64 - (void)cr_terminateWhenCountIsOne; |
| 65 @end |
| 66 |
| 67 @implementation UIApplication (ExitsOnSuspend) |
| 68 |
| 69 - (void)cr_terminateWhenDoneWithBackgroundTasks { |
| 70 // Add a background task for the count observation. |
| 71 DCHECK(countTaskIdentifier == UIBackgroundTaskInvalid); |
| 72 countTaskIdentifier = [self beginBackgroundTaskWithExpirationHandler:^{ |
| 73 // If we get to the end of the 10 minutes, exit. |
| 74 [self cr_terminateImmediately]; |
| 75 }]; |
| 76 |
| 77 [self cr_terminateWhenCountIsOne]; |
| 78 } |
| 79 |
| 80 - (void)cr_cancelTermination { |
| 81 [NSObject |
| 82 cancelPreviousPerformRequestsWithTarget:self |
| 83 selector:@selector( |
| 84 cr_terminateWhenCountIsOne) |
| 85 object:nil]; |
| 86 |
| 87 // Cancel the count observation background task. |
| 88 [self endBackgroundTask:countTaskIdentifier]; |
| 89 countTaskIdentifier = UIBackgroundTaskInvalid; |
| 90 } |
| 91 |
| 92 #pragma mark - Private |
| 93 |
| 94 - (void)cr_terminateImmediately { |
| 95 DVLOG(1) << "App exited when suspended after running background tasks."; |
| 96 // exit(0) will trigger at_exit handlers. Some need to be run on a IOAllowed |
| 97 // thread, such as file_util::MemoryMappedFile::CloseHandles(). |
| 98 base::ThreadRestrictions::SetIOAllowed(true); |
| 99 exit(0); |
| 100 } |
| 101 |
| 102 - (void)cr_terminateWhenCountIsOne { |
| 103 if (backgroundTasksCount <= 1) |
| 104 [self cr_terminateImmediately]; |
| 105 [self performSelector:_cmd withObject:nil afterDelay:1]; |
| 106 } |
| 107 |
| 108 @end |
| 109 |
| 110 #endif // !defined(NDEBUG) |
| OLD | NEW |