Changeset 236922 in webkit


Ignore:
Timestamp:
Oct 8, 2018 10:22:18 AM (6 years ago)
Author:
aestes@apple.com
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:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r236921 r236922  
     12018-10-08  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Requests should be aborted after details settle when the user cancels
     4        https://bugs.webkit.org/show_bug.cgi?id=190333
     5
     6        Reviewed by Alex Christensen.
     7
     8        * http/tests/paymentrequest/payment-request-show-method.https-expected.txt:
     9        * http/tests/paymentrequest/payment-request-show-method.https.html:
     10
    1112018-10-08  Ryan Haddad  <ryanhaddad@apple.com>
    212
  • trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https-expected.txt

    r228195 r236922  
    55PASS If payment method consultation produces no supported method of payment, then return a promise rejected with a "NotSupportedError" DOMException.
    66PASS If the user aborts the payment request algorithm, then return a promise rejected with an "AbortError" DOMException.
     7PASS If the user aborts the payment request algorithm while details are updating, then reject the accept promise with an "AbortError" when the details settle.
    78PASS A request is updated when show()'s detail promise resolves.
    89PASS Change events do not occur until show()'s detail promise resolves.
  • trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https.html

    r228195 r236922  
    7979user_activation_test(async t => {
    8080  const request = new PaymentRequest(defaultMethods, defaultDetails);
     81  const acceptPromise = request.show(new Promise(resolve => {
     82    window.setTimeout(() => {
     83      internals.mockPaymentCoordinator.cancelPayment();
     84      window.setTimeout(() => resolve(defaultDetails));
     85    });
     86  })); // Sets state to "interactive"
     87  await promise_rejects(t, "AbortError", acceptPromise);
     88}, `If the user aborts the payment request algorithm while details are updating, then reject the accept promise with an "AbortError" when the details settle.`);
     89
     90user_activation_test(async t => {
     91  const request = new PaymentRequest(defaultMethods, defaultDetails);
    8192  const expectedLabel = "Updated Total";
    8293  const expectedAmount = "2.00";
  • trunk/Source/WebCore/ChangeLog

    r236917 r236922  
     12018-10-08  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Requests should be aborted after details settle when the user cancels
     4        https://bugs.webkit.org/show_bug.cgi?id=190333
     5
     6        Reviewed by Alex Christensen.
     7
     8        In Payment Request's "update a PaymentRequest's details" algorithm, user agents are expected
     9        to disable the payment UI when PaymentRequest details are being updated by the merchant.
     10        This is to prevent the user from accepting a payment before updated details are displayed.
     11
     12        Further, Payment Request's "user aborts the payment request" algorithm says that the
     13        algorithm should be terminated prior to throwing an AbortError if the request is currently
     14        being updated, and also that user agents SHOULD ensure this never occurs. This is based on
     15        the assumption that payment UIs are disabled during details updates.
     16
     17        For Apple Pay, while it is true that a payment cannot be accepted by the user while details
     18        are being updated by the merchant, the payment UI is not completely disabled. In particular,
     19        the user is allowed to abort the payment while details are being updated. We need to honor
     20        the user's request to abort without doing so in the middle of a details update.
     21
     22        This patch defers a user-initiated abort until after details are settled, at which point the
     23        promise returned by show() is rejected with an AbortError. This behaves as if the details
     24        update promise were rejected by the merchant.
     25
     26        Added a test case to http/tests/paymentrequest/payment-request-show-method.https.html.
     27
     28        * Modules/paymentrequest/PaymentRequest.cpp:
     29        (WebCore::PaymentRequest::settleDetailsPromise):
     30        (WebCore::PaymentRequest::whenDetailsSettled):
     31        (WebCore::PaymentRequest::cancel):
     32        * Modules/paymentrequest/PaymentRequest.h:
     33
    1342018-10-08  Chris Dumez  <cdumez@apple.com>
    235
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp

    r236552 r236922  
    615615    auto scopeExit = makeScopeExit([&] {
    616616        m_isUpdating = false;
     617        m_isCancelPending = false;
    617618        m_detailsPromise = nullptr;
    618619    });
     
    621622        return;
    622623
    623     if (m_detailsPromise->status() == DOMPromise::Status::Rejected) {
     624    if (m_isCancelPending || m_detailsPromise->status() == DOMPromise::Status::Rejected) {
    624625        stop();
    625626        return;
     
    667668void PaymentRequest::whenDetailsSettled(std::function<void()>&& callback)
    668669{
    669     if (!m_detailsPromise) {
     670    auto whenSettledFunction = [this, callback = WTFMove(callback)] {
    670671        ASSERT(m_state == State::Interactive);
    671672        ASSERT(!m_isUpdating);
     673        ASSERT(!m_isCancelPending);
     674        ASSERT_UNUSED(this, this);
    672675        callback();
    673         return;
    674     }
    675 
    676     m_detailsPromise->whenSettled([this, protectedThis = makeRefPtr(this), callback = WTFMove(callback)] {
    677         if (m_state != State::Interactive)
    678             return;
    679 
    680         ASSERT(!m_isUpdating);
    681         callback();
     676    };
     677
     678    if (!m_detailsPromise) {
     679        whenSettledFunction();
     680        return;
     681    }
     682
     683    m_detailsPromise->whenSettled([this, protectedThis = makeRefPtr(this), whenSettledFunction = WTFMove(whenSettledFunction)] {
     684        if (m_state == State::Interactive)
     685            whenSettledFunction();
    682686    });
    683687}
     
    720724        return;
    721725
    722     if (m_isUpdating)
    723         return;
    724 
    725726    m_activePaymentHandler = nullptr;
     727
     728    if (m_isUpdating) {
     729        m_isCancelPending = true;
     730        return;
     731    }
     732
    726733    stop();
    727734}
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h

    r236429 r236922  
    137137    RefPtr<DOMPromise> m_merchantSessionPromise;
    138138    bool m_isUpdating { false };
     139    bool m_isCancelPending { false };
    139140};
    140141
Note: See TracChangeset for help on using the changeset viewer.