From 43b75a1029e9bdf17f8897f09726822df5cf356a Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Mon, 18 Mar 2019 17:08:54 +0100 Subject: [PATCH] Add completion handler to intent dispatcher --- Passepartout-iOS/AppDelegate.swift | 2 +- .../Sources/Intents/IntentDispatcher.swift | 64 ++++++++++++------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/Passepartout-iOS/AppDelegate.swift b/Passepartout-iOS/AppDelegate.swift index 607e5792..7745165f 100644 --- a/Passepartout-iOS/AppDelegate.swift +++ b/Passepartout-iOS/AppDelegate.swift @@ -161,7 +161,7 @@ extension AppDelegate { return false } if #available(iOS 12, *) { - IntentDispatcher.handleInteraction(interaction) + IntentDispatcher.handleInteraction(interaction, completionHandler: nil) } return true } diff --git a/Passepartout/Sources/Intents/IntentDispatcher.swift b/Passepartout/Sources/Intents/IntentDispatcher.swift index 30becdaa..c050d0be 100644 --- a/Passepartout/Sources/Intents/IntentDispatcher.swift +++ b/Passepartout/Sources/Intents/IntentDispatcher.swift @@ -113,35 +113,37 @@ public class IntentDispatcher { // - public static func handleInteraction(_ interaction: INInteraction) { - handleIntent(interaction.intent, interaction: interaction) + public static func handleInteraction(_ interaction: INInteraction, completionHandler: ((Error?) -> Void)?) { + handleIntent(interaction.intent, interaction: interaction, completionHandler: completionHandler) } - public static func handleIntent(_ intent: INIntent, interaction: INInteraction?) { + public static func handleIntent(_ intent: INIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { if let custom = intent as? ConnectVPNIntent { - handleConnectVPN(custom, interaction: interaction) + handleConnectVPN(custom, interaction: interaction, completionHandler: completionHandler) } else if let custom = intent as? EnableVPNIntent { - handleEnableVPN(custom, interaction: interaction) + handleEnableVPN(custom, interaction: interaction, completionHandler: completionHandler) } else if let custom = intent as? DisableVPNIntent { - handleDisableVPN(custom, interaction: interaction) + handleDisableVPN(custom, interaction: interaction, completionHandler: completionHandler) } else if let custom = intent as? MoveToLocationIntent { - handleMoveToLocation(custom, interaction: interaction) + handleMoveToLocation(custom, interaction: interaction, completionHandler: completionHandler) } else if let _ = intent as? TrustCurrentNetworkIntent { - handleCurrentNetwork(trust: true, interaction: interaction) + handleCurrentNetwork(trust: true, interaction: interaction, completionHandler: completionHandler) } else if let _ = intent as? UntrustCurrentNetworkIntent { - handleCurrentNetwork(trust: false, interaction: interaction) + handleCurrentNetwork(trust: false, interaction: interaction, completionHandler: completionHandler) } else if let _ = intent as? TrustCellularNetworkIntent { - handleCellularNetwork(trust: true, interaction: interaction) + handleCellularNetwork(trust: true, interaction: interaction, completionHandler: completionHandler) } else if let _ = intent as? UntrustCellularNetworkIntent { - handleCellularNetwork(trust: false, interaction: interaction) + handleCellularNetwork(trust: false, interaction: interaction, completionHandler: completionHandler) } } - private static func handleConnectVPN(_ intent: ConnectVPNIntent, interaction: INInteraction?) { + public static func handleConnectVPN(_ intent: ConnectVPNIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { guard let contextValue = intent.context, let context = Context(rawValue: contextValue), let id = intent.profileId else { if let interactionIdentifier = interaction?.identifier { INInteraction.delete(with: [interactionIdentifier], completion: nil) } + // FIXME: error = missing data, programming error + completionHandler?(nil) return } let profileKey = ProfileKey(context, id) @@ -151,22 +153,29 @@ public class IntentDispatcher { let vpn = VPN.shared guard !(service.isActiveProfile(profileKey) && (vpn.status == .connected)) else { log.info("Profile is already active and connected") + completionHandler?(nil) return } guard let profile = service.profile(withContext: context, id: id) else { + // FIXME: error = no profile + completionHandler?(nil) return } service.activateProfile(profile) - refreshVPN(service: service, doReconnect: true) + refreshVPN(service: service, doReconnect: true, completionHandler: completionHandler) } - private static func handleMoveToLocation(_ intent: MoveToLocationIntent, interaction: INInteraction?) { + public static func handleMoveToLocation(_ intent: MoveToLocationIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { guard let providerId = intent.providerId, let poolId = intent.poolId else { + // FIXME: error = no provider/pool + completionHandler?(nil) return } let service = TransientStore.shared.service guard let providerProfile = service.profile(withContext: .provider, id: providerId) as? ProviderConnectionProfile else { + // FIXME: error = no provider + completionHandler?(nil) return } log.info("Move to provider location: \(providerId) @ [\(poolId)]") @@ -174,29 +183,33 @@ public class IntentDispatcher { let vpn = VPN.shared guard !(service.isActiveProfile(providerProfile) && (providerProfile.poolId == poolId) && (vpn.status == .connected)) else { log.info("Profile is already active and connected to \(poolId)") + completionHandler?(nil) return } providerProfile.poolId = poolId service.activateProfile(providerProfile) - refreshVPN(service: service, doReconnect: true) + refreshVPN(service: service, doReconnect: true, completionHandler: completionHandler) } - private static func handleEnableVPN(_ intent: EnableVPNIntent, interaction: INInteraction?) { + public static func handleEnableVPN(_ intent: EnableVPNIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { let service = TransientStore.shared.service log.info("Enabling VPN...") - refreshVPN(service: service, doReconnect: true) + refreshVPN(service: service, doReconnect: true, completionHandler: completionHandler) } - private static func handleDisableVPN(_ intent: DisableVPNIntent, interaction: INInteraction?) { + public static func handleDisableVPN(_ intent: DisableVPNIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { log.info("Disabling VPN...") VPN.shared.disconnect { (error) in notifyServiceUpdate() + completionHandler?(error) } } - private static func handleCurrentNetwork(trust: Bool, interaction: INInteraction?) { + public static func handleCurrentNetwork(trust: Bool, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { guard let currentWifi = Utils.currentWifiNetworkName() else { + // FIXME: error = not connected to wifi + completionHandler?(nil) return } let service = TransientStore.shared.service @@ -204,11 +217,13 @@ public class IntentDispatcher { TransientStore.shared.serialize(withProfiles: false) log.info("\(trust ? "Trusted" : "Untrusted") Wi-Fi: \(currentWifi)") - refreshVPN(service: service, doReconnect: false) + refreshVPN(service: service, doReconnect: false, completionHandler: completionHandler) } - private static func handleCellularNetwork(trust: Bool, interaction: INInteraction?) { + public static func handleCellularNetwork(trust: Bool, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { guard Utils.hasCellularData() else { + // FIXME: error = has no mobile data + completionHandler?(nil) return } let service = TransientStore.shared.service @@ -216,16 +231,17 @@ public class IntentDispatcher { TransientStore.shared.serialize(withProfiles: false) log.info("\(trust ? "Trusted" : "Untrusted") cellular network") - refreshVPN(service: service, doReconnect: false) + refreshVPN(service: service, doReconnect: false, completionHandler: completionHandler) } - private static func refreshVPN(service: ConnectionService, doReconnect: Bool) { + private static func refreshVPN(service: ConnectionService, doReconnect: Bool, completionHandler: ((Error?) -> Void)?) { let configuration: VPNConfiguration do { configuration = try service.vpnConfiguration() } catch let e { log.error("Unable to build VPN configuration: \(e)") notifyServiceUpdate() + completionHandler?(e) return } @@ -234,11 +250,13 @@ public class IntentDispatcher { log.info("Reconnecting VPN: \(configuration)") vpn.reconnect(configuration: configuration) { (error) in notifyServiceUpdate() + completionHandler?(error) } } else { log.info("Reinstalling VPN: \(configuration)") vpn.install(configuration: configuration) { (error) in notifyServiceUpdate() + completionHandler?(error) } } }