diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-12-13 10:19:43 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-12-13 14:42:27 +0100 |
| commit | 00a0ec2adcfdd7c15c25f0a1bfeb9554d85ba17a (patch) | |
| tree | 30e0b33ed4b47c6d040e9a006da984a1fb663dd4 /ios | |
| parent | 800c01bf3d521f23b919e7d5bb0c0a2cf386ec01 (diff) | |
| download | mullvadvpn-00a0ec2adcfdd7c15c25f0a1bfeb9554d85ba17a.tar.xz mullvadvpn-00a0ec2adcfdd7c15c25f0a1bfeb9554d85ba17a.zip | |
Periodically update device data while capping it at 1 update per minute
Diffstat (limited to 'ios')
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 4 | ||||
| -rw-r--r-- | ios/MullvadVPN/AccountDataThrottling.swift | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/DeviceDataThrottling.swift | 55 | ||||
| -rw-r--r-- | ios/MullvadVPN/SceneDelegate.swift | 38 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/TunnelManager.swift | 12 |
5 files changed, 91 insertions, 20 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index a4aba1db17..f37fd833ba 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -85,6 +85,7 @@ 580F8B8628197958002E0998 /* DNSSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8528197958002E0998 /* DNSSettings.swift */; }; 580F8B872819795C002E0998 /* DNSSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8528197958002E0998 /* DNSSettings.swift */; }; 5811DE50239014550011EB53 /* NEVPNStatus+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5811DE4F239014550011EB53 /* NEVPNStatus+Debug.swift */; }; + 58138E61294871C600684F0C /* DeviceDataThrottling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58138E60294871C600684F0C /* DeviceDataThrottling.swift */; }; 5818139F28E09BD8002817DE /* libOperations.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58E5126528DDF04200B0BCDE /* libOperations.a */; }; 581813A128E09DBB002817DE /* NoCancelledDependenciesCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581813A028E09DBB002817DE /* NoCancelledDependenciesCondition.swift */; }; 581813A328E09DCD002817DE /* NoFailedDependenciesCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581813A228E09DCD002817DE /* NoFailedDependenciesCondition.swift */; }; @@ -598,6 +599,7 @@ 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsV2.swift; sourceTree = "<group>"; }; 580F8B8528197958002E0998 /* DNSSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSSettings.swift; sourceTree = "<group>"; }; 5811DE4F239014550011EB53 /* NEVPNStatus+Debug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NEVPNStatus+Debug.swift"; sourceTree = "<group>"; }; + 58138E60294871C600684F0C /* DeviceDataThrottling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceDataThrottling.swift; sourceTree = "<group>"; }; 581813A028E09DBB002817DE /* NoCancelledDependenciesCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoCancelledDependenciesCondition.swift; sourceTree = "<group>"; }; 581813A228E09DCD002817DE /* NoFailedDependenciesCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoFailedDependenciesCondition.swift; sourceTree = "<group>"; }; 581813A428E09DE2002817DE /* BlockCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockCondition.swift; sourceTree = "<group>"; }; @@ -1327,6 +1329,7 @@ 06AC114028F841390037AF9A /* AddressCacheTracker.swift */, 5896CEF126972DEB00B0FAE8 /* AccountContentView.swift */, 587988C628A2A01F00E3DF54 /* AccountDataThrottling.swift */, + 58138E60294871C600684F0C /* DeviceDataThrottling.swift */, 58C3A4B122456F1A00340BDB /* AccountInputGroupView.swift */, 58CCA01D2242787B004F3011 /* AccountTextField.swift */, 582AE30F2440A6CA00E6733A /* AccountTokenInput.swift */, @@ -2250,6 +2253,7 @@ 58F2E146276A2C9900A79513 /* StopTunnelOperation.swift in Sources */, E1187ABC289BBB850024E748 /* OutOfTimeViewController.swift in Sources */, 58293FB125124117005D0BB5 /* CustomTextField.swift in Sources */, + 58138E61294871C600684F0C /* DeviceDataThrottling.swift in Sources */, 5878A279290954790096FC88 /* ConnectInteractor.swift in Sources */, 582AE3102440A6CA00E6733A /* AccountTokenInput.swift in Sources */, 5820EDAB288FF0D2006BF4E4 /* DeviceRowView.swift in Sources */, diff --git a/ios/MullvadVPN/AccountDataThrottling.swift b/ios/MullvadVPN/AccountDataThrottling.swift index f6093beeb2..3f8ae0daf4 100644 --- a/ios/MullvadVPN/AccountDataThrottling.swift +++ b/ios/MullvadVPN/AccountDataThrottling.swift @@ -66,7 +66,7 @@ struct AccountDataThrottling { switch comparisonResult { case .orderedAscending, .orderedSame: - lastUpdate = Date() + lastUpdate = now tunnelManager.updateAccountData() case .orderedDescending: diff --git a/ios/MullvadVPN/DeviceDataThrottling.swift b/ios/MullvadVPN/DeviceDataThrottling.swift new file mode 100644 index 0000000000..cb30b130ff --- /dev/null +++ b/ios/MullvadVPN/DeviceDataThrottling.swift @@ -0,0 +1,55 @@ +// +// DeviceDataThrottling.swift +// MullvadVPN +// +// Created by pronebird on 13/12/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +/// Struct used for throttling UI calls to update device data via tunnel manager. +struct DeviceDataThrottling { + /// Default cooldown interval between requests. + private static let defaultWaitInterval: TimeInterval = 60 + + let tunnelManager: TunnelManager + private(set) var lastUpdate: Date? + + init(tunnelManager: TunnelManager) { + self.tunnelManager = tunnelManager + } + + mutating func requestUpdate(forceUpdate: Bool) { + guard tunnelManager.deviceState.isLoggedIn else { + return + } + + let now = Date() + + guard !forceUpdate else { + startUpdate(now: now) + return + } + + let nextUpdateAfter = lastUpdate?.addingTimeInterval(Self.defaultWaitInterval) + let comparisonResult = nextUpdateAfter?.compare(now) ?? .orderedAscending + + switch comparisonResult { + case .orderedAscending, .orderedSame: + startUpdate(now: now) + + case .orderedDescending: + break + } + } + + mutating func reset() { + lastUpdate = nil + } + + private mutating func startUpdate(now: Date) { + lastUpdate = now + tunnelManager.updateDeviceData() + } +} diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift index 26b29c3805..1f3838b2ae 100644 --- a/ios/MullvadVPN/SceneDelegate.swift +++ b/ios/MullvadVPN/SceneDelegate.swift @@ -38,7 +38,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe private var connectController: ConnectViewController? private weak var settingsNavController: SettingsNavigationController? private var lastLoginAction: LoginAction? - private lazy var accountDataThrottling = AccountDataThrottling(tunnelManager: tunnelManager) + + private var accountDataThrottling: AccountDataThrottling? + private var deviceDataThrottling: DeviceDataThrottling? private var outOfTimeTimer: Timer? @@ -92,6 +94,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe isSceneConfigured = true + accountDataThrottling = AccountDataThrottling(tunnelManager: tunnelManager) + deviceDataThrottling = DeviceDataThrottling(tunnelManager: tunnelManager) + rootContainer.delegate = self window?.rootViewController = rootContainer @@ -107,7 +112,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe relayCacheTracker.addObserver(self) NotificationManager.shared.delegate = self - accountDataThrottling.requestUpdate(condition: .always) + refreshDeviceAndAccountData(forceUpdate: true) } private func setShowsPrivacyOverlay(_ showOverlay: Bool) { @@ -120,6 +125,21 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe } } + private func refreshDeviceAndAccountData(forceUpdate: Bool) { + let condition: AccountDataThrottling.Condition = + settingsNavController == nil && !forceUpdate + ? .whenCloseToExpiryAndBeyond + : .always + + accountDataThrottling?.requestUpdate(condition: condition) + deviceDataThrottling?.requestUpdate(forceUpdate: forceUpdate) + } + + private func resetDeviceAndAccountDataThrottling() { + accountDataThrottling?.reset() + deviceDataThrottling?.reset() + } + // MARK: - UIWindowSceneDelegate func scene( @@ -148,11 +168,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe func sceneDidBecomeActive(_ scene: UIScene) { if isSceneConfigured { - accountDataThrottling.requestUpdate( - condition: settingsNavController == nil - ? .whenCloseToExpiryAndBeyond - : .always - ) + refreshDeviceAndAccountData(forceUpdate: false) } setShowsPrivacyOverlay(false) @@ -190,7 +206,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe let navController = makeSettingsNavigationController(route: route) // Refresh account data each time user opens settings - accountDataThrottling.requestUpdate(condition: .always) + refreshDeviceAndAccountData(forceUpdate: true) // On iPad the login controller can be presented modally above the root container. // in that case we have to use the presented controller to present the next modal. @@ -734,7 +750,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe ) { switch route { case .root, .account: - accountDataThrottling.requestUpdate(condition: .always) + refreshDeviceAndAccountData(forceUpdate: false) default: break @@ -903,10 +919,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe } case .loggedOut: - accountDataThrottling.reset() + resetDeviceAndAccountDataThrottling() case .revoked: - accountDataThrottling.reset() + resetDeviceAndAccountDataThrottling() showRevokedDeviceView() } } diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift index 5dd4711ed1..c117dee394 100644 --- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift +++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift @@ -428,10 +428,7 @@ final class TunnelManager: StorePaymentObserver { operationQueue.addOperation(operation) } - func updateDeviceData(_ completionHandler: @escaping (OperationCompletion< - StoredDeviceData, - Error - >) -> Void) -> Cancellable { + func updateDeviceData(_ completionHandler: ((Error?) -> Void)? = nil) { let operation = UpdateDeviceDataOperation( dispatchQueue: internalQueue, interactor: TunnelInteractorProxy(self), @@ -442,11 +439,12 @@ final class TunnelManager: StorePaymentObserver { operation.completionHandler = { [weak self] completion in guard let self = self else { return } - if let error = completion.error { + let error = completion.error + if let error = error { self.checkIfDeviceRevoked(error) } - completionHandler(completion) + completionHandler?(error) } operation.addObserver( @@ -462,8 +460,6 @@ final class TunnelManager: StorePaymentObserver { ) operationQueue.addOperation(operation) - - return operation } func rotatePrivateKey( |
