| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "components/previous_session_info/previous_session_info.h" |
| |
| #include <mach/mach.h> |
| |
| #import <UIKit/UIKit.h> |
| |
| #include "base/ios/ios_util.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "base/system/sys_info.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #import "components/previous_session_info/previous_session_info_private.h" |
| #include "components/version_info/version_info.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| using previous_session_info_constants::DeviceBatteryState; |
| using previous_session_info_constants::DeviceThermalState; |
| |
| namespace { |
| |
| // Returns timestamp (in seconds since January 2001) when OS has started. |
| NSTimeInterval GetOSStartTimeIntervalSinceReferenceDate() { |
| return NSDate.timeIntervalSinceReferenceDate - |
| NSProcessInfo.processInfo.systemUptime; |
| } |
| |
| // Translates a UIDeviceBatteryState value to DeviceBatteryState value. |
| DeviceBatteryState GetBatteryStateFromUIDeviceBatteryState( |
| UIDeviceBatteryState device_battery_state) { |
| switch (device_battery_state) { |
| case UIDeviceBatteryStateUnknown: |
| return DeviceBatteryState::kUnknown; |
| case UIDeviceBatteryStateUnplugged: |
| return DeviceBatteryState::kUnplugged; |
| case UIDeviceBatteryStateCharging: |
| return DeviceBatteryState::kCharging; |
| case UIDeviceBatteryStateFull: |
| return DeviceBatteryState::kFull; |
| } |
| |
| return DeviceBatteryState::kUnknown; |
| } |
| |
| // Translates a NSProcessInfoThermalState value to DeviceThermalState value. |
| DeviceThermalState GetThermalStateFromNSProcessInfoThermalState( |
| NSProcessInfoThermalState process_info_thermal_state) { |
| switch (process_info_thermal_state) { |
| case NSProcessInfoThermalStateNominal: |
| return DeviceThermalState::kNominal; |
| case NSProcessInfoThermalStateFair: |
| return DeviceThermalState::kFair; |
| case NSProcessInfoThermalStateSerious: |
| return DeviceThermalState::kSerious; |
| case NSProcessInfoThermalStateCritical: |
| return DeviceThermalState::kCritical; |
| } |
| |
| return DeviceThermalState::kUnknown; |
| } |
| |
| // NSUserDefaults keys. |
| // - The (string) application version. |
| NSString* const kLastRanVersion = @"LastRanVersion"; |
| // - The (string) device language. |
| NSString* const kLastRanLanguage = @"LastRanLanguage"; |
| // - The (integer) available device storage, in kilobytes. |
| NSString* const kPreviousSessionInfoAvailableDeviceStorage = |
| @"PreviousSessionInfoAvailableDeviceStorage"; |
| // - The (float) battery charge level. |
| NSString* const kPreviousSessionInfoBatteryLevel = |
| @"PreviousSessionInfoBatteryLevel"; |
| // - The (integer) underlying value of the DeviceBatteryState enum representing |
| // the device battery state. |
| NSString* const kPreviousSessionInfoBatteryState = |
| @"PreviousSessionInfoBatteryState"; |
| // - The (Date) of the recording start. |
| NSString* const kPreviousSessionInfoStartTime = @"PreviousSessionInfoStartTime"; |
| // - The (Date) of the estimated end of the session. |
| NSString* const kPreviousSessionInfoEndTime = @"PreviousSessionInfoEndTime"; |
| // - The (string) OS version. |
| NSString* const kPreviousSessionInfoOSVersion = @"PreviousSessionInfoOSVersion"; |
| // - The (integer) underlying value of the DeviceThermalState enum representing |
| // the device thermal state. |
| NSString* const kPreviousSessionInfoThermalState = |
| @"PreviousSessionInfoThermalState"; |
| // TODO(crbug.com/1266034): Remove key for no longer logged state. |
| // - A (boolean) describing whether or not low power mode is enabled. |
| NSString* const kPreviousSessionInfoLowPowerMode = |
| @"PreviousSessionInfoLowPowerMode"; |
| // TODO(crbug.com/1295763): Remove key for no longer used state. |
| // - A (boolean) describing whether the last session was on Multi-Window enabled |
| // version of the application. |
| NSString* const kPreviousSessionInfoMultiWindowEnabled = |
| @"PreviousSessionInfoMultiWindowEnabled"; |
| // - A (boolean) describing whether the last session received |
| // ApplicationWillTerminate Notification. |
| NSString* const kPreviousSessionInfoAppWillTerminate = |
| @"PreviousSessionInfoAppWillTerminate"; |
| } // namespace |
| |
| namespace previous_session_info_constants { |
| NSString* const kPreviousSessionInfoApplicationState = |
| @"PreviousSessionInfoApplicationState"; |
| NSString* const kDidSeeMemoryWarningShortlyBeforeTerminating = |
| @"DidSeeMemoryWarning"; |
| NSString* const kOSStartTime = @"OSStartTime"; |
| NSString* const kPreviousSessionInfoRestoringSession = |
| @"PreviousSessionInfoRestoringSession"; |
| NSString* const kPreviousSessionInfoConnectedSceneSessionIDs = |
| @"PreviousSessionInfoConnectedSceneSessionIDs"; |
| NSString* const kPreviousSessionInfoParams = @"PreviousSessionInfoParams"; |
| NSString* const kPreviousSessionInfoMemoryFootprint = |
| @"PreviousSessionInfoMemoryFootprint"; |
| NSString* const kPreviousSessionInfoTabCount = @"PreviousSessionInfoTabCount"; |
| NSString* const kPreviousSessionInfoOTRTabCount = |
| @"PreviousSessionInfoOTRTabCount"; |
| } // namespace previous_session_info_constants |
| |
| @interface PreviousSessionInfo () |
| |
| // Whether beginRecordingCurrentSession was called. |
| @property(nonatomic, assign) BOOL didBeginRecordingCurrentSession; |
| |
| // Whether recording data is in progress. |
| @property(nonatomic, assign) BOOL recordingCurrentSession; |
| |
| // Used for setting and resetting kPreviousSessionInfoRestoringSession flag. |
| // Can be greater than one if multiple sessions are being restored in parallel. |
| @property(atomic, assign) int numberOfSessionsBeingRestored; |
| |
| // Redefined to be read-write. |
| @property(nonatomic, assign) NSInteger availableDeviceStorage; |
| @property(nonatomic, assign) float deviceBatteryLevel; |
| @property(nonatomic, assign) DeviceBatteryState deviceBatteryState; |
| @property(nonatomic, assign) DeviceThermalState deviceThermalState; |
| @property(nonatomic, assign) BOOL didSeeMemoryWarningShortlyBeforeTerminating; |
| @property(nonatomic, assign) BOOL isFirstSessionAfterUpgrade; |
| @property(nonatomic, assign) BOOL isFirstSessionAfterLanguageChange; |
| @property(nonatomic, assign) BOOL OSRestartedAfterPreviousSession; |
| @property(nonatomic, strong) NSString* OSVersion; |
| @property(nonatomic, strong) NSDate* sessionStartTime; |
| @property(nonatomic, strong) NSDate* sessionEndTime; |
| @property(nonatomic, assign) BOOL terminatedDuringSessionRestoration; |
| @property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs; |
| @property(nonatomic, copy) NSDictionary<NSString*, NSString*>* reportParameters; |
| @property(nonatomic, assign) NSInteger memoryFootprint; |
| @property(nonatomic, assign) BOOL applicationWillTerminateWasReceived; |
| @property(nonatomic, assign) NSInteger tabCount; |
| @property(nonatomic, assign) NSInteger OTRTabCount; |
| |
| @end |
| |
| @implementation PreviousSessionInfo { |
| std::unique_ptr<UIApplicationState> _applicationState; |
| base::RepeatingTimer _memoryFootprintUpdateTimer; |
| } |
| |
| // Singleton PreviousSessionInfo. |
| static PreviousSessionInfo* gSharedInstance = nil; |
| |
| + (instancetype)sharedInstance { |
| if (!gSharedInstance) { |
| gSharedInstance = [[PreviousSessionInfo alloc] init]; |
| |
| // Load the persisted information. |
| NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| |
| gSharedInstance->_applicationState.reset(); |
| if ([defaults objectForKey:previous_session_info_constants:: |
| kPreviousSessionInfoApplicationState]) { |
| gSharedInstance->_applicationState = std::make_unique<UIApplicationState>( |
| static_cast<UIApplicationState>([defaults |
| integerForKey:previous_session_info_constants:: |
| kPreviousSessionInfoApplicationState])); |
| } |
| |
| gSharedInstance.availableDeviceStorage = -1; |
| if ([defaults objectForKey:kPreviousSessionInfoAvailableDeviceStorage]) { |
| gSharedInstance.availableDeviceStorage = |
| [defaults integerForKey:kPreviousSessionInfoAvailableDeviceStorage]; |
| } |
| gSharedInstance.didSeeMemoryWarningShortlyBeforeTerminating = |
| [defaults boolForKey:previous_session_info_constants:: |
| kDidSeeMemoryWarningShortlyBeforeTerminating]; |
| gSharedInstance.deviceBatteryState = static_cast<DeviceBatteryState>( |
| [defaults integerForKey:kPreviousSessionInfoBatteryState]); |
| gSharedInstance.deviceBatteryLevel = |
| [defaults floatForKey:kPreviousSessionInfoBatteryLevel]; |
| gSharedInstance.deviceThermalState = static_cast<DeviceThermalState>( |
| [defaults integerForKey:kPreviousSessionInfoThermalState]); |
| gSharedInstance.sessionStartTime = |
| [defaults objectForKey:kPreviousSessionInfoStartTime]; |
| gSharedInstance.sessionEndTime = |
| [defaults objectForKey:kPreviousSessionInfoEndTime]; |
| |
| NSString* versionOfOSAtLastRun = |
| [defaults stringForKey:kPreviousSessionInfoOSVersion]; |
| gSharedInstance.OSVersion = versionOfOSAtLastRun; |
| |
| NSString* lastRanVersion = [defaults stringForKey:kLastRanVersion]; |
| NSString* currentVersion = |
| base::SysUTF8ToNSString(version_info::GetVersionNumber()); |
| gSharedInstance.isFirstSessionAfterUpgrade = |
| ![lastRanVersion isEqualToString:currentVersion]; |
| |
| // This key is no longer being used so we remove it here, |
| // but this should be cleaned-up in many milestones. |
| // TODO(crbug.com/1295763): Remove this line. |
| [[NSUserDefaults standardUserDefaults] |
| removeObjectForKey:kPreviousSessionInfoMultiWindowEnabled]; |
| |
| gSharedInstance.connectedSceneSessionsIDs = [NSMutableSet |
| setWithArray:[defaults |
| stringArrayForKey: |
| previous_session_info_constants:: |
| kPreviousSessionInfoConnectedSceneSessionIDs]]; |
| |
| NSTimeInterval lastSystemStartTime = |
| [defaults doubleForKey:previous_session_info_constants::kOSStartTime]; |
| |
| gSharedInstance.OSRestartedAfterPreviousSession = |
| // Allow 5 seconds variation to account for rounding error. |
| (abs(lastSystemStartTime - GetOSStartTimeIntervalSinceReferenceDate()) > |
| 5) && |
| // Ensure that previous session actually exists. |
| lastSystemStartTime; |
| |
| NSString* lastRanLanguage = [defaults stringForKey:kLastRanLanguage]; |
| NSString* currentLanguage = [[NSLocale preferredLanguages] objectAtIndex:0]; |
| gSharedInstance.isFirstSessionAfterLanguageChange = |
| ![lastRanLanguage isEqualToString:currentLanguage]; |
| |
| gSharedInstance.terminatedDuringSessionRestoration = |
| [defaults boolForKey:previous_session_info_constants:: |
| kPreviousSessionInfoRestoringSession]; |
| |
| gSharedInstance.reportParameters = |
| [defaults dictionaryForKey:previous_session_info_constants:: |
| kPreviousSessionInfoParams]; |
| |
| gSharedInstance.memoryFootprint = |
| [defaults integerForKey:previous_session_info_constants:: |
| kPreviousSessionInfoMemoryFootprint]; |
| |
| gSharedInstance.applicationWillTerminateWasReceived = |
| [defaults boolForKey:kPreviousSessionInfoAppWillTerminate]; |
| gSharedInstance.tabCount = |
| [defaults integerForKey:previous_session_info_constants:: |
| kPreviousSessionInfoTabCount]; |
| gSharedInstance.OTRTabCount = |
| [defaults integerForKey:previous_session_info_constants:: |
| kPreviousSessionInfoOTRTabCount]; |
| } |
| return gSharedInstance; |
| } |
| |
| + (void)resetSharedInstanceForTesting { |
| gSharedInstance = nil; |
| } |
| |
| - (void)beginRecordingCurrentSession { |
| if (self.didBeginRecordingCurrentSession) |
| return; |
| self.didBeginRecordingCurrentSession = YES; |
| NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| |
| // Set the current Chrome version. |
| NSString* currentVersion = |
| base::SysUTF8ToNSString(version_info::GetVersionNumber()); |
| [defaults setObject:currentVersion forKey:kLastRanVersion]; |
| |
| // Set the current OS start time. |
| [defaults setDouble:GetOSStartTimeIntervalSinceReferenceDate() |
| forKey:previous_session_info_constants::kOSStartTime]; |
| |
| // Set the current OS version. |
| NSString* currentOSVersion = |
| base::SysUTF8ToNSString(base::SysInfo::OperatingSystemVersion()); |
| [defaults setObject:currentOSVersion forKey:kPreviousSessionInfoOSVersion]; |
| |
| // Set the current language. |
| NSString* currentLanguage = [[NSLocale preferredLanguages] objectAtIndex:0]; |
| [defaults setObject:currentLanguage forKey:kLastRanLanguage]; |
| |
| // Clear the memory warning flag. |
| [defaults |
| removeObjectForKey:previous_session_info_constants:: |
| kDidSeeMemoryWarningShortlyBeforeTerminating]; |
| |
| [[NSUserDefaults standardUserDefaults] |
| removeObjectForKey:kPreviousSessionInfoAppWillTerminate]; |
| [[NSUserDefaults standardUserDefaults] |
| removeObjectForKey:kPreviousSessionInfoLowPowerMode]; |
| |
| [defaults setObject:[NSDate date] forKey:kPreviousSessionInfoStartTime]; |
| |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(updateApplicationState) |
| name:UIApplicationDidEnterBackgroundNotification |
| object:nil]; |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(updateApplicationState) |
| name:UIApplicationWillEnterForegroundNotification |
| 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] |
| addObserver:self |
| selector:@selector(updateApplicationState) |
| name:UIApplicationDidBecomeActiveNotification |
| object:nil]; |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(updateApplicationState) |
| name:UIApplicationWillResignActiveNotification |
| object:nil]; |
| |
| [UIDevice currentDevice].batteryMonitoringEnabled = YES; |
| |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(updateStoredBatteryLevel) |
| name:UIDeviceBatteryLevelDidChangeNotification |
| object:nil]; |
| |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(updateStoredBatteryState) |
| name:UIDeviceBatteryStateDidChangeNotification |
| object:nil]; |
| |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(updateStoredThermalState) |
| name:NSProcessInfoThermalStateDidChangeNotification |
| object:nil]; |
| |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(applicationWillTerminate) |
| name:UIApplicationWillTerminateNotification |
| object:nil]; |
| |
| [self resumeRecordingCurrentSession]; |
| } |
| |
| - (void)startRecordingMemoryFootprintWithInterval:(base::TimeDelta)interval { |
| _memoryFootprintUpdateTimer.Start(FROM_HERE, interval, base::BindRepeating(^{ |
| [self updateMemoryFootprint]; |
| })); |
| } |
| |
| - (void)stopRecordingMemoryFootprint { |
| _memoryFootprintUpdateTimer.Stop(); |
| } |
| - (void)resumeRecordingCurrentSession { |
| if (self.recordingCurrentSession) |
| return; |
| self.recordingCurrentSession = YES; |
| [self updateApplicationState]; |
| [self updateStoredBatteryLevel]; |
| [self updateStoredBatteryState]; |
| [self updateStoredThermalState]; |
| // Save critical state information for crash detection. |
| [[NSUserDefaults standardUserDefaults] synchronize]; |
| } |
| |
| - (void)pauseRecordingCurrentSession { |
| self.recordingCurrentSession = NO; |
| } |
| |
| - (void)protectedDataWillBecomeUnavailable { |
| [self pauseRecordingCurrentSession]; |
| } |
| |
| - (void)protectedDataDidBecomeAvailable { |
| [self resumeRecordingCurrentSession]; |
| } |
| |
| - (UIApplicationState*)applicationState { |
| return _applicationState.get(); |
| } |
| |
| - (void)updateAvailableDeviceStorage:(NSInteger)availableStorage { |
| if (!self.recordingCurrentSession) |
| return; |
| |
| [[NSUserDefaults standardUserDefaults] |
| setInteger:availableStorage |
| forKey:kPreviousSessionInfoAvailableDeviceStorage]; |
| |
| [self updateSessionEndTime]; |
| } |
| |
| - (void)updateSessionEndTime { |
| if (!self.recordingCurrentSession) |
| return; |
| [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] |
| forKey:kPreviousSessionInfoEndTime]; |
| } |
| |
| - (void)updateStoredBatteryLevel { |
| if (!self.recordingCurrentSession) |
| return; |
| [[NSUserDefaults standardUserDefaults] |
| setFloat:[UIDevice currentDevice].batteryLevel |
| forKey:kPreviousSessionInfoBatteryLevel]; |
| [self updateSessionEndTime]; |
| } |
| |
| - (void)updateApplicationState { |
| if (!self.recordingCurrentSession) |
| return; |
| [[NSUserDefaults standardUserDefaults] |
| setInteger:UIApplication.sharedApplication.applicationState |
| forKey:previous_session_info_constants:: |
| kPreviousSessionInfoApplicationState]; |
| |
| [self updateSessionEndTime]; |
| } |
| |
| - (void)updateStoredBatteryState { |
| if (!self.recordingCurrentSession) |
| return; |
| UIDevice* device = [UIDevice currentDevice]; |
| // Translate value to an app defined enum as the system could change the |
| // underlying values of UIDeviceBatteryState between OS versions. |
| DeviceBatteryState batteryState = |
| GetBatteryStateFromUIDeviceBatteryState(device.batteryState); |
| NSInteger batteryStateValue = |
| static_cast<std::underlying_type<DeviceBatteryState>::type>(batteryState); |
| |
| [[NSUserDefaults standardUserDefaults] |
| setInteger:batteryStateValue |
| forKey:kPreviousSessionInfoBatteryState]; |
| |
| [self updateSessionEndTime]; |
| } |
| |
| - (void)updateStoredThermalState { |
| if (!self.recordingCurrentSession) |
| return; |
| NSProcessInfo* processInfo = [NSProcessInfo processInfo]; |
| // Translate value to an app defined enum as the system could change the |
| // underlying values of NSProcessInfoThermalState between OS versions. |
| DeviceThermalState thermalState = |
| GetThermalStateFromNSProcessInfoThermalState([processInfo thermalState]); |
| NSInteger thermalStateValue = |
| static_cast<std::underlying_type<DeviceThermalState>::type>(thermalState); |
| |
| [[NSUserDefaults standardUserDefaults] |
| setInteger:thermalStateValue |
| forKey:kPreviousSessionInfoThermalState]; |
| |
| [self updateSessionEndTime]; |
| } |
| |
| - (void)applicationWillTerminate { |
| [NSUserDefaults.standardUserDefaults |
| setBool:YES |
| forKey:kPreviousSessionInfoAppWillTerminate]; |
| [NSUserDefaults.standardUserDefaults synchronize]; |
| } |
| |
| - (void)updateMemoryFootprint { |
| if (!self.recordingCurrentSession) |
| return; |
| |
| task_vm_info taskInfoData; |
| mach_msg_type_number_t count = sizeof(task_vm_info) / sizeof(natural_t); |
| kern_return_t result = |
| task_info(mach_task_self(), TASK_VM_INFO, |
| reinterpret_cast<task_info_t>(&taskInfoData), &count); |
| if (result == KERN_SUCCESS) { |
| [NSUserDefaults.standardUserDefaults |
| setInteger:taskInfoData.phys_footprint |
| forKey:previous_session_info_constants:: |
| kPreviousSessionInfoMemoryFootprint]; |
| [self updateSessionEndTime]; |
| } |
| } |
| |
| - (void)setMemoryWarningFlag { |
| if (!self.didBeginRecordingCurrentSession) |
| return; |
| |
| NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| [defaults setBool:YES |
| forKey:previous_session_info_constants:: |
| kDidSeeMemoryWarningShortlyBeforeTerminating]; |
| // Save critical state information for crash detection. |
| [defaults synchronize]; |
| } |
| |
| - (void)resetMemoryWarningFlag { |
| if (!self.didBeginRecordingCurrentSession) |
| return; |
| |
| NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| [defaults |
| removeObjectForKey:previous_session_info_constants:: |
| kDidSeeMemoryWarningShortlyBeforeTerminating]; |
| // Save critical state information for crash detection. |
| [defaults synchronize]; |
| } |
| |
| - (void)synchronizeSceneSessionIDs { |
| NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| [defaults setObject:[self.connectedSceneSessionsIDs allObjects] |
| forKey:previous_session_info_constants:: |
| kPreviousSessionInfoConnectedSceneSessionIDs]; |
| [defaults synchronize]; |
| } |
| |
| - (void)addSceneSessionID:(NSString*)sessionID { |
| [self.connectedSceneSessionsIDs addObject:sessionID]; |
| [self synchronizeSceneSessionIDs]; |
| } |
| |
| - (void)removeSceneSessionID:(NSString*)sessionID { |
| [self.connectedSceneSessionsIDs removeObject:sessionID]; |
| [self synchronizeSceneSessionIDs]; |
| } |
| |
| - (void)resetConnectedSceneSessionIDs { |
| self.connectedSceneSessionsIDs = [[NSMutableSet alloc] init]; |
| [self synchronizeSceneSessionIDs]; |
| } |
| |
| - (base::ScopedClosureRunner)startSessionRestoration { |
| if (self.numberOfSessionsBeingRestored == 0) { |
| [NSUserDefaults.standardUserDefaults |
| setBool:YES |
| forKey:previous_session_info_constants:: |
| kPreviousSessionInfoRestoringSession]; |
| // Save critical state information for crash detection. |
| [NSUserDefaults.standardUserDefaults synchronize]; |
| } |
| ++self.numberOfSessionsBeingRestored; |
| |
| return base::ScopedClosureRunner(base::BindOnce(^{ |
| --self.numberOfSessionsBeingRestored; |
| if (self.numberOfSessionsBeingRestored == 0) { |
| [self resetSessionRestorationFlag]; |
| } |
| })); |
| } |
| |
| - (void)resetSessionRestorationFlag { |
| gSharedInstance.terminatedDuringSessionRestoration = NO; |
| [NSUserDefaults.standardUserDefaults |
| removeObjectForKey:previous_session_info_constants:: |
| kPreviousSessionInfoRestoringSession]; |
| // Save critical state information for crash detection. |
| [NSUserDefaults.standardUserDefaults synchronize]; |
| } |
| |
| - (void)updateCurrentSessionTabCount:(NSInteger)count { |
| [NSUserDefaults.standardUserDefaults |
| setInteger:count |
| forKey:previous_session_info_constants::kPreviousSessionInfoTabCount]; |
| [NSUserDefaults.standardUserDefaults synchronize]; |
| } |
| |
| - (void)updateCurrentSessionOTRTabCount:(NSInteger)count { |
| [NSUserDefaults.standardUserDefaults |
| setInteger:count |
| forKey:previous_session_info_constants:: |
| kPreviousSessionInfoOTRTabCount]; |
| [NSUserDefaults.standardUserDefaults synchronize]; |
| } |
| |
| - (void)setReportParameterValue:(NSString*)value forKey:(NSString*)key { |
| NSMutableDictionary* params = [[NSUserDefaults.standardUserDefaults |
| dictionaryForKey:previous_session_info_constants:: |
| kPreviousSessionInfoParams] mutableCopy]; |
| if (!params) { |
| params = [NSMutableDictionary dictionaryWithCapacity:1]; |
| } |
| params[key] = value; |
| [NSUserDefaults.standardUserDefaults |
| setObject:params |
| forKey:previous_session_info_constants::kPreviousSessionInfoParams]; |
| [NSUserDefaults.standardUserDefaults synchronize]; |
| } |
| |
| - (void)setReportParameterURL:(const GURL&)URL forKey:(NSString*)key { |
| // Store only URL origin (not whole URL spec) as requested by Privacy Team. |
| [self |
| setReportParameterValue:base::SysUTF8ToNSString( |
| URL.DeprecatedGetOriginAsURL().spec().c_str()) |
| forKey:key]; |
| } |
| |
| - (void)removeReportParameterForKey:(NSString*)key { |
| NSMutableDictionary* URLs = [[NSUserDefaults.standardUserDefaults |
| dictionaryForKey:previous_session_info_constants:: |
| kPreviousSessionInfoParams] mutableCopy]; |
| if (URLs) { |
| URLs[key] = nil; |
| if (URLs.count == 0) { |
| URLs = nil; |
| } |
| [NSUserDefaults.standardUserDefaults |
| setObject:URLs |
| forKey:previous_session_info_constants::kPreviousSessionInfoParams]; |
| [NSUserDefaults.standardUserDefaults synchronize]; |
| } |
| } |
| |
| @end |