Changeset 223160 in webkit


Ignore:
Timestamp:
Oct 10, 2017 5:37:49 PM (7 years ago)
Author:
aestes@apple.com
Message:

[Payment Request] Implement PaymentRequest.canMakePayment()
https://bugs.webkit.org/show_bug.cgi?id=178048

Reviewed by Youenn Fablet.

LayoutTests/imported/w3c:

  • web-platform-tests/payment-request/payment-request-canmakepayment-method.https-expected.txt: Removed.

Source/WebCore:

Test: http/tests/paymentrequest/payment-request-canmakepayment-method.https.html

  • Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:

(WebCore::ApplePayPaymentHandler::convertData): Moved
ApplePayRequest-to-ApplePaySessionPaymentRequest conversion from here to show().
(WebCore::ApplePayPaymentHandler::show): Returned an exception if
ApplePaySessionPaymentRequest conversion fails.
(WebCore::shouldDiscloseApplePayCapability): Checked if we are in an ephimeral session or if
Settings::applePayCapabilityDisclosureAllowed() is false.
(WebCore::ApplePayPaymentHandler::canMakePayment): Called
PaymentCoordinator::canMakePayments() or PaymentCoordinator::canMakePaymentsWithActiveCard()
depending on shouldDiscloseApplePayCapability().

  • Modules/applepay/paymentrequest/ApplePayPaymentHandler.h:
  • Modules/applepay/paymentrequest/ApplePayRequest.h:
  • Modules/applepay/paymentrequest/ApplePayRequest.idl: Defined merchantIdentifier.
  • Modules/paymentrequest/PaymentHandler.h:
  • Modules/paymentrequest/PaymentRequest.cpp:

(WebCore::parse): Moved JSON-parsing to here from show().
(WebCore::PaymentRequest::show): Returned the exception from PaymentHandler::show().
(WebCore::PaymentRequest::canMakePayment): For each payment method, try to create a
PaymentHandler.
For the first valid PaymentHandler, call canMakePayment() and pass a lambda that resolves
the promise.

  • Modules/paymentrequest/PaymentRequest.h:
  • Modules/paymentrequest/PaymentRequest.idl: Added CallWith=Document annotations to show()

and canMakePayment().

LayoutTests:

  • http/tests/paymentrequest/payment-request-canmakepayment-method.https-expected.txt: Added.
  • http/tests/paymentrequest/payment-request-canmakepayment-method.https.html: Added.
  • http/tests/ssl/applepay/PaymentRequest.https.html:
  • platform/ios-wk2/TestExpectations:
  • platform/mac-wk2/TestExpectations:
