From a29c18fa45c67694ac19156f5623edd807b6eeb5 Mon Sep 17 00:00:00 2001 From: Brandon Evans Date: Sun, 17 Jan 2021 11:56:39 -0700 Subject: [PATCH 1/4] Xcode really wants to reorder these files, so let it --- Xcodes.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Xcodes.xcodeproj/project.pbxproj b/Xcodes.xcodeproj/project.pbxproj index 3186a93..f3ea93c 100644 --- a/Xcodes.xcodeproj/project.pbxproj +++ b/Xcodes.xcodeproj/project.pbxproj @@ -46,12 +46,12 @@ CAA1CB45255A5B60003FD669 /* SignIn2FAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB44255A5B60003FD669 /* SignIn2FAView.swift */; }; CAA1CB49255A5C97003FD669 /* SignInSMSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB48255A5C97003FD669 /* SignInSMSView.swift */; }; CAA1CB4D255A5CFD003FD669 /* SignInPhoneListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB4C255A5CFD003FD669 /* SignInPhoneListView.swift */; }; - CAA858CD25A3D8BC00ACF8C0 /* ErrorHandling in Frameworks */ = {isa = PBXBuildFile; productRef = CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */; }; CAA8587C25A2B37900ACF8C0 /* IsTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA8587B25A2B37900ACF8C0 /* IsTesting.swift */; }; CAA8589325A2B77E00ACF8C0 /* aria2c in Copy aria2c */ = {isa = PBXBuildFile; fileRef = CAA8588025A2B63A00ACF8C0 /* aria2c */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; CAA8589B25A2B83000ACF8C0 /* Aria2CError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA8589A25A2B83000ACF8C0 /* Aria2CError.swift */; }; - CAA858DB25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz in Resources */ = {isa = PBXBuildFile; fileRef = CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */; }; CAA858C425A2BE4E00ACF8C0 /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA858C325A2BE4E00ACF8C0 /* Downloader.swift */; }; + CAA858CD25A3D8BC00ACF8C0 /* ErrorHandling in Frameworks */ = {isa = PBXBuildFile; productRef = CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */; }; + CAA858DB25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz in Resources */ = {isa = PBXBuildFile; fileRef = CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */; }; CABFA9BB2592EEEA00380FEE /* DateFormatter+.swift in Sources */ = {isa = PBXBuildFile; fileRef = CABFA9BA2592EEEA00380FEE /* DateFormatter+.swift */; }; CABFA9BD2592EEEA00380FEE /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = CABFA9A92592EEE900380FEE /* Environment.swift */; }; CABFA9BF2592EEEA00380FEE /* URLSession+DownloadTaskPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = CABFA9B32592EEEA00380FEE /* URLSession+DownloadTaskPublisher.swift */; }; @@ -200,8 +200,8 @@ CAA8588025A2B63A00ACF8C0 /* aria2c */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = aria2c; sourceTree = ""; }; CAA8588A25A2B69300ACF8C0 /* aria2c.LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aria2c.LICENSE; sourceTree = ""; }; CAA8589A25A2B83000ACF8C0 /* Aria2CError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Aria2CError.swift; sourceTree = ""; }; - CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = "aria2-release-1.35.0.tar.gz"; sourceTree = ""; }; CAA858C325A2BE4E00ACF8C0 /* Downloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = ""; }; + CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = "aria2-release-1.35.0.tar.gz"; sourceTree = ""; }; CABFA9A02592EAF500380FEE /* R&PLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "R&PLogo.png"; sourceTree = ""; }; CABFA9A12592EAFB00380FEE /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; CABFA9A32592ED5700380FEE /* Apple.paw */ = {isa = PBXFileReference; lastKnownFileType = file; name = Apple.paw; path = ../xcodes/Apple.paw; sourceTree = ""; }; From 55e0447e541bf04b2b708a449c62fe77b2831f9e Mon Sep 17 00:00:00 2001 From: Brandon Evans Date: Sun, 17 Jan 2021 11:57:45 -0700 Subject: [PATCH 2/4] Invalidate XPC connection after installing --- Xcodes.xcodeproj/project.pbxproj | 4 --- Xcodes/Backend/Environment.swift | 2 +- Xcodes/Backend/HelperClient.swift | 45 ++++++++++++++++++++++++++++ Xcodes/Backend/HelperInstaller.swift | 44 --------------------------- Xcodes/Backend/Logger.swift | 2 +- 5 files changed, 47 insertions(+), 50 deletions(-) delete mode 100644 Xcodes/Backend/HelperInstaller.swift diff --git a/Xcodes.xcodeproj/project.pbxproj b/Xcodes.xcodeproj/project.pbxproj index f3ea93c..0b00eb6 100644 --- a/Xcodes.xcodeproj/project.pbxproj +++ b/Xcodes.xcodeproj/project.pbxproj @@ -39,7 +39,6 @@ CA9FF8DB25959B4000E47BAF /* XPCDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8DA25959B4000E47BAF /* XPCDelegate.swift */; }; CA9FF8E025959BAA00E47BAF /* ConnectionVerifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8DF25959BAA00E47BAF /* ConnectionVerifier.swift */; }; CA9FF8E625959BB800E47BAF /* AuditTokenHack.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8E525959BB800E47BAF /* AuditTokenHack.m */; }; - CA9FF8F525959CE000E47BAF /* HelperInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8F425959CE000E47BAF /* HelperInstaller.swift */; }; CA9FF9362595B44700E47BAF /* HelperClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF9352595B44700E47BAF /* HelperClient.swift */; }; CAA1CB2D255A5262003FD669 /* AppleAPI in Frameworks */ = {isa = PBXBuildFile; productRef = CAA1CB2C255A5262003FD669 /* AppleAPI */; }; CAA1CB35255A5AD5003FD669 /* SignInCredentialsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB34255A5AD5003FD669 /* SignInCredentialsView.swift */; }; @@ -188,7 +187,6 @@ CA9FF8E425959BB800E47BAF /* AuditTokenHack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuditTokenHack.h; sourceTree = ""; }; CA9FF8E525959BB800E47BAF /* AuditTokenHack.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuditTokenHack.m; sourceTree = ""; }; CA9FF8EA25959BDD00E47BAF /* com.robotsandpencils.XcodesApp.Helper-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "com.robotsandpencils.XcodesApp.Helper-Bridging-Header.h"; sourceTree = ""; }; - CA9FF8F425959CE000E47BAF /* HelperInstaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelperInstaller.swift; sourceTree = ""; }; CA9FF9052595A28400E47BAF /* com.robotsandpencils.XcodesApp.HelperTest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = com.robotsandpencils.XcodesApp.HelperTest.entitlements; sourceTree = ""; }; CA9FF9252595A7EB00E47BAF /* Scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Scripts; sourceTree = ""; }; CA9FF9352595B44700E47BAF /* HelperClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelperClient.swift; sourceTree = ""; }; @@ -409,7 +407,6 @@ CABFA9B82592EEEA00380FEE /* FileManager+.swift */, CAFBDB942598FE96003DCC5A /* FocusedValues.swift */, CABFA9AC2592EEE900380FEE /* Foundation.swift */, - CA9FF8F425959CE000E47BAF /* HelperInstaller.swift */, CA9FF9352595B44700E47BAF /* HelperClient.swift */, CAC281D9259F985100B8AB0B /* InstallationStep.swift */, CA9FF8862595607900E47BAF /* InstalledXcode.swift */, @@ -754,7 +751,6 @@ CAA1CB35255A5AD5003FD669 /* SignInCredentialsView.swift in Sources */, CA9FF877259528CC00E47BAF /* Version+XcodeReleases.swift in Sources */, CABFAA2D2592FBFC00380FEE /* Configure.swift in Sources */, - CA9FF8F525959CE000E47BAF /* HelperInstaller.swift in Sources */, CA73510D257BFCEF00EA9CF8 /* NSAttributedString+.swift in Sources */, CAFBDB952598FE96003DCC5A /* FocusedValues.swift in Sources */, CAC281CD259F97FA00B8AB0B /* ObservingProgressIndicator.swift in Sources */, diff --git a/Xcodes/Backend/Environment.swift b/Xcodes/Backend/Environment.swift index b812835..16c2826 100644 --- a/Xcodes/Backend/Environment.swift +++ b/Xcodes/Backend/Environment.swift @@ -237,7 +237,7 @@ public struct Defaults { private let helperClient = HelperClient() public struct Helper { - var install: () -> Void = HelperInstaller.install + var install: () -> Void = helperClient.install var checkIfLatestHelperIsInstalled: () -> AnyPublisher = helperClient.checkIfLatestHelperIsInstalled var getVersion: () -> AnyPublisher = helperClient.getVersion var switchXcodePath: (_ absolutePath: String) -> AnyPublisher = helperClient.switchXcodePath diff --git a/Xcodes/Backend/HelperClient.swift b/Xcodes/Backend/HelperClient.swift index cc8801f..db37998 100644 --- a/Xcodes/Backend/HelperClient.swift +++ b/Xcodes/Backend/HelperClient.swift @@ -1,5 +1,7 @@ import Combine import Foundation +import os.log +import ServiceManagement final class HelperClient { private var connection: NSXPCConnection? @@ -223,4 +225,47 @@ final class HelperClient { .map { $0.0 } .eraseToAnyPublisher() } + + // MARK: - Install + // From https://github.com/securing/SimpleXPCApp/ + + func install() { + var authItem = kSMRightBlessPrivilegedHelper.withCString { name in + AuthorizationItem(name: name, valueLength: 0, value:UnsafeMutableRawPointer(bitPattern: 0), flags: 0) + } + var authRights = withUnsafeMutablePointer(to: &authItem) { authItem in + AuthorizationRights(count: 1, items: authItem) + } + + do { + let authRef = try authorizationRef(&authRights, nil, [.interactionAllowed, .extendRights, .preAuthorize]) + var cfError: Unmanaged? + SMJobBless(kSMDomainSystemLaunchd, machServiceName as CFString, authRef, &cfError) + if let error = cfError?.takeRetainedValue() { throw error } + + self.connection?.invalidate() + self.connection = nil + } catch { + Logger.helperClient.error("\(error.localizedDescription)") + } + } + + private func executeAuthorizationFunction(_ authorizationFunction: () -> (OSStatus) ) throws { + let osStatus = authorizationFunction() + guard osStatus == errAuthorizationSuccess else { + throw HelperClientError.message(String(describing: SecCopyErrorMessageString(osStatus, nil))) + } + } + + func authorizationRef(_ rights: UnsafePointer?, + _ environment: UnsafePointer?, + _ flags: AuthorizationFlags) throws -> AuthorizationRef? { + var authRef: AuthorizationRef? + try executeAuthorizationFunction { AuthorizationCreate(rights, environment, flags, &authRef) } + return authRef + } +} + +enum HelperClientError: Error { + case message(String) } diff --git a/Xcodes/Backend/HelperInstaller.swift b/Xcodes/Backend/HelperInstaller.swift deleted file mode 100644 index af70188..0000000 --- a/Xcodes/Backend/HelperInstaller.swift +++ /dev/null @@ -1,44 +0,0 @@ -// From https://github.com/securing/SimpleXPCApp/ - -import Foundation -import os.log -import ServiceManagement - -enum HelperAuthorizationError: Error { - case message(String) -} - -class HelperInstaller { - private static func executeAuthorizationFunction(_ authorizationFunction: () -> (OSStatus) ) throws { - let osStatus = authorizationFunction() - guard osStatus == errAuthorizationSuccess else { - throw HelperAuthorizationError.message(String(describing: SecCopyErrorMessageString(osStatus, nil))) - } - } - - static func authorizationRef(_ rights: UnsafePointer?, - _ environment: UnsafePointer?, - _ flags: AuthorizationFlags) throws -> AuthorizationRef? { - var authRef: AuthorizationRef? - try executeAuthorizationFunction { AuthorizationCreate(rights, environment, flags, &authRef) } - return authRef - } - - static func install() { - var authItem = kSMRightBlessPrivilegedHelper.withCString { name in - AuthorizationItem(name: name, valueLength: 0, value:UnsafeMutableRawPointer(bitPattern: 0), flags: 0) - } - var authRights = withUnsafeMutablePointer(to: &authItem) { authItem in - AuthorizationRights(count: 1, items: authItem) - } - - do { - let authRef = try authorizationRef(&authRights, nil, [.interactionAllowed, .extendRights, .preAuthorize]) - var cfError: Unmanaged? - SMJobBless(kSMDomainSystemLaunchd, machServiceName as CFString, authRef, &cfError) - if let error = cfError?.takeRetainedValue() { throw error } - } catch { - Logger.helperInstaller.error("\(error.localizedDescription)") - } - } -} diff --git a/Xcodes/Backend/Logger.swift b/Xcodes/Backend/Logger.swift index d83f9b3..57540b8 100644 --- a/Xcodes/Backend/Logger.swift +++ b/Xcodes/Backend/Logger.swift @@ -5,6 +5,6 @@ extension Logger { private static var subsystem = Bundle.main.bundleIdentifier! static let appState = Logger(subsystem: subsystem, category: "appState") - static let helperInstaller = Logger(subsystem: subsystem, category: "helperInstaller") + static let helperClient = Logger(subsystem: subsystem, category: "helperClient") static let subprocess = Logger(subsystem: subsystem, category: "subprocess") } From 3d5edb39682a0ac9dd231985dfee185fa822e22a Mon Sep 17 00:00:00 2001 From: Brandon Evans Date: Sun, 17 Jan 2021 12:16:16 -0700 Subject: [PATCH 3/4] Replace NSError() with specific error --- Xcodes/Backend/HelperClient.swift | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Xcodes/Backend/HelperClient.swift b/Xcodes/Backend/HelperClient.swift index db37998..4d6c0af 100644 --- a/Xcodes/Backend/HelperClient.swift +++ b/Xcodes/Backend/HelperClient.swift @@ -55,7 +55,7 @@ final class HelperClient { guard let helper = self.helper(errorSubject: connectionErrorSubject) else { - return Fail(error: NSError()) + return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) .eraseToAnyPublisher() } @@ -81,7 +81,7 @@ final class HelperClient { guard let helper = self.helper(errorSubject: connectionErrorSubject) else { - return Fail(error: NSError()) + return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) .eraseToAnyPublisher() } @@ -111,7 +111,7 @@ final class HelperClient { guard let helper = self.helper(errorSubject: connectionErrorSubject) else { - return Fail(error: NSError()) + return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) .eraseToAnyPublisher() } @@ -141,7 +141,7 @@ final class HelperClient { guard let helper = self.helper(errorSubject: connectionErrorSubject) else { - return Fail(error: NSError()) + return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) .eraseToAnyPublisher() } @@ -171,7 +171,7 @@ final class HelperClient { guard let helper = self.helper(errorSubject: connectionErrorSubject) else { - return Fail(error: NSError()) + return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) .eraseToAnyPublisher() } @@ -201,7 +201,7 @@ final class HelperClient { guard let helper = self.helper(errorSubject: connectionErrorSubject) else { - return Fail(error: NSError()) + return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) .eraseToAnyPublisher() } @@ -266,6 +266,16 @@ final class HelperClient { } } -enum HelperClientError: Error { +enum HelperClientError: LocalizedError { + case failedToCreateRemoteObjectProxy case message(String) + + var errorDescription: String? { + switch self { + case .failedToCreateRemoteObjectProxy: + return "Unable to communicate with privileged helper." + case let .message(message): + return message + } + } } From e467f26adcda877c6e35d7c5aafc9076d2e7d095 Mon Sep 17 00:00:00 2001 From: Brandon Evans Date: Sun, 17 Jan 2021 12:37:40 -0700 Subject: [PATCH 4/4] Add more logging to HelperClient --- Xcodes/Backend/HelperClient.swift | 86 ++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/Xcodes/Backend/HelperClient.swift b/Xcodes/Backend/HelperClient.swift index 4d6c0af..ae72a3e 100644 --- a/Xcodes/Backend/HelperClient.swift +++ b/Xcodes/Backend/HelperClient.swift @@ -36,26 +36,35 @@ final class HelperClient { } func checkIfLatestHelperIsInstalled() -> AnyPublisher { + Logger.helperClient.info(#function) + let helperURL = Bundle.main.bundleURL.appendingPathComponent("Contents/Library/LaunchServices/" + machServiceName) guard let helperBundleInfo = CFBundleCopyInfoDictionaryForURL(helperURL as CFURL) as? [String: Any], let bundledHelperVersion = helperBundleInfo["CFBundleShortVersionString"] as? String else { - return Just(false).eraseToAnyPublisher() + return Just(false) + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") }) + .eraseToAnyPublisher() } return getVersion() .map { installedHelperVersion in installedHelperVersion == bundledHelperVersion } .catch { _ in Just(false) } + // Failure is Never, so don't bother logging completion + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0), privacy: .public)") }) .eraseToAnyPublisher() } func getVersion() -> AnyPublisher { + Logger.helperClient.info(#function) + let connectionErrorSubject = PassthroughSubject() guard let helper = self.helper(errorSubject: connectionErrorSubject) else { return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) + .handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") }) .eraseToAnyPublisher() } @@ -73,15 +82,27 @@ final class HelperClient { .map { _ in Void() } ) .map { $0.0 } + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0), privacy: .public)") }, + receiveCompletion: { completion in + switch completion { + case .finished: + Logger.helperClient.info("\(#function): finished") + case let .failure(error): + Logger.helperClient.error("\(#function): \(String(describing: error))") + } + }) .eraseToAnyPublisher() } func switchXcodePath(_ absolutePath: String) -> AnyPublisher { + Logger.helperClient.info("\(#function): \(absolutePath, privacy: .private(mask: .hash))") + let connectionErrorSubject = PassthroughSubject() guard let helper = self.helper(errorSubject: connectionErrorSubject) else { return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) + .handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") }) .eraseToAnyPublisher() } @@ -103,15 +124,27 @@ final class HelperClient { .map { _ in Void() } ) .map { $0.0 } + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") }, + receiveCompletion: { completion in + switch completion { + case .finished: + Logger.helperClient.info("\(#function): finished") + case let .failure(error): + Logger.helperClient.error("\(#function): \(String(describing: error))") + } + }) .eraseToAnyPublisher() } func devToolsSecurityEnable() -> AnyPublisher { + Logger.helperClient.info(#function) + let connectionErrorSubject = PassthroughSubject() guard let helper = self.helper(errorSubject: connectionErrorSubject) else { return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) + .handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") }) .eraseToAnyPublisher() } @@ -133,15 +166,27 @@ final class HelperClient { .map { _ in Void() } ) .map { $0.0 } + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") }, + receiveCompletion: { completion in + switch completion { + case .finished: + Logger.helperClient.info("\(#function): finished") + case let .failure(error): + Logger.helperClient.error("\(#function): \(String(describing: error))") + } + }) .eraseToAnyPublisher() } func addStaffToDevelopersGroup() -> AnyPublisher { + Logger.helperClient.info(#function) + let connectionErrorSubject = PassthroughSubject() guard let helper = self.helper(errorSubject: connectionErrorSubject) else { return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) + .handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") }) .eraseToAnyPublisher() } @@ -163,15 +208,27 @@ final class HelperClient { .map { _ in Void() } ) .map { $0.0 } + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") }, + receiveCompletion: { completion in + switch completion { + case .finished: + Logger.helperClient.info("\(#function): finished") + case let .failure(error): + Logger.helperClient.error("\(#function): \(String(describing: error))") + } + }) .eraseToAnyPublisher() } func acceptXcodeLicense(absoluteXcodePath: String) -> AnyPublisher { + Logger.helperClient.info("\(#function): \(absoluteXcodePath, privacy: .private(mask: .hash))") + let connectionErrorSubject = PassthroughSubject() guard let helper = self.helper(errorSubject: connectionErrorSubject) else { return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) + .handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") }) .eraseToAnyPublisher() } @@ -193,15 +250,27 @@ final class HelperClient { .map { _ in Void() } ) .map { $0.0 } + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") }, + receiveCompletion: { completion in + switch completion { + case .finished: + Logger.helperClient.info("\(#function): finished") + case let .failure(error): + Logger.helperClient.error("\(#function): \(String(describing: error))") + } + }) .eraseToAnyPublisher() } func runFirstLaunch(absoluteXcodePath: String) -> AnyPublisher { + Logger.helperClient.info("\(#function): \(absoluteXcodePath, privacy: .private(mask: .hash))") + let connectionErrorSubject = PassthroughSubject() guard let helper = self.helper(errorSubject: connectionErrorSubject) else { return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy) + .handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") }) .eraseToAnyPublisher() } @@ -223,6 +292,15 @@ final class HelperClient { .map { _ in Void() } ) .map { $0.0 } + .handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") }, + receiveCompletion: { completion in + switch completion { + case .finished: + Logger.helperClient.info("\(#function): finished") + case let .failure(error): + Logger.helperClient.error("\(#function): \(String(describing: error))") + } + }) .eraseToAnyPublisher() } @@ -230,6 +308,8 @@ final class HelperClient { // From https://github.com/securing/SimpleXPCApp/ func install() { + Logger.helperClient.info(#function) + var authItem = kSMRightBlessPrivilegedHelper.withCString { name in AuthorizationItem(name: name, valueLength: 0, value:UnsafeMutableRawPointer(bitPattern: 0), flags: 0) } @@ -245,8 +325,10 @@ final class HelperClient { self.connection?.invalidate() self.connection = nil + + Logger.helperClient.info("\(#function): Finished installation") } catch { - Logger.helperClient.error("\(error.localizedDescription)") + Logger.helperClient.error("\(#function): \(error.localizedDescription)") } }