diff options
author | Roopesh Chander <roop@roopc.net> | 2019-04-30 15:38:38 +0530 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-25 13:24:01 +0200 |
commit | f852b6f91931fa545968ee38c4b43e1233a6ac43 (patch) | |
tree | abfc7e701be7ac4c9433b5099b61f13d0e62a564 /WireGuard/WireGuard | |
parent | macOS: Workaround for unresponsive main menu when launched from Xcode (diff) | |
download | wireguard-apple-f852b6f91931fa545968ee38c4b43e1233a6ac43.tar.xz wireguard-apple-f852b6f91931fa545968ee38c4b43e1233a6ac43.zip |
iOS: Keep track of most-recently-activated tunnels
Signed-off-by: Roopesh Chander <roop@roopc.net>
Diffstat (limited to 'WireGuard/WireGuard')
-rw-r--r-- | WireGuard/WireGuard/Tunnel/TunnelsManager.swift | 19 | ||||
-rw-r--r-- | WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift | 72 |
2 files changed, 90 insertions, 1 deletions
diff --git a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift index edf7690..460a9f6 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift @@ -46,7 +46,11 @@ class TunnelsManager { var tunnelManagers = managers ?? [] var refs: Set<Data> = [] + var tunnelNames: Set<String> = [] for (index, tunnelManager) in tunnelManagers.enumerated().reversed() { + if let tunnelName = tunnelManager.localizedDescription { + tunnelNames.insert(tunnelName) + } guard let proto = tunnelManager.protocolConfiguration as? NETunnelProviderProtocol else { continue } if proto.migrateConfigurationIfNeeded(called: tunnelManager.localizedDescription ?? "unknown") { tunnelManager.saveToPreferences { _ in } @@ -66,6 +70,7 @@ class TunnelsManager { } } Keychain.deleteReferences(except: refs) + RecentTunnelsTracker.cleanupTunnels(except: tunnelNames) completionHandler(.success(TunnelsManager(tunnelProviders: tunnelManagers))) } #endif @@ -188,7 +193,8 @@ class TunnelsManager { } let tunnelProviderManager = tunnel.tunnelProvider - let isNameChanged = tunnelName != tunnelProviderManager.localizedDescription + let oldName = tunnelProviderManager.localizedDescription ?? "" + let isNameChanged = tunnelName != oldName if isNameChanged { guard !tunnels.contains(where: { $0.name == tunnelName }) else { completionHandler(TunnelsManagerError.tunnelAlreadyExistsWithThatName) @@ -220,6 +226,9 @@ class TunnelsManager { self.tunnels.sort { TunnelsManager.tunnelNameIsLessThan($0.name, $1.name) } let newIndex = self.tunnels.firstIndex(of: tunnel)! self.tunnelsListDelegate?.tunnelMoved(from: oldIndex, to: newIndex) + #if os(iOS) + RecentTunnelsTracker.handleTunnelRenamed(oldName: oldName, newName: tunnelName) + #endif } self.tunnelsListDelegate?.tunnelModified(at: self.tunnels.firstIndex(of: tunnel)!) @@ -266,6 +275,10 @@ class TunnelsManager { self.tunnelsListDelegate?.tunnelRemoved(at: index, tunnel: tunnel) } completionHandler(nil) + + #if os(iOS) + RecentTunnelsTracker.handleTunnelRemoved(tunnelName: tunnel.name) + #endif } } @@ -343,6 +356,10 @@ class TunnelsManager { #else tunnel.startActivation(activationDelegate: activationDelegate) #endif + + #if os(iOS) + RecentTunnelsTracker.handleTunnelActivated(tunnelName: tunnel.name) + #endif } func startDeactivation(of tunnel: TunnelContainer) { diff --git a/WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift b/WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift new file mode 100644 index 0000000..787a624 --- /dev/null +++ b/WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. + +import Foundation + +class RecentTunnelsTracker { + + private static let keyRecentlyActivatedTunnelNames = "recentlyActivatedTunnelNames" + private static let maxNumberOfTunnels = 10 + + private static var userDefaults: UserDefaults? { + guard let appGroupId = FileManager.appGroupId else { + wg_log(.error, staticMessage: "Cannot obtain app group ID from bundle for tracking recently used tunnels") + return nil + } + guard let userDefaults = UserDefaults(suiteName: appGroupId) else { + wg_log(.error, staticMessage: "Cannot obtain shared user defaults for tracking recently used tunnels") + return nil + } + return userDefaults + } + + static func handleTunnelActivated(tunnelName: String) { + guard let userDefaults = RecentTunnelsTracker.userDefaults else { return } + var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? [] + if let existingIndex = recentTunnels.firstIndex(of: tunnelName) { + recentTunnels.remove(at: existingIndex) + } + recentTunnels.insert(tunnelName, at: 0) + if recentTunnels.count > maxNumberOfTunnels { + recentTunnels.removeLast(recentTunnels.count - maxNumberOfTunnels) + } + userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames) + } + + static func handleTunnelRemoved(tunnelName: String) { + guard let userDefaults = RecentTunnelsTracker.userDefaults else { return } + var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? [] + if let existingIndex = recentTunnels.firstIndex(of: tunnelName) { + recentTunnels.remove(at: existingIndex) + userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames) + } + } + + static func handleTunnelRenamed(oldName: String, newName: String) { + guard let userDefaults = RecentTunnelsTracker.userDefaults else { return } + var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? [] + if let existingIndex = recentTunnels.firstIndex(of: oldName) { + recentTunnels[existingIndex] = newName + userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames) + } + } + + static func cleanupTunnels(except tunnelNamesToKeep: Set<String>) { + guard let userDefaults = RecentTunnelsTracker.userDefaults else { return } + var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? [] + let oldCount = recentTunnels.count + recentTunnels.removeAll { !tunnelNamesToKeep.contains($0) } + if oldCount != recentTunnels.count { + userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames) + } + } + + static func recentlyActivatedTunnelNames(limit: Int) -> [String] { + guard let userDefaults = RecentTunnelsTracker.userDefaults else { return [] } + var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? [] + if limit < recentTunnels.count { + recentTunnels.removeLast(recentTunnels.count - limit) + } + return recentTunnels + } +} |