Document Manager subspec

Refactor notifications to newer Swift convention.
This commit is contained in:
Davide De Rosa 2020-06-13 15:30:48 +02:00
parent e625360914
commit 10aec5185d
10 changed files with 103 additions and 20 deletions

View File

@ -43,6 +43,16 @@ custom_categories:
- NETunnelInterface - NETunnelInterface
- NEUDPSocket - NEUDPSocket
- NSNotification - NSNotification
- name: Manager
children:
- VPN
- VPNProvider
- MockVPNProvider
- StandardVPNProvider
- VPNConfiguration
- NetworkExtensionVPNConfiguration
- VPNStatus
- NSNotification
- name: Protocols/OpenVPN - name: Protocols/OpenVPN
children: children:
- OpenVPN - OpenVPN

View File

@ -62,7 +62,7 @@ class ViewController: UIViewController, URLSessionDataDelegate {
NotificationCenter.default.addObserver( NotificationCenter.default.addObserver(
self, self,
selector: #selector(VPNStatusDidChange(notification:)), selector: #selector(VPNStatusDidChange(notification:)),
name: .VPNDidChangeStatus, name: VPN.didChangeStatus,
object: nil object: nil
) )

View File

@ -58,7 +58,7 @@ class ViewController: NSViewController {
NotificationCenter.default.addObserver( NotificationCenter.default.addObserver(
self, self,
selector: #selector(VPNStatusDidChange(notification:)), selector: #selector(VPNStatusDidChange(notification:)),
name: .NEVPNStatusDidChange, name: VPN.didChangeStatus,
object: nil object: nil
) )

View File

@ -44,7 +44,7 @@ private let log = SwiftyBeaver.self
public class InterfaceObserver: NSObject { public class InterfaceObserver: NSObject {
/// A change in Wi-Fi state occurred. /// A change in Wi-Fi state occurred.
public static let didDetectWifiChange = NSNotification.Name("InterfaceObserverDidDetectWifiChange") public static let didDetectWifiChange = Notification.Name("InterfaceObserverDidDetectWifiChange")
private var queue: DispatchQueue? private var queue: DispatchQueue?

View File

@ -25,6 +25,7 @@
import Foundation import Foundation
/// :nodoc:
public class MockVPNProvider: VPNProvider { public class MockVPNProvider: VPNProvider {
public let isPrepared: Bool = true public let isPrepared: Bool = true
@ -33,7 +34,7 @@ public class MockVPNProvider: VPNProvider {
public private(set) var status: VPNStatus = .disconnected public private(set) var status: VPNStatus = .disconnected
public func prepare(completionHandler: (() -> Void)?) { public func prepare(completionHandler: (() -> Void)?) {
NotificationCenter.default.post(name: .VPNDidPrepare, object: nil) NotificationCenter.default.post(name: VPN.didPrepare, object: nil)
completionHandler?() completionHandler?()
} }
@ -45,28 +46,28 @@ public class MockVPNProvider: VPNProvider {
public func connect(completionHandler: ((Error?) -> Void)?) { public func connect(completionHandler: ((Error?) -> Void)?) {
isEnabled = true isEnabled = true
status = .connected status = .connected
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) NotificationCenter.default.post(name: VPN.didChangeStatus, object: self)
completionHandler?(nil) completionHandler?(nil)
} }
public func disconnect(completionHandler: ((Error?) -> Void)?) { public func disconnect(completionHandler: ((Error?) -> Void)?) {
isEnabled = false isEnabled = false
status = .disconnected status = .disconnected
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) NotificationCenter.default.post(name: VPN.didChangeStatus, object: self)
completionHandler?(nil) completionHandler?(nil)
} }
public func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) { public func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
isEnabled = true isEnabled = true
status = .connected status = .connected
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) NotificationCenter.default.post(name: VPN.didChangeStatus, object: self)
completionHandler?(nil) completionHandler?(nil)
} }
public func uninstall(completionHandler: (() -> Void)?) { public func uninstall(completionHandler: (() -> Void)?) {
isEnabled = false isEnabled = false
status = .disconnected status = .disconnected
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) NotificationCenter.default.post(name: VPN.didChangeStatus, object: self)
completionHandler?() completionHandler?()
} }

View File

@ -26,6 +26,7 @@
import Foundation import Foundation
import NetworkExtension import NetworkExtension
/// :nodoc:
public class StandardVPNProvider: VPNProvider { public class StandardVPNProvider: VPNProvider {
private let bundleIdentifier: String private let bundleIdentifier: String
@ -83,7 +84,7 @@ public class StandardVPNProvider: VPNProvider {
public func prepare(completionHandler: (() -> Void)?) { public func prepare(completionHandler: (() -> Void)?) {
find(with: bundleIdentifier) { find(with: bundleIdentifier) {
self.manager = $0 self.manager = $0
NotificationCenter.default.post(name: .VPNDidPrepare, object: nil) NotificationCenter.default.post(name: VPN.didPrepare, object: nil)
completionHandler?() completionHandler?()
} }
} }
@ -307,10 +308,10 @@ public class StandardVPNProvider: VPNProvider {
} }
lastNotifiedStatus = status lastNotifiedStatus = status
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) NotificationCenter.default.post(name: VPN.didChangeStatus, object: self)
} }
@objc private func vpnDidReinstall(_ notification: Notification) { @objc private func vpnDidReinstall(_ notification: Notification) {
NotificationCenter.default.post(name: .VPNDidReinstall, object: self) NotificationCenter.default.post(name: VPN.didReinstall, object: self)
} }
} }

