- Revision
- 236922
- Author
- [email protected]
- Date
- 2018-10-08 10:22:18 -0700 (Mon, 08 Oct 2018)
Log Message
[Payment Request] Requests should be aborted after details settle when the user cancels
https://bugs.webkit.org/show_bug.cgi?id=190333
Reviewed by Alex Christensen.
Source/WebCore:
In Payment Request's "update a PaymentRequest's details" algorithm, user agents are expected
to disable the payment UI when PaymentRequest details are being updated by the merchant.
This is to prevent the user from accepting a payment before updated details are displayed.
Further, Payment Request's "user aborts the payment request" algorithm says that the
algorithm should be terminated prior to throwing an AbortError if the request is currently
being updated, and also that user agents SHOULD ensure this never occurs. This is based on
the assumption that payment UIs are disabled during details updates.
For Apple Pay, while it is true that a payment cannot be accepted by the user while details
are being updated by the merchant, the payment UI is not completely disabled. In particular,
the user is allowed to abort the payment while details are being updated. We need to honor
the user's request to abort without doing so in the middle of a details update.
This patch defers a user-initiated abort until after details are settled, at which point the
promise returned by show() is rejected with an AbortError. This behaves as if the details
update promise were rejected by the merchant.
Added a test case to http/tests/paymentrequest/payment-request-show-method.https.html.
* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::settleDetailsPromise):
(WebCore::PaymentRequest::whenDetailsSettled):
(WebCore::PaymentRequest::cancel):
* Modules/paymentrequest/PaymentRequest.h:
LayoutTests:
* http/tests/paymentrequest/payment-request-show-method.https-expected.txt:
* http/tests/paymentrequest/payment-request-show-method.https.html:
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (236921 => 236922)
--- trunk/LayoutTests/ChangeLog 2018-10-08 17:19:09 UTC (rev 236921)
+++ trunk/LayoutTests/ChangeLog 2018-10-08 17:22:18 UTC (rev 236922)
@@ -1,3 +1,13 @@
+2018-10-08 Andy Estes <[email protected]>
+
+ [Payment Request] Requests should be aborted after details settle when the user cancels
+ https://bugs.webkit.org/show_bug.cgi?id=190333
+
+ Reviewed by Alex Christensen.
+
+ * http/tests/paymentrequest/payment-request-show-method.https-expected.txt:
+ * http/tests/paymentrequest/payment-request-show-method.https.html:
+
2018-10-08 Ryan Haddad <[email protected]>
REGRESSION (r235630?): [Mojave WK1] Layout test compositing/filters/opacity-change-on-filtered-paints-into-ancestor.html is a flaky image failure
Modified: trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https-expected.txt (236921 => 236922)
--- trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https-expected.txt 2018-10-08 17:19:09 UTC (rev 236921)
+++ trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https-expected.txt 2018-10-08 17:22:18 UTC (rev 236922)
@@ -4,6 +4,7 @@
PASS If the user agent's "payment request is showing" boolean is true, then return a promise rejected with an "AbortError" DOMException.
PASS If payment method consultation produces no supported method of payment, then return a promise rejected with a "NotSupportedError" DOMException.
PASS If the user aborts the payment request algorithm, then return a promise rejected with an "AbortError" DOMException.
+PASS If the user aborts the payment request algorithm while details are updating, then reject the accept promise with an "AbortError" when the details settle.
PASS A request is updated when show()'s detail promise resolves.
PASS Change events do not occur until show()'s detail promise resolves.
Modified: trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https.html (236921 => 236922)
--- trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https.html 2018-10-08 17:19:09 UTC (rev 236921)
+++ trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https.html 2018-10-08 17:22:18 UTC (rev 236922)
@@ -78,6 +78,17 @@
user_activation_test(async t => {
const request = new PaymentRequest(defaultMethods, defaultDetails);
+ const acceptPromise = request.show(new Promise(resolve => {
+ window.setTimeout(() => {
+ internals.mockPaymentCoordinator.cancelPayment();
+ window.setTimeout(() => resolve(defaultDetails));
+ });
+ })); // Sets state to "interactive"
+ await promise_rejects(t, "AbortError", acceptPromise);
+}, `If the user aborts the payment request algorithm while details are updating, then reject the accept promise with an "AbortError" when the details settle.`);
+
+user_activation_test(async t => {
+ const request = new PaymentRequest(defaultMethods, defaultDetails);
const expectedLabel = "Updated Total";
const expectedAmount = "2.00";
const details = {
Modified: trunk/Source/WebCore/ChangeLog (236921 => 236922)
--- trunk/Source/WebCore/ChangeLog 2018-10-08 17:19:09 UTC (rev 236921)
+++ trunk/Source/WebCore/ChangeLog 2018-10-08 17:22:18 UTC (rev 236922)
@@ -1,3 +1,36 @@
+2018-10-08 Andy Estes <[email protected]>
+
+ [Payment Request] Requests should be aborted after details settle when the user cancels
+ https://bugs.webkit.org/show_bug.cgi?id=190333
+
+ Reviewed by Alex Christensen.
+
+ In Payment Request's "update a PaymentRequest's details" algorithm, user agents are expected
+ to disable the payment UI when PaymentRequest details are being updated by the merchant.
+ This is to prevent the user from accepting a payment before updated details are displayed.
+
+ Further, Payment Request's "user aborts the payment request" algorithm says that the
+ algorithm should be terminated prior to throwing an AbortError if the request is currently
+ being updated, and also that user agents SHOULD ensure this never occurs. This is based on
+ the assumption that payment UIs are disabled during details updates.
+
+ For Apple Pay, while it is true that a payment cannot be accepted by the user while details
+ are being updated by the merchant, the payment UI is not completely disabled. In particular,
+ the user is allowed to abort the payment while details are being updated. We need to honor
+ the user's request to abort without doing so in the middle of a details update.
+
+ This patch defers a user-initiated abort until after details are settled, at which point the
+ promise returned by show() is rejected with an AbortError. This behaves as if the details
+ update promise were rejected by the merchant.
+
+ Added a test case to http/tests/paymentrequest/payment-request-show-method.https.html.
+
+ * Modules/paymentrequest/PaymentRequest.cpp:
+ (WebCore::PaymentRequest::settleDetailsPromise):
+ (WebCore::PaymentRequest::whenDetailsSettled):
+ (WebCore::PaymentRequest::cancel):
+ * Modules/paymentrequest/PaymentRequest.h:
+
2018-10-08 Chris Dumez <[email protected]>
Have DOMWindowProperty get is frame from its associated DOMWindow
Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp (236921 => 236922)
--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp 2018-10-08 17:19:09 UTC (rev 236921)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp 2018-10-08 17:22:18 UTC (rev 236922)
@@ -614,6 +614,7 @@
{
auto scopeExit = makeScopeExit([&] {
m_isUpdating = false;
+ m_isCancelPending = false;
m_detailsPromise = nullptr;
});
@@ -620,7 +621,7 @@
if (m_state != State::Interactive)
return;
- if (m_detailsPromise->status() == DOMPromise::Status::Rejected) {
+ if (m_isCancelPending || m_detailsPromise->status() == DOMPromise::Status::Rejected) {
stop();
return;
}
@@ -666,19 +667,22 @@
void PaymentRequest::whenDetailsSettled(std::function<void()>&& callback)
{
- if (!m_detailsPromise) {
+ auto whenSettledFunction = [this, callback = WTFMove(callback)] {
ASSERT(m_state == State::Interactive);
ASSERT(!m_isUpdating);
+ ASSERT(!m_isCancelPending);
+ ASSERT_UNUSED(this, this);
callback();
+ };
+
+ if (!m_detailsPromise) {
+ whenSettledFunction();
return;
}
- m_detailsPromise->whenSettled([this, protectedThis = makeRefPtr(this), callback = WTFMove(callback)] {
- if (m_state != State::Interactive)
- return;
-
- ASSERT(!m_isUpdating);
- callback();
+ m_detailsPromise->whenSettled([this, protectedThis = makeRefPtr(this), whenSettledFunction = WTFMove(whenSettledFunction)] {
+ if (m_state == State::Interactive)
+ whenSettledFunction();
});
}
@@ -719,10 +723,13 @@
if (m_state != State::Interactive)
return;
- if (m_isUpdating)
+ m_activePaymentHandler = nullptr;
+
+ if (m_isUpdating) {
+ m_isCancelPending = true;
return;
+ }
- m_activePaymentHandler = nullptr;
stop();
}
Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h (236921 => 236922)
--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h 2018-10-08 17:19:09 UTC (rev 236921)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h 2018-10-08 17:22:18 UTC (rev 236922)
@@ -136,6 +136,7 @@
RefPtr<DOMPromise> m_detailsPromise;
RefPtr<DOMPromise> m_merchantSessionPromise;
bool m_isUpdating { false };
+ bool m_isCancelPending { false };
};
std::optional<PaymentRequest::MethodIdentifier> convertAndValidatePaymentMethodIdentifier(const String& identifier);