Commit 03f43b39 authored by jdonnelly's avatar jdonnelly Committed by Commit bot

Add support for method selection in the Payment Request UI on iOS.

This includes:
- Moving the mapping between autofill credit card types and types
  defined in the spec to components/autofill.
- Adding the basic credit card response type from the spec.

BUG=602666

Committed: https://crrev.com/c3d5660f6d497ea5dffc885f198cefdc7aabad83
Review-Url: https://codereview.chromium.org/2285523002
Cr-Original-Commit-Position: refs/heads/master@{#415351}
Cr-Commit-Position: refs/heads/master@{#416329}
parent bca67f4b
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "components/autofill/content/browser/content_autofill_driver.h" #include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/country_names.h" #include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/field_types.h"
...@@ -131,41 +132,11 @@ void PopulateNativeProfileFromJava( ...@@ -131,41 +132,11 @@ void PopulateNativeProfileFromJava(
Java_AutofillProfile_getLanguageCode(env, jprofile))); Java_AutofillProfile_getLanguageCode(env, jprofile)));
} }
// Mapping from Chrome card types to PaymentRequest basic card payment spec and
// icons. Note that "generic" is not in the spec.
// https://w3c.github.io/webpayments-methods-card/#method-id
const struct PaymentRequestData {
const char* card_type;
const char* basic_card_payment_type;
const int icon_resource_id;
} kPaymentRequestData[] {
{"genericCC", "generic", IDR_AUTOFILL_PR_GENERIC},
{"americanExpressCC", "amex", IDR_AUTOFILL_PR_AMEX},
{"dinersCC", "diners", IDR_AUTOFILL_PR_DINERS},
{"discoverCC", "discover", IDR_AUTOFILL_PR_DISCOVER},
{"jcbCC", "jcb", IDR_AUTOFILL_PR_JCB},
{"masterCardCC", "mastercard", IDR_AUTOFILL_PR_MASTERCARD},
{"unionPayCC", "unionpay", IDR_AUTOFILL_PR_UNIONPAY},
{"visaCC", "visa", IDR_AUTOFILL_PR_VISA},
};
// Converts the card type into PaymentRequest type according to the basic card
// payment spec and an icon. Will set the type and the icon to "generic" for
// unrecognized card type.
const PaymentRequestData& GetPaymentRequestData(const std::string& type) {
for (size_t i = 0; i < arraysize(kPaymentRequestData); ++i) {
if (type == kPaymentRequestData[i].card_type)
return kPaymentRequestData[i];
}
return kPaymentRequestData[0];
}
ScopedJavaLocalRef<jobject> CreateJavaCreditCardFromNative( ScopedJavaLocalRef<jobject> CreateJavaCreditCardFromNative(
JNIEnv* env, JNIEnv* env,
const CreditCard& card) { const CreditCard& card) {
const PaymentRequestData& payment_request_data = const data_util::PaymentRequestData& payment_request_data =
GetPaymentRequestData(card.type()); data_util::GetPaymentRequestData(card.type());
return Java_CreditCard_create( return Java_CreditCard_create(
env, ConvertUTF8ToJavaString(env, card.guid()), env, ConvertUTF8ToJavaString(env, card.guid()),
ConvertUTF8ToJavaString(env, card.origin()), ConvertUTF8ToJavaString(env, card.origin()),
...@@ -184,16 +155,6 @@ ScopedJavaLocalRef<jobject> CreateJavaCreditCardFromNative( ...@@ -184,16 +155,6 @@ ScopedJavaLocalRef<jobject> CreateJavaCreditCardFromNative(
ConvertUTF8ToJavaString(env, card.server_id())); ConvertUTF8ToJavaString(env, card.server_id()));
} }
const char* GetCardTypeForBasicCardPaymentType(
const std::string& basic_card_payment_type) {
for (size_t i = 0; i < arraysize(kPaymentRequestData); ++i) {
if (basic_card_payment_type ==
kPaymentRequestData[i].basic_card_payment_type)
return kPaymentRequestData[i].card_type;
}
return kPaymentRequestData[0].card_type;
}
void PopulateNativeCreditCardFromJava( void PopulateNativeCreditCardFromJava(
const jobject& jcard, const jobject& jcard,
JNIEnv* env, JNIEnv* env,
...@@ -225,9 +186,8 @@ void PopulateNativeCreditCardFromJava( ...@@ -225,9 +186,8 @@ void PopulateNativeCreditCardFromJava(
} else { } else {
card->set_record_type(CreditCard::MASKED_SERVER_CARD); card->set_record_type(CreditCard::MASKED_SERVER_CARD);
card->SetTypeForMaskedCard( card->SetTypeForMaskedCard(
GetCardTypeForBasicCardPaymentType( data_util::GetCardTypeForBasicCardPaymentType(ConvertJavaStringToUTF8(
ConvertJavaStringToUTF8( env, Java_CreditCard_getBasicCardPaymentType(env, jcard))));
env, Java_CreditCard_getBasicCardPaymentType(env, jcard))));
} }
} }
} }
...@@ -489,11 +449,11 @@ PersonalDataManagerAndroid::GetBasicCardPaymentTypeIfValid( ...@@ -489,11 +449,11 @@ PersonalDataManagerAndroid::GetBasicCardPaymentTypeIfValid(
const JavaParamRef<jstring>& jcard_number) { const JavaParamRef<jstring>& jcard_number) {
base::string16 card_number = ConvertJavaStringToUTF16(env, jcard_number); base::string16 card_number = ConvertJavaStringToUTF16(env, jcard_number);
return ConvertUTF8ToJavaString( return ConvertUTF8ToJavaString(
env, env, IsValidCreditCardNumber(card_number)
IsValidCreditCardNumber(card_number) ? data_util::GetPaymentRequestData(
? GetPaymentRequestData(CreditCard::GetCreditCardType(card_number)) CreditCard::GetCreditCardType(card_number))
.basic_card_payment_type .basic_card_payment_type
: ""); : "");
} }
void PersonalDataManagerAndroid::AddServerCreditCardForTest( void PersonalDataManagerAndroid::AddServerCreditCardForTest(
......
...@@ -18,6 +18,21 @@ namespace autofill { ...@@ -18,6 +18,21 @@ namespace autofill {
namespace data_util { namespace data_util {
namespace { namespace {
// Mappings from Chrome card types to Payment Request API basic card payment
// spec types and icons. Note that "generic" is not in the spec.
// https://w3c.github.io/webpayments-methods-card/#method-id
const PaymentRequestData kPaymentRequestData[]{
{"americanExpressCC", "amex", IDR_AUTOFILL_PR_AMEX},
{"dinersCC", "diners", IDR_AUTOFILL_PR_DINERS},
{"discoverCC", "discover", IDR_AUTOFILL_PR_DISCOVER},
{"jcbCC", "jcb", IDR_AUTOFILL_PR_JCB},
{"masterCardCC", "mastercard", IDR_AUTOFILL_PR_MASTERCARD},
{"unionPayCC", "unionpay", IDR_AUTOFILL_PR_UNIONPAY},
{"visaCC", "visa", IDR_AUTOFILL_PR_VISA},
};
const PaymentRequestData kGenericPaymentRequestData = {"genericCC", "generic",
IDR_AUTOFILL_PR_GENERIC};
const char* const name_prefixes[] = { const char* const name_prefixes[] = {
"1lt", "1st", "2lt", "2nd", "3rd", "admiral", "capt", "1lt", "1st", "2lt", "2nd", "3rd", "admiral", "capt",
"captain", "col", "cpt", "dr", "gen", "general", "lcdr", "captain", "col", "cpt", "dr", "gen", "general", "lcdr",
...@@ -383,5 +398,24 @@ bool ProfileMatchesFullName(const base::string16 full_name, ...@@ -383,5 +398,24 @@ bool ProfileMatchesFullName(const base::string16 full_name,
return false; return false;
} }
const PaymentRequestData& GetPaymentRequestData(const std::string& type) {
for (size_t i = 0; i < arraysize(kPaymentRequestData); ++i) {
if (type == kPaymentRequestData[i].card_type)
return kPaymentRequestData[i];
}
return kGenericPaymentRequestData;
}
const char* GetCardTypeForBasicCardPaymentType(
const std::string& basic_card_payment_type) {
for (size_t i = 0; i < arraysize(kPaymentRequestData); ++i) {
if (basic_card_payment_type ==
kPaymentRequestData[i].basic_card_payment_type) {
return kPaymentRequestData[i].card_type;
}
}
return kGenericPaymentRequestData.card_type;
}
} // namespace data_util } // namespace data_util
} // namespace autofill } // namespace autofill
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_profile.h"
#include "grit/components_scaled_resources.h"
namespace autofill { namespace autofill {
namespace data_util { namespace data_util {
...@@ -17,6 +18,14 @@ struct NameParts { ...@@ -17,6 +18,14 @@ struct NameParts {
base::string16 family; base::string16 family;
}; };
// Used to map Chrome card types to Payment Request API basic card payment spec
// types and icons. https://w3c.github.io/webpayments-methods-card/#method-id
struct PaymentRequestData {
const char* card_type;
const char* basic_card_payment_type;
const int icon_resource_id;
};
// Returns true if |name| looks like a CJK name (or some kind of mish-mash of // Returns true if |name| looks like a CJK name (or some kind of mish-mash of
// the three, at least). // the three, at least).
bool IsCJKName(const base::string16& name); bool IsCJKName(const base::string16& name);
...@@ -38,6 +47,15 @@ base::string16 JoinNameParts(const base::string16& given, ...@@ -38,6 +47,15 @@ base::string16 JoinNameParts(const base::string16& given,
bool ProfileMatchesFullName(const base::string16 full_name, bool ProfileMatchesFullName(const base::string16 full_name,
const autofill::AutofillProfile& profile); const autofill::AutofillProfile& profile);
// Returns the Payment Request API basic card payment spec data for the provided
// autofill credit card |type|. Will set the type and the icon to "generic" for
// any unrecognized type.
const PaymentRequestData& GetPaymentRequestData(const std::string& type);
// Returns the autofill credit card type string for the provided Payment Request
// API basic card payment spec |type|.
const char* GetCardTypeForBasicCardPaymentType(const std::string& type);
} // namespace data_util } // namespace data_util
} // namespace autofill } // namespace autofill
......
...@@ -6,25 +6,28 @@ ...@@ -6,25 +6,28 @@
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_MASTERCARD" file="autofill/mastercard.png" /> <structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_MASTERCARD" file="autofill/mastercard.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_VISA" file="autofill/visa.png" /> <structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_VISA" file="autofill/visa.png" />
<!-- These are not used on desktop, only Android, so use a placeholder file.
TODO(rouslan): Remove non-keyboard-accessory icon when keyboard
accessory becomes default on Android. -->
<if expr="is_android"> <if expr="is_android">
<!-- These are not used on desktop, only Android, so use a placeholder file.
TODO(rouslan): Remove non-keyboard-accessory icon when keyboard
accessory becomes default on Android. -->
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_SCAN_NEW" file="autofill/cc-generic.png" /> <structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_SCAN_NEW" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_SCAN_NEW_KEYBOARD_ACCESSORY" file="autofill/cc-generic.png" /> <structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_SCAN_NEW_KEYBOARD_ACCESSORY" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_SETTINGS" file="autofill/cc-generic.png" /> <structure type="chrome_scaled_image" name="IDR_AUTOFILL_SETTINGS" file="autofill/cc-generic.png" />
<!-- PaymentRequest image variants -->
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_AMEX" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_DINERS" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_DISCOVER" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_GENERIC" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_JCB" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_MASTERCARD" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_UNIONPAY" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_VISA" file="autofill/cc-generic.png" />
</if> </if>
<!-- PaymentRequest image variants.
TODO(crbug.com/602666): Move the credit card icons into
components/resources and refer to them here instead of the placeholder
files so they can be used on platforms other than Android. -->
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_AMEX" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_DINERS" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_DISCOVER" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_GENERIC" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_JCB" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_MASTERCARD" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_UNIONPAY" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_VISA" file="autofill/cc-generic.png" />
<structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT" file="autofill/credit_card_cvc_hint.png" /> <structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT" file="autofill/credit_card_cvc_hint.png" />
<structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT_AMEX" file="autofill/credit_card_cvc_hint_amex.png" /> <structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT_AMEX" file="autofill/credit_card_cvc_hint_amex.png" />
<structure type="chrome_scaled_image" name="IDR_INFOBAR_AUTOFILL_CC" file="autofill/infobar_autofill_cc.png" /> <structure type="chrome_scaled_image" name="IDR_INFOBAR_AUTOFILL_CC" file="autofill/infobar_autofill_cc.png" />
......
...@@ -11,6 +11,18 @@ namespace { ...@@ -11,6 +11,18 @@ namespace {
// All of these are defined here (even though most are only used once each) so // All of these are defined here (even though most are only used once each) so
// the format details are easy to locate and update or compare to the spec doc. // the format details are easy to locate and update or compare to the spec doc.
// (https://w3c.github.io/browser-payment-api/). // (https://w3c.github.io/browser-payment-api/).
static const char kAddressCountry[] = "country";
static const char kAddressAddressLine[] = "addressLine";
static const char kAddressRegion[] = "region";
static const char kAddressCity[] = "city";
static const char kAddressDependentLocality[] = "dependentLocality";
static const char kAddressPostalCode[] = "postalCode";
static const char kAddressSortingCode[] = "sortingCode";
static const char kAddressLanguageCode[] = "languageCode";
static const char kAddressOrganization[] = "organization";
static const char kAddressRecipient[] = "recipient";
static const char kAddressCareOf[] = "careOf";
static const char kAddressPhone[] = "phone";
static const char kMethodData[] = "methodData"; static const char kMethodData[] = "methodData";
static const char kSupportedMethods[] = "supportedMethods"; static const char kSupportedMethods[] = "supportedMethods";
static const char kData[] = "data"; static const char kData[] = "data";
...@@ -20,6 +32,12 @@ static const char kPaymentDetailsTotalAmount[] = "amount"; ...@@ -20,6 +32,12 @@ static const char kPaymentDetailsTotalAmount[] = "amount";
static const char kPaymentDetailsTotalAmountCurrency[] = "currency"; static const char kPaymentDetailsTotalAmountCurrency[] = "currency";
static const char kPaymentDetailsTotalAmountValue[] = "value"; static const char kPaymentDetailsTotalAmountValue[] = "value";
static const char kMethodName[] = "methodName"; static const char kMethodName[] = "methodName";
static const char kCardCardholderName[] = "cardholderName";
static const char kCardCardNumber[] = "cardNumber";
static const char kCardExpiryMonth[] = "expiryMonth";
static const char kCardExpiryYear[] = "expiryYear";
static const char kCardCardSecurityCode[] = "cardSecurityCode";
static const char kCardBillingAddress[] = "billingAddress";
} // namespace } // namespace
...@@ -46,6 +64,45 @@ bool PaymentAddress::operator!=(const PaymentAddress& other) const { ...@@ -46,6 +64,45 @@ bool PaymentAddress::operator!=(const PaymentAddress& other) const {
return !(*this == other); return !(*this == other);
} }
std::unique_ptr<base::DictionaryValue> PaymentAddress::ToDictionaryValue()
const {
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
if (!this->country.empty())
result->SetString(kAddressCountry, this->country);
if (!this->address_line.empty()) {
std::unique_ptr<base::ListValue> address_line(new base::ListValue);
for (base::string16 address_line_string : this->address_line) {
address_line->AppendString(address_line_string);
}
result->Set(kAddressAddressLine, std::move(address_line));
}
if (!this->region.empty())
result->SetString(kAddressRegion, this->region);
if (!this->city.empty())
result->SetString(kAddressCity, this->city);
if (!this->dependent_locality.empty())
result->SetString(kAddressDependentLocality, this->dependent_locality);
if (!this->postal_code.empty())
result->SetString(kAddressPostalCode, this->postal_code);
if (!this->sorting_code.empty())
result->SetString(kAddressSortingCode, this->sorting_code);
if (!this->language_code.empty())
result->SetString(kAddressLanguageCode, this->language_code);
if (!this->organization.empty())
result->SetString(kAddressOrganization, this->organization);
if (!this->recipient.empty())
result->SetString(kAddressRecipient, this->recipient);
if (!this->care_of.empty())
result->SetString(kAddressCareOf, this->care_of);
if (!this->phone.empty())
result->SetString(kAddressPhone, this->phone);
return result;
}
PaymentMethodData::PaymentMethodData() {} PaymentMethodData::PaymentMethodData() {}
PaymentMethodData::PaymentMethodData(const PaymentMethodData& other) = default; PaymentMethodData::PaymentMethodData(const PaymentMethodData& other) = default;
PaymentMethodData::~PaymentMethodData() = default; PaymentMethodData::~PaymentMethodData() = default;
...@@ -217,7 +274,44 @@ bool PaymentRequest::FromDictionaryValue(const base::DictionaryValue& value) { ...@@ -217,7 +274,44 @@ bool PaymentRequest::FromDictionaryValue(const base::DictionaryValue& value) {
return true; return true;
} }
BasicCardResponse::BasicCardResponse() {}
BasicCardResponse::BasicCardResponse(const BasicCardResponse& other) = default;
BasicCardResponse::~BasicCardResponse() = default;
bool BasicCardResponse::operator==(const BasicCardResponse& other) const {
return this->cardholder_name == other.cardholder_name &&
this->card_number == other.card_number &&
this->expiry_month == other.expiry_month &&
this->expiry_year == other.expiry_year &&
this->card_security_code == other.card_security_code &&
this->billing_address == other.billing_address;
}
bool BasicCardResponse::operator!=(const BasicCardResponse& other) const {
return !(*this == other);
}
std::unique_ptr<base::DictionaryValue> BasicCardResponse::ToDictionaryValue()
const {
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
if (!this->cardholder_name.empty())
result->SetString(kCardCardholderName, this->cardholder_name);
if (!this->card_number.empty())
result->SetString(kCardCardNumber, this->card_number);
if (!this->expiry_month.empty())
result->SetString(kCardExpiryMonth, this->expiry_month);
if (!this->expiry_year.empty())
result->SetString(kCardExpiryYear, this->expiry_year);
if (!this->card_security_code.empty())
result->SetString(kCardCardSecurityCode, this->card_security_code);
result->Set(kCardBillingAddress, this->billing_address.ToDictionaryValue());
return result;
}
PaymentResponse::PaymentResponse() {} PaymentResponse::PaymentResponse() {}
PaymentResponse::PaymentResponse(const PaymentResponse& other) = default;
PaymentResponse::~PaymentResponse() = default; PaymentResponse::~PaymentResponse() = default;
bool PaymentResponse::operator==(const PaymentResponse& other) const { bool PaymentResponse::operator==(const PaymentResponse& other) const {
...@@ -229,12 +323,19 @@ bool PaymentResponse::operator!=(const PaymentResponse& other) const { ...@@ -229,12 +323,19 @@ bool PaymentResponse::operator!=(const PaymentResponse& other) const {
return !(*this == other); return !(*this == other);
} }
void PaymentResponse::ToDictionaryValue(base::DictionaryValue* value) const { std::unique_ptr<base::DictionaryValue> PaymentResponse::ToDictionaryValue()
DCHECK(value); const {
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
if (!this->method_name.empty()) if (!this->method_name.empty())
value->SetString(kMethodName, this->method_name); result->SetString(kMethodName, this->method_name);
if (!this->details.empty()) result->Set(kPaymentDetails, this->details.ToDictionaryValue());
value->SetString(kPaymentDetails, this->details);
return result;
}
void PaymentResponse::ToDictionaryValue(base::DictionaryValue* value) const {
value->MergeDictionary(ToDictionaryValue().get());
} }
} // namespace web } // namespace web
...@@ -104,29 +104,40 @@ TEST(PaymentRequestTest, ParsingFullyPopulatedRequestDictionarySucceeds) { ...@@ -104,29 +104,40 @@ TEST(PaymentRequestTest, ParsingFullyPopulatedRequestDictionarySucceeds) {
// Tests that serializing a default PaymentResponse yields an empty dictionary. // Tests that serializing a default PaymentResponse yields an empty dictionary.
TEST(PaymentRequestTest, EmptyResponseDictionary) { TEST(PaymentRequestTest, EmptyResponseDictionary) {
base::DictionaryValue expected_value; base::DictionaryValue expected_value;
base::DictionaryValue output_value; std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue);
std::unique_ptr<base::DictionaryValue> address(new base::DictionaryValue);
details->Set("billingAddress", std::move(address));
expected_value.Set("details", std::move(details));
PaymentResponse payment_response; PaymentResponse payment_response;
payment_response.ToDictionaryValue(&output_value); EXPECT_TRUE(
EXPECT_TRUE(expected_value.Equals(&output_value)); expected_value.Equals(payment_response.ToDictionaryValue().get()));
} }
// Tests that serializing a populated PaymentResponse yields the expected // Tests that serializing a populated PaymentResponse yields the expected
// result. // result.
TEST(PaymentRequestTest, PopulatedResponseDictionary) { TEST(PaymentRequestTest, PopulatedResponseDictionary) {
base::DictionaryValue expected_value; base::DictionaryValue expected_value;
base::DictionaryValue output_value; std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue);
std::unique_ptr<base::DictionaryValue> address(new base::DictionaryValue);
details->Set("billingAddress", std::move(address));
expected_value.Set("details", std::move(details));
expected_value.SetString("methodName", "American Express"); expected_value.SetString("methodName", "American Express");
PaymentResponse payment_response; PaymentResponse payment_response;
payment_response.method_name = base::ASCIIToUTF16("American Express"); payment_response.method_name = base::ASCIIToUTF16("American Express");
payment_response.ToDictionaryValue(&output_value); EXPECT_TRUE(
EXPECT_TRUE(expected_value.Equals(&output_value)); expected_value.Equals(payment_response.ToDictionaryValue().get()));
expected_value.SetString("details", "{cardSecurityCode: '123'}"); details.reset(new base::DictionaryValue);
payment_response.details = base::ASCIIToUTF16("{cardSecurityCode: '123'}"); address.reset(new base::DictionaryValue);
payment_response.ToDictionaryValue(&output_value); address->SetString("postalCode", "90210");
EXPECT_TRUE(expected_value.Equals(&output_value)); details->Set("billingAddress", std::move(address));
expected_value.Set("details", std::move(details));
payment_response.details.billing_address.postal_code =
base::ASCIIToUTF16("90210");
EXPECT_TRUE(
expected_value.Equals(payment_response.ToDictionaryValue().get()));
} }
// Value equality tests. // Value equality tests.
...@@ -519,9 +530,66 @@ TEST(PaymentRequestTest, PaymentRequestEquality) { ...@@ -519,9 +530,66 @@ TEST(PaymentRequestTest, PaymentRequestEquality) {
EXPECT_EQ(request1, request2); EXPECT_EQ(request1, request2);
} }
// Tests that two credit card response objects are not equal if their property
// values differ or one is missing a value present in the other, and equal
// otherwise. Doesn't test all properties of child objects, relying instead on
// their respective tests.
TEST(PaymentRequestTest, BasicCardResponseEquality) {
BasicCardResponse card_response1;
BasicCardResponse card_response2;
EXPECT_EQ(card_response1, card_response2);
card_response1.cardholder_name = base::ASCIIToUTF16("Shadow Moon");
EXPECT_NE(card_response1, card_response2);
card_response2.cardholder_name = base::ASCIIToUTF16("Mad Sweeney");
EXPECT_NE(card_response1, card_response2);
card_response2.cardholder_name = base::ASCIIToUTF16("Shadow Moon");
EXPECT_EQ(card_response1, card_response2);
card_response1.card_number = base::ASCIIToUTF16("4111111111111111");
EXPECT_NE(card_response1, card_response2);
card_response2.card_number = base::ASCIIToUTF16("1111");
EXPECT_NE(card_response1, card_response2);
card_response2.card_number = base::ASCIIToUTF16("4111111111111111");
EXPECT_EQ(card_response1, card_response2);
card_response1.expiry_month = base::ASCIIToUTF16("01");
EXPECT_NE(card_response1, card_response2);
card_response2.expiry_month = base::ASCIIToUTF16("11");
EXPECT_NE(card_response1, card_response2);
card_response2.expiry_month = base::ASCIIToUTF16("01");
EXPECT_EQ(card_response1, card_response2);
card_response1.expiry_year = base::ASCIIToUTF16("27");
EXPECT_NE(card_response1, card_response2);
card_response2.expiry_year = base::ASCIIToUTF16("72");
EXPECT_NE(card_response1, card_response2);
card_response2.expiry_year = base::ASCIIToUTF16("27");
EXPECT_EQ(card_response1, card_response2);
card_response1.expiry_year = base::ASCIIToUTF16("123");
EXPECT_NE(card_response1, card_response2);
card_response2.expiry_year = base::ASCIIToUTF16("999");
EXPECT_NE(card_response1, card_response2);
card_response2.expiry_year = base::ASCIIToUTF16("123");
EXPECT_EQ(card_response1, card_response2);
PaymentAddress billing_address1;
billing_address1.postal_code = base::ASCIIToUTF16("90210");
PaymentAddress billing_address2;
billing_address2.postal_code = base::ASCIIToUTF16("01209");
card_response1.billing_address = billing_address1;
EXPECT_NE(card_response1, card_response2);
card_response2.billing_address = billing_address2;
EXPECT_NE(card_response1, card_response2);
card_response2.billing_address = billing_address1;
EXPECT_EQ(card_response1, card_response2);
}
// Tests that two payment response objects are not equal if their property // Tests that two payment response objects are not equal if their property
// values differ or one is missing a value present in the other, and equal // values differ or one is missing a value present in the other, and equal
// otherwise. // otherwise. Doesn't test all properties of child objects, relying instead on
// their respective tests.
TEST(PaymentRequestTest, PaymentResponseEquality) { TEST(PaymentRequestTest, PaymentResponseEquality) {
PaymentResponse response1; PaymentResponse response1;
PaymentResponse response2; PaymentResponse response2;
...@@ -534,11 +602,15 @@ TEST(PaymentRequestTest, PaymentResponseEquality) { ...@@ -534,11 +602,15 @@ TEST(PaymentRequestTest, PaymentResponseEquality) {
response2.method_name = base::ASCIIToUTF16("Visa"); response2.method_name = base::ASCIIToUTF16("Visa");
EXPECT_EQ(response1, response2); EXPECT_EQ(response1, response2);
response1.details = base::ASCIIToUTF16("{cardSecurityCode: '123'}"); BasicCardResponse card_response1;
card_response1.card_number = base::ASCIIToUTF16("1234");
BasicCardResponse card_response2;
card_response2.card_number = base::ASCIIToUTF16("8888");
response1.details = card_response1;
EXPECT_NE(response1, response2); EXPECT_NE(response1, response2);
response2.details = base::ASCIIToUTF16("{cardSecurityCode: '---'}"); response2.details = card_response2;
EXPECT_NE(response1, response2); EXPECT_NE(response1, response2);
response2.details = base::ASCIIToUTF16("{cardSecurityCode: '123'}"); response2.details = card_response1;
EXPECT_EQ(response1, response2); EXPECT_EQ(response1, response2);
} }
......
...@@ -5,12 +5,14 @@ ...@@ -5,12 +5,14 @@
#ifndef IOS_WEB_PUBLIC_PAYMENTS_PAYMENT_REQUEST_H_ #ifndef IOS_WEB_PUBLIC_PAYMENTS_PAYMENT_REQUEST_H_
#define IOS_WEB_PUBLIC_PAYMENTS_PAYMENT_REQUEST_H_ #define IOS_WEB_PUBLIC_PAYMENTS_PAYMENT_REQUEST_H_
#include <memory>
#include <vector> #include <vector>
#include "base/strings/string16.h" #include "base/strings/string16.h"
// C++ bindings for the PaymentRequest API. Conforms to the 18 July 2016 // C++ bindings for the PaymentRequest API. Conforms to the following specs:
// editor's draft at https://w3c.github.io/browser-payment-api/. // https://w3c.github.io/browser-payment-api/ (18 July 2016 editor's draft)
// https://w3c.github.io/webpayments-methods-card/ (31 May 2016 editor's draft)
namespace base { namespace base {
class DictionaryValue; class DictionaryValue;
...@@ -28,6 +30,9 @@ class PaymentAddress { ...@@ -28,6 +30,9 @@ class PaymentAddress {
bool operator==(const PaymentAddress& other) const; bool operator==(const PaymentAddress& other) const;
bool operator!=(const PaymentAddress& other) const; bool operator!=(const PaymentAddress& other) const;
// Populates |value| with the properties of this PaymentAddress.
std::unique_ptr<base::DictionaryValue> ToDictionaryValue() const;
// The CLDR (Common Locale Data Repository) region code. For example, US, GB, // The CLDR (Common Locale Data Repository) region code. For example, US, GB,
// CN, or JP. // CN, or JP.
base::string16 country; base::string16 country;
...@@ -261,28 +266,65 @@ class PaymentRequest { ...@@ -261,28 +266,65 @@ class PaymentRequest {
PaymentOptions options; PaymentOptions options;
}; };
// Contains the response from the PaymentRequest API when a user accepts
// payment with a Basic Payment Card payment method (which is currently the only
// method supported on iOS).
class BasicCardResponse {
public:
BasicCardResponse();
BasicCardResponse(const BasicCardResponse& other);
~BasicCardResponse();
bool operator==(const BasicCardResponse& other) const;
bool operator!=(const BasicCardResponse& other) const;
// Populates |value| with the properties of this BasicCardResponse.
std::unique_ptr<base::DictionaryValue> ToDictionaryValue() const;
// The cardholder's name as it appears on the card.
base::string16 cardholder_name;
// The primary account number (PAN) for the payment card.
base::string16 card_number;
// A two-digit string for the expiry month of the card in the range 01 to 12.
base::string16 expiry_month;
// A two-digit string for the expiry year of the card in the range 00 to 99.
base::string16 expiry_year;
// A three or four digit string for the security code of the card (sometimes
// known as the CVV, CVC, CVN, CVE or CID).
base::string16 card_security_code;
// The billing address information associated with the payment card.
PaymentAddress billing_address;
};
// Information provided in the Promise returned by a call to // Information provided in the Promise returned by a call to
// PaymentRequest.show(). // PaymentRequest.show().
class PaymentResponse { class PaymentResponse {
public: public:
PaymentResponse(); PaymentResponse();
PaymentResponse(const PaymentResponse& other);
~PaymentResponse(); ~PaymentResponse();
bool operator==(const PaymentResponse& other) const; bool operator==(const PaymentResponse& other) const;
bool operator!=(const PaymentResponse& other) const; bool operator!=(const PaymentResponse& other) const;
// Populates |value| with the properties of this PaymentResponse. // Populates |value| with the properties of this PaymentResponse.
std::unique_ptr<base::DictionaryValue> ToDictionaryValue() const;
// TODO(jdonnelly): Remove this after removing downstream use.
void ToDictionaryValue(base::DictionaryValue* value) const; void ToDictionaryValue(base::DictionaryValue* value) const;
// The payment method identifier for the payment method that the user selected // The payment method identifier for the payment method that the user selected
// to fulfil the transaction. // to fulfil the transaction.
base::string16 method_name; base::string16 method_name;
// A JSON-serialized object that provides a payment method specific message // A credit card response object used by the merchant to process the
// used by the merchant to process the transaction and determine successful // transaction and determine successful fund transfer.
// fund transfer. This data is returned by the payment app that satisfies the BasicCardResponse details;
// payment request.
base::string16 details;
}; };
} // namespace web } // namespace web
......
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