Add a ClientBuilder hook. (#3056)

This commit is contained in:
Doug
2024-07-18 09:47:37 +01:00
committed by GitHub
parent 536d6a1567
commit de07f441f0
10 changed files with 61 additions and 18 deletions

View File

@@ -82,6 +82,7 @@
1146E9EDCF8344F7D6E0D553 /* MockCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0376C429FAB1687C3D905F3E /* MockCoder.swift */; };
119AE9A3FC6E0606C1146528 /* NotificationSettingsEditScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97F8963B14EB0AF3940DDBF /* NotificationSettingsEditScreenRoomCell.swift */; };
11A6B8E3CBDBF0A4107FF4CE /* OnboardingFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */; };
121DDBFAD88B785630852C9A /* AppHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B048CB133239700CD890F5D /* AppHooks.swift */; };
126EE01D8BEAEF26105D83C5 /* RoomDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */; };
12C867E85E6D12EEDFD0B127 /* CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */; };
12CCA59536EDD99A3272CF77 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; };
@@ -5712,6 +5713,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
121DDBFAD88B785630852C9A /* AppHooks.swift in Sources */,
43F06DF42EC00B3CE2B020A4 /* AppSettings.swift in Sources */,
F253AAB4C8F06208173C9C4A /* Assets.swift in Sources */,
484202C5D50983442D24D061 /* AttributedString.swift in Sources */,

View File