View File

@ -25,6 +25,18 @@
import Foundation import Foundation
/// Wrapper for shared access to VPN-related objects.
public class VPN { public class VPN {
/// The VPN became ready to use.
public static let didPrepare = Notification.Name("VPNDidPrepare")
/// The VPN did change status.
public static let didChangeStatus = Notification.Name("VPNDidChangeStatus")
/// The VPN profile did (re)install.
public static let didReinstall = Notification.Name("VPNDidReinstall")
/// A singleton `VPNProvider` instance (default is a `MockVPNProvider`). Make sure to set this on app launch.
public static var shared: VPNProvider = MockVPNProvider() public static var shared: VPNProvider = MockVPNProvider()
} }

View File

@ -26,14 +26,20 @@
import Foundation import Foundation
import NetworkExtension import NetworkExtension
/// Generic marker for objects able to configure a `VPNProvider`.
public protocol VPNConfiguration { public protocol VPNConfiguration {
} }
/// A `VPNConfiguration` built on top of NetworkExtension entities.
public struct NetworkExtensionVPNConfiguration: VPNConfiguration { public struct NetworkExtensionVPNConfiguration: VPNConfiguration {
/// The `NETunnelProviderProtocol` object embedding tunnel configuration.
public let protocolConfiguration: NETunnelProviderProtocol public let protocolConfiguration: NETunnelProviderProtocol
/// The on-demand rules to establish.
public let onDemandRules: [NEOnDemandRule] public let onDemandRules: [NEOnDemandRule]
/// :nodoc:
public init(protocolConfiguration: NETunnelProviderProtocol, onDemandRules: [NEOnDemandRule]) { public init(protocolConfiguration: NETunnelProviderProtocol, onDemandRules: [NEOnDemandRule]) {
self.protocolConfiguration = protocolConfiguration self.protocolConfiguration = protocolConfiguration
self.onDemandRules = onDemandRules self.onDemandRules = onDemandRules

View File

@ -25,36 +25,83 @@
import Foundation import Foundation
/// Helps controlling a VPN without messing with underlying implementations.
public protocol VPNProvider: class { public protocol VPNProvider: class {
/// `true` if the VPN is ready for use.
var isPrepared: Bool { get } var isPrepared: Bool { get }
/// `true` if the associated VPN profile is enabled.
var isEnabled: Bool { get } var isEnabled: Bool { get }
/// The status of the VPN.
var status: VPNStatus { get } var status: VPNStatus { get }
/**
Prepares the VPN for use.
- Postcondition: The VPN is ready to use and `isPrepared` becomes `true`.
- Parameter completionHandler: The completion handler.
- Seealso: `isPrepared`
*/
func prepare(completionHandler: (() -> Void)?) func prepare(completionHandler: (() -> Void)?)
/**
Installs the VPN profile.
- Parameter configuration: The `VPNConfiguration` to install.
- Parameter completionHandler: The completion handler with an optional error.
*/
func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?)
/**
Connects to the VPN.
- Parameter completionHandler: The completion handler with an optional error.
*/
func connect(completionHandler: ((Error?) -> Void)?) func connect(completionHandler: ((Error?) -> Void)?)
/**
Disconnects from the VPN.
- Parameter completionHandler: The completion handler with an optional error.
*/
func disconnect(completionHandler: ((Error?) -> Void)?) func disconnect(completionHandler: ((Error?) -> Void)?)
/**
Reconnects to the VPN.
- Parameter configuration: The `VPNConfiguration` to install.
- Parameter completionHandler: The completion handler with an optional error.
*/
func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?)
/**
Uninstalls the VPN profile.
- Parameter completionHandler: The completion handler.
*/
func uninstall(completionHandler: (() -> Void)?) func uninstall(completionHandler: (() -> Void)?)
/**
Request a debug log from the VPN.
- Parameter fallback: The block resolving to a fallback `String` if no debug log is available.
- Parameter completionHandler: The completion handler with the debug log.
*/
func requestDebugLog(fallback: (() -> String)?, completionHandler: @escaping (String) -> Void) func requestDebugLog(fallback: (() -> String)?, completionHandler: @escaping (String) -> Void)
/**
Requests the current received/sent bytes count from the VPN.
- Parameter completionHandler: The completion handler with an optional received/sent bytes count.
*/
func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void)
/**
Requests the server configuration from the VPN.
- Parameter completionHandler: The completion handler with an optional configuration object.
*/
func requestServerConfiguration(completionHandler: @escaping (Any?) -> Void) func requestServerConfiguration(completionHandler: @escaping (Any?) -> Void)
} }
public extension Notification.Name {
static let VPNDidPrepare = Notification.Name("VPNDidPrepare")
static let VPNDidChangeStatus = Notification.Name("VPNDidChangeStatus")
static let VPNDidReinstall = Notification.Name("VPNDidReinstall")
}

View File

@ -25,12 +25,18 @@
import Foundation import Foundation
/// Status of a `VPNProvider`.
public enum VPNStatus { public enum VPNStatus {
/// VPN is connected.
case connected case connected
/// VPN is attempting a connection.
case connecting case connecting
/// VPN is disconnected.
case disconnected case disconnected
/// VPN is completing a disconnection.
case disconnecting case disconnecting
} }