[Web Payments] Verbose payment app failure message.
Before this patch, if a payment app failed to launch or intentionally
cancelled an ongoing transaction, a web developer would always get
"AbortError: User closed the Payment Request UI" error message. However,
an unintentional failure in a payment handler should trigger a fallback,
whereas intentional cancellation should not.
This patch passes the reason why a payment did not succeed from the
payment app to the merchant via an error message used for rejecting
PaymentRequest.show().
After this patch, a web developer can distinguish between an internal
failure of a payment app and intentional cancellation of payment by the
user.
Bug: 977145
Change-Id: I6e5659e8c1de50f241c36680437bd47188e54205
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1674293
Reviewed-by: Chris Palmer <[email protected]>
Reviewed-by: Danyao Wang <[email protected]>
Commit-Queue: Rouslan Solomakhin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#672904}
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc
index 87fc9d1f..5ba7207 100644
--- a/components/payments/content/payment_request.cc
+++ b/components/payments/content/payment_request.cc
@@ -133,20 +133,20 @@
bool allowed_origin =
UrlUtil::IsOriginAllowedToUseWebPaymentApis(last_committed_url);
if (!allowed_origin) {
- prohibited_origin_or_invalid_ssl_error_message_ = errors::kProhibitedOrigin;
+ reject_show_error_message_ = errors::kProhibitedOrigin;
}
bool invalid_ssl = false;
if (last_committed_url.SchemeIsCryptographic()) {
- DCHECK(prohibited_origin_or_invalid_ssl_error_message_.empty());
- prohibited_origin_or_invalid_ssl_error_message_ =
+ DCHECK(reject_show_error_message_.empty());
+ reject_show_error_message_ =
delegate_->GetInvalidSslCertificateErrorMessage();
- invalid_ssl = !prohibited_origin_or_invalid_ssl_error_message_.empty();
+ invalid_ssl = !reject_show_error_message_.empty();
}
if (!allowed_origin || invalid_ssl) {
// Intentionally don't set |spec_| and |state_|, so the UI is never shown.
- log_.Error(prohibited_origin_or_invalid_ssl_error_message_);
+ log_.Error(reject_show_error_message_);
log_.Error(errors::kProhibitedOriginOrInvalidSslExplanation);
return;
}
@@ -489,8 +489,8 @@
journey_logger_.SetNotShown(
JourneyLogger::NOT_SHOWN_REASON_NO_SUPPORTED_PAYMENT_METHOD);
client_->OnError(mojom::PaymentErrorReason::NOT_SUPPORTED,
- !prohibited_origin_or_invalid_ssl_error_message_.empty()
- ? prohibited_origin_or_invalid_ssl_error_message_
+ !reject_show_error_message_.empty()
+ ? reject_show_error_message_
: GetNotSupportedErrorMessage(spec_.get()));
if (observer_for_testing_)
observer_for_testing_->OnNotSupportedError();
@@ -531,17 +531,12 @@
void PaymentRequest::OnPaymentResponseAvailable(
mojom::PaymentResponsePtr response) {
+ DCHECK(!response->method_name.empty());
+ DCHECK(!response->stringified_details.empty());
+
journey_logger_.SetEventOccurred(
JourneyLogger::EVENT_RECEIVED_INSTRUMENT_DETAILS);
- // Do not send invalid response to client.
- if (response->method_name.empty() || response->stringified_details.empty()) {
- RecordFirstAbortReason(
- JourneyLogger::ABORT_REASON_INSTRUMENT_DETAILS_ERROR);
- delegate_->ShowErrorMessage();
- return;
- }
-
// Log the correct "selected instrument" metric according to its type and
// the method name in response.
DCHECK(state_->selected_instrument());
@@ -574,6 +569,17 @@
client_->OnPaymentResponse(std::move(response));
}
+void PaymentRequest::OnPaymentResponseError(const std::string& error_message) {
+ journey_logger_.SetEventOccurred(
+ JourneyLogger::EVENT_RECEIVED_INSTRUMENT_DETAILS);
+ RecordFirstAbortReason(JourneyLogger::ABORT_REASON_INSTRUMENT_DETAILS_ERROR);
+
+ reject_show_error_message_ = error_message;
+ delegate_->ShowErrorMessage();
+ // When the user dismisses the error message, UserCancelled() will reject
+ // PaymentRequest.show() with |reject_show_error_message_|.
+}
+
void PaymentRequest::OnShippingOptionIdSelected(
std::string shipping_option_id) {
client_->OnShippingOptionChange(shipping_option_id);
@@ -607,7 +613,9 @@
// This sends an error to the renderer, which informs the API user.
client_->OnError(mojom::PaymentErrorReason::USER_CANCEL,
- errors::kUserCancelled);
+ !reject_show_error_message_.empty()
+ ? reject_show_error_message_
+ : errors::kUserCancelled);
// We close all bindings and ask to be destroyed.
client_.reset();