@@ -102,7 +102,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
let keychainController = KeychainController(service: .sessions,
accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier)
userSessionStore = UserSessionStore(keychainController: keychainController)
userSessionStore = UserSessionStore(keychainController: keychainController, appHooks: appHooks)
let appLockService = AppLockService(keychainController: keychainController, appSettings: appSettings)
let appLockNavigationCoordinator = NavigationRootCoordinator()
@@ -458,10 +458,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
let encryptionKeyProvider = EncryptionKeyProvider()
let authenticationService = AuthenticationService(userSessionStore: userSessionStore,
encryptionKeyProvider: encryptionKeyProvider,
appSettings: appSettings)
appSettings: appSettings,
appHooks: appHooks)
let qrCodeLoginService = QRCodeLoginService(encryptionKeyProvider: encryptionKeyProvider,
userSessionStore: userSessionStore,
appSettings: appSettings)
appSettings: appSettings,
appHooks: appHooks)
authenticationFlowCoordinator = AuthenticationFlowCoordinator(authenticationService: authenticationService,
qrCodeLoginService: qrCodeLoginService,
@@ -489,7 +491,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
let authenticationService = AuthenticationService(userSessionStore: userSessionStore,
encryptionKeyProvider: EncryptionKeyProvider(),
appSettings: appSettings)
appSettings: appSettings,
appHooks: appHooks)
_ = await authenticationService.configure(for: userSession.clientProxy.homeserver)
let parameters = SoftLogoutScreenCoordinatorParameters(authenticationService: authenticationService,

View File

@@ -15,10 +15,12 @@
//
import Foundation
import MatrixRustSDK
// MARK: Registration
class AppHooks: AppHooksProtocol {
#if IS_MAIN_APP
private var appSettingsHook: AppSettingsHookProtocol?
func registerAppSettingsHook(_ hook: AppSettingsHookProtocol) {
appSettingsHook = hook
@@ -38,6 +40,17 @@ class AppHooks: AppHooksProtocol {
guard let bugReportHook else { return bugReport }
return bugReportHook.run(bugReport: bugReport)
}
#endif
private var clientBuilderHook: ClientBuilderHookProtocol?
func registerClientBuilderHook(_ hook: ClientBuilderHookProtocol) {
clientBuilderHook = hook
}
func runClientBuilderHook(_ clientBuilder: ClientBuilder) -> ClientBuilder {
guard let clientBuilderHook else { return clientBuilder }
return clientBuilderHook.run(builder: clientBuilder)
}
}
protocol AppHooksProtocol {
@@ -50,6 +63,7 @@ extension AppHooksProtocol {
// MARK: Protocols
#if IS_MAIN_APP
protocol AppSettingsHookProtocol {
func run(appSettings: AppSettings) -> AppSettings
}
@@ -57,3 +71,8 @@ protocol AppSettingsHookProtocol {
protocol BugReportHookProtocol {
func run(bugReport: BugReport) -> BugReport
}
#endif
protocol ClientBuilderHookProtocol {
func run(builder: ClientBuilder) -> ClientBuilder
}

View File

@@ -19,7 +19,11 @@ import MatrixRustSDK
extension ClientBuilder {
/// A helper method that applies the common builder modifiers needed for the app.
static func baseBuilder(setupEncryption: Bool = true, httpProxy: String? = nil, slidingSyncProxy: URL? = nil, sessionDelegate: ClientSessionDelegate) -> ClientBuilder {
static func baseBuilder(setupEncryption: Bool = true,
httpProxy: String? = nil,
slidingSyncProxy: URL? = nil,
sessionDelegate: ClientSessionDelegate,
appHooks: AppHooks) -> ClientBuilder {
var builder = ClientBuilder()
.slidingSyncProxy(slidingSyncProxy: slidingSyncProxy?.absoluteString)
.enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier, sessionDelegate: sessionDelegate)
@@ -36,6 +40,6 @@ extension ClientBuilder {
builder = builder.proxy(url: httpProxy)
}
return builder
return appHooks.runClientBuilderHook(builder)
}
}

View File

@@ -25,15 +25,17 @@ class AuthenticationService: AuthenticationServiceProtocol {
private let userSessionStore: UserSessionStoreProtocol
private let appSettings: AppSettings
private let appHooks: AppHooks
private let homeserverSubject: CurrentValueSubject<LoginHomeserver, Never>
var homeserver: CurrentValuePublisher<LoginHomeserver, Never> { homeserverSubject.asCurrentValuePublisher() }
init(userSessionStore: UserSessionStoreProtocol, encryptionKeyProvider: EncryptionKeyProviderProtocol, appSettings: AppSettings) {
init(userSessionStore: UserSessionStoreProtocol, encryptionKeyProvider: EncryptionKeyProviderProtocol, appSettings: AppSettings, appHooks: AppHooks) {
sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString)
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
self.userSessionStore = userSessionStore
self.appSettings = appSettings
self.appHooks = appHooks
homeserverSubject = .init(LoginHomeserver(address: appSettings.defaultHomeserverAddress,
loginMode: .unknown))
@@ -140,7 +142,8 @@ class AuthenticationService: AuthenticationServiceProtocol {
ClientBuilder
.baseBuilder(httpProxy: appSettings.websiteURL.globalProxy,
slidingSyncProxy: appSettings.slidingSyncProxyURL,
sessionDelegate: userSessionStore.clientSessionDelegate)
sessionDelegate: userSessionStore.clientSessionDelegate,
appHooks: appHooks)
.sessionPath(path: sessionDirectory.path(percentEncoded: false))
.passphrase(passphrase: passphrase)
.requiresSlidingSync()

View File

@@ -22,8 +22,10 @@ import MatrixRustSDK
final class QRCodeLoginService: QRCodeLoginServiceProtocol {
private let sessionDirectory: URL
private let passphrase: String
private let userSessionStore: UserSessionStoreProtocol
private let appSettings: AppSettings
private let appHooks: AppHooks
private let qrLoginProgressSubject = PassthroughSubject<QrLoginProgress, Never>()
var qrLoginProgressPublisher: AnyPublisher<QrLoginProgress, Never> {
@@ -32,11 +34,13 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
init(encryptionKeyProvider: EncryptionKeyProviderProtocol,
userSessionStore: UserSessionStoreProtocol,
appSettings: AppSettings) {
self.userSessionStore = userSessionStore
self.appSettings = appSettings
appSettings: AppSettings,
appHooks: AppHooks) {
sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString)
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
self.userSessionStore = userSessionStore
self.appSettings = appSettings
self.appHooks = appHooks
}
func loginWithQRCode(data: Data) async -> Result<UserSessionProtocol, QRCodeLoginServiceError> {
@@ -56,7 +60,8 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
let client = try await ClientBuilder
.baseBuilder(httpProxy: appSettings.websiteURL.globalProxy,
slidingSyncProxy: appSettings.slidingSyncProxyURL,
sessionDelegate: userSessionStore.clientSessionDelegate)
sessionDelegate: userSessionStore.clientSessionDelegate,
appHooks: appHooks)
.sessionPath(path: sessionDirectory.path(percentEncoded: false))
.passphrase(passphrase: passphrase)
.requiresSlidingSync()

View File

@@ -20,6 +20,7 @@ import MatrixRustSDK
class UserSessionStore: UserSessionStoreProtocol {
private let keychainController: KeychainControllerProtocol
private let appHooks: AppHooks
private let matrixSDKStateKey = "matrix-sdk-state"
/// Whether or not there are sessions in the store.
@@ -29,8 +30,9 @@ class UserSessionStore: UserSessionStoreProtocol {
var clientSessionDelegate: ClientSessionDelegate { keychainController }
init(keychainController: KeychainControllerProtocol) {
init(keychainController: KeychainControllerProtocol, appHooks: AppHooks) {
self.keychainController = keychainController
self.appHooks = appHooks
}
/// Deletes all data stored in the shared container and keychain
@@ -120,7 +122,8 @@ class UserSessionStore: UserSessionStoreProtocol {
let builder = ClientBuilder
.baseBuilder(httpProxy: URL(string: homeserverURL)?.globalProxy,
sessionDelegate: keychainController)
sessionDelegate: keychainController,
appHooks: appHooks)
.sessionPath(path: credentials.restorationToken.sessionDirectory.path(percentEncoded: false))
.username(username: credentials.userID)
.homeserverUrl(url: homeserverURL)

View File

@@ -50,6 +50,8 @@ class NotificationServiceExtension: UNNotificationServiceExtension {
private var handler: ((UNNotificationContent) -> Void)?
private var modifiedContent: UNMutableNotificationContent?
private let appHooks = AppHooks()
// Used to create one single UserSession across process/instances/runs
private static let serialQueue = DispatchQueue(label: "io.element.elementx.nse")
private static var userSession: NSEUserSession?
@@ -82,9 +84,9 @@ class NotificationServiceExtension: UNNotificationServiceExtension {
if Self.userSession == nil {
// This function might be run concurrently and from different processes
// It's imperative that we create **at most** one UserSession/Client per process
Task.synchronous {
Task.synchronous { [appHooks] in
do {
Self.userSession = try await NSEUserSession(credentials: credentials, clientSessionDelegate: keychainController)
Self.userSession = try await NSEUserSession(credentials: credentials, clientSessionDelegate: keychainController, appHooks: appHooks)
} catch {
MXLog.error("Failed creating user session with error: \(error)")
}

View File

@@ -25,7 +25,7 @@ final class NSEUserSession {
imageCache: .onlyOnDisk)
private let delegateHandle: TaskHandle?
init(credentials: KeychainCredentials, clientSessionDelegate: ClientSessionDelegate) async throws {
init(credentials: KeychainCredentials, clientSessionDelegate: ClientSessionDelegate, appHooks: AppHooks) async throws {
userID = credentials.userID
if credentials.restorationToken.passphrase != nil {
MXLog.info("Restoring client with encrypted store.")
@@ -35,7 +35,8 @@ final class NSEUserSession {
let clientBuilder = ClientBuilder
.baseBuilder(setupEncryption: false,
httpProxy: URL(string: homeserverURL)?.globalProxy,
sessionDelegate: clientSessionDelegate)
sessionDelegate: clientSessionDelegate,
appHooks: appHooks)
.sessionPath(path: credentials.restorationToken.sessionDirectory.path(percentEncoded: false))
.username(username: credentials.userID)
.homeserverUrl(url: homeserverURL)

View File

@@ -107,3 +107,4 @@ targets:
- path: ../../ElementX/Sources/Services/UserSession/RestorationToken.swift
- path: ../../ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift
- path: ../../ElementX/Sources/Application/AppSettings.swift
- path: ../../ElementX/Sources/Hooks/AppHooks.swift