Files
2021-06-02 12:28:09 +03:00

169 lines
5.0 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// PrivadoUninstallerClient.swift
// PrivadoVPN
//
// Created by Juraldinio on 12/24/20.
// Copyright © 2020 Privado LLC. All rights reserved.
//
import Foundation
final class PrivadoUninstallerClient: NSObject {
// MARK: - Properties
private var connection: NSXPCConnection?
private var installed = false
private(set) var state: XPCClientState = .undefined
func install(installer: @escaping (String) -> Bool) -> Future<PrivadoUninstallerClient> {
self.state = .installing
return Future<PrivadoUninstallerClient> { completion in
let success = installer(PrivadoConstants.Uninstaller.bundle)
self.installed = success
let result: Result<PrivadoUninstallerClient, Error> = success ? .success(self) : .failure(FutureError.none)
completion(result)
}
}
func resume() {
guard let connection = self.connection else {
self.createConnection()
return
}
connection.resume()
}
func uninstall() -> Future<Void> {
return self
.checkCallAllowed()
.flatMap { intercomm -> Future<Void> in
return Future<Void> { completion in
intercomm.uninstall { completion(.success(())) }
}
}.onSuccess { [weak self] in self?.reset() }
}
// MARK: - Private
private func reset() {
guard self.state == .undefined else { return }
self.connection?.invalidate()
self.connection = nil
}
private func createConnection() {
guard !self.connection.isExist else { return }
let connection = NSXPCConnection(machServiceName: PrivadoConstants.Uninstaller.bundle, options: .privileged)
connection.exportedInterface = NSXPCInterface(with: IntercommConsoleClientType.self)
connection.exportedObject = self
connection.remoteObjectInterface = NSXPCInterface(with: IntercommUninstallerType.self)
connection.invalidationHandler = self.connectionInvalidationHandler
connection.interruptionHandler = self.connetionInterruptionHandler
self.connection = connection
connection.resume()
}
private func intercomm() -> Future<IntercommUninstallerType> {
return Future<IntercommUninstallerType> { [weak self] completion in
guard let self = self else {
completion(.failure(XPCСommonClientError.unowned))
return
}
guard let connection = self.connection
, let intercomm = connection.remoteObjectProxyWithErrorHandler({ error in
completion(.failure(XPCСommonClientError.proxy(error)))
}) as? IntercommUninstallerType else {
completion(.failure(XPCСommonClientError.incorrectType))
return
}
completion(.success(intercomm))
}.onResult { result in
switch result {
case let .failure(hiveError):
switch hiveError {
case XPCСommonClientError.unowned:
break
case let XPCСommonClientError.proxy(error):
CometLogger.shared.record(error: error)
if self.state == .initializing {
self.state = .invalid
}
case XPCСommonClientError.incorrectType:
if self.state == .initializing {
self.state = .invalid
}
default:
break
}
default:
break
}
}
}
private func checkCallAllowed() -> Future<IntercommUninstallerType> {
return self.intercomm().onFailure { [weak self] _ in
self?.state = .undefined
/*throw NSError(domain: PrivadoConstants.Hive.error,
code: PrivadoConstants.Hive.ErrorCode.xpcEmptyRemoteObject,
userInfo: nil)*/
}
}
private func connetionInterruptionHandler() {
guard self.state != .requireUpdate else { return }
if self.state == .initializing
, !self.installed {
self.state = .invalid
return
}
self.state = .interrupted
// NSLog("[SMJBS]: \(#function)")
}
private func connectionInvalidationHandler() {
if self.installed {
// Think what I must todo here
return
}
guard self.state != .invalid else { return }
if self.state == .initializing {
self.state = .invalid
return
}
self.state = .invalid
// NSLog("[SMJBS]: \(#function)")
}
}