| /* |
| * Copyright (C) 2015-2019 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 "Document.h" |
| #include "LinkIconCollector.h" |
| #include "Logging.h" |
| #include "Page.h" |
| #include "PaymentAuthorizationStatus.h" |
| #include "PaymentCoordinatorClient.h" |
| #include "PaymentSession.h" |
| #include "UserContentProvider.h" |
| #include <wtf/CompletionHandler.h> |
| #include <wtf/URL.h> |
| |
| #undef RELEASE_LOG_ERROR_IF_ALLOWED |
| #undef RELEASE_LOG_IF_ALLOWED |
| #define RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(m_client.isAlwaysOnLoggingAllowed(), ApplePay, "%p - PaymentCoordinator::" fmt, this, ##__VA_ARGS__) |
| #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(m_client.isAlwaysOnLoggingAllowed(), 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); |
| RELEASE_LOG_IF_ALLOWED("supportsVersion(%d) -> %d", version, supportsVersion); |
| return supportsVersion; |
| } |
| |
| bool PaymentCoordinator::canMakePayments(Document& document) |
| { |
| auto canMakePayments = m_client.canMakePayments(); |
| RELEASE_LOG_IF_ALLOWED("canMakePayments() -> %d", canMakePayments); |
| |
| if (!canMakePayments) |
| return false; |
| |
| if (!setApplePayIsActiveIfAllowed(document)) |
| return false; |
| |
| return true; |
| } |
| |
| void PaymentCoordinator::canMakePaymentsWithActiveCard(Document& document, const String& merchantIdentifier, WTF::Function<void(bool)>&& completionHandler) |
| { |
| m_client.canMakePaymentsWithActiveCard(merchantIdentifier, document.domain(), [this, weakThis = makeWeakPtr(*this), document = makeWeakPtr(document), completionHandler = WTFMove(completionHandler)](bool canMakePayments) { |
| if (!weakThis) |
| return completionHandler(false); |
| |
| RELEASE_LOG_IF_ALLOWED("canMakePaymentsWithActiveCard() -> %d", canMakePayments); |
| |
| if (!canMakePayments) |
| return completionHandler(false); |
| |
| if (!document || !setApplePayIsActiveIfAllowed(*document)) |
| return completionHandler(false); |
| |
| completionHandler(true); |
| }); |
| } |
| |
| void PaymentCoordinator::openPaymentSetup(Document& document, const String& merchantIdentifier, WTF::Function<void(bool)>&& completionHandler) |
| { |
| RELEASE_LOG_IF_ALLOWED("openPaymentSetup()"); |
| m_client.openPaymentSetup(merchantIdentifier, document.domain(), WTFMove(completionHandler)); |
| } |
| |
| bool PaymentCoordinator::beginPaymentSession(Document& document, PaymentSession& paymentSession, const ApplePaySessionPaymentRequest& paymentRequest) |
| { |
| ASSERT(!m_activeSession); |
| |
| if (!setApplePayIsActiveIfAllowed(document)) |
| return false; |
| |
| Vector<URL> linkIconURLs; |
| for (auto& icon : LinkIconCollector { document }.iconsOfTypes({ LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon })) |
| linkIconURLs.append(icon.url); |
| |
| auto showPaymentUI = m_client.showPaymentUI(document.url(), linkIconURLs, paymentRequest); |
| RELEASE_LOG_IF_ALLOWED("beginPaymentSession() -> %d", showPaymentUI); |
| if (!showPaymentUI) |
| return false; |
| |
| m_activeSession = &paymentSession; |
| return true; |
| } |
| |
| void PaymentCoordinator::completeMerchantValidation(const PaymentMerchantSession& paymentMerchantSession) |
| { |
| ASSERT(m_activeSession); |
| RELEASE_LOG_IF_ALLOWED("completeMerchantValidation()"); |
| m_client.completeMerchantValidation(paymentMerchantSession); |
| } |
| |
| void PaymentCoordinator::completeShippingMethodSelection(Optional<ShippingMethodUpdate>&& update) |
| { |
| ASSERT(m_activeSession); |
| RELEASE_LOG_IF_ALLOWED("completeShippingMethodSelection()"); |
| m_client.completeShippingMethodSelection(WTFMove(update)); |
| } |
| |
| void PaymentCoordinator::completeShippingContactSelection(Optional<ShippingContactUpdate>&& update) |
| { |
| ASSERT(m_activeSession); |
| RELEASE_LOG_IF_ALLOWED("completeShippingContactSelection()"); |
| m_client.completeShippingContactSelection(WTFMove(update)); |
| } |
| |
| void PaymentCoordinator::completePaymentMethodSelection(Optional<PaymentMethodUpdate>&& update) |
| { |
| ASSERT(m_activeSession); |
| RELEASE_LOG_IF_ALLOWED("completePaymentMethodSelection()"); |
| m_client.completePaymentMethodSelection(WTFMove(update)); |
| } |
| |
| void PaymentCoordinator::completePaymentSession(Optional<PaymentAuthorizationResult>&& result) |
| { |
| ASSERT(m_activeSession); |
| |
| bool isFinalState = isFinalStateResult(result); |
| RELEASE_LOG_IF_ALLOWED("completePaymentSession() (isFinalState: %d)", isFinalState); |
| m_client.completePaymentSession(WTFMove(result)); |
| |
| if (!isFinalState) |
| return; |
| |
| m_activeSession = nullptr; |
| } |
| |
| void PaymentCoordinator::abortPaymentSession() |
| { |
| ASSERT(m_activeSession); |
| RELEASE_LOG_IF_ALLOWED("abortPaymentSession()"); |
| m_client.abortPaymentSession(); |
| m_activeSession = nullptr; |
| } |
| |
| void PaymentCoordinator::cancelPaymentSession() |
| { |
| ASSERT(m_activeSession); |
| RELEASE_LOG_IF_ALLOWED("cancelPaymentSession()"); |
| m_client.cancelPaymentSession(); |
| } |
| |
| void PaymentCoordinator::validateMerchant(URL&& validationURL) |
| { |
| if (!m_activeSession) { |
| // It's possible that the payment has been aborted already. |
| return; |
| } |
| |
| RELEASE_LOG_IF_ALLOWED("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; |
| } |
| |
| RELEASE_LOG_IF_ALLOWED("validateMerchant()"); |
| m_activeSession->didAuthorizePayment(payment); |
| } |
| |
| void PaymentCoordinator::didSelectPaymentMethod(const PaymentMethod& paymentMethod) |
| { |
| if (!m_activeSession) { |
| // It's possible that the payment has been aborted already. |
| return; |
| } |
| |
| RELEASE_LOG_IF_ALLOWED("didSelectPaymentMethod()"); |
| m_activeSession->didSelectPaymentMethod(paymentMethod); |
| } |
| |
| void PaymentCoordinator::didSelectShippingMethod(const ApplePaySessionPaymentRequest::ShippingMethod& shippingMethod) |
| { |
| if (!m_activeSession) { |
| // It's possible that the payment has been aborted already. |
| return; |
| } |
| |
| RELEASE_LOG_IF_ALLOWED("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; |
| } |
| |
| RELEASE_LOG_IF_ALLOWED("didSelectShippingContact()"); |
| m_activeSession->didSelectShippingContact(shippingContact); |
| } |
| |
| void PaymentCoordinator::didCancelPaymentSession(PaymentSessionError&& error) |
| { |
| if (!m_activeSession) { |
| // It's possible that the payment has been aborted already. |
| return; |
| } |
| |
| RELEASE_LOG_IF_ALLOWED("didCancelPaymentSession()"); |
| m_activeSession->didCancelPaymentSession(WTFMove(error)); |
| m_activeSession = nullptr; |
| } |
| |
| Optional<String> PaymentCoordinator::validatedPaymentNetwork(Document&, unsigned version, const String& paymentNetwork) const |
| { |
| if (version < 2 && equalIgnoringASCIICase(paymentNetwork, "jcb")) |
| return WTF::nullopt; |
| |
| if (version < 3 && equalIgnoringASCIICase(paymentNetwork, "carteBancaire")) |
| return WTF::nullopt; |
| |
| return m_client.validatedPaymentNetwork(paymentNetwork); |
| } |
| |
| bool PaymentCoordinator::shouldEnableApplePayAPIs(Document& document) const |
| { |
| if (m_client.supportsUnrestrictedApplePay()) |
| return true; |
| |
| bool shouldEnableAPIs = true; |
| document.page()->userContentProvider().forEachUserScript([&](DOMWrapperWorld&, const UserScript&) { |
| shouldEnableAPIs = false; |
| }); |
| |
| if (!shouldEnableAPIs) |
| RELEASE_LOG_IF_ALLOWED("shouldEnableApplePayAPIs() -> false (user scripts)"); |
| |
| return shouldEnableAPIs; |
| } |
| |
| bool PaymentCoordinator::setApplePayIsActiveIfAllowed(Document& document) const |
| { |
| auto hasEvaluatedUserAgentScripts = document.hasEvaluatedUserAgentScripts(); |
| auto isRunningUserScripts = document.isRunningUserScripts(); |
| auto supportsUnrestrictedApplePay = m_client.supportsUnrestrictedApplePay(); |
| |
| if (!supportsUnrestrictedApplePay && (hasEvaluatedUserAgentScripts || isRunningUserScripts)) { |
| ASSERT(!document.isApplePayActive()); |
| RELEASE_LOG_IF_ALLOWED("setApplePayIsActiveIfAllowed() -> false (hasEvaluatedUserAgentScripts: %d, isRunningUserScripts: %d)", hasEvaluatedUserAgentScripts, isRunningUserScripts); |
| return false; |
| } |
| |
| RELEASE_LOG_IF_ALLOWED("setApplePayIsActiveIfAllowed() -> true (supportsUnrestrictedApplePay: %d)", supportsUnrestrictedApplePay); |
| document.setApplePayIsActive(); |
| return true; |
| } |
| |
| bool PaymentCoordinator::shouldAllowUserAgentScripts(Document& document) const |
| { |
| if (m_client.supportsUnrestrictedApplePay() || !document.isApplePayActive()) |
| return true; |
| |
| ASSERT(!document.hasEvaluatedUserAgentScripts()); |
| ASSERT(!document.isRunningUserScripts()); |
| RELEASE_LOG_ERROR_IF_ALLOWED("shouldAllowUserAgentScripts() -> false (active session)"); |
| return false; |
| } |
| |
| } // namespace WebCore |
| |
| #undef RELEASE_LOG_ERROR_IF_ALLOWED |
| #undef RELEASE_LOG_IF_ALLOWED |
| |
| #endif // ENABLE(APPLE_PAY) |