refactor: rework password dialog to avoid memory leak

This commit is contained in:
Harsh Shandilya 2023-07-09 18:49:28 +05:30
parent 227a2bf174
commit 26abbbef97
No known key found for this signature in database
3 changed files with 21 additions and 19 deletions

View file

@ -11,6 +11,7 @@ import android.content.IntentSender
import android.os.Build
import android.os.Bundle
import android.view.autofill.AutofillManager
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope
import app.passwordstore.R
import app.passwordstore.data.crypto.PGPPassphraseCache
@ -35,7 +36,6 @@ import dagger.hilt.android.AndroidEntryPoint
import java.io.ByteArrayOutputStream
import java.io.File
import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import logcat.LogPriority.ERROR
@ -120,16 +120,15 @@ class AutofillDecryptActivity : BasePGPActivity() {
private fun askPassphrase(filePath: String, clientState: Bundle, action: AutofillAction) {
val dialog = PasswordDialog()
lifecycleScope.launch {
withContext(dispatcherProvider.main()) {
dialog.password.collectLatest { value ->
if (value != null) {
decryptWithPassphrase(File(filePath), clientState, action, value)
}
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle ->
if (key == PasswordDialog.PASSWORD_RESULT_KEY) {
val value = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
lifecycleScope.launch(dispatcherProvider.main()) {
decryptWithPassphrase(File(filePath), clientState, action, value)
}
}
}
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
}
private suspend fun decryptWithPassphrase(

View file

@ -9,6 +9,7 @@ import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope
import app.passwordstore.R
import app.passwordstore.crypto.PGPIdentifier
@ -35,7 +36,6 @@ import java.io.File
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -189,9 +189,11 @@ class DecryptActivity : BasePGPActivity() {
if (isError) {
dialog.setError()
}
lifecycleScope.launch(dispatcherProvider.main()) {
dialog.password.collectLatest { value ->
if (value != null) {
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle ->
if (key == PasswordDialog.PASSWORD_RESULT_KEY) {
val value = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
lifecycleScope.launch(dispatcherProvider.main()) {
when (val result = decryptWithPassphrase(value, gpgIdentifiers)) {
is Ok -> {
val entry = passwordEntryFactory.create(result.value.toByteArray())
@ -210,7 +212,6 @@ class DecryptActivity : BasePGPActivity() {
}
}
}
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
}
private suspend fun decryptWithCachedPassphrase(

View file

@ -10,24 +10,21 @@ import android.content.DialogInterface
import android.os.Bundle
import android.view.KeyEvent
import android.view.WindowManager
import androidx.core.os.bundleOf
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.setFragmentResult
import app.passwordstore.R
import app.passwordstore.databinding.DialogPasswordEntryBinding
import app.passwordstore.util.extensions.finish
import app.passwordstore.util.extensions.unsafeLazy
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
/** [DialogFragment] to request a password from the user and forward it along. */
class PasswordDialog : DialogFragment() {
private val binding by unsafeLazy { DialogPasswordEntryBinding.inflate(layoutInflater) }
private var isError: Boolean = false
private val _password = MutableStateFlow<String?>(null)
val password = _password.asStateFlow()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = MaterialAlertDialogBuilder(requireContext())
@ -66,7 +63,12 @@ class PasswordDialog : DialogFragment() {
}
private fun setPasswordAndDismiss() {
_password.update { binding.passwordEditText.text.toString() }
val password = binding.passwordEditText.text.toString()
setFragmentResult(PASSWORD_RESULT_KEY, bundleOf(PASSWORD_RESULT_KEY to password))
dismissAllowingStateLoss()
}
companion object {
const val PASSWORD_RESULT_KEY = "password_result"
}
}