This commit is contained in:
parent
d80d2ca656
commit
df4661a718
|
@ -45,6 +45,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, AgentProtocol {
|
|||
guard let update = update else { return }
|
||||
self.notifier.notify(update: update, ignore: self.updater.ignore(release:))
|
||||
}
|
||||
// TODO: REMOVE
|
||||
notifier.notify(update: Release(name: "Test", prerelease: false, html_url: URL(string: "https://example.com")!, body: ""), ignore: nil)
|
||||
connect()
|
||||
}
|
||||
|
||||
|
@ -55,6 +57,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, AgentProtocol {
|
|||
}
|
||||
|
||||
func updatedStore(withID id: UUID) async throws {
|
||||
// TODO: REMOVE
|
||||
notifier.notify(update: Release(name: "UPDATESTORE", prerelease: false, html_url: URL(string: "https://example.com")!, body: ""), ignore: nil)
|
||||
logger.debug("Reloading keys for store with id: \(id)")
|
||||
guard let store = storeList.modifiableStore, store.id == id else { throw AgentProtocolStoreNotFoundError() }
|
||||
try store.reload()
|
||||
|
@ -63,7 +67,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, AgentProtocol {
|
|||
|
||||
}
|
||||
|
||||
class ServiceDelegate: NSObject, NSXPCListenerDelegate {
|
||||
// TODO: MOVE
|
||||
class ServiceDelegate: NSObject, NSXPCListenerDelegate {
|
||||
|
||||
let exported: AgentProtocol
|
||||
|
||||
|
@ -78,4 +83,4 @@ class AppDelegate: NSObject, NSApplicationDelegate, AgentProtocol {
|
|||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,10 @@ struct Secretive: App {
|
|||
// Two conditions in which we reinstall/attempt a force launch:
|
||||
// 1: The app was just updated, and an old version of the agent is alive. Reinstall will deactivate this and activate a new one.
|
||||
// 2: The agent is not running for some reason. We'll attempt to reinstall it, or relaunch directly if that fails.
|
||||
reinstallAgent {
|
||||
reinstallAgent(uninstallFirst: agentStatusChecker.running) {
|
||||
if agentStatusChecker.noninstanceSecretAgentProcesses.isEmpty {
|
||||
agentLaunchController.killNonInstanceAgents(agents: agentStatusChecker.noninstanceSecretAgentProcesses)
|
||||
}
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
agentCommunicationController.configure()
|
||||
}
|
||||
|
@ -72,7 +75,7 @@ struct Secretive: App {
|
|||
CommandGroup(after: .help) {
|
||||
Button("TEST") {
|
||||
Task {
|
||||
try await agentCommunicationController.agent.updatedStore(withID: storeList.modifiableStore?.id as? UUID ?? UUID())
|
||||
try await agentCommunicationController.agent?.updatedStore(withID: storeList.modifiableStore?.id ?? UUID())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,9 +87,9 @@ struct Secretive: App {
|
|||
|
||||
extension Secretive {
|
||||
|
||||
private func reinstallAgent(completion: @escaping () -> Void) {
|
||||
private func reinstallAgent(uninstallFirst: Bool, completion: @escaping () -> Void) {
|
||||
justUpdatedChecker.check()
|
||||
agentLaunchController.install {
|
||||
agentLaunchController.install(uninstallFirst: uninstallFirst) {
|
||||
// Wait a second for launchd to kick in (next runloop isn't enough).
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
agentStatusChecker.check()
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
import Foundation
|
||||
import Combine
|
||||
import AppKit
|
||||
import OSLog
|
||||
import SecretKit
|
||||
import SecretAgentKitProtocol
|
||||
|
||||
protocol AgentCommunicationControllerProtocol: ObservableObject {
|
||||
var agent: AgentProtocol { get }
|
||||
var agent: AgentProtocol? { get }
|
||||
}
|
||||
|
||||
class AgentCommunicationController: ObservableObject, AgentCommunicationControllerProtocol {
|
||||
|
||||
let agent: AgentProtocol
|
||||
private let connection: NSXPCConnection
|
||||
private(set) var agent: AgentProtocol? = nil
|
||||
private var connection: NSXPCConnection? = nil
|
||||
private var running = false
|
||||
|
||||
init() {
|
||||
connection = NSXPCConnection(machServiceName: Bundle.main.agentBundleID)
|
||||
connection.remoteObjectInterface = NSXPCInterface(with: AgentProtocol.self)
|
||||
connection.invalidationHandler = {
|
||||
print("INVALID")
|
||||
}
|
||||
agent = connection.remoteObjectProxyWithErrorHandler({ x in
|
||||
print(x)
|
||||
}) as! AgentProtocol
|
||||
}
|
||||
|
||||
func configure() {
|
||||
guard !running else { return }
|
||||
connection = NSXPCConnection(machServiceName: Bundle.main.agentBundleID)
|
||||
connection?.remoteObjectInterface = NSXPCInterface(with: AgentProtocol.self)
|
||||
connection?.invalidationHandler = {
|
||||
Logger().warning("XPC connection invalidated")
|
||||
}
|
||||
connection?.resume()
|
||||
agent = connection?.remoteObjectProxyWithErrorHandler({ error in
|
||||
Logger().error("\(String(describing: error))")
|
||||
}) as! AgentProtocol
|
||||
running = true
|
||||
connection.resume()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,16 +6,20 @@ import SecretKit
|
|||
|
||||
struct AgentLaunchController {
|
||||
|
||||
func install(completion: (() -> Void)? = nil) {
|
||||
func install(uninstallFirst: Bool = true, completion: (() -> Void)? = nil) {
|
||||
Logger().debug("Installing agent")
|
||||
if uninstallFirst {
|
||||
_ = setEnabled(false)
|
||||
}
|
||||
// This is definitely a bit of a "seems to work better" thing but:
|
||||
// Seems to more reliably hit if these are on separate runloops, otherwise it seems like it sometimes doesn't kill old
|
||||
// and start new?
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
_ = setEnabled(true)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
completion?()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,6 +40,12 @@ struct AgentLaunchController {
|
|||
}
|
||||
}
|
||||
|
||||
func killNonInstanceAgents(agents: [NSRunningApplication]) {
|
||||
for agent in agents {
|
||||
agent.terminate()
|
||||
}
|
||||
}
|
||||
|
||||
private func setEnabled(_ enabled: Bool) -> Bool {
|
||||
SMLoginItemSetEnabled(Bundle.main.agentBundleID as CFString, enabled)
|
||||
}
|
||||
|
|
|
@ -30,13 +30,18 @@ class AgentStatusChecker: ObservableObject, AgentStatusCheckerProtocol {
|
|||
let agents = secretAgentProcesses
|
||||
for agent in agents {
|
||||
guard let url = agent.bundleURL else { continue }
|
||||
if url.absoluteString.hasPrefix(Bundle.main.bundleURL.absoluteString) {
|
||||
if url.absoluteString.contains(Bundle.main.bundleURL.absoluteString) {
|
||||
return agent
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// All processes, _NOT_ including one the instance agent.
|
||||
var noninstanceSecretAgentProcesses: [NSRunningApplication] {
|
||||
NSRunningApplication.runningApplications(withBundleIdentifier: Bundle.main.agentBundleID)
|
||||
.filter({ !($0.bundleURL?.absoluteString.contains(Bundle.main.bundleURL.absoluteString) ?? false) })
|
||||
}
|
||||
|
||||
// Whether Secretive is being run in an Xcode environment.
|
||||
var developmentBuild: Bool {
|
||||
|
|
|
@ -54,7 +54,7 @@ struct CreateSecretView<StoreType: SecretStoreModifiable, AgentCommunicationCont
|
|||
func save() {
|
||||
try! store.create(name: name, requiresAuthentication: requiresAuthentication)
|
||||
Task {
|
||||
try! await agentCommunicationController.agent.updatedStore(withID: store.id)
|
||||
try! await agentCommunicationController.agent!.updatedStore(withID: store.id)
|
||||
}
|
||||
showing = false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue