Skip to content
Permalink
Browse files
[Apple Pay] Implement a paymentmethodselected event for PaymentRequest
https://bugs.webkit.org/show_bug.cgi?id=178765

Reviewed by Tim Horton.

Source/WebCore:

When the Apple Pay payment method changes, fire an applepaypaymentmethodchanged event on the
PaymentRequest object. The event has a paymentMethod property and an updateWith() method
which behaves identically to PaymentRequestUpdateEvent.updateWith().

Test: http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https.html

* DerivedSources.make:
* Modules/applepay/ApplePayPaymentMethod.idl:
* Modules/applepay/ApplePayPaymentMethodSelectedEvent.h:
* Modules/applepay/PaymentMethod.h:
(WebCore::PaymentMethod::PaymentMethod): Deleted.
(WebCore::PaymentMethod::pkPaymentMethod const): Deleted.
* Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
(WebCore::ApplePayPaymentHandler::detailsUpdated):
(WebCore::ApplePayPaymentHandler::paymentMethodUpdated):
(WebCore::ApplePayPaymentHandler::didSelectPaymentMethod):
* Modules/applepay/paymentrequest/ApplePayPaymentHandler.h:
* Modules/applepay/paymentrequest/ApplePayPaymentMethodUpdateEvent.cpp: Added.
(WebCore::ApplePayPaymentMethodUpdateEvent::ApplePayPaymentMethodUpdateEvent):
(WebCore::ApplePayPaymentMethodUpdateEvent::eventInterface const):
* Modules/applepay/paymentrequest/ApplePayPaymentMethodUpdateEvent.h: Added.
* Modules/applepay/paymentrequest/ApplePayPaymentMethodUpdateEvent.idl: Added.
* Modules/paymentrequest/PaymentHandler.h:
* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::shippingAddressChanged):
(WebCore::PaymentRequest::shippingOptionChanged):
(WebCore::PaymentRequest::dispatchEvent):
(WebCore::PaymentRequest::updateWith):
(WebCore::PaymentRequest::settleDetailsPromise):
(WebCore::PaymentRequest::dispatchUpdateEvent): Deleted.
* Modules/paymentrequest/PaymentRequest.h:
* Modules/paymentrequest/PaymentRequest.idl:
* Modules/paymentrequest/PaymentRequestUpdateEvent.cpp:
(WebCore::PaymentRequestUpdateEvent::updateWith):
* Modules/paymentrequest/PaymentRequestUpdateEvent.h:
* WebCore.xcodeproj/project.pbxproj:
* dom/EventNames.h:
* dom/EventNames.in:
* testing/MockPaymentCoordinator.cpp:
(WebCore::MockPaymentCoordinator::changePaymentMethod):
* testing/MockPaymentCoordinator.h:
* testing/MockPaymentCoordinator.idl:
* testing/MockPaymentMethod.h: Added.

LayoutTests:

* http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https-expected.txt: Added.
* http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https.html: Added.


Canonical link: https://commits.webkit.org/194941@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223945 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
aestes committed Oct 25, 2017
1 parent 74238b9 commit 33796ae96222a4664c1219963c540d38fc207456
Showing 26 changed files with 477 additions and 45 deletions.
@@ -1,3 +1,13 @@
2017-10-24 Andy Estes <aestes@apple.com>

[Apple Pay] Implement a paymentmethodselected event for PaymentRequest
https://bugs.webkit.org/show_bug.cgi?id=178765

Reviewed by Tim Horton.

* http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https-expected.txt: Added.
* http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https.html: Added.

2017-10-24 Daniel Bates <dabates@apple.com>

Test fast/writing-mode/english-bt-text-with-spelling-marker.html should wait for editing commands to complete
@@ -0,0 +1,19 @@
Test the applepaypaymentmethodchanged event.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


Testing ApplePayMerchantValidationEvent

PASS event.paymentMethod.displayName is expectedPaymentMethod.displayName
PASS event.paymentMethod.network is expectedPaymentMethod.network
PASS event.paymentMethod.type is expectedPaymentMethod.type
PASS event.paymentMethod.paymentPass.primaryAccountIdentifier is expectedPaymentMethod.paymentPass.primaryAccountIdentifier
PASS event.paymentMethod.paymentPass.primaryAccountNumberSuffix is expectedPaymentMethod.paymentPass.primaryAccountNumberSuffix
PASS event.paymentMethod.paymentPass.deviceAccountIdentifier is expectedPaymentMethod.paymentPass.deviceAccountIdentifier
PASS event.paymentMethod.paymentPass.deviceAccountNumberSuffix is expectedPaymentMethod.paymentPass.deviceAccountNumberSuffix
PASS event.paymentMethod.paymentPass.activationState is expectedPaymentMethod.paymentPass.activationState
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="/js-test-resources/ui-helper.js"></script>
<script src="/resources/js-test-pre.js"></script>
</head>
<body>
<script>

description("Test the applepaypaymentmethodchanged event.");

window.jsTestIsAsync = true;

function validPaymentMethod() {
return {
supportedMethods: 'https://apple.com/apple-pay',
data: {
version: 2,
merchantIdentifier: '',
countryCode: 'US',
supportedNetworks: ['visa', 'masterCard'],
merchantCapabilities: ['supports3DS'],
},
}
}

function validPaymentDetails() {
return {
total: { label: 'Your label', amount: { currency: 'USD', value: '10.00' } },
}
}

async function go() {
debug("Testing ApplePayMerchantValidationEvent");
debug("");

expectedPaymentMethod = {
displayName: 'test',
network: 'test',
type: 'prepaid',
paymentPass: {
primaryAccountIdentifier: 'test',
primaryAccountNumberSuffix: 'test',
deviceAccountIdentifier: 'test',
deviceAccountNumberSuffix: 'test',
activationState: 'requiresActivation',
},
};

var paymentRequest = new PaymentRequest([validPaymentMethod()], validPaymentDetails());
paymentRequest.onapplepaypaymentmethodchanged = (event) => {
shouldBe("event.paymentMethod.displayName", "expectedPaymentMethod.displayName");
shouldBe("event.paymentMethod.network", "expectedPaymentMethod.network");
shouldBe("event.paymentMethod.type", "expectedPaymentMethod.type");
shouldBe("event.paymentMethod.paymentPass.primaryAccountIdentifier", "expectedPaymentMethod.paymentPass.primaryAccountIdentifier");
shouldBe("event.paymentMethod.paymentPass.primaryAccountNumberSuffix", "expectedPaymentMethod.paymentPass.primaryAccountNumberSuffix");
shouldBe("event.paymentMethod.paymentPass.deviceAccountIdentifier", "expectedPaymentMethod.paymentPass.deviceAccountIdentifier");
shouldBe("event.paymentMethod.paymentPass.deviceAccountNumberSuffix", "expectedPaymentMethod.paymentPass.deviceAccountNumberSuffix");
shouldBe("event.paymentMethod.paymentPass.activationState", "expectedPaymentMethod.paymentPass.activationState");

document.querySelector("button").remove();
finishJSTest();
};

paymentRequest.show();
internals.mockPaymentCoordinator.changePaymentMethod(expectedPaymentMethod);
}

window.onload = function() {
var button = document.querySelector("button");
let x = button.offsetLeft + 2;
let y = button.offsetTop + 2;
UIHelper.activateAt(x, y);
}

</script>
<button onclick='go()'>Go</button>
<script src="/resources/js-test-post.js"></script>
</body>
</html>
@@ -1,3 +1,54 @@
2017-10-24 Andy Estes <aestes@apple.com>

[Apple Pay] Implement a paymentmethodselected event for PaymentRequest
https://bugs.webkit.org/show_bug.cgi?id=178765

Reviewed by Tim Horton.

When the Apple Pay payment method changes, fire an applepaypaymentmethodchanged event on the
PaymentRequest object. The event has a paymentMethod property and an updateWith() method
which behaves identically to PaymentRequestUpdateEvent.updateWith().

Test: http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https.html

