Skip to content

Commit

Permalink
Add a ClientBuilder hook.
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Jul 17, 2024
1 parent 95d53f1 commit 249d435
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 18 deletions.
2 changes: 2 additions & 0 deletions ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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 */,
Expand Down
11 changes: 7 additions & 4 deletions ElementX/Sources/Application/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,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()
Expand Down Expand Up @@ -460,10 +460,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,
Expand Down Expand Up @@ -491,7 +493,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,
Expand Down
19 changes: 19 additions & 0 deletions ElementX/Sources/Hooks/AppHooks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -50,10 +63,16 @@ extension AppHooksProtocol {

// MARK: Protocols

#if IS_MAIN_APP
protocol AppSettingsHookProtocol {
func run(appSettings: AppSettings) -> AppSettings
}

protocol BugReportHookProtocol {
func run(bugReport: BugReport) -> BugReport
}
#endif

protocol ClientBuilderHookProtocol {
func run(builder: ClientBuilder) -> ClientBuilder
}
8 changes: 6 additions & 2 deletions ElementX/Sources/Other/Extensions/ClientBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -36,6 +40,6 @@ extension ClientBuilder {
builder = builder.proxy(url: httpProxy)
}

return builder
return appHooks.runClientBuilderHook(builder)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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()
Expand Down
13 changes: 9 additions & 4 deletions ElementX/Sources/Services/QRCode/QRCodeLoginService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -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> {
Expand All @@ -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()
Expand Down
7 changes: 5 additions & 2 deletions ElementX/Sources/Services/UserSession/UserSessionStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 4 additions & 2 deletions NSE/Sources/NotificationServiceExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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)")
}
Expand Down
5 changes: 3 additions & 2 deletions NSE/Sources/Other/NSEUserSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions NSE/SupportingFiles/target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 249d435

Please sign in to comment.