Changeset 221020 in webkit


Ignore:
Timestamp:
Aug 22, 2017 9:59:49 AM (7 years ago)
Author:
aestes@apple.com
Message:

[Payment Request] Implement error checking for show(), abort(), and canMakePayment()
https://bugs.webkit.org/show_bug.cgi?id=175789

Reviewed by Brady Eidson.
LayoutTests/imported/w3c:

  • web-platform-tests/payment-request/payment-request-abort-method.https-expected.txt:
  • web-platform-tests/payment-request/payment-request-show-method.https-expected.txt:

Source/WebCore:

Implement many of the exceptions and promise rejections specified for PaymentRequest's
show(), abort(), and canMakePayment() methods. Also implement basic state tracking.

  • Modules/paymentrequest/PaymentRequest.cpp:

(WebCore::PaymentRequest::create): Changed serializedMethodData from a
HashMap<String, String> to a Vector<PaymentRequest::Method>.
(WebCore::PaymentRequest::PaymentRequest):
(WebCore::PaymentRequest::show): Added promise rejection for invalid state, updated the
state to Interactive, stored the promise in m_showPromise, and dispatched finishShowing().
(WebCore::PaymentRequest::finishShowing): Added JSON parsing of payment method serialized
data and exception propagation. If there are no exceptions, rejected m_showPromise with
NotSupportedError since we don't yet support any payment methods.
(WebCore::PaymentRequest::abort): Added promise rejection for invalid state and stored the
promise in m_abortPromise. Dispatched a lambda to update the state to Closed, reject
m_showPromise, and resolve m_abortPromise.
(WebCore::PaymentRequest::canMakePayment): Added promise rejection for invalid state and
stored the promise in m_canMakePaymentPromise. Dispatched a lambda to resolve
m_canMakePaymentPromise with false since we don't yet support any payment methods.

  • Modules/paymentrequest/PaymentRequest.h:
  • Modules/paymentrequest/PaymentRequest.idl: Annotated abort() with MayThrowException.

LayoutTests:

