diff --git a/DuckDuckGo/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtectionTunnelController.swift index 595b0afa13..77a09a12e1 100644 --- a/DuckDuckGo/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtectionTunnelController.swift @@ -31,6 +31,9 @@ final class NetworkProtectionTunnelController: TunnelController { private let debugFeatures = NetworkProtectionDebugFeatures() private let tokenStore = NetworkProtectionKeychainTokenStore() private let errorStore = NetworkProtectionTunnelErrorStore() + private let notificationCenter: NotificationCenter = .default + private var previousStatus: NEVPNStatus = .invalid + private var cancellables = Set() // MARK: - Starting & Stopping the VPN @@ -39,6 +42,10 @@ final class NetworkProtectionTunnelController: TunnelController { case simulateControllerFailureError } + init() { + subscribeToStatusChanges() + } + /// Starts the VPN connection used for Network Protection /// func start() async { @@ -142,12 +149,6 @@ final class NetworkProtectionTunnelController: TunnelController { Pixel.fire(pixel: .networkProtectionActivationRequestFailed, error: error) throw error } - - if !debugFeatures.alwaysOnDisabled { - Task { - try await enableOnDemand(tunnelManager: tunnelManager) - } - } } /// The actual storage for our tunnel manager. @@ -231,6 +232,35 @@ final class NetworkProtectionTunnelController: TunnelController { tunnelManager.onDemandRules = [NEOnDemandRuleConnect()] } + // MARK: - Observing Status Changes + + private func subscribeToStatusChanges() { + notificationCenter.publisher(for: .NEVPNStatusDidChange) + .sink(receiveValue: handleStatusChange(_:)) + .store(in: &cancellables) + } + + private func handleStatusChange(_ notification: Notification) { + guard !debugFeatures.alwaysOnDisabled, + let session = (notification.object as? NETunnelProviderSession), + session.status != previousStatus, + let manager = session.manager as? NETunnelProviderManager else { + return + } + + Task { @MainActor in + previousStatus = session.status + + switch session.status { + case .connected: + try await enableOnDemand(tunnelManager: manager) + default: + break + } + + } + } + // MARK: - On Demand @MainActor