diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index bbfcb337e..c6f7388dc 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -685,6 +685,8 @@ B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */; }; B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */; }; DB1392A2332C3CAF6C9962EF /* Pods_RiotPods_RiotNSE.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4D418D054E4032F2CFA8B51 /* Pods_RiotPods_RiotNSE.framework */; }; + EC2B4EF124A1EEBD005EB739 /* DataProtectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2B4EF024A1EEBD005EB739 /* DataProtectionHelper.swift */; }; + EC2B4EF224A1EF34005EB739 /* DataProtectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2B4EF024A1EEBD005EB739 /* DataProtectionHelper.swift */; }; EC85D6AE2477DC89002C44C9 /* RoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D6AD2477DC89002C44C9 /* RoundedButton.swift */; }; EC85D7142477DCD7002C44C9 /* KeyVerificationScanConfirmationViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D70C2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewState.swift */; }; EC85D7152477DCD7002C44C9 /* KeyVerificationScanConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D70D2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewController.swift */; }; @@ -1692,6 +1694,7 @@ BABB6681FBD79219B1213D6C /* Pods-RiotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotTests.debug.xcconfig"; path = "Target Support Files/Pods-RiotTests/Pods-RiotTests.debug.xcconfig"; sourceTree = ""; }; E2599D0ECB8DD206624E450B /* Pods-RiotPods-SiriIntents.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-SiriIntents.release.xcconfig"; path = "Target Support Files/Pods-RiotPods-SiriIntents/Pods-RiotPods-SiriIntents.release.xcconfig"; sourceTree = ""; }; E4D418D054E4032F2CFA8B51 /* Pods_RiotPods_RiotNSE.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_RiotNSE.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EC2B4EF024A1EEBD005EB739 /* DataProtectionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProtectionHelper.swift; sourceTree = ""; }; EC85D6AD2477DC89002C44C9 /* RoundedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoundedButton.swift; sourceTree = ""; }; EC85D70C2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationScanConfirmationViewState.swift; sourceTree = ""; }; EC85D70D2477DCD7002C44C9 /* KeyVerificationScanConfirmationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationScanConfirmationViewController.swift; sourceTree = ""; }; @@ -4440,6 +4443,7 @@ F083BC151E7009EC00A9B29C /* Tools.m */, B1DB4F0D22316FFF0065DBFA /* UserNameColorGenerator.swift */, B197B7C5243DE947005ABBF3 /* EncryptionTrustLevelBadgeImageHelper.swift */, + EC2B4EF024A1EEBD005EB739 /* DataProtectionHelper.swift */, ); path = Utils; sourceTree = ""; @@ -4611,6 +4615,7 @@ }; EC85D7422477E5F7002C44C9 = { CreatedOnToolsVersion = 11.3.1; + LastSwiftMigration = 1140; }; F094A9A11B78D8F000B1FBBF = { CreatedOnToolsVersion = 6.2; @@ -5106,6 +5111,7 @@ files = ( EC85D74F2477E8EB002C44C9 /* RiotSettings.swift in Sources */, EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */, + EC2B4EF224A1EF34005EB739 /* DataProtectionHelper.swift in Sources */, EC85D7462477E5F7002C44C9 /* NotificationService.swift in Sources */, EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */, EC85D755247C0F84002C44C9 /* Constants.swift in Sources */, @@ -5212,6 +5218,7 @@ B110872521F098F0003554A5 /* ActivityIndicatorPresenter.swift in Sources */, 32242F1521E8FBA900725742 /* DarkTheme.swift in Sources */, B1D211E222BD193C00D939BD /* ReactionsMenuViewModel.swift in Sources */, + EC2B4EF124A1EEBD005EB739 /* DataProtectionHelper.swift in Sources */, B140B4A621F89E7600E3F5FE /* KeyBackupSetupCoordinatorBridgePresenter.swift in Sources */, B1B5577420EE702900210D55 /* WidgetViewController.m in Sources */, B1DCC63122E7026F00625807 /* EmojiPickerHeaderView.swift in Sources */, diff --git a/Riot/Utils/DataProtectionHelper.swift b/Riot/Utils/DataProtectionHelper.swift new file mode 100644 index 000000000..5103b82cb --- /dev/null +++ b/Riot/Utils/DataProtectionHelper.swift @@ -0,0 +1,62 @@ +/* +Copyright 2020 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 + +final class DataProtectionHelper { + + static func isDeviceInRebootedAndLockedState(appGroupIdentifier: String? = nil) -> Bool { + do { + let str = String.unique + let dummyData = str.data(using: .utf8)! + + var url: URL! + if let identifier = appGroupIdentifier { + let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: identifier) + if containerURL == nil { + url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] + } else { + url = containerURL?.appendingPathComponent("Library/Caches") + } + } else { + url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] + } + + url = url.appendingPathComponent(String.unique) + + try dummyData.write(to: url, options: .completeFileProtectionUntilFirstUserAuthentication) + let readData = try Data(contentsOf: url) + let readString = String(data: readData, encoding: .utf8) + try FileManager.default.removeItem(at: url) + if readString != str { + return true + } + } catch { + return true + } + return false + } + +} + +extension String { + + /// Returns a globally unique string + static var unique: String { + return ProcessInfo.processInfo.globallyUniqueString + } + +} diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 0e4a953a3..05ca60bd5 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -37,6 +37,11 @@ class NotificationService: UNNotificationServiceExtension { // set app-group identifier first MXSDKOptions.sharedInstance().applicationGroupIdentifier = "group.im.vector" + if DataProtectionHelper.isDeviceInRebootedAndLockedState(appGroupIdentifier: MXSDKOptions.sharedInstance().applicationGroupIdentifier) { + // kill the process in this state, this leads for the notification to be displayed as came from APNS + exit(0) + } + // setup logs setupLogger()