Skip to content
Permalink
Browse files
[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:


Canonical link: https://commits.webkit.org/194402@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223160 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
aestes committed Oct 11, 2017
1 parent d3a05f6 commit 3ab46f35fde5b488e023d580faae86240340706e
Showing 19 changed files with 342 additions and 53 deletions.
@@ -1,3 +1,16 @@
2017-10-10 Andy Estes <aestes@apple.com>

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

Reviewed by Youenn Fablet.

* 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:

2017-10-10 Joanmarie Diggs <jdiggs@igalia.com>

AX: [ATK] ARIA form role should be mapped to ATK_ROLE_LANDMARK; not ATK_ROLE_FORM
@@ -18,6 +18,7 @@
supportedMethods: "https://apple.com/apple-pay",
data: {
version: 2,
merchantIdentifier: '',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa', 'masterCard'],
countryCode: 'US',
@@ -0,0 +1,8 @@

PASS If request.[[state]] is "created", then return a promise that resolves to true for known method.
PASS If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.
PASS If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.
PASS If payment method identifier and serialized parts are supported, resolve promise with true.
PASS If payment method identifier is unknown, resolve promise with false.
PASS Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.

@@ -0,0 +1,174 @@
<!DOCTYPE html>
<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
<!-- Copyright (C) 2017 Apple Inc. All rights reserved. -->
<!-- FIXME: Upstream this test to web-platform-tests/payment-request/. -->
<meta charset="utf-8">
<title>Tests for PaymentRequest.canMakePayment() method</title>
<link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const applePay = Object.freeze({
supportedMethods: "https://apple.com/apple-pay",
data: {
version: 2,
merchantIdentifier: "",
merchantCapabilities: ["supports3DS"],
supportedNetworks: ["visa", "masterCard"],
countryCode: "US",
currencyCode: "USD",
}
});
const defaultMethods = Object.freeze([applePay]);
const defaultDetails = Object.freeze({
total: {
label: "Total",
amount: {
currency: "USD",
value: "1.00",
},
},
});

promise_test(async t => {
const request = new PaymentRequest(defaultMethods, defaultDetails);
try {
assert_true(
await request.canMakePayment(),
`canMakePaymentPromise should be true`
);
assert_true(
await request.canMakePayment(),
`canMakePaymentPromise should be true`
);
} catch (err) {
assert_equals(
err.name,
"NotAllowedError",
"if it throws, then it must be a NotAllowedError."
);
}
}, `If request.[[state]] is "created", then return a promise that resolves to true for known method.`);

promise_test(async t => {
const request = new PaymentRequest(defaultMethods, defaultDetails);
const acceptPromise = request.show(); // Sets state to "interactive"
const canMakePaymentPromise = request.canMakePayment();
try {
const result = await canMakePaymentPromise;
assert_true(
false,
`canMakePaymentPromise should have thrown InvalidStateError`
);
} catch (err) {
await promise_rejects(t, "InvalidStateError", canMakePaymentPromise);
} finally {
await request.abort();
await promise_rejects(t, "AbortError", acceptPromise);
}
// The state should be "closed"
await promise_rejects(t, "InvalidStateError", request.canMakePayment());
}, `If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.`);

promise_test(async t => {
const request = new PaymentRequest(defaultMethods, defaultDetails);
const acceptPromise = request.show(); // The state is now "interactive"
acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools.
await request.abort(); // The state is now "closed"
await promise_rejects(t, "InvalidStateError", request.canMakePayment());
try {
const result = await request.canMakePayment();
assert_true(
false,
`should have thrown InvalidStateError, but instead returned "${result}"`
);
} catch (err) {
assert_equals(
err.name,
"InvalidStateError",
"must be an InvalidStateError."
);
}
}, `If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.`);

promise_test(async t => {
const request = new PaymentRequest(defaultMethods, defaultDetails);
assert_true(await request.canMakePayment(), "basic-card should be supported");
}, `If payment method identifier and serialized parts are supported, resolve promise with true.`);

promise_test(async t => {
const unsupportedMethods = [
"this-is-not-supported",
"https://not.supported",
"e",
"n6jzof05mk2g4lhxr-u-q-w1-c-i-pa-ty-bdvs9-ho-ae7-p-md8-s-wq3-h-qd-e-q-sa",
"a-b-q-n-s-pw0",
"m-u",
"s-l5",
"k9-f",
"m-l",
"u4-n-t",
"i488jh6-g18-fck-yb-v7-i",
"x-x-t-t-c34-o",
"https://wpt",
"https://wpt.fyi/",
"https://wpt.fyi/payment",
"https://wpt.fyi/payment-request",
"https://wpt.fyi/payment-request?",
"https://wpt.fyi/payment-request?this=is",
"https://wpt.fyi/payment-request?this=is&totally",
"https://wpt.fyi:443/payment-request?this=is&totally",
"https://wpt.fyi:443/payment-request?this=is&totally#fine",
"https://:@wpt.fyi:443/payment-request?this=is&totally#👍",
" \thttps://wpt\n ",
"https://xn--c1yn36f",
"https://點看",
];
for (const method of unsupportedMethods) {
try {
const request = new PaymentRequest(
[{ supportedMethods: method }],
defaultDetails
);
assert_false(
await request.canMakePayment(),
`method "${method}" must not be supported`
);
} catch (err) {
assert_true(
false,
`Unexpected exception testing method ${method}, expected false. See error console.`
);
}
}
}, `If payment method identifier is unknown, resolve promise with false.`);

promise_test(async t => {
// This test might never actually hit its assertion, but that's allowed.
const request = new PaymentRequest(defaultMethods, defaultDetails);
for (let i = 0; i < 1000; i++) {
try {
await request.canMakePayment();
} catch (err) {
assert_equals(
err.name,
"NotAllowedError",
"if it throws, then it must be a NotAllowedError."
);
break;
}
}
for (let i = 0; i < 1000; i++) {
try {
await new PaymentRequest(defaultMethods, defaultDetails).canMakePayment();
} catch (err) {
assert_equals(
err.name,
"NotAllowedError",
"if it throws, then it must be a NotAllowedError."
);
break;
}
}
}, `Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.`);
</script>
@@ -13,6 +13,7 @@
supportedMethods: "https://apple.com/apple-pay",
data: {
version: 2,
merchantIdentifier: '',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa', 'masterCard'],
countryCode: 'US',
@@ -16,6 +16,7 @@
supportedMethods: 'https://apple.com/apple-pay',
data: {
version: 2,
merchantIdentifier: '',
countryCode: 'US',
currencyCode: 'USD',
supportedNetworks: ['visa', 'masterCard'],
@@ -1,3 +1,12 @@
2017-10-10 Andy Estes <aestes@apple.com>

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

Reviewed by Youenn Fablet.

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

2017-10-09 Chris Dumez <cdumez@apple.com>

It should not be possible to submit a form that is disconnected

This file was deleted.

@@ -40,6 +40,7 @@ webkit.org/b/175611 imported/w3c/web-platform-tests/payment-request/allowpayment
# skip in favor of tests in http/tests/paymentrequest
imported/w3c/web-platform-tests/payment-request/payment-request-show-method.https.html [ WontFix ]
imported/w3c/web-platform-tests/payment-request/payment-request-abort-method.https.html [ WontFix ]
imported/w3c/web-platform-tests/payment-request/payment-request-canmakepayment-method.https.html [ WontFix ]

# skip manual payment-request tests
imported/w3c/web-platform-tests/payment-request/algorithms-manual.https.html [ Skip ]
@@ -38,6 +38,7 @@ webkit.org/b/177783 imported/w3c/web-platform-tests/payment-request/rejects_if_n
# skip in favor of tests in http/tests/paymentrequest
imported/w3c/web-platform-tests/payment-request/payment-request-show-method.https.html [ WontFix ]
imported/w3c/web-platform-tests/payment-request/payment-request-abort-method.https.html [ WontFix ]
imported/w3c/web-platform-tests/payment-request/payment-request-canmakepayment-method.https.html [ WontFix ]

# skip manual payment-request tests
imported/w3c/web-platform-tests/payment-request/algorithms-manual.https.html [ Skip ]
@@ -1,3 +1,37 @@
2017-10-10 Andy Estes <aestes@apple.com>

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

Reviewed by Youenn Fablet.

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().

2017-10-10 Chris Dumez <cdumez@apple.com>

Unreviewed, really fix the build with certain SDKs.
@@ -32,13 +32,14 @@
#include "ApplePayMerchantCapability.h"
#include "ApplePaySessionPaymentRequest.h"
#include "Document.h"
#include "Frame.h"
#include "JSApplePayRequest.h"
#include "LinkIconCollector.h"
#include "MainFrame.h"
#include "Page.h"
#include "PaymentContact.h"
#include "PaymentCoordinator.h"
#include "PaymentRequestValidator.h"
#include "Settings.h"

namespace WebCore {

@@ -108,7 +109,7 @@ static ApplePaySessionPaymentRequest::ShippingType convert(PaymentShippingType t
ASSERT_NOT_REACHED();
return ApplePaySessionPaymentRequest::ShippingType::Shipping;
}

static ApplePaySessionPaymentRequest::ShippingMethod convert(const PaymentShippingOption& shippingOption)
{
ApplePaySessionPaymentRequest::ShippingMethod result;
@@ -125,7 +126,13 @@ ExceptionOr<void> ApplePayPaymentHandler::convertData(JSC::ExecState& execState,
if (throwScope.exception())
return Exception { ExistingExceptionError };

auto validatedRequest = convertAndValidate(applePayRequest.version, applePayRequest);
m_applePayRequest = WTFMove(applePayRequest);
return { };
}

ExceptionOr<void> ApplePayPaymentHandler::show(Document& document)
{
auto validatedRequest = convertAndValidate(m_applePayRequest->version, *m_applePayRequest);
if (validatedRequest.hasException())
return validatedRequest.releaseException();

@@ -154,24 +161,38 @@ ExceptionOr<void> ApplePayPaymentHandler::convertData(JSC::ExecState& execState,
if (exception.hasException())
return exception.releaseException();

m_applePayRequest = WTFMove(request);
return { };
}

void ApplePayPaymentHandler::show(Document& document)
{
Vector<URL> linkIconURLs;
for (auto& icon : LinkIconCollector { document }.iconsOfTypes({ LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon }))
linkIconURLs.append(icon.url);

paymentCoordinator(document).beginPaymentSession(*this, document.url(), linkIconURLs, *m_applePayRequest);
paymentCoordinator(document).beginPaymentSession(*this, document.url(), linkIconURLs, request);
return { };
}

void ApplePayPaymentHandler::hide(Document& document)
{
paymentCoordinator(document).abortPaymentSession();
}

static bool shouldDiscloseApplePayCapability(Document& document)
{
auto* page = document.page();
if (!page || page->usesEphemeralSession())
return false;

return document.settings().applePayCapabilityDisclosureAllowed();
}

void ApplePayPaymentHandler::canMakePayment(Document& document, WTF::Function<void(bool)>&& completionHandler)
{
if (!shouldDiscloseApplePayCapability(document)) {
completionHandler(paymentCoordinator(document).canMakePayments());
return;
}

paymentCoordinator(document).canMakePaymentsWithActiveCard(m_applePayRequest->merchantIdentifier, document.domain(), WTFMove(completionHandler));
}

} // namespace WebCore

#endif // ENABLE(APPLE_PAY) && ENABLE(PAYMENT_REQUEST)

0 comments on commit 3ab46f3

Please sign in to comment.