Commit 0692640e authored by Olivier Robin's avatar Olivier Robin Committed by Commit Bot

Pause PreviousSessionInfo when protected data is unavailable.

When Protected data is not available, access NSUserDefault can freeze
the application.
Pause all the data collection based on notifications on that period.

Bug: 1129779
Change-Id: I2d304e410b2e2068b71ab3363e548e43e66b973c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454088Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Commit-Queue: Olivier Robin <olivierrobin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815161}
parent c3740b5c
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "url/gurl.h" #include "url/gurl.h"
namespace previous_session_info_constants { namespace previous_session_info_constants {
// - The (Integer) representing UIApplicationState.
extern NSString* const kPreviousSessionInfoApplicationState;
// Key in the UserDefaults for a boolean value keeping track of memory warnings. // Key in the UserDefaults for a boolean value keeping track of memory warnings.
extern NSString* const kDidSeeMemoryWarningShortlyBeforeTerminating; extern NSString* const kDidSeeMemoryWarningShortlyBeforeTerminating;
// Key in the UserDefaults for a double value which stores OS start time. // Key in the UserDefaults for a double value which stores OS start time.
......
...@@ -66,9 +66,6 @@ DeviceThermalState GetThermalStateFromNSProcessInfoThermalState( ...@@ -66,9 +66,6 @@ DeviceThermalState GetThermalStateFromNSProcessInfoThermalState(
NSString* const kLastRanVersion = @"LastRanVersion"; NSString* const kLastRanVersion = @"LastRanVersion";
// - The (string) device language. // - The (string) device language.
NSString* const kLastRanLanguage = @"LastRanLanguage"; NSString* const kLastRanLanguage = @"LastRanLanguage";
// - The (Integer) representing UIApplicationState.
NSString* const kPreviousSessionInfoApplicationState =
@"PreviousSessionInfoApplicationState";
// - The (integer) available device storage, in kilobytes. // - The (integer) available device storage, in kilobytes.
NSString* const kPreviousSessionInfoAvailableDeviceStorage = NSString* const kPreviousSessionInfoAvailableDeviceStorage =
@"PreviousSessionInfoAvailableDeviceStorage"; @"PreviousSessionInfoAvailableDeviceStorage";
...@@ -97,6 +94,8 @@ NSString* const kPreviousSessionInfoMultiWindowEnabled = ...@@ -97,6 +94,8 @@ NSString* const kPreviousSessionInfoMultiWindowEnabled =
} // namespace } // namespace
namespace previous_session_info_constants { namespace previous_session_info_constants {
NSString* const kPreviousSessionInfoApplicationState =
@"PreviousSessionInfoApplicationState";
NSString* const kDidSeeMemoryWarningShortlyBeforeTerminating = NSString* const kDidSeeMemoryWarningShortlyBeforeTerminating =
@"DidSeeMemoryWarning"; @"DidSeeMemoryWarning";
NSString* const kOSStartTime = @"OSStartTime"; NSString* const kOSStartTime = @"OSStartTime";
...@@ -112,6 +111,9 @@ NSString* const kPreviousSessionInfoURLs = @"PreviousSessionInfoURLs"; ...@@ -112,6 +111,9 @@ NSString* const kPreviousSessionInfoURLs = @"PreviousSessionInfoURLs";
// Whether beginRecordingCurrentSession was called. // Whether beginRecordingCurrentSession was called.
@property(nonatomic, assign) BOOL didBeginRecordingCurrentSession; @property(nonatomic, assign) BOOL didBeginRecordingCurrentSession;
// Whether recording data is in progress.
@property(nonatomic, assign) BOOL recordingCurrentSession;
// Used for setting and resetting kPreviousSessionInfoRestoringSession flag. // Used for setting and resetting kPreviousSessionInfoRestoringSession flag.
// Can be greater than one if multiple sessions are being restored in parallel. // Can be greater than one if multiple sessions are being restored in parallel.
@property(atomic, assign) int numberOfSessionsBeingRestored; @property(atomic, assign) int numberOfSessionsBeingRestored;
...@@ -151,10 +153,12 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -151,10 +153,12 @@ static PreviousSessionInfo* gSharedInstance = nil;
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
gSharedInstance->_applicationState.reset(); gSharedInstance->_applicationState.reset();
if ([defaults objectForKey:kPreviousSessionInfoApplicationState]) { if ([defaults objectForKey:previous_session_info_constants::
gSharedInstance->_applicationState = kPreviousSessionInfoApplicationState]) {
std::make_unique<UIApplicationState>(static_cast<UIApplicationState>( gSharedInstance->_applicationState = std::make_unique<UIApplicationState>(
[defaults integerForKey:kPreviousSessionInfoApplicationState])); static_cast<UIApplicationState>([defaults
integerForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]));
} }
gSharedInstance.availableDeviceStorage = -1; gSharedInstance.availableDeviceStorage = -1;
...@@ -231,7 +235,6 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -231,7 +235,6 @@ static PreviousSessionInfo* gSharedInstance = nil;
if (self.didBeginRecordingCurrentSession) if (self.didBeginRecordingCurrentSession)
return; return;
self.didBeginRecordingCurrentSession = YES; self.didBeginRecordingCurrentSession = YES;
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
// Set the current Chrome version. // Set the current Chrome version.
...@@ -263,7 +266,6 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -263,7 +266,6 @@ static PreviousSessionInfo* gSharedInstance = nil;
removeObjectForKey:previous_session_info_constants:: removeObjectForKey:previous_session_info_constants::
kDidSeeMemoryWarningShortlyBeforeTerminating]; kDidSeeMemoryWarningShortlyBeforeTerminating];
[self updateApplicationState];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
selector:@selector(updateApplicationState) selector:@selector(updateApplicationState)
...@@ -274,6 +276,16 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -274,6 +276,16 @@ static PreviousSessionInfo* gSharedInstance = nil;
selector:@selector(updateApplicationState) selector:@selector(updateApplicationState)
name:UIApplicationWillEnterForegroundNotification name:UIApplicationWillEnterForegroundNotification
object:nil]; object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(protectedDataWillBecomeUnavailable)
name:UIApplicationProtectedDataWillBecomeUnavailable
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(protectedDataDidBecomeAvailable)
name:UIApplicationProtectedDataWillBecomeUnavailable
object:nil];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
selector:@selector(updateApplicationState) selector:@selector(updateApplicationState)
...@@ -286,36 +298,57 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -286,36 +298,57 @@ static PreviousSessionInfo* gSharedInstance = nil;
object:nil]; object:nil];
[UIDevice currentDevice].batteryMonitoringEnabled = YES; [UIDevice currentDevice].batteryMonitoringEnabled = YES;
[self updateStoredBatteryLevel];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
selector:@selector(updateStoredBatteryLevel) selector:@selector(updateStoredBatteryLevel)
name:UIDeviceBatteryLevelDidChangeNotification name:UIDeviceBatteryLevelDidChangeNotification
object:nil]; object:nil];
[self updateStoredBatteryState];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
selector:@selector(updateStoredBatteryState) selector:@selector(updateStoredBatteryState)
name:UIDeviceBatteryStateDidChangeNotification name:UIDeviceBatteryStateDidChangeNotification
object:nil]; object:nil];
[self updateStoredLowPowerMode];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
selector:@selector(updateStoredLowPowerMode) selector:@selector(updateStoredLowPowerMode)
name:NSProcessInfoPowerStateDidChangeNotification name:NSProcessInfoPowerStateDidChangeNotification
object:nil]; object:nil];
[self updateStoredThermalState];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
selector:@selector(updateStoredThermalState) selector:@selector(updateStoredThermalState)
name:NSProcessInfoThermalStateDidChangeNotification name:NSProcessInfoThermalStateDidChangeNotification
object:nil]; object:nil];
[self resumeRecordingCurrentSession];
}
- (void)resumeRecordingCurrentSession {
if (self.recordingCurrentSession)
return;
self.recordingCurrentSession = YES;
[self updateApplicationState];
[self updateStoredBatteryLevel];
[self updateStoredBatteryState];
[self updateStoredLowPowerMode];
[self updateStoredThermalState];
// Save critical state information for crash detection. // Save critical state information for crash detection.
[defaults synchronize]; [[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)pauseRecordingCurrentSession {
self.recordingCurrentSession = NO;
}
- (void)protectedDataWillBecomeUnavailable {
[self pauseRecordingCurrentSession];
}
- (void)protectedDataDidBecomeAvailable {
[self resumeRecordingCurrentSession];
} }
- (UIApplicationState*)applicationState { - (UIApplicationState*)applicationState {
...@@ -323,7 +356,7 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -323,7 +356,7 @@ static PreviousSessionInfo* gSharedInstance = nil;
} }
- (void)updateAvailableDeviceStorage:(NSInteger)availableStorage { - (void)updateAvailableDeviceStorage:(NSInteger)availableStorage {
if (!self.didBeginRecordingCurrentSession) if (!self.recordingCurrentSession)
return; return;
[[NSUserDefaults standardUserDefaults] [[NSUserDefaults standardUserDefaults]
...@@ -334,11 +367,15 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -334,11 +367,15 @@ static PreviousSessionInfo* gSharedInstance = nil;
} }
- (void)updateSessionEndTime { - (void)updateSessionEndTime {
if (!self.recordingCurrentSession)
return;
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] [[NSUserDefaults standardUserDefaults] setObject:[NSDate date]
forKey:kPreviousSessionInfoEndTime]; forKey:kPreviousSessionInfoEndTime];
} }
- (void)updateStoredBatteryLevel { - (void)updateStoredBatteryLevel {
if (!self.recordingCurrentSession)
return;
[[NSUserDefaults standardUserDefaults] [[NSUserDefaults standardUserDefaults]
setFloat:[UIDevice currentDevice].batteryLevel setFloat:[UIDevice currentDevice].batteryLevel
forKey:kPreviousSessionInfoBatteryLevel]; forKey:kPreviousSessionInfoBatteryLevel];
...@@ -346,14 +383,19 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -346,14 +383,19 @@ static PreviousSessionInfo* gSharedInstance = nil;
} }
- (void)updateApplicationState { - (void)updateApplicationState {
if (!self.recordingCurrentSession)
return;
[[NSUserDefaults standardUserDefaults] [[NSUserDefaults standardUserDefaults]
setInteger:UIApplication.sharedApplication.applicationState setInteger:UIApplication.sharedApplication.applicationState
forKey:kPreviousSessionInfoApplicationState]; forKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState];
[self updateSessionEndTime]; [self updateSessionEndTime];
} }
- (void)updateStoredBatteryState { - (void)updateStoredBatteryState {
if (!self.recordingCurrentSession)
return;
UIDevice* device = [UIDevice currentDevice]; UIDevice* device = [UIDevice currentDevice];
// Translate value to an app defined enum as the system could change the // Translate value to an app defined enum as the system could change the
// underlying values of UIDeviceBatteryState between OS versions. // underlying values of UIDeviceBatteryState between OS versions.
...@@ -370,6 +412,8 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -370,6 +412,8 @@ static PreviousSessionInfo* gSharedInstance = nil;
} }
- (void)updateStoredLowPowerMode { - (void)updateStoredLowPowerMode {
if (!self.recordingCurrentSession)
return;
BOOL isLowPoweredModeEnabled = BOOL isLowPoweredModeEnabled =
[[NSProcessInfo processInfo] isLowPowerModeEnabled]; [[NSProcessInfo processInfo] isLowPowerModeEnabled];
[[NSUserDefaults standardUserDefaults] [[NSUserDefaults standardUserDefaults]
...@@ -380,6 +424,8 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -380,6 +424,8 @@ static PreviousSessionInfo* gSharedInstance = nil;
} }
- (void)updateStoredThermalState { - (void)updateStoredThermalState {
if (!self.recordingCurrentSession)
return;
NSProcessInfo* processInfo = [NSProcessInfo processInfo]; NSProcessInfo* processInfo = [NSProcessInfo processInfo];
// Translate value to an app defined enum as the system could change the // Translate value to an app defined enum as the system could change the
// underlying values of NSProcessInfoThermalState between OS versions. // underlying values of NSProcessInfoThermalState between OS versions.
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
+ (void)resetSharedInstanceForTesting; + (void)resetSharedInstanceForTesting;
- (void)pauseRecordingCurrentSession;
- (void)resumeRecordingCurrentSession;
- (void)updateApplicationState;
@end @end
#endif // IOS_CHROME_BROWSER_METRICS_PREVIOUS_SESSION_INFO_PRIVATE_H_ #endif // IOS_CHROME_BROWSER_METRICS_PREVIOUS_SESSION_INFO_PRIVATE_H_
...@@ -552,4 +552,78 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) { ...@@ -552,4 +552,78 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) {
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
} }
// Tests data collection pausing.
TEST_F(PreviousSessionInfoTest, PausePreviousSessionInfoCollection) {
// Default state.
[NSUserDefaults.standardUserDefaults
removeObjectForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState];
[PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_FALSE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Start recording. This should update the state.
[[PreviousSessionInfo sharedInstance] beginRecordingCurrentSession];
EXPECT_TRUE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Cleanup.
[NSUserDefaults.standardUserDefaults
removeObjectForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState];
EXPECT_FALSE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Updating state should work when recording is enabled.
[[PreviousSessionInfo sharedInstance] updateApplicationState];
EXPECT_TRUE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Cleanup.
[NSUserDefaults.standardUserDefaults
removeObjectForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState];
EXPECT_FALSE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Updating state should be noop when recording is paused.
[[PreviousSessionInfo sharedInstance] pauseRecordingCurrentSession];
[[PreviousSessionInfo sharedInstance] updateApplicationState];
EXPECT_FALSE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Resume recording should update the state.
[[PreviousSessionInfo sharedInstance] resumeRecordingCurrentSession];
EXPECT_TRUE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Cleanup
[NSUserDefaults.standardUserDefaults
removeObjectForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState];
EXPECT_FALSE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Updating state should work when recording is enabled.
[[PreviousSessionInfo sharedInstance] updateApplicationState];
EXPECT_TRUE([NSUserDefaults.standardUserDefaults
valueForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState]);
// Cleanup.
[NSUserDefaults.standardUserDefaults
removeObjectForKey:previous_session_info_constants::
kPreviousSessionInfoApplicationState];
[PreviousSessionInfo resetSharedInstanceForTesting];
}
} // namespace } // namespace
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment