[SES-3434] - Fix receiving left groups' notification (#986)

* Fix still receiving generic notification for groups

* Imports

* Fixes tests

* Fixes compile issues
pull/1710/head
SessionHero01 1 month ago committed by GitHub
parent 119a3e7cfe
commit b44ea31d8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -40,6 +40,7 @@ import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner;
import androidx.work.Configuration;
import com.google.firebase.messaging.FirebaseMessaging;
import com.squareup.phrase.Phrase;
import org.conscrypt.Conscrypt;
@ -499,37 +500,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
}
});
}
// Method to clear the local data - returns true on success otherwise false
@SuppressLint("ApplySharedPref")
public boolean clearAllData() {
TextSecurePreferences.clearAll(this);
getSharedPreferences(PREFERENCES_NAME, 0).edit().clear().commit();
if (!deleteDatabase(SQLCipherOpenHelper.DATABASE_NAME)) {
Log.d("Loki", "Failed to delete database.");
return false;
}
configFactory.clearAll();
return true;
}
/**
* Clear all local profile data and message history then restart the app after a brief delay.
* @return true on success, false otherwise.
*/
@SuppressLint("ApplySharedPref")
public boolean clearAllDataAndRestart() {
clearAllData();
Util.runOnMain(() -> new Handler().postDelayed(ApplicationContext.this::restartApplication, 200));
return true;
}
public void restartApplication() {
Intent intent = new Intent(this, HomeActivity.class);
startActivity(Intent.makeRestartActivityTask(intent.getComponent()));
Runtime.getRuntime().exit(0);
}
// endregion
// Method to wake up the screen and dismiss the keyguard