Stopped marking payment-request-abort-method.https.html and payment-request-show-method.https.html as flaky.

  • platform/ios-wk2/TestExpectations:
  • platform/mac-wk2/TestExpectations:
Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r221019 r221020  
     12017-08-22  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Implement error checking for show(), abort(), and canMakePayment()
     4        https://bugs.webkit.org/show_bug.cgi?id=175789
     5
     6        Reviewed by Brady Eidson.
     7       
     8        Stopped marking payment-request-abort-method.https.html and payment-request-show-method.https.html  as flaky.
     9
     10        * platform/ios-wk2/TestExpectations:
     11        * platform/mac-wk2/TestExpectations:
     12
    1132017-08-22  Chris Dumez  <cdumez@apple.com>
    214
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r220998 r221020  
     12017-08-22  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Implement error checking for show(), abort(), and canMakePayment()
     4        https://bugs.webkit.org/show_bug.cgi?id=175789
     5
     6        Reviewed by Brady Eidson.
     7
     8        * web-platform-tests/payment-request/payment-request-abort-method.https-expected.txt:
     9        * web-platform-tests/payment-request/payment-request-show-method.https-expected.txt:
     10
    1112017-08-21  Youenn Fablet  <youenn@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/web-platform-tests/payment-request/payment-request-abort-method.https-expected.txt

    r220955 r221020  
    1 CONSOLE MESSAGE: Unhandled Promise Rejection: NotSupportedError: Not implemented
     1CONSOLE MESSAGE: Unhandled Promise Rejection: NotSupportedError: The operation is not supported.
    22
    3 FAIL Throws if the promise [[state]] is not "interactive" assert_throws: function "function () { throw e }" threw object "NotSupportedError: Not implemented" that is not a DOMException InvalidStateError: property "code" is equal to 9, expected 11
    4 FAIL Calling abort must not change the [[state]] until after "interactive" assert_throws: function "function () { throw e }" threw object "NotSupportedError: Not implemented" that is not a DOMException InvalidStateError: property "code" is equal to 9, expected 11
    5 FAIL calling .abort() causes acceptPromise to reject and closes the request. assert_true: Unexpected promise rejection: Not implemented expected true got false
     3PASS Throws if the promise [[state]] is not "interactive"
     4PASS Calling abort must not change the [[state]] until after "interactive"
     5FAIL calling .abort() causes acceptPromise to reject and closes the request. assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." that is not a DOMException AbortError: property "code" is equal to 9, expected 20
    66
  • trunk/LayoutTests/imported/w3c/web-platform-tests/payment-request/payment-request-show-method.https-expected.txt

    r220955 r221020  
    1 CONSOLE MESSAGE: Unhandled Promise Rejection: NotSupportedError: Not implemented
    2 CONSOLE MESSAGE: Unhandled Promise Rejection: NotSupportedError: Not implemented
     1CONSOLE MESSAGE: Unhandled Promise Rejection: NotSupportedError: The operation is not supported.
    32
    4 Harness Error (FAIL), message = Not implemented
     3FAIL Throws if the promise [[state]] is not "created" assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." that is not a DOMException AbortError: property "code" is equal to 9, expected 20
     4FAIL If the user agent's "payment request is showing" boolean is true, then return a promise rejected with an "AbortError" DOMException. assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." that is not a DOMException AbortError: property "code" is equal to 9, expected 20
    55
    6 FAIL Throws if the promise [[state]] is not "created" assert_throws: function "function () { throw e }" threw object "NotSupportedError: Not implemented" that is not a DOMException InvalidStateError: property "code" is equal to 9, expected 11
    7 FAIL If the user agent's "payment request is showing" boolean is true, then return a promise rejected with an "AbortError" DOMException. assert_throws: function "function () { throw e }" threw object "NotSupportedError: Not implemented" that is not a DOMException AbortError: property "code" is equal to 9, expected 20
    8 
  • trunk/LayoutTests/platform/ios-wk2/TestExpectations

    r220955 r221020  
    3535webkit.org/b/175611 imported/w3c/web-platform-tests/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Skip ]
    3636webkit.org/b/175611 imported/w3c/web-platform-tests/payment-request/allowpaymentrequest/setting-allowpaymentrequest.https.sub.html [ Skip ]
    37 webkit.org/b/175753 imported/w3c/web-platform-tests/payment-request/payment-request-abort-method.https.html [ Pass Failure ]
    38 webkit.org/b/175753 imported/w3c/web-platform-tests/payment-request/payment-request-show-method.https.html [ Pass Failure ]
    3937
    4038#//////////////////////////////////////////////////////////////////////////////////////////
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r221019 r221020  
    3838webkit.org/b/175611 imported/w3c/web-platform-tests/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Skip ]
    3939webkit.org/b/175611 imported/w3c/web-platform-tests/payment-request/allowpaymentrequest/setting-allowpaymentrequest.https.sub.html [ Skip ]
    40 webkit.org/b/175753 imported/w3c/web-platform-tests/payment-request/payment-request-abort-method.https.html [ Pass Failure ]
    41 webkit.org/b/175753 imported/w3c/web-platform-tests/payment-request/payment-request-show-method.https.html [ Pass Failure ]
    4240
    4341#//////////////////////////////////////////////////////////////////////////////////////////
  • trunk/Source/WebCore/ChangeLog

    r221017 r221020  
     12017-08-22  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Implement error checking for show(), abort(), and canMakePayment()
     4        https://bugs.webkit.org/show_bug.cgi?id=175789
     5
     6        Reviewed by Brady Eidson.
     7
     8        Implement many of the exceptions and promise rejections specified for PaymentRequest's
     9        show(), abort(), and canMakePayment() methods. Also implement basic state tracking.
     10
     11        * Modules/paymentrequest/PaymentRequest.cpp:
     12        (WebCore::PaymentRequest::create): Changed serializedMethodData from a
     13        HashMap<String, String> to a Vector<PaymentRequest::Method>.
     14        (WebCore::PaymentRequest::PaymentRequest):
     15        (WebCore::PaymentRequest::show): Added promise rejection for invalid state, updated the
     16        state to Interactive, stored the promise in m_showPromise, and dispatched finishShowing().
     17        (WebCore::PaymentRequest::finishShowing): Added JSON parsing of payment method serialized
     18        data and exception propagation. If there are no exceptions, rejected m_showPromise with
     19        NotSupportedError since we don't yet support any payment methods.
     20        (WebCore::PaymentRequest::abort): Added promise rejection for invalid state and stored the
     21        promise in m_abortPromise. Dispatched a lambda to update the state to Closed, reject
     22        m_showPromise, and resolve m_abortPromise.
     23        (WebCore::PaymentRequest::canMakePayment): Added promise rejection for invalid state and
     24        stored the promise in m_canMakePaymentPromise. Dispatched a lambda to resolve
     25        m_canMakePaymentPromise with false since we don't yet support any payment methods.
     26        * Modules/paymentrequest/PaymentRequest.h:
     27        * Modules/paymentrequest/PaymentRequest.idl: Annotated abort() with MayThrowException.
     28
    1292017-08-22  Brent Fulgham  <bfulgham@apple.com> and Pranjal Jumde  <pjumde@apple.com>
    230
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp

    r220980 r221020  
    3535#include "PaymentMethodData.h"
    3636#include "PaymentOptions.h"
     37#include "ScriptController.h"
    3738#include <JavaScriptCore/JSONObject.h>
    3839#include <JavaScriptCore/ThrowScope.h>
    3940#include <wtf/ASCIICType.h>
     41#include <wtf/RunLoop.h>
    4042#include <wtf/UUID.h>
    4143
     
    170172        return Exception { TypeError, ASCIILiteral("At least one payment method is required.") };
    171173
    172     HashMap<String, String> serializedMethodData;
     174    Vector<Method> serializedMethodData;
     175    serializedMethodData.reserveInitialCapacity(methodData.size());
    173176    for (auto& paymentMethod : methodData) {
    174177        if (paymentMethod.supportedMethods.isEmpty())
     
    182185                return Exception { ExistingExceptionError };
    183186        }
    184         serializedMethodData.add(paymentMethod.supportedMethods, WTFMove(serializedData));
     187        serializedMethodData.uncheckedAppend({ paymentMethod.supportedMethods, WTFMove(serializedData) });
    185188    }
    186189
     
    241244}
    242245
    243 PaymentRequest::PaymentRequest(Document& document, PaymentOptions&& options, PaymentDetailsInit&& details, Vector<String>&& serializedModifierData, HashMap<String, String>&& serializedMethodData, String&& selectedShippingOption)
     246PaymentRequest::PaymentRequest(Document& document, PaymentOptions&& options, PaymentDetailsInit&& details, Vector<String>&& serializedModifierData, Vector<Method>&& serializedMethodData, String&& selectedShippingOption)
    244247    : ActiveDOMObject { &document }
    245248    , m_options { WTFMove(options) }
     
    256259}
    257260
    258 void PaymentRequest::show(DOMPromiseDeferred<IDLInterface<PaymentResponse>>&& promise)
    259 {
    260     promise.reject(Exception { NotSupportedError, ASCIILiteral("Not implemented") });
    261 }
    262 
    263 void PaymentRequest::abort(DOMPromiseDeferred<void>&& promise)
    264 {
    265     promise.reject(Exception { NotSupportedError, ASCIILiteral("Not implemented") });
    266 }
    267 
    268 void PaymentRequest::canMakePayment(DOMPromiseDeferred<IDLBoolean>&& promise)
    269 {
    270     promise.reject(Exception { NotSupportedError, ASCIILiteral("Not implemented") });
    271 }
    272    
     261// https://www.w3.org/TR/payment-request/#show()-method
     262void PaymentRequest::show(ShowPromise&& promise)
     263{
     264    // FIXME: Reject promise with SecurityError if show() was not triggered by a user gesture.
     265    // Find a way to do this without breaking the payment-request web platform tests.
     266
     267    if (m_state != State::Created) {
     268        promise.reject(Exception { InvalidStateError });
     269        return;
     270    }
     271
     272    // FIXME: Reject promise with AbortError if PaymentCoordinator already has an active session.
     273
     274    m_state = State::Interactive;
     275    ASSERT(!m_showPromise);
     276    m_showPromise = WTFMove(promise);
     277
     278    // The spec requires these steps to be run after returning `promise` to the caller.
     279    RunLoop::main().dispatch([this, protectedThis = makeRef(*this)] {
     280        finishShowing();
     281    });
     282}
     283
     284void PaymentRequest::finishShowing()
     285{
     286    ASSERT(m_showPromise);
     287
     288    for (auto& paymentMethod : m_serializedMethodData) {
     289        auto scope = DECLARE_THROW_SCOPE(scriptExecutionContext()->vm());
     290        JSC::JSValue data = JSONParse(scriptExecutionContext()->execState(), paymentMethod.serializedData);
     291        if (scope.exception()) {
     292            m_showPromise->reject(Exception { ExistingExceptionError });
     293            return;
     294        }
     295
     296        // FIXME: If there is a payment handler that can support this payment method, allow it to
     297        // convert the serialized data (propagating any exceptions that might be thrown) and add it
     298        // to a list of handlers.
     299        UNUSED(data);
     300    }
     301
     302    // FIXME: If the list of handlers is non-empty, present the payment UI instead of rejecting.
     303    m_showPromise->reject(Exception { NotSupportedError });
     304}
     305
     306// https://www.w3.org/TR/payment-request/#abort()-method
     307ExceptionOr<void> PaymentRequest::abort(AbortPromise&& promise)
     308{
     309    if (m_state != State::Interactive)
     310        return Exception { InvalidStateError };
     311
     312    ASSERT(m_showPromise);
     313    ASSERT(!m_abortPromise);
     314    m_abortPromise = WTFMove(promise);
     315
     316    // The spec requires these steps to be run after returning `promise` to the caller.
     317    RunLoop::main().dispatch([this, protectedThis = makeRef(*this)] {
     318        m_state = State::Closed;
     319        m_showPromise->reject(Exception { AbortError });
     320        m_abortPromise->resolve();
     321    });
     322
     323    return { };
     324}
     325
     326// https://www.w3.org/TR/payment-request/#canmakepayment()-method
     327void PaymentRequest::canMakePayment(CanMakePaymentPromise&& promise)
     328{
     329    if (m_state != State::Created) {
     330        promise.reject(Exception { InvalidStateError });
     331        return;
     332    }
     333
     334    m_canMakePaymentPromise = WTFMove(promise);
     335
     336    // The spec requires these steps to be run after returning `promise` to the caller.
     337    RunLoop::main().dispatch([this, protectedThis = makeRef(*this)] {
     338        // FIXME: Resolve the promise with true if we can support any of the payment methods in m_serializedMethodData.
     339        m_canMakePaymentPromise->resolve(false);
     340    });
     341}
     342
    273343const String& PaymentRequest::id() const
    274344{
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h

    r220980 r221020  
    4545class PaymentRequest final : public RefCounted<PaymentRequest>, public ActiveDOMObject, public EventTargetWithInlineData {
    4646public:
     47    using ShowPromise = DOMPromiseDeferred<IDLInterface<PaymentResponse>>;
     48    using AbortPromise = DOMPromiseDeferred<void>;
     49    using CanMakePaymentPromise = DOMPromiseDeferred<IDLBoolean>;
     50
    4751    static ExceptionOr<Ref<PaymentRequest>> create(Document&, Vector<PaymentMethodData>&&, PaymentDetailsInit&&, PaymentOptions&&);
    4852    ~PaymentRequest();
    4953
    50     void show(DOMPromiseDeferred<IDLInterface<PaymentResponse>>&&);
    51     void abort(DOMPromiseDeferred<void>&&);
    52     void canMakePayment(DOMPromiseDeferred<IDLBoolean>&&);
     54    void show(ShowPromise&&);
     55    ExceptionOr<void> abort(AbortPromise&&);
     56    void canMakePayment(CanMakePaymentPromise&&);
    5357
    5458    const String& id() const;
     
    6165
    6266private:
    63     PaymentRequest(Document&, PaymentOptions&&, PaymentDetailsInit&&, Vector<String>&& serializedModifierData, HashMap<String, String>&& serializedMethodData, String&& selectedShippingOption);
     67    enum class State {
     68        Created,
     69        Interactive,
     70        Closed,
     71    };
     72
     73    struct Method {
     74        String supportedMethods;
     75        String serializedData;
     76    };
     77
     78    PaymentRequest(Document&, PaymentOptions&&, PaymentDetailsInit&&, Vector<String>&& serializedModifierData, Vector<Method>&& serializedMethodData, String&& selectedShippingOption);
     79
     80    void finishShowing();
    6481
    6582    // ActiveDOMObject
     
    7794    PaymentDetailsInit m_details;
    7895    Vector<String> m_serializedModifierData;
    79     HashMap<String, String> m_serializedMethodData;
     96    Vector<Method> m_serializedMethodData;
    8097    String m_shippingOption;
    8198    RefPtr<PaymentAddress> m_shippingAddress;
     99    State m_state { State::Created };
     100    std::optional<ShowPromise> m_showPromise;
     101    std::optional<AbortPromise> m_abortPromise;
     102    std::optional<CanMakePaymentPromise> m_canMakePaymentPromise;
    82103};
    83104
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.idl

    r220971 r221020  
    3434] interface PaymentRequest : EventTarget {
    3535    Promise<PaymentResponse> show();
    36     Promise<void> abort();
     36    [MayThrowException] Promise<void> abort();
    3737    Promise<boolean> canMakePayment();
    3838
Note: See TracChangeset for help on using the changeset viewer.