Disable saving PIN to password manager.

We haven't found a reliable way to make the auto-fill framework differentiate between the PIN and backup key, so we are disabling prompts to save Signal PINs to password managers to avoid accidentally overwriting a saved backup key with a PIN value.

Co-authored-by: Michelle Tang <mtang@signal.org>
This commit is contained in:
jeffrey-signal
2025-09-04 16:21:56 -04:00
committed by Greyson Parrelli
parent 217a6187c2
commit b1f067536b
16 changed files with 33 additions and 123 deletions

View File

@@ -9,6 +9,7 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.method.PasswordTransformationMethod;
import android.text.style.ClickableSpan;
import android.util.DisplayMetrics;
import android.view.Display;
@@ -21,9 +22,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.autofill.HintConstants;
import androidx.core.app.DialogCompat;
import androidx.core.view.ViewCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
@@ -74,16 +73,16 @@ public final class SignalPinReminderDialog {
SpannableString forgotText = new SpannableString(context.getString(R.string.KbsReminderDialog__forgot_pin));
ViewUtil.focusAndShowKeyboard(pinEditText);
ViewCompat.setAutofillHints(pinEditText, HintConstants.AUTOFILL_HINT_PASSWORD);
switch (SignalStore.pin().getKeyboardType()) {
case NUMERIC:
pinEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
pinEditText.setInputType(InputType.TYPE_CLASS_NUMBER);
break;
case ALPHA_NUMERIC:
pinEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
pinEditText.setInputType(InputType.TYPE_CLASS_TEXT );
break;
}
pinEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
ClickableSpan clickableSpan = new ClickableSpan() {
@Override

View File

@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.lock.v2;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -192,8 +193,8 @@ public abstract class BaseSvrPinFragment<ViewModel extends BaseSvrPinViewModel>
private void updateKeyboard(@NonNull PinKeyboardType keyboard) {
boolean isAlphaNumeric = keyboard == PinKeyboardType.ALPHA_NUMERIC;
input.setInputType(isAlphaNumeric ? InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
: InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
input.setInputType(isAlphaNumeric ? InputType.TYPE_CLASS_TEXT : InputType.TYPE_CLASS_NUMBER);
input.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
private @StringRes int resolveKeyboardToggleText(@NonNull PinKeyboardType keyboard) {

View File

@@ -3,14 +3,9 @@ package org.thoughtcrime.securesms.lock.v2
import android.app.Activity
import android.content.DialogInterface
import android.view.View
import androidx.autofill.HintConstants
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.lock.v2.ConfirmSvrPinViewModel.SaveAnimation
@@ -18,7 +13,6 @@ import org.thoughtcrime.securesms.megaphone.Megaphones
import org.thoughtcrime.securesms.registration.util.RegistrationUtil
import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.util.SpanUtil
import org.thoughtcrime.securesms.util.storage.AndroidCredentialRepository
internal class ConfirmSvrPinFragment : BaseSvrPinFragment<ConfirmSvrPinViewModel>() {
@@ -29,9 +23,6 @@ internal class ConfirmSvrPinFragment : BaseSvrPinFragment<ConfirmSvrPinViewModel
} else {
initializeViewStatesForPinCreate()
}
ViewCompat.setImportantForAutofill(input, View.IMPORTANT_FOR_AUTOFILL_YES)
ViewCompat.setAutofillHints(input, HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
}
override fun initializeViewModel(): ConfirmSvrPinViewModel {
@@ -92,7 +83,6 @@ internal class ConfirmSvrPinFragment : BaseSvrPinFragment<ConfirmSvrPinViewModel
closeNavGraphBranch()
RegistrationUtil.maybeMarkRegistrationComplete()
StorageSyncHelper.scheduleSyncForDataChange()
showSavePinToPasswordManagerPrompt()
}
SaveAnimation.FAILURE -> {
@@ -127,14 +117,4 @@ internal class ConfirmSvrPinFragment : BaseSvrPinFragment<ConfirmSvrPinViewModel
private fun markMegaphoneSeenIfNecessary() {
AppDependencies.megaphoneRepository.markSeen(Megaphones.Event.PINS_FOR_ALL)
}
private fun showSavePinToPasswordManagerPrompt() {
CoroutineScope(Dispatchers.Main).launch {
AndroidCredentialRepository.saveCredential(
activityContext = requireActivity(),
username = getString(R.string.ConfirmKbsPinFragment__pin_password_manager_id),
password = input.text.toString()
)
}
}
}

View File

@@ -1,13 +1,10 @@
package org.thoughtcrime.securesms.lock.v2
import android.view.View
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.widget.EditText
import androidx.annotation.PluralsRes
import androidx.autofill.HintConstants
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.Navigation.findNavController
import org.thoughtcrime.securesms.R
@@ -27,9 +24,6 @@ class CreateSvrPinFragment : BaseSvrPinFragment<CreateSvrPinViewModel?>() {
label.text = getPinLengthRestrictionText(R.plurals.CreateKbsPinFragment__pin_must_be_at_least_digits)
confirm.isEnabled = false
ViewCompat.setImportantForAutofill(input, View.IMPORTANT_FOR_AUTOFILL_YES)
ViewCompat.setAutofillHints(input, HintConstants.AUTOFILL_HINT_PASSWORD)
}
private fun initializeViewStatesForPinChange() {