From 89a38be9d286ed05c2257ee82edeb38e2a085430 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 1 May 2024 14:56:13 +0200 Subject: [PATCH 1/3] Count VPN controller cancellations (#2720) Task/Issue URL: https://app.asana.com/0/1199230911884351/1207193126056882/f ## Description Stop counting when the user disables the VPN configuration creation as a controller start failure. --- .../NetworkProtectionPixelEvent.swift | 6 +++ .../NetworkProtectionTunnelController.swift | 54 +++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionPixelEvent.swift b/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionPixelEvent.swift index 50a2b96444..e9b9f4c847 100644 --- a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionPixelEvent.swift +++ b/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionPixelEvent.swift @@ -28,6 +28,7 @@ enum NetworkProtectionPixelEvent: PixelKitEventV2 { case networkProtectionControllerStartAttempt case networkProtectionControllerStartSuccess + case networkProtectionControllerStartCancelled case networkProtectionControllerStartFailure(_ error: Error) case networkProtectionTunnelStartAttempt @@ -122,6 +123,9 @@ enum NetworkProtectionPixelEvent: PixelKitEventV2 { case .networkProtectionControllerStartSuccess: return "netp_controller_start_success" + case .networkProtectionControllerStartCancelled: + return "netp_controller_start_cancelled" + case .networkProtectionControllerStartFailure: return "netp_controller_start_failure" @@ -344,6 +348,7 @@ enum NetworkProtectionPixelEvent: PixelKitEventV2 { .networkProtectionNewUser, .networkProtectionControllerStartAttempt, .networkProtectionControllerStartSuccess, + .networkProtectionControllerStartCancelled, .networkProtectionControllerStartFailure, .networkProtectionTunnelStartAttempt, .networkProtectionTunnelStartSuccess, @@ -415,6 +420,7 @@ enum NetworkProtectionPixelEvent: PixelKitEventV2 { .networkProtectionNewUser, .networkProtectionControllerStartAttempt, .networkProtectionControllerStartSuccess, + .networkProtectionControllerStartCancelled, .networkProtectionTunnelStartAttempt, .networkProtectionTunnelStartSuccess, .networkProtectionTunnelStopAttempt, diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index b1bebcadbb..a9051ab6a2 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -448,14 +448,18 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr // MARK: - Starting & Stopping the VPN - enum StartError: LocalizedError { + enum StartError: LocalizedError, CustomNSError { + case cancelled case noAuthToken case connectionStatusInvalid case connectionAlreadyStarted case simulateControllerFailureError + case startTunnelFailure(_ error: Error) var errorDescription: String? { switch self { + case .cancelled: + return nil case .noAuthToken: return "You need a subscription to start the VPN" case .connectionAlreadyStarted: @@ -473,6 +477,34 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr #endif case .simulateControllerFailureError: return "Simulated a controller error as requested" + case .startTunnelFailure(let error): + return error.localizedDescription + } + } + + var errorCode: Int { + switch self { + case .cancelled: return 0 + // MARK: Setup errors + case .noAuthToken: return 1 + case .connectionStatusInvalid: return 2 + case .connectionAlreadyStarted: return 3 + case .simulateControllerFailureError: return 4 + // MARK: Actual connection attempt issues + case .startTunnelFailure: return 100 + } + } + + var errorUserInfo: [String: Any] { + switch self { + case .cancelled, + .noAuthToken, + .connectionStatusInvalid, + .connectionAlreadyStarted, + .simulateControllerFailureError: + return [:] + case .startTunnelFailure(let error): + return [NSUnderlyingErrorKey: error] } } } @@ -502,6 +534,8 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr } catch { if case NEVPNError.configurationReadWriteFailed = error { onboardingStatusRawValue = OnboardingStatus.isOnboarding(step: .userNeedsToAllowVPNConfiguration).rawValue + + throw StartError.cancelled } throw error @@ -528,9 +562,15 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr } catch { VPNOperationErrorRecorder().recordControllerStartFailure(error) - PixelKit.fire( - NetworkProtectionPixelEvent.networkProtectionControllerStartFailure(error), frequency: .dailyAndCount, includeAppVersionParameter: true - ) + if case StartError.cancelled = error { + PixelKit.fire( + NetworkProtectionPixelEvent.networkProtectionControllerStartCancelled, frequency: .dailyAndCount, includeAppVersionParameter: true + ) + } else { + PixelKit.fire( + NetworkProtectionPixelEvent.networkProtectionControllerStartFailure(error), frequency: .dailyAndCount, includeAppVersionParameter: true + ) + } await stop() @@ -577,7 +617,11 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr throw StartError.simulateControllerFailureError } - try tunnelManager.connection.startVPNTunnel(options: options) + do { + try tunnelManager.connection.startVPNTunnel(options: options) + } catch { + throw StartError.startTunnelFailure(error) + } PixelKit.fire( NetworkProtectionPixelEvent.networkProtectionNewUser, From 398f9b86b9b250fdcc26725a4ec0158816e697f8 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 1 May 2024 22:46:30 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Fixes=20an=20issue=20that's=20causing=20the?= =?UTF-8?q?=20Allow=20VPN=20to=20show=20up=20twice=20when=20dis=E2=80=A6?= =?UTF-8?q?=20(#2728)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task/Issue URL: https://app.asana.com/0/1199230911884351/1207210448609392/f Description We no longer ask twice to allow the VPN configuration if the user decides to not allow it. --- .../BothAppTargets/NetworkProtectionTunnelController.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index a9051ab6a2..ed20ffef1d 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -572,7 +572,9 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr ) } - await stop() + if await isConnected { + await stop() + } // Always keep the first error message shown, as it's the more actionable one. if controllerErrorStore.lastErrorMessage == nil { From 8de8379f74d5d5f520536f1fe8270ebb4d998fac Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Thu, 2 May 2024 05:13:15 +0000 Subject: [PATCH 3/3] Bump version to 1.86.0 (181) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index ca1afd458a..e94261020d 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 180 +CURRENT_PROJECT_VERSION = 181