|
|
|
|
Quelle BusinessInjector.swift
Sprache: JAVA
|
|
import AudioSessionManager
import AudioSessionManagerRTC
import CocoaLumberjackSwift
import Foundation
import Keychain
import RemoteSecretProtocol
import ThreemaEssentials
/// If your code is run in the notification extension (`NotificationService`) you should generally
/// use the already created instance of business injector.
/// Otherwise inconsistencies might occur in the database.
public final class BusinessInjector: NSObject, FrameworkInjectorProtocol {
/// Shared instance to be used for everything in the UI (MainThread)
@objc public static let ui = BusinessInjector()
// This must be initialized lazy, because `BusinessInjector` is used in `AppMigration` and
// the migration of files (see `AppFilesMigration.run()`) must be completed before the `TaskManager`
// is initialized!
private lazy var taskManager: TaskManagerProtocol = TaskManager(
backgroundEntityManager: backgroundEntityManager,
serverConnector: serverConnector
)
// Will be used for none public services, that must be running in the background anyway
private let backgroundEntityManager: EntityManager
/// Main designated initializer that accepts EntityManager and PersistenceManager.
/// Use this when you want full control over both dependencies.
/// - Parameters:
/// - entityManager: The entity manager to use
/// - persistenceManager: The persistence manager (provides database and background entity manager)
required init(entityManager: EntityManager, persistenceManager: PersistenceManager) {
self.runsInBackground = entityManager.hasBackgroundChildContext
self.entityManager = entityManager
if entityManager.hasBackgroundChildContext {
self.backgroundEntityManager = entityManager
}
else {
self.backgroundEntityManager = persistenceManager.backgroundEntityManager
}
}
/// Legacy initializer for backward compatibility (uses RemoteSecretProvider.remoteSecretManager).
@objc convenience init(entityManager: EntityManager) {
// This `assert` would be nice, than the `BusinessInjector` can only be used when My Identity is present.
// But in the moment the assert throws if unit tests are running, because e.g.
// `ContactEntity.setFeatureMask(...` uses an instance of `BusinessInjector`, this should be mocked.
// There are many issues of this kind!
// assert(MyIdentityStore.shared().identity != nil, "My identity should be set when using business injector")
let persistenceManager = PersistenceManager(
appGroupID: AppGroup.groupID(),
userDefaults: AppGroup.userDefaults(),
remoteSecretManager: RemoteSecretProvider.remoteSecretManager
)
self.init(entityManager: entityManager, persistenceManager: persistenceManager)
}
/// Create `BusinessInjector` for main thread or background (Core Data child context) thread.
///
/// - Parameter forBackgroundProcess: Use this only for special cases (like Notification Extension), in general use
/// the functions `runInBackground` and `runInBackgroundAndWait` for background threads
@objc public convenience init(forBackgroundProcess: Bool) {
let persistenceManager = PersistenceManager(
appGroupID: AppGroup.groupID(),
userDefaults: AppGroup.userDefaults(),
remoteSecretManager: RemoteSecretProvider.remoteSecretManager
)
if forBackgroundProcess {
self.init(entityManager: persistenceManager.backgroundEntityManager)
}
else {
self.init(entityManager: persistenceManager.entityManager)
}
}
@objc override public convenience init() {
self.init(forBackgroundProcess: false)
}
/// Create `BusinessInjector` with injected RemoteSecretManager (avoids AppLaunchManager singleton).
/// Use this for new coordinator-based architecture.
/// - Parameter remoteSecretManager: The RemoteSecretManager to use for persistence
public convenience init(remoteSecretManager: any RemoteSecretManagerProtocol) {
let persistenceManager = PersistenceManager(
appGroupID: AppGroup.groupID(),
userDefaults: AppGroup.userDefaults(),
remoteSecretManager: remoteSecretManager
)
self.init(entityManager: persistenceManager.entityManager, persistenceManager: persistenceManager)
}
// MARK: - Audio session
/// The single owner of the process-wide audio session.
///
/// Exposed as a `public static` so callers can obtain the audio session manager without forcing
/// the full `BusinessInjector.ui` singleton to initialize. Constructing `BusinessInjector.ui`
/// reads `RemoteSecretProvider.remoteSecretManager`, which fatalErrors when the provider has not
/// been set yet. That happens on a cold VoIP-push launch, before the launch sequence runs.
public static let sharedAudioSessionManager = AudioSessionManagerFactory.make()
// MARK: BusinessInjectorProtocol
public let runsInBackground: Bool
public var audioSessionManager: any AudioSessionManagerProtocol {
Self.sharedAudioSessionManager
}
public private(set) lazy var profileStore: any ProfileStoreProtocol = ThreemaFramework
.ProfileStore(myIdentity: ThreemaIdentity(self.myIdentityStore.identity))
// Do not mark as lazy, to prevent blocking thread when calling singleton init
public private(set) var contactStore: ContactStoreProtocol = ContactStore.shared()
public private(set) lazy var conversationStore: any ConversationStoreProtocol = ConversationStore(
userSettings: userSettings,
pushSettingManager: pushSettingManager,
groupManager: groupManager,
entityManager: entityManager,
taskManager: taskManager
)
@available(*, deprecated, message: "Only use from Objective-C", renamed: "conversationStore")
@objc public private(set) lazy var conversationStoreObjC = ConversationStore(
userSettings: userSettings,
pushSettingManager: pushSettingManager,
groupManager: groupManager,
entityManager: entityManager,
taskManager: taskManager
)
@objc public let entityManager: EntityManager
public private(set) lazy var groupManager: GroupManagerProtocol = GroupManager(
myIdentityStore: myIdentityStore,
contactStore: contactStore,
taskManager: taskManager,
userSettings: userSettings,
entityManager: entityManager,
groupPhotoSender: {
GroupPhotoSender()
}
)
@available(*, deprecated, message: "Only use from Objective-C", renamed: "groupManager")
@objc public private(set) lazy var groupManagerObjC = GroupManager(
myIdentityStore: myIdentityStore,
contactStore: contactStore,
taskManager: taskManager,
userSettings: userSettings,
entityManager: entityManager,
groupPhotoSender: {
GroupPhotoSender()
}
)
public private(set) lazy var distributionListManager: any DistributionListManagerProtocol =
DistributionListManager(entityManager: entityManager)
// Do not mark as lazy, to prevent blocking thread when calling singleton init
public private(set) var licenseStore: any LicenseStoreProtocol = LicenseStore.shared()
public private(set) lazy var messageSender: any MessageSenderProtocol = MessageSender(
serverConnector: serverConnector,
myIdentityStore: myIdentityStore,
userSettings: userSettings,
groupManager: groupManager,
taskManager: taskManager,
entityManager: entityManager
)
public private(set) lazy var multiDeviceManager: MultiDeviceManagerProtocol =
MultiDeviceManager(
serverConnector: serverConnector,
contactStore: contactStore,
userSettings: userSettings,
taskManager: taskManager,
entityManager: entityManager,
keychainManager: keychainManager
)
// Do not mark as lazy, to prevent blocking thread when calling singleton init
@objc public private(set) var myIdentityStore: MyIdentityStoreProtocol = MyIdentityStore.shared()
public lazy var unreadMessages: UnreadMessagesProtocol = UnreadMessages(
entityManager: entityManager,
taskManager: taskManager
)
public private(set) lazy var messageRetentionManager: any MessageRetentionManagerModelProtocol =
MessageRetentionManagerModel(
userSettings: userSettings,
unreadMessages: unreadMessages,
groupManager: groupManager,
entityManager: entityManager
)
// Do not mark as lazy, to prevent blocking thread when calling singleton init
@objc public private(set) var userSettings: any UserSettingsProtocol = UserSettings.shared()
public private(set) lazy var settingsStore: any SettingsStoreProtocol = SettingsStore(
serverConnector: serverConnector,
myIdentityStore: myIdentityStore,
contactStore: contactStore,
userSettings: userSettings,
taskManager: taskManager
)
// Do not mark as lazy, to prevent blocking thread when calling singleton init
public private(set) var serverConnector: ServerConnectorProtocol = ServerConnector.shared()
public private(set) lazy var pushSettingManager: any PushSettingManagerProtocol = PushSettingManager(
userSettings: userSettings,
groupManager: groupManager,
entityManager: entityManager,
markupParser: MarkupParser(),
taskManager: taskManager,
isWorkApp: TargetManager.isBusinessApp
)
public private(set) lazy var keychainManager: any KeychainManagerProtocol = KeychainManager(
remoteSecretManager: RemoteSecretProvider.remoteSecretManager
)
@available(
*,
deprecated,
message: "Only use from Objective-C",
renamed: "keychainManager"
)
@objc public private(set) lazy var keychainManagerObjC: KeychainManager = keychainManager as! KeychainManager
public private(set) lazy var workAvailabilityStatusManager: any WorkAvailabilityStatusManagerProtocol = {
guard TargetManager.isWork else {
return WorkAvailabilityStatusManagerNull()
}
return WorkAvailabilityStatusManager(defaults: AppGroup.userDefaults())
}()
public private(set) lazy var workDataFetcher: any WorkDataFetcherProtocol = {
let apiCaller = WorkDataAPICaller(licenseStore: licenseStore)
let mdmSetup = MDMSetup()!
let appFlavorService = AppFlavorService()
let workDataThreemaMDMFetcher = WorkDataThreemaMDMFetcher(
mdmSetup: mdmSetup,
licenseStore: licenseStore,
appFlavorService: appFlavorService,
workDataAPICaller: apiCaller
)
return WorkDataFetcher(
contactStore: ContactStore.shared(),
licenseStore: licenseStore,
identityStore: myIdentityStore,
userSettings: userSettings,
userDefaults: AppGroup.userDefaults(),
serverInfoProvider: ServerInfoProviderFactory.makeServerInfoProvider(),
appFlavorService: appFlavorService,
entityManager: entityManager,
mdmSetup: mdmSetup,
workDataAPICaller: apiCaller,
workDataThreemaMDMFetcher: workDataThreemaMDMFetcher
)
}()
public func runInBackground<T>(
_ block: @escaping (BusinessInjectorProtocol) async throws -> T
) async rethrows
-> T {
if entityManager.hasBackgroundChildContext {
try await block(self)
}
else {
try await block(BusinessInjector(forBackgroundProcess: true))
}
}
public func runInBackgroundAndWait<T>(_ block: (BusinessInjectorProtocol) throws -> T) rethrows -> T {
if entityManager.hasBackgroundChildContext {
try block(self)
}
else {
try block(BusinessInjector(forBackgroundProcess: true))
}
}
// MARK: BusinessInternalInjectorProtocol
private var mediatorReflectedProcessorInstance: MediatorReflectedProcessorProtocol?
private var messageProcessorInstance: MessageProcessorProtocol?
private var fsmpInstance: ForwardSecurityMessageProcessor?
private var fsStatusSender: ForwardSecurityStatusSender?
private static var dhSessionStoreInstance: DHSessionStoreProtocol = try! SQLDHSessionStore()
private(set) lazy var mediatorMessageProtocol: MediatorMessageProtocolProtocol = MediatorMessageProtocol(
deviceGroupKeys: self
.serverConnector.deviceGroupKeys
)
private(set) lazy var mediatorReflectedProcessor: MediatorReflectedProcessorProtocol = MediatorReflectedProcessor(
frameworkInjector: self,
messageProcessorDelegate: serverConnector
)
var messageProcessor: MessageProcessorProtocol {
if messageProcessorInstance == nil {
messageProcessorInstance = MessageProcessor(
serverConnector,
groupManager: GroupManager(
myIdentityStore: myIdentityStore,
contactStore: contactStore,
taskManager: taskManager,
userSettings: userSettings,
entityManager: backgroundEntityManager,
groupPhotoSender: {
GroupPhotoSender()
}
),
entityManager: backgroundEntityManager,
fsmp: fsmp,
nonceGuard: nonceGuard as? NSObject
)
}
return messageProcessorInstance!
}
var fsmp: ForwardSecurityMessageProcessor {
if fsmpInstance == nil {
fsmpInstance = ForwardSecurityMessageProcessor(
dhSessionStore: dhSessionStore,
identityStore: myIdentityStore,
messageSender: messageSender,
taskManager: taskManager
)
fsStatusSender = ForwardSecurityStatusSender(entityManager: entityManager)
fsmpInstance?.addListener(listener: fsStatusSender!)
}
return fsmpInstance!
}
public var dhSessionStore: DHSessionStoreProtocol {
BusinessInjector.dhSessionStoreInstance
}
private(set) lazy var conversationStoreInternal: ConversationStoreInternalProtocol =
conversationStore as! ConversationStoreInternalProtocol
private(set) lazy var settingsStoreInternal: SettingsStoreInternalProtocol =
settingsStore as! SettingsStoreInternalProtocol
private(set) lazy var userNotificationCenterManager: UserNotificationCenterManagerProtocol =
UserNotificationCenterManager()
private(set) lazy var nonceGuard: NonceGuardProtocol = NonceGuard(
myIdentityStore: myIdentityStore,
entityManager: backgroundEntityManager
)
private(set) lazy var blobUploader: BlobUploaderProtocol =
BlobUploader(blobURL: BlobURL(serverConnector: self.serverConnector, userSettings: self.userSettings))
}
¤ Dauer der Verarbeitung: 0.6 Sekunden
¤
*© Formatika GbR, Deutschland
|
|
2026-11-01
|
|
|
|
|
Neuigkeiten |
| Aktuelles |
| Motto des Tages |
|
Open Source Software |
|
|
|
Jenseits des Üblichen ....
|
|
Besucherstatistik |
|
|
| Statistik |
| #Sources=1104845 |
| #Domains=499168 |
|
|