Commit 6225da69 authored by gogerald's avatar gogerald Committed by Commit bot

Auto-advance to next field after typing in valid credit card with maximum digits

BUG=666885

Review-Url: https://codereview.chromium.org/2585453002
Cr-Commit-Position: refs/heads/master@{#439173}
parent 09e3482e
...@@ -308,6 +308,11 @@ public class AddressEditor extends EditorBase<AutofillAddress> { ...@@ -308,6 +308,11 @@ public class AddressEditor extends EditorBase<AutofillAddress> {
&& PhoneNumberUtils.isGlobalPhoneNumber( && PhoneNumberUtils.isGlobalPhoneNumber(
PhoneNumberUtils.stripSeparators(value.toString())); PhoneNumberUtils.stripSeparators(value.toString()));
} }
@Override
public boolean isLengthMaximum(@Nullable CharSequence value) {
return false;
}
}; };
} }
return mPhoneValidator; return mPhoneValidator;
......
...@@ -67,6 +67,16 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument> ...@@ -67,6 +67,16 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument>
} }
} }
/** The support credit card names. */
private static final String AMEX = "amex";
private static final String DINERS = "diners";
private static final String DISCOVER = "discover";
private static final String JCB = "jcb";
private static final String MASTERCARD = "mastercard";
private static final String MIR = "mir";
private static final String UNIONPAY = "unionpay";
private static final String VISA = "visa";
/** The dropdown key that triggers the address editor to add a new billing address. */ /** The dropdown key that triggers the address editor to add a new billing address. */
private static final String BILLING_ADDRESS_ADD_NEW = "add"; private static final String BILLING_ADDRESS_ADD_NEW = "add";
...@@ -161,22 +171,18 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument> ...@@ -161,22 +171,18 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument>
} }
mCardTypes = new HashMap<>(); mCardTypes = new HashMap<>();
mCardTypes.put("amex", mCardTypes.put(AMEX, new CardTypeInfo(R.drawable.pr_amex, R.string.autofill_cc_amex));
new CardTypeInfo(R.drawable.pr_amex, R.string.autofill_cc_amex)); mCardTypes.put(
mCardTypes.put("diners", DINERS, new CardTypeInfo(R.drawable.pr_dinersclub, R.string.autofill_cc_diners));
new CardTypeInfo(R.drawable.pr_dinersclub, R.string.autofill_cc_diners)); mCardTypes.put(
mCardTypes.put("discover", DISCOVER, new CardTypeInfo(R.drawable.pr_discover, R.string.autofill_cc_discover));
new CardTypeInfo(R.drawable.pr_discover, R.string.autofill_cc_discover)); mCardTypes.put(JCB, new CardTypeInfo(R.drawable.pr_jcb, R.string.autofill_cc_jcb));
mCardTypes.put("jcb", mCardTypes.put(
new CardTypeInfo(R.drawable.pr_jcb, R.string.autofill_cc_jcb)); MASTERCARD, new CardTypeInfo(R.drawable.pr_mc, R.string.autofill_cc_mastercard));
mCardTypes.put("mastercard", mCardTypes.put(MIR, new CardTypeInfo(R.drawable.pr_mir, R.string.autofill_cc_mir));
new CardTypeInfo(R.drawable.pr_mc, R.string.autofill_cc_mastercard)); mCardTypes.put(
mCardTypes.put("mir", UNIONPAY, new CardTypeInfo(R.drawable.pr_unionpay, R.string.autofill_cc_union_pay));
new CardTypeInfo(R.drawable.pr_mir, R.string.autofill_cc_mir)); mCardTypes.put(VISA, new CardTypeInfo(R.drawable.pr_visa, R.string.autofill_cc_visa));
mCardTypes.put("unionpay",
new CardTypeInfo(R.drawable.pr_unionpay, R.string.autofill_cc_union_pay));
mCardTypes.put("visa",
new CardTypeInfo(R.drawable.pr_visa, R.string.autofill_cc_visa));
mAcceptedCardTypes = new HashSet<>(); mAcceptedCardTypes = new HashSet<>();
mAcceptedCardTypeInfos = new ArrayList<>(); mAcceptedCardTypeInfos = new ArrayList<>();
...@@ -190,6 +196,11 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument> ...@@ -190,6 +196,11 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument>
PersonalDataManager.getInstance().getBasicCardPaymentType( PersonalDataManager.getInstance().getBasicCardPaymentType(
value.toString(), true)); value.toString(), true));
} }
@Override
public boolean isLengthMaximum(@Nullable CharSequence value) {
return isCardNumberLengthMaximum(value);
}
}; };
mCardIconGenerator = new EditorValueIconGenerator() { mCardIconGenerator = new EditorValueIconGenerator() {
...@@ -213,6 +224,32 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument> ...@@ -213,6 +224,32 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument>
mCalendar.execute(); mCalendar.execute();
} }
private boolean isCardNumberLengthMaximum(@Nullable CharSequence value) {
if (TextUtils.isEmpty(value)) return false;
String cardType =
PersonalDataManager.getInstance().getBasicCardPaymentType(value.toString(), false);
if (TextUtils.isEmpty(cardType)) return false;
// Below maximum values are consistent with the values used to check the validity of the
// credit card number in autofill::IsValidCreditCardNumber.
String cardNumber = removeSpaceAndBar(value);
switch (cardType) {
case AMEX:
return cardNumber.length() == 15;
case DINERS:
return cardNumber.length() == 14;
case UNIONPAY:
return cardNumber.length() == 19;
default:
// Valid DISCOVER, JCB, MASTERCARD, MIR and VISA cards have at most 16 digits.
return cardNumber.length() == 16;
}
}
private static String removeSpaceAndBar(CharSequence value) {
return value.toString().replace(" ", "").replace("-", "");
}
/** /**
* Adds accepted payment methods to the editor, if they are recognized credit card types. * Adds accepted payment methods to the editor, if they are recognized credit card types.
* *
...@@ -430,6 +467,11 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument> ...@@ -430,6 +467,11 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument>
return year > mCurrentYear return year > mCurrentYear
|| (year == mCurrentYear && month >= mCurrentMonth); || (year == mCurrentYear && month >= mCurrentMonth);
} }
@Override
public boolean isLengthMaximum(@Nullable CharSequence value) {
return false;
}
}; };
} }
...@@ -612,7 +654,7 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument> ...@@ -612,7 +654,7 @@ public class CardEditor extends EditorBase<AutofillPaymentInstrument>
return; return;
} }
card.setNumber(mNumberField.getValue().toString().replace(" ", "").replace("-", "")); card.setNumber(removeSpaceAndBar(mNumberField.getValue()));
card.setName(mNameField.getValue().toString()); card.setName(mNameField.getValue().toString());
card.setMonth(mMonthField.getValue().toString()); card.setMonth(mMonthField.getValue().toString());
card.setYear(mYearField.getValue().toString()); card.setYear(mYearField.getValue().toString());
......
...@@ -227,6 +227,11 @@ public class ContactEditor extends EditorBase<AutofillContact> { ...@@ -227,6 +227,11 @@ public class ContactEditor extends EditorBase<AutofillContact> {
&& PhoneNumberUtils.isGlobalPhoneNumber( && PhoneNumberUtils.isGlobalPhoneNumber(
PhoneNumberUtils.stripSeparators(value.toString())); PhoneNumberUtils.stripSeparators(value.toString()));
} }
@Override
public boolean isLengthMaximum(@Nullable CharSequence value) {
return false;
}
}; };
} }
return mPhoneValidator; return mPhoneValidator;
...@@ -239,6 +244,11 @@ public class ContactEditor extends EditorBase<AutofillContact> { ...@@ -239,6 +244,11 @@ public class ContactEditor extends EditorBase<AutofillContact> {
public boolean isValid(@Nullable CharSequence value) { public boolean isValid(@Nullable CharSequence value) {
return value != null && Patterns.EMAIL_ADDRESS.matcher(value).matches(); return value != null && Patterns.EMAIL_ADDRESS.matcher(value).matches();
} }
@Override
public boolean isLengthMaximum(@Nullable CharSequence value) {
return false;
}
}; };
} }
return mEmailValidator; return mEmailValidator;
......
...@@ -34,6 +34,15 @@ public class EditorFieldModel { ...@@ -34,6 +34,15 @@ public class EditorFieldModel {
* @return True if the value is valid. * @return True if the value is valid.
*/ */
boolean isValid(@Nullable CharSequence value); boolean isValid(@Nullable CharSequence value);
/**
* Called to check whehter the length of the field value is maximum.
*
* @param value The value of the field to check.
* @return True if the field value length is maximum among all the possible valid values in
* this field.
*/
boolean isLengthMaximum(@Nullable CharSequence value);
} }
/** /**
...@@ -498,6 +507,16 @@ public class EditorFieldModel { ...@@ -498,6 +507,16 @@ public class EditorFieldModel {
return true; return true;
} }
/**
* Returns true if the field value length is maximum among all the possible valid values in this
* field.
*
* @Return Whether the field value length is maximum.
*/
public boolean isLengthMaximum() {
return mValidator == null ? false : mValidator.isLengthMaximum(mValue);
}
/** /**
* Sets the dropdown callback. * Sets the dropdown callback.
* *
......
...@@ -9,10 +9,12 @@ import android.text.Editable; ...@@ -9,10 +9,12 @@ import android.text.Editable;
import android.text.InputFilter; import android.text.InputFilter;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView; import android.widget.AutoCompleteTextView;
import android.widget.FrameLayout; import android.widget.FrameLayout;
...@@ -32,6 +34,7 @@ import javax.annotation.Nullable; ...@@ -32,6 +34,7 @@ import javax.annotation.Nullable;
@VisibleForTesting @VisibleForTesting
public class EditorTextField extends FrameLayout implements EditorFieldView, View.OnClickListener { public class EditorTextField extends FrameLayout implements EditorFieldView, View.OnClickListener {
private EditorFieldModel mEditorFieldModel; private EditorFieldModel mEditorFieldModel;
private OnEditorActionListener mEditorActionListener;
private CompatibilityTextInputLayout mInputLayout; private CompatibilityTextInputLayout mInputLayout;
private AutoCompleteTextView mInput; private AutoCompleteTextView mInput;
private View mIconsLayer; private View mIconsLayer;
...@@ -42,11 +45,12 @@ public class EditorTextField extends FrameLayout implements EditorFieldView, Vie ...@@ -42,11 +45,12 @@ public class EditorTextField extends FrameLayout implements EditorFieldView, Vie
@Nullable private PaymentRequestObserverForTest mObserverForTest; @Nullable private PaymentRequestObserverForTest mObserverForTest;
public EditorTextField(Context context, final EditorFieldModel fieldModel, public EditorTextField(Context context, final EditorFieldModel fieldModel,
OnEditorActionListener actionlistener, @Nullable InputFilter filter, OnEditorActionListener actionListener, @Nullable InputFilter filter,
@Nullable TextWatcher formatter, @Nullable PaymentRequestObserverForTest observer) { @Nullable TextWatcher formatter, @Nullable PaymentRequestObserverForTest observer) {
super(context); super(context);
assert fieldModel.getInputTypeHint() != EditorFieldModel.INPUT_TYPE_HINT_DROPDOWN; assert fieldModel.getInputTypeHint() != EditorFieldModel.INPUT_TYPE_HINT_DROPDOWN;
mEditorFieldModel = fieldModel; mEditorFieldModel = fieldModel;
mEditorActionListener = actionListener;
mObserverForTest = observer; mObserverForTest = observer;
LayoutInflater.from(context).inflate(R.layout.payments_request_editor_textview, this, true); LayoutInflater.from(context).inflate(R.layout.payments_request_editor_textview, this, true);
...@@ -60,7 +64,7 @@ public class EditorTextField extends FrameLayout implements EditorFieldView, Vie ...@@ -60,7 +64,7 @@ public class EditorTextField extends FrameLayout implements EditorFieldView, Vie
mInput = (AutoCompleteTextView) mInputLayout.findViewById(R.id.text_view); mInput = (AutoCompleteTextView) mInputLayout.findViewById(R.id.text_view);
mInput.setText(fieldModel.getValue()); mInput.setText(fieldModel.getValue());
mInput.setContentDescription(label); mInput.setContentDescription(label);
mInput.setOnEditorActionListener(actionlistener); mInput.setOnEditorActionListener(mEditorActionListener);
mIconsLayer = findViewById(R.id.icons_layer); mIconsLayer = findViewById(R.id.icons_layer);
mIconsLayer.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { mIconsLayer.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
...@@ -114,6 +118,13 @@ public class EditorTextField extends FrameLayout implements EditorFieldView, Vie ...@@ -114,6 +118,13 @@ public class EditorTextField extends FrameLayout implements EditorFieldView, Vie
if (mObserverForTest != null) { if (mObserverForTest != null) {
mObserverForTest.onPaymentRequestEditorTextUpdate(); mObserverForTest.onPaymentRequestEditorTextUpdate();
} }
if (!mEditorFieldModel.isLengthMaximum()) return;
updateDisplayedError(true);
if (isValid()) {
// Simulate editor action to select next selectable field.
mEditorActionListener.onEditorAction(mInput, EditorInfo.IME_ACTION_NEXT,
new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
}
} }
@Override @Override
......
...@@ -43,6 +43,7 @@ bool IsValidCreditCardNumber(const base::string16& text) { ...@@ -43,6 +43,7 @@ bool IsValidCreditCardNumber(const base::string16& text) {
// defined sizes. // defined sizes.
// [1] http://www.merriampark.com/anatomycc.htm // [1] http://www.merriampark.com/anatomycc.htm
// [2] http://en.wikipedia.org/wiki/Bank_card_number // [2] http://en.wikipedia.org/wiki/Bank_card_number
// CardEditor.isCardNumberLengthMaxium() needs to be kept in sync.
const char* const type = CreditCard::GetCreditCardType(text); const char* const type = CreditCard::GetCreditCardType(text);
if (type == kAmericanExpressCard && number.size() != 15) if (type == kAmericanExpressCard && number.size() != 15)
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment