Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java

Issue 2557873002: [Payments] Move focus to next field in expired cvc unmask prompt. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.autofill; 5 package org.chromium.chrome.browser.autofill;
6 6
7 import android.content.Context; 7 import android.content.Context;
8 import android.content.DialogInterface; 8 import android.content.DialogInterface;
9 import android.content.res.Resources; 9 import android.content.res.Resources;
10 import android.graphics.Color; 10 import android.graphics.Color;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 private final View mVerificationOverlay; 71 private final View mVerificationOverlay;
72 private final ProgressBar mVerificationProgressBar; 72 private final ProgressBar mVerificationProgressBar;
73 private final TextView mVerificationView; 73 private final TextView mVerificationView;
74 private final long mSuccessMessageDurationMilliseconds; 74 private final long mSuccessMessageDurationMilliseconds;
75 75
76 private int mThisYear; 76 private int mThisYear;
77 private int mThisMonth; 77 private int mThisMonth;
78 private boolean mValidationWaitsForCalendarTask; 78 private boolean mValidationWaitsForCalendarTask;
79 79
80 private String mCvcErrorMessage; 80 private String mCvcErrorMessage;
81 private String mExpirationErrorMessage; 81 private String mExpirationMonthErrorMessage;
82 private String mExpirationYearErrorMessage;
83 private String mExpirationDateErrorMessage;
82 private String mCvcAndExpirationErrorMessage; 84 private String mCvcAndExpirationErrorMessage;
83 85
84 private boolean mFinishedTypingMonth; 86 private boolean mStartedTypingMonth;
85 private boolean mFinishedTypingYear; 87 private boolean mStartedTypingYear;
86 private boolean mFinishedTypingCvc; 88 private boolean mStartedTypingCvc;
87 89
88 public static final int ERROR_TYPE_EXPIRATION = 1; 90 private static final int EXPIRATION_FIELDS_LENGTH = 2;
89 public static final int ERROR_TYPE_CVC = 2; 91
90 public static final int ERROR_TYPE_BOTH = 3; 92 public static final int ERROR_TYPE_EXPIRATION_MONTH = 1;
93 public static final int ERROR_TYPE_EXPIRATION_YEAR = 2;
94 public static final int ERROR_TYPE_EXPIRATION_DATE = 3;
95 public static final int ERROR_TYPE_CVC = 4;
96 public static final int ERROR_TYPE_CVC_AND_EXPIRATION = 5;
97 public static final int ERROR_TYPE_NOT_ENOUGH_INFO = 6;
98 public static final int ERROR_TYPE_NONE = 7;
91 99
92 @Retention(RetentionPolicy.SOURCE) 100 @Retention(RetentionPolicy.SOURCE)
93 @IntDef({ 101 @IntDef({ERROR_TYPE_EXPIRATION_MONTH, ERROR_TYPE_EXPIRATION_YEAR, ERROR_TYPE _EXPIRATION_DATE,
94 ERROR_TYPE_EXPIRATION, 102 ERROR_TYPE_CVC, ERROR_TYPE_CVC_AND_EXPIRATION, ERROR_TYPE_NOT_ENOUGH _INFO,
95 ERROR_TYPE_CVC, 103 ERROR_TYPE_NONE})
96 ERROR_TYPE_BOTH
97 })
98 public @interface ErrorType {} 104 public @interface ErrorType {}
99 105
100 /** 106 /**
101 * An interface to handle the interaction with an CardUnmaskPrompt object. 107 * An interface to handle the interaction with an CardUnmaskPrompt object.
102 */ 108 */
103 public interface CardUnmaskPromptDelegate { 109 public interface CardUnmaskPromptDelegate {
104 /** 110 /**
105 * Called when the dialog has been dismissed. 111 * Called when the dialog has been dismissed.
106 */ 112 */
107 void dismissed(); 113 void dismissed();
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 .setNegativeButton(R.string.cancel, null) 193 .setNegativeButton(R.string.cancel, null)
188 .setPositiveButton(confirmButtonLabel, null) 194 .setPositiveButton(confirmButtonLabel, null)
189 .create(); 195 .create();
190 mDialog.setOnDismissListener(this); 196 mDialog.setOnDismissListener(this);
191 197
192 mShouldRequestExpirationDate = shouldRequestExpirationDate; 198 mShouldRequestExpirationDate = shouldRequestExpirationDate;
193 mThisYear = -1; 199 mThisYear = -1;
194 mThisMonth = -1; 200 mThisMonth = -1;
195 if (mShouldRequestExpirationDate) new CalendarTask().execute(); 201 if (mShouldRequestExpirationDate) new CalendarTask().execute();
196 202
197 // Create the observers to be notified when the user has finished editin g the input fields. 203 // Create the listeners to be notified when the user focuses out the inp ut fields.
198 mCardUnmaskInput.setOnFocusChangeListener(new OnFocusChangeListener() { 204 mCardUnmaskInput.setOnFocusChangeListener(new OnFocusChangeListener() {
199 @Override 205 @Override
200 public void onFocusChange(View v, boolean hasFocus) { 206 public void onFocusChange(View v, boolean hasFocus) {
201 if (!hasFocus && !mCardUnmaskInput.getText().toString().isEmpty( ) 207 validate();
202 && !mFinishedTypingCvc) {
203 mFinishedTypingCvc = true;
204 validate();
205 }
206 } 208 }
207 }); 209 });
208 mMonthInput.setOnFocusChangeListener(new OnFocusChangeListener() { 210 mMonthInput.setOnFocusChangeListener(new OnFocusChangeListener() {
209 @Override 211 @Override
210 public void onFocusChange(View v, boolean hasFocus) { 212 public void onFocusChange(View v, boolean hasFocus) {
211 if (!hasFocus && !mMonthInput.getText().toString().isEmpty() 213 validate();
212 && !mFinishedTypingMonth) {
213 mFinishedTypingMonth = true;
214 validate();
215 }
216 } 214 }
217 }); 215 });
218 mYearInput.setOnFocusChangeListener(new OnFocusChangeListener() { 216 mYearInput.setOnFocusChangeListener(new OnFocusChangeListener() {
219 @Override 217 @Override
220 public void onFocusChange(View v, boolean hasFocus) { 218 public void onFocusChange(View v, boolean hasFocus) {
221 if (!hasFocus && !mYearInput.getText().toString().isEmpty() 219 validate();
222 && !mFinishedTypingYear) {
223 mFinishedTypingYear = true;
224 validate();
225 }
226 } 220 }
227 }); 221 });
228 222
223 // Create the listeners to be notified when the user types into the inpu t fields.
224 mCardUnmaskInput.addTextChangedListener(new TextWatcher() {
225 @Override
226 public void afterTextChanged(Editable s) {}
227
228 @Override
229 public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
230
231 @Override
232 public void onTextChanged(CharSequence s, int start, int before, int count) {
233 mStartedTypingCvc = true;
234 }
235 });
236 mMonthInput.addTextChangedListener(new TextWatcher() {
237 @Override
238 public void afterTextChanged(Editable s) {}
239
240 @Override
241 public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
242
243 @Override
244 public void onTextChanged(CharSequence s, int start, int before, int count) {
245 mStartedTypingMonth = true;
246 }
247 });
248 mYearInput.addTextChangedListener(new TextWatcher() {
249 @Override
250 public void afterTextChanged(Editable s) {}
251
252 @Override
253 public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
254
255 @Override
256 public void onTextChanged(CharSequence s, int start, int before, int count) {
257 mStartedTypingYear = true;
258 }
259 });
260
261 // Load the error messages to show to the user.
229 Resources resources = context.getResources(); 262 Resources resources = context.getResources();
230 mCvcErrorMessage = 263 mCvcErrorMessage =
231 resources.getString(R.string.autofill_card_unmask_prompt_error_t ry_again_cvc); 264 resources.getString(R.string.autofill_card_unmask_prompt_error_t ry_again_cvc);
232 mExpirationErrorMessage = resources.getString( 265 mExpirationMonthErrorMessage = resources.getString(
233 R.string.autofill_card_unmask_prompt_error_try_again_expiration) ; 266 R.string.autofill_card_unmask_prompt_error_try_again_expiration_ month);
267 mExpirationYearErrorMessage = resources.getString(
268 R.string.autofill_card_unmask_prompt_error_try_again_expiration_ year);
269 mExpirationDateErrorMessage = resources.getString(
270 R.string.autofill_card_unmask_prompt_error_try_again_expiration_ date);
234 mCvcAndExpirationErrorMessage = resources.getString( 271 mCvcAndExpirationErrorMessage = resources.getString(
235 R.string.autofill_card_unmask_prompt_error_try_again_cvc_and_exp iration); 272 R.string.autofill_card_unmask_prompt_error_try_again_cvc_and_exp iration);
236 } 273 }
237 274
238 /** 275 /**
239 * Avoids disk reads for timezone when getting the default instance of Calen dar. 276 * Avoids disk reads for timezone when getting the default instance of Calen dar.
240 */ 277 */
241 private class CalendarTask extends AsyncTask<Void, Void, Calendar> { 278 private class CalendarTask extends AsyncTask<Void, Void, Calendar> {
242 @Override 279 @Override
243 protected Calendar doInBackground(Void... unused) { 280 protected Calendar doInBackground(Void... unused) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 mVerificationProgressBar.setVisibility(View.VISIBLE); 335 mVerificationProgressBar.setVisibility(View.VISIBLE);
299 mVerificationView.setText(R.string.autofill_card_unmask_verification_in_ progress); 336 mVerificationView.setText(R.string.autofill_card_unmask_verification_in_ progress);
300 mVerificationView.announceForAccessibility(mVerificationView.getText()); 337 mVerificationView.announceForAccessibility(mVerificationView.getText());
301 clearInputError(); 338 clearInputError();
302 } 339 }
303 340
304 public void verificationFinished(String errorMessage, boolean allowRetry) { 341 public void verificationFinished(String errorMessage, boolean allowRetry) {
305 if (errorMessage != null) { 342 if (errorMessage != null) {
306 setOverlayVisibility(View.GONE); 343 setOverlayVisibility(View.GONE);
307 if (allowRetry) { 344 if (allowRetry) {
308 setInputError(errorMessage, ERROR_TYPE_BOTH); 345 showErrorMessage(errorMessage);
309 setInputsEnabled(true); 346 setInputsEnabled(true);
310 setInitialFocus(); 347 setInitialFocus();
311 348
312 if (!mShouldRequestExpirationDate) mNewCardLink.setVisibility(Vi ew.VISIBLE); 349 if (!mShouldRequestExpirationDate) mNewCardLink.setVisibility(Vi ew.VISIBLE);
313 } else { 350 } else {
314 clearInputError(); 351 clearInputError();
315 setNoRetryError(errorMessage); 352 setNoRetryError(errorMessage);
316 } 353 }
317 } else { 354 } else {
318 Runnable dismissRunnable = new Runnable() { 355 Runnable dismissRunnable = new Runnable() {
(...skipping 17 matching lines...) Expand all
336 @Override 373 @Override
337 public void onDismiss(DialogInterface dialog) { 374 public void onDismiss(DialogInterface dialog) {
338 mDelegate.dismissed(); 375 mDelegate.dismissed();
339 } 376 }
340 377
341 @Override 378 @Override
342 public void afterTextChanged(Editable s) { 379 public void afterTextChanged(Editable s) {
343 validate(); 380 validate();
344 } 381 }
345 382
383 /**
384 * Validates the values of the input fields to determine whether the submit button should be
385 * enabled. Also displays a detailed error message and highlights the fields for which the value
386 * is wrong. Finally checks whether the focuse should move to the next field .
387 */
346 private void validate() { 388 private void validate() {
347 Button positiveButton = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); 389 Button positiveButton = mDialog.getButton(AlertDialog.BUTTON_POSITIVE);
348 390
349 boolean hasValidExpiration = isExpirationDateValid(); 391 @ErrorType int errorType = areExpirationAndCvcValid();
350 boolean hasValidCvc = isCvcValid(); 392 positiveButton.setEnabled(errorType == ERROR_TYPE_NONE);
351 393 showDetailedErrorMessage(errorType);
352 // Since the CVC input field is the last one, users won't necessarily fo cus out of it. It 394 moveFocus(errorType);
353 // should be considered as finished once the CVC becomes valid.
354 if (hasValidCvc) mFinishedTypingCvc = true;
355
356 positiveButton.setEnabled(hasValidExpiration && hasValidCvc);
357 showDetailedErrorMessage(hasValidExpiration, hasValidCvc);
358 395
359 if (sObserverForTest != null) { 396 if (sObserverForTest != null) {
360 sObserverForTest.onCardUnmaskPromptValidationDone(this); 397 sObserverForTest.onCardUnmaskPromptValidationDone(this);
361 398
362 if (positiveButton.isEnabled()) { 399 if (positiveButton.isEnabled()) {
363 sObserverForTest.onCardUnmaskPromptReadyToUnmask(this); 400 sObserverForTest.onCardUnmaskPromptReadyToUnmask(this);
364 } 401 }
365 } 402 }
366 } 403 }
367 404
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 InputMethodManager imm = (InputMethodManager) mDialog.getContext().getSy stemService( 490 InputMethodManager imm = (InputMethodManager) mDialog.getContext().getSy stemService(
454 Context.INPUT_METHOD_SERVICE); 491 Context.INPUT_METHOD_SERVICE);
455 View view = mShouldRequestExpirationDate ? mMonthInput : mCardUnmaskInpu t; 492 View view = mShouldRequestExpirationDate ? mMonthInput : mCardUnmaskInpu t;
456 imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); 493 imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
457 view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 494 view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
458 if (sObserverForTest != null) { 495 if (sObserverForTest != null) {
459 sObserverForTest.onCardUnmaskPromptReadyForInput(this); 496 sObserverForTest.onCardUnmaskPromptReadyForInput(this);
460 } 497 }
461 } 498 }
462 499
463 private void showDetailedErrorMessage(boolean hasValidExpiration, boolean ha sValidCvc) { 500 /**
464 // Only show an expiration date error if the user has finished typing bo th the month and 501 * Moves the focus to the next field based on the value of the fields and th e specified type of
465 // year fields. 502 * error found for the unmask field(s).
466 boolean shouldShowExpirationError = 503 *
467 !hasValidExpiration && mFinishedTypingMonth && mFinishedTypingYe ar; 504 * @param errorType The type of error detected.
468 505 */
469 // Only show a CVC error if the user has fininshed typing. 506 private void moveFocus(@ErrorType int errorType) {
470 boolean shouldShowCvcError = !hasValidCvc && mFinishedTypingCvc; 507 if (errorType == ERROR_TYPE_NOT_ENOUGH_INFO) {
471 508 if (mMonthInput.isFocused() && mMonthInput.getText().length() == 2) {
472 if (shouldShowExpirationError && shouldShowCvcError) { 509 mYearInput.requestFocus();
473 setInputError(mCvcAndExpirationErrorMessage, ERROR_TYPE_BOTH); 510 } else if (mYearInput.isFocused() && mYearInput.getText().length() = = 2) {
474 } else if (shouldShowExpirationError) { 511 mCardUnmaskInput.requestFocus();
475 setInputError(mExpirationErrorMessage, ERROR_TYPE_EXPIRATION); 512 }
476 } else if (shouldShowCvcError) {
477 setInputError(mCvcErrorMessage, ERROR_TYPE_CVC);
478 } else {
479 clearInputError();
480 } 513 }
481 } 514 }
482 515
483 private boolean isExpirationDateValid() { 516 /**
484 if (!mShouldRequestExpirationDate) return true; 517 * Shows (or removes) the appropriate error message and apply the error filt er to the
518 * appropriate fields depending on the error type.
519 *
520 * @param errorType The type of error detected.
521 */
522 private void showDetailedErrorMessage(@ErrorType int errorType) {
523 switch (errorType) {
524 case ERROR_TYPE_NONE:
525 case ERROR_TYPE_NOT_ENOUGH_INFO:
526 default:
please use gerrit instead 2016/12/08 18:59:59 Default usually goes to the bottom and you don't n
sebsg 2016/12/08 19:55:27 I moved it down But I get warnings if I remove the
527 clearInputError();
528 return;
485 529
530 case ERROR_TYPE_EXPIRATION_MONTH:
531 showErrorMessage(mExpirationMonthErrorMessage);
532 break;
533
534 case ERROR_TYPE_EXPIRATION_YEAR:
535 showErrorMessage(mExpirationYearErrorMessage);
536 break;
537
538 case ERROR_TYPE_EXPIRATION_DATE:
539 showErrorMessage(mExpirationDateErrorMessage);
540 break;
541
542 case ERROR_TYPE_CVC:
543 showErrorMessage(mCvcErrorMessage);
544 break;
545
546 case ERROR_TYPE_CVC_AND_EXPIRATION:
547 showErrorMessage(mCvcAndExpirationErrorMessage);
548 break;
549 }
550
551 updateColorForInputs(errorType);
552 }
553
554 /**
555 * Applies the error filter to the invalid fields based on the errorType.
556 *
557 * @param The ErrorType value representing the type of error found for the u nmask fields.
558 */
559 private void updateColorForInputs(@ErrorType int errorType) {
560 // The rest of this code makes L-specific assumptions about the backgrou nd being used to
561 // draw the TextInput.
562 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
563
564 ColorFilter filter = new PorterDuffColorFilter(
565 ApiCompatibilityUtils.getColor(
566 mDialog.getContext().getResources(), R.color.input_under line_error_color),
567 PorterDuff.Mode.SRC_IN);
568
569 // Decide on what field(s) to apply the filter.
570 boolean filterMonth = errorType == ERROR_TYPE_EXPIRATION_MONTH
571 || errorType == ERROR_TYPE_EXPIRATION_DATE
572 || errorType == ERROR_TYPE_CVC_AND_EXPIRATION;
573 boolean filterYear = errorType == ERROR_TYPE_EXPIRATION_YEAR
574 || errorType == ERROR_TYPE_EXPIRATION_DATE
575 || errorType == ERROR_TYPE_CVC_AND_EXPIRATION;
576 boolean filterCvc =
577 errorType == ERROR_TYPE_CVC || errorType == ERROR_TYPE_CVC_AND_E XPIRATION;
578
579 updateColorForInput(mMonthInput, filterMonth ? filter : null);
580 updateColorForInput(mYearInput, filterYear ? filter : null);
581 updateColorForInput(mCardUnmaskInput, filterCvc ? filter : null);
582 }
583
584 /**
585 * Determines what type of error, if any, is present in the cvc and expirati on date fields of
586 * the prompt.
587 *
588 * @return The ErrorType value representing the type of error found for the unmask fields.
589 */
590 private int areExpirationAndCvcValid() {
please use gerrit instead 2016/12/08 18:59:58 @ErrorType
please use gerrit instead 2016/12/08 18:59:58 This does not return a boolean, so it's inadvisabl
sebsg 2016/12/08 19:55:27 Done.
sebsg 2016/12/08 19:55:27 Done.
591 @ErrorType
592 int errorType = ERROR_TYPE_NONE;
593
594 if (mShouldRequestExpirationDate) {
please use gerrit instead 2016/12/08 18:59:59 Single line?
sebsg 2016/12/08 19:55:27 Done.
595 errorType = isExpirationDateValid();
596 }
597
598 // If the CVC is valid, return the error type determined so far.
599 if (isCvcValid()) return errorType;
600
601 if (mStartedTypingCvc && !mCardUnmaskInput.isFocused()) {
602 // The CVC is invalid and the user has typed in the CVC field, but i s not focused on it
603 // now. Add the CVC error to the current error.
604 if (errorType == ERROR_TYPE_NONE || errorType == ERROR_TYPE_NOT_ENOU GH_INFO) {
605 errorType = ERROR_TYPE_CVC;
606 } else {
607 errorType = ERROR_TYPE_CVC_AND_EXPIRATION;
608 }
609 } else {
610 // The CVC is invalid but the user is not done with the field.
611 // If no other errors were detected, set that there is not enough in formation.
612 if (errorType == ERROR_TYPE_NONE) errorType = ERROR_TYPE_NOT_ENOUGH_ INFO;
613 }
614
615 return errorType;
616 }
617
618 /**
619 * Determines what type of error, if any, is present in the expiration date fields of the
620 * prompt.
621 *
622 * @return The ErrorType value representing the type of error found for the expiration date
623 * unmask fields.
624 */
please use gerrit instead 2016/12/08 18:59:59 @ErrorType private int getExpirationDateErrorType(
sebsg 2016/12/08 19:55:27 Done.
625 private int isExpirationDateValid() {
486 if (mThisYear == -1 || mThisMonth == -1) { 626 if (mThisYear == -1 || mThisMonth == -1) {
487 mValidationWaitsForCalendarTask = true; 627 mValidationWaitsForCalendarTask = true;
488 return false; 628 return ERROR_TYPE_NOT_ENOUGH_INFO;
489 } 629 }
490 630
491 int month = -1; 631 int month = getMonth();
492 try { 632 if (month < 1 || month > 12) {
493 month = Integer.parseInt(mMonthInput.getText().toString()); 633 if (mMonthInput.getText().length() == EXPIRATION_FIELDS_LENGTH
494 if (month < 1 || month > 12) return false; 634 || (!mMonthInput.isFocused() && mStartedTypingMonth)) {
495 } catch (NumberFormatException e) { 635 // mFinishedTypingMonth = true;
496 return false; 636 return ERROR_TYPE_EXPIRATION_MONTH;
637 }
638 return ERROR_TYPE_NOT_ENOUGH_INFO;
497 } 639 }
498 640
499 int year = getFourDigitYear(); 641 int year = getFourDigitYear();
500 if (year < mThisYear || year > mThisYear + 10) return false; 642 if (year < mThisYear || year > mThisYear + 10) {
643 if (mYearInput.getText().length() == EXPIRATION_FIELDS_LENGTH
644 || (!mYearInput.isFocused() && mStartedTypingYear)) {
645 // mFinishedTypingYear = true;
646 return ERROR_TYPE_EXPIRATION_YEAR;
647 }
648 return ERROR_TYPE_NOT_ENOUGH_INFO;
649 }
501 650
502 if (year == mThisYear && month < mThisMonth) return false; 651 if (year == mThisYear && month < mThisMonth) {
652 return ERROR_TYPE_EXPIRATION_DATE;
653 }
503 654
504 return true; 655 return ERROR_TYPE_NONE;
505 } 656 }
506 657
658 /**
659 * Makes a call to the native code to determine if the value in the CVC inpu t field is valid.
660 *
661 * @return Whether the CVC is valid.
662 */
507 private boolean isCvcValid() { 663 private boolean isCvcValid() {
508 return mDelegate.checkUserInputValidity(mCardUnmaskInput.getText().toStr ing()); 664 return mDelegate.checkUserInputValidity(mCardUnmaskInput.getText().toStr ing());
509 } 665 }
510 666
511 /** 667 /**
512 * Sets the enabled state of the main contents, and hides or shows the verif ication overlay. 668 * Sets the enabled state of the main contents, and hides or shows the verif ication overlay.
513 * @param enabled True if the inputs should be useable, false if the verific ation overlay 669 * @param enabled True if the inputs should be useable, false if the verific ation overlay
514 * obscures them. 670 * obscures them.
515 */ 671 */
516 private void setInputsEnabled(boolean enabled) { 672 private void setInputsEnabled(boolean enabled) {
(...skipping 21 matching lines...) Expand all
538 ViewCompat.setImportantForAccessibility(mControlsContainer, 694 ViewCompat.setImportantForAccessibility(mControlsContainer,
539 contentsShowing ? View.IMPORTANT_FOR_ACCESSIBILITY_AUTO 695 contentsShowing ? View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
540 : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCE NDANTS); 696 : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCE NDANTS);
541 mControlsContainer.setDescendantFocusability( 697 mControlsContainer.setDescendantFocusability(
542 contentsShowing ? ViewGroup.FOCUS_BEFORE_DESCENDANTS 698 contentsShowing ? ViewGroup.FOCUS_BEFORE_DESCENDANTS
543 : ViewGroup.FOCUS_BLOCK_DESCENDANTS); 699 : ViewGroup.FOCUS_BLOCK_DESCENDANTS);
544 } 700 }
545 701
546 /** 702 /**
547 * Sets the error message on the inputs. 703 * Sets the error message on the inputs.
548 * @param message The error message to show, or null if the error state shou ld be cleared. 704 * @param message The error message to show.
549 */ 705 */
550 private void setInputError(String message, @ErrorType int errorType) { 706 private void showErrorMessage(String message) {
551 assert message != null; 707 assert message != null;
552 708
553 // Set the message to display; 709 // Set the message to display;
554 mErrorMessage.setText(message); 710 mErrorMessage.setText(message);
555 mErrorMessage.setVisibility(View.VISIBLE); 711 mErrorMessage.setVisibility(View.VISIBLE);
556 712
557 // A null message is passed in during card verification, which also make s an announcement. 713 // A null message is passed in during card verification, which also make s an announcement.
558 // Announcing twice in a row may cancel the first announcement. 714 // Announcing twice in a row may cancel the first announcement.
559 mErrorMessage.announceForAccessibility(message); 715 mErrorMessage.announceForAccessibility(message);
560
561 // The rest of this code makes L-specific assumptions about the backgrou nd being used to
562 // draw the TextInput.
563 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
564
565 ColorFilter filter = new PorterDuffColorFilter(ApiCompatibilityUtils.get Color(
566 mDialog.getContext().getResources(),
567 R.color.input_underline_error_color), PorterDuff.Mode.SRC_IN);
568
569 if (errorType == ERROR_TYPE_BOTH) {
570 updateColorForInput(mCardUnmaskInput, filter);
571 updateColorForInput(mMonthInput, filter);
572 updateColorForInput(mYearInput, filter);
573 } else if (errorType == ERROR_TYPE_CVC) {
574 updateColorForInput(mCardUnmaskInput, filter);
575 updateColorForInput(mMonthInput, null);
576 updateColorForInput(mYearInput, null);
577 } else if (errorType == ERROR_TYPE_EXPIRATION) {
578 updateColorForInput(mMonthInput, filter);
579 updateColorForInput(mYearInput, filter);
580 updateColorForInput(mCardUnmaskInput, null);
581 }
582 } 716 }
583 717
584 /** 718 /**
585 * Removes the error message on the inputs. 719 * Removes the error message on the inputs.
586 */ 720 */
587 private void clearInputError() { 721 private void clearInputError() {
588 mErrorMessage.setText(null); 722 mErrorMessage.setText(null);
589 mErrorMessage.setVisibility(View.GONE); 723 mErrorMessage.setVisibility(View.GONE);
590 724
591 // The rest of this code makes L-specific assumptions about the backgrou nd being used to 725 // The rest of this code makes L-specific assumptions about the backgrou nd being used to
(...skipping 18 matching lines...) Expand all
610 /** 744 /**
611 * Sets the stroke color for the given input. 745 * Sets the stroke color for the given input.
612 * @param input The input to modify. 746 * @param input The input to modify.
613 * @param filter The color filter to apply to the background. 747 * @param filter The color filter to apply to the background.
614 */ 748 */
615 private void updateColorForInput(EditText input, ColorFilter filter) { 749 private void updateColorForInput(EditText input, ColorFilter filter) {
616 input.getBackground().mutate().setColorFilter(filter); 750 input.getBackground().mutate().setColorFilter(filter);
617 } 751 }
618 752
619 /** 753 /**
620 * Returns the expiration year the user entered. 754 * @return The expiration year the user entered.
621 * Two digit values (such as 17) will be converted to 4 digit years (such as 2017). 755 * Two digit values (such as 17) will be converted to 4 digit years (such as 2017).
622 * Returns -1 if the input is empty or otherwise not a valid year. 756 * Returns -1 if the input is empty or otherwise not a valid year.
623 */ 757 */
624 private int getFourDigitYear() { 758 private int getFourDigitYear() {
625 try { 759 try {
626 int year = Integer.parseInt(mYearInput.getText().toString()); 760 int year = Integer.parseInt(mYearInput.getText().toString());
627 if (year < 0) return -1; 761 if (year < 0) return -1;
628 if (year < 100) year += mThisYear - mThisYear % 100; 762 if (year < 100) year += mThisYear - mThisYear % 100;
629 return year; 763 return year;
630 } catch (NumberFormatException e) { 764 } catch (NumberFormatException e) {
631 return -1; 765 return -1;
632 } 766 }
633 } 767 }
634 768
769 /**
770 * @return The expiration month the user entered.
771 * Returns -1 if the input is empty or otherwise not a valid month.
please use gerrit instead 2016/12/08 18:59:59 You can't say "otherwise not a valid month", becau
sebsg 2016/12/08 19:55:27 Done.
772 */
773 private int getMonth() {
774 try {
775 return Integer.parseInt(mMonthInput.getText().toString());
776 } catch (NumberFormatException e) {
777 return -1;
778 }
779 }
780
635 @VisibleForTesting 781 @VisibleForTesting
636 public static void setObserverForTest(CardUnmaskObserverForTest observerForT est) { 782 public static void setObserverForTest(CardUnmaskObserverForTest observerForT est) {
637 sObserverForTest = observerForTest; 783 sObserverForTest = observerForTest;
638 } 784 }
639 785
640 @VisibleForTesting 786 @VisibleForTesting
641 public AlertDialog getDialogForTest() { 787 public AlertDialog getDialogForTest() {
642 return mDialog; 788 return mDialog;
643 } 789 }
644 790
645 @VisibleForTesting 791 @VisibleForTesting
646 public String getErrorMessage() { 792 public String getErrorMessage() {
647 return mErrorMessage.getText().toString(); 793 return mErrorMessage.getText().toString();
648 } 794 }
649 } 795 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698