From bb2716f640e421804561eb5b54ad85ba6ee54eb0 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Sun, 16 Aug 2020 14:56:11 +0200 Subject: [PATCH] Prevent a crash on rotation while a ProgressDialogTask is still running This patch ensures ProgressDialogs are dismissed when the ON_PAUSE event is fired. --- .../aegis/helpers/ContextHelper.java | 39 +++++++++++++++++++ .../aegis/importers/AndOtpImporter.java | 5 ++- .../aegis/ui/AuthActivity.java | 3 +- .../com/beemdevelopment/aegis/ui/Dialogs.java | 6 ++- .../aegis/ui/PreferencesFragment.java | 4 +- .../aegis/ui/slides/SecuritySetupSlide.java | 3 +- .../aegis/ui/tasks/ProgressDialogTask.java | 34 +++++++++++++++- 7 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/beemdevelopment/aegis/helpers/ContextHelper.java diff --git a/app/src/main/java/com/beemdevelopment/aegis/helpers/ContextHelper.java b/app/src/main/java/com/beemdevelopment/aegis/helpers/ContextHelper.java new file mode 100644 index 00000000..2eaad2c7 --- /dev/null +++ b/app/src/main/java/com/beemdevelopment/aegis/helpers/ContextHelper.java @@ -0,0 +1,39 @@ +package com.beemdevelopment.aegis.helpers; + +import android.content.Context; +import android.content.ContextWrapper; + +import androidx.activity.ComponentActivity; +import androidx.annotation.NonNull; +import androidx.lifecycle.Lifecycle; + +import javax.annotation.Nullable; + +/** + * ContextHelper contains some disgusting hacks to obtain the Activity/Lifecycle from a Context. + */ +public class ContextHelper { + private ContextHelper() { + + } + + // source: https://github.com/androidx/androidx/blob/e32e1da51a0c7448c74861c667fa76738a415a89/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java#L425-L435 + @Nullable + public static ComponentActivity getActivity(@NonNull Context context) { + while (context instanceof ContextWrapper) { + if (context instanceof ComponentActivity) { + return (ComponentActivity) context; + } + + context = ((ContextWrapper) context).getBaseContext(); + } + + return null; + } + + @Nullable + public static Lifecycle getLifecycle(@NonNull Context context) { + ComponentActivity activity = getActivity(context); + return activity == null ? null : activity.getLifecycle(); + } +} diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java index bd6fccbb..05a5e803 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java @@ -3,6 +3,7 @@ package com.beemdevelopment.aegis.importers; import android.content.Context; import androidx.appcompat.app.AlertDialog; +import androidx.lifecycle.Lifecycle; import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.crypto.CryptParameters; @@ -10,6 +11,7 @@ import com.beemdevelopment.aegis.crypto.CryptResult; import com.beemdevelopment.aegis.crypto.CryptoUtils; import com.beemdevelopment.aegis.encoding.Base32; import com.beemdevelopment.aegis.encoding.EncodingException; +import com.beemdevelopment.aegis.helpers.ContextHelper; import com.beemdevelopment.aegis.otp.HotpInfo; import com.beemdevelopment.aegis.otp.OtpInfo; import com.beemdevelopment.aegis.otp.OtpInfoException; @@ -148,7 +150,8 @@ public class AndOtpImporter extends DatabaseImporter { listener.onError(e); } }); - task.execute(params); + Lifecycle lifecycle = ContextHelper.getLifecycle(context); + task.execute(lifecycle, params); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/AuthActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/AuthActivity.java index ab288a50..ed922055 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/AuthActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/AuthActivity.java @@ -154,7 +154,8 @@ public class AuthActivity extends AegisActivity { char[] password = EditTextHelper.getEditTextChars(_textPassword); List slots = _slots.findAll(PasswordSlot.class); PasswordSlotDecryptTask.Params params = new PasswordSlotDecryptTask.Params(slots, password); - new PasswordSlotDecryptTask(AuthActivity.this, new PasswordDerivationListener()).execute(params); + PasswordSlotDecryptTask task = new PasswordSlotDecryptTask(AuthActivity.this, new PasswordDerivationListener()); + task.execute(getLifecycle(), params); }); biometricsButton.setOnClickListener(v -> { diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/Dialogs.java b/app/src/main/java/com/beemdevelopment/aegis/ui/Dialogs.java index 2a12690b..24118f52 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/Dialogs.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/Dialogs.java @@ -23,6 +23,7 @@ import android.widget.NumberPicker; import android.widget.ProgressBar; import android.widget.TextView; +import androidx.activity.ComponentActivity; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; @@ -94,7 +95,7 @@ public class Dialogs { .create()); } - public static void showSetPasswordDialog(Activity activity, Dialogs.SlotListener listener) { + public static void showSetPasswordDialog(ComponentActivity activity, Dialogs.SlotListener listener) { Zxcvbn zxcvbn = new Zxcvbn(); View view = activity.getLayoutInflater().inflate(R.layout.dialog_password, null); EditText textPassword = view.findViewById(R.id.text_password); @@ -150,7 +151,8 @@ public class Dialogs { listener.onSlotResult(slot, cipher); dialog.dismiss(); }); - task.execute(new KeyDerivationTask.Params(slot, password)); + KeyDerivationTask.Params params = new KeyDerivationTask.Params(slot, password); + task.execute(activity.getLifecycle(), params); }); }); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java b/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java index 943e8350..155e2017 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java @@ -37,6 +37,7 @@ import com.beemdevelopment.aegis.services.NotificationService; import com.beemdevelopment.aegis.ui.models.ImportEntry; import com.beemdevelopment.aegis.ui.preferences.SwitchPreference; import com.beemdevelopment.aegis.ui.tasks.PasswordSlotDecryptTask; +import com.beemdevelopment.aegis.ui.tasks.ProgressDialogTask; import com.beemdevelopment.aegis.util.UUIDMap; import com.beemdevelopment.aegis.vault.VaultBackupManager; import com.beemdevelopment.aegis.vault.VaultEntry; @@ -384,7 +385,8 @@ public class PreferencesFragment extends PreferenceFragmentCompat { if (isDigitsOnly(new String(password))) { List slots = _vault.getCredentials().getSlots().findAll(PasswordSlot.class); PasswordSlotDecryptTask.Params params = new PasswordSlotDecryptTask.Params(slots, password); - new PasswordSlotDecryptTask(getActivity(), new PasswordConfirmationListener()).execute(params); + PasswordSlotDecryptTask task = new PasswordSlotDecryptTask(getActivity(), new PasswordConfirmationListener()); + task.execute(getLifecycle(), params); } else { setPinKeyboardPreference(false); Dialogs.showSecureDialog(new AlertDialog.Builder(getActivity()) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/slides/SecuritySetupSlide.java b/app/src/main/java/com/beemdevelopment/aegis/ui/slides/SecuritySetupSlide.java index f2c1b473..ef6d5524 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/slides/SecuritySetupSlide.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/slides/SecuritySetupSlide.java @@ -125,7 +125,8 @@ public class SecuritySetupSlide extends SlideFragment { private void deriveKey() { PasswordSlot slot = new PasswordSlot(); KeyDerivationTask.Params params = new KeyDerivationTask.Params(slot, EditTextHelper.getEditTextChars(_textPassword)); - new KeyDerivationTask(getContext(), new PasswordDerivationListener()).execute(params); + KeyDerivationTask task = new KeyDerivationTask(getContext(), new PasswordDerivationListener()); + task.execute(getLifecycle(), params); } @Override diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ProgressDialogTask.java b/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ProgressDialogTask.java index c7af2a33..8ecb1641 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ProgressDialogTask.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ProgressDialogTask.java @@ -1,13 +1,18 @@ package com.beemdevelopment.aegis.ui.tasks; +import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import android.os.Process; -import com.beemdevelopment.aegis.ui.Dialogs; - import androidx.annotation.CallSuper; +import androidx.annotation.Nullable; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; + +import com.beemdevelopment.aegis.ui.Dialogs; public abstract class ProgressDialogTask extends AsyncTask { private ProgressDialog _dialog; @@ -47,4 +52,29 @@ public abstract class ProgressDialogTask extends AsyncTask