diff --git a/CHANGES.md b/CHANGES.md index 3484fcf48..c24df14b8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,15 @@ +## Changes in 1.10.0 (2023-02-02) + +🙌 Improvements + +- CryptoV2: Generate Crypto SDK store key ([#7310](https://github.com/vector-im/element-ios/pull/7310)) +- Backup: Display backup import progress ([#7319](https://github.com/vector-im/element-ios/pull/7319)) +- CryptoV2: Reset Crypto SDK on logout ([#7323](https://github.com/vector-im/element-ios/pull/7323)) +- CryptoV2: Refresh notification service on crypto change ([#7332](https://github.com/vector-im/element-ios/pull/7332)) +- CryptoV2: Enable Crypto SDK for production ([#7333](https://github.com/vector-im/element-ios/pull/7333)) +- Upgrade MatrixSDK version ([v0.25.0](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.25.0)). + + ## Changes in 1.9.17 (2023-01-26) 🙌 Improvements diff --git a/Config/AppVersion.xcconfig b/Config/AppVersion.xcconfig index 210603b23..d203e4e63 100644 --- a/Config/AppVersion.xcconfig +++ b/Config/AppVersion.xcconfig @@ -15,5 +15,5 @@ // // Version -MARKETING_VERSION = 1.9.17 -CURRENT_PROJECT_VERSION = 1.9.17 +MARKETING_VERSION = 1.10.0 +CURRENT_PROJECT_VERSION = 1.10.0 diff --git a/Config/CommonConfiguration.swift b/Config/CommonConfiguration.swift index f3172a710..35001b1e4 100644 --- a/Config/CommonConfiguration.swift +++ b/Config/CommonConfiguration.swift @@ -92,11 +92,14 @@ class CommonConfiguration: NSObject, Configurable { sdkOptions.enableNewClientInformationFeature = RiotSettings.shared.enableClientInformationFeature - #if DEBUG if sdkOptions.isCryptoSDKAvailable { - sdkOptions.enableCryptoSDK = RiotSettings.shared.enableCryptoSDK + let isEnabled = RiotSettings.shared.enableCryptoSDK + MXLog.debug("[CommonConfiguration] Crypto SDK is \(isEnabled ? "enabled" : "disabled")") + sdkOptions.enableCryptoSDK = isEnabled + sdkOptions.enableStartupProgress = isEnabled + } else { + MXLog.debug("[CommonConfiguration] Crypto SDK is not available)") } - #endif } private func makeASCIIUserAgent() -> String? { diff --git a/Config/CryptoSDKConfiguration.swift b/Config/CryptoSDKConfiguration.swift new file mode 100644 index 000000000..3c922e547 --- /dev/null +++ b/Config/CryptoSDKConfiguration.swift @@ -0,0 +1,42 @@ +// +// Copyright 2023 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// Configuration for enabling / disabling Matrix Crypto SDK +@objcMembers class CryptoSDKConfiguration: NSObject { + static let shared = CryptoSDKConfiguration() + + func enable() { + guard MXSDKOptions.sharedInstance().isCryptoSDKAvailable else { + return + } + + RiotSettings.shared.enableCryptoSDK = true + MXSDKOptions.sharedInstance().enableCryptoSDK = true + MXSDKOptions.sharedInstance().enableStartupProgress = true + + MXLog.debug("[CryptoSDKConfiguration] enabling Crypto SDK") + } + + func disable() { + RiotSettings.shared.enableCryptoSDK = false + MXSDKOptions.sharedInstance().enableCryptoSDK = false + MXSDKOptions.sharedInstance().enableStartupProgress = false + + MXLog.debug("[CryptoSDKConfiguration] disabling Crypto SDK") + } +} diff --git a/Podfile b/Podfile index 35ba935b2..376ec852a 100644 --- a/Podfile +++ b/Podfile @@ -16,7 +16,7 @@ use_frameworks! # - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixSDKVersion = '= 0.24.8' +$matrixSDKVersion = '= 0.25.0' # $matrixSDKVersion = :local # $matrixSDKVersion = { :branch => 'develop'} # $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } } diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 5d7ac9e4a..3b2871460 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -804,9 +804,9 @@ Tap the + to start adding people."; "settings_labs_enable_new_app_layout" = "New Application Layout"; "settings_labs_enable_wysiwyg_composer" = "Try out the rich text editor"; "settings_labs_enable_voice_broadcast" = "Voice broadcast"; -"settings_labs_enable_crypto_sdk" = "Enable new rust-based Crypto SDK"; -"settings_labs_confirm_crypto_sdk" = "This action cannot be undone"; -"settings_labs_disable_crypto_sdk" = "Crypto SDK is enabled. To disable please reinstall the app"; +"settings_labs_enable_crypto_sdk" = "Rust end-to-end encryption"; +"settings_labs_confirm_crypto_sdk" = "Please be advised that as this feature is still in its experimental stage, it may not function as expected and could potentially have unintended consequences. To revert the feature, simply log out and log back in. Use at your own discretion and with caution."; +"settings_labs_disable_crypto_sdk" = "Rust end-to-end encryption (log out to disable)"; "settings_version" = "Version %@"; "settings_olm_version" = "Olm Version %@"; @@ -1469,6 +1469,7 @@ Tap the + to start adding people."; // Recover from private key "key_backup_recover_from_private_key_info" = "Restoring backup…"; +"key_backup_recover_from_private_key_progress" = "%@%% Complete"; // Recover from passphrase diff --git a/Riot/Categories/MatrixSDKCrypto+LocalizedError.swift b/Riot/Categories/MatrixSDKCrypto+LocalizedError.swift new file mode 100644 index 000000000..4b314a0c1 --- /dev/null +++ b/Riot/Categories/MatrixSDKCrypto+LocalizedError.swift @@ -0,0 +1,26 @@ +// +// Copyright 2023 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import MatrixSDKCrypto + +extension CryptoStoreError: LocalizedError { + public var errorDescription: String? { + // We dont really care about the type of error here when showing to the user. + // Details about the error are tracked independently + return VectorL10n.e2eNeedLogInAgain + } +} diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index d42977875..8c676d666 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2755,6 +2755,10 @@ public class VectorL10n: NSObject { public static var keyBackupRecoverFromPrivateKeyInfo: String { return VectorL10n.tr("Vector", "key_backup_recover_from_private_key_info") } + /// %@%% Complete + public static func keyBackupRecoverFromPrivateKeyProgress(_ p1: String) -> String { + return VectorL10n.tr("Vector", "key_backup_recover_from_private_key_progress", p1) + } /// Use your Security Key to unlock your secure message history public static var keyBackupRecoverFromRecoveryKeyInfo: String { return VectorL10n.tr("Vector", "key_backup_recover_from_recovery_key_info") @@ -7583,7 +7587,7 @@ public class VectorL10n: NSObject { public static var settingsLabs: String { return VectorL10n.tr("Vector", "settings_labs") } - /// This action cannot be undone + /// Please be advised that as this feature is still in its experimental stage, it may not function as expected and could potentially have unintended consequences. To revert the feature, simply log out and log back in. Use at your own discretion and with caution. public static var settingsLabsConfirmCryptoSdk: String { return VectorL10n.tr("Vector", "settings_labs_confirm_crypto_sdk") } @@ -7591,7 +7595,7 @@ public class VectorL10n: NSObject { public static var settingsLabsCreateConferenceWithJitsi: String { return VectorL10n.tr("Vector", "settings_labs_create_conference_with_jitsi") } - /// Crypto SDK is enabled. To disable please reinstall the app + /// Rust end-to-end encryption (log out to disable) public static var settingsLabsDisableCryptoSdk: String { return VectorL10n.tr("Vector", "settings_labs_disable_crypto_sdk") } @@ -7607,7 +7611,7 @@ public class VectorL10n: NSObject { public static var settingsLabsEnableAutoReportDecryptionErrors: String { return VectorL10n.tr("Vector", "settings_labs_enable_auto_report_decryption_errors") } - /// Enable new rust-based Crypto SDK + /// Rust end-to-end encryption public static var settingsLabsEnableCryptoSdk: String { return VectorL10n.tr("Vector", "settings_labs_enable_crypto_sdk") } diff --git a/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift b/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift index 5085e9efb..484a63832 100644 --- a/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift +++ b/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift @@ -31,6 +31,7 @@ class EncryptionKeyManager: NSObject, MXKeyProviderDelegate { private static let cryptoOlmPickleKey: KeyValueStoreKey = "cryptoOlmPickleKey" private static let roomLastMessageIv: KeyValueStoreKey = "roomLastMessageIv" private static let roomLastMessageAesKey: KeyValueStoreKey = "roomLastMessageAesKey" + private static let cryptoSDKStoreKey: KeyValueStoreKey = "cryptoSDKStoreKey" private let keychainStore: KeyValueStore = KeychainStore(withKeychain: Keychain(service: keychainService, accessGroup: BuildSettings.keychainAccessGroup)) @@ -47,6 +48,7 @@ class EncryptionKeyManager: NSObject, MXKeyProviderDelegate { generateKeyIfNotExists(forKey: EncryptionKeyManager.cryptoOlmPickleKey, size: 32) generateIvIfNotExists(forKey: EncryptionKeyManager.roomLastMessageIv) generateAesKeyIfNotExists(forKey: EncryptionKeyManager.roomLastMessageAesKey) + generateKeyIfNotExists(forKey: EncryptionKeyManager.cryptoSDKStoreKey, size: 32) assert(keychainStore.containsObject(forKey: EncryptionKeyManager.contactsIv), "[EncryptionKeyManager] initKeys: Failed to generate IV for acount") assert(keychainStore.containsObject(forKey: EncryptionKeyManager.contactsAesKey), "[EncryptionKeyManager] initKeys: Failed to generate AES Key for acount") @@ -55,6 +57,7 @@ class EncryptionKeyManager: NSObject, MXKeyProviderDelegate { assert(keychainStore.containsObject(forKey: EncryptionKeyManager.cryptoOlmPickleKey), "[EncryptionKeyManager] initKeys: Failed to generate Key for olm pickle key") assert(keychainStore.containsObject(forKey: EncryptionKeyManager.roomLastMessageIv), "[EncryptionKeyManager] initKeys: Failed to generate IV for room last message") assert(keychainStore.containsObject(forKey: EncryptionKeyManager.roomLastMessageAesKey), "[EncryptionKeyManager] initKeys: Failed to generate AES Key for room last message encryption") + assert(keychainStore.containsObject(forKey: EncryptionKeyManager.cryptoSDKStoreKey), "[EncryptionKeyManager] initKeys: Failed to generate Key for crypto sdk store") } // MARK: - MXKeyProviderDelegate @@ -64,6 +67,7 @@ class EncryptionKeyManager: NSObject, MXKeyProviderDelegate { || dataType == MXKAccountManagerDataType || dataType == MXCryptoOlmPickleKeyDataType || dataType == MXRoomLastMessageDataType + || dataType == MXCryptoSDKStoreKeyDataType } func hasKeyForData(ofType dataType: String) -> Bool { @@ -77,7 +81,10 @@ class EncryptionKeyManager: NSObject, MXKeyProviderDelegate { case MXRoomLastMessageDataType: return keychainStore.containsObject(forKey: EncryptionKeyManager.roomLastMessageIv) && keychainStore.containsObject(forKey: EncryptionKeyManager.roomLastMessageAesKey) + case MXCryptoSDKStoreKeyDataType: + return keychainStore.containsObject(forKey: EncryptionKeyManager.cryptoSDKStoreKey) default: + MXLog.warning("[EncryptionKeyManager] hasKeyForData: No key for \(dataType)") return false } } @@ -103,7 +110,12 @@ class EncryptionKeyManager: NSObject, MXKeyProviderDelegate { let aesKey = try? keychainStore.data(forKey: EncryptionKeyManager.roomLastMessageAesKey) { return MXAesKeyData(iv: ivKey, key: aesKey) } + case MXCryptoSDKStoreKeyDataType: + if let key = try? keychainStore.data(forKey: EncryptionKeyManager.cryptoSDKStoreKey) { + return MXRawDataKey(key: key) + } default: + MXLog.failure("[EncryptionKeyManager] keyDataForData: Attempting to get data for unknown type", dataType) return nil } return nil diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index d9e64a1af..260a0aca7 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -192,11 +192,9 @@ final class RiotSettings: NSObject { @UserDefault(key: "enableVoiceBroadcast", defaultValue: false, storage: defaults) var enableVoiceBroadcast - #if DEBUG /// Flag indicating if we are using rust-based `MatrixCryptoSDK` instead of `MatrixSDK`'s internal crypto module @UserDefault(key: "enableCryptoSDK", defaultValue: false, storage: defaults) var enableCryptoSDK - #endif // MARK: Calls diff --git a/Riot/Modules/Analytics/Analytics.swift b/Riot/Modules/Analytics/Analytics.swift index b608c862e..60e1560b9 100644 --- a/Riot/Modules/Analytics/Analytics.swift +++ b/Riot/Modules/Analytics/Analytics.swift @@ -324,6 +324,11 @@ extension Analytics { viewRoomTrigger = .unknown capture(event: event) } + + func trackCryptoSDKEnabled() { + let event = AnalyticsEvent.CryptoSDKEnabled() + capture(event: event) + } } // MARK: - MXAnalyticsDelegate @@ -393,3 +398,14 @@ extension Analytics: MXAnalyticsDelegate { monitoringClient.trackNonFatalIssue(issue, details: details) } } + +/// iOS-specific analytics event triggered when users select the Crypto SDK labs option +/// +/// Due to this event being iOS only, and temporary during gradual rollout of Crypto SDK, +/// this event is not added into the shared analytics schema +extension AnalyticsEvent { + struct CryptoSDKEnabled: AnalyticsEventProtocol { + let eventName = "CryptoSDKEnabled" + let properties: [String: Any] = [:] + } +} diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 7bf51dd46..302ba990e 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -2183,6 +2183,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // Clear cache [self clearCache]; + // Reset Crypto SDK configuration (labs flag for which crypto module to use) + [CryptoSDKConfiguration.shared disable]; + // Reset key backup banner preferences [SecureBackupBannerPreferences.shared reset]; diff --git a/Riot/Modules/Home/AllChats/AllChatsViewController.swift b/Riot/Modules/Home/AllChats/AllChatsViewController.swift index 4b7ff566c..3e689a42e 100644 --- a/Riot/Modules/Home/AllChats/AllChatsViewController.swift +++ b/Riot/Modules/Home/AllChats/AllChatsViewController.swift @@ -885,10 +885,12 @@ extension AllChatsViewController: SplitViewMasterViewControllerProtocol { return } - let devices = mainSession.crypto.devices(forUser: mainSession.myUserId).values - let userHasOneUnverifiedDevice = devices.contains(where: {!$0.trustLevel.isCrossSigningVerified}) - if userHasOneUnverifiedDevice { - presentReviewUnverifiedSessionsAlert(with: session) + if let userId = mainSession.myUserId, let crypto = mainSession.crypto { + let devices = crypto.devices(forUser: userId).values + let userHasOneUnverifiedDevice = devices.contains(where: {!$0.trustLevel.isCrossSigningVerified}) + if userHasOneUnverifiedDevice { + presentReviewUnverifiedSessionsAlert(with: session) + } } } diff --git a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.storyboard b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.storyboard index 1c8ba341c..42e99205e 100644 --- a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.storyboard +++ b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.storyboard @@ -1,25 +1,23 @@ - - - - + + - + - + - + - + @@ -40,15 +38,24 @@ + + + + @@ -72,6 +79,7 @@ + @@ -79,10 +87,10 @@ - + diff --git a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.swift b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.swift index 1aaf96e62..a02fed201 100644 --- a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewController.swift @@ -29,6 +29,7 @@ final class KeyBackupRecoverFromPrivateKeyViewController: UIViewController { @IBOutlet private weak var shieldImageView: UIImageView! @IBOutlet private weak var informationLabel: UILabel! + @IBOutlet private weak var progressLabel: UILabel! // MARK: Private @@ -118,8 +119,8 @@ final class KeyBackupRecoverFromPrivateKeyViewController: UIViewController { private func render(viewState: KeyBackupRecoverFromPrivateKeyViewState) { switch viewState { - case .loading: - self.renderLoading() + case .loading(let progress): + self.renderLoading(progress: progress) case .loaded: self.renderLoaded() case .error(let error): @@ -127,8 +128,11 @@ final class KeyBackupRecoverFromPrivateKeyViewController: UIViewController { } } - private func renderLoading() { + private func renderLoading(progress: Double) { self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) + + let percent = Int(round(progress * 100)) + self.progressLabel.text = VectorL10n.keyBackupRecoverFromPrivateKeyProgress("\(percent)") } private func renderLoaded() { diff --git a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModel.swift b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModel.swift index cef1d7c0c..04fb48850 100644 --- a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModel.swift @@ -27,6 +27,7 @@ final class KeyBackupRecoverFromPrivateKeyViewModel: KeyBackupRecoverFromPrivate private let keyBackup: MXKeyBackup private var currentHTTPOperation: MXHTTPOperation? private let keyBackupVersion: MXKeyBackupVersion + private var progressUpdateTimer: Timer? // MARK: Public @@ -56,7 +57,14 @@ final class KeyBackupRecoverFromPrivateKeyViewModel: KeyBackupRecoverFromPrivate private func recoverWithPrivateKey() { - self.update(viewState: .loading) + self.update(viewState: .loading(0)) + + // Update loading progress every second until no longer loading + progressUpdateTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in + if let progress = self?.keyBackup.importProgress { + self?.update(viewState: .loading(progress.fractionCompleted)) + } + } self.currentHTTPOperation = keyBackup.restore(usingPrivateKeyKeyBackup: keyBackupVersion, room: nil, session: nil, success: { [weak self] (_, _) in guard let self = self else { @@ -91,6 +99,11 @@ final class KeyBackupRecoverFromPrivateKeyViewModel: KeyBackupRecoverFromPrivate } private func update(viewState: KeyBackupRecoverFromPrivateKeyViewState) { + if case .loading = viewState {} else { + progressUpdateTimer?.invalidate() + progressUpdateTimer = nil + } + self.viewDelegate?.keyBackupRecoverFromPrivateKeyViewModel(self, didUpdateViewState: viewState) } } diff --git a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewState.swift b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewState.swift index bdd417853..b4ef05fb9 100644 --- a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewState.swift +++ b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewState.swift @@ -20,7 +20,7 @@ import Foundation /// KeyBackupRecoverFromPrivateKeyViewController view state enum KeyBackupRecoverFromPrivateKeyViewState { - case loading + case loading(Double) case loaded case error(Error) } diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 90533cfd1..ea8b57b22 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -588,12 +588,10 @@ ChangePasswordCoordinatorBridgePresenterDelegate> if (BuildSettings.settingsScreenShowLabSettings) { Section *sectionLabs = [Section sectionWithTag:SECTION_TAG_LABS]; - #if DEBUG if (MXSDKOptions.sharedInstance.isCryptoSDKAvailable) { [sectionLabs addRowWithTag:LABS_ENABLE_CRYPTO_SDK]; } - #endif [sectionLabs addRowWithTag:LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX]; [sectionLabs addRowWithTag:LABS_ENABLE_THREADS_INDEX]; @@ -2593,7 +2591,6 @@ ChangePasswordCoordinatorBridgePresenterDelegate> } else { - #if DEBUG if (row == LABS_ENABLE_CRYPTO_SDK) { MXKTableViewCellWithLabelAndSwitch *labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; @@ -2602,11 +2599,10 @@ ChangePasswordCoordinatorBridgePresenterDelegate> labelAndSwitchCell.mxkSwitch.on = isEnabled; [labelAndSwitchCell.mxkSwitch setEnabled:!isEnabled]; labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; - [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleEnableCryptoSDKFeature:) forControlEvents:UIControlEventTouchUpInside]; + [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(enableCryptoSDKFeature:) forControlEvents:UIControlEventTouchUpInside]; cell = labelAndSwitchCell; } - #endif } } else if (section == SECTION_TAG_SECURITY) @@ -3379,17 +3375,14 @@ ChangePasswordCoordinatorBridgePresenterDelegate> RiotSettings.shared.enableVoiceBroadcast = sender.isOn; } -#if DEBUG -- (void)toggleEnableCryptoSDKFeature:(UISwitch *)sender +- (void)enableCryptoSDKFeature:(UISwitch *)sender { - BOOL isEnabled = sender.isOn; - MXWeakify(self); - [currentAlert dismissViewControllerAnimated:NO completion:nil]; - UIAlertController *confirmationAlert = [UIAlertController alertControllerWithTitle:nil + UIAlertController *confirmationAlert = [UIAlertController alertControllerWithTitle:VectorL10n.settingsLabsEnableCryptoSdk message:VectorL10n.settingsLabsConfirmCryptoSdk preferredStyle:UIAlertControllerStyleAlert]; + MXWeakify(self); [confirmationAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { MXStrongifyAndReturnIfNil(self); self->currentAlert = nil; @@ -3398,17 +3391,16 @@ ChangePasswordCoordinatorBridgePresenterDelegate> }]]; [confirmationAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n continue] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - MXStrongifyAndReturnIfNil(self); - RiotSettings.shared.enableCryptoSDK = isEnabled; - MXSDKOptions.sharedInstance.enableCryptoSDK = isEnabled; + [CryptoSDKConfiguration.shared enable]; + [Analytics.shared trackCryptoSDKEnabled]; + [[AppDelegate theDelegate] reloadMatrixSessions:YES]; }]]; [self presentViewController:confirmationAlert animated:YES completion:nil]; currentAlert = confirmationAlert; } -#endif - (void)togglePinRoomsWithMissedNotif:(UISwitch *)sender { diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index f9779641f..6560290ab 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -41,6 +41,7 @@ class NotificationService: UNNotificationServiceExtension { private var ongoingVoIPPushRequests: [String: Bool] = [:] private var userAccount: MXKAccount? + private var isCryptoSDKEnabled = false /// Best attempt contents. Will be updated incrementally, if something fails during the process, this best attempt content will be showed as notification. Keys are eventId's private var bestAttemptContents: [String: UNMutableNotificationContent] = [:] @@ -195,9 +196,10 @@ class NotificationService: UNNotificationServiceExtension { self.userAccount = MXKAccountManager.shared()?.activeAccounts.first if let userAccount = userAccount { Self.backgroundServiceInitQueue.sync { - if NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials { + if hasChangedCryptoSDK() || NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials { MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: BEFORE") self.logMemory() + NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials, persistTokenDataHandler: { persistTokenDataHandler in MXKAccountManager.shared().readAndWriteCredentials(persistTokenDataHandler) }, unauthenticatedHandler: { error, softLogout, refreshTokenAuth, completion in @@ -214,6 +216,16 @@ class NotificationService: UNNotificationServiceExtension { } } + /// Determine whether we have switched from using crypto v1 to v2 or vice versa which will require + /// rebuilding `MXBackgroundSyncService` + private func hasChangedCryptoSDK() -> Bool { + guard isCryptoSDKEnabled != RiotSettings.shared.enableCryptoSDK else { + return false + } + isCryptoSDKEnabled = RiotSettings.shared.enableCryptoSDK + return true + } + /// Attempts to preprocess payload and attach room display name to the best attempt content /// - Parameters: /// - eventId: Event identifier to mutate best attempt content