| // 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.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.WindowManager; |
| 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.ChromeVersionInfo; |
| 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.CompatibilityTextInputLayout; |
| |
| import java.text.SimpleDateFormat; |
| import java.util.Calendar; |
| import java.util.Locale; |
| |
| /** |
| * Local credit card settings. |
| */ |
| public class AutofillLocalCardEditor extends AutofillCreditCardEditor { |
| private CompatibilityTextInputLayout mNameLabel; |
| private EditText mNameText; |
| private CompatibilityTextInputLayout mNumberLabel; |
| private EditText mNumberText; |
| private Spinner mExpirationMonth; |
| private Spinner mExpirationYear; |
| |
| private int mInitialExpirationMonthPos; |
| private int mInitialExpirationYearPos; |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| // Allow screenshots of the credit card number in Canary, Dev, and developer builds. |
| if (ChromeVersionInfo.isBetaBuild() || ChromeVersionInfo.isStableBuild()) { |
| WindowManager.LayoutParams attributes = getActivity().getWindow().getAttributes(); |
| attributes.flags |= WindowManager.LayoutParams.FLAG_SECURE; |
| getActivity().getWindow().setAttributes(attributes); |
| } |
| |
| View v = super.onCreateView(inflater, container, savedInstanceState); |
| |
| mNameLabel = (CompatibilityTextInputLayout) v.findViewById(R.id.credit_card_name_label); |
| mNameText = (EditText) v.findViewById(R.id.credit_card_name_edit); |
| mNumberLabel = (CompatibilityTextInputLayout) 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); |
| |
| addSpinnerAdapters(); |
| addCardDataToEditFields(); |
| initializeButtons(v); |
| return v; |
| } |
| |
| @Override |
| protected int getLayoutId() { |
| return R.layout.autofill_local_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 afterTextChanged(Editable s) { |
| 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); |
| } |
| |
| private void addCardDataToEditFields() { |
| if (mCard == null) { |
| mNameLabel.requestFocus(); |
| return; |
| } |
| |
| if (!TextUtils.isEmpty(mCard.getName())) { |
| mNameLabel.getEditText().setText(mCard.getName()); |
| } |
| if (!TextUtils.isEmpty(mCard.getNumber())) { |
| mNumberLabel.getEditText().setText(mCard.getNumber()); |
| } |
| |
| // Make the name label focusable in touch mode so that mNameText doesn't get focused. |
| mNameLabel.setFocusableInTouchMode(true); |
| |
| int monthAsInt = 1; |
| if (!mCard.getMonth().isEmpty()) { |
| monthAsInt = Integer.parseInt(mCard.getMonth()); |
| } |
| mInitialExpirationMonthPos = monthAsInt - 1; |
| mExpirationMonth.setSelection(mInitialExpirationMonthPos); |
| |
| mInitialExpirationYearPos = 0; |
| boolean foundYear = false; |
| for (int i = 0; i < mExpirationYear.getAdapter().getCount(); i++) { |
| if (mCard.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 && !mCard.getYear().isEmpty()) { |
| @SuppressWarnings("unchecked") |
| ArrayAdapter<CharSequence> adapter = |
| (ArrayAdapter<CharSequence>) mExpirationYear.getAdapter(); |
| adapter.insert(mCard.getYear(), 0); |
| mInitialExpirationYearPos = 0; |
| } |
| mExpirationYear.setSelection(mInitialExpirationYearPos); |
| } |
| |
| @Override |
| protected boolean saveEntry() { |
| // Remove all spaces in editText. |
| String cardNumber = mNumberText.getText().toString().replaceAll("\\s+", ""); |
| PersonalDataManager personalDataManager = PersonalDataManager.getInstance(); |
| // Issuer network will be empty if credit card number is not valid. |
| if (TextUtils.isEmpty(personalDataManager.getBasicCardIssuerNetwork( |
| cardNumber, true /* emptyIfInvalid */))) { |
| mNumberLabel.setError(mContext.getString( |
| R.string.payments_card_number_invalid_validation_message)); |
| return false; |
| } |
| CreditCard card = new CreditCard(mGUID, AutofillAndPaymentsPreferences.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 */, |
| "" /* serverId */); |
| personalDataManager.setCreditCard(card); |
| return true; |
| } |
| |
| @Override |
| protected void deleteEntry() { |
| if (mGUID != null) { |
| PersonalDataManager.getInstance().deleteCreditCard(mGUID); |
| } |
| } |
| |
| @Override |
| protected void initializeButtons(View v) { |
| super.initializeButtons(v); |
| |
| // Listen for change to inputs. Enable the save button after something has changed. |
| mNameText.addTextChangedListener(this); |
| mNumberText.addTextChangedListener(this); |
| mExpirationMonth.setOnItemSelectedListener(this); |
| mExpirationYear.setOnItemSelectedListener(this); |
| |
| // Listen for touch events for drop down menus. We clear the keyboard when user touches |
| // any of these fields. |
| mExpirationMonth.setOnTouchListener(this); |
| mExpirationYear.setOnTouchListener(this); |
| } |
| |
| private void updateSaveButtonEnabled() { |
| // Enable save button if credit card number is not empty. We validate the credit card number |
| // when user presses the save button. |
| boolean enabled = !TextUtils.isEmpty(mNumberText.getText()); |
| ((Button) getView().findViewById(R.id.button_primary)).setEnabled(enabled); |
| } |
| } |