blob: d710bb003adf327ece602e46c587956a1f0760ec [file] [log] [blame]
/*
* Copyright (C) 2015-2020 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 "PaymentCoordinator.h"
#if ENABLE(APPLE_PAY)
#include "ApplePayCouponCodeUpdate.h"
#include "ApplePayPaymentMethodUpdate.h"
#include "ApplePayShippingContactUpdate.h"
#include "ApplePayShippingMethod.h"
#include "ApplePayShippingMethodUpdate.h"
#include "Document.h"
#include "ExceptionDetails.h"
#include "LinkIconCollector.h"
#include "Logging.h"
#include "Page.h"
#include "PaymentCoordinatorClient.h"
#include "PaymentSession.h"
#include "UserContentProvider.h"
#include <wtf/CompletionHandler.h>
#include <wtf/URL.h>
#define PAYMENT_COORDINATOR_RELEASE_LOG_ERROR(fmt, ...) RELEASE_LOG_ERROR(ApplePay, "%p - PaymentCoordinator::" fmt, this, ##__VA_ARGS__)
#define PAYMENT_COORDINATOR_RELEASE_LOG(fmt, ...) RELEASE_LOG(ApplePay, "%p - PaymentCoordinator::" fmt, this, ##__VA_ARGS__)
namespace WebCore {
PaymentCoordinator::PaymentCoordinator(PaymentCoordinatorClient& client)
: m_client { client }
{
}
PaymentCoordinator::~PaymentCoordinator()
{
m_client.paymentCoordinatorDestroyed();
}
bool PaymentCoordinator::supportsVersion(Document&, unsigned version) const
{
auto supportsVersion = m_client.supportsVersion(version);
PAYMENT_COORDINATOR_RELEASE_LOG("supportsVersion(%d) -> %d", version, supportsVersion);
return supportsVersion;
}
bool PaymentCoordinator::canMakePayments()
{
auto canMakePayments = m_client.canMakePayments();
PAYMENT_COORDINATOR_RELEASE_LOG("canMakePayments() -> %d", canMakePayments);
return canMakePayments;
}
void PaymentCoordinator::canMakePaymentsWithActiveCard(Document& document, const String& merchantIdentifier, Function<void(bool)>&& completionHandler)
{
m_client.canMakePaymentsWithActiveCard(merchantIdentifier, document.domain(), [this, weakThis = WeakPtr { *this }, document = WeakPtr { document }, completionHandler = WTFMove(completionHandler)](bool canMakePayments) {
if (!weakThis)
return completionHandler(false);
PAYMENT_COORDINATOR_RELEASE_LOG("canMakePaymentsWithActiveCard() -> %d", canMakePayments);
if (!canMakePayments)
return completionHandler(false);
if (!document)
return completionHandler(false);
completionHandler(true);
});
}
void PaymentCoordinator::openPaymentSetup(Document& document, const String& merchantIdentifier, Function<void(bool)>&& completionHandler)
{
PAYMENT_COORDINATOR_RELEASE_LOG("openPaymentSetup()");
m_client.openPaymentSetup(merchantIdentifier, document.domain(), WTFMove(completionHandler));
}
bool PaymentCoordinator::beginPaymentSession(Document& document, PaymentSession& paymentSession, const ApplePaySessionPaymentRequest& paymentRequest)
{
ASSERT(!m_activeSession);
auto linkIconURLs = LinkIconCollector { document }.iconsOfTypes({ LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon }).map([](auto& icon) {
return icon.url;
});
auto showPaymentUI = m_client.showPaymentUI(document.url(), WTFMove(linkIconURLs), paymentRequest);
PAYMENT_COORDINATOR_RELEASE_LOG("beginPaymentSession() -> %d", showPaymentUI);
if (!showPaymentUI)
return false;
m_activeSession = &paymentSession;
return true;
}
void PaymentCoordinator::completeMerchantValidation(const PaymentMerchantSession& paymentMerchantSession)
{
ASSERT(m_activeSession);
PAYMENT_COORDINATOR_RELEASE_LOG("completeMerchantValidation()");
m_client.completeMerchantValidation(paymentMerchantSession);
}
void PaymentCoordinator::completeShippingMethodSelection(std::optional<ApplePayShippingMethodUpdate>&& update)
{
ASSERT(m_activeSession);
PAYMENT_COORDINATOR_RELEASE_LOG("completeShippingMethodSelection()");
m_client.completeShippingMethodSelection(WTFMove(update));
}
void PaymentCoordinator::completeShippingContactSelection(std::optional<ApplePayShippingContactUpdate>&& update)
{
ASSERT(m_activeSession);
PAYMENT_COORDINATOR_RELEASE_LOG("completeShippingContactSelection()");
m_client.completeShippingContactSelection(WTFMove(update));
}
void PaymentCoordinator::completePaymentMethodSelection(std::optional<ApplePayPaymentMethodUpdate>&& update)
{
ASSERT(m_activeSession);
PAYMENT_COORDINATOR_RELEASE_LOG("completePaymentMethodSelection()");
m_client.completePaymentMethodSelection(WTFMove(update));
}
#if ENABLE(APPLE_PAY_COUPON_CODE)
void PaymentCoordinator::completeCouponCodeChange(std::optional<ApplePayCouponCodeUpdate>&& update)
{
ASSERT(m_activeSession);
PAYMENT_COORDINATOR_RELEASE_LOG("completeCouponCodeChange()");
m_client.completeCouponCodeChange(WTFMove(update));
}
#endif // ENABLE(APPLE_PAY_COUPON_CODE)
void PaymentCoordinator::completePaymentSession(ApplePayPaymentAuthorizationResult&& result)
{
ASSERT(m_activeSession);
bool isFinalState = result.isFinalState();
PAYMENT_COORDINATOR_RELEASE_LOG("completePaymentSession() (isFinalState: %d)", isFinalState);
m_client.completePaymentSession(WTFMove(result));
if (!isFinalState)
return;
m_activeSession = nullptr;
}
void PaymentCoordinator::abortPaymentSession()
{
ASSERT(m_activeSession);
PAYMENT_COORDINATOR_RELEASE_LOG("abortPaymentSession()");
m_client.abortPaymentSession();
m_activeSession = nullptr;
}
void PaymentCoordinator::cancelPaymentSession()
{
ASSERT(m_activeSession);
PAYMENT_COORDINATOR_RELEASE_LOG("cancelPaymentSession()");
m_client.cancelPaymentSession();
}
void PaymentCoordinator::validateMerchant(URL&& validationURL)
{
if (!m_activeSession) {
// It's possible that the payment has been aborted already.
return;
}
PAYMENT_COORDINATOR_RELEASE_LOG("validateMerchant()");
m_activeSession->validateMerchant(WTFMove(validationURL));
}
void PaymentCoordinator::didAuthorizePayment(const Payment& payment)
{
if (!m_activeSession) {
// It's possible that the payment has been aborted already.
return;
}
PAYMENT_COORDINATOR_RELEASE_LOG("didAuthorizePayment()");
m_activeSession->didAuthorizePayment(payment);
}
void PaymentCoordinator::didSelectPaymentMethod(const PaymentMethod& paymentMethod)
{
if (!m_activeSession) {
// It's possible that the payment has been aborted already.
return;
}
PAYMENT_COORDINATOR_RELEASE_LOG("didSelectPaymentMethod()");
m_activeSession->didSelectPaymentMethod(paymentMethod);
}
void PaymentCoordinator::didSelectShippingMethod(const ApplePayShippingMethod& shippingMethod)
{
if (!m_activeSession) {
// It's possible that the payment has been aborted already.
return;
}
PAYMENT_COORDINATOR_RELEASE_LOG("didSelectShippingMethod()");
m_activeSession->didSelectShippingMethod(shippingMethod);
}
void PaymentCoordinator::didSelectShippingContact(const PaymentContact& shippingContact)
{
if (!m_activeSession) {
// It's possible that the payment has been aborted already.
return;
}
PAYMENT_COORDINATOR_RELEASE_LOG("didSelectShippingContact()");
m_activeSession->didSelectShippingContact(shippingContact);
}
#if ENABLE(APPLE_PAY_COUPON_CODE)
void PaymentCoordinator::didChangeCouponCode(String&& couponCode)
{
if (!m_activeSession) {
// It's possible that the payment has been aborted already.
return;
}
PAYMENT_COORDINATOR_RELEASE_LOG("didChangeCouponCode()");
m_activeSession->didChangeCouponCode(WTFMove(couponCode));
}
#endif // ENABLE(APPLE_PAY_COUPON_CODE)
void PaymentCoordinator::didCancelPaymentSession(PaymentSessionError&& error)
{
if (!m_activeSession) {
// It's possible that the payment has been aborted already.
return;
}
PAYMENT_COORDINATOR_RELEASE_LOG("didCancelPaymentSession()");
m_activeSession->didCancelPaymentSession(WTFMove(error));
m_activeSession = nullptr;
}
std::optional<String> PaymentCoordinator::validatedPaymentNetwork(Document&, unsigned version, const String& paymentNetwork) const
{
if (version < 2 && equalLettersIgnoringASCIICase(paymentNetwork, "jcb"_s))
return std::nullopt;
if (version < 3 && equalIgnoringASCIICase(paymentNetwork, "carteBancaire"_s))
return std::nullopt;
return m_client.validatedPaymentNetwork(paymentNetwork);
}
void PaymentCoordinator::getSetupFeatures(const ApplePaySetupConfiguration& configuration, const URL& url, CompletionHandler<void(Vector<Ref<ApplePaySetupFeature>>&&)>&& completionHandler)
{
PAYMENT_COORDINATOR_RELEASE_LOG("getSetupFeatures()");
m_client.getSetupFeatures(configuration, url, [this, weakThis = WeakPtr { *this }, completionHandler = WTFMove(completionHandler)](Vector<Ref<ApplePaySetupFeature>>&& features) mutable {
if (!weakThis)
return;
PAYMENT_COORDINATOR_RELEASE_LOG("getSetupFeatures() completed (features: %zu)", features.size());
completionHandler(WTFMove(features));
});
}
void PaymentCoordinator::beginApplePaySetup(const ApplePaySetupConfiguration& configuration, const URL& url, Vector<RefPtr<ApplePaySetupFeature>>&& features, CompletionHandler<void(bool)>&& completionHandler)
{
PAYMENT_COORDINATOR_RELEASE_LOG("beginApplePaySetup()");
m_client.beginApplePaySetup(configuration, url, WTFMove(features), [this, weakThis = WeakPtr { *this }, completionHandler = WTFMove(completionHandler)](bool success) mutable {
if (!weakThis)
return;
PAYMENT_COORDINATOR_RELEASE_LOG("beginApplePaySetup() completed (success: %d)", success);
completionHandler(success);
});
}
void PaymentCoordinator::endApplePaySetup()
{
PAYMENT_COORDINATOR_RELEASE_LOG("endApplePaySetup()");
m_client.endApplePaySetup();
}
} // namespace WebCore
#undef PAYMENT_COORDINATOR_RELEASE_LOG_ERROR
#undef PAYMENT_COORDINATOR_RELEASE_LOG
#endif // ENABLE(APPLE_PAY)