From fdc042e6d40af34f1ce01e0c1a5c967f23ea2b33 Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 18 Jun 2021 16:01:34 +1000 Subject: [PATCH] feat: testnet clearing network data on delete and differentiating dialogs --- .../securesms/database/Storage.kt | 6 -- .../loki/activities/SettingsActivity.kt | 8 +- .../loki/dialogs/ClearAllDataDialog.kt | 96 +++++++++++++------ .../loki/protocol/MultiDeviceProtocol.kt | 10 +- app/src/main/res/layout/activity_settings.xml | 10 ++ .../main/res/layout/dialog_clear_all_data.xml | 18 +++- app/src/main/res/values/strings.xml | 1 + .../xml/network_security_configuration.xml | 2 +- .../libsession/database/StorageProtocol.kt | 1 - .../messaging/open_groups/OpenGroupAPIV2.kt | 4 +- .../open_groups/OpenGroupMessageV2.kt | 7 +- .../sending_receiving/MessageEncrypter.kt | 2 +- .../org/session/libsession/snode/SnodeAPI.kt | 46 +++++++-- .../libsession/snode/SnodeDeleteMessage.kt | 8 +- .../org/session/libsignal/utilities/Snode.kt | 1 + 15 files changed, 156 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 1c67eac4e3..07ab9e20cb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -42,12 +42,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, return TextSecurePreferences.getLocalNumber(context) } - override fun getUserKeyPair(): Pair? { - val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return null - val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize() - return Pair(userPublicKey, userPrivateKey) - } - override fun getUserX25519KeyPair(): ECKeyPair { return DatabaseFactory.getLokiAPIDatabase(context).getUserX25519KeyPair() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index ac342a707c..af834f18de 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -92,6 +92,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { helpTranslateButton.setOnClickListener { helpTranslate() } seedButton.setOnClickListener { showSeed() } clearAllDataButton.setOnClickListener { clearAllData() } + clearAllDataAndNetworkButton.setOnClickListener { clearAllDataIncludingNetwork() } versionTextView.text = String.format(getString(R.string.version_s), "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") } @@ -302,8 +303,13 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } private fun clearAllData() { - ClearAllDataDialog().show(supportFragmentManager, "Clear All Data Dialog") + ClearAllDataDialog(deleteNetworkMessages = false).show(supportFragmentManager, "Clear All Data Dialog") } + + private fun clearAllDataIncludingNetwork() { + ClearAllDataDialog(deleteNetworkMessages = true).show(supportFragmentManager, "Clear All Data Dialog") + } + // endregion private inner class DisplayNameEditActionModeCallback: ActionMode.Callback { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt index ac18e224a1..2e34f83b79 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.loki.dialogs import android.app.Dialog +import android.content.DialogInterface import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.os.Bundle @@ -11,22 +12,23 @@ import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope import kotlinx.android.synthetic.main.dialog_clear_all_data.* import kotlinx.android.synthetic.main.dialog_clear_all_data.view.* -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import kotlinx.coroutines.* import network.loki.messenger.R +import nl.komponents.kovenant.Promise import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.snode.SnodeAPI -import org.session.libsession.snode.SnodeDeleteMessage import org.session.libsession.utilities.KeyPairUtilities +import org.session.libsignal.utilities.Log +import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol +import java.util.concurrent.Executors -class ClearAllDataDialog : DialogFragment() { +class ClearAllDataDialog(val deleteNetworkMessages: Boolean) : DialogFragment() { var clearJob: Job? = null - set(value) { - field = value - updateUI() - } + set(value) { + field = value + } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val builder = AlertDialog.Builder(requireContext()) @@ -40,41 +42,73 @@ class ClearAllDataDialog : DialogFragment() { return result } - private fun updateUI() { - if (clearJob?.isActive == true) { - // clear background job is running, prevent interaction - dialog?.let { view -> - view.cancelButton.isVisible = false - view.clearAllDataButton.isVisible = false - } - } else { - dialog?.let { view -> - view.cancelButton.isVisible = false - view.clearAllDataButton.isVisible = false - } + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + } + + override fun onStart() { + super.onStart() + isCancelable = false + dialog?.setCanceledOnTouchOutside(false) + } + + private fun updateUI(isLoading: Boolean) { + dialog?.let { view -> + view.cancelButton.isVisible = !isLoading + view.clearAllDataButton.isVisible = !isLoading + view.progressBar.isVisible = isLoading } } private fun clearAllData() { if (KeyPairUtilities.hasV2KeyPair(requireContext())) { - clearJob = lifecycleScope.launch { - delay(5_000) - // finish - val userPublicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey() + clearJob = lifecycleScope.launch(Dispatchers.IO) { + withContext(Dispatchers.Main) { + updateUI(true) + } + if (!deleteNetworkMessages) { + try { + MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(requireContext()).get() + ApplicationContext.getInstance(context).clearAllData(false) + withContext(Dispatchers.Main) { + dismiss() + } + } catch (e: Exception) { + Log.e("Loki", "Failed to force sync", e) + } + } else { + // finish + val promises = SnodeAPI.deleteAllMessages(requireContext()).get() - val deleteMessage = SnodeDeleteMessage(userKey, System.currentTimeMillis(), ) - SnodeAPI.deleteAllMessages() - // TODO: re-add the clear data here - //ApplicationContext.getInstance(context).clearAllData(false) + val rawResponses = promises.map { + try { + it.get() + } catch (e: Exception) { + null + } + } + // TODO: process the responses here + if (rawResponses.any { it == null || it["failed"] as? Boolean == true }) { + // didn't succeed (at least one) + withContext(Dispatchers.Main) { + updateUI(false) + } + } else { + // don't force sync because all the messages are deleted? + ApplicationContext.getInstance(context).clearAllData(false) + withContext(Dispatchers.Main) { + dismiss() + } + } + } } } else { val dialog = AlertDialog.Builder(requireContext()) val message = "We’ve upgraded the way Session IDs are generated, so you will be unable to restore your current Session ID." dialog.setMessage(message) dialog.setPositiveButton("Yes") { _, _ -> - // TODO: re-add the clear data here - // ApplicationContext.getInstance(context).clearAllData(false) + ApplicationContext.getInstance(context).clearAllData(false) } dialog.setNegativeButton("Cancel") { _, _ -> // Do nothing diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt index e9e88215ea..29fb98a89a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.loki.protocol import android.content.Context import com.google.protobuf.ByteString +import nl.komponents.kovenant.Promise import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.messages.Destination import org.session.libsession.messaging.messages.control.ConfigurationMessage @@ -28,16 +29,17 @@ object MultiDeviceProtocol { TextSecurePreferences.setLastConfigurationSyncTime(context, now) } - fun forceSyncConfigurationNowIfNeeded(context: Context) { - val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return + fun forceSyncConfigurationNowIfNeeded(context: Context): Promise { + val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return Promise.ofSuccess(Unit) val contacts = ContactUtilities.getAllContacts(context).filter { recipient -> !recipient.isGroupRecipient && !recipient.isBlocked && !recipient.name.isNullOrEmpty() && !recipient.isLocalNumber && recipient.address.serialize().isNotEmpty() }.map { recipient -> ConfigurationMessage.Contact(recipient.address.serialize(), recipient.name!!, recipient.profileAvatar, recipient.profileKey) } - val configurationMessage = ConfigurationMessage.getCurrent(contacts) ?: return - MessageSender.send(configurationMessage, Destination.from(Address.fromSerialized(userPublicKey))) + val configurationMessage = ConfigurationMessage.getCurrent(contacts) ?: return Promise.ofSuccess(Unit) + val promise = MessageSender.send(configurationMessage, Destination.from(Address.fromSerialized(userPublicKey))) TextSecurePreferences.setLastConfigurationSyncTime(context, System.currentTimeMillis()) + return promise } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index bafea51469..5b655b9fe0 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -185,6 +185,16 @@ android:textStyle="bold" android:gravity="center" android:text="@string/activity_settings_clear_all_data_button_title" /> + -