* DerivedSources.make:
* Modules/applepay/ApplePayPaymentMethod.idl:
* Modules/applepay/ApplePayPaymentMethodSelectedEvent.h:
* Modules/applepay/PaymentMethod.h:
(WebCore::PaymentMethod::PaymentMethod): Deleted.
(WebCore::PaymentMethod::pkPaymentMethod const): Deleted.
* Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
(WebCore::ApplePayPaymentHandler::detailsUpdated):
(WebCore::ApplePayPaymentHandler::paymentMethodUpdated):
(WebCore::ApplePayPaymentHandler::didSelectPaymentMethod):
* Modules/applepay/paymentrequest/ApplePayPaymentHandler.h:
* Modules/applepay/paymentrequest/ApplePayPaymentMethodUpdateEvent.cpp: Added.
(WebCore::ApplePayPaymentMethodUpdateEvent::ApplePayPaymentMethodUpdateEvent):
(WebCore::ApplePayPaymentMethodUpdateEvent::eventInterface const):
* Modules/applepay/paymentrequest/ApplePayPaymentMethodUpdateEvent.h: Added.
* Modules/applepay/paymentrequest/ApplePayPaymentMethodUpdateEvent.idl: Added.
* Modules/paymentrequest/PaymentHandler.h:
* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::shippingAddressChanged):
(WebCore::PaymentRequest::shippingOptionChanged):
(WebCore::PaymentRequest::dispatchEvent):
(WebCore::PaymentRequest::updateWith):
(WebCore::PaymentRequest::settleDetailsPromise):
(WebCore::PaymentRequest::dispatchUpdateEvent): Deleted.
* Modules/paymentrequest/PaymentRequest.h:
* Modules/paymentrequest/PaymentRequest.idl:
* Modules/paymentrequest/PaymentRequestUpdateEvent.cpp:
(WebCore::PaymentRequestUpdateEvent::updateWith):
* Modules/paymentrequest/PaymentRequestUpdateEvent.h:
* WebCore.xcodeproj/project.pbxproj:
* dom/EventNames.h:
* dom/EventNames.in:
* testing/MockPaymentCoordinator.cpp:
(WebCore::MockPaymentCoordinator::changePaymentMethod):
* testing/MockPaymentCoordinator.h:
* testing/MockPaymentCoordinator.idl:
* testing/MockPaymentMethod.h: Added.

2017-10-24 Youenn Fablet <youenn@apple.com>

ServiceWorkerClientFetch should return an error that is not null in case of failure
@@ -108,6 +108,7 @@ JS_BINDING_IDLS = \
$(WebCore)/Modules/applepay/ApplePayShippingMethodUpdate.idl \
$(WebCore)/Modules/applepay/ApplePayValidateMerchantEvent.idl \
$(WebCore)/Modules/applepay/paymentrequest/ApplePayMerchantValidationEvent.idl \
$(WebCore)/Modules/applepay/paymentrequest/ApplePayPaymentMethodUpdateEvent.idl \
$(WebCore)/Modules/applepay/paymentrequest/ApplePayRequest.idl \
$(WebCore)/Modules/beacon/NavigatorBeacon.idl \
$(WebCore)/Modules/cache/DOMWindowCaches.idl \
@@ -34,6 +34,7 @@

