Commit be463a2a authored by Jinho Bang's avatar Jinho Bang Committed by Commit Bot

PaymentRequest: Implement PaymentResponse.retry() in renderer and mojo

This patch only includs an implementation of PaymentResponse.retry() in
renderer and mojo side. We should implement UI in browser side in follow
up CLs.

Once this patch is applied, most test cases will be passed except when
the UI is required.

Intent to implement:
  https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/wayZGnuBkrI

Test:
  //components/payments/core/payments_validators_unittest.cc
  //third_party/blink/renderer/modules/payments/payments_validators_test.cc
  https://github.com/web-platform-tests/wpt/pull/11101

Bug: 861704
Change-Id: I8a644a32ed589a2292ad021f5699105482ad9dd1
Reviewed-on: https://chromium-review.googlesource.com/1142045Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Jinho Bang <jinho.bang@samsung.com>
Cr-Commit-Position: refs/heads/master@{#580126}
parent f1e736e3
...@@ -14,6 +14,7 @@ import org.chromium.payments.mojom.PaymentMethodData; ...@@ -14,6 +14,7 @@ import org.chromium.payments.mojom.PaymentMethodData;
import org.chromium.payments.mojom.PaymentOptions; import org.chromium.payments.mojom.PaymentOptions;
import org.chromium.payments.mojom.PaymentRequest; import org.chromium.payments.mojom.PaymentRequest;
import org.chromium.payments.mojom.PaymentRequestClient; import org.chromium.payments.mojom.PaymentRequestClient;
import org.chromium.payments.mojom.PaymentValidationErrors;
import org.chromium.services.service_manager.InterfaceFactory; import org.chromium.services.service_manager.InterfaceFactory;
/** /**
...@@ -55,6 +56,9 @@ public class PaymentRequestFactory implements InterfaceFactory<PaymentRequest> { ...@@ -55,6 +56,9 @@ public class PaymentRequestFactory implements InterfaceFactory<PaymentRequest> {
@Override @Override
public void complete(int result) {} public void complete(int result) {}
@Override
public void retry(PaymentValidationErrors errors) {}
@Override @Override
public void canMakePayment() { public void canMakePayment() {
if (mClient != null) { if (mClient != null) {
......
...@@ -70,6 +70,7 @@ import org.chromium.payments.mojom.PaymentRequestClient; ...@@ -70,6 +70,7 @@ import org.chromium.payments.mojom.PaymentRequestClient;
import org.chromium.payments.mojom.PaymentResponse; import org.chromium.payments.mojom.PaymentResponse;
import org.chromium.payments.mojom.PaymentShippingOption; import org.chromium.payments.mojom.PaymentShippingOption;
import org.chromium.payments.mojom.PaymentShippingType; import org.chromium.payments.mojom.PaymentShippingType;
import org.chromium.payments.mojom.PaymentValidationErrors;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -1478,6 +1479,20 @@ public class PaymentRequestImpl ...@@ -1478,6 +1479,20 @@ public class PaymentRequestImpl
closeUIAndDestroyNativeObjects(/*immediateClose=*/PaymentComplete.FAIL != result); closeUIAndDestroyNativeObjects(/*immediateClose=*/PaymentComplete.FAIL != result);
} }
@Override
public void retry(PaymentValidationErrors errors) {
if (mClient == null) return;
if (!PaymentValidator.validatePaymentValidationErrors(errors)) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage("Invalid payment validation errors");
return;
}
// TODO(zino): Should implement this method (including updating UI part).
// Please see https://crbug.com/861704
}
@Override @Override
public void onCardAndAddressSettingsClicked() { public void onCardAndAddressSettingsClicked() {
Context context = ChromeActivity.fromWebContents(mWebContents); Context context = ChromeActivity.fromWebContents(mWebContents);
......
...@@ -11,10 +11,10 @@ static_library("android") { ...@@ -11,10 +11,10 @@ static_library("android") {
"currency_formatter_android.cc", "currency_formatter_android.cc",
"currency_formatter_android.h", "currency_formatter_android.h",
"origin_security_checker_android.cc", "origin_security_checker_android.cc",
"payment_details_validation_android.cc",
"payment_manifest_downloader_android.cc", "payment_manifest_downloader_android.cc",
"payment_manifest_parser_android.cc", "payment_manifest_parser_android.cc",
"payment_manifest_parser_android.h", "payment_manifest_parser_android.h",
"payment_validator_android.cc",
] ]
deps = [ deps = [
":jni_headers", ":jni_headers",
......
...@@ -6,6 +6,7 @@ package org.chromium.components.payments; ...@@ -6,6 +6,7 @@ package org.chromium.components.payments;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.payments.mojom.PaymentDetails; import org.chromium.payments.mojom.PaymentDetails;
import org.chromium.payments.mojom.PaymentValidationErrors;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
...@@ -21,5 +22,13 @@ public class PaymentValidator { ...@@ -21,5 +22,13 @@ public class PaymentValidator {
return nativeValidatePaymentDetailsAndroid(details.serialize()); return nativeValidatePaymentDetailsAndroid(details.serialize());
} }
public static boolean validatePaymentValidationErrors(PaymentValidationErrors errors) {
if (errors == null) {
return false;
}
return nativeValidatePaymentValidationErrorsAndroid(errors.serialize());
}
private static native boolean nativeValidatePaymentDetailsAndroid(ByteBuffer buffer); private static native boolean nativeValidatePaymentDetailsAndroid(ByteBuffer buffer);
private static native boolean nativeValidatePaymentValidationErrorsAndroid(ByteBuffer buffer);
}; };
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "components/payments/content/payment_request_converter.h" #include "components/payments/content/payment_request_converter.h"
#include "components/payments/core/payment_details.h" #include "components/payments/core/payment_details.h"
#include "components/payments/core/payment_details_validation.h" #include "components/payments/core/payment_details_validation.h"
#include "components/payments/core/payments_validators.h"
#include "jni/PaymentValidator_jni.h" #include "jni/PaymentValidator_jni.h"
#include "third_party/blink/public/platform/modules/payments/payment_request.mojom.h" #include "third_party/blink/public/platform/modules/payments/payment_request.mojom.h"
...@@ -34,4 +35,21 @@ jboolean JNI_PaymentValidator_ValidatePaymentDetailsAndroid( ...@@ -34,4 +35,21 @@ jboolean JNI_PaymentValidator_ValidatePaymentDetailsAndroid(
&unused_error_message); &unused_error_message);
} }
jboolean JNI_PaymentValidator_ValidatePaymentValidationErrorsAndroid(
JNIEnv* env,
const base::android::JavaParamRef<jclass>& jcaller,
const base::android::JavaParamRef<jobject>& buffer) {
jbyte* buf_in = static_cast<jbyte*>(env->GetDirectBufferAddress(buffer));
jlong buf_size = env->GetDirectBufferCapacity(buffer);
std::vector<uint8_t> mojo_buffer(buf_size);
memcpy(&mojo_buffer[0], buf_in, buf_size);
mojom::PaymentValidationErrorsPtr errors;
if (!mojom::PaymentValidationErrors::Deserialize(std::move(mojo_buffer),
&errors))
return false;
std::string unused_error_message;
return PaymentsValidators::IsValidPaymentValidationErrorsFormat(
std::move(errors), &unused_error_message);
}
} // namespace payments } // namespace payments
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "components/payments/core/payment_details_validation.h" #include "components/payments/core/payment_details_validation.h"
#include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_instrument.h"
#include "components/payments/core/payment_prefs.h" #include "components/payments/core/payment_prefs.h"
#include "components/payments/core/payments_validators.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "components/ukm/content/source_url_recorder.h" #include "components/ukm/content/source_url_recorder.h"
#include "components/url_formatter/elide_url.h" #include "components/url_formatter/elide_url.h"
...@@ -186,6 +187,21 @@ void PaymentRequest::Show(bool is_user_gesture) { ...@@ -186,6 +187,21 @@ void PaymentRequest::Show(bool is_user_gesture) {
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
} }
void PaymentRequest::Retry(mojom::PaymentValidationErrorsPtr errors) {
std::string error;
if (!PaymentsValidators::IsValidPaymentValidationErrorsFormat(errors,
&error)) {
DLOG(ERROR) << error;
client_->OnError(mojom::PaymentErrorReason::USER_CANCEL);
OnConnectionTerminated();
return;
}
// TODO(zino): Should implement this method (including updating UI part).
// Please see https://crbug.com/861704
NOTIMPLEMENTED();
}
void PaymentRequest::AreRequestedMethodsSupportedCallback( void PaymentRequest::AreRequestedMethodsSupportedCallback(
bool methods_supported) { bool methods_supported) {
if (methods_supported) { if (methods_supported) {
......
...@@ -66,6 +66,7 @@ class PaymentRequest : public mojom::PaymentRequest, ...@@ -66,6 +66,7 @@ class PaymentRequest : public mojom::PaymentRequest,
mojom::PaymentDetailsPtr details, mojom::PaymentDetailsPtr details,
mojom::PaymentOptionsPtr options) override; mojom::PaymentOptionsPtr options) override;
void Show(bool is_user_gesture) override; void Show(bool is_user_gesture) override;
void Retry(mojom::PaymentValidationErrorsPtr errors) override;
void UpdateWith(mojom::PaymentDetailsPtr details) override; void UpdateWith(mojom::PaymentDetailsPtr details) override;
void NoUpdatedPaymentDetails() override; void NoUpdatedPaymentDetails() override;
void Abort() override; void Abort() override;
......
...@@ -113,4 +113,41 @@ bool PaymentsValidators::IsValidErrorMsgFormat( ...@@ -113,4 +113,41 @@ bool PaymentsValidators::IsValidErrorMsgFormat(
return false; return false;
} }
// static
bool PaymentsValidators::IsValidPaymentValidationErrorsFormat(
const mojom::PaymentValidationErrorsPtr& errors,
std::string* optional_error_message) {
if (!errors || !errors->payer || !errors->shipping_address)
return false;
return IsValidErrorMsgFormat(errors->payer->email, optional_error_message) &&
IsValidErrorMsgFormat(errors->payer->email, optional_error_message) &&
IsValidErrorMsgFormat(errors->payer->name, optional_error_message) &&
IsValidErrorMsgFormat(errors->payer->phone, optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->address_line,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->city,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->country,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->dependent_locality,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->language_code,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->organization,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->phone,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->postal_code,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->recipient,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->region,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->region_code,
optional_error_message) &&
IsValidErrorMsgFormat(errors->shipping_address->sorting_code,
optional_error_message);
}
} // namespace payments } // namespace payments
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "components/payments/mojom/payment_request_data.mojom.h"
namespace payments { namespace payments {
...@@ -44,6 +45,12 @@ class PaymentsValidators { ...@@ -44,6 +45,12 @@ class PaymentsValidators {
static bool IsValidErrorMsgFormat(const std::string& code, static bool IsValidErrorMsgFormat(const std::string& code,
std::string* optional_error_message); std::string* optional_error_message);
// Returns false and optionally populate |optional_error_message| if any
// fields of |errors| have too long string (greater than 2048).
static bool IsValidPaymentValidationErrorsFormat(
const mojom::PaymentValidationErrorsPtr& errors,
std::string* optional_error_message);
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PaymentsValidators); DISALLOW_IMPLICIT_CONSTRUCTORS(PaymentsValidators);
}; };
......
...@@ -22,11 +22,11 @@ struct CurrencyCodeTestCase { ...@@ -22,11 +22,11 @@ struct CurrencyCodeTestCase {
class PaymentsCurrencyValidatorTest class PaymentsCurrencyValidatorTest
: public testing::TestWithParam<CurrencyCodeTestCase> {}; : public testing::TestWithParam<CurrencyCodeTestCase> {};
const char* longString2048() { const char* LongString2049() {
static char long_string[2049]; static char long_string[2050];
for (int i = 0; i < 2048; i++) for (int i = 0; i < 2049; i++)
long_string[i] = 'a'; long_string[i] = 'a';
long_string[2048] = '\0'; long_string[2049] = '\0';
return long_string; return long_string;
} }
...@@ -62,7 +62,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -62,7 +62,7 @@ INSTANTIATE_TEST_CASE_P(
CurrencyCodeTestCase("usd", false), CurrencyCodeTestCase("usd", false),
CurrencyCodeTestCase("ANYSTRING", false), CurrencyCodeTestCase("ANYSTRING", false),
CurrencyCodeTestCase("", false), CurrencyCodeTestCase("", false),
CurrencyCodeTestCase(longString2048(), false))); CurrencyCodeTestCase(LongString2049(), false)));
struct TestCase { struct TestCase {
TestCase(const char* input, bool expected_valid) TestCase(const char* input, bool expected_valid)
...@@ -251,5 +251,153 @@ INSTANTIATE_TEST_CASE_P( ...@@ -251,5 +251,153 @@ INSTANTIATE_TEST_CASE_P(
LanguageTagTestCase("en-Latn-US", "en", "Latn"), LanguageTagTestCase("en-Latn-US", "en", "Latn"),
LanguageTagTestCase("en-US", "en", ""))); LanguageTagTestCase("en-US", "en", "")));
struct ValidationErrorsTestCase {
explicit ValidationErrorsTestCase(bool expected_valid)
: expected_valid(expected_valid) {}
const char* m_payer_email = "";
const char* m_payer_name = "";
const char* m_payer_phone = "";
const char* m_shipping_address_address_line = "";
const char* m_shipping_address_city = "";
const char* m_shipping_address_country = "";
const char* m_shipping_address_dependent_locality = "";
const char* m_shipping_address_language_code = "";
const char* m_shipping_address_organization = "";
const char* m_shipping_address_phone = "";
const char* m_shipping_address_postal_code = "";
const char* m_shipping_address_recipient = "";
const char* m_shipping_address_region = "";
const char* m_shipping_address_region_code = "";
const char* m_shipping_address_sorting_code = "";
bool expected_valid;
};
#define VALIDATION_ERRORS_TEST_CASE(field, value, expected_valid) \
([]() { \
ValidationErrorsTestCase test_case(expected_valid); \
test_case.m_##field = value; \
return test_case; \
})()
mojom::PaymentValidationErrorsPtr toPaymentValidationErrors(
ValidationErrorsTestCase test_case) {
mojom::PaymentValidationErrorsPtr errors =
mojom::PaymentValidationErrors::New();
mojom::PayerErrorFieldsPtr payer = mojom::PayerErrorFields::New();
payer->email = test_case.m_payer_email;
payer->name = test_case.m_payer_name;
payer->phone = test_case.m_payer_phone;
mojom::AddressErrorsPtr shipping_address = mojom::AddressErrors::New();
shipping_address->address_line = test_case.m_shipping_address_address_line;
shipping_address->city = test_case.m_shipping_address_city;
shipping_address->country = test_case.m_shipping_address_country;
shipping_address->dependent_locality =
test_case.m_shipping_address_dependent_locality;
shipping_address->language_code = test_case.m_shipping_address_language_code;
shipping_address->organization = test_case.m_shipping_address_organization;
shipping_address->phone = test_case.m_shipping_address_phone;
shipping_address->postal_code = test_case.m_shipping_address_postal_code;
shipping_address->recipient = test_case.m_shipping_address_recipient;
shipping_address->region = test_case.m_shipping_address_region;
shipping_address->region_code = test_case.m_shipping_address_region_code;
shipping_address->sorting_code = test_case.m_shipping_address_sorting_code;
errors->payer = std::move(payer);
errors->shipping_address = std::move(shipping_address);
return errors;
}
class PaymentsErrorMessageValidatorTest
: public testing::TestWithParam<ValidationErrorsTestCase> {};
TEST_P(PaymentsErrorMessageValidatorTest,
IsValidPaymentValidationErrorsFormat) {
mojom::PaymentValidationErrorsPtr errors =
toPaymentValidationErrors(GetParam());
std::string error_message;
EXPECT_EQ(GetParam().expected_valid,
PaymentsValidators::IsValidPaymentValidationErrorsFormat(
errors, &error_message))
<< error_message;
}
INSTANTIATE_TEST_CASE_P(
PaymentValidationErrorss,
PaymentsErrorMessageValidatorTest,
testing::Values(
VALIDATION_ERRORS_TEST_CASE(payer_email, "test", true),
VALIDATION_ERRORS_TEST_CASE(payer_name, "test", true),
VALIDATION_ERRORS_TEST_CASE(payer_phone, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_address_line,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_country, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_dependent_locality,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_language_code,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_organization,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_phone, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_postal_code, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_recipient, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region_code, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_sorting_code,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(payer_email, LongString2049(), false),
VALIDATION_ERRORS_TEST_CASE(payer_name, LongString2049(), false),
VALIDATION_ERRORS_TEST_CASE(payer_phone, LongString2049(), false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_address_line,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_country,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_dependent_locality,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_language_code,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_organization,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_phone,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_postal_code,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_recipient,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region_code,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_sorting_code,
LongString2049(),
false)));
} // namespace } // namespace
} // namespace payments } // namespace payments
...@@ -44,3 +44,36 @@ struct PaymentCurrencyAmount { ...@@ -44,3 +44,36 @@ struct PaymentCurrencyAmount {
// digits. Separated by a dot. // digits. Separated by a dot.
string value; string value;
}; };
// The |PaymentValidationErrors| data structure that the renderer provides to
// the browser process when calling retry() method in JavaScript. It contains
// merchant-defined error message strings.
struct PaymentValidationErrors {
PayerErrorFields payer;
AddressErrors shipping_address;
};
// The |PayerErrorFields| is used to represent validation errors with one or
// more payer details.
struct PayerErrorFields {
string email;
string name;
string phone;
};
// The |AddressErrors| is used to represent validation errors with specific
// parts of a physical address.
struct AddressErrors {
string address_line;
string city;
string country;
string dependent_locality;
string language_code;
string organization;
string phone;
string postal_code;
string recipient;
string region;
string region_code;
string sorting_code;
};
...@@ -205,6 +205,12 @@ interface PaymentRequest { ...@@ -205,6 +205,12 @@ interface PaymentRequest {
// Closes the payment user interface. // Closes the payment user interface.
Complete(PaymentComplete result); Complete(PaymentComplete result);
// Called when the merchant calls explicitly retry() method in JavaScript.
// The |errors| contains merchant-defined error message strings. They are
// used to indicate to the end-user that something is wrong with the data of
// the payment response.
Retry(PaymentValidationErrors errors);
// Queries whether the user has a form of payment on file. // Queries whether the user has a form of payment on file.
CanMakePayment(); CanMakePayment();
}; };
...@@ -33,6 +33,7 @@ class ExceptionState; ...@@ -33,6 +33,7 @@ class ExceptionState;
class ExecutionContext; class ExecutionContext;
class PaymentAddress; class PaymentAddress;
class PaymentDetailsInit; class PaymentDetailsInit;
class PaymentResponse;
class ScriptPromiseResolver; class ScriptPromiseResolver;
class ScriptState; class ScriptState;
...@@ -128,14 +129,22 @@ class MODULES_EXPORT PaymentRequest final ...@@ -128,14 +129,22 @@ class MODULES_EXPORT PaymentRequest final
// Clears the promise resolvers and closes the Mojo connection. // Clears the promise resolvers and closes the Mojo connection.
void ClearResolversAndCloseMojoConnection(); void ClearResolversAndCloseMojoConnection();
// Returns the resolver for the current pending accept promise that should
// be resolved if the user accepts or aborts the payment request.
// The pending promise can be [[acceptPromise]] or [[retryPromise]] in the
// spec.
ScriptPromiseResolver* GetPendingAcceptPromiseResolver();
PaymentOptions options_; PaymentOptions options_;
Member<PaymentAddress> shipping_address_; Member<PaymentAddress> shipping_address_;
Member<PaymentResponse> payment_response_;
String id_; String id_;
String shipping_option_; String shipping_option_;
String shipping_type_; String shipping_type_;
HashSet<String> method_names_; HashSet<String> method_names_;
Member<ScriptPromiseResolver> show_resolver_; Member<ScriptPromiseResolver> show_resolver_;
Member<ScriptPromiseResolver> complete_resolver_; Member<ScriptPromiseResolver> complete_resolver_;
Member<ScriptPromiseResolver> retry_resolver_;
Member<ScriptPromiseResolver> abort_resolver_; Member<ScriptPromiseResolver> abort_resolver_;
Member<ScriptPromiseResolver> can_make_payment_resolver_; Member<ScriptPromiseResolver> can_make_payment_resolver_;
payments::mojom::blink::PaymentRequestPtr payment_provider_; payments::mojom::blink::PaymentRequestPtr payment_provider_;
......
...@@ -33,6 +33,19 @@ PaymentResponse::PaymentResponse( ...@@ -33,6 +33,19 @@ PaymentResponse::PaymentResponse(
PaymentResponse::~PaymentResponse() = default; PaymentResponse::~PaymentResponse() = default;
void PaymentResponse::Update(
payments::mojom::blink::PaymentResponsePtr response,
PaymentAddress* shipping_address) {
DCHECK(response);
method_name_ = response->method_name;
stringified_details_ = response->stringified_details;
shipping_address_ = shipping_address;
shipping_option_ = response->shipping_option;
payer_name_ = response->payer_name;
payer_email_ = response->payer_email;
payer_phone_ = response->payer_phone;
}
ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const { ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const {
V8ObjectBuilder result(script_state); V8ObjectBuilder result(script_state);
result.AddString("requestId", requestId()); result.AddString("requestId", requestId());
......
...@@ -34,6 +34,8 @@ class MODULES_EXPORT PaymentResponse final : public ScriptWrappable { ...@@ -34,6 +34,8 @@ class MODULES_EXPORT PaymentResponse final : public ScriptWrappable {
const String& requestId); const String& requestId);
~PaymentResponse() override; ~PaymentResponse() override;
void Update(payments::mojom::blink::PaymentResponsePtr, PaymentAddress*);
ScriptValue toJSONForBinding(ScriptState*) const; ScriptValue toJSONForBinding(ScriptState*) const;
const String& requestId() const { return requestId_; } const String& requestId() const { return requestId_; }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/payments/payments_validators.h" #include "third_party/blink/renderer/modules/payments/payments_validators.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h" #include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
#include "third_party/blink/renderer/modules/payments/payment_validation_errors.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h" #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
...@@ -124,4 +125,66 @@ bool PaymentsValidators::IsValidErrorMsgFormat(const String& error, ...@@ -124,4 +125,66 @@ bool PaymentsValidators::IsValidErrorMsgFormat(const String& error,
return false; return false;
} }
// static
bool PaymentsValidators::IsValidPaymentValidationErrorsFormat(
const PaymentValidationErrors& errors,
String* optional_error_message) {
if (errors.hasPayer()) {
if ((errors.payer().hasEmail() &&
!IsValidErrorMsgFormat(errors.payer().email(),
optional_error_message)) ||
(errors.payer().hasName() &&
!IsValidErrorMsgFormat(errors.payer().name(),
optional_error_message)) ||
(errors.payer().hasPhone() &&
!IsValidErrorMsgFormat(errors.payer().phone(),
optional_error_message))) {
return false;
}
}
if (errors.hasShippingAddress()) {
if ((errors.shippingAddress().hasAddressLine() &&
!IsValidErrorMsgFormat(errors.shippingAddress().addressLine(),
optional_error_message)) ||
(errors.shippingAddress().hasCity() &&
!IsValidErrorMsgFormat(errors.shippingAddress().city(),
optional_error_message)) ||
(errors.shippingAddress().hasCountry() &&
!IsValidErrorMsgFormat(errors.shippingAddress().country(),
optional_error_message)) ||
(errors.shippingAddress().hasDependentLocality() &&
!IsValidErrorMsgFormat(errors.shippingAddress().dependentLocality(),
optional_error_message)) ||
(errors.shippingAddress().hasLanguageCode() &&
!IsValidErrorMsgFormat(errors.shippingAddress().languageCode(),
optional_error_message)) ||
(errors.shippingAddress().hasOrganization() &&
!IsValidErrorMsgFormat(errors.shippingAddress().organization(),
optional_error_message)) ||
(errors.shippingAddress().hasPhone() &&
!IsValidErrorMsgFormat(errors.shippingAddress().phone(),
optional_error_message)) ||
(errors.shippingAddress().hasPostalCode() &&
!IsValidErrorMsgFormat(errors.shippingAddress().postalCode(),
optional_error_message)) ||
(errors.shippingAddress().hasRecipient() &&
!IsValidErrorMsgFormat(errors.shippingAddress().recipient(),
optional_error_message)) ||
(errors.shippingAddress().hasRegion() &&
!IsValidErrorMsgFormat(errors.shippingAddress().region(),
optional_error_message)) ||
(errors.shippingAddress().hasRegionCode() &&
!IsValidErrorMsgFormat(errors.shippingAddress().regionCode(),
optional_error_message)) ||
(errors.shippingAddress().hasSortingCode() &&
!IsValidErrorMsgFormat(errors.shippingAddress().sortingCode(),
optional_error_message))) {
return false;
}
}
return true;
}
} // namespace blink } // namespace blink
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
namespace blink { namespace blink {
class PaymentValidationErrors;
class MODULES_EXPORT PaymentsValidators final { class MODULES_EXPORT PaymentsValidators final {
STATIC_ONLY(PaymentsValidators); STATIC_ONLY(PaymentsValidators);
...@@ -51,6 +53,12 @@ class MODULES_EXPORT PaymentsValidators final { ...@@ -51,6 +53,12 @@ class MODULES_EXPORT PaymentsValidators final {
// Returns false if |error| is too long (greater than 2048). // Returns false if |error| is too long (greater than 2048).
static bool IsValidErrorMsgFormat(const String& code, static bool IsValidErrorMsgFormat(const String& code,
String* optional_error_message); String* optional_error_message);
// Returns false if |payment_validation_errors| has too long string (greater
// than 2048).
static bool IsValidPaymentValidationErrorsFormat(
const PaymentValidationErrors& errors,
String* optional_error_message);
}; };
} // namespace blink } // namespace blink
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/modules/payments/payment_validation_errors.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink { namespace blink {
...@@ -23,11 +24,11 @@ struct CurrencyCodeTestCase { ...@@ -23,11 +24,11 @@ struct CurrencyCodeTestCase {
class PaymentsCurrencyValidatorTest class PaymentsCurrencyValidatorTest
: public testing::TestWithParam<CurrencyCodeTestCase> {}; : public testing::TestWithParam<CurrencyCodeTestCase> {};
const char* LongString2048() { const char* LongString2049() {
static char long_string[2049]; static char long_string[2050];
for (int i = 0; i < 2048; i++) for (int i = 0; i < 2049; i++)
long_string[i] = 'a'; long_string[i] = 'a';
long_string[2048] = '\0'; long_string[2049] = '\0';
return long_string; return long_string;
} }
...@@ -64,7 +65,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -64,7 +65,7 @@ INSTANTIATE_TEST_CASE_P(
CurrencyCodeTestCase("usd", true), CurrencyCodeTestCase("usd", true),
CurrencyCodeTestCase("ANYSTRING", false), CurrencyCodeTestCase("ANYSTRING", false),
CurrencyCodeTestCase("", false), CurrencyCodeTestCase("", false),
CurrencyCodeTestCase(LongString2048(), false))); CurrencyCodeTestCase(LongString2049(), false)));
struct TestCase { struct TestCase {
TestCase(const char* input, bool expected_valid) TestCase(const char* input, bool expected_valid)
...@@ -262,5 +263,152 @@ INSTANTIATE_TEST_CASE_P( ...@@ -262,5 +263,152 @@ INSTANTIATE_TEST_CASE_P(
ShippingAddressTestCase("US", "en", "InvalidScriptCode", false), ShippingAddressTestCase("US", "en", "InvalidScriptCode", false),
ShippingAddressTestCase("US", "", "Latn", false))); ShippingAddressTestCase("US", "", "Latn", false)));
struct ValidationErrorsTestCase {
ValidationErrorsTestCase(bool expected_valid)
: expected_valid(expected_valid) {}
const char* m_payer_email = "";
const char* m_payer_name = "";
const char* m_payer_phone = "";
const char* m_shipping_address_address_line = "";
const char* m_shipping_address_city = "";
const char* m_shipping_address_country = "";
const char* m_shipping_address_dependent_locality = "";
const char* m_shipping_address_language_code = "";
const char* m_shipping_address_organization = "";
const char* m_shipping_address_phone = "";
const char* m_shipping_address_postal_code = "";
const char* m_shipping_address_recipient = "";
const char* m_shipping_address_region = "";
const char* m_shipping_address_region_code = "";
const char* m_shipping_address_sorting_code = "";
bool expected_valid;
};
#define VALIDATION_ERRORS_TEST_CASE(field, value, expected_valid) \
([]() { \
ValidationErrorsTestCase test_case(expected_valid); \
test_case.m_##field = value; \
return test_case; \
})()
PaymentValidationErrors toPaymentValidationErrors(
ValidationErrorsTestCase test_case) {
PaymentValidationErrors errors;
PayerErrorFields payer;
payer.setEmail(test_case.m_payer_email);
payer.setName(test_case.m_payer_name);
payer.setPhone(test_case.m_payer_phone);
AddressErrors shipping_address;
shipping_address.setAddressLine(test_case.m_shipping_address_address_line);
shipping_address.setCity(test_case.m_shipping_address_city);
shipping_address.setCountry(test_case.m_shipping_address_country);
shipping_address.setDependentLocality(
test_case.m_shipping_address_dependent_locality);
shipping_address.setLanguageCode(test_case.m_shipping_address_language_code);
shipping_address.setOrganization(test_case.m_shipping_address_organization);
shipping_address.setPhone(test_case.m_shipping_address_phone);
shipping_address.setPostalCode(test_case.m_shipping_address_postal_code);
shipping_address.setRecipient(test_case.m_shipping_address_recipient);
shipping_address.setRegion(test_case.m_shipping_address_region);
shipping_address.setRegionCode(test_case.m_shipping_address_region_code);
shipping_address.setSortingCode(test_case.m_shipping_address_sorting_code);
errors.setPayer(payer);
errors.setShippingAddress(shipping_address);
return errors;
}
class PaymentsErrorMessageValidatorTest
: public testing::TestWithParam<ValidationErrorsTestCase> {};
TEST_P(PaymentsErrorMessageValidatorTest,
IsValidPaymentValidationErrorsFormat) {
PaymentValidationErrors errors = toPaymentValidationErrors(GetParam());
String error_message;
EXPECT_EQ(GetParam().expected_valid,
PaymentsValidators::IsValidPaymentValidationErrorsFormat(
errors, &error_message))
<< error_message;
}
INSTANTIATE_TEST_CASE_P(
PaymentValidationErrorss,
PaymentsErrorMessageValidatorTest,
testing::Values(
VALIDATION_ERRORS_TEST_CASE(payer_email, "test", true),
VALIDATION_ERRORS_TEST_CASE(payer_name, "test", true),
VALIDATION_ERRORS_TEST_CASE(payer_phone, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_address_line,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_country, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_dependent_locality,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_language_code,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_organization,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_phone, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_postal_code, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_recipient, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region_code, "test", true),
VALIDATION_ERRORS_TEST_CASE(shipping_address_sorting_code,
"test",
true),
VALIDATION_ERRORS_TEST_CASE(payer_email, LongString2049(), false),
VALIDATION_ERRORS_TEST_CASE(payer_name, LongString2049(), false),
VALIDATION_ERRORS_TEST_CASE(payer_phone, LongString2049(), false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_address_line,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_city,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_country,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_dependent_locality,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_language_code,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_organization,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_phone,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_postal_code,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_recipient,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_region_code,
LongString2049(),
false),
VALIDATION_ERRORS_TEST_CASE(shipping_address_sorting_code,
LongString2049(),
false)));
} // namespace } // namespace
} // namespace blink } // namespace blink
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