Fixed the broken unit tests

Fixed a few bugs uncovered by the unit tests
This commit is contained in:
Morgan Pretty 2022-06-22 14:27:34 +10:00
parent 153880cf4d
commit a998cadbb7
62 changed files with 1956 additions and 2512 deletions

View File

@ -564,7 +564,6 @@
FD078E4F27E175F1000769AF /* DependencyExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E4E27E175F1000769AF /* DependencyExtensions.swift */; };
FD078E5227E1760A000769AF /* OGMDependencyExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E5127E1760A000769AF /* OGMDependencyExtensions.swift */; };
FD078E5427E197CA000769AF /* OpenGroupManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909D27D85751005DAE71 /* OpenGroupManagerSpec.swift */; };
FD078E5827E1B831000769AF /* TestIncomingMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E5727E1B831000769AF /* TestIncomingMessage.swift */; };
FD078E5A27E29F09000769AF /* MockNonce16Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E5927E29F09000769AF /* MockNonce16Generator.swift */; };
FD078E5C27E29F78000769AF /* MockNonce24Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E5B27E29F78000769AF /* MockNonce24Generator.swift */; };
FD09796927F6BEA700936362 /* SwarmSnode.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09796827F6BEA700936362 /* SwarmSnode.swift */; };
@ -738,16 +737,12 @@
FDC2909827D7129B005DAE71 /* PersonalizationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909727D7129B005DAE71 /* PersonalizationSpec.swift */; };
FDC2909A27D71376005DAE71 /* NonceGeneratorSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909927D71376005DAE71 /* NonceGeneratorSpec.swift */; };
FDC2909C27D713D2005DAE71 /* SodiumProtocolsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909B27D713D2005DAE71 /* SodiumProtocolsSpec.swift */; };
FDC290A027D85826005DAE71 /* TestContactThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909F27D85826005DAE71 /* TestContactThread.swift */; };
FDC290A227D85890005DAE71 /* TestInteraction.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290A127D85890005DAE71 /* TestInteraction.swift */; };
FDC290A627D860CE005DAE71 /* Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290A527D860CE005DAE71 /* Mock.swift */; };
FDC290A827D9B46D005DAE71 /* NimbleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290A727D9B46D005DAE71 /* NimbleExtensions.swift */; };
FDC290A927D9B46D005DAE71 /* NimbleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290A727D9B46D005DAE71 /* NimbleExtensions.swift */; };
FDC290AA27D9B6FD005DAE71 /* Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290A527D860CE005DAE71 /* Mock.swift */; };
FDC290AC27DB0B1C005DAE71 /* MockedExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290AB27DB0B1C005DAE71 /* MockedExtensions.swift */; };
FDC290AF27DFEE97005DAE71 /* TestTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290AE27DFEE97005DAE71 /* TestTransaction.swift */; };
FDC290B327DFF9F5005DAE71 /* TestOnionRequestAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290B227DFF9F5005DAE71 /* TestOnionRequestAPI.swift */; };
FDC290B727E00FDB005DAE71 /* TestGroupThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC290B627E00FDB005DAE71 /* TestGroupThread.swift */; };
FDC4380927B31D4E00C60D73 /* SOGSError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4380827B31D4E00C60D73 /* SOGSError.swift */; };
FDC4381527B329CE00C60D73 /* NonceGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4381427B329CE00C60D73 /* NonceGenerator.swift */; };
FDC4381727B32EC700C60D73 /* Personalization.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4381627B32EC700C60D73 /* Personalization.swift */; };
@ -776,13 +771,14 @@
FDC438B327BB15B400C60D73 /* ResponseInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438B227BB15B400C60D73 /* ResponseInfo.swift */; };
FDC438B927BB161E00C60D73 /* OnionRequestAPIVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438B827BB161E00C60D73 /* OnionRequestAPIVersion.swift */; };
FDC438BD27BB2AB400C60D73 /* Mockable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438BC27BB2AB400C60D73 /* Mockable.swift */; };
FDC438C127BB4E6800C60D73 /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438C027BB4E6800C60D73 /* Dependencies.swift */; };
FDC438C127BB4E6800C60D73 /* SMKDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438C027BB4E6800C60D73 /* SMKDependencies.swift */; };
FDC438C327BB512200C60D73 /* SodiumProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438C227BB512200C60D73 /* SodiumProtocols.swift */; };
FDC438C727BB6DF000C60D73 /* DirectMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438C627BB6DF000C60D73 /* DirectMessage.swift */; };
FDC438C927BB706500C60D73 /* SendDirectMessageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438C827BB706500C60D73 /* SendDirectMessageRequest.swift */; };
FDC438CB27BB7DB100C60D73 /* UpdateMessageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438CA27BB7DB100C60D73 /* UpdateMessageRequest.swift */; };
FDC438CD27BC641200C60D73 /* Set+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438CC27BC641200C60D73 /* Set+Utilities.swift */; };
FDC6D6F32860607300B04575 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7542807C4BB004C14C5 /* Environment.swift */; };
FDC6D7602862B3F600B04575 /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC6D75F2862B3F600B04575 /* Dependencies.swift */; };
FDCDB8DE2810F73B00352A0C /* Differentiable+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DD2810F73B00352A0C /* Differentiable+Utilities.swift */; };
FDCDB8E02811007F00352A0C /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DF2811007F00352A0C /* HomeViewModel.swift */; };
FDCDB8E42817819600352A0C /* (null) in Sources */ = {isa = PBXBuildFile; };
@ -1634,7 +1630,6 @@
FD078E4C27E17156000769AF /* MockOGMCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockOGMCache.swift; sourceTree = "<group>"; };
FD078E4E27E175F1000769AF /* DependencyExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependencyExtensions.swift; sourceTree = "<group>"; };
FD078E5127E1760A000769AF /* OGMDependencyExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OGMDependencyExtensions.swift; sourceTree = "<group>"; };
FD078E5727E1B831000769AF /* TestIncomingMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestIncomingMessage.swift; sourceTree = "<group>"; };
FD078E5927E29F09000769AF /* MockNonce16Generator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNonce16Generator.swift; sourceTree = "<group>"; };
FD078E5B27E29F78000769AF /* MockNonce24Generator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNonce24Generator.swift; sourceTree = "<group>"; };
FD09796827F6BEA700936362 /* SwarmSnode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwarmSnode.swift; sourceTree = "<group>"; };
@ -1781,14 +1776,10 @@
FDC2909927D71376005DAE71 /* NonceGeneratorSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonceGeneratorSpec.swift; sourceTree = "<group>"; };
FDC2909B27D713D2005DAE71 /* SodiumProtocolsSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SodiumProtocolsSpec.swift; sourceTree = "<group>"; };
FDC2909D27D85751005DAE71 /* OpenGroupManagerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupManagerSpec.swift; sourceTree = "<group>"; };
FDC2909F27D85826005DAE71 /* TestContactThread.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestContactThread.swift; sourceTree = "<group>"; };
FDC290A127D85890005DAE71 /* TestInteraction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestInteraction.swift; sourceTree = "<group>"; };
FDC290A527D860CE005DAE71 /* Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mock.swift; sourceTree = "<group>"; };
FDC290A727D9B46D005DAE71 /* NimbleExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NimbleExtensions.swift; sourceTree = "<group>"; };
FDC290AB27DB0B1C005DAE71 /* MockedExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockedExtensions.swift; sourceTree = "<group>"; };
FDC290AE27DFEE97005DAE71 /* TestTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestTransaction.swift; sourceTree = "<group>"; };
FDC290B227DFF9F5005DAE71 /* TestOnionRequestAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestOnionRequestAPI.swift; sourceTree = "<group>"; };
FDC290B627E00FDB005DAE71 /* TestGroupThread.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestGroupThread.swift; sourceTree = "<group>"; };
FDC4380827B31D4E00C60D73 /* SOGSError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSError.swift; sourceTree = "<group>"; };
FDC4381427B329CE00C60D73 /* NonceGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonceGenerator.swift; sourceTree = "<group>"; };
FDC4381627B32EC700C60D73 /* Personalization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Personalization.swift; sourceTree = "<group>"; };
@ -1817,12 +1808,13 @@
FDC438B227BB15B400C60D73 /* ResponseInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseInfo.swift; sourceTree = "<group>"; };
FDC438B827BB161E00C60D73 /* OnionRequestAPIVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnionRequestAPIVersion.swift; sourceTree = "<group>"; };
FDC438BC27BB2AB400C60D73 /* Mockable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mockable.swift; sourceTree = "<group>"; };
FDC438C027BB4E6800C60D73 /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = "<group>"; };
FDC438C027BB4E6800C60D73 /* SMKDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMKDependencies.swift; sourceTree = "<group>"; };
FDC438C227BB512200C60D73 /* SodiumProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SodiumProtocols.swift; sourceTree = "<group>"; };
FDC438C627BB6DF000C60D73 /* DirectMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectMessage.swift; sourceTree = "<group>"; };
FDC438C827BB706500C60D73 /* SendDirectMessageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendDirectMessageRequest.swift; sourceTree = "<group>"; };
FDC438CA27BB7DB100C60D73 /* UpdateMessageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateMessageRequest.swift; sourceTree = "<group>"; };
FDC438CC27BC641200C60D73 /* Set+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Set+Utilities.swift"; sourceTree = "<group>"; };
FDC6D75F2862B3F600B04575 /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = "<group>"; };
FDCDB8DD2810F73B00352A0C /* Differentiable+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Differentiable+Utilities.swift"; sourceTree = "<group>"; };
FDCDB8DF2811007F00352A0C /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
FDCDB8F02817ABE600352A0C /* Optional+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Utilities.swift"; sourceTree = "<group>"; };
@ -2395,6 +2387,7 @@
C33FDAA8255A57FF00E217F9 /* BuildConfiguration.swift */,
B8F5F58225EC94A6003BF8D4 /* Collection+Subscripting.swift */,
FDFD645A27F26D4600808CA1 /* Data+Utilities.swift */,
FDC6D75F2862B3F600B04575 /* Dependencies.swift */,
C3C2A5D52553860A00C340D1 /* Dictionary+Utilities.swift */,
B87EF18026377A1D00124B3C /* Features.swift */,
B8BC00BF257D90E30032E807 /* General.swift */,
@ -3058,7 +3051,7 @@
C33FDB75255A581000E217F9 /* AppReadiness.m */,
FDF0B7542807C4BB004C14C5 /* Environment.swift */,
FD859EF127BF6BA200510D0C /* Data+Utilities.swift */,
FDC438C027BB4E6800C60D73 /* Dependencies.swift */,
FDC438C027BB4E6800C60D73 /* SMKDependencies.swift */,
C38EF309255B6DBE007E1867 /* DeviceSleepManager.swift */,
C3BBE0C62554F1570050F1E3 /* FixedWidthInteger+BigEndian.swift */,
C3A71D0A2558989C0043A11F /* MessageWrapper.swift */,
@ -3869,11 +3862,6 @@
FD83B9D127D59495005E1583 /* MockUserDefaults.swift */,
FD078E4C27E17156000769AF /* MockOGMCache.swift */,
FDC290B227DFF9F5005DAE71 /* TestOnionRequestAPI.swift */,
FDC290AE27DFEE97005DAE71 /* TestTransaction.swift */,
FDC290B627E00FDB005DAE71 /* TestGroupThread.swift */,
FDC2909F27D85826005DAE71 /* TestContactThread.swift */,
FDC290A127D85890005DAE71 /* TestInteraction.swift */,
FD078E5727E1B831000769AF /* TestIncomingMessage.swift */,
FDC290AB27DB0B1C005DAE71 /* MockedExtensions.swift */,
FD078E4E27E175F1000769AF /* DependencyExtensions.swift */,
FD078E5127E1760A000769AF /* OGMDependencyExtensions.swift */,
@ -5034,6 +5022,7 @@
C32C600F256E07F5003C73A2 /* NSUserDefaults+OWS.m in Sources */,
C3D9E35E25675F640040E4F3 /* OWSFileSystem.m in Sources */,
FD09797D27FBDB2000936362 /* Notification+Utilities.swift in Sources */,
FDC6D7602862B3F600B04575 /* Dependencies.swift in Sources */,
C3C2AC2E2553CBEB00C340D1 /* String+Trimming.swift in Sources */,
C32C5B48256DC211003C73A2 /* NSNotificationCenter+OWS.m in Sources */,
FD17D7C727F5207C00122BE0 /* DatabaseMigrator+Utilities.swift in Sources */,
@ -5246,7 +5235,7 @@
FD09798127FCFEE800936362 /* SessionThread.swift in Sources */,
FD09C5EA282A1BB2000CE219 /* ThreadTypingIndicator.swift in Sources */,
FDF0B75E280AAF35004C14C5 /* Preferences.swift in Sources */,
FDC438C127BB4E6800C60D73 /* Dependencies.swift in Sources */,
FDC438C127BB4E6800C60D73 /* SMKDependencies.swift in Sources */,
FDC4383827B3863200C60D73 /* VersionResponse.swift in Sources */,
B806ECA126C4A7E4008BDA44 /* WebRTCSession+UI.swift in Sources */,
7BCD116C27016062006330F1 /* WebRTCSession+DataChannel.swift in Sources */,
@ -5464,10 +5453,8 @@
files = (
FDC290AC27DB0B1C005DAE71 /* MockedExtensions.swift in Sources */,
FD3C905C27E3FBEF00CD579F /* BatchRequestInfoSpec.swift in Sources */,
FD078E5827E1B831000769AF /* TestIncomingMessage.swift in Sources */,
FD859EFA27C2F5C500510D0C /* MockGenericHash.swift in Sources */,
FDC2909427D710B4005DAE71 /* SOGSEndpointSpec.swift in Sources */,
FDC290AF27DFEE97005DAE71 /* TestTransaction.swift in Sources */,
FDC290B327DFF9F5005DAE71 /* TestOnionRequestAPI.swift in Sources */,
FDC2909127D709CA005DAE71 /* SOGSMessageSpec.swift in Sources */,
FD3C906A27E417CE00CD579F /* SodiumUtilitiesSpec.swift in Sources */,
@ -5481,7 +5468,6 @@
FDC2909A27D71376005DAE71 /* NonceGeneratorSpec.swift in Sources */,
FD3C906427E4122F00CD579F /* RequestSpec.swift in Sources */,
FD078E4827E02561000769AF /* CommonMockedExtensions.swift in Sources */,
FDC290A027D85826005DAE71 /* TestContactThread.swift in Sources */,
FD859EF827C2F58900510D0C /* MockAeadXChaCha20Poly1305Ietf.swift in Sources */,
FDC2909827D7129B005DAE71 /* PersonalizationSpec.swift in Sources */,
FD859EF427C2F49200510D0C /* MockSodium.swift in Sources */,
@ -5496,7 +5482,6 @@
FDC2908B27D707F3005DAE71 /* SendMessageRequestSpec.swift in Sources */,
FDC290A827D9B46D005DAE71 /* NimbleExtensions.swift in Sources */,
FD3C906227E411AF00CD579F /* HeaderSpec.swift in Sources */,
FDC290B727E00FDB005DAE71 /* TestGroupThread.swift in Sources */,
FDC2908F27D70938005DAE71 /* SendDirectMessageRequestSpec.swift in Sources */,
FDC438BD27BB2AB400C60D73 /* Mockable.swift in Sources */,
FD859EF627C2F52C00510D0C /* MockSign.swift in Sources */,
@ -5505,7 +5490,6 @@
FD078E5A27E29F09000769AF /* MockNonce16Generator.swift in Sources */,
FD3C906D27E43C4B00CD579F /* MessageSenderEncryptionSpec.swift in Sources */,
FDC2908D27D70905005DAE71 /* UpdateMessageRequestSpec.swift in Sources */,
FDC290A227D85890005DAE71 /* TestInteraction.swift in Sources */,
FD078E5427E197CA000769AF /* OpenGroupManagerSpec.swift in Sources */,
FD3C906727E416AF00CD579F /* BlindedIdMappingSpec.swift in Sources */,
FD83B9D227D59495005E1583 /* MockUserDefaults.swift in Sources */,

View File

@ -386,7 +386,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
private func tryToReconnect() {
reconnectTimer?.invalidate()
guard Environment.shared.reachabilityManager.isReachable else {
guard Environment.shared?.reachabilityManager.isReachable == true else {
reconnectTimer = Timer.scheduledTimerOnMainThread(withTimeInterval: 5, repeats: false) { _ in
self.tryToReconnect()
}

View File

@ -1412,7 +1412,7 @@ extension ConversationVC:
let url: URL = URL(fileURLWithPath: directory).appendingPathComponent(fileName)
// Set up audio session
let isConfigured = audioSession.startAudioActivity(recordVoiceMessageActivity)
let isConfigured = (Environment.shared?.audioSession.startAudioActivity(recordVoiceMessageActivity) == true)
guard isConfigured else {
return cancelVoiceMessageRecording()
}
@ -1514,7 +1514,7 @@ extension ConversationVC:
func stopVoiceMessageRecording() {
audioRecorder?.stop()
audioSession.endAudioActivity(recordVoiceMessageActivity)
Environment.shared?.audioSession.endAudioActivity(recordVoiceMessageActivity)
}
// MARK: - Permissions
@ -1570,7 +1570,7 @@ extension ConversationVC:
// the picker view then will dismiss, too. The selection process cannot be finished
// this way. So we add a flag (isRequestingPermission) to prevent the ScreenLockUI
// from showing when we request the photo library permission.
Environment.shared.isRequestingPermission = true
Environment.shared?.isRequestingPermission = true
let appMode = AppModeManager.shared.currentAppMode
// FIXME: Rather than setting the app mode to light and then to dark again once we're done,
// it'd be better to just customize the appearance of the image picker. There doesn't currently
@ -1580,7 +1580,7 @@ extension ConversationVC:
DispatchQueue.main.async {
AppModeManager.shared.setCurrentAppMode(to: appMode)
}
Environment.shared.isRequestingPermission = false
Environment.shared?.isRequestingPermission = false
if [ PHAuthorizationStatus.authorized, PHAuthorizationStatus.limited ].contains(status) {
onAuthorized()
}

View File

@ -53,8 +53,6 @@ final class ConversationVC: BaseVC, OWSConversationSettingsViewDelegate, Convers
var scrollDistanceToBottomBeforeUpdate: CGFloat?
var baselineKeyboardHeight: CGFloat = 0
var audioSession: OWSAudioSession { Environment.shared.audioSession }
/// This flag is used to temporarily prevent the ConversationVC from becoming the first responder (primarily used with
/// custom transitions from preventing them from being buggy
var delayFirstResponder: Bool = false

View File

@ -41,18 +41,13 @@ class PhotoCapture: NSObject {
self.session = AVCaptureSession()
self.captureOutput = CaptureOutput()
}
// MARK: - Dependencies
var audioSession: OWSAudioSession {
return Environment.shared.audioSession
}
// MARK: -
var audioDeviceInput: AVCaptureDeviceInput?
func startAudioCapture() throws {
assertIsOnSessionQueue()
guard audioSession.startAudioActivity(recordingAudioActivity) else {
guard Environment.shared?.audioSession.startAudioActivity(recordingAudioActivity) == true else {
throw PhotoCaptureError.assertionError(description: "unable to capture audio activity")
}
@ -83,7 +78,7 @@ class PhotoCapture: NSObject {
}
session.removeInput(audioDeviceInput)
self.audioDeviceInput = nil
audioSession.endAudioActivity(recordingAudioActivity)
Environment.shared?.audioSession.endAudioActivity(recordingAudioActivity)
}
func startCapture() -> Promise<Void> {

View File

@ -85,8 +85,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
DeviceSleepManager.sharedInstance.removeBlock(blockObject: strongSelf)
AppVersion.sharedInstance().mainAppLaunchDidComplete()
Environment.shared.audioSession.setup()
Environment.shared.reachabilityManager.setup()
Environment.shared?.audioSession.setup()
Environment.shared?.reachabilityManager.setup()
GRDBStorage.shared.writeAsync { db in
// Disable the SAE until the main app has successfully completed launch process

View File

@ -44,10 +44,10 @@ public class AppEnvironment {
public func setup() {
// Hang certain singletons on Environment too.
Environment.shared.callManager.mutate {
Environment.shared?.callManager.mutate {
$0 = callManager
}
Environment.shared.notificationsManager.mutate {
Environment.shared?.notificationsManager.mutate {
$0 = notificationPresenter
}
setupLogFiles()

View File

@ -245,7 +245,7 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
- (BOOL)isRunningTests
{
return (NSProcessInfo.processInfo.environment[@"XCInjectBundleInto"] != nil);
return (NSProcessInfo.processInfo.environment[@"XCTestConfigurationFilePath"] != nil);
}
- (void)setNetworkActivityIndicatorVisible:(BOOL)value
@ -296,11 +296,6 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
backgroundTask = nil;
}
- (id<SSKKeychainStorage>)keychainStorage
{
return [SSKDefaultKeychainStorage shared];
}
- (NSString *)appDocumentDirectoryPath
{
NSFileManager *fileManager = [NSFileManager defaultManager];

View File

@ -50,7 +50,7 @@ public func requestLibraryPermissionIfNeeded(onAuthorized: @escaping () -> Void)
// the picker view then will dismiss, too. The selection process cannot be finished
// this way. So we add a flag (isRequestingPermission) to prevent the ScreenLockUI
// from showing when we request the photo library permission.
Environment.shared.isRequestingPermission = true
Environment.shared?.isRequestingPermission = true
let appMode = AppModeManager.shared.currentAppMode
// FIXME: Rather than setting the app mode to light and then to dark again once we're done,
// it'd be better to just customize the appearance of the image picker. There doesn't currently
@ -60,7 +60,7 @@ public func requestLibraryPermissionIfNeeded(onAuthorized: @escaping () -> Void)
DispatchQueue.main.async {
AppModeManager.shared.setCurrentAppMode(to: appMode)
}
Environment.shared.isRequestingPermission = false
Environment.shared?.isRequestingPermission = false
if [ PHAuthorizationStatus.authorized, PHAuthorizationStatus.limited ].contains(status) {
onAuthorized()
}

View File

@ -198,7 +198,6 @@ enum _001_InitialSetupMigration: Migration {
t.column(.authorId, .text)
.notNull()
.indexed() // Quicker querying
.references(Profile.self)
t.column(.variant, .integer).notNull()
t.column(.body, .text)
@ -369,6 +368,6 @@ enum _001_InitialSetupMigration: Migration {
t.column(.timestampMs, .integer).notNull()
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -55,6 +55,6 @@ enum _002_SetupStandardJobs: Migration {
)?.inserted(db)
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -79,7 +79,7 @@ enum _003_YDBToGRDBMigration: Migration {
legacyMigrations.insert(legacyMigration)
}
GRDBStorage.shared.update(progress: 0.01, for: self, in: target)
GRDBStorage.update(progress: 0.01, for: self, in: target)
// MARK: --Contacts
@ -95,7 +95,7 @@ enum _003_YDBToGRDBMigration: Migration {
forKey: SMKLegacy.blockedPhoneNumbersKey,
inCollection: SMKLegacy.blockListCollection
) as? [String] ?? [])
GRDBStorage.shared.update(progress: 0.02, for: self, in: target)
GRDBStorage.update(progress: 0.02, for: self, in: target)
// MARK: --Threads
@ -180,7 +180,7 @@ enum _003_YDBToGRDBMigration: Migration {
openGroupImage[thread.uniqueId] = transaction.object(forKey: openGroup.id, inCollection: SMKLegacy.openGroupImageCollection) as? Data
}
}
GRDBStorage.shared.update(progress: 0.04, for: self, in: target)
GRDBStorage.update(progress: 0.04, for: self, in: target)
// MARK: --Interactions
@ -229,7 +229,7 @@ enum _003_YDBToGRDBMigration: Migration {
rowIndex += 1
GRDBStorage.shared.update(
GRDBStorage.update(
progress: min(
interactionsCompleteProgress,
((rowIndex / roughNumRows) * (interactionsCompleteProgress - startProgress))
@ -238,7 +238,7 @@ enum _003_YDBToGRDBMigration: Migration {
in: target
)
}
GRDBStorage.shared.update(progress: interactionsCompleteProgress, for: self, in: target)
GRDBStorage.update(progress: interactionsCompleteProgress, for: self, in: target)
// MARK: --Attachments
@ -253,7 +253,7 @@ enum _003_YDBToGRDBMigration: Migration {
attachments[key] = attachment
}
GRDBStorage.shared.update(progress: 0.21, for: self, in: target)
GRDBStorage.update(progress: 0.21, for: self, in: target)
// MARK: --Read Receipts
@ -312,7 +312,7 @@ enum _003_YDBToGRDBMigration: Migration {
guard let job = object as? SMKLegacy._AttachmentDownloadJob else { return }
attachmentDownloadJobs.insert(job)
}
GRDBStorage.shared.update(progress: 0.22, for: self, in: target)
GRDBStorage.update(progress: 0.22, for: self, in: target)
// MARK: --Preferences
@ -371,7 +371,7 @@ enum _003_YDBToGRDBMigration: Migration {
.asType(NSNumber.self)?
.doubleValue)
.defaulting(to: (15 * 60))
GRDBStorage.shared.update(progress: 0.23, for: self, in: target)
GRDBStorage.update(progress: 0.23, for: self, in: target)
}
// We can't properly throw within the 'enumerateKeysAndObjects' block so have to throw here
@ -461,7 +461,7 @@ enum _003_YDBToGRDBMigration: Migration {
}
// Increment the progress for each contact
GRDBStorage.shared.update(
GRDBStorage.update(
progress: contactStartProgress + (progressPerContact * CGFloat(index + 1)),
for: self,
in: target
@ -1066,7 +1066,7 @@ enum _003_YDBToGRDBMigration: Migration {
}
// Increment the progress for each contact
GRDBStorage.shared.update(
GRDBStorage.update(
progress: (
threadInteractionsStartProgress +
(progressPerInteraction * (interactionCounter + 1))
@ -1337,7 +1337,7 @@ enum _003_YDBToGRDBMigration: Migration {
)?.inserted(db)
}
}
GRDBStorage.shared.update(progress: 0.99, for: self, in: target)
GRDBStorage.update(progress: 0.99, for: self, in: target)
// MARK: - Preferences
@ -1376,7 +1376,7 @@ enum _003_YDBToGRDBMigration: Migration {
db[.hasSentAMessage] = (legacyPreferences[SMKLegacy.preferencesKeyHasSentAMessageKey] as? Bool == true)
db[.isReadyForAppExtensions] = CurrentAppContext().appUserDefaults().bool(forKey: SMKLegacy.preferencesKeyIsReadyForAppExtensions)
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
// MARK: - Convenience

View File

@ -74,7 +74,7 @@ public extension BlindedIdLookup {
blindedId: String,
openGroupServer: String,
openGroupPublicKey: String,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) throws -> BlindedIdLookup {
var lookup: BlindedIdLookup = (try? BlindedIdLookup
.fetchOne(db, id: blindedId))

View File

@ -4,7 +4,7 @@ import Foundation
import GRDB
import SessionUtilitiesKit
public struct GroupMember: Codable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible {
public struct GroupMember: Codable, Equatable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible {
public static var databaseTableName: String { "groupMember" }
internal static let openGroupForeignKey = ForeignKey([Columns.groupId], to: [OpenGroup.Columns.threadId])
internal static let closedGroupForeignKey = ForeignKey([Columns.groupId], to: [ClosedGroup.Columns.threadId])

View File

@ -140,6 +140,7 @@ public struct OpenGroup: Codable, Identifiable, FetchableRecord, PersistableReco
public extension OpenGroup {
func with(
publicKey: String? = nil,
isActive: Bool? = nil,
name: String? = nil,
roomDescription: String? = nil,
@ -152,7 +153,7 @@ public extension OpenGroup {
return OpenGroup(
server: self.server,
roomToken: self.roomToken,
publicKey: self.publicKey,
publicKey: (publicKey ?? self.publicKey),
isActive: (isActive ?? self.isActive),
name: (name ?? self.name),
roomDescription: (roomDescription ?? self.roomDescription),
@ -184,7 +185,7 @@ extension OpenGroup: CustomStringConvertible, CustomDebugStringConvertible {
"roomToken: \"\(roomToken)\"",
"id: \"\(id)\"",
"publicKey: \"\(publicKey)\"",
"isActive: \"\(isActive)\"",
"isActive: \(isActive)",
"name: \"\(name)\"",
"roomDescription: \(roomDescription.map { "\"\($0)\"" } ?? "null")",
"imageId: \(imageId ?? "null")",

View File

@ -291,7 +291,7 @@ public extension Message {
openGroupServerPublicKey: String,
message: OpenGroupAPI.Message,
data: Data,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) throws -> ProcessedMessage? {
// Need a sender in order to process the message
guard let sender: String = message.sender else { return nil }
@ -325,7 +325,7 @@ public extension Message {
data: Data,
isOutgoing: Bool? = nil,
otherBlindedPublicKey: String? = nil,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) throws -> ProcessedMessage? {
// Note: The `posted` value is in seconds but all messages in the database use milliseconds for timestamps
let envelopeBuilder = SNProtoEnvelope.builder(type: .sessionMessage, timestamp: UInt64(floor(message.posted * 1000)))
@ -362,7 +362,7 @@ public extension Message {
isOutgoing: Bool? = nil,
otherBlindedPublicKey: String? = nil,
handleClosedGroupKeyUpdateMessages: Bool,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) throws -> ProcessedMessage? {
let (message, proto, threadId) = try MessageReceiver.parse(
db,

View File

@ -48,7 +48,7 @@ extension OpenGroupAPI.Message {
guard let sender: String = maybeSender, let data = Data(base64Encoded: base64EncodedData), let signature = Data(base64Encoded: base64EncodedSignature) else {
throw HTTP.Error.parsingFailed
}
guard let dependencies: Dependencies = decoder.userInfo[Dependencies.userInfoKey] as? Dependencies else {
guard let dependencies: SMKDependencies = decoder.userInfo[Dependencies.userInfoKey] as? SMKDependencies else {
throw HTTP.Error.parsingFailed
}

View File

@ -32,7 +32,7 @@ public enum OpenGroupAPI {
server: String,
hasPerformedInitialPoll: Bool,
timeSinceLastPoll: TimeInterval,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<[Endpoint: (OnionRequestResponseInfoType, Codable?)]> {
let lastInboxMessageId: Int64 = (try? OpenGroup
.select(.inboxLatestMessageId)
@ -146,7 +146,7 @@ public enum OpenGroupAPI {
_ db: Database,
server: String,
requests: [BatchRequestInfoType],
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<[Endpoint: (OnionRequestResponseInfoType, Codable?)]> {
let requestBody: BatchRequest = requests.map { $0.toSubRequest() }
let responseTypes = requests.map { $0.responseType }
@ -185,7 +185,7 @@ public enum OpenGroupAPI {
server: String,
requests: [BatchRequestInfoType],
authenticated: Bool = true,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<[Endpoint: (OnionRequestResponseInfoType, Codable?)]> {
let requestBody: BatchRequest = requests.map { $0.toSubRequest() }
let responseTypes = requests.map { $0.responseType }
@ -223,7 +223,7 @@ public enum OpenGroupAPI {
public static func capabilities(
_ db: Database,
server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Capabilities)> {
return OpenGroupAPI
.send(
@ -245,7 +245,7 @@ public enum OpenGroupAPI {
public static func rooms(
_ db: Database,
server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [Room])> {
return OpenGroupAPI
.send(
@ -269,7 +269,7 @@ public enum OpenGroupAPI {
_ db: Database,
for roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Room)> {
return OpenGroupAPI
.send(
@ -297,7 +297,7 @@ public enum OpenGroupAPI {
lastUpdated: Int64,
for roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, RoomPollInfo)> {
return OpenGroupAPI
.send(
@ -318,7 +318,7 @@ public enum OpenGroupAPI {
for roomToken: String,
on server: String,
authenticated: Bool = true,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(capabilities: (info: OnionRequestResponseInfoType, data: Capabilities), room: (info: OnionRequestResponseInfoType, data: Room))> {
let requestResponseType: [BatchRequestInfoType] = [
// Get the latest capabilities for the server (in case it's a new server or the cached ones are stale)
@ -389,7 +389,7 @@ public enum OpenGroupAPI {
whisperTo: String?,
whisperMods: Bool,
fileIds: [String]?,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Message)> {
guard let signResult: (publicKey: String, signature: Bytes) = sign(db, messageBytes: plaintext.bytes, for: server, fallbackSigningType: .standard, using: dependencies) else {
return Promise(error: Error.signingFailed)
@ -421,7 +421,7 @@ public enum OpenGroupAPI {
id: Int64,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Message)> {
return OpenGroupAPI
.send(
@ -445,7 +445,7 @@ public enum OpenGroupAPI {
fileIds: [Int64]?,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data?)> {
guard let signResult: (publicKey: String, signature: Bytes) = sign(db, messageBytes: plaintext.bytes, for: server, fallbackSigningType: .standard, using: dependencies) else {
return Promise(error: Error.signingFailed)
@ -473,7 +473,7 @@ public enum OpenGroupAPI {
id: Int64,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data?)> {
return OpenGroupAPI
.send(
@ -495,7 +495,7 @@ public enum OpenGroupAPI {
_ db: Database,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [Message])> {
return OpenGroupAPI
.send(
@ -518,7 +518,7 @@ public enum OpenGroupAPI {
messageId: Int64,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [Message])> {
return OpenGroupAPI
.send(
@ -541,7 +541,7 @@ public enum OpenGroupAPI {
seqNo: Int64,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [Message])> {
return OpenGroupAPI
.send(
@ -573,7 +573,7 @@ public enum OpenGroupAPI {
sessionId: String,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data?)> {
return OpenGroupAPI
.send(
@ -604,7 +604,7 @@ public enum OpenGroupAPI {
id: Int64,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<OnionRequestResponseInfoType> {
return OpenGroupAPI
.send(
@ -627,7 +627,7 @@ public enum OpenGroupAPI {
id: Int64,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<OnionRequestResponseInfoType> {
return OpenGroupAPI
.send(
@ -649,7 +649,7 @@ public enum OpenGroupAPI {
_ db: Database,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<OnionRequestResponseInfoType> {
return OpenGroupAPI
.send(
@ -672,7 +672,7 @@ public enum OpenGroupAPI {
fileName: String? = nil,
to roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, FileUploadResponse)> {
return OpenGroupAPI
.send(
@ -699,7 +699,7 @@ public enum OpenGroupAPI {
fileId: Int64,
from roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data)> {
return OpenGroupAPI
.send(
@ -728,7 +728,7 @@ public enum OpenGroupAPI {
public static func inbox(
_ db: Database,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [DirectMessage]?)> {
return OpenGroupAPI
.send(
@ -752,7 +752,7 @@ public enum OpenGroupAPI {
_ db: Database,
id: Int64,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [DirectMessage]?)> {
return OpenGroupAPI
.send(
@ -774,7 +774,7 @@ public enum OpenGroupAPI {
ciphertext: Data,
toInboxFor blindedSessionId: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, SendDirectMessageResponse)> {
return OpenGroupAPI
.send(
@ -801,7 +801,7 @@ public enum OpenGroupAPI {
public static func outbox(
_ db: Database,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [DirectMessage]?)> {
return OpenGroupAPI
.send(
@ -825,7 +825,7 @@ public enum OpenGroupAPI {
_ db: Database,
id: Int64,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, [DirectMessage]?)> {
return OpenGroupAPI
.send(
@ -878,7 +878,7 @@ public enum OpenGroupAPI {
for timeout: TimeInterval? = nil,
from roomTokens: [String]? = nil,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data?)> {
return OpenGroupAPI
.send(
@ -926,7 +926,7 @@ public enum OpenGroupAPI {
sessionId: String,
from roomTokens: [String]?,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data?)> {
return OpenGroupAPI
.send(
@ -1003,7 +1003,7 @@ public enum OpenGroupAPI {
visible: Bool,
for roomTokens: [String]?,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data?)> {
guard (moderator != nil && admin == nil) || (moderator == nil && admin != nil) else {
return Promise(error: HTTP.Error.generic)
@ -1035,7 +1035,7 @@ public enum OpenGroupAPI {
sessionId: String,
in roomToken: String,
on server: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<[OnionRequestResponseInfoType]> {
let banRequestBody: UserBanRequest = UserBanRequest(
rooms: [roomToken],
@ -1080,7 +1080,7 @@ public enum OpenGroupAPI {
messageBytes: Bytes,
for serverName: String,
fallbackSigningType signingType: SessionId.Prefix,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> (publicKey: String, signature: Bytes)? {
guard
let userEdKeyPair: Box.KeyPair = Identity.fetchUserEd25519KeyPair(db),
@ -1146,7 +1146,7 @@ public enum OpenGroupAPI {
request: URLRequest,
for serverName: String,
with serverPublicKey: String,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> URLRequest? {
guard let url: URL = request.url else { return nil }
@ -1204,7 +1204,7 @@ public enum OpenGroupAPI {
_ db: Database,
request: Request<T, Endpoint>,
authenticated: Bool = true,
using dependencies: Dependencies = Dependencies()
using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<(OnionRequestResponseInfoType, Data?)> {
let urlRequest: URLRequest

View File

@ -67,7 +67,7 @@ public final class OpenGroupManager: NSObject {
public func startPolling(using dependencies: OGMDependencies = OGMDependencies()) {
guard !dependencies.cache.isPolling else { return }
let servers: Set<String> = GRDBStorage.shared
let servers: Set<String> = dependencies.storage
.read { db in
// The default room promise creates an OpenGroup with an empty `roomToken` value,
// we don't want to start a poller for this as the user hasn't actually joined a room
@ -85,11 +85,16 @@ public final class OpenGroupManager: NSObject {
cache.isPolling = true
cache.pollers = servers
.reduce(into: [:]) { result, server in
result[server]?.stop() // Should never occur
result[server] = OpenGroupAPI.Poller(for: server)
result[server]?.startIfNeeded(using: dependencies)
result[server.lowercased()]?.stop() // Should never occur
result[server.lowercased()] = OpenGroupAPI.Poller(for: server.lowercased())
}
// Note: We loop separately here because when the cache is mocked-out for tests it
// doesn't actually store the value (meaning the pollers won't be started), but if
// we do it in the 'reduce' function, the 'reduce' result will actually store the
// poller value resulting in a bunch of OpenGroup pollers running in a way that can't
// be stopped during unit tests
cache.pollers.forEach { _, poller in poller.startIfNeeded(using: dependencies) }
}
}
@ -104,13 +109,13 @@ public final class OpenGroupManager: NSObject {
// MARK: - Adding & Removing
public func hasExistingOpenGroup(_ db: Database, roomToken: String, server: String, publicKey: String, dependencies: OGMDependencies = OGMDependencies()) -> Bool {
guard let serverUrl: URL = URL(string: server) else { return false }
guard let serverUrl: URL = URL(string: server.lowercased()) else { return false }
let serverHost: String = (serverUrl.host ?? server)
let serverHost: String = (serverUrl.host ?? server.lowercased())
let serverPort: String = (serverUrl.port.map { ":\($0)" } ?? "")
let defaultServerHost: String = OpenGroupAPI.defaultServer.substring(from: "http://".count)
var serverOptions: Set<String> = Set([
server,
server.lowercased(),
"\(serverHost)\(serverPort)",
"http://\(serverHost)\(serverPort)",
"https://\(serverHost)\(serverPort)"
@ -252,13 +257,13 @@ public final class OpenGroupManager: NSObject {
// Note: The default room promise creates an OpenGroup with an empty `roomToken` value,
// we don't want to start a poller for this as the user hasn't actually joined a room
let numActiveRooms: Int = (try? OpenGroup
.filter(OpenGroup.Columns.server == server)
.filter(OpenGroup.Columns.server == server?.lowercased())
.filter(OpenGroup.Columns.roomToken != "")
.filter(OpenGroup.Columns.isActive)
.fetchCount(db))
.defaulting(to: 1)
if numActiveRooms == 1, let server: String = server {
if numActiveRooms == 1, let server: String = server?.lowercased() {
let poller = dependencies.cache.pollers[server]
poller?.stop()
dependencies.mutableCache.mutate { $0.pollers[server] = nil }
@ -297,13 +302,13 @@ public final class OpenGroupManager: NSObject {
) {
// Remove old capabilities first
_ = try? Capability
.filter(Capability.Columns.openGroupServer == server)
.filter(Capability.Columns.openGroupServer == server.lowercased())
.deleteAll(db)
// Then insert the new capabilities (both present and missing)
capabilities.capabilities.forEach { capability in
_ = try? Capability(
openGroupServer: server,
openGroupServer: server.lowercased(),
variant: Capability.Variant(from: capability.rawValue),
isMissing: false
)
@ -311,7 +316,7 @@ public final class OpenGroupManager: NSObject {
}
capabilities.missing?.forEach { capability in
_ = try? Capability(
openGroupServer: server,
openGroupServer: server.lowercased(),
variant: Capability.Variant(from: capability.rawValue),
isMissing: true
)
@ -336,6 +341,7 @@ public final class OpenGroupManager: NSObject {
let updatedOpenGroup: OpenGroup = try openGroup
.with(
publicKey: maybePublicKey,
name: pollInfo.details?.name,
roomDescription: pollInfo.details?.roomDescription,
imageId: pollInfo.details?.imageId.map { "\($0)" },
@ -369,10 +375,10 @@ public final class OpenGroupManager: NSObject {
db.afterNextTransactionCommit { db in
// Start the poller if needed
if dependencies.cache.pollers[server] == nil {
if dependencies.cache.pollers[server.lowercased()] == nil {
dependencies.mutableCache.mutate {
$0.pollers[server] = OpenGroupAPI.Poller(for: server)
$0.pollers[server]?.startIfNeeded(using: dependencies)
$0.pollers[server.lowercased()] = OpenGroupAPI.Poller(for: server.lowercased())
$0.pollers[server.lowercased()]?.startIfNeeded(using: dependencies)
}
}
@ -507,7 +513,7 @@ public final class OpenGroupManager: NSObject {
) {
// Don't need to do anything if we have no messages (it's a valid case)
guard !messages.isEmpty else { return }
guard let openGroup: OpenGroup = try? OpenGroup.filter(OpenGroup.Columns.server == server).fetchOne(db) else {
guard let openGroup: OpenGroup = try? OpenGroup.filter(OpenGroup.Columns.server == server.lowercased()).fetchOne(db) else {
SNLog("Couldn't receive inbox message.")
return
}
@ -522,12 +528,12 @@ public final class OpenGroupManager: NSObject {
// Update the 'latestMessageId' value
if fromOutbox {
_ = try? OpenGroup
.filter(OpenGroup.Columns.server == server)
.filter(OpenGroup.Columns.server == server.lowercased())
.updateAll(db, OpenGroup.Columns.outboxLatestMessageId.set(to: latestMessageId))
}
else {
_ = try? OpenGroup
.filter(OpenGroup.Columns.server == server)
.filter(OpenGroup.Columns.server == server.lowercased())
.updateAll(db, OpenGroup.Columns.inboxLatestMessageId.set(to: latestMessageId))
}
@ -644,7 +650,7 @@ public final class OpenGroupManager: NSObject {
// Conveniently the logic for these different cases works in order so we can fallthrough each
// case with only minor efficiency losses
let userPublicKey: String = getUserHexEncodedPublicKey(db)
let userPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies)
switch sessionId.prefix {
case .standard:
@ -796,7 +802,7 @@ public final class OpenGroupManager: NSObject {
let updateInterval: TimeInterval = (7 * 24 * 60 * 60)
if
server == OpenGroupAPI.defaultServer,
server.lowercased() == OpenGroupAPI.defaultServer,
timeSinceLastUpdate < updateInterval,
let data = try? OpenGroup
.select(.imageData)
@ -805,7 +811,7 @@ public final class OpenGroupManager: NSObject {
.fetchOne(db)
{ return Promise.value(data) }
if let promise = dependencies.cache.groupImagePromises["\(server).\(roomToken)"] {
if let promise = dependencies.cache.groupImagePromises[threadId] {
return promise
}
@ -814,7 +820,7 @@ public final class OpenGroupManager: NSObject {
// Trigger the download on a background queue
DispatchQueue.global(qos: .background).async {
dependencies.storage
.writeAsync { db in
.read { db in
OpenGroupAPI
.downloadFile(
db,
@ -824,8 +830,8 @@ public final class OpenGroupManager: NSObject {
using: dependencies
)
}
.done(on: OpenGroupAPI.workQueue) { _, imageData in
if server == OpenGroupAPI.defaultServer {
.done { _, imageData in
if server.lowercased() == OpenGroupAPI.defaultServer {
dependencies.storage.write { db in
_ = try OpenGroup
.filter(id: threadId)
@ -841,7 +847,7 @@ public final class OpenGroupManager: NSObject {
}
dependencies.mutableCache.mutate { cache in
cache.groupImagePromises["\(server).\(roomToken)"] = promise
cache.groupImagePromises[threadId] = promise
}
return promise
@ -880,7 +886,7 @@ public final class OpenGroupManager: NSObject {
// MARK: - OGMDependencies
extension OpenGroupManager {
public class OGMDependencies: Dependencies {
public class OGMDependencies: SMKDependencies {
internal var _mutableCache: Atomic<OGMCacheType>?
public var mutableCache: Atomic<OGMCacheType> {
get { Dependencies.getValueSettingIfNull(&_mutableCache) { OpenGroupManager.shared.mutableCache } }

View File

@ -49,7 +49,7 @@ extension MessageReceiver {
if let interaction: Interaction = try MessageReceiver.insertCallInfoMessage(db, for: message, state: .missed) {
let thread: SessionThread = try SessionThread.fetchOrCreate(db, id: sender, variant: .contact)
Environment.shared.notificationsManager.wrappedValue?
Environment.shared?.notificationsManager.wrappedValue?
.notifyUser(
db,
forIncomingCall: interaction,
@ -63,7 +63,7 @@ extension MessageReceiver {
if let interaction: Interaction = try MessageReceiver.insertCallInfoMessage(db, for: message, state: .permissionDenied) {
let thread: SessionThread = try SessionThread.fetchOrCreate(db, id: sender, variant: .contact)
Environment.shared.notificationsManager.wrappedValue?
Environment.shared?.notificationsManager.wrappedValue?
.notifyUser(
db,
forIncomingCall: interaction,
@ -81,7 +81,7 @@ extension MessageReceiver {
}
// Ensure we have a call manager before continuing
guard let callManager: CallManagerProtocol = Environment.shared.callManager.wrappedValue else { return }
guard let callManager: CallManagerProtocol = Environment.shared?.callManager.wrappedValue else { return }
// Ignore pre offer message after the same call instance has been generated
if let currentCall: CurrentCallProtocol = callManager.currentCall, currentCall.uuid == message.uuid {
@ -109,7 +109,7 @@ extension MessageReceiver {
// Ensure we have a call manager before continuing
guard
let callManager: CallManagerProtocol = Environment.shared.callManager.wrappedValue,
let callManager: CallManagerProtocol = Environment.shared?.callManager.wrappedValue,
let currentCall: CurrentCallProtocol = callManager.currentCall,
currentCall.uuid == message.uuid,
let sdp: String = message.sdps.first
@ -125,7 +125,7 @@ extension MessageReceiver {
guard
let currentWebRTCSession: WebRTCSession = WebRTCSession.current,
currentWebRTCSession.uuid == message.uuid,
let callManager: CallManagerProtocol = Environment.shared.callManager.wrappedValue,
let callManager: CallManagerProtocol = Environment.shared?.callManager.wrappedValue,
var currentCall: CurrentCallProtocol = callManager.currentCall,
currentCall.uuid == message.uuid,
let sender: String = message.sender
@ -151,7 +151,7 @@ extension MessageReceiver {
guard
WebRTCSession.current?.uuid == message.uuid,
let callManager: CallManagerProtocol = Environment.shared.callManager.wrappedValue,
let callManager: CallManagerProtocol = Environment.shared?.callManager.wrappedValue,
let currentCall: CurrentCallProtocol = callManager.currentCall,
currentCall.uuid == message.uuid,
let sender: String = message.sender

View File

@ -140,7 +140,7 @@ extension MessageReceiver {
ClosedGroupPoller.shared.startPolling(for: groupPublicKey)
// Notify the PN server
let _ = PushNotificationAPI.performOperation(.subscribe, for: groupPublicKey, publicKey: getUserHexEncodedPublicKey())
let _ = PushNotificationAPI.performOperation(.subscribe, for: groupPublicKey, publicKey: getUserHexEncodedPublicKey(db))
}
/// Extracts and adds the new encryption key pair to our list of key pairs if there is one for our public key, AND the message was

View File

@ -8,9 +8,9 @@ extension MessageReceiver {
internal static func handleMessageRequestResponse(
_ db: Database,
message: MessageRequestResponse,
dependencies: Dependencies
dependencies: SMKDependencies
) throws {
let userPublicKey = getUserHexEncodedPublicKey(db)
let userPublicKey = getUserHexEncodedPublicKey(db, dependencies: dependencies)
var hadBlindedContact: Bool = false
// Ignore messages which were sent from the current user

View File

@ -46,7 +46,7 @@ extension MessageReceiver {
}
// Store the message variant so we can run variant-specific behaviours
let currentUserPublicKey: String = getUserHexEncodedPublicKey(db)
let currentUserPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies)
let thread: SessionThread = try SessionThread
.fetchOrCreate(db, id: threadInfo.id, variant: threadInfo.variant)
let variant: Interaction.Variant = {
@ -273,7 +273,7 @@ extension MessageReceiver {
guard variant == .standardIncoming else { return interactionId }
// Use the same identifier for notifications when in backgroud polling to prevent spam
Environment.shared.notificationsManager.wrappedValue?
Environment.shared?.notificationsManager.wrappedValue?
.notifyUser(
db,
for: interaction,

View File

@ -11,7 +11,7 @@ extension MessageSender {
public static var distributingKeyPairs: Atomic<[String: [ClosedGroupKeyPair]]> = Atomic([:])
public static func createClosedGroup(_ db: Database, name: String, members: Set<String>) throws -> Promise<SessionThread> {
let userPublicKey: String = getUserHexEncodedPublicKey()
let userPublicKey: String = getUserHexEncodedPublicKey(db)
var members: Set<String> = members
// Generate the group's public key

View File

@ -8,7 +8,7 @@ import Curve25519Kit
import SessionUtilitiesKit
extension MessageReceiver {
internal static func decryptWithSessionProtocol(ciphertext: Data, using x25519KeyPair: Box.KeyPair, dependencies: Dependencies = Dependencies()) throws -> (plaintext: Data, senderX25519PublicKey: String) {
internal static func decryptWithSessionProtocol(ciphertext: Data, using x25519KeyPair: Box.KeyPair, dependencies: SMKDependencies = SMKDependencies()) throws -> (plaintext: Data, senderX25519PublicKey: String) {
let recipientX25519PrivateKey = x25519KeyPair.secretKey
let recipientX25519PublicKey = x25519KeyPair.publicKey
let signatureSize = dependencies.sign.Bytes
@ -46,7 +46,7 @@ extension MessageReceiver {
return (Data(plaintext), SessionId(.standard, publicKey: senderX25519PublicKey).hexString)
}
internal static func decryptWithSessionBlindingProtocol(data: Data, isOutgoing: Bool, otherBlindedPublicKey: String, with openGroupPublicKey: String, userEd25519KeyPair: Box.KeyPair, using dependencies: Dependencies = Dependencies()) throws -> (plaintext: Data, senderX25519PublicKey: String) {
internal static func decryptWithSessionBlindingProtocol(data: Data, isOutgoing: Bool, otherBlindedPublicKey: String, with openGroupPublicKey: String, userEd25519KeyPair: Box.KeyPair, using dependencies: SMKDependencies = SMKDependencies()) throws -> (plaintext: Data, senderX25519PublicKey: String) {
/// Ensure the data is at least long enough to have the required components
guard
data.count > (dependencies.nonceGenerator24.NonceBytes + 2),

View File

@ -18,9 +18,9 @@ public enum MessageReceiver {
openGroupServerPublicKey: String?,
isOutgoing: Bool? = nil,
otherBlindedPublicKey: String? = nil,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) throws -> (Message, SNProtoContent, String) {
let userPublicKey: String = getUserHexEncodedPublicKey(db)
let userPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies)
let isOpenGroupMessage: Bool = (openGroupId != nil)
// Decrypt the contents
@ -182,7 +182,7 @@ public enum MessageReceiver {
associatedWithProto proto: SNProtoContent,
openGroupId: String?,
isBackgroundPoll: Bool,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) throws {
switch message {
case let message as ReadReceipt:
@ -282,7 +282,7 @@ public enum MessageReceiver {
sentTimestamp: TimeInterval,
dependencies: Dependencies = Dependencies()
) throws {
let isCurrentUser = (publicKey == getUserHexEncodedPublicKey(db))
let isCurrentUser = (publicKey == getUserHexEncodedPublicKey(db, dependencies: dependencies))
var profile: Profile = Profile.fetchOrCreate(id: publicKey)
// Name

View File

@ -5,7 +5,11 @@ import Sodium
import SessionUtilitiesKit
extension MessageSender {
internal static func encryptWithSessionProtocol(_ plaintext: Data, for recipientHexEncodedX25519PublicKey: String, using dependencies: Dependencies = Dependencies()) throws -> Data {
internal static func encryptWithSessionProtocol(
_ plaintext: Data,
for recipientHexEncodedX25519PublicKey: String,
using dependencies: SMKDependencies = SMKDependencies()
) throws -> Data {
guard let userEd25519KeyPair: Box.KeyPair = dependencies.storage.read({ db in Identity.fetchUserEd25519KeyPair(db) }) else {
throw MessageSenderError.noUserED25519KeyPair
}
@ -25,7 +29,12 @@ extension MessageSender {
return Data(ciphertext)
}
internal static func encryptWithSessionBlindingProtocol(_ plaintext: Data, for recipientBlindedId: String, openGroupPublicKey: String, using dependencies: Dependencies = Dependencies()) throws -> Data {
internal static func encryptWithSessionBlindingProtocol(
_ plaintext: Data,
for recipientBlindedId: String,
openGroupPublicKey: String,
using dependencies: SMKDependencies = SMKDependencies()
) throws -> Data {
guard SessionId.Prefix(from: recipientBlindedId) == .blinded else { throw MessageSenderError.signingFailed }
guard let userEd25519KeyPair: Box.KeyPair = dependencies.storage.read({ db in Identity.fetchUserEd25519KeyPair(db) }) else {
throw MessageSenderError.noUserED25519KeyPair

View File

@ -306,7 +306,7 @@ public final class MessageSender {
message: Message,
to destination: Message.Destination,
interactionId: Int64?,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) -> Promise<Void> {
let (promise, seal) = Promise<Void>.pending()
let threadId: String
@ -445,10 +445,10 @@ public final class MessageSender {
message: Message,
to destination: Message.Destination,
interactionId: Int64?,
dependencies: Dependencies = Dependencies()
dependencies: SMKDependencies = SMKDependencies()
) -> Promise<Void> {
let (promise, seal) = Promise<Void>.pending()
let userPublicKey: String = getUserHexEncodedPublicKey(db)
let userPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies)
guard case .openGroupInbox(let server, let openGroupPublicKey, let recipientBlindedPublicKey) = destination else {
preconditionFailure()
@ -615,7 +615,7 @@ public final class MessageSender {
// it's a visible message or an expiration timer update
// the destination was a contact
// we didn't sync it already
let userPublicKey = getUserHexEncodedPublicKey()
let userPublicKey = getUserHexEncodedPublicKey(db)
if case .contact(let publicKey) = destination, !isSyncMessage {
if let message = message as? VisibleMessage { message.syncTarget = publicKey }
if let message = message as? ExpirationTimerUpdate { message.syncTarget = publicKey }

View File

@ -56,7 +56,7 @@ extension OpenGroupAPI {
promise.retainUntilComplete()
Threading.pollerQueue.async {
GRDBStorage.shared
dependencies.storage
.read { db in
OpenGroupAPI
.poll(

View File

@ -4,7 +4,7 @@ import Foundation
import SessionUtilitiesKit
public class Environment {
public static var shared: Environment!
public static var shared: Environment?
public let reachabilityManager: SSKReachabilityManager
@ -55,8 +55,8 @@ public class Environment {
public class SMKEnvironment: NSObject {
@objc public static let shared: SMKEnvironment = SMKEnvironment()
@objc public var audioSession: OWSAudioSession { Environment.shared.audioSession }
@objc public var windowManager: OWSWindowManager { Environment.shared.windowManager }
@objc public var audioSession: OWSAudioSession? { Environment.shared?.audioSession }
@objc public var windowManager: OWSWindowManager? { Environment.shared?.windowManager }
@objc public var isRequestingPermission: Bool { Environment.shared.isRequestingPermission }
@objc public var isRequestingPermission: Bool { (Environment.shared?.isRequestingPermission == true) }
}

View File

@ -18,13 +18,7 @@ public class AudioActivity: NSObject {
}
deinit {
audioSession.ensureAudioSessionActivationStateAfterDelay()
}
// MARK: Dependencies
var audioSession: OWSAudioSession {
return Environment.shared.audioSession
Environment.shared?.audioSession.ensureAudioSessionActivationStateAfterDelay()
}
// MARK:
@ -44,10 +38,6 @@ public class OWSAudioSession: NSObject {
// MARK: Dependencies
var proximityMonitoringManager: OWSProximityMonitoringManager {
return Environment.shared.proximityMonitoringManager
}
private let avAudioSession = AVAudioSession.sharedInstance()
private let device = UIDevice.current
@ -94,9 +84,9 @@ public class OWSAudioSession: NSObject {
func ensureAudioCategory() throws {
if aggregateBehaviors.contains(.audioMessagePlayback) {
self.proximityMonitoringManager.add(lifetime: self)
Environment.shared?.proximityMonitoringManager.add(lifetime: self)
} else {
self.proximityMonitoringManager.remove(lifetime: self)
Environment.shared?.proximityMonitoringManager.remove(lifetime: self)
}
if aggregateBehaviors.contains(.call) {

View File

@ -5,25 +5,13 @@ import Sodium
import SessionSnodeKit
import SessionUtilitiesKit
public class Dependencies {
public class SMKDependencies: Dependencies {
internal var _onionApi: OnionRequestAPIType.Type?
public var onionApi: OnionRequestAPIType.Type {
get { Dependencies.getValueSettingIfNull(&_onionApi) { OnionRequestAPI.self } }
set { _onionApi = newValue }
}
internal var _generalCache: Atomic<GeneralCacheType>?
public var generalCache: Atomic<GeneralCacheType> {
get { Dependencies.getValueSettingIfNull(&_generalCache) { General.cache } }
set { _generalCache = newValue }
}
internal var _storage: GRDBStorage?
public var storage: GRDBStorage {
get { Dependencies.getValueSettingIfNull(&_storage) { GRDBStorage.shared } }
set { _storage = newValue }
}
internal var _sodium: SodiumType?
public var sodium: SodiumType {
get { Dependencies.getValueSettingIfNull(&_sodium) { Sodium() } }
@ -72,18 +60,6 @@ public class Dependencies {
set { _nonceGenerator24 = newValue }
}
internal var _standardUserDefaults: UserDefaultsType?
public var standardUserDefaults: UserDefaultsType {
get { Dependencies.getValueSettingIfNull(&_standardUserDefaults) { UserDefaults.standard } }
set { _standardUserDefaults = newValue }
}
internal var _date: Date?
public var date: Date {
get { Dependencies.getValueSettingIfNull(&_date) { Date() } }
set { _date = newValue }
}
// MARK: - Initialization
public init(
@ -102,8 +78,6 @@ public class Dependencies {
date: Date? = nil
) {
_onionApi = onionApi
_generalCache = generalCache
_storage = storage
_sodium = sodium
_box = box
_genericHash = genericHash
@ -112,19 +86,12 @@ public class Dependencies {
_ed25519 = ed25519
_nonceGenerator16 = nonceGenerator16
_nonceGenerator24 = nonceGenerator24
_standardUserDefaults = standardUserDefaults
_date = date
}
// MARK: - Convenience
internal static func getValueSettingIfNull<T>(_ maybeValue: inout T?, _ valueGenerator: () -> T) -> T {
guard let value: T = maybeValue else {
let value: T = valueGenerator()
maybeValue = value
return value
}
return value
super.init(
generalCache: generalCache,
storage: storage,
standardUserDefaults: standardUserDefaults,
date: date
)
}
}

View File

@ -18,7 +18,7 @@ class SOGSMessageSpec: QuickSpec {
var decoder: JSONDecoder!
var mockSign: MockSign!
var mockEd25519: MockEd25519!
var dependencies: Dependencies!
var dependencies: SMKDependencies!
beforeEach {
messageJson = """
@ -37,7 +37,7 @@ class SOGSMessageSpec: QuickSpec {
messageData = messageJson.data(using: .utf8)!
mockSign = MockSign()
mockEd25519 = MockEd25519()
dependencies = Dependencies(
dependencies = SMKDependencies(
sign: mockSign,
ed25519: mockEd25519
)

View File

@ -23,7 +23,7 @@ class OpenGroupAPISpec: QuickSpec {
var mockEd25519: MockEd25519!
var mockNonce16Generator: MockNonce16Generator!
var mockNonce24Generator: MockNonce24Generator!
var dependencies: Dependencies!
var dependencies: SMKDependencies!
var response: (OnionRequestResponseInfoType, Codable)? = nil
var pollResponse: [OpenGroupAPI.Endpoint: (OnionRequestResponseInfoType, Codable?)]?
@ -33,7 +33,13 @@ class OpenGroupAPISpec: QuickSpec {
// MARK: - Configuration
beforeEach {
mockStorage = GRDBStorage(customWriter: DatabaseQueue())
mockStorage = GRDBStorage(
customWriter: DatabaseQueue(),
customMigrations: [
SNUtilitiesKit.migrations(),
SNMessagingKit.migrations()
]
)
mockSodium = MockSodium()
mockAeadXChaCha20Poly1305Ietf = MockAeadXChaCha20Poly1305Ietf()
mockSign = MockSign()
@ -41,7 +47,7 @@ class OpenGroupAPISpec: QuickSpec {
mockNonce16Generator = MockNonce16Generator()
mockNonce24Generator = MockNonce24Generator()
mockEd25519 = MockEd25519()
dependencies = Dependencies(
dependencies = SMKDependencies(
onionApi: TestOnionRequestAPI.self,
storage: mockStorage,
sodium: mockSodium,
@ -204,9 +210,9 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (pollResponse?[.capabilities]?.0 as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.urlString).to(equal("testServer/batch"))
expect(requestData?.urlString).to(equal("testserver/batch"))
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.publicKey).to(equal("88672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
}
@ -840,8 +846,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("GET"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/capabilities"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/capabilities"))
}
}
@ -911,8 +917,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("GET"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/rooms"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/rooms"))
}
}
@ -1005,8 +1011,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.capabilities.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/sequence"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/sequence"))
}
}
@ -1641,8 +1647,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("GET"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/message/123"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/message/123"))
}
}
@ -1693,8 +1699,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate signature headers
let requestData: TestOnionRequestAPI.RequestData? = (response?.0 as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("PUT"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/message/123"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/message/123"))
}
context("when unblinded") {
@ -1717,7 +1723,7 @@ class OpenGroupAPISpec: QuickSpec {
plaintext: "test".data(using: .utf8)!,
fileIds: nil,
in: "testRoom",
on: "testServer",
on: "testserver",
using: dependencies
)
}
@ -1861,7 +1867,7 @@ class OpenGroupAPISpec: QuickSpec {
plaintext: "test".data(using: .utf8)!,
fileIds: nil,
in: "testRoom",
on: "testServer",
on: "testserver",
using: dependencies
)
}
@ -1974,7 +1980,7 @@ class OpenGroupAPISpec: QuickSpec {
plaintext: "test".data(using: .utf8)!,
fileIds: nil,
in: "testRoom",
on: "testServer",
on: "testserver",
using: dependencies
)
}
@ -2027,8 +2033,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("DELETE"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/message/123"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/message/123"))
}
}
@ -2054,7 +2060,7 @@ class OpenGroupAPISpec: QuickSpec {
db,
sessionId: "testUserId",
in: "testRoom",
on: "testServer",
on: "testserver",
using: dependencies
)
}
@ -2072,8 +2078,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("DELETE"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/all/testUserId"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/all/testUserId"))
}
}
@ -2113,8 +2119,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/pin/123"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/pin/123"))
}
}
@ -2152,8 +2158,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/unpin/123"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/unpin/123"))
}
}
@ -2190,8 +2196,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/unpin/all"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/unpin/all"))
}
}
@ -2231,8 +2237,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate signature headers
let requestData: TestOnionRequestAPI.RequestData? = (response?.0 as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/file"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/file"))
}
it("doesn't add a fileName to the content-disposition header when not provided") {
@ -2342,8 +2348,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate signature headers
let requestData: TestOnionRequestAPI.RequestData? = (response?.0 as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("GET"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/room/testRoom/file/1"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/room/testRoom/file/1"))
}
}
@ -2403,8 +2409,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate signature headers
let requestData: TestOnionRequestAPI.RequestData? = (response?.0 as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/inbox/testUserId"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/inbox/testUserId"))
}
}
@ -2451,8 +2457,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/user/testUserId/ban"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/user/testUserId/ban"))
}
it("does a global ban if no room tokens are provided") {
@ -2560,8 +2566,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/user/testUserId/unban"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/user/testUserId/unban"))
}
it("does a global ban if no room tokens are provided") {
@ -2670,8 +2676,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.info as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/user/testUserId/moderator"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/user/testUserId/moderator"))
}
it("does a global update if no room tokens are provided") {
@ -2832,8 +2838,8 @@ class OpenGroupAPISpec: QuickSpec {
// Validate request data
let requestData: TestOnionRequestAPI.RequestData? = (response?.first as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.httpMethod).to(equal("POST"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.urlString).to(equal("testServer/sequence"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.urlString).to(equal("testserver/sequence"))
}
it("bans the user from the specified room rather than globally") {
@ -3001,13 +3007,13 @@ class OpenGroupAPISpec: QuickSpec {
// Validate signature headers
let requestData: TestOnionRequestAPI.RequestData? = (response?.0 as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.urlString).to(equal("testServer/rooms"))
expect(requestData?.urlString).to(equal("testserver/rooms"))
expect(requestData?.httpMethod).to(equal("GET"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.publicKey).to(equal("88672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
expect(requestData?.headers).to(haveCount(4))
expect(requestData?.headers[Header.sogsPubKey.rawValue])
.to(equal("0088672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
.to(equal("00bac6e71efd7dfa4a83c98ed24f254ab2c267f9ccdb172a5280a0444ad24e89cc"))
expect(requestData?.headers[Header.sogsTimestamp.rawValue]).to(equal("1234567890"))
expect(requestData?.headers[Header.sogsNonce.rawValue]).to(equal("pK6YRtQApl4NhECGizF0Cg=="))
expect(requestData?.headers[Header.sogsSignature.rawValue]).to(equal("TestSignature".bytes.toBase64()))
@ -3071,9 +3077,9 @@ class OpenGroupAPISpec: QuickSpec {
// Validate signature headers
let requestData: TestOnionRequestAPI.RequestData? = (response?.0 as? TestOnionRequestAPI.ResponseInfo)?.requestData
expect(requestData?.urlString).to(equal("testServer/rooms"))
expect(requestData?.urlString).to(equal("testserver/rooms"))
expect(requestData?.httpMethod).to(equal("GET"))
expect(requestData?.server).to(equal("testServer"))
expect(requestData?.server).to(equal("testserver"))
expect(requestData?.publicKey).to(equal("88672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
expect(requestData?.headers).to(haveCount(4))
expect(requestData?.headers[Header.sogsPubKey.rawValue]).to(equal("1588672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))

File diff suppressed because it is too large Load Diff

View File

@ -21,11 +21,17 @@ class MessageReceiverDecryptionSpec: QuickSpec {
var mockSign: MockSign!
var mockAeadXChaCha: MockAeadXChaCha20Poly1305Ietf!
var mockNonce24Generator: MockNonce24Generator!
var dependencies: Dependencies!
var dependencies: SMKDependencies!
describe("a MessageReceiver") {
beforeEach {
mockStorage = GRDBStorage(customWriter: DatabaseQueue())
mockStorage = GRDBStorage(
customWriter: DatabaseQueue(),
customMigrations: [
SNUtilitiesKit.migrations(),
SNMessagingKit.migrations()
]
)
mockSodium = MockSodium()
mockBox = MockBox()
mockGenericHash = MockGenericHash()
@ -37,7 +43,7 @@ class MessageReceiverDecryptionSpec: QuickSpec {
.when { $0.encrypt(message: anyArray(), secretKey: anyArray(), nonce: anyArray()) }
.thenReturn(nil)
dependencies = Dependencies(
dependencies = SMKDependencies(
storage: mockStorage,
sodium: mockSodium,
box: mockBox,
@ -111,7 +117,7 @@ class MessageReceiverDecryptionSpec: QuickSpec {
publicKey: Data.data(fromHex: TestConstants.publicKey)!.bytes,
secretKey: Data.data(fromHex: TestConstants.privateKey)!.bytes
),
dependencies: Dependencies()
dependencies: SMKDependencies()
)
expect(String(data: (result?.plaintext ?? Data()), encoding: .utf8)).to(equal("TestMessage"))
@ -217,7 +223,7 @@ class MessageReceiverDecryptionSpec: QuickSpec {
publicKey: Data.data(fromHex: TestConstants.edPublicKey)!.bytes,
secretKey: Data.data(fromHex: TestConstants.edSecretKey)!.bytes
),
using: Dependencies()
using: SMKDependencies()
)
expect(String(data: (result?.plaintext ?? Data()), encoding: .utf8)).to(equal("TestMessage"))

View File

@ -18,16 +18,22 @@ class MessageSenderEncryptionSpec: QuickSpec {
var mockBox: MockBox!
var mockSign: MockSign!
var mockNonce24Generator: MockNonce24Generator!
var dependencies: Dependencies!
var dependencies: SMKDependencies!
describe("a MessageSender") {
beforeEach {
mockStorage = GRDBStorage(customWriter: DatabaseQueue())
mockStorage = GRDBStorage(
customWriter: DatabaseQueue(),
customMigrations: [
SNUtilitiesKit.migrations(),
SNMessagingKit.migrations()
]
)
mockBox = MockBox()
mockSign = MockSign()
mockNonce24Generator = MockNonce24Generator()
dependencies = Dependencies(
dependencies = SMKDependencies(
storage: mockStorage,
box: mockBox,
sign: mockSign,
@ -53,7 +59,7 @@ class MessageSenderEncryptionSpec: QuickSpec {
let result = try? MessageSender.encryptWithSessionProtocol(
"TestMessage".data(using: .utf8)!,
for: "05\(TestConstants.publicKey)",
using: Dependencies(storage: mockStorage)
using: SMKDependencies(storage: mockStorage)
)
// Note: A Nonce is used for this so we can't compare the exact value when not mocked

View File

@ -6,7 +6,7 @@ import SessionUtilitiesKit
@testable import SessionMessagingKit
extension Dependencies {
extension SMKDependencies {
public func with(
onionApi: OnionRequestAPIType.Type? = nil,
generalCache: Atomic<GeneralCacheType>? = nil,
@ -21,8 +21,8 @@ extension Dependencies {
nonceGenerator24: NonceGenerator24ByteType? = nil,
standardUserDefaults: UserDefaultsType? = nil,
date: Date? = nil
) -> Dependencies {
return Dependencies(
) -> SMKDependencies {
return SMKDependencies(
onionApi: (onionApi ?? self._onionApi),
generalCache: (generalCache ?? self._generalCache),
storage: (storage ?? self._storage),

View File

@ -2,6 +2,7 @@
import Foundation
import PromiseKit
import SessionUtilitiesKit
@testable import SessionMessagingKit
@ -26,16 +27,6 @@ class MockOGMCache: Mock<OGMCacheType>, OGMCacheType {
set { accept(args: [newValue]) }
}
var moderators: [String: [String: Set<String>]] {
get { return accept() as! [String: [String: Set<String>]] }
set { accept(args: [newValue]) }
}
var admins: [String: [String: Set<String>]] {
get { return accept() as! [String: [String: Set<String>]] }
set { accept(args: [newValue]) }
}
var hasPerformedInitialPoll: [String: Bool] {
get { return accept() as! [String: Bool] }
set { accept(args: [newValue]) }

View File

@ -4,8 +4,6 @@ import Foundation
import SessionUtilitiesKit
class MockUserDefaults: Mock<UserDefaultsType>, UserDefaultsType {
var storage: [String: Any] = [:]
func object(forKey defaultName: String) -> Any? { return accept(args: [defaultName]) }
func string(forKey defaultName: String) -> String? { return accept(args: [defaultName]) as? String }
func array(forKey defaultName: String) -> [Any]? { return accept(args: [defaultName]) as? [Any] }

View File

@ -1,34 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionMessagingKit
extension OpenGroup: Mocked {
static var mockValue: OpenGroup = OpenGroup(
server: any(),
roomToken: any(),
publicKey: TestConstants.publicKey,
isActive: any(),
name: any(),
roomDescription: any(),
imageId: any(),
imageData: any(),
userCount: any(),
infoUpdates: any(),
sequenceNumber: any(),
inboxLatestMessageId: any(),
outboxLatestMessageId: any()
)
}
extension VisibleMessage: Mocked {
static var mockValue: VisibleMessage = VisibleMessage(text: "")
}
extension BlindedIdMapping: Mocked {
static var mockValue: BlindedIdMapping = BlindedIdMapping(
blindedId: any(),
sessionId: any(),
serverPublicKey: any()
)
}

View File

@ -1,51 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionMessagingKit
// FIXME: Turn this into a protocol to make mocking possible
class TestContactThread: TSContactThread, Mockable {
// MARK: - Mockable
enum DataKey: Hashable {
case uniqueId
case interactions
}
typealias Key = DataKey
var mockData: [DataKey: Any] = [:]
var numSaveCalls: Int = 0
var didCallRemoveAllThreadInteractions: Bool = false
var didCallRemove: Bool = false
// MARK: - TSContactThread
override var uniqueId: String? {
get { (mockData[.uniqueId] as? String) }
set {}
}
override func enumerateInteractions(_ block: @escaping (TSInteraction) -> Void) {
((mockData[.interactions] as? [TSInteraction]) ?? []).forEach(block)
}
override func enumerateInteractions(with transaction: YapDatabaseReadTransaction, using block: @escaping (TSInteraction, UnsafeMutablePointer<ObjCBool>) -> Void) {
var stop: ObjCBool = false
for interaction in ((mockData[.interactions] as? [TSInteraction]) ?? []) {
block(interaction, &stop)
if stop.boolValue { break }
}
}
override func removeAllThreadInteractions(with transaction: YapDatabaseReadWriteTransaction) {
didCallRemoveAllThreadInteractions = true
}
override func remove(with transaction: YapDatabaseReadWriteTransaction) {
didCallRemove = true
}
override func save(with transaction: YapDatabaseReadWriteTransaction) { numSaveCalls += 1 }
}

View File

@ -1,57 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionMessagingKit
// FIXME: Turn this into a protocol to make mocking possible
class TestGroupThread: TSGroupThread, Mockable {
// MARK: - Mockable
enum DataKey: Hashable {
case uniqueId
case groupModel
case interactions
}
typealias Key = DataKey
var mockData: [DataKey: Any] = [:]
var numSaveCalls: Int = 0
var didCallRemoveAllThreadInteractions: Bool = false
var didCallRemove: Bool = false
// MARK: - TSGroupThread
override var uniqueId: String? {
get { (mockData[.uniqueId] as? String) }
set {}
}
override var groupModel: TSGroupModel {
get { (mockData[.groupModel] as! TSGroupModel) }
set { mockData[.groupModel] = newValue }
}
override func enumerateInteractions(_ block: @escaping (TSInteraction) -> Void) {
((mockData[.interactions] as? [TSInteraction]) ?? []).forEach(block)
}
override func enumerateInteractions(with transaction: YapDatabaseReadTransaction, using block: @escaping (TSInteraction, UnsafeMutablePointer<ObjCBool>) -> Void) {
var stop: ObjCBool = false
for interaction in ((mockData[.interactions] as? [TSInteraction]) ?? []) {
block(interaction, &stop)
if stop.boolValue { break }
}
}
override func removeAllThreadInteractions(with transaction: YapDatabaseReadWriteTransaction) {
didCallRemoveAllThreadInteractions = true
}
override func remove(with transaction: YapDatabaseReadWriteTransaction) {
didCallRemove = true
}
override func save(with transaction: YapDatabaseReadWriteTransaction) { numSaveCalls += 1 }
}

View File

@ -1,23 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionMessagingKit
// FIXME: Turn this into a protocol to make mocking possible
class TestIncomingMessage: TSIncomingMessage, Mockable {
// MARK: - Mockable
enum DataKey: Hashable {
}
typealias Key = DataKey
var mockData: [DataKey: Any] = [:]
var didCallSave: Bool = false
var didCallRemove: Bool = false
// MARK: - TSInteraction
override func save(with transaction: YapDatabaseReadWriteTransaction) { didCallSave = true }
override func remove(with transaction: YapDatabaseReadWriteTransaction) { didCallRemove = true }
}

View File

@ -1,32 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionMessagingKit
// FIXME: Turn this into a protocol to make mocking possible
class TestInteraction: TSInteraction, Mockable {
// MARK: - Mockable
enum DataKey: Hashable {
case uniqueId
case timestamp
}
typealias Key = DataKey
var mockData: [DataKey: Any] = [:]
var didCallSave: Bool = false
// MARK: - TSInteraction
override var uniqueId: String? {
get { (mockData[.uniqueId] as? String) }
set { mockData[.uniqueId] = newValue }
}
override var timestamp: UInt64 {
(mockData[.timestamp] as! UInt64)
}
override func save(with transaction: YapDatabaseReadWriteTransaction) { didCallSave = true }
}

View File

@ -1,35 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import YapDatabase
// FIXME: Turn this into a protocol to make mocking possible
final class TestTransaction: YapDatabaseReadWriteTransaction, Mockable {
// MARK: - Mockable
enum DataKey: Hashable {
case objectForKey
}
typealias Key = DataKey
var mockData: [DataKey: Any] = [:]
// MARK: - YapDatabaseReadWriteTransaction
override func object(forKey key: String, inCollection collection: String?) -> Any? {
if let dictionary: [String: Any] = mockData[.objectForKey] as? [String: Any] {
return dictionary[key]
}
return mockData[.objectForKey]
}
override func addCompletionQueue(_ completionQueue: DispatchQueue?, completionBlock: @escaping () -> Void) {
completionBlock()
}
}
extension TestTransaction: Mocked {
static var mockValue: TestTransaction = TestTransaction()
}

View File

@ -108,7 +108,7 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension
if let sender: String = callMessage.sender, let interaction: Interaction = try MessageReceiver.insertCallInfoMessage(db, for: callMessage, state: .permissionDenied) {
let thread: SessionThread = try SessionThread.fetchOrCreate(db, id: sender, variant: .contact)
Environment.shared.notificationsManager.wrappedValue?
Environment.shared?.notificationsManager.wrappedValue?
.notifyUser(
db,
forIncomingCall: interaction,
@ -168,7 +168,7 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension
AppSetup.setupEnvironment(
appSpecificBlock: {
Environment.shared.notificationsManager.mutate {
Environment.shared?.notificationsManager.mutate {
$0 = NSENotificationPresenter()
}
},

View File

@ -56,10 +56,6 @@ final class NotificationServiceExtensionContext : NSObject, AppContext {
return userDefaults
}
func keychainStorage() -> SSKKeychainStorage {
return SSKDefaultKeychainStorage.shared
}
// MARK: - Currently Unused
let frame = CGRect.zero

View File

@ -142,10 +142,6 @@ final class ShareAppExtensionContext: NSObject, AppContext {
return rootViewController.findFrontmostViewController(true)
}
func keychainStorage() -> SSKKeychainStorage {
return SSKDefaultKeychainStorage.shared
}
func appDocumentDirectoryPath() -> String {
let targetPath: String? = FileManager.default
.urls(

View File

@ -44,7 +44,7 @@ final class ShareVC : UINavigationController, ShareViewDelegate, AppModeManagerD
AppSetup.setupEnvironment(
appSpecificBlock: {
Environment.shared.notificationsManager.mutate {
Environment.shared?.notificationsManager.mutate {
$0 = NoopNotificationsManager()
}
},

View File

@ -52,6 +52,6 @@ enum _001_InitialSetupMigration: Migration {
t.uniqueKey([.key, .hash])
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -21,6 +21,6 @@ enum _002_SetupStandardJobs: Migration {
).inserted(db)
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -67,7 +67,7 @@ enum _003_YDBToGRDBMigration: Migration {
snodeSetResult["\(SnodeSet.onionRequestPathPrefix)1"] = [ path1Snode0, path1Snode1, path1Snode2 ]
}
}
GRDBStorage.shared.update(progress: 0.02, for: self, in: target)
GRDBStorage.update(progress: 0.02, for: self, in: target)
// MARK: --SnodePool
@ -100,7 +100,7 @@ enum _003_YDBToGRDBMigration: Migration {
collectionIndex += 1
GRDBStorage.shared.update(
GRDBStorage.update(
progress: min(
swarmCompleteProgress,
((collectionIndex / roughNumCollections) * (swarmCompleteProgress - startProgress))
@ -109,7 +109,7 @@ enum _003_YDBToGRDBMigration: Migration {
in: target
)
}
GRDBStorage.shared.update(progress: swarmCompleteProgress, for: self, in: target)
GRDBStorage.update(progress: swarmCompleteProgress, for: self, in: target)
for swarmCollection in swarmCollections {
let collection: String = "\(SSKLegacy.swarmCollectionPrefix)\(swarmCollection)"
@ -120,7 +120,7 @@ enum _003_YDBToGRDBMigration: Migration {
snodeSetResult[swarmCollection] = (snodeSetResult[swarmCollection] ?? Set()).inserting(snode)
}
}
GRDBStorage.shared.update(progress: 0.92, for: self, in: target)
GRDBStorage.update(progress: 0.92, for: self, in: target)
// MARK: --Received message hashes
@ -128,7 +128,7 @@ enum _003_YDBToGRDBMigration: Migration {
guard let hashSet = object as? Set<String> else { return }
receivedMessageResults[key] = hashSet
}
GRDBStorage.shared.update(progress: 0.93, for: self, in: target)
GRDBStorage.update(progress: 0.93, for: self, in: target)
// MARK: --Last message info
@ -141,7 +141,7 @@ enum _003_YDBToGRDBMigration: Migration {
lastMessageResults[key] = (lastMessageHash, lastMessageJson)
receivedMessageResults[key] = receivedMessageResults[key]?.removing(lastMessageHash)
}
GRDBStorage.shared.update(progress: 0.94, for: self, in: target)
GRDBStorage.update(progress: 0.94, for: self, in: target)
}
// MARK: - Insert into GRDB
@ -161,7 +161,7 @@ enum _003_YDBToGRDBMigration: Migration {
x25519PublicKey: legacySnode.publicKeySet.x25519Key
).insert(db)
}
GRDBStorage.shared.update(progress: 0.96, for: self, in: target)
GRDBStorage.update(progress: 0.96, for: self, in: target)
// MARK: --SnodeSets
@ -176,7 +176,7 @@ enum _003_YDBToGRDBMigration: Migration {
).insert(db)
}
}
GRDBStorage.shared.update(progress: 0.98, for: self, in: target)
GRDBStorage.update(progress: 0.98, for: self, in: target)
}
try autoreleasepool {
@ -191,7 +191,7 @@ enum _003_YDBToGRDBMigration: Migration {
).inserted(db)
}
}
GRDBStorage.shared.update(progress: 0.99, for: self, in: target)
GRDBStorage.update(progress: 0.99, for: self, in: target)
// MARK: --Last Message Hash
@ -209,6 +209,6 @@ enum _003_YDBToGRDBMigration: Migration {
}
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -36,13 +36,24 @@ public final class GRDBStorage {
// GRDBStorage.deleteDatabaseFiles() // TODO: Remove this.
// try! GRDBStorage.deleteDbKeys() // TODO: Remove this.
// }
public init(customWriter: DatabaseWriter? = nil) {
public init(
customWriter: DatabaseWriter? = nil,
customMigrations: [TargetMigrations]? = nil
) {
// Create the database directory if needed and ensure it's protection level is set before attempting to
// create the database KeySpec or the database itself
OWSFileSystem.ensureDirectoryExists(GRDBStorage.sharedDatabaseDirectoryPath)
OWSFileSystem.protectFileOrFolder(atPath: GRDBStorage.sharedDatabaseDirectoryPath)
// If a custom writer was provided then use that (for unit testing)
guard customWriter == nil else {
dbWriter = customWriter
isValid = true
perform(migrations: (customMigrations ?? []), async: false, onProgressUpdate: nil, onComplete: { _, _ in })
return
}
// Generate the database KeySpec if needed (this MUST be done before we try to access the database
// as a different thread might attempt to access the database before the key is successfully created)
//
@ -76,13 +87,6 @@ public final class GRDBStorage {
try db.execute(sql: "PRAGMA cipher_plaintext_header_size = 32")
}
// If a custom writer was provided then use that (for unit testing)
guard customWriter == nil else {
dbWriter = customWriter
isValid = true
return
}
// Create the DatabasePool to allow us to connect to the database and mark the storage as valid
do {
dbWriter = try DatabasePool(
@ -98,6 +102,7 @@ public final class GRDBStorage {
public func perform(
migrations: [TargetMigrations],
async: Bool = true,
onProgressUpdate: ((CGFloat, TimeInterval) -> ())?,
onComplete: @escaping (Bool, Bool) -> ()
) {
@ -174,7 +179,8 @@ public final class GRDBStorage {
self.migrationProgressUpdater?.wrappedValue(firstMigrationKey, 0)
}
self.migrator?.asyncMigrate(dbWriter) { [weak self] _, error in
// Store the logic to run when the migration completes
let migrationCompleted: (Error?) -> () = { [weak self] error in
self?.hasCompletedMigrations = true
self?.migrationProgressUpdater = nil
SUKLegacy.clearLegacyDatabaseInstance()
@ -185,20 +191,37 @@ public final class GRDBStorage {
onComplete((error == nil), needsConfigSync)
}
// Note: The non-async migration should only be used for unit tests
guard async else {
do { try self.migrator?.migrate(dbWriter) }
catch { migrationCompleted(error) }
return
}
self.migrator?.asyncMigrate(dbWriter) { _, error in
migrationCompleted(error)
}
}
public func update(
public static func update(
progress: CGFloat,
for migration: Migration.Type,
in target: TargetMigrations.Identifier
) {
// In test builds ignore any migration progress updates (we run in a custom database writer anyway),
// this code should be the same as 'CurrentAppContext().isRunningTests' but since the tests can run
// without being attached to a host application the `CurrentAppContext` might not have been set and
// would crash as it gets force-unwrapped - better to just do the check explicitly instead
guard ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] == nil else { return }
GRDBStorage.shared.migrationProgressUpdater?.wrappedValue(target.key(with: migration), progress)
}
// MARK: - Security
private static func getDatabaseCipherKeySpec() throws -> Data {
return try CurrentAppContext().keychainStorage().data(forService: keychainService, key: dbCipherKeySpecKey)
return try SSKDefaultKeychainStorage.shared.data(forService: keychainService, key: dbCipherKeySpecKey)
}
@discardableResult private static func getOrGenerateDatabaseKeySpec() -> Data {
@ -228,7 +251,7 @@ public final class GRDBStorage {
var keySpec: Data = Randomness.generateRandomBytes(kSQLCipherKeySpecLength)
defer { keySpec.resetBytes(in: 0..<keySpec.count) } // Reset content immediately after use
try CurrentAppContext().keychainStorage().set(data: keySpec, service: keychainService, key: dbCipherKeySpecKey)
try SSKDefaultKeychainStorage.shared.set(data: keySpec, service: keychainService, key: dbCipherKeySpecKey)
print("RAWR new keySpec generated and saved")
return keySpec
}
@ -281,7 +304,7 @@ public final class GRDBStorage {
}
private static func deleteDbKeys() throws {
try CurrentAppContext().keychainStorage().remove(service: keychainService, key: dbCipherKeySpecKey)
try SSKDefaultKeychainStorage.shared.remove(service: keychainService, key: dbCipherKeySpecKey)
}
// MARK: - Functions

View File

@ -58,7 +58,7 @@ public enum SUKLegacy {
guard SUKLegacy.database == nil else { return true }
/// Ensure the databaseKeySpec exists
var maybeKeyData: Data? = try? CurrentAppContext().keychainStorage().data(
var maybeKeyData: Data? = try? SSKDefaultKeychainStorage.shared.data(
forService: keychainService,
key: keychainDBCipherKeySpec
)
@ -75,7 +75,7 @@ public enum SUKLegacy {
options.cipherKeySpecBlock = {
/// To avoid holding the keySpec in memory too long we load it as needed, since we have already confirmed
/// it's existence we can force-try here (the database will crash if it's invalid anyway)
var keySpec: Data = try! CurrentAppContext().keychainStorage().data(
var keySpec: Data = try! SSKDefaultKeychainStorage.shared.data(
forService: keychainService,
key: keychainDBCipherKeySpec
)

View File

@ -65,6 +65,6 @@ enum _001_InitialSetupMigration: Migration {
t.column(.value, .blob).notNull()
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -21,6 +21,6 @@ enum _002_SetupStandardJobs: Migration {
).inserted(db)
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -114,6 +114,6 @@ enum _003_YDBToGRDBMigration: Migration {
).insert(db)
}
GRDBStorage.shared.update(progress: 1, for: self, in: target) // In case this is the last migration
GRDBStorage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -104,8 +104,6 @@ NSString *NSStringForUIApplicationState(UIApplicationState value);
@property (atomic, readonly) NSDate *appLaunchTime;
- (id<SSKKeychainStorage>)keychainStorage;
- (NSString *)appDocumentDirectoryPath;
- (NSString *)appSharedDataDirectoryPath;

View File

@ -0,0 +1,55 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
open class Dependencies {
public var _generalCache: Atomic<GeneralCacheType>?
public var generalCache: Atomic<GeneralCacheType> {
get { Dependencies.getValueSettingIfNull(&_generalCache) { General.cache } }
set { _generalCache = newValue }
}
public var _storage: GRDBStorage?
public var storage: GRDBStorage {
get { Dependencies.getValueSettingIfNull(&_storage) { GRDBStorage.shared } }
set { _storage = newValue }
}
public var _standardUserDefaults: UserDefaultsType?
public var standardUserDefaults: UserDefaultsType {
get { Dependencies.getValueSettingIfNull(&_standardUserDefaults) { UserDefaults.standard } }
set { _standardUserDefaults = newValue }
}
public var _date: Date?
public var date: Date {
get { Dependencies.getValueSettingIfNull(&_date) { Date() } }
set { _date = newValue }
}
// MARK: - Initialization
public init(
generalCache: Atomic<GeneralCacheType>? = nil,
storage: GRDBStorage? = nil,
standardUserDefaults: UserDefaultsType? = nil,
date: Date? = nil
) {
_generalCache = generalCache
_storage = storage
_standardUserDefaults = standardUserDefaults
_date = date
}
// MARK: - Convenience
public static func getValueSettingIfNull<T>(_ maybeValue: inout T?, _ valueGenerator: () -> T) -> T {
guard let value: T = maybeValue else {
let value: T = valueGenerator()
maybeValue = value
return value
}
return value
}
}

View File

@ -20,13 +20,13 @@ public enum GeneralError: Error {
case keyGenerationFailed
}
public func getUserHexEncodedPublicKey(_ db: Database? = nil) -> String {
if let cachedKey: String = General.cache.wrappedValue.encodedPublicKey { return cachedKey }
public func getUserHexEncodedPublicKey(_ db: Database? = nil, dependencies: Dependencies = Dependencies()) -> String {
if let cachedKey: String = dependencies.generalCache.wrappedValue.encodedPublicKey { return cachedKey }
if let publicKey: Data = Identity.fetchUserPublicKey(db) { // Can be nil under some circumstances
let sessionId: SessionId = SessionId(.standard, publicKey: publicKey.bytes)
General.cache.mutate { $0.encodedPublicKey = sessionId.hexString }
dependencies.generalCache.mutate { $0.encodedPublicKey = sessionId.hexString }
return sessionId.hexString
}

View File

@ -4,6 +4,7 @@
import Foundation
import AVFoundation
import SessionMessagingKit
public protocol OWSVideoPlayerDelegate: AnyObject {
func videoPlayerDidPlayToCompletion(_ videoPlayer: OWSVideoPlayer)
@ -26,23 +27,17 @@ public class OWSVideoPlayer {
object: avPlayer.currentItem)
}
// MARK: Dependencies
var audioSession: OWSAudioSession {
return Environment.shared.audioSession
}
// MARK: Playback Controls
@objc
public func pause() {
avPlayer.pause()
audioSession.endAudioActivity(self.audioActivity)
Environment.shared?.audioSession.endAudioActivity(self.audioActivity)
}
@objc
public func play() {
let success = audioSession.startAudioActivity(self.audioActivity)
let success = (Environment.shared?.audioSession.startAudioActivity(self.audioActivity) == true)
assert(success)
guard let item = avPlayer.currentItem else {
@ -62,7 +57,7 @@ public class OWSVideoPlayer {
public func stop() {
avPlayer.pause()
avPlayer.seek(to: CMTime.zero, toleranceBefore: .zero, toleranceAfter: .zero)
audioSession.endAudioActivity(self.audioActivity)
Environment.shared?.audioSession.endAudioActivity(self.audioActivity)
}
@objc(seekToTime:)
@ -75,6 +70,6 @@ public class OWSVideoPlayer {
@objc
private func playerItemDidPlayToCompletion(_ notification: Notification) {
self.delegate?.videoPlayerDidPlayToCompletion(self)
audioSession.endAudioActivity(self.audioActivity)
Environment.shared?.audioSession.endAudioActivity(self.audioActivity)
}
}