[
Conditional=APPLE_PAY,
ExportMacro=WEBCORE_EXPORT,
JSGenerateToJSObject
] dictionary ApplePayPaymentMethod {
DOMString displayName;
@@ -34,7 +34,7 @@ namespace WebCore {

class PaymentMethod;

class ApplePayPaymentMethodSelectedEvent final : public Event {
class ApplePayPaymentMethodSelectedEvent : public Event {
public:
static Ref<ApplePayPaymentMethodSelectedEvent> create(const AtomicString& type, const PaymentMethod& paymentMethod)
{
@@ -45,12 +45,13 @@ class ApplePayPaymentMethodSelectedEvent final : public Event {

const ApplePayPaymentMethod& paymentMethod() { return m_paymentMethod; }

private:
protected:
ApplePayPaymentMethodSelectedEvent(const AtomicString& type, const PaymentMethod&);

// Event.
EventInterface eventInterface() const override;

private:
const ApplePayPaymentMethod m_paymentMethod;
};

@@ -35,18 +35,17 @@ namespace WebCore {

struct ApplePayPaymentMethod;

class PaymentMethod {
class WEBCORE_EXPORT PaymentMethod {
public:
PaymentMethod()
{
}
PaymentMethod() = default;
virtual ~PaymentMethod() = default;

explicit PaymentMethod(PKPaymentMethod *pkPaymentMethod)
: m_pkPaymentMethod(pkPaymentMethod)
{
}

ApplePayPaymentMethod toApplePayPaymentMethod() const;
virtual ApplePayPaymentMethod toApplePayPaymentMethod() const;

PKPaymentMethod *pkPaymentMethod() const { return m_pkPaymentMethod.get(); }

@@ -32,6 +32,7 @@
#include "ApplePayMerchantCapability.h"
#include "ApplePayMerchantValidationEvent.h"
#include "ApplePayPayment.h"
#include "ApplePayPaymentMethodUpdateEvent.h"
#include "ApplePaySessionPaymentRequest.h"
#include "Document.h"
#include "EventNames.h"
@@ -44,6 +45,7 @@
#include "PaymentAuthorizationStatus.h"
#include "PaymentContact.h"
#include "PaymentCoordinator.h"
#include "PaymentMethod.h"
#include "PaymentRequestValidator.h"
#include "PaymentResponse.h"
#include "Settings.h"
@@ -267,6 +269,21 @@ static ExceptionOr<ApplePaySessionPaymentRequest::TotalAndLineItems> convertAndV
return ApplePaySessionPaymentRequest::TotalAndLineItems { total.releaseReturnValue(), lineItems.releaseReturnValue() };
}

ExceptionOr<void> ApplePayPaymentHandler::detailsUpdated(const AtomicString& eventType, const String& error)
{
if (eventType == eventNames().shippingaddresschangeEvent)
return shippingAddressUpdated(error);

if (eventType == eventNames().shippingoptionchangeEvent)
return shippingOptionUpdated();

if (eventType == eventNames().applepaypaymentmethodchangedEvent)
return paymentMethodUpdated();

ASSERT_NOT_REACHED();
return { };
}

ExceptionOr<void> ApplePayPaymentHandler::shippingAddressUpdated(const String& error)
{
ShippingContactUpdate update;
@@ -300,6 +317,19 @@ ExceptionOr<void> ApplePayPaymentHandler::shippingOptionUpdated()
return { };
}

ExceptionOr<void> ApplePayPaymentHandler::paymentMethodUpdated()
{
PaymentMethodUpdate update;

auto newTotalAndLineItems = convertAndValidate(m_paymentRequest->paymentDetails());
if (newTotalAndLineItems.hasException())
return newTotalAndLineItems.releaseException();
update.newTotalAndLineItems = newTotalAndLineItems.releaseReturnValue();

paymentCoordinator().completePaymentMethodSelection(WTFMove(update));
return { };
}

void ApplePayPaymentHandler::complete(std::optional<PaymentComplete>&& result)
{
if (!result) {
@@ -353,6 +383,12 @@ void ApplePayPaymentHandler::didSelectShippingContact(const PaymentContact& ship
m_paymentRequest->shippingAddressChanged(convert(shippingContact.toApplePayPaymentContact()));
}

void ApplePayPaymentHandler::didSelectPaymentMethod(const PaymentMethod& paymentMethod)
{
auto event = ApplePayPaymentMethodUpdateEvent::create(eventNames().applepaypaymentmethodchangedEvent, paymentMethod.toApplePayPaymentMethod(), m_paymentRequest.get());
m_paymentRequest->dispatchEvent(event.get());
}

} // namespace WebCore

#endif // ENABLE(APPLE_PAY) && ENABLE(PAYMENT_REQUEST)
@@ -51,21 +51,24 @@ class ApplePayPaymentHandler final : public PaymentHandler, public PaymentSessio
Document& document();
PaymentCoordinator& paymentCoordinator();

ExceptionOr<void> shippingAddressUpdated(const String& error);
ExceptionOr<void> shippingOptionUpdated();
ExceptionOr<void> paymentMethodUpdated();

// PaymentHandler
ExceptionOr<void> convertData(JSC::JSValue&&) final;
ExceptionOr<void> show() final;
void hide() final;
void canMakePayment(WTF::Function<void(bool)>&& completionHandler) final;
ExceptionOr<void> shippingAddressUpdated(const String& error) final;
ExceptionOr<void> shippingOptionUpdated() final;
ExceptionOr<void> detailsUpdated(const AtomicString& eventType, const String& error) final;
void complete(std::optional<PaymentComplete>&&) final;

// PaymentSession
void validateMerchant(const URL&) final;
void didAuthorizePayment(const Payment&) final;
void didSelectShippingMethod(const ApplePaySessionPaymentRequest::ShippingMethod&) final;
void didSelectShippingContact(const PaymentContact&) final;
void didSelectPaymentMethod(const PaymentMethod&) final { }
void didSelectPaymentMethod(const PaymentMethod&) final;
void didCancelPaymentSession() final { }

PaymentRequest::MethodIdentifier m_identifier;
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "config.h"
#include "ApplePayPaymentMethodUpdateEvent.h"

#if ENABLE(APPLE_PAY) && ENABLE(PAYMENT_REQUEST)

#include "PaymentRequest.h"

namespace WebCore {

ApplePayPaymentMethodUpdateEvent::ApplePayPaymentMethodUpdateEvent(const AtomicString& type, const ApplePayPaymentMethod& paymentMethod, PaymentRequest& paymentRequest)
: PaymentRequestUpdateEvent { type, paymentRequest }
, m_paymentMethod { paymentMethod }
{
}

EventInterface ApplePayPaymentMethodUpdateEvent::eventInterface() const
{
return ApplePayPaymentMethodUpdateEventInterfaceType;
}

} // namespace WebCore

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

0 comments on commit 33796ae

Please sign in to comment.