android, desktop: adapted code for self destruct for ios logic (#3643)
* android, desktop: adapted code for self destruct for ios logic * init db in case of periodic && self destruct enabled
This commit is contained in:
parent
61c507e7da
commit
a853ba3a15
@ -3,11 +3,12 @@ package chat.simplex.app
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import chat.simplex.app.*
|
|
||||||
import chat.simplex.app.SimplexService.Companion.showPassphraseNotification
|
import chat.simplex.app.SimplexService.Companion.showPassphraseNotification
|
||||||
import chat.simplex.common.model.ChatController
|
import chat.simplex.common.model.ChatController
|
||||||
import chat.simplex.common.views.helpers.DBMigrationResult
|
import chat.simplex.common.views.helpers.DBMigrationResult
|
||||||
import chat.simplex.app.BuildConfig
|
import chat.simplex.common.platform.chatModel
|
||||||
|
import chat.simplex.common.platform.initChatControllerAndRunMigrations
|
||||||
|
import chat.simplex.common.views.helpers.DatabaseUtils
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@ -57,6 +58,10 @@ class MessagesFetcherWork(
|
|||||||
val durationSeconds = inputData.getInt(INPUT_DATA_DURATION, 60)
|
val durationSeconds = inputData.getInt(INPUT_DATA_DURATION, 60)
|
||||||
var shouldReschedule = true
|
var shouldReschedule = true
|
||||||
try {
|
try {
|
||||||
|
// In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here
|
||||||
|
if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
withTimeout(durationSeconds * 1000L) {
|
withTimeout(durationSeconds * 1000L) {
|
||||||
val chatController = ChatController
|
val chatController = ChatController
|
||||||
SimplexService.waitDbMigrationEnds(chatController)
|
SimplexService.waitDbMigrationEnds(chatController)
|
||||||
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.sync.withLock
|
|||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
const val TAG = "SIMPLEX"
|
const val TAG = "SIMPLEX"
|
||||||
|
|
||||||
@ -46,8 +47,8 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
|||||||
try {
|
try {
|
||||||
Looper.loop()
|
Looper.loop()
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
if (e.message != null && e.message!!.startsWith("Unable to start activity")) {
|
if (e is UnsatisfiedLinkError || e.message?.startsWith("Unable to start activity") == true) {
|
||||||
android.os.Process.killProcess(android.os.Process.myPid())
|
Process.killProcess(Process.myPid())
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
// Send it to our exception handled because it will not get the exception otherwise
|
// Send it to our exception handled because it will not get the exception otherwise
|
||||||
@ -63,7 +64,9 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
|||||||
tmpDir.deleteRecursively()
|
tmpDir.deleteRecursively()
|
||||||
tmpDir.mkdir()
|
tmpDir.mkdir()
|
||||||
|
|
||||||
initChatControllerAndRunMigrations(false)
|
if (DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
ProcessLifecycleOwner.get().lifecycle.addObserver(this@SimplexApp)
|
ProcessLifecycleOwner.get().lifecycle.addObserver(this@SimplexApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,10 @@ class SimplexService: Service() {
|
|||||||
stopSelf()
|
stopSelf()
|
||||||
} else {
|
} else {
|
||||||
isServiceStarted = true
|
isServiceStarted = true
|
||||||
|
// In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here
|
||||||
|
if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,21 +41,20 @@ val appPreferences: AppPreferences
|
|||||||
|
|
||||||
val chatController: ChatController = ChatController
|
val chatController: ChatController = ChatController
|
||||||
|
|
||||||
fun initChatControllerAndRunMigrations(ignoreSelfDestruct: Boolean) {
|
fun initChatControllerAndRunMigrations() {
|
||||||
if (ignoreSelfDestruct || DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
withBGApi {
|
||||||
withBGApi {
|
if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) {
|
||||||
if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) {
|
initChatController(startChat = ::showStartChatAfterRestartAlert)
|
||||||
initChatController(startChat = ::showStartChatAfterRestartAlert)
|
} else {
|
||||||
} else {
|
initChatController()
|
||||||
initChatController()
|
|
||||||
}
|
|
||||||
runMigrations()
|
|
||||||
}
|
}
|
||||||
|
runMigrations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: () -> CompletableDeferred<Boolean> = { CompletableDeferred(true) }) {
|
suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: () -> CompletableDeferred<Boolean> = { CompletableDeferred(true) }) {
|
||||||
try {
|
try {
|
||||||
|
if (chatModel.ctrlInitInProgress.value) return
|
||||||
chatModel.ctrlInitInProgress.value = true
|
chatModel.ctrlInitInProgress.value = true
|
||||||
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
|
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
|
||||||
val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
|
val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
|
||||||
|
@ -460,10 +460,10 @@ suspend fun deleteChatAsync(m: ChatModel) {
|
|||||||
m.controller.apiDeleteStorage()
|
m.controller.apiDeleteStorage()
|
||||||
DatabaseUtils.ksDatabasePassword.remove()
|
DatabaseUtils.ksDatabasePassword.remove()
|
||||||
m.controller.appPrefs.storeDBPassphrase.set(true)
|
m.controller.appPrefs.storeDBPassphrase.set(true)
|
||||||
deleteChatDatabaseFiles()
|
deleteAppDatabaseAndFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteChatDatabaseFiles() {
|
fun deleteAppDatabaseAndFiles() {
|
||||||
val chat = File(dataDir, chatDatabaseFileName)
|
val chat = File(dataDir, chatDatabaseFileName)
|
||||||
val chatBak = File(dataDir, "$chatDatabaseFileName.bak")
|
val chatBak = File(dataDir, "$chatDatabaseFileName.bak")
|
||||||
val agent = File(dataDir, agentDatabaseFileName)
|
val agent = File(dataDir, agentDatabaseFileName)
|
||||||
@ -473,6 +473,7 @@ fun deleteChatDatabaseFiles() {
|
|||||||
agent.delete()
|
agent.delete()
|
||||||
agentBak.delete()
|
agentBak.delete()
|
||||||
filesDir.deleteRecursively()
|
filesDir.deleteRecursively()
|
||||||
|
filesDir.mkdir()
|
||||||
remoteHostsDir.deleteRecursively()
|
remoteHostsDir.deleteRecursively()
|
||||||
tmpDir.deleteRecursively()
|
tmpDir.deleteRecursively()
|
||||||
tmpDir.mkdir()
|
tmpDir.mkdir()
|
||||||
|
@ -17,7 +17,7 @@ object DatabaseUtils {
|
|||||||
val ksAppPassword = KeyStoreItem(APP_PASSWORD_ALIAS, appPreferences.encryptedAppPassphrase, appPreferences.initializationVectorAppPassphrase)
|
val ksAppPassword = KeyStoreItem(APP_PASSWORD_ALIAS, appPreferences.encryptedAppPassphrase, appPreferences.initializationVectorAppPassphrase)
|
||||||
val ksSelfDestructPassword = KeyStoreItem(SELF_DESTRUCT_PASSWORD_ALIAS, appPreferences.encryptedSelfDestructPassphrase, appPreferences.initializationVectorSelfDestructPassphrase)
|
val ksSelfDestructPassword = KeyStoreItem(SELF_DESTRUCT_PASSWORD_ALIAS, appPreferences.encryptedSelfDestructPassphrase, appPreferences.initializationVectorSelfDestructPassphrase)
|
||||||
|
|
||||||
class KeyStoreItem(val alias: String, val passphrase: SharedPreference<String?>, val initVector: SharedPreference<String?>) {
|
class KeyStoreItem(private val alias: String, val passphrase: SharedPreference<String?>, val initVector: SharedPreference<String?>) {
|
||||||
fun get(): String? {
|
fun get(): String? {
|
||||||
return cryptor.decryptData(
|
return cryptor.decryptData(
|
||||||
passphrase.get()?.toByteArrayFromBase64ForPassphrase() ?: return null,
|
passphrase.get()?.toByteArrayFromBase64ForPassphrase() ?: return null,
|
||||||
|
@ -34,7 +34,7 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) {
|
|||||||
} else {
|
} else {
|
||||||
val r: LAResult = if (passcode.value == authRequest.password) {
|
val r: LAResult = if (passcode.value == authRequest.password) {
|
||||||
if (authRequest.selfDestruct && sdPassword != null && controller.ctrl == -1L) {
|
if (authRequest.selfDestruct && sdPassword != null && controller.ctrl == -1L) {
|
||||||
initChatControllerAndRunMigrations(true)
|
initChatControllerAndRunMigrations()
|
||||||
}
|
}
|
||||||
LAResult.Success
|
LAResult.Success
|
||||||
} else {
|
} else {
|
||||||
@ -67,8 +67,8 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (
|
|||||||
* */
|
* */
|
||||||
chatCloseStore(ctrl)
|
chatCloseStore(ctrl)
|
||||||
}
|
}
|
||||||
deleteChatDatabaseFiles()
|
deleteAppDatabaseAndFiles()
|
||||||
// Clear sensitive data on screen just in case ModalManager will fail to prevent hiding its modals while database encrypts itself
|
// Clear sensitive data on screen just in case ModalManager fails to hide its modals while new database is created
|
||||||
m.chatId.value = null
|
m.chatId.value = null
|
||||||
m.chatItems.clear()
|
m.chatItems.clear()
|
||||||
m.chats.clear()
|
m.chats.clear()
|
||||||
|
@ -12,6 +12,7 @@ import chat.simplex.res.MR
|
|||||||
@Composable
|
@Composable
|
||||||
fun SetAppPasscodeView(
|
fun SetAppPasscodeView(
|
||||||
passcodeKeychain: DatabaseUtils.KeyStoreItem = ksAppPassword,
|
passcodeKeychain: DatabaseUtils.KeyStoreItem = ksAppPassword,
|
||||||
|
prohibitedPasscodeKeychain: DatabaseUtils.KeyStoreItem = ksSelfDestructPassword,
|
||||||
title: String = generalGetString(MR.strings.new_passcode),
|
title: String = generalGetString(MR.strings.new_passcode),
|
||||||
reason: String? = null,
|
reason: String? = null,
|
||||||
submit: () -> Unit,
|
submit: () -> Unit,
|
||||||
@ -51,7 +52,7 @@ fun SetAppPasscodeView(
|
|||||||
} else {
|
} else {
|
||||||
SetPasswordView(title, generalGetString(MR.strings.save_verb),
|
SetPasswordView(title, generalGetString(MR.strings.save_verb),
|
||||||
// Do not allow to set app passcode == selfDestruct passcode
|
// Do not allow to set app passcode == selfDestruct passcode
|
||||||
submitEnabled = { pwd -> pwd != (if (passcodeKeychain.alias == ksSelfDestructPassword.alias) ksAppPassword else ksSelfDestructPassword).get() }) {
|
submitEnabled = { pwd -> pwd != prohibitedPasscodeKeychain.get() }) {
|
||||||
enteredPassword = passcode.value
|
enteredPassword = passcode.value
|
||||||
passcode.value = ""
|
passcode.value = ""
|
||||||
confirming = true
|
confirming = true
|
||||||
|
@ -454,6 +454,7 @@ fun SimplexLockView(
|
|||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
passcodeKeychain = ksSelfDestructPassword,
|
passcodeKeychain = ksSelfDestructPassword,
|
||||||
|
prohibitedPasscodeKeychain = ksAppPassword,
|
||||||
reason = generalGetString(MR.strings.self_destruct),
|
reason = generalGetString(MR.strings.self_destruct),
|
||||||
submit = {
|
submit = {
|
||||||
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_changed))
|
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_changed))
|
||||||
@ -600,7 +601,7 @@ private fun EnableSelfDestruct(
|
|||||||
) {
|
) {
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
passcodeKeychain = ksSelfDestructPassword, title = generalGetString(MR.strings.set_passcode), reason = generalGetString(MR.strings.enabled_self_destruct_passcode),
|
passcodeKeychain = ksSelfDestructPassword, prohibitedPasscodeKeychain = ksAppPassword, title = generalGetString(MR.strings.set_passcode), reason = generalGetString(MR.strings.enabled_self_destruct_passcode),
|
||||||
submit = {
|
submit = {
|
||||||
selfDestruct.set(true)
|
selfDestruct.set(true)
|
||||||
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_enabled))
|
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_enabled))
|
||||||
|
@ -24,7 +24,9 @@ fun initApp() {
|
|||||||
override fun cancelAllNotifications() = chat.simplex.common.model.NtfManager.cancelAllNotifications()
|
override fun cancelAllNotifications() = chat.simplex.common.model.NtfManager.cancelAllNotifications()
|
||||||
}
|
}
|
||||||
applyAppLocale()
|
applyAppLocale()
|
||||||
initChatControllerAndRunMigrations(false)
|
if (DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
// LALAL
|
// LALAL
|
||||||
//testCrypto()
|
//testCrypto()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user