feat: mobile security prefs (#1496)

* feat: move mobile-specific security items to Web when rendered in WebView

* feat: better UI for biometrics section

* feat: move Multitasking Privacy section to WebView (mostly UI)

* feat: move Multitasking Privacy section to WebView (going to understand why in WebView multitasking privacy value is auto-changed after reopening the WebView)

* feat: store MultitaskingPrivacy value as "NonWrapped" so that it's the same both on mobile and WebView

* feat: open WebView correctly when "Storage Encryption" is disabled on mobile

* fix: remove unnecessary changes and comments

* chore: revert ios-related unneeded changes

* fix: let Android to correctly recognize the NativeMobileWeb environment when opening WebView on Android

* fix: correct styles for the selected state of Biometrics/Passcode options

* chore: code cleanup

* fix: store Multitasking/Screenshot Privacy in the `Default` storage value mode

* chore: remove comment

* fix: use application's method instead of directly updating Screenshot Privacy preference

* fix: remove unused variable

* fix: use methods from Application and MobileDeviceInterface in all places, remove duplicate code

* fix: hide Multitasking Privacy and Biometrics Lock in WebView

Co-authored-by: Aman Harwara
This commit is contained in:
Vardan Hakobyan
2022-09-14 13:07:10 +04:00
committed by GitHub
parent e73d187b65
commit d7aca2c13a
14 changed files with 324 additions and 92 deletions

View File

@@ -24,6 +24,11 @@ export enum ProtectionEvent {
UnprotectedSessionExpired = 'UnprotectedSessionExpired',
}
export enum MobileUnlockTiming {
Immediately = 'immediately',
OnQuit = 'on-quit',
}
export const ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction = 30
export enum UnprotectedAccessSecondsDuration {
@@ -63,6 +68,8 @@ export const ProtectionSessionDurations = [
*/
export class SNProtectionService extends AbstractService<ProtectionEvent> implements ProtectionsClientInterface {
private sessionExpiryTimeout = -1
private mobilePasscodeTiming: MobileUnlockTiming | undefined = MobileUnlockTiming.Immediately
private mobileBiometricsTiming: MobileUnlockTiming | undefined = MobileUnlockTiming.Immediately
constructor(
private protocolService: EncryptionService,
@@ -224,6 +231,68 @@ export class SNProtectionService extends AbstractService<ProtectionEvent> implem
})
}
getPasscodeTimingOptions() {
return [
{
title: 'Immediately',
key: MobileUnlockTiming.Immediately,
selected: this.mobilePasscodeTiming === MobileUnlockTiming.Immediately,
},
{
title: 'On Quit',
key: MobileUnlockTiming.OnQuit,
selected: this.mobilePasscodeTiming === MobileUnlockTiming.OnQuit,
},
]
}
getBiometricsTimingOptions() {
return [
{
title: 'Immediately',
key: MobileUnlockTiming.Immediately,
selected: this.mobileBiometricsTiming === MobileUnlockTiming.Immediately,
},
{
title: 'On Quit',
key: MobileUnlockTiming.OnQuit,
selected: this.mobileBiometricsTiming === MobileUnlockTiming.OnQuit,
},
]
}
private async getBiometricsTiming(): Promise<MobileUnlockTiming | undefined> {
return this.storageService.getValue<Promise<MobileUnlockTiming | undefined>>(
StorageKey.MobileBiometricsTiming,
StorageValueModes.Nonwrapped,
)
}
private async getPasscodeTiming(): Promise<MobileUnlockTiming | undefined> {
return this.storageService.getValue<Promise<MobileUnlockTiming | undefined>>(
StorageKey.MobilePasscodeTiming,
StorageValueModes.Nonwrapped,
)
}
async setBiometricsTiming(timing: MobileUnlockTiming) {
await this.storageService.setValue(StorageKey.MobileBiometricsTiming, timing, StorageValueModes.Nonwrapped)
this.mobileBiometricsTiming = timing
}
async setMobileScreenshotPrivacyEnabled(isEnabled: boolean) {
return this.storageService.setValue(StorageKey.MobileScreenshotPrivacyEnabled, isEnabled, StorageValueModes.Default)
}
async getMobileScreenshotPrivacyEnabled(): Promise<boolean | undefined> {
return this.storageService.getValue(StorageKey.MobileScreenshotPrivacyEnabled, StorageValueModes.Default)
}
async loadMobileUnlockTiming() {
this.mobilePasscodeTiming = await this.getPasscodeTiming()
this.mobileBiometricsTiming = await this.getBiometricsTiming()
}
private async validateOrRenewSession(
reason: ChallengeReason,
{ fallBackToAccountPassword = true, requireAccountPassword = false } = {},
@@ -270,7 +339,9 @@ export class SNProtectionService extends AbstractService<ProtectionEvent> implem
chosenSessionLength,
),
)
const response = await this.challengeService.promptForChallengeResponse(new Challenge(prompts, reason, true))
if (response) {
const length = response.values.find(
(value) => value.prompt.validation === ChallengeValidation.ProtectionSessionDuration,