From 0638b31c1fde5cfa2347db2392f667435d2c94a4 Mon Sep 17 00:00:00 2001 From: Nicholas Tinsley Date: Tue, 4 Jun 2024 15:00:51 -0400 Subject: [PATCH] More registration lock V2 improvements. --- .../v2/ui/RegistrationV2Activity.kt | 5 +- .../v2/ui/RegistrationV2ViewModel.kt | 34 +++++++++- .../RegistrationLockV2Fragment.kt | 68 ++++--------------- .../RestoreLocalBackupFragment.kt | 1 - 4 files changed, 49 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2Activity.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2Activity.kt index d5d9706f3b..3231adc6bf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2Activity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2Activity.kt @@ -42,8 +42,8 @@ class RegistrationV2Activity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_registration_navigation_v2) - sharedViewModel.uiState.observe(this) { - if (it.registrationCheckpoint == RegistrationCheckpoint.SERVICE_REGISTRATION_COMPLETED) { + sharedViewModel.checkpoint.observe(this) { + if (it >= RegistrationCheckpoint.LOCAL_REGISTRATION_COMPLETE) { handleSuccessfulVerify() } } @@ -57,6 +57,7 @@ class RegistrationV2Activity : BaseActivity() { if (SignalStore.storageService().needsAccountRestore()) { Log.i(TAG, "Performing pin restore.") startActivity(Intent(this, PinRestoreActivity::class.java)) + finish() } else { val isProfileNameEmpty = Recipient.self().profileName.isEmpty val isAvatarEmpty = !AvatarHelper.hasAvatar(this, Recipient.self().id) diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2ViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2ViewModel.kt index 5f31bc6558..845f0fda9d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2ViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/RegistrationV2ViewModel.kt @@ -21,12 +21,16 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.updateAndGet import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.signal.core.util.Stopwatch import org.signal.core.util.isNotNullOrBlank import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.jobs.MultiDeviceProfileContentUpdateJob import org.thoughtcrime.securesms.jobs.MultiDeviceProfileKeyUpdateJob import org.thoughtcrime.securesms.jobs.ProfileUploadJob +import org.thoughtcrime.securesms.jobs.ReclaimUsernameAndLinkJob +import org.thoughtcrime.securesms.jobs.StorageAccountRestoreJob +import org.thoughtcrime.securesms.jobs.StorageSyncJob import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.pin.SvrRepository @@ -64,6 +68,7 @@ import org.whispersystems.signalservice.api.SvrNoDataException import org.whispersystems.signalservice.api.kbs.MasterKey import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse import java.io.IOException +import java.util.concurrent.TimeUnit import kotlin.jvm.optionals.getOrNull import kotlin.time.Duration.Companion.minutes @@ -496,6 +501,11 @@ class RegistrationV2ViewModel : ViewModel() { when (registrationResult) { is RegisterAccountResult.Success -> { Log.i(TAG, "Register account result: Success! Registration lock: $reglockEnabled") + store.update { + it.copy( + registrationCheckpoint = RegistrationCheckpoint.SERVICE_REGISTRATION_COMPLETED + ) + } onSuccessfulRegistration(context, registrationData, registrationResult.accountRegistrationResult, reglockEnabled) return true } @@ -749,11 +759,31 @@ class RegistrationV2ViewModel : ViewModel() { Log.v(TAG, "onSuccessfulRegistration()") RegistrationRepository.registerAccountLocally(context, registrationData, remoteResult, reglockEnabled) - refreshFeatureFlags() + if (reglockEnabled) { + SignalStore.onboarding().clearAll() + val stopwatch = Stopwatch("RegistrationLockRestore") + + AppDependencies.jobManager.runSynchronously(StorageAccountRestoreJob(), StorageAccountRestoreJob.LIFESPAN) + stopwatch.split("AccountRestore") + + AppDependencies.jobManager + .startChain(StorageSyncJob()) + .then(ReclaimUsernameAndLinkJob()) + .enqueueAndBlockUntilCompletion(TimeUnit.SECONDS.toMillis(10)) + stopwatch.split("ContactRestore") + + refreshFeatureFlags() + + stopwatch.split("FeatureFlags") + + stopwatch.stop(TAG) + } else { + refreshFeatureFlags() + } store.update { it.copy( - registrationCheckpoint = RegistrationCheckpoint.SERVICE_REGISTRATION_COMPLETED, + registrationCheckpoint = RegistrationCheckpoint.LOCAL_REGISTRATION_COMPLETE, inProgress = false ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/registrationlock/RegistrationLockV2Fragment.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/registrationlock/RegistrationLockV2Fragment.kt index cc7699929e..b4088dd0b3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/registrationlock/RegistrationLockV2Fragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/v2/ui/registrationlock/RegistrationLockV2Fragment.kt @@ -15,17 +15,11 @@ import android.widget.Toast import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import com.google.android.material.dialog.MaterialAlertDialogBuilder -import org.signal.core.util.Stopwatch -import org.signal.core.util.concurrent.SimpleTask import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.LoggingFragment import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.ViewBinderDelegate import org.thoughtcrime.securesms.databinding.FragmentRegistrationLockBinding -import org.thoughtcrime.securesms.dependencies.AppDependencies -import org.thoughtcrime.securesms.jobs.ReclaimUsernameAndLinkJob -import org.thoughtcrime.securesms.jobs.StorageAccountRestoreJob -import org.thoughtcrime.securesms.jobs.StorageSyncJob import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.lock.v2.PinKeyboardType import org.thoughtcrime.securesms.lock.v2.SvrConstants @@ -33,14 +27,11 @@ import org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegat import org.thoughtcrime.securesms.registration.v2.data.network.RegisterAccountResult import org.thoughtcrime.securesms.registration.v2.data.network.RegistrationResult import org.thoughtcrime.securesms.registration.v2.data.network.VerificationCodeRequestResult -import org.thoughtcrime.securesms.registration.v2.ui.RegistrationCheckpoint import org.thoughtcrime.securesms.registration.v2.ui.RegistrationV2ViewModel import org.thoughtcrime.securesms.util.CommunicationActions -import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.SupportEmailUtil import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.navigation.safeNavigate -import java.io.IOException import java.util.concurrent.TimeUnit class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registration_lock) { @@ -93,12 +84,6 @@ class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registratio viewModel.lockedTimeRemaining.observe(viewLifecycleOwner) { t: Long -> timeRemaining = t } - viewModel.checkpoint.observe(viewLifecycleOwner) { - if (it >= RegistrationCheckpoint.SERVICE_REGISTRATION_COMPLETED) { - handleSuccessfulPinEntry() - } - } - val triesRemaining: Int = viewModel.svrTriesRemaining if (triesRemaining <= 3) { @@ -143,6 +128,8 @@ class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registratio return } + SignalStore.pinValues().keyboardType = getPinEntryKeyboardType() + binding.kbsLockPinConfirm.setSpinning() viewModel.verifyCodeAndRegisterAccountWithRegistrationLock(requireContext(), pin, ::handleSessionErrorResponse, ::handleRegistrationErrorResponse) @@ -152,7 +139,10 @@ class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registratio when (requestResult) { is VerificationCodeRequestResult.Success -> Unit is VerificationCodeRequestResult.RateLimited -> onRateLimited() - is VerificationCodeRequestResult.AttemptsExhausted -> navigateToAccountLocked() + is VerificationCodeRequestResult.AttemptsExhausted -> { + findNavController().safeNavigate(RegistrationLockV2FragmentDirections.actionAccountLocked()) + } + is VerificationCodeRequestResult.RegistrationLocked -> { Log.i(TAG, "Registration locked response to verify account!") binding.kbsLockPinConfirm.cancelSpinning() @@ -171,7 +161,10 @@ class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registratio when (result) { is RegisterAccountResult.Success -> Unit is RegisterAccountResult.RateLimited -> onRateLimited() - is RegisterAccountResult.AttemptsExhausted -> navigateToAccountLocked() + is RegisterAccountResult.AttemptsExhausted -> { + findNavController().safeNavigate(RegistrationLockV2FragmentDirections.actionAccountLocked()) + } + is RegisterAccountResult.RegistrationLocked -> { Log.i(TAG, "Registration locked response to register account!") binding.kbsLockPinConfirm.cancelSpinning() @@ -180,7 +173,9 @@ class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registratio } is RegisterAccountResult.SvrWrongPin -> onIncorrectKbsRegistrationLockPin(result.triesRemaining) - is RegisterAccountResult.SvrNoData -> navigateToAccountLocked() + is RegisterAccountResult.SvrNoData -> { + findNavController().safeNavigate(RegistrationLockV2FragmentDirections.actionAccountLocked()) + } else -> { Log.w(TAG, "Unable to register account with registration lock", result.getCause()) @@ -196,7 +191,7 @@ class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registratio if (svrTriesRemaining == 0) { Log.w(TAG, "Account locked. User out of attempts on KBS.") - navigateToAccountLocked() + findNavController().safeNavigate(RegistrationLockV2FragmentDirections.actionAccountLocked()) return } @@ -281,41 +276,6 @@ class RegistrationLockV2Fragment : LoggingFragment(R.layout.fragment_registratio binding.kbsLockPinInput.getText().clear() } - private fun navigateToAccountLocked() { - findNavController().safeNavigate(RegistrationLockV2FragmentDirections.actionAccountLocked()) - } - - private fun handleSuccessfulPinEntry() { - SignalStore.pinValues().keyboardType = getPinEntryKeyboardType() - - SimpleTask.run({ - SignalStore.onboarding().clearAll() - val stopwatch = Stopwatch("RegistrationLockRestore") - - AppDependencies.jobManager.runSynchronously(StorageAccountRestoreJob(), StorageAccountRestoreJob.LIFESPAN) - stopwatch.split("AccountRestore") - - AppDependencies.jobManager - .startChain(StorageSyncJob()) - .then(ReclaimUsernameAndLinkJob()) - .enqueueAndBlockUntilCompletion(TimeUnit.SECONDS.toMillis(10)) - stopwatch.split("ContactRestore") - - try { - FeatureFlags.refreshSync() - } catch (e: IOException) { - Log.w(TAG, "Failed to refresh flags.", e) - } - stopwatch.split("FeatureFlags") - - stopwatch.stop(TAG) - null - }, { - binding.kbsLockPinConfirm.cancelSpinning() - findNavController().safeNavigate(RegistrationLockV2FragmentDirections.actionSuccessfulRegistration()) - }) - } - private fun sendEmailToSupport() { val subject = R.string.RegistrationLockFragment__signal_registration_need_help_with_pin_for_android_v2_pin diff --git a/app/src/main/java/org/thoughtcrime/securesms/restore/restorelocalbackup/RestoreLocalBackupFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/restore/restorelocalbackup/RestoreLocalBackupFragment.kt index da84898bef..ff77c7aeff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/restore/restorelocalbackup/RestoreLocalBackupFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/restore/restorelocalbackup/RestoreLocalBackupFragment.kt @@ -13,7 +13,6 @@ import android.widget.Toast import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController -import androidx.navigation.fragment.navArgs import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe