Skip to content

Commit 8d3cb59

Browse files
committed
Add XPCCommunicationBridge
1 parent 10a1fbc commit 8d3cb59

3 files changed

Lines changed: 89 additions & 1 deletion

File tree

Tool/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ let package = Package(
8080
targets: [
8181
// MARK: - Helpers
8282

83-
.target(name: "XPCShared", dependencies: ["SuggestionModel"]),
83+
.target(name: "XPCShared", dependencies: ["SuggestionModel", "Logger"]),
8484

8585
.target(name: "Configs"),
8686

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Foundation
2+
3+
@objc(CommunicationBridgeXPCServiceProtocol)
4+
public protocol CommunicationBridgeXPCServiceProtocol {
5+
func launchExtensionServiceIfNeeded(withReply reply: @escaping (NSXPCListenerEndpoint?) -> Void)
6+
func quit(withReply reply: @escaping () -> Void)
7+
func updateServiceEndpoint(
8+
endpoint: NSXPCListenerEndpoint,
9+
withReply reply: @escaping () -> Void
10+
)
11+
}
12+
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import Foundation
2+
import Logger
3+
4+
public enum XPCCommunicationBridgeError: Swift.Error, LocalizedError {
5+
case failedToCreateXPCConnection
6+
case xpcServiceError(Error)
7+
8+
public var errorDescription: String? {
9+
switch self {
10+
case .failedToCreateXPCConnection:
11+
return "Failed to create XPC connection"
12+
case let .xpcServiceError(error):
13+
return "XPC Service error: \(error.localizedDescription)"
14+
}
15+
}
16+
}
17+
18+
@XPCServiceActor
19+
public class XPCCommunicationBridge {
20+
let service: XPCService
21+
let logger: Logger
22+
var serviceEndpoint: NSXPCListenerEndpoint?
23+
24+
nonisolated
25+
public init(logger: Logger) {
26+
service = .init(
27+
kind: .machService(
28+
identifier: Bundle(for: XPCService.self)
29+
.object(forInfoDictionaryKey: "BUNDLE_IDENTIFIER_BASE") as! String +
30+
".CommunicationBridge"
31+
),
32+
interface: NSXPCInterface(with: CommunicationBridgeXPCServiceProtocol.self),
33+
logger: logger
34+
)
35+
self.logger = logger
36+
}
37+
38+
public func launchExtensionServiceIfNeeded() async throws -> NSXPCListenerEndpoint? {
39+
try await withXPCServiceConnected { service, continuation in
40+
service.launchExtensionServiceIfNeeded { endpoint in
41+
continuation.resume(endpoint)
42+
}
43+
}
44+
}
45+
46+
public func quit() async throws {
47+
try await withXPCServiceConnected { service, continuation in
48+
service.quit {
49+
continuation.resume(())
50+
}
51+
}
52+
}
53+
54+
public func updateServiceEndpoint(_ endpoint: NSXPCListenerEndpoint) async throws {
55+
try await withXPCServiceConnected { service, continuation in
56+
service.updateServiceEndpoint(endpoint: endpoint) {
57+
continuation.resume(())
58+
}
59+
}
60+
}
61+
}
62+
63+
extension XPCCommunicationBridge {
64+
func withXPCServiceConnected<T>(
65+
_ fn: @escaping (CommunicationBridgeXPCServiceProtocol, AutoFinishContinuation<T>) -> Void
66+
) async throws -> T {
67+
guard let connection = service.connection
68+
else { throw XPCCommunicationBridgeError.failedToCreateXPCConnection }
69+
do {
70+
return try await XPCShared.withXPCServiceConnected(connection: connection, fn)
71+
} catch {
72+
throw XPCCommunicationBridgeError.xpcServiceError(error)
73+
}
74+
}
75+
}
76+

0 commit comments

Comments
 (0)