| Index: chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java
|
| index ae2e59d3554dfca85117df4952e881a964d4c361..c4181576fe441c0f82c93783ffe2ed4f44969b88 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java
|
| @@ -1,124 +1,37 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| package org.chromium.chrome.browser.preferences.autofill;
|
|
|
| import android.os.Bundle;
|
| -import android.text.Editable;
|
| import android.text.TextUtils;
|
| -import android.text.TextWatcher;
|
| import android.view.LayoutInflater;
|
| import android.view.View;
|
| import android.view.ViewGroup;
|
| -import android.widget.AdapterView;
|
| import android.widget.ArrayAdapter;
|
| -import android.widget.Button;
|
| -import android.widget.EditText;
|
| import android.widget.Spinner;
|
|
|
| import org.chromium.chrome.R;
|
| import org.chromium.chrome.browser.autofill.PersonalDataManager;
|
| import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
|
| import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
|
| -import org.chromium.chrome.browser.widget.FloatLabelLayout;
|
|
|
| -import java.text.SimpleDateFormat;
|
| -import java.util.Calendar;
|
| import java.util.List;
|
| -import java.util.Locale;
|
|
|
| /**
|
| - * Provides the Java-ui for editing a Credit Card autofill entry.
|
| + * The base class for credit card settings.
|
| */
|
| -public class AutofillCreditCardEditor extends AutofillEditorBase {
|
| - private FloatLabelLayout mNameLabel;
|
| - private EditText mNameText;
|
| - private FloatLabelLayout mNumberLabel;
|
| - private EditText mNumberText;
|
| - private Spinner mExpirationMonth;
|
| - private Spinner mExpirationYear;
|
| - private Spinner mBillingAddress;
|
| -
|
| - private int mInitialExpirationMonthPos;
|
| - private int mInitialExpirationYearPos;
|
| - private int mInitialBillingAddressPos;
|
| +abstract class AutofillCreditCardEditor extends AutofillEditorBase {
|
| + protected CreditCard mCard;
|
| + protected Spinner mBillingAddress;
|
| + protected int mInitialBillingAddressPos;
|
|
|
| @Override
|
| public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
| Bundle savedInstanceState) {
|
| View v = super.onCreateView(inflater, container, savedInstanceState);
|
|
|
| - mNameLabel = (FloatLabelLayout) v.findViewById(R.id.credit_card_name_label);
|
| - mNameText = (EditText) v.findViewById(R.id.credit_card_name_edit);
|
| - mNumberLabel = (FloatLabelLayout) v.findViewById(R.id.credit_card_number_label);
|
| - mNumberText = (EditText) v.findViewById(R.id.credit_card_number_edit);
|
| -
|
| - // Set text watcher to format credit card number
|
| - mNumberText.addTextChangedListener(new CreditCardNumberFormattingTextWatcher());
|
| -
|
| - mExpirationMonth = (Spinner) v.findViewById(R.id.autofill_credit_card_editor_month_spinner);
|
| - mExpirationYear = (Spinner) v.findViewById(R.id.autofill_credit_card_editor_year_spinner);
|
| - mBillingAddress =
|
| - (Spinner) v.findViewById(R.id.autofill_credit_card_editor_billing_address_spinner);
|
| -
|
| - addSpinnerAdapters();
|
| - addCardDataToEditFields();
|
| - initializeButtons(v);
|
| - return v;
|
| - }
|
| -
|
| - @Override
|
| - protected int getLayoutId() {
|
| - return R.layout.autofill_credit_card_editor;
|
| - }
|
| -
|
| - @Override
|
| - protected int getTitleResourceId(boolean isNewEntry) {
|
| - return isNewEntry
|
| - ? R.string.autofill_create_credit_card : R.string.autofill_edit_credit_card;
|
| - }
|
| -
|
| - @Override
|
| - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
| - if ((parent == mExpirationYear && position != mInitialExpirationYearPos)
|
| - || (parent == mExpirationMonth && position != mInitialExpirationMonthPos)
|
| - || (parent == mBillingAddress && position != mInitialBillingAddressPos)) {
|
| - updateSaveButtonEnabled();
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void onTextChanged(CharSequence s, int start, int before, int count) {
|
| - updateSaveButtonEnabled();
|
| - }
|
| -
|
| - void addSpinnerAdapters() {
|
| - ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getActivity(),
|
| - android.R.layout.simple_spinner_item);
|
| -
|
| - // Populate the month dropdown.
|
| - Calendar calendar = Calendar.getInstance();
|
| - calendar.set(Calendar.DAY_OF_MONTH, 1);
|
| - SimpleDateFormat formatter = new SimpleDateFormat("MMMM (MM)", Locale.getDefault());
|
| -
|
| - for (int month = 0; month < 12; month++) {
|
| - calendar.set(Calendar.MONTH, month);
|
| - adapter.add(formatter.format(calendar.getTime()));
|
| - }
|
| - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
| - mExpirationMonth.setAdapter(adapter);
|
| -
|
| - // Populate the year dropdown.
|
| - adapter = new ArrayAdapter<CharSequence>(getActivity(),
|
| - android.R.layout.simple_spinner_item);
|
| - int initialYear = calendar.get(Calendar.YEAR);
|
| - for (int year = initialYear; year < initialYear + 10; year++) {
|
| - adapter.add(Integer.toString(year));
|
| - }
|
| - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
| - mExpirationYear.setAdapter(adapter);
|
| -
|
| // Populate the billing address dropdown.
|
| ArrayAdapter<AutofillProfile> profilesAdapter = new ArrayAdapter<AutofillProfile>(
|
| getActivity(), android.R.layout.simple_spinner_item);
|
| @@ -135,200 +48,29 @@ public class AutofillCreditCardEditor extends AutofillEditorBase {
|
| if (profile.getIsLocal()) profilesAdapter.add(profile);
|
| }
|
|
|
| + mBillingAddress =
|
| + (Spinner) v.findViewById(R.id.autofill_credit_card_editor_billing_address_spinner);
|
| mBillingAddress.setAdapter(profilesAdapter);
|
| - mInitialBillingAddressPos = 0;
|
| - mBillingAddress.setSelection(0);
|
|
|
| // TODO(rouslan): Use an [+ ADD ADDRESS] button instead of disabling the dropdown.
|
| // http://crbug.com/623629
|
| if (profilesAdapter.getCount() == 1) mBillingAddress.setEnabled(false);
|
| - }
|
| -
|
| - private void addCardDataToEditFields() {
|
| - CreditCard card = PersonalDataManager.getInstance().getCreditCard(mGUID);
|
| - if (card == null) {
|
| - mNameLabel.focusWithoutAnimation();
|
| - return;
|
| - }
|
| -
|
| - if (!TextUtils.isEmpty(card.getName())) {
|
| - mNameLabel.setText(card.getName());
|
| - }
|
| - if (!TextUtils.isEmpty(card.getNumber())) {
|
| - mNumberLabel.setText(card.getNumber());
|
| - }
|
| -
|
| - // Make the name label focusable in touch mode so that mNameText doesn't get focused.
|
| - mNameLabel.getLabel().setFocusableInTouchMode(true);
|
| -
|
| - int monthAsInt = 1;
|
| - if (!card.getMonth().isEmpty()) {
|
| - monthAsInt = Integer.parseInt(card.getMonth());
|
| - }
|
| - mExpirationMonth.setSelection(monthAsInt - 1);
|
| -
|
| - mInitialExpirationYearPos = 0;
|
| - boolean foundYear = false;
|
| - for (int i = 0; i < mExpirationYear.getAdapter().getCount(); i++) {
|
| - if (card.getYear().equals(mExpirationYear.getAdapter().getItem(i))) {
|
| - mInitialExpirationYearPos = i;
|
| - foundYear = true;
|
| - break;
|
| - }
|
| - }
|
| - // Maybe your card expired years ago? Add the card's year
|
| - // to the spinner adapter if not found.
|
| - if (!foundYear && !card.getYear().isEmpty()) {
|
| - @SuppressWarnings("unchecked")
|
| - ArrayAdapter<CharSequence> adapter =
|
| - (ArrayAdapter<CharSequence>) mExpirationYear.getAdapter();
|
| - adapter.insert(card.getYear(), 0);
|
| - mInitialExpirationYearPos = 0;
|
| - }
|
| - mExpirationYear.setSelection(mInitialExpirationYearPos);
|
|
|
| - if (!TextUtils.isEmpty(card.getBillingAddressId())) {
|
| - for (int i = 0; i < mBillingAddress.getAdapter().getCount(); i++) {
|
| - AutofillProfile profile = (AutofillProfile) mBillingAddress.getAdapter().getItem(i);
|
| - if (TextUtils.equals(profile.getGUID(), card.getBillingAddressId())) {
|
| - mInitialBillingAddressPos = i;
|
| - mBillingAddress.setSelection(i);
|
| - break;
|
| + mCard = PersonalDataManager.getInstance().getCreditCard(mGUID);
|
| + if (mCard != null) {
|
| + if (!TextUtils.isEmpty(mCard.getBillingAddressId())) {
|
| + for (int i = 0; i < mBillingAddress.getAdapter().getCount(); i++) {
|
| + AutofillProfile profile =
|
| + (AutofillProfile) mBillingAddress.getAdapter().getItem(i);
|
| + if (TextUtils.equals(profile.getGUID(), mCard.getBillingAddressId())) {
|
| + mInitialBillingAddressPos = i;
|
| + mBillingAddress.setSelection(i);
|
| + break;
|
| + }
|
| }
|
| }
|
| }
|
| - }
|
| -
|
| - // Read edited data; save in the associated Chrome profile.
|
| - // Ignore empty fields.
|
| - @Override
|
| - protected void saveEntry() {
|
| - // Remove all spaces in editText.
|
| - String cardNumber = mNumberText.getText().toString().replaceAll("\\s+", "");
|
| - CreditCard card = new CreditCard(mGUID, AutofillPreferences.SETTINGS_ORIGIN,
|
| - true /* isLocal */, false /* isCached */, mNameText.getText().toString().trim(),
|
| - cardNumber, "" /* obfuscatedNumber */,
|
| - String.valueOf(mExpirationMonth.getSelectedItemPosition() + 1),
|
| - (String) mExpirationYear.getSelectedItem(), "" /* basicCardPaymentType */,
|
| - 0 /* issuerIconDrawableId */,
|
| - ((AutofillProfile) mBillingAddress.getSelectedItem()).getGUID() /* billing */);
|
| -
|
| - PersonalDataManager.getInstance().setCreditCard(card);
|
| - }
|
| -
|
| - @Override
|
| - protected void deleteEntry() {
|
| - if (mGUID != null) {
|
| - PersonalDataManager.getInstance().deleteCreditCard(mGUID);
|
| - }
|
| - }
|
|
|
| - @Override
|
| - protected void initializeButtons(View v) {
|
| - super.initializeButtons(v);
|
| -
|
| - // Listen for changes to inputs. Enable the save button after something has changed.
|
| - mNameText.addTextChangedListener(this);
|
| - mNumberText.addTextChangedListener(this);
|
| - mExpirationMonth.setOnItemSelectedListener(this);
|
| - mExpirationYear.setOnItemSelectedListener(this);
|
| - mBillingAddress.setOnItemSelectedListener(this);
|
| - }
|
| -
|
| - private void updateSaveButtonEnabled() {
|
| - boolean enabled = !TextUtils.isEmpty(mNameText.getText())
|
| - || !TextUtils.isEmpty(mNumberText.getText());
|
| - Button button = (Button) getView().findViewById(R.id.button_primary);
|
| - button.setEnabled(enabled);
|
| - }
|
| -
|
| - /**
|
| - * Watch a TextView and if a credit card number is entered, it will format the number.
|
| - * Disable formatting when user:
|
| - * 1. Inputs dashes or spaces.
|
| - * 2. Removes separators in the middle of the string
|
| - * 3. Enters a number longer than 16 digits.
|
| - *
|
| - * Formatting will be re-enabled once text is cleared.
|
| - */
|
| - private static class CreditCardNumberFormattingTextWatcher implements TextWatcher {
|
| - /** Character for card number section separator. */
|
| - private static final String SEPARATOR = " ";
|
| -
|
| - /**
|
| - * Whether to format the credit card number. If true, spaces will be inserted
|
| - * automatically between each group of 4 digits in the credit card number as the user types.
|
| - * This is set to false if the user types a dash or deletes one of the auto-inserted spaces.
|
| - */
|
| - private boolean mFormattingEnabled = true;
|
| -
|
| - /**
|
| - * Whether the change was caused by ourselves.
|
| - * This is set true when we are manipulating the text of EditText,
|
| - * and all callback functions should check this boolean to avoid infinite recursion.
|
| - */
|
| - private boolean mSelfChange = false;
|
| -
|
| - @Override
|
| - public void onTextChanged(CharSequence s, int start, int before, int count) {
|
| - if (mSelfChange || !mFormattingEnabled) return;
|
| - // If user enters non-digit characters, do not format.
|
| - if (count > 0 && hasDashOrSpace(s, start, count)) {
|
| - mFormattingEnabled = false;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
| - if (mSelfChange || !mFormattingEnabled) return;
|
| - // If user deletes non-digit characters, do not format.
|
| - if (count > 0 && hasDashOrSpace(s, start, count)) {
|
| - mFormattingEnabled = false;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void afterTextChanged(Editable s) {
|
| - if (mSelfChange) return;
|
| - mSelfChange = true;
|
| -
|
| - if (mFormattingEnabled) {
|
| - removeSeparators(s);
|
| - // If number is too long, do not format it and remove all
|
| - // previous separators.
|
| - if (s.length() > 16) {
|
| - mFormattingEnabled = false;
|
| - } else {
|
| - insertSeparators(s);
|
| - }
|
| - }
|
| - // If user clears the input, re-enable formatting
|
| - if (s.length() == 0) mFormattingEnabled = true;
|
| -
|
| - mSelfChange = false;
|
| - }
|
| -
|
| - public static void removeSeparators(Editable s) {
|
| - int index = TextUtils.indexOf(s, SEPARATOR);
|
| - while (index >= 0) {
|
| - s.delete(index, index + 1);
|
| - index = TextUtils.indexOf(s, SEPARATOR, index + 1);
|
| - }
|
| - }
|
| -
|
| - public static void insertSeparators(Editable s) {
|
| - final int[] positions = {4, 9, 14 };
|
| - for (int i : positions) {
|
| - if (s.length() > i) {
|
| - s.insert(i, SEPARATOR);
|
| - }
|
| - }
|
| - }
|
| -
|
| - public static boolean hasDashOrSpace(final CharSequence s, final int start,
|
| - final int count) {
|
| - return TextUtils.indexOf(s, " ", start, start + count) != -1
|
| - || TextUtils.indexOf(s, "-", start, start + count) != -1;
|
| - }
|
| + return v;
|
| }
|
| }
|
|
|