Location:
trunk
Files:
2 added
1 deleted
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r223145 r223160  
     12017-10-10  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Implement PaymentRequest.canMakePayment()
     4        https://bugs.webkit.org/show_bug.cgi?id=178048
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * http/tests/paymentrequest/payment-request-canmakepayment-method.https-expected.txt: Added.
     9        * http/tests/paymentrequest/payment-request-canmakepayment-method.https.html: Added.
     10        * http/tests/ssl/applepay/PaymentRequest.https.html:
     11        * platform/ios-wk2/TestExpectations:
     12        * platform/mac-wk2/TestExpectations:
     13
    1142017-10-10  Joanmarie Diggs  <jdiggs@igalia.com>
    215
  • trunk/LayoutTests/http/tests/paymentrequest/payment-request-abort-method.https.html

    r223076 r223160  
    1919    data: {
    2020        version: 2,
     21        merchantIdentifier: '',
    2122        merchantCapabilities: ['supports3DS'],
    2223        supportedNetworks: ['visa', 'masterCard'],
  • trunk/LayoutTests/http/tests/paymentrequest/payment-request-show-method.https.html

    r223076 r223160  
    1414    data: {
    1515        version: 2,
     16        merchantIdentifier: '',
    1617        merchantCapabilities: ['supports3DS'],
    1718        supportedNetworks: ['visa', 'masterCard'],
  • trunk/LayoutTests/http/tests/ssl/applepay/PaymentRequest.https.html

    r222921 r223160  
    1717        data: {
    1818            version: 2,
     19            merchantIdentifier: '',
    1920            countryCode: 'US',
    2021            currencyCode: 'USD',
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r223117 r223160  
     12017-10-10  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Implement PaymentRequest.canMakePayment()
     4        https://bugs.webkit.org/show_bug.cgi?id=178048
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * web-platform-tests/payment-request/payment-request-canmakepayment-method.https-expected.txt: Removed.
     9
    1102017-10-09  Chris Dumez  <cdumez@apple.com>
    211
  • trunk/LayoutTests/platform/ios-wk2/TestExpectations

    r223115 r223160  
    4141imported/w3c/web-platform-tests/payment-request/payment-request-show-method.https.html [ WontFix ]
    4242imported/w3c/web-platform-tests/payment-request/payment-request-abort-method.https.html [ WontFix ]
     43imported/w3c/web-platform-tests/payment-request/payment-request-canmakepayment-method.https.html [ WontFix ]
    4344
    4445 # skip manual payment-request tests
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r223115 r223160  
    3939imported/w3c/web-platform-tests/payment-request/payment-request-show-method.https.html [ WontFix ]
    4040imported/w3c/web-platform-tests/payment-request/payment-request-abort-method.https.html [ WontFix ]
     41imported/w3c/web-platform-tests/payment-request/payment-request-canmakepayment-method.https.html [ WontFix ]
    4142
    4243# skip manual payment-request tests
  • trunk/Source/WebCore/ChangeLog

    r223156 r223160  
     12017-10-10  Andy Estes  <aestes@apple.com>
     2
     3        [Payment Request] Implement PaymentRequest.canMakePayment()
     4        https://bugs.webkit.org/show_bug.cgi?id=178048
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Test: http/tests/paymentrequest/payment-request-canmakepayment-method.https.html
     9
     10        * Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
     11        (WebCore::ApplePayPaymentHandler::convertData): Moved
     12        ApplePayRequest-to-ApplePaySessionPaymentRequest conversion from here to show().
     13        (WebCore::ApplePayPaymentHandler::show): Returned an exception if
     14        ApplePaySessionPaymentRequest conversion fails.
     15        (WebCore::shouldDiscloseApplePayCapability): Checked if we are in an ephimeral session or if
     16        Settings::applePayCapabilityDisclosureAllowed() is false.
     17        (WebCore::ApplePayPaymentHandler::canMakePayment): Called
     18        PaymentCoordinator::canMakePayments() or PaymentCoordinator::canMakePaymentsWithActiveCard()
     19        depending on shouldDiscloseApplePayCapability().
     20        * Modules/applepay/paymentrequest/ApplePayPaymentHandler.h:
     21        * Modules/applepay/paymentrequest/ApplePayRequest.h:
     22        * Modules/applepay/paymentrequest/ApplePayRequest.idl: Defined merchantIdentifier.
     23        * Modules/paymentrequest/PaymentHandler.h:
     24        * Modules/paymentrequest/PaymentRequest.cpp:
     25        (WebCore::parse): Moved JSON-parsing to here from show().
     26        (WebCore::PaymentRequest::show): Returned the exception from PaymentHandler::show().
     27        (WebCore::PaymentRequest::canMakePayment): For each payment method, try to create a
     28        PaymentHandler.
     29        For the first valid PaymentHandler, call canMakePayment() and pass a lambda that resolves
     30        the promise.
     31        * Modules/paymentrequest/PaymentRequest.h:
     32        * Modules/paymentrequest/PaymentRequest.idl: Added CallWith=Document annotations to show()
     33        and canMakePayment().
     34
    1352017-10-10  Chris Dumez  <cdumez@apple.com>
    236
  • trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp

    r223076 r223160  
    3333#include "ApplePaySessionPaymentRequest.h"
    3434#include "Document.h"
    35 #include "Frame.h"
    3635#include "JSApplePayRequest.h"
    3736#include "LinkIconCollector.h"
    3837#include "MainFrame.h"
     38#include "Page.h"
    3939#include "PaymentContact.h"
    4040#include "PaymentCoordinator.h"
    4141#include "PaymentRequestValidator.h"
     42#include "Settings.h"
    4243
    4344namespace WebCore {
     
    109110    return ApplePaySessionPaymentRequest::ShippingType::Shipping;
    110111}
    111    
     112
    112113static ApplePaySessionPaymentRequest::ShippingMethod convert(const PaymentShippingOption& shippingOption)
    113114{
     
    126127        return Exception { ExistingExceptionError };
    127128
    128     auto validatedRequest = convertAndValidate(applePayRequest.version, applePayRequest);
     129    m_applePayRequest = WTFMove(applePayRequest);
     130    return { };
     131}
     132
     133ExceptionOr<void> ApplePayPaymentHandler::show(Document& document)
     134{
     135    auto validatedRequest = convertAndValidate(m_applePayRequest->version, *m_applePayRequest);
    129136    if (validatedRequest.hasException())
    130137        return validatedRequest.releaseException();
     
    155162        return exception.releaseException();
    156163
    157     m_applePayRequest = WTFMove(request);
    158     return { };
    159 }
    160 
    161 void ApplePayPaymentHandler::show(Document& document)
    162 {
    163164    Vector<URL> linkIconURLs;
    164165    for (auto& icon : LinkIconCollector { document }.iconsOfTypes({ LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon }))
    165166        linkIconURLs.append(icon.url);
    166167
    167     paymentCoordinator(document).beginPaymentSession(*this, document.url(), linkIconURLs, *m_applePayRequest);
     168    paymentCoordinator(document).beginPaymentSession(*this, document.url(), linkIconURLs, request);
     169    return { };
    168170}
    169171
     
    173175}
    174176
     177static bool shouldDiscloseApplePayCapability(Document& document)
     178{
     179    auto* page = document.page();
     180    if (!page || page->usesEphemeralSession())
     181        return false;
     182
     183    return document.settings().applePayCapabilityDisclosureAllowed();
     184}
     185
     186void ApplePayPaymentHandler::canMakePayment(Document& document, WTF::Function<void(bool)>&& completionHandler)
     187{
     188    if (!shouldDiscloseApplePayCapability(document)) {
     189        completionHandler(paymentCoordinator(document).canMakePayments());
     190        return;
     191    }
     192
     193    paymentCoordinator(document).canMakePaymentsWithActiveCard(m_applePayRequest->merchantIdentifier, document.domain(), WTFMove(completionHandler));
     194}
     195
    175196} // namespace WebCore
    176197
  • trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.h

    r223076 r223160  
    2828#if ENABLE(APPLE_PAY) && ENABLE(PAYMENT_REQUEST)
    2929
    30 #include "ApplePaySessionPaymentRequest.h"
     30#include "ApplePayRequest.h"
    3131#include "PaymentHandler.h"
    3232#include "PaymentSession.h"
     
    4949    // PaymentHandler
    5050    ExceptionOr<void> convertData(JSC::ExecState&, JSC::JSValue&&) final;
    51     void show(Document&) final;
     51    ExceptionOr<void> show(Document&) final;
    5252    void hide(Document&) final;
     53    void canMakePayment(Document&, WTF::Function<void(bool)>&& completionHandler) final;
    5354
    5455    // PaymentSession
     
    6162
    6263    Ref<PaymentRequest> m_paymentRequest;
    63     std::optional<ApplePaySessionPaymentRequest> m_applePayRequest;
     64    std::optional<ApplePayRequest> m_applePayRequest;
    6465};
    6566
  • trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayRequest.h

    r222921 r223160  
    3434struct ApplePayRequest : public ApplePayRequestBase {
    3535    unsigned long version;
     36    String merchantIdentifier;
    3637};
    3738
  • trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayRequest.idl

    r222921 r223160  
    2828] dictionary ApplePayRequest : ApplePayRequestBase {
    2929    required unsigned long version;
     30    required DOMString merchantIdentifier;
    3031};
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h

    r223076 r223160  
    3030#include "PaymentRequest.h"
    3131#include "PaymentSessionBase.h"
     32#include <wtf/Function.h>
    3233
    3334namespace JSC {
     
    4647
    4748    virtual ExceptionOr<void> convertData(JSC::ExecState&, JSC::JSValue&&) = 0;
    48     virtual void show(Document&) = 0;
     49    virtual ExceptionOr<void> show(Document&) = 0;
    4950    virtual void hide(Document&) = 0;
     51    virtual void canMakePayment(Document&, WTF::Function<void(bool)>&& completionHandler) = 0;
    5052};
    5153
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp

    r223076 r223160  
    341341}
    342342
     343static ExceptionOr<JSC::JSValue> parse(ScriptExecutionContext& context, const String& string)
     344{
     345    auto scope = DECLARE_THROW_SCOPE(context.vm());
     346    JSC::JSValue data = JSONParse(context.execState(), string);
     347    if (scope.exception())
     348        return Exception { ExistingExceptionError };
     349    return WTFMove(data);
     350}
     351
    343352// https://www.w3.org/TR/payment-request/#show()-method
    344 void PaymentRequest::show(ShowPromise&& promise)
     353void PaymentRequest::show(Document& document, ShowPromise&& promise)
    345354{
    346355    // FIXME: Reject promise with SecurityError if show() was not triggered by a user gesture.
     
    352361    }
    353362
    354     auto& document = downcast<Document>(*scriptExecutionContext());
    355363    if (PaymentHandler::hasActiveSession(document)) {
    356364        promise.reject(Exception { AbortError });
     
    364372    RefPtr<PaymentHandler> selectedPaymentHandler;
    365373    for (auto& paymentMethod : m_serializedMethodData) {
    366         auto scope = DECLARE_THROW_SCOPE(document.vm());
    367         JSC::JSValue data = JSONParse(document.execState(), paymentMethod.serializedData);
    368         if (scope.exception()) {
    369             m_showPromise->reject(Exception { ExistingExceptionError });
     374        auto data = parse(document, paymentMethod.serializedData);
     375        if (data.hasException()) {
     376            m_showPromise->reject(data.releaseException());
    370377            return;
    371378        }
     
    375382            continue;
    376383
    377         auto result = handler->convertData(*document.execState(), WTFMove(data));
     384        auto result = handler->convertData(*document.execState(), data.releaseReturnValue());
    378385        if (result.hasException()) {
    379386            m_showPromise->reject(result.releaseException());
     
    390397    }
    391398
     399    auto exception = selectedPaymentHandler->show(document);
     400    if (exception.hasException()) {
     401        m_showPromise->reject(exception.releaseException());
     402        return;
     403    }
     404
    392405    ASSERT(!m_activePaymentHandler);
    393406    m_activePaymentHandler = WTFMove(selectedPaymentHandler);
    394 
    395     m_activePaymentHandler->show(document);
    396     setPendingActivity(this);
     407    setPendingActivity(this); // unsetPendingActivity() is called below in stop()
     408}
     409
     410void PaymentRequest::stop()
     411{
     412    if (m_state != State::Interactive)
     413        return;
     414
     415    if (auto paymentHandler = std::exchange(m_activePaymentHandler, nullptr)) {
     416        unsetPendingActivity(this);
     417        paymentHandler->hide(downcast<Document>(*scriptExecutionContext()));
     418    }
     419
     420    ASSERT(m_state == State::Interactive);
     421    m_state = State::Closed;
     422    m_showPromise->reject(Exception { AbortError });
    397423}
    398424
     
    409435
    410436// https://www.w3.org/TR/payment-request/#canmakepayment()-method
    411 void PaymentRequest::canMakePayment(CanMakePaymentPromise&& promise)
     437void PaymentRequest::canMakePayment(Document& document, CanMakePaymentPromise&& promise)
    412438{
    413439    if (m_state != State::Created) {
     
    416442    }
    417443
    418     // FIXME: Resolve the promise with true if we can support any of the payment methods in m_serializedMethodData.
     444    for (auto& paymentMethod : m_serializedMethodData) {
     445        auto data = parse(document, paymentMethod.serializedData);
     446        if (data.hasException())
     447            continue;
     448
     449        auto handler = PaymentHandler::create(*this, paymentMethod.identifier);
     450        if (!handler)
     451            continue;
     452
     453        auto exception = handler->convertData(*document.execState(), data.releaseReturnValue());
     454        if (exception.hasException())
     455            continue;
     456
     457        handler->canMakePayment(document, [promise = WTFMove(promise)](bool canMakePayment) mutable {
     458            promise.resolve(canMakePayment);
     459        });
     460        return;
     461    }
     462
    419463    promise.resolve(false);
    420464}
     
    444488}
    445489
    446 void PaymentRequest::stop()
    447 {
    448     if (m_state != State::Interactive)
    449         return;
    450 
    451     if (auto paymentHandler = std::exchange(m_activePaymentHandler, nullptr)) {
    452         unsetPendingActivity(this);
    453         paymentHandler->hide(downcast<Document>(*scriptExecutionContext()));
    454     }
    455 
    456     ASSERT(m_state == State::Interactive);
    457     m_state = State::Closed;
    458     m_showPromise->reject(Exception { AbortError });
    459 }
    460 
    461490} // namespace WebCore
    462491
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h

    r223076 r223160  
    5555    ~PaymentRequest();
    5656
    57     void show(ShowPromise&&);
     57    void show(Document&, ShowPromise&&);
    5858    ExceptionOr<void> abort(AbortPromise&&);
    59     void canMakePayment(CanMakePaymentPromise&&);
     59    void canMakePayment(Document&, CanMakePaymentPromise&&);
    6060
    6161    const String& id() const;
     
    104104    State m_state { State::Created };
    105105    std::optional<ShowPromise> m_showPromise;
    106     std::optional<CanMakePaymentPromise> m_canMakePaymentPromise;
    107106    RefPtr<PaymentHandler> m_activePaymentHandler;
    108107};
  • trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.idl

    r221020 r223160  
    3333    SecureContext
    3434] interface PaymentRequest : EventTarget {
    35     Promise<PaymentResponse> show();
     35    [CallWith=Document] Promise<PaymentResponse> show();
    3636    [MayThrowException] Promise<void> abort();
    37     Promise<boolean> canMakePayment();
     37    [CallWith=Document] Promise<boolean> canMakePayment();
    3838
    3939    readonly attribute DOMString id;
Note: See TracChangeset for help on using the changeset viewer.