Commit 6c4344f5 authored by John Z Wu's avatar John Z Wu Committed by Commit Bot

Define CWVCreditCardExpirationFixer to help with fixing expired cards

If a new card was entered with an already expired date, we may prompt
the user to fix it up before uploading.

Bug: 1066690
Change-Id: Iff960a26a512dc66e6f356190e0524b63cba362c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2133552
Commit-Queue: John Wu <jzw@chromium.org>
Reviewed-by: default avatarHiroshi Ichikawa <ichikawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755900}
parent 16af3fc3
...@@ -89,6 +89,7 @@ if (ios_web_view_enable_autofill) { ...@@ -89,6 +89,7 @@ if (ios_web_view_enable_autofill) {
"public/cwv_autofill_profile.h", "public/cwv_autofill_profile.h",
"public/cwv_autofill_suggestion.h", "public/cwv_autofill_suggestion.h",
"public/cwv_credit_card.h", "public/cwv_credit_card.h",
"public/cwv_credit_card_expiration_fixer.h",
"public/cwv_credit_card_saver.h", "public/cwv_credit_card_saver.h",
"public/cwv_credit_card_verifier.h", "public/cwv_credit_card_verifier.h",
"public/cwv_password.h", "public/cwv_password.h",
...@@ -252,6 +253,8 @@ if (ios_web_view_enable_autofill) { ...@@ -252,6 +253,8 @@ if (ios_web_view_enable_autofill) {
"internal/autofill/cwv_autofill_suggestion.mm", "internal/autofill/cwv_autofill_suggestion.mm",
"internal/autofill/cwv_autofill_suggestion_internal.h", "internal/autofill/cwv_autofill_suggestion_internal.h",
"internal/autofill/cwv_credit_card.mm", "internal/autofill/cwv_credit_card.mm",
"internal/autofill/cwv_credit_card_expiration_fixer.mm",
"internal/autofill/cwv_credit_card_expiration_fixer_internal.h",
"internal/autofill/cwv_credit_card_internal.h", "internal/autofill/cwv_credit_card_internal.h",
"internal/autofill/cwv_credit_card_saver.mm", "internal/autofill/cwv_credit_card_saver.mm",
"internal/autofill/cwv_credit_card_saver_internal.h", "internal/autofill/cwv_credit_card_saver_internal.h",
...@@ -415,6 +418,7 @@ test("ios_web_view_unittests") { ...@@ -415,6 +418,7 @@ test("ios_web_view_unittests") {
"internal/autofill/cwv_autofill_form_unittest.mm", "internal/autofill/cwv_autofill_form_unittest.mm",
"internal/autofill/cwv_autofill_profile_unittest.mm", "internal/autofill/cwv_autofill_profile_unittest.mm",
"internal/autofill/cwv_autofill_suggestion_unittest.mm", "internal/autofill/cwv_autofill_suggestion_unittest.mm",
"internal/autofill/cwv_credit_card_expiration_fixer_unittest.mm",
"internal/autofill/cwv_credit_card_saver_unittest.mm", "internal/autofill/cwv_credit_card_saver_unittest.mm",
"internal/autofill/cwv_credit_card_unittest.mm", "internal/autofill/cwv_credit_card_unittest.mm",
"internal/autofill/cwv_credit_card_verifier_unittest.mm", "internal/autofill/cwv_credit_card_verifier_unittest.mm",
......
// Copyright 2020 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.
#import "ios/web_view/internal/autofill/cwv_credit_card_expiration_fixer_internal.h"
#include "base/strings/sys_string_conversions.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_controller_impl.h"
#include "components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_clock.h"
#import "ios/web_view/internal/autofill/cwv_credit_card_internal.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace ios_web_view {
// Empty implementation of autofill::CardExpirationDateFixFlowView.
class WebViewCardExpirationFixFlowView
: public autofill::CardExpirationDateFixFlowView {
public:
void Show() override {
// No op.
}
void ControllerGone() override {
// No op.
}
};
} // namespace ios_web_view
@implementation CWVCreditCardExpirationFixer {
std::unique_ptr<ios_web_view::WebViewCardExpirationFixFlowView> _view;
std::unique_ptr<autofill::CardExpirationDateFixFlowControllerImpl>
_controller;
}
- (instancetype)initWithCreditCard:(const autofill::CreditCard&)creditCard
callback:
(base::OnceCallback<void(const base::string16&,
const base::string16&)>)
callback {
self = [super init];
if (self) {
_card = [[CWVCreditCard alloc] initWithCreditCard:creditCard];
_view = std::make_unique<ios_web_view::WebViewCardExpirationFixFlowView>();
_controller =
std::make_unique<autofill::CardExpirationDateFixFlowControllerImpl>();
_controller->Show(_view.get(), creditCard, std::move(callback));
}
return self;
}
- (void)dealloc {
_controller->OnDialogClosed();
}
#pragma mark - Public
- (NSString*)titleText {
return base::SysUTF16ToNSString(_controller->GetTitleText());
}
- (NSString*)saveButtonLabel {
return base::SysUTF16ToNSString(_controller->GetSaveButtonLabel());
}
- (NSString*)cardLabel {
return base::SysUTF16ToNSString(_controller->GetCardLabel());
}
- (NSString*)cancelButtonLabel {
return base::SysUTF16ToNSString(_controller->GetCancelButtonLabel());
}
- (NSString*)inputLabel {
return base::SysUTF16ToNSString(_controller->GetInputLabel());
}
- (NSString*)dateSeparator {
return base::SysUTF16ToNSString(_controller->GetDateSeparator());
}
- (NSString*)invalidDateErrorMessage {
return base::SysUTF16ToNSString(_controller->GetInvalidDateError());
}
- (BOOL)acceptWithMonth:(NSString*)month year:(NSString*)year {
BOOL isValidDate = autofill::IsValidCreditCardExpirationDate(
year.intValue, month.intValue, autofill::AutofillClock::Now());
if (isValidDate) {
_controller->OnAccepted(base::SysNSStringToUTF16(month),
base::SysNSStringToUTF16(year));
}
return isValidDate;
}
- (void)cancel {
_controller->OnDismissed();
}
@end
// Copyright 2020 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.
#ifndef IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_CREDIT_CARD_EXPIRATION_FIXER_INTERNAL_H_
#define IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_CREDIT_CARD_EXPIRATION_FIXER_INTERNAL_H_
#import "ios/web_view/public/cwv_credit_card_expiration_fixer.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/strings/string16.h"
namespace autofill {
class CreditCard;
} // namespace autofill
@interface CWVCreditCardExpirationFixer ()
// Initializes with a |creditCard| that needs its expiration date fixed and
// a |callback| to be invoked with a new expiration. |callback| should be ran
// with a month and year in MM and YYYY format.
- (instancetype)
initWithCreditCard:(const autofill::CreditCard&)creditCard
callback:(base::OnceCallback<void(const base::string16&,
const base::string16&)>)callback
NS_DESIGNATED_INITIALIZER;
@end
#endif // IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_CREDIT_CARD_EXPIRATION_FIXER_INTERNAL_H_
// Copyright 2020 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.
#import "ios/web_view/internal/autofill/cwv_credit_card_expiration_fixer_internal.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/strings/sys_string_conversions.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#import "ios/web_view/internal/autofill/cwv_credit_card_internal.h"
#include "ios/web_view/test/test_with_locale_and_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace ios_web_view {
class CWVCreditCardExpirationFixerTest : public TestWithLocaleAndResources {
public:
void AcceptExpiration(const base::string16& month,
const base::string16& year) {
_accepted_month = base::SysUTF16ToNSString(month);
_accepted_year = base::SysUTF16ToNSString(year);
}
NSString* _accepted_month;
NSString* _accepted_year;
};
// Tests CWVCreditCardExpirationFixer properties.
TEST_F(CWVCreditCardExpirationFixerTest, Properties) {
autofill::CreditCard card = autofill::test::GetCreditCard();
CWVCreditCardExpirationFixer* fixer = [[CWVCreditCardExpirationFixer alloc]
initWithCreditCard:card
callback:base::DoNothing()];
EXPECT_EQ(card, *fixer.card.internalCard);
EXPECT_TRUE(fixer.titleText);
EXPECT_TRUE(fixer.saveButtonLabel);
EXPECT_TRUE(fixer.cardLabel);
EXPECT_TRUE(fixer.cancelButtonLabel);
EXPECT_TRUE(fixer.inputLabel);
EXPECT_TRUE(fixer.dateSeparator);
EXPECT_TRUE(fixer.invalidDateErrorMessage);
}
// Tests CWVCreditCardExpirationFixer properly accepts a valid expiration.
TEST_F(CWVCreditCardExpirationFixerTest, AcceptValidExpiration) {
autofill::CreditCard card = autofill::test::GetCreditCard();
base::OnceCallback<void(const base::string16&, const base::string16&)>
callback =
base::BindOnce(&CWVCreditCardExpirationFixerTest::AcceptExpiration,
base::Unretained(this));
CWVCreditCardExpirationFixer* fixer = [[CWVCreditCardExpirationFixer alloc]
initWithCreditCard:card
callback:std::move(callback)];
NSString* valid_month = @"12";
NSString* valid_year = @"2099";
EXPECT_TRUE([fixer acceptWithMonth:valid_month year:valid_year]);
EXPECT_NSEQ(valid_month, _accepted_month);
EXPECT_NSEQ(valid_year, _accepted_year);
}
// Tests CWVCreditCardExpirationFixer properly rejects invalid expirations.
TEST_F(CWVCreditCardExpirationFixerTest, RejectsInvalidExpirations) {
autofill::CreditCard card = autofill::test::GetCreditCard();
base::OnceCallback<void(const base::string16&, const base::string16&)>
callback =
base::BindOnce(&CWVCreditCardExpirationFixerTest::AcceptExpiration,
base::Unretained(this));
CWVCreditCardExpirationFixer* fixer = [[CWVCreditCardExpirationFixer alloc]
initWithCreditCard:card
callback:std::move(callback)];
// Date values which are out of range should not be accepted.
EXPECT_FALSE([fixer acceptWithMonth:@"13" year:@"2099"]);
EXPECT_FALSE([fixer acceptWithMonth:@"12" year:@"-2099"]);
// Date values which are alphanumeric should not be accepted.
EXPECT_FALSE([fixer acceptWithMonth:@"December" year:@"2099"]);
EXPECT_FALSE([fixer acceptWithMonth:@"12" year:@"Twenty Ninety Nine"]);
// No expirations should have been accepted.
EXPECT_FALSE(_accepted_month);
EXPECT_FALSE(_accepted_year);
}
} // namespace ios_web_view
// Copyright 2020 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.
#ifndef IOS_WEB_VIEW_PUBLIC_CWV_CREDIT_CARD_EXPIRATION_FIXER_H_
#define IOS_WEB_VIEW_PUBLIC_CWV_CREDIT_CARD_EXPIRATION_FIXER_H_
#import <Foundation/Foundation.h>
#import "cwv_export.h"
NS_ASSUME_NONNULL_BEGIN
@class CWVCreditCard;
// Interface for responding to expiration date fix requests. This can happen
// when the user attempts to save a card with an expired expiration. Depending
// on the user's decision, either call |acceptWithMonth:year:| or |cancel|.
CWV_EXPORT
@interface CWVCreditCardExpirationFixer : NSObject
// The credit card whose expiration date needs fixing.
@property(nonatomic, readonly) CWVCreditCard* card;
// Title text to display in the header.
@property(nonatomic, readonly, copy) NSString* titleText;
// Label for the save button.
@property(nonatomic, readonly, copy) NSString* saveButtonLabel;
// Obfuscated label describing the |card|.
@property(nonatomic, readonly, copy) NSString* cardLabel;
// Label for the cancel button.
@property(nonatomic, readonly, copy) NSString* cancelButtonLabel;
// Label for the input control.
@property(nonatomic, readonly, copy) NSString* inputLabel;
// Separator to be used between the month and year.
@property(nonatomic, readonly, copy) NSString* dateSeparator;
// Error message describing why the date is invalid.
@property(nonatomic, readonly, copy) NSString* invalidDateErrorMessage;
- (instancetype)init NS_UNAVAILABLE;
// Accepts |month| and |year| as the new expiration.
// The expected format for month and year is MM and YYYY, respectively.
// Returns BOOL indicating whether or not the |month| and |year| are valid.
// May be called multiple times until the user provides a valid date.
- (BOOL)acceptWithMonth:(NSString*)month year:(NSString*)year;
// Cancels the expiration fix request. The card will not be saved.
// Do not call |acceptWithMonth:year:| after this.
- (void)cancel;
@end
NS_ASSUME_NONNULL_END
#endif // IOS_WEB_VIEW_PUBLIC_CWV_CREDIT_CARD_EXPIRATION_FIXER_H_
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