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

@@ -4,6 +4,7 @@ import android.content.Context
import android.content.Intent
import android.graphics.Typeface
import android.text.InputType
import android.text.method.PasswordTransformationMethod
import android.util.DisplayMetrics
import android.view.ViewGroup
import android.widget.EditText
@@ -13,7 +14,6 @@ import androidx.annotation.ColorRes
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog
import androidx.autofill.HintConstants
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.MaterialTheme
@@ -31,7 +31,6 @@ import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.core.app.DialogCompat
import androidx.core.view.ViewCompat
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
@@ -117,10 +116,10 @@ class AccountSettingsFragment : ComposeFragment() {
changeKeyboard.setOnClickListener {
if (pinEditText.inputType and InputType.TYPE_CLASS_NUMBER == 0) {
pinEditText.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
pinEditText.inputType = InputType.TYPE_CLASS_NUMBER
changeKeyboard.setIconResource(PinKeyboardType.ALPHA_NUMERIC.iconResource)
} else {
pinEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
pinEditText.inputType = InputType.TYPE_CLASS_TEXT
changeKeyboard.setIconResource(PinKeyboardType.NUMERIC.iconResource)
}
pinEditText.typeface = Typeface.DEFAULT
@@ -130,20 +129,19 @@ class AccountSettingsFragment : ComposeFragment() {
ViewUtil.focusAndShowKeyboard(pinEditText)
}
ViewCompat.setAutofillHints(pinEditText, HintConstants.AUTOFILL_HINT_PASSWORD)
when (SignalStore.pin.keyboardType) {
PinKeyboardType.NUMERIC -> {
pinEditText.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
pinEditText.inputType = InputType.TYPE_CLASS_NUMBER
changeKeyboard.setIconResource(PinKeyboardType.ALPHA_NUMERIC.iconResource)
}
PinKeyboardType.ALPHA_NUMERIC -> {
pinEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
pinEditText.inputType = InputType.TYPE_CLASS_TEXT
changeKeyboard.setIconResource(PinKeyboardType.NUMERIC.iconResource)
}
}
pinEditText.transformationMethod = PasswordTransformationMethod.getInstance()
pinEditText.addTextChangedListener(object : SimpleTextWatcher() {
override fun onTextChanged(text: String) {
turnOffButton.isEnabled = text.length >= SvrConstants.MINIMUM_PIN_LENGTH

View File

@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.components.settings.app.changenumber
import android.os.Bundle
import android.text.InputType
import android.text.method.PasswordTransformationMethod
import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.EditorInfo
@@ -287,11 +288,12 @@ class ChangeNumberRegistrationLockFragment : LoggingFragment(R.layout.fragment_c
val isAlphaNumeric = keyboard == PinKeyboardType.ALPHA_NUMERIC
binding.kbsLockPinInput.setInputType(
if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
else InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT
else InputType.TYPE_CLASS_NUMBER
)
binding.kbsLockPinInput.getText().clear()
binding.kbsLockPinInput.transformationMethod = PasswordTransformationMethod.getInstance()
}
private fun navigateToAccountLocked() {

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() {

View File

@@ -4,6 +4,7 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -262,8 +263,8 @@ public class PinRestoreEntryFragment extends LoggingFragment {
private void updateKeyboard(@NonNull PinKeyboardType keyboard) {
boolean isAlphaNumeric = keyboard == PinKeyboardType.ALPHA_NUMERIC;
pinEntry.setInputType(isAlphaNumeric ? InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
: InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
pinEntry.setInputType(isAlphaNumeric ? InputType.TYPE_CLASS_TEXT : InputType.TYPE_CLASS_NUMBER );
pinEntry.setTransformationMethod(PasswordTransformationMethod.getInstance());
pinEntry.getText().clear();
}

View File

@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.registration.ui.registrationlock
import android.os.Bundle
import android.text.InputType
import android.text.method.PasswordTransformationMethod
import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.EditorInfo
@@ -275,11 +276,11 @@ class RegistrationLockFragment : LoggingFragment(R.layout.fragment_registration_
val isAlphaNumeric = keyboard == PinKeyboardType.ALPHA_NUMERIC
binding.kbsLockPinInput.setInputType(
if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
else InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT else InputType.TYPE_CLASS_NUMBER
)
binding.kbsLockPinInput.getText().clear()
binding.kbsLockPinInput.transformationMethod = PasswordTransformationMethod.getInstance()
}
private fun sendEmailToSupport() {

View File

@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.registration.ui.reregisterwithpin
import android.os.Bundle
import android.text.InputType
import android.text.method.PasswordTransformationMethod
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.Toast
@@ -201,8 +202,9 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
private fun updateKeyboard(keyboard: PinKeyboardType) {
val isAlphaNumeric = keyboard == PinKeyboardType.ALPHA_NUMERIC
binding.pinRestorePinInput.inputType = if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD else InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
binding.pinRestorePinInput.inputType = if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT else InputType.TYPE_CLASS_NUMBER
binding.pinRestorePinInput.text?.clear()
binding.pinRestorePinInput.transformationMethod = PasswordTransformationMethod.getInstance()
}
private fun onNeedHelpClicked() {

View File

@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.registrationv3.ui.registrationlock
import android.os.Bundle
import android.text.InputType
import android.text.method.PasswordTransformationMethod
import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.EditorInfo
@@ -275,11 +276,12 @@ class RegistrationLockFragment : LoggingFragment(R.layout.fragment_registration_
val isAlphaNumeric = keyboard == PinKeyboardType.ALPHA_NUMERIC
binding.kbsLockPinInput.setInputType(
if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
else InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT
else InputType.TYPE_CLASS_NUMBER
)
binding.kbsLockPinInput.getText().clear()
binding.kbsLockPinInput.transformationMethod = PasswordTransformationMethod.getInstance()
}
private fun sendEmailToSupport() {

View File

@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.registrationv3.ui.reregisterwithpin
import android.os.Bundle
import android.text.InputType
import android.text.method.PasswordTransformationMethod
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.Toast
@@ -202,8 +203,9 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
private fun updateKeyboard(keyboard: PinKeyboardType) {
val isAlphaNumeric = keyboard == PinKeyboardType.ALPHA_NUMERIC
binding.pinRestorePinInput.inputType = if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD else InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
binding.pinRestorePinInput.inputType = if (isAlphaNumeric) InputType.TYPE_CLASS_TEXT else InputType.TYPE_CLASS_NUMBER
binding.pinRestorePinInput.text?.clear()
binding.pinRestorePinInput.transformationMethod = PasswordTransformationMethod.getInstance()
}
private fun onNeedHelpClicked() {