diff --git a/wire-ios-build-assets b/wire-ios-build-assets index 31ae91bd82f..4f15c02e0c0 160000 --- a/wire-ios-build-assets +++ b/wire-ios-build-assets @@ -1 +1 @@ -Subproject commit 31ae91bd82f89444981e107898cd658397608dfe +Subproject commit 4f15c02e0c0d6de929c044ac1e22e22b40b0d595 diff --git a/wire-ios-data-model/Source/ManagedObjectContext/CoreDataStack.swift b/wire-ios-data-model/Source/ManagedObjectContext/CoreDataStack.swift index a0218f0e2cd..d506c80a340 100644 --- a/wire-ios-data-model/Source/ManagedObjectContext/CoreDataStack.swift +++ b/wire-ios-data-model/Source/ManagedObjectContext/CoreDataStack.swift @@ -401,13 +401,6 @@ public class CoreDataStack: NSObject, CoreDataStackProtocol { context.accountDirectoryURL = self.accountContainer context.applicationContainerURL = self.applicationContainer - if !DeveloperFlag.proteusViaCoreCrypto.isOn { - context.setupUserKeyStore( - accountDirectory: self.accountContainer, - applicationContainer: self.applicationContainer - ) - } - context.undoManager = nil context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType) diff --git a/wire-ios-data-model/Source/Proteus/CryptoboxMigrationManager.swift b/wire-ios-data-model/Source/Proteus/CryptoboxMigrationManager.swift index 14210c11202..4060e9f547b 100644 --- a/wire-ios-data-model/Source/Proteus/CryptoboxMigrationManager.swift +++ b/wire-ios-data-model/Source/Proteus/CryptoboxMigrationManager.swift @@ -60,9 +60,8 @@ public class CryptoboxMigrationManager: CryptoboxMigrationManagerInterface { // MARK: - Methods public func isMigrationNeeded(accountDirectory: URL) -> Bool { - guard DeveloperFlag.proteusViaCoreCrypto.isOn else { return false } - let cryptoboxDirectory = fileManager.cryptoboxDirectory(in: accountDirectory) - return fileManager.fileExists(atPath: cryptoboxDirectory.path) + // disabling migration. This will be removed completely in https://wearezeta.atlassian.net/browse/WPB-22227 + false } public func performMigration( diff --git a/wire-ios-data-model/Source/Utilis/NSManagedObjectContact+Unpack.swift b/wire-ios-data-model/Source/Utilis/NSManagedObjectContext+Unpack.swift similarity index 100% rename from wire-ios-data-model/Source/Utilis/NSManagedObjectContact+Unpack.swift rename to wire-ios-data-model/Source/Utilis/NSManagedObjectContext+Unpack.swift diff --git a/wire-ios-data-model/Tests/Proteus/CryptoboxMigrationManagerTests.swift b/wire-ios-data-model/Tests/Proteus/CryptoboxMigrationManagerTests.swift deleted file mode 100644 index ec8757a9192..00000000000 --- a/wire-ios-data-model/Tests/Proteus/CryptoboxMigrationManagerTests.swift +++ /dev/null @@ -1,145 +0,0 @@ -// -// Wire -// Copyright (C) 2025 Wire Swiss GmbH -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/. -// - -import Foundation -import WireTransport -import XCTest - -@testable import WireDataModel -@testable import WireDataModelSupport - -class CryptoboxMigrationManagerTests: ZMBaseManagedObjectTest { - - var sut: CryptoboxMigrationManager! - var mockFileManager: MockFileManagerInterface! - var proteusViaCoreCryptoFlag: DeveloperFlag! - var mockSafeCoreCrypto: MockSafeCoreCrypto! - - override func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - proteusViaCoreCryptoFlag = .proteusViaCoreCrypto - - mockFileManager = MockFileManagerInterface() - mockFileManager.cryptoboxDirectoryIn_MockValue = cryptoboxDirectory - mockFileManager.removeItemAt_MockMethod = { _ in } - mockSafeCoreCrypto = MockSafeCoreCrypto() - sut = CryptoboxMigrationManager(fileManager: mockFileManager) - } - - override func tearDown() { - sut = nil - mockFileManager = nil - mockSafeCoreCrypto = nil - - syncMOC.performAndWait { - syncMOC.proteusService = nil - } - - proteusViaCoreCryptoFlag.isOn = false - DeveloperFlag.storage = UserDefaults.standard - - super.tearDown() - } - - var accountDirectory: URL { - FileManager.default - .temporaryDirectory - .appendingPathComponent("CryptoBoxMigrationManagerTests") - } - - lazy var cryptoboxDirectory = accountDirectory.appendingPathComponent("otr") - - // MARK: - Verifying if migration is needed - - func test_IsMigrationNeeded_FilesExistAndFlagIsOn() { - // Given - mockFileManager.fileExistsAtPath_MockValue = true - proteusViaCoreCryptoFlag.isOn = true - - // When - let result = sut.isMigrationNeeded(accountDirectory: accountDirectory) - - // Then - XCTAssertTrue(result) - } - - func test_IsMigrationNeeded_FilesExistAndFlagIsOff() { - // Given - mockFileManager.fileExistsAtPath_MockValue = true - proteusViaCoreCryptoFlag.isOn = false - - // When - let result = sut.isMigrationNeeded(accountDirectory: accountDirectory) - - // Then - XCTAssertFalse(result) - } - - func test_IsMigrationNeeded_FilesDoNotExistAndFlagIsOn() { - // Given - mockFileManager.fileExistsAtPath_MockValue = false - proteusViaCoreCryptoFlag.isOn = true - - // When - let result = sut.isMigrationNeeded(accountDirectory: accountDirectory) - - // Then - XCTAssertFalse(result) - } - - // MARK: - Perform migration - - func test_itPerformsMigrations() async throws { - // Given - let migrated = customExpectation(description: "Cryptobox was migrated") - mockFileManager.fileExistsAtPath_MockValue = true - proteusViaCoreCryptoFlag.isOn = true - mockSafeCoreCrypto.coreCryptoContext.proteusCryptoboxMigratePath_MockMethod = { _ in - migrated.fulfill() - } - - // When - try await sut.performMigration(accountDirectory: accountDirectory, coreCrypto: mockSafeCoreCrypto) - - // Then - XCTAssertEqual(mockFileManager.removeItemAt_Invocations, [cryptoboxDirectory]) - XCTAssertTrue(waitForCustomExpectations(withTimeout: 0.5)) - } - - func test_itDoesNotPerformMigration_CoreCryptoError() async { - // Given - mockFileManager.fileExistsAtPath_MockValue = true - proteusViaCoreCryptoFlag.isOn = true - - mockSafeCoreCrypto.coreCryptoContext.proteusCryptoboxMigratePath_MockMethod = { _ in - throw CryptoboxMigrationManager.Failure.failedToMigrateData - } - - // When - await assertItThrows(error: CryptoboxMigrationManager.Failure.failedToMigrateData) { - try await self.sut.performMigration( - accountDirectory: self.accountDirectory, - coreCrypto: self.mockSafeCoreCrypto - ) - } - - // Then - XCTAssertTrue(mockFileManager.removeItemAt_Invocations.isEmpty) - } -} diff --git a/wire-ios-data-model/Tests/Source/Model/Conversation/ZMConversationLastMessagesTest.swift b/wire-ios-data-model/Tests/Source/Model/Conversation/ZMConversationLastMessagesTest.swift index 76f107328e7..328079baa1d 100644 --- a/wire-ios-data-model/Tests/Source/Model/Conversation/ZMConversationLastMessagesTest.swift +++ b/wire-ios-data-model/Tests/Source/Model/Conversation/ZMConversationLastMessagesTest.swift @@ -23,19 +23,6 @@ import XCTest class ZMConversationLastMessagesTest: ZMBaseManagedObjectTest { - override class func setUp() { - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - - super.setUp() - } - - override class func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - func createConversation(on moc: NSManagedObjectContext? = nil) -> ZMConversation { let conversation = ZMConversation.insertNewObject(in: moc ?? uiMOC) conversation.remoteIdentifier = UUID() diff --git a/wire-ios-data-model/Tests/Source/Model/Messages/CacheAssetTests.swift b/wire-ios-data-model/Tests/Source/Model/Messages/CacheAssetTests.swift index f30019e4efc..665d1dd61ba 100644 --- a/wire-ios-data-model/Tests/Source/Model/Messages/CacheAssetTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/Messages/CacheAssetTests.swift @@ -21,18 +21,6 @@ import XCTest class CacheAssetTests: BaseZMAssetClientMessageTests { - override class func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override class func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - // MARK: - Fixtures func fileAsset() -> WireDataModel.CacheAsset { diff --git a/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests+MLSEncryptedPayloadGenerator.swift b/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests+MLSEncryptedPayloadGenerator.swift index d81908866c5..1ca13c3bdc9 100644 --- a/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests+MLSEncryptedPayloadGenerator.swift +++ b/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests+MLSEncryptedPayloadGenerator.swift @@ -23,19 +23,6 @@ import GenericMessageProtocol final class ZMClientMessageTests_MLSEncryptedPayloadGenerator: BaseZMClientMessageTests { - override func setUp() { - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = true - - super.setUp() - } - - override func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - let encryptionFunction: (Data) throws -> Data = { $0.zmSHA256Digest() } diff --git a/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests.swift b/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests.swift index ff8e15e17f9..627d77b67c2 100644 --- a/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/Messages/ZMClientMessageTests.swift @@ -23,18 +23,6 @@ import XCTest final class ClientMessageTests: BaseZMClientMessageTests { - override static func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override static func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - func testThatItDoesNotCreateTextMessagesFromUpdateEventIfThereIsAlreadyAClientMessageWithTheSameNonce() { // given let nonce = UUID.create() diff --git a/wire-ios-data-model/Tests/Source/Model/PermissionsTests.swift b/wire-ios-data-model/Tests/Source/Model/PermissionsTests.swift index f43e2080db4..131a7ae93e3 100644 --- a/wire-ios-data-model/Tests/Source/Model/PermissionsTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/PermissionsTests.swift @@ -21,18 +21,6 @@ import WireTesting class PermissionsTests: BaseZMClientMessageTests { - override class func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override class func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - private let allPermissions: Permissions = [ .createConversation, .deleteConversation, diff --git a/wire-ios-data-model/Tests/Source/Model/TeamDeletionRuleTests.swift b/wire-ios-data-model/Tests/Source/Model/TeamDeletionRuleTests.swift index 276065ede18..826452fcd85 100644 --- a/wire-ios-data-model/Tests/Source/Model/TeamDeletionRuleTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/TeamDeletionRuleTests.swift @@ -21,18 +21,6 @@ import WireTesting class TeamDeletionRuleTests: BaseZMClientMessageTests { - override class func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override class func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - func testThatItDoesntDeleteConversationsWhichArePartOfATeamWhenTeamGetsDeleted() { // given let team = Team.insertNewObject(in: uiMOC) diff --git a/wire-ios-data-model/Tests/Source/Model/TextSearchQueryTests.swift b/wire-ios-data-model/Tests/Source/Model/TextSearchQueryTests.swift index 207d2689014..d01b9498a9a 100644 --- a/wire-ios-data-model/Tests/Source/Model/TextSearchQueryTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/TextSearchQueryTests.swift @@ -32,18 +32,6 @@ private class MockTextSearchQueryDelegate: TextSearchQueryDelegate { class TextSearchQueryTests: BaseZMClientMessageTests { - override class func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override class func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - func testThatItOnlyReturnsResultFromTheCorrectConversationNotYetIndexed() { // Given let conversation = ZMConversation.insertNewObject(in: uiMOC) diff --git a/wire-ios-data-model/Tests/Source/Model/User/ZMUserLegalHoldTests.swift b/wire-ios-data-model/Tests/Source/Model/User/ZMUserLegalHoldTests.swift index 328d6873ab4..f06dd6534ff 100644 --- a/wire-ios-data-model/Tests/Source/Model/User/ZMUserLegalHoldTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/User/ZMUserLegalHoldTests.swift @@ -24,18 +24,6 @@ import XCTest @preconcurrency class ZMUserLegalHoldTests: ModelObjectsTests { - override func setUp() { - DeveloperFlag.storage = .temporary() - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - super.setUp() - } - - override func tearDown() { - DeveloperFlag.storage = .standard - super.tearDown() - } - func testThatLegalHoldStatusIsDisabled_ByDefault() { // GIVEN let selfUser = ZMUser.selfUser(in: uiMOC) diff --git a/wire-ios-data-model/Tests/Source/Model/UserClient/UserClientTests.swift b/wire-ios-data-model/Tests/Source/Model/UserClient/UserClientTests.swift index 0773c7af682..3dbaf86405c 100644 --- a/wire-ios-data-model/Tests/Source/Model/UserClient/UserClientTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/UserClient/UserClientTests.swift @@ -16,7 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -import WireCryptobox import WireUtilities import XCTest @@ -25,18 +24,6 @@ import XCTest final class UserClientTests: ZMBaseManagedObjectTest { - override static func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override static func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - func clientWithTrustedClientCount( _ trustedCount: UInt, ignoredClientCount: UInt, @@ -169,8 +156,6 @@ final class UserClientTests: ZMBaseManagedObjectTest { func testThatItDeletesASession() async throws { // Given - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = true var otherClient: UserClient! let mockProteusService = MockProteusServiceInterface() mockProteusService.deleteSessionId_MockMethod = { _ in @@ -195,13 +180,10 @@ final class UserClientTests: ZMBaseManagedObjectTest { } XCTAssert(waitForAllGroupsToBeEmpty(withTimeout: 0.5)) - flag.isOn = false } func testThatItDeletesASessionWhenDeletingAClient() async { // Given - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = true var otherClient: UserClient! var otherClientSessionID: ProteusSessionID! let mockProteusService = MockProteusServiceInterface() @@ -230,7 +212,6 @@ final class UserClientTests: ZMBaseManagedObjectTest { } XCTAssert(waitForAllGroupsToBeEmpty(withTimeout: 0.5)) - flag.isOn = false } func testThatItUpdatesConversationSecurityLevelWhenDeletingClient() async { diff --git a/wire-ios-data-model/Tests/Source/Model/Utils/ProtobufUtilitiesTests.swift b/wire-ios-data-model/Tests/Source/Model/Utils/ProtobufUtilitiesTests.swift index 8da9bdc8fd2..5789343bd03 100644 --- a/wire-ios-data-model/Tests/Source/Model/Utils/ProtobufUtilitiesTests.swift +++ b/wire-ios-data-model/Tests/Source/Model/Utils/ProtobufUtilitiesTests.swift @@ -24,18 +24,6 @@ import XCTest class ProtobufUtilitiesTests: BaseZMClientMessageTests { - override class func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override class func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - func testThatItSetsAndReadsTheLoudness() { // given diff --git a/wire-ios-data-model/WireDataModel.xcodeproj/project.pbxproj b/wire-ios-data-model/WireDataModel.xcodeproj/project.pbxproj index b0ed3840821..ac2d415750b 100644 --- a/wire-ios-data-model/WireDataModel.xcodeproj/project.pbxproj +++ b/wire-ios-data-model/WireDataModel.xcodeproj/project.pbxproj @@ -8,7 +8,7 @@ /* Begin PBXBuildFile section */ 010093B32D4BA2F400429015 /* ZMConversationTests_SystemMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 010093B22D4BA2DB00429015 /* ZMConversationTests_SystemMessages.swift */; }; - 010347222ED4566D000676DE /* NSManagedObjectContact+Unpack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 010347212ED4566D000676DE /* NSManagedObjectContact+Unpack.swift */; }; + 010347222ED4566D000676DE /* NSManagedObjectContext+Unpack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 010347212ED4566D000676DE /* NSManagedObjectContext+Unpack.swift */; }; 0129E7F929A520870065E6DB /* SafeCoreCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0129E7F829A520870065E6DB /* SafeCoreCrypto.swift */; }; 0129E7FB29A520EB0065E6DB /* SafeFileContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0129E7FA29A520EB0065E6DB /* SafeFileContext.swift */; }; 013887A22B9A5C6000323DD0 /* CleanupModels107PreAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013887A12B9A5C6000323DD0 /* CleanupModels107PreAction.swift */; }; @@ -530,7 +530,6 @@ EE74E4E02A37B3BF00B63E6E /* SubconversationGroupIDRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE74E4DF2A37B3BF00B63E6E /* SubconversationGroupIDRepositoryTests.swift */; }; EE770DAF25344B4F00163C4A /* NotificationDispatcher.OperationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE770DAE25344B4F00163C4A /* NotificationDispatcher.OperationMode.swift */; }; EE79699629D4684C00075E38 /* CryptoboxMigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE79699529D4684C00075E38 /* CryptoboxMigrationManager.swift */; }; - EE79699829D469A800075E38 /* CryptoboxMigrationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE79699729D469A700075E38 /* CryptoboxMigrationManagerTests.swift */; }; EE7A90EC2B21CADD00B58E84 /* LegacyOneOnOneResolverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7A90EB2B21CADD00B58E84 /* LegacyOneOnOneResolverTests.swift */; }; EE7A90EE2B21DE3B00B58E84 /* OneOnOneProtocolSelectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7A90ED2B21DE3B00B58E84 /* OneOnOneProtocolSelectorTests.swift */; }; EE7A90F02B21E29E00B58E84 /* OneOnOneMigratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7A90EF2B21E29E00B58E84 /* OneOnOneMigratorTests.swift */; }; @@ -768,7 +767,7 @@ /* Begin PBXFileReference section */ 010093B22D4BA2DB00429015 /* ZMConversationTests_SystemMessages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZMConversationTests_SystemMessages.swift; sourceTree = ""; }; - 010347212ED4566D000676DE /* NSManagedObjectContact+Unpack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContact+Unpack.swift"; sourceTree = ""; }; + 010347212ED4566D000676DE /* NSManagedObjectContext+Unpack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Unpack.swift"; sourceTree = ""; }; 0129E7F829A520870065E6DB /* SafeCoreCrypto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeCoreCrypto.swift; sourceTree = ""; }; 0129E7FA29A520EB0065E6DB /* SafeFileContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeFileContext.swift; sourceTree = ""; }; 013887A12B9A5C6000323DD0 /* CleanupModels107PreAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CleanupModels107PreAction.swift; sourceTree = ""; }; @@ -1270,7 +1269,6 @@ EE74E4DF2A37B3BF00B63E6E /* SubconversationGroupIDRepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubconversationGroupIDRepositoryTests.swift; sourceTree = ""; }; EE770DAE25344B4F00163C4A /* NotificationDispatcher.OperationMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationDispatcher.OperationMode.swift; sourceTree = ""; }; EE79699529D4684C00075E38 /* CryptoboxMigrationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoboxMigrationManager.swift; sourceTree = ""; }; - EE79699729D469A700075E38 /* CryptoboxMigrationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoboxMigrationManagerTests.swift; sourceTree = ""; }; EE7A90EB2B21CADD00B58E84 /* LegacyOneOnOneResolverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyOneOnOneResolverTests.swift; sourceTree = ""; }; EE7A90ED2B21DE3B00B58E84 /* OneOnOneProtocolSelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneOnOneProtocolSelectorTests.swift; sourceTree = ""; }; EE7A90EF2B21E29E00B58E84 /* OneOnOneMigratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneOnOneMigratorTests.swift; sourceTree = ""; }; @@ -2142,7 +2140,6 @@ isa = PBXGroup; children = ( EE032B3529A62CD600E1DDF3 /* ProteusServiceTests.swift */, - EE79699729D469A700075E38 /* CryptoboxMigrationManagerTests.swift */, ); path = Proteus; sourceTree = ""; @@ -2556,7 +2553,7 @@ 0614E96C2A863EED007BB1F6 /* NSPredicate+BaseCompounds.swift */, 1657FA9B2D9C432200A7B337 /* CoreCryptoContextProtocolExt.swift */, E66029D12BDA43E10033C524 /* SearchUsersCache.swift */, - 010347212ED4566D000676DE /* NSManagedObjectContact+Unpack.swift */, + 010347212ED4566D000676DE /* NSManagedObjectContext+Unpack.swift */, ); path = Utilis; sourceTree = ""; @@ -3807,7 +3804,7 @@ 063D292A24212AFD00FA6FEE /* ZMClientMessage.swift in Sources */, CB1BF6FC2C8AF6A5001EC670 /* ExpirationReason+Description.swift in Sources */, EE9B9F5929964F6A00A257BC /* NSManagedObjectContext+CoreCrypto.swift in Sources */, - 010347222ED4566D000676DE /* NSManagedObjectContact+Unpack.swift in Sources */, + 010347222ED4566D000676DE /* NSManagedObjectContext+Unpack.swift in Sources */, 599EA3D52C246955009319D4 /* MutableConversationContainer.swift in Sources */, 017B55792CFFB560005FFBD4 /* NSManagedObjectContext+SyncResources.swift in Sources */, 5986A08F2C6B744300299181 /* TextMessage.swift in Sources */, @@ -4044,7 +4041,6 @@ F9C348861E2CC27D0015D69D /* NewUnreadMessageObserverTests.swift in Sources */, 63F376DA2834FF7200FE1F05 /* NSManagedObjectContextTests+Federation.swift in Sources */, 87A7FA25203DD1CC00AA066C /* ZMConversationTests+AccessMode.swift in Sources */, - EE79699829D469A800075E38 /* CryptoboxMigrationManagerTests.swift in Sources */, F9A708601CAEEF4700C2F5FE /* MessagingTest+EventFactory.m in Sources */, F9DBA5291E29162A00BE23C0 /* MessageObserverTests.swift in Sources */, BF1B980D1EC3410000DE033B /* PermissionsTests.swift in Sources */, diff --git a/wire-ios-notification-engine/Sources/NotificationSession.swift b/wire-ios-notification-engine/Sources/NotificationSession.swift index f12cceea837..ac1909b3509 100644 --- a/wire-ios-notification-engine/Sources/NotificationSession.swift +++ b/wire-ios-notification-engine/Sources/NotificationSession.swift @@ -152,7 +152,7 @@ public final class NotificationSession { throw InitializationError.pendingCryptoboxMigration } coreDataStack.syncContext.performAndWait { - if DeveloperFlag.proteusViaCoreCrypto.isOn, coreDataStack.syncContext.proteusService == nil { + if coreDataStack.syncContext.proteusService == nil { coreDataStack.syncContext.proteusService = proteusService } diff --git a/wire-ios-request-strategy/Sources/Message Sending/MessageInfoExtractorTests.swift b/wire-ios-request-strategy/Sources/Message Sending/MessageInfoExtractorTests.swift index e9d3ecd3897..b74bc2359cb 100644 --- a/wire-ios-request-strategy/Sources/Message Sending/MessageInfoExtractorTests.swift +++ b/wire-ios-request-strategy/Sources/Message Sending/MessageInfoExtractorTests.swift @@ -32,7 +32,6 @@ final class MessageInfoExtractorTests: XCTestCase { override func setUp() async throws { try await super.setUp() - DeveloperFlag.proteusViaCoreCrypto.enable(true, storage: .temporary()) coreDataStack = CoreDataStack( account: .init(userName: "F", userIdentifier: .create()), diff --git a/wire-ios-request-strategy/Sources/Message Sending/ProteusMessagePayloadBuilderTests.swift b/wire-ios-request-strategy/Sources/Message Sending/ProteusMessagePayloadBuilderTests.swift index 03aba5277c7..6f42b427ed4 100644 --- a/wire-ios-request-strategy/Sources/Message Sending/ProteusMessagePayloadBuilderTests.swift +++ b/wire-ios-request-strategy/Sources/Message Sending/ProteusMessagePayloadBuilderTests.swift @@ -29,7 +29,6 @@ final class ProteusMessagePayloadBuilderTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() - DeveloperFlag.proteusViaCoreCrypto.enable(true, storage: .temporary()) proteusService = MockProteusServiceInterface() } diff --git a/wire-ios-request-strategy/Sources/Synchronization/Decoding/EventDecoderTest.swift b/wire-ios-request-strategy/Sources/Synchronization/Decoding/EventDecoderTest.swift index 35e6d17fe78..5b5eecc71cb 100644 --- a/wire-ios-request-strategy/Sources/Synchronization/Decoding/EventDecoderTest.swift +++ b/wire-ios-request-strategy/Sources/Synchronization/Decoding/EventDecoderTest.swift @@ -456,7 +456,6 @@ extension EventDecoderTest { extension EventDecoderTest { func test_ProteusEventDecryption() async throws { - var proteusViaCoreCrypto = DeveloperFlag.proteusViaCoreCrypto let mockProteusService = MockProteusServiceInterface() // Given @@ -467,8 +466,6 @@ extension EventDecoderTest { let message = GenericMessage(content: Text(content: "foo")) let event = try await encryptedUpdateEventToSelfFromOtherClient(message: message) - proteusViaCoreCrypto.isOn = true - await syncMOC.perform { self.syncMOC.proteusService = mockProteusService } @@ -482,14 +479,9 @@ extension EventDecoderTest { XCTAssertEqual(mockProteusService.decryptDataForSessionContext_Invocations.count, 1) // Cleanup - proteusViaCoreCrypto.isOn = false } func test_ProteusEventDecryptionDoesStoreLastEventIdIfFails() async throws { - DeveloperFlag.proteusViaCoreCrypto.enable(true, storage: .temporary()) - defer { - DeveloperFlag.proteusViaCoreCrypto.enable(false, storage: .standard) - } let mockProteusService = MockProteusServiceInterface() enum FakeError: Error { @@ -520,10 +512,6 @@ extension EventDecoderTest { func test_MLSEventDecryptionDoesNotStoreLastEventIdIfFails() async throws { // Given - DeveloperFlag.proteusViaCoreCrypto.enable(true, storage: .temporary()) - defer { - DeveloperFlag.proteusViaCoreCrypto.enable(false, storage: .standard) - } let mockProteusService = MockProteusServiceInterface() let decryptionErrorReason = DummyError() @@ -560,10 +548,6 @@ extension EventDecoderTest { func test_MLSEventDecryptionStoresLastEventIdIfDecryptionSuccessWithEmptyResults() async throws { // Given - DeveloperFlag.proteusViaCoreCrypto.enable(true, storage: .temporary()) - defer { - DeveloperFlag.proteusViaCoreCrypto.enable(false, storage: .standard) - } let mockProteusService = MockProteusServiceInterface() mockProteusService.decryptDataForSessionContext_MockMethod = { data, _, _ in @@ -609,10 +593,6 @@ extension EventDecoderTest { func test_MLSEventDecryptionStoresLastEventIdIfDecryptionSuccessWithProposalResult() async throws { // Given - DeveloperFlag.proteusViaCoreCrypto.enable(true, storage: .temporary()) - defer { - DeveloperFlag.proteusViaCoreCrypto.enable(false, storage: .standard) - } let mockProteusService = MockProteusServiceInterface() mockProteusService.decryptDataForSessionContext_MockMethod = { data, _, _ in diff --git a/wire-ios-request-strategy/Tests/Sources/Notifications/PushNotifications/ZMLocalNotificationTests_Message.swift b/wire-ios-request-strategy/Tests/Sources/Notifications/PushNotifications/ZMLocalNotificationTests_Message.swift index 253f0fb50ec..be7af94bcf1 100644 --- a/wire-ios-request-strategy/Tests/Sources/Notifications/PushNotifications/ZMLocalNotificationTests_Message.swift +++ b/wire-ios-request-strategy/Tests/Sources/Notifications/PushNotifications/ZMLocalNotificationTests_Message.swift @@ -165,18 +165,18 @@ final class ZMLocalNotificationTests_Message: ZMLocalNotificationTests { // "push.notification.add.message.group" = "%1$@: %2$@"; // "push.notification.add.message.group.noconversationname" = "%1$@ in a conversation: %2$@"; syncMOC.performGroupedAndWait { - XCTAssertEqual(self.bodyForNote(self.oneOnOneConversation, sender: self.sender), "Hello Hello!") - XCTAssertEqual(self.bodyForNote(self.groupConversation, sender: self.sender), "Super User: Hello Hello!") + XCTAssertEqual(bodyForNote(oneOnOneConversation, sender: sender), "Hello Hello!") + XCTAssertEqual(bodyForNote(groupConversation, sender: sender), "Super User: Hello Hello!") XCTAssertEqual( - self.bodyForNote(self.groupConversationWithoutUserDefinedName, sender: self.sender), + bodyForNote(groupConversationWithoutUserDefinedName, sender: sender), "Super User: Hello Hello!" ) XCTAssertEqual( - self.bodyForNote(self.groupConversationWithoutName, sender: self.sender), + bodyForNote(groupConversationWithoutName, sender: sender), "Super User in a conversation: Hello Hello!" ) XCTAssertEqual( - self.bodyForNote(self.invalidConversation, sender: self.sender), + bodyForNote(invalidConversation, sender: sender), "Super User in a conversation: Hello Hello!" ) } @@ -198,10 +198,10 @@ final class ZMLocalNotificationTests_Message: ZMLocalNotificationTests { } } - func testThatItDoesNotDuplicatePercentageSignsInTextAndConversationName() { - syncMOC.performGroupedAndWait { + func testThatItDoesNotDuplicatePercentageSignsInTextAndConversationName() throws { + try syncMOC.performGroupedAndWait { XCTAssertEqual( - self.bodyForNote(self.groupConversation, sender: self.sender, text: "Today we grew by 100%"), + try bodyForNote(groupConversation, sender: sender, text: "Today we grew by 100%"), "Super User: Today we grew by 100%" ) } diff --git a/wire-ios-share-engine/Sources/SharingSession.swift b/wire-ios-share-engine/Sources/SharingSession.swift index b81c58ad7f0..6cab6f429a3 100644 --- a/wire-ios-share-engine/Sources/SharingSession.swift +++ b/wire-ios-share-engine/Sources/SharingSession.swift @@ -296,7 +296,7 @@ public final class SharingSession { } coreDataStack.syncContext.performAndWait { - if DeveloperFlag.proteusViaCoreCrypto.isOn, coreDataStack.syncContext.proteusService == nil { + if coreDataStack.syncContext.proteusService == nil { coreDataStack.syncContext.proteusService = proteusService } diff --git a/wire-ios-sync-engine/Tests/Source/Integration/IntegrationTest.swift b/wire-ios-sync-engine/Tests/Source/Integration/IntegrationTest.swift index b5092458ea6..f364df0cf4a 100644 --- a/wire-ios-sync-engine/Tests/Source/Integration/IntegrationTest.swift +++ b/wire-ios-sync-engine/Tests/Source/Integration/IntegrationTest.swift @@ -150,18 +150,11 @@ extension IntegrationTest { MockJailbreakDetector() } - var proteusViaCoreCryptoEnabled: Bool { - false - } - @objc func _setUp() { PrekeyGenerator._test_overrideNumberOfKeys = 1 - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = proteusViaCoreCryptoEnabled - sharedContainerDirectory = Bundle.main.appGroupIdentifier.map(FileManager.sharedContainerDirectory) deleteSharedContainerContent() ZMPersistentCookieStorage.setDoNotPersistToKeychain(!useRealKeychain) diff --git a/wire-ios-sync-engine/Tests/Source/MessagingTest+Swift.swift b/wire-ios-sync-engine/Tests/Source/MessagingTest+Swift.swift index f6a1fca477e..bca761dc0e3 100644 --- a/wire-ios-sync-engine/Tests/Source/MessagingTest+Swift.swift +++ b/wire-ios-sync-engine/Tests/Source/MessagingTest+Swift.swift @@ -91,9 +91,6 @@ public extension MessagingTest { func setBackendInfoDefaults() { BackendInfo.apiVersion = .v0 BackendInfo.domain = "example.com" - - var proteusViaCoreCrypto = DeveloperFlag.proteusViaCoreCrypto - proteusViaCoreCrypto.isOn = false } @objc diff --git a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/CallingRequestStrategyTests.swift b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/CallingRequestStrategyTests.swift index ecb7a1a36c1..d8c5dc072d7 100644 --- a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/CallingRequestStrategyTests.swift +++ b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/CallingRequestStrategyTests.swift @@ -19,12 +19,13 @@ import Foundation import GenericMessageProtocol import WireDataModelSupport -import WireRequestStrategy +@preconcurrency import WireRequestStrategy import WireSyncEngineSupport import WireTransport @testable import WireSyncEngine +@preconcurrency class CallingRequestStrategyTests: MessagingTest { var sut: CallingRequestStrategy! @@ -32,13 +33,6 @@ class CallingRequestStrategyTests: MessagingTest { var mockFetchUserClientsUseCase: MockFetchUserClientsUseCase! var mockMessageSender: MockMessageSenderInterface! - override class func setUp() { - super.setUp() - - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - override func setUp() { super.setUp() @@ -503,7 +497,6 @@ class CallingRequestStrategyTests: MessagingTest { // MARK: - Targeted Calling Messages func testThatItTargetsCallMessagesIfTargetClientsAreSpecified() throws { - var sentMessage: GenericMessageEntity? let (conversationAVSID, user1, client1, user2, client2, targets) = try syncMOC.performAndWait { [self] in sut = CallingRequestStrategy( managedObjectContext: syncMOC, @@ -547,14 +540,15 @@ class CallingRequestStrategyTests: MessagingTest { let avsClient2 = AVSClient(userId: user2.avsIdentifier, clientId: client2.remoteIdentifier!) let targets = [avsClient1, avsClient2] - mockMessageSender.sendMessageMessage_MockMethod = { message in - sentMessage = message as? GenericMessageEntity - } - let conversationAVSID = try XCTUnwrap(conversation.avsIdentifier) return (conversationAVSID, user1, client1, user2, client2, targets) } + var sentMessage: GenericMessageEntity? + mockMessageSender.sendMessageMessage_MockMethod = { message in + sentMessage = message as? GenericMessageEntity + } + // When we schedule the targeted message syncMOC.performGroupedBlock { self.sut.send( @@ -596,7 +590,7 @@ class CallingRequestStrategyTests: MessagingTest { } func testThatItDoesNotTargetCallMessagesIfNoTargetClientsAreSpecified() async throws { - let (user1, user2, client1, client2, client3, client4, conversationAVSID) = try await syncMOC + let conversationAVSID = try await syncMOC .perform { [self] in // Given let selfClient = createSelfClient() @@ -605,15 +599,15 @@ class CallingRequestStrategyTests: MessagingTest { let user1 = ZMUser.insertNewObject(in: syncMOC) user1.remoteIdentifier = .create() - let client1 = createClient(for: user1, connectedTo: selfClient) - let client2 = createClient(for: user1, connectedTo: selfClient) + createClient(for: user1, connectedTo: selfClient) + createClient(for: user1, connectedTo: selfClient) // Another user with two clients connected to self let user2 = ZMUser.insertNewObject(in: syncMOC) user2.remoteIdentifier = .create() - let client3 = createClient(for: user2, connectedTo: selfClient) - let client4 = createClient(for: user2, connectedTo: selfClient) + createClient(for: user2, connectedTo: selfClient) + createClient(for: user2, connectedTo: selfClient) // A conversation with both users and self let conversation = ZMConversation.insertNewObject(in: syncMOC) @@ -626,8 +620,7 @@ class CallingRequestStrategyTests: MessagingTest { syncMOC.saveOrRollback() - let conversationAVSID = try XCTUnwrap(conversation.avsIdentifier) - return (user1, user2, client1, client2, client3, client4, conversationAVSID) + return try XCTUnwrap(conversation.avsIdentifier) } var sentMessage: GenericMessageEntity? @@ -665,16 +658,6 @@ class CallingRequestStrategyTests: MessagingTest { let client = UserClient.insertNewObject(in: syncMOC) client.remoteIdentifier = .randomRemoteIdentifier() client.user = user - - // swiftlint:disable:next todo_requires_jira_link - // TODO: [John] use flag here - syncMOC.zm_cryptKeyStore.encryptionContext.perform { session in - try! session.createClientSession( - client.sessionIdentifier!, - base64PreKeyString: syncMOC.zm_cryptKeyStore.lastPreKey() - ) - } - return client } @@ -728,7 +711,6 @@ class CallingRequestStrategyTests: MessagingTest { } func test_ThatItHandlesMLSRejectMessage() throws { - var sentMessage: GenericMessageEntity? let (user1AVSIdentifier, client1RemoteIdentifier, conversationAVSID) = try syncMOC.performAndWait { [self] in // Given createMLSSelfConversation() @@ -755,10 +737,6 @@ class CallingRequestStrategyTests: MessagingTest { syncMOC.saveOrRollback() - mockMessageSender.sendMessageMessage_MockMethod = { message in - sentMessage = message as? GenericMessageEntity - } - let mockMLSService = MockMLSServiceInterface() syncMOC.mlsService = mockMLSService @@ -767,6 +745,11 @@ class CallingRequestStrategyTests: MessagingTest { return (user1.avsIdentifier, client1.remoteIdentifier!, conversationAVSID) } + var sentMessage: GenericMessageEntity? + mockMessageSender.sendMessageMessage_MockMethod = { message in + sentMessage = message as? GenericMessageEntity + } + // Targeting one client let avsClient1 = AVSClient(userId: user1AVSIdentifier, clientId: client1RemoteIdentifier) let targets = [avsClient1] diff --git a/wire-ios-sync-engine/Tests/Source/Use cases/GetUserClientFingerprintUseCaseTests.swift b/wire-ios-sync-engine/Tests/Source/Use cases/GetUserClientFingerprintUseCaseTests.swift index bd1172563ac..a520be38b8a 100644 --- a/wire-ios-sync-engine/Tests/Source/Use cases/GetUserClientFingerprintUseCaseTests.swift +++ b/wire-ios-sync-engine/Tests/Source/Use cases/GetUserClientFingerprintUseCaseTests.swift @@ -104,7 +104,7 @@ final class GetUserClientFingerprintUseCaseTests: MessagingTest { // MARK: - localFingerprint - func test_itLoadsLocalFingerprint_ProteusViaCoreCryptoFlagEnabled() async { + func test_itLoadsLocalFingerprint() async { // GIVEN sut = createSut() diff --git a/wire-ios-utilities/Source/DeveloperFlag.swift b/wire-ios-utilities/Source/DeveloperFlag.swift index 084a136ed62..e73f8a27730 100644 --- a/wire-ios-utilities/Source/DeveloperFlag.swift +++ b/wire-ios-utilities/Source/DeveloperFlag.swift @@ -35,7 +35,6 @@ public enum DeveloperFlag: String, CaseIterable { case ignoreIncomingEvents case multibackend case newRegistration - case proteusViaCoreCrypto case showCreateMLSGroupToggle case showUnreadConversationsFilter case skipMLSMessagesDecryption @@ -56,9 +55,6 @@ public enum DeveloperFlag: String, CaseIterable { case .showCreateMLSGroupToggle: "Turn on to show the MLS toggle when creating a new group." - case .proteusViaCoreCrypto: - "Turn on to use CoreCrypto for proteus messaging." - case .forceDatabaseLoadingFailure: "Turn on to force database loading failure in the process of database migration" @@ -136,8 +132,6 @@ public enum DeveloperFlag: String, CaseIterable { switch self { case .createLegacyBackups: "CreateLegacyBackupsEnabled" - case .proteusViaCoreCrypto: - "ProteusByCoreCryptoEnabled" case .forceDatabaseLoadingFailure: "ForceDatabaseLoadingFailure" case .ignoreIncomingEvents: diff --git a/wire-ios-utilities/WireUtilities-Info.plist b/wire-ios-utilities/WireUtilities-Info.plist index 5651f3bcb66..4ed7d8e640a 100644 --- a/wire-ios-utilities/WireUtilities-Info.plist +++ b/wire-ios-utilities/WireUtilities-Info.plist @@ -4,8 +4,6 @@ MultibackendEnabled $(MULTIBACKEND_ENABLED) - ProteusByCoreCryptoEnabled - $(PROTEUS_BY_CORECRYPTO_ENABLED) WireAuthenticationEnabled $(WIRE_AUTHENTICATION_ENABLED) CreateLegacyBackupsEnabled diff --git a/wire-ios/Configuration/Developer-Flags.xcconfig b/wire-ios/Configuration/Developer-Flags.xcconfig index 39e50628f83..7da38d42395 100644 --- a/wire-ios/Configuration/Developer-Flags.xcconfig +++ b/wire-ios/Configuration/Developer-Flags.xcconfig @@ -16,6 +16,5 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -PROTEUS_BY_CORECRYPTO_ENABLED=1 WIRE_AUTHENTICATION_ENABLED=1 MULTIBACKEND_ENABLED=1 diff --git a/wire-ios/Wire-iOS Tests/AVAsset/AVURLAsset+conversionTests.swift b/wire-ios/Wire-iOS Tests/AVAsset/AVURLAsset+conversionTests.swift index 766c6959d71..f05399f85d0 100644 --- a/wire-ios/Wire-iOS Tests/AVAsset/AVURLAsset+conversionTests.swift +++ b/wire-ios/Wire-iOS Tests/AVAsset/AVURLAsset+conversionTests.swift @@ -22,18 +22,6 @@ import XCTest final class AVURLAsset_conversionTests: XCTestCase { - override static func setUp() { - super.setUp() - DeveloperFlag.storage = UserDefaults(suiteName: UUID().uuidString)! - var flag = DeveloperFlag.proteusViaCoreCrypto - flag.isOn = false - } - - override static func tearDown() { - super.tearDown() - DeveloperFlag.storage = UserDefaults.standard - } - func testThatVideoIsConvertedToUploadFormat() { // GIVEN let videoURL = urlForResource(inTestBundleNamed: "video.mp4") diff --git a/wire-ios/WireUITests/TeamManageTests.swift b/wire-ios/WireUITests/TeamManageTests.swift index e2680712f2b..c4ae7de8b0c 100644 --- a/wire-ios/WireUITests/TeamManageTests.swift +++ b/wire-ios/WireUITests/TeamManageTests.swift @@ -177,7 +177,7 @@ final class TeamManageTests: WireUITestCase { conversationDetailsPage.userCells .matching(NSPredicate(format: "label == %@", teamMembers[0].name)) .firstMatch - .exists, + .waitForExistence(timeout: 5), "User \(teamMembers[0].name) is not present in group" ) }