@ -16,6 +16,7 @@ import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.session.libsession.messaging.groups.LegacyGroupDeprecationManager
import org.thoughtcrime.securesms.util.ClearDataUtils
import java.time.ZonedDateTime
import javax.inject.Inject
@ -25,6 +26,7 @@ class DebugMenuViewModel @Inject constructor(
private val textSecurePreferences: TextSecurePreferences,
private val configFactory: ConfigFactory,
private val deprecationManager: LegacyGroupDeprecationManager,
private val clearDataUtils: ClearDataUtils
) : ViewModel() {
private val TAG = "DebugMenu"
@ -86,7 +88,7 @@ class DebugMenuViewModel @Inject constructor(
// restart app
viewModelScope.launch {
delay(500) // giving time to save data
ApplicationContext.getInstance(application).restartApplication()
clearDataUtils.restartApplication()
}
}
@ -128,21 +130,21 @@ class DebugMenuViewModel @Inject constructor(
// clear remote and local data, then restart the app
viewModelScope.launch {
ApplicationContext.getInstance(application).clearAllData().let { success ->
if(success){
// save the environment
textSecurePreferences.setEnvironment(env)
delay(500)
ApplicationContext.getInstance(application).restartApplication()
} else {
_uiState.value = _uiState.value.copy(
showEnvironmentWarningDialog = false,
showLoadingDialog = false
)
Log.e(TAG, "Failed to force sync when deleting data")
_uiState.value = _uiState.value.copy(snackMessage = "Sorry, something went wrong...")
return@launch
}
val success = runCatching { clearDataUtils.clearAllData() } .isSuccess
if(success){
// save the environment
textSecurePreferences.setEnvironment(env)
delay(500)
clearDataUtils.restartApplication()
} else {
_uiState.value = _uiState.value.copy(
showEnvironmentWarningDialog = false,
showLoadingDialog = false
)
Log.e(TAG, "Failed to force sync when deleting data")
_uiState.value = _uiState.value.copy(snackMessage = "Sorry, something went wrong...")
return@launch
}
}
}

@ -26,6 +26,7 @@ import org.session.libsession.utilities.ConfigMessage
import org.session.libsession.utilities.bencode.Bencode
import org.session.libsession.utilities.bencode.BencodeList
import org.session.libsession.utilities.bencode.BencodeString
import org.session.libsession.utilities.getGroup
import org.session.libsignal.protos.SignalServiceProtos.Envelope
import org.session.libsignal.utilities.AccountId
import org.session.libsignal.utilities.Base64
@ -62,14 +63,8 @@ class PushReceiver @Inject constructor(
}
private fun addMessageReceiveJob(pushData: PushData?) {
// send a generic notification if we have no data
if (pushData?.data == null) {
sendGenericNotification()
return
}
try {
val namespace = pushData.metadata?.namespace
val namespace = pushData?.metadata?.namespace
val params = when {
namespace == Namespace.GROUP_MESSAGES() ||
namespace == Namespace.REVOKED_GROUP_MESSAGES() ||
@ -80,6 +75,17 @@ class PushReceiver @Inject constructor(
"Received a closed group message push notification without an account ID"
})
if (configFactory.getGroup(groupId)?.shouldPoll != true) {
Log.d(TAG, "Received a push notification for a group that isn't active")
return
}
// send a generic notification if we have no data
if (pushData.data == null) {
sendGenericNotification()
return
}
if (namespace == Namespace.GROUP_MESSAGES()) {
val envelope = checkNotNull(tryDecryptGroupEnvelope(groupId, pushData.data)) {
"Unable to decrypt closed group message"
@ -125,7 +131,13 @@ class PushReceiver @Inject constructor(
}
}
namespace == Namespace.DEFAULT() || pushData.metadata == null -> {
namespace == Namespace.DEFAULT() || pushData?.metadata == null -> {
// send a generic notification if we have no data
if (pushData?.data == null) {
sendGenericNotification()
return
}
val envelopeAsData = MessageWrapper.unwrap(pushData.data).toByteArray()
MessageReceiveParameters(
data = envelopeAsData,

@ -16,14 +16,15 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import network.loki.messenger.R
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.onboarding.manager.CreateAccountManager
import org.thoughtcrime.securesms.util.ClearDataUtils
internal class MessageNotificationsViewModel(
private val state: State,
private val application: Application,
private val prefs: TextSecurePreferences,
private val createAccountManager: CreateAccountManager
private val createAccountManager: CreateAccountManager,
private val clearDataUtils: ClearDataUtils,
): AndroidViewModel(application) {
private val _uiStates = MutableStateFlow(UiState())
val uiStates = _uiStates.asStateFlow()
@ -71,8 +72,8 @@ internal class MessageNotificationsViewModel(
fun quit() {
_uiStates.update { it.copy(clearData = true) }
viewModelScope.launch(Dispatchers.IO) {
ApplicationContext.getInstance(application).clearAllDataAndRestart()
viewModelScope.launch {
clearDataUtils.clearAllDataAndRestart()
}
}
@ -100,6 +101,7 @@ internal class MessageNotificationsViewModel(
private val application: Application,
private val prefs: TextSecurePreferences,
private val createAccountManager: CreateAccountManager,
private val clearDataUtils: ClearDataUtils,
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -107,7 +109,8 @@ internal class MessageNotificationsViewModel(
state = profileName?.let(State::CreateAccount) ?: State.LoadAccount,
application = application,
prefs = prefs,
createAccountManager = createAccountManager
createAccountManager = createAccountManager,
clearDataUtils = clearDataUtils,
) as T
}
}

@ -25,6 +25,7 @@ import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.createSessionDialog
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.ClearDataUtils
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import javax.inject.Inject
@ -37,6 +38,9 @@ class ClearAllDataDialog : DialogFragment() {
@Inject
lateinit var storage: StorageProtocol
@Inject
lateinit var clearDataUtils: ClearDataUtils
private enum class Steps {
INFO_PROMPT,
NETWORK_PROMPT,
@ -123,13 +127,15 @@ class ClearAllDataDialog : DialogFragment() {
}
private suspend fun performDeleteLocalDataOnlyStep() {
ApplicationContext.getInstance(context).clearAllDataAndRestart().let { success ->
withContext(Main) {
if (success) {
dismissAllowingStateLoss()
} else {
Toast.makeText(ApplicationContext.getInstance(requireContext()), R.string.errorUnknown, Toast.LENGTH_LONG).show()
}
val result = runCatching {
clearDataUtils.clearAllDataAndRestart()
}
withContext(Main) {
if (result.isSuccess) {
dismissAllowingStateLoss()
} else {
Toast.makeText(ApplicationContext.getInstance(requireContext()), R.string.errorUnknown, Toast.LENGTH_LONG).show()
}
}
}
@ -160,15 +166,7 @@ class ClearAllDataDialog : DialogFragment() {
}
else if (deletionResultMap.values.all { it }) {
// ..otherwise if the network data deletion was successful proceed to delete the local data as well.
ApplicationContext.getInstance(context).clearAllDataAndRestart().let { success ->
withContext(Main) {
if (success) {
dismissAllowingStateLoss()
} else {
Toast.makeText(ApplicationContext.getInstance(requireContext()), R.string.errorUnknown, Toast.LENGTH_LONG).show()
}
}
}
performDeleteLocalDataOnlyStep()
}
}
}

@ -0,0 +1,63 @@
package org.thoughtcrime.securesms.util
import android.annotation.SuppressLint
import android.app.Application
import android.content.Intent
import com.google.firebase.messaging.FirebaseMessaging
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.thoughtcrime.securesms.home.HomeActivity
import javax.inject.Inject
import androidx.core.content.edit
import kotlinx.coroutines.tasks.await
class ClearDataUtils @Inject constructor(
private val application: Application,
private val configFactory: ConfigFactory,
) {
// Method to clear the local data - returns true on success otherwise false
@SuppressLint("ApplySharedPref")
suspend fun clearAllData() {
return withContext(Dispatchers.Default) {
// Should not proceed if we can't delete db
check(application.deleteDatabase(SQLCipherOpenHelper.DATABASE_NAME)) {
"Failed to delete database"
}
TextSecurePreferences.clearAll(application)
application.getSharedPreferences(ApplicationContext.PREFERENCES_NAME, 0).edit(commit = true) { clear() }
configFactory.clearAll()
// The token deletion is nice but not critical, so don't let it block the rest of the process
runCatching {
FirebaseMessaging.getInstance().deleteToken().await()
}.onFailure { e ->
Log.w("ClearDataUtils", "Failed to delete Firebase token: ${e.message}", e)
}
}
}
/**
* Clear all local profile data and message history then restart the app after a brief delay.
* @return true on success, false otherwise.
*/
@SuppressLint("ApplySharedPref")
suspend fun clearAllDataAndRestart() {
clearAllData()
delay(200)
restartApplication()
}
fun restartApplication() {
val intent = Intent(application, HomeActivity::class.java)
application.startActivity(Intent.makeRestartActivityTask(intent.component))
Runtime.getRuntime().exit(0)
}
}

@ -2,9 +2,6 @@ package org.thoughtcrime.securesms.notifications
import com.google.firebase.messaging.FirebaseMessaging
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.tasks.await
import org.session.libsession.messaging.notifications.TokenFetcher
import javax.inject.Inject
import javax.inject.Singleton

@ -49,6 +49,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
configFactory = mock(),
groupManagerV2 = mock(),
legacyGroupDeprecationManager = mock(),
expiredGroupManager = mock()
)
}

Loading…
Cancel
Save