| /* |
| * Copyright (C) 2015-2018 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 "WebPaymentCoordinatorProxy.h" |
| |
| #if ENABLE(APPLE_PAY) |
| |
| #include "WebPageProxy.h" |
| #include "WebPaymentCoordinatorMessages.h" |
| #include "WebPaymentCoordinatorProxyMessages.h" |
| #include "WebProcessProxy.h" |
| #include <WebCore/PaymentAuthorizationStatus.h> |
| |
| namespace WebKit { |
| |
| static WebPaymentCoordinatorProxy* activePaymentCoordinatorProxy; |
| |
| WebPaymentCoordinatorProxy::WebPaymentCoordinatorProxy(WebPageProxy& webPageProxy) |
| : m_webPageProxy(webPageProxy) |
| , m_state(State::Idle) |
| , m_merchantValidationState(MerchantValidationState::Idle) |
| { |
| m_webPageProxy.process().addMessageReceiver(Messages::WebPaymentCoordinatorProxy::messageReceiverName(), m_webPageProxy.pageID(), *this); |
| } |
| |
| WebPaymentCoordinatorProxy::~WebPaymentCoordinatorProxy() |
| { |
| if (activePaymentCoordinatorProxy == this) |
| activePaymentCoordinatorProxy = nullptr; |
| |
| if (m_state != State::Idle) |
| hidePaymentUI(); |
| |
| m_webPageProxy.process().removeMessageReceiver(Messages::WebPaymentCoordinatorProxy::messageReceiverName(), m_webPageProxy.pageID()); |
| } |
| |
| void WebPaymentCoordinatorProxy::availablePaymentNetworks(Vector<String>& networks) |
| { |
| networks = platformAvailablePaymentNetworks(); |
| } |
| |
| void WebPaymentCoordinatorProxy::canMakePayments(bool& reply) |
| { |
| reply = platformCanMakePayments(); |
| } |
| |
| void WebPaymentCoordinatorProxy::canMakePaymentsWithActiveCard(const String& merchantIdentifier, const String& domainName, uint64_t requestID) |
| { |
| auto weakThis = m_weakPtrFactory.createWeakPtr(*this); |
| platformCanMakePaymentsWithActiveCard(merchantIdentifier, domainName, [weakThis, requestID](bool canMakePayments) { |
| auto paymentCoordinatorProxy = weakThis.get(); |
| if (!paymentCoordinatorProxy) |
| return; |
| |
| paymentCoordinatorProxy->m_webPageProxy.send(Messages::WebPaymentCoordinator::CanMakePaymentsWithActiveCardReply(requestID, canMakePayments)); |
| }); |
| } |
| |
| void WebPaymentCoordinatorProxy::openPaymentSetup(const String& merchantIdentifier, const String& domainName, uint64_t requestID) |
| { |
| auto weakThis = m_weakPtrFactory.createWeakPtr(*this); |
| platformOpenPaymentSetup(merchantIdentifier, domainName, [weakThis, requestID](bool result) { |
| auto paymentCoordinatorProxy = weakThis.get(); |
| if (!paymentCoordinatorProxy) |
| return; |
| |
| paymentCoordinatorProxy->m_webPageProxy.send(Messages::WebPaymentCoordinator::OpenPaymentSetupReply(requestID, result)); |
| }); |
| } |
| |
| void WebPaymentCoordinatorProxy::showPaymentUI(const String& originatingURLString, const Vector<String>& linkIconURLStrings, const WebCore::ApplePaySessionPaymentRequest& paymentRequest, bool& result) |
| { |
| // FIXME: Make this a message check. |
| ASSERT(canBegin()); |
| |
| if (activePaymentCoordinatorProxy) { |
| activePaymentCoordinatorProxy->hidePaymentUI(); |
| activePaymentCoordinatorProxy->didCancelPaymentSession(); |
| } |
| |
| activePaymentCoordinatorProxy = this; |
| |
| m_state = State::Activating; |
| |
| WebCore::URL originatingURL(WebCore::URL(), originatingURLString); |
| |
| Vector<WebCore::URL> linkIconURLs; |
| for (const auto& linkIconURLString : linkIconURLStrings) |
| linkIconURLs.append(WebCore::URL(WebCore::URL(), linkIconURLString)); |
| |
| platformShowPaymentUI(originatingURL, linkIconURLs, paymentRequest, [this](bool result) { |
| ASSERT(m_state == State::Activating); |
| if (!result) { |
| didCancelPaymentSession(); |
| return; |
| } |
| |
| m_state = State::Active; |
| }); |
| |
| result = true; |
| } |
| |
| |
| void WebPaymentCoordinatorProxy::completeMerchantValidation(const WebCore::PaymentMerchantSession& paymentMerchantSession) |
| { |
| // It's possible that the payment has been canceled already. |
| if (m_state == State::Idle) |
| return; |
| |
| // FIXME: This should be a MESSAGE_CHECK. |
| ASSERT(m_merchantValidationState == MerchantValidationState::Validating); |
| |
| platformCompleteMerchantValidation(paymentMerchantSession); |
| m_merchantValidationState = MerchantValidationState::ValidationComplete; |
| } |
| |
| void WebPaymentCoordinatorProxy::completeShippingMethodSelection(const std::optional<WebCore::ShippingMethodUpdate>& update) |
| { |
| // It's possible that the payment has been canceled already. |
| if (m_state == State::Idle) |
| return; |
| |
| // FIXME: This should be a MESSAGE_CHECK. |
| ASSERT(m_state == State::ShippingMethodSelected); |
| |
| platformCompleteShippingMethodSelection(update); |
| m_state = State::Active; |
| } |
| |
| void WebPaymentCoordinatorProxy::completeShippingContactSelection(const std::optional<WebCore::ShippingContactUpdate>& update) |
| { |
| // It's possible that the payment has been canceled already. |
| if (m_state == State::Idle) |
| return; |
| |
| // FIXME: This should be a MESSAGE_CHECK. |
| ASSERT(m_state == State::ShippingContactSelected); |
| |
| platformCompleteShippingContactSelection(update); |
| m_state = State::Active; |
| } |
| |
| void WebPaymentCoordinatorProxy::completePaymentMethodSelection(const std::optional<WebCore::PaymentMethodUpdate>& update) |
| { |
| // It's possible that the payment has been canceled already. |
| if (m_state == State::Idle) |
| return; |
| |
| // FIXME: This should be a MESSAGE_CHECK. |
| ASSERT(m_state == State::PaymentMethodSelected); |
| |
| platformCompletePaymentMethodSelection(update); |
| m_state = State::Active; |
| } |
| |
| void WebPaymentCoordinatorProxy::completePaymentSession(const std::optional<WebCore::PaymentAuthorizationResult>& result) |
| { |
| // It's possible that the payment has been canceled already. |
| if (!canCompletePayment()) |
| return; |
| |
| bool isFinalStateResult = WebCore::isFinalStateResult(result); |
| |
| platformCompletePaymentSession(result); |
| |
| if (!isFinalStateResult) { |
| m_state = State::Active; |
| return; |
| } |
| |
| didReachFinalState(); |
| } |
| |
| void WebPaymentCoordinatorProxy::abortPaymentSession() |
| { |
| // It's possible that the payment has been canceled already. |
| if (!canAbort()) |
| return; |
| |
| hidePaymentUI(); |
| |
| didReachFinalState(); |
| } |
| |
| void WebPaymentCoordinatorProxy::cancelPaymentSession() |
| { |
| if (!canCancel()) |
| return; |
| |
| hidePaymentUI(); |
| didCancelPaymentSession(); |
| } |
| |
| void WebPaymentCoordinatorProxy::didCancelPaymentSession() |
| { |
| ASSERT(canCancel()); |
| |
| m_webPageProxy.send(Messages::WebPaymentCoordinator::DidCancelPaymentSession()); |
| |
| didReachFinalState(); |
| } |
| |
| void WebPaymentCoordinatorProxy::validateMerchant(const WebCore::URL& url) |
| { |
| ASSERT(m_merchantValidationState == MerchantValidationState::Idle); |
| |
| m_merchantValidationState = MerchantValidationState::Validating; |
| m_webPageProxy.send(Messages::WebPaymentCoordinator::ValidateMerchant(url.string())); |
| } |
| |
| void WebPaymentCoordinatorProxy::didAuthorizePayment(const WebCore::Payment& payment) |
| { |
| m_state = State::Authorized; |
| m_webPageProxy.send(Messages::WebPaymentCoordinator::DidAuthorizePayment(payment)); |
| } |
| |
| void WebPaymentCoordinatorProxy::didSelectShippingMethod(const WebCore::ApplePaySessionPaymentRequest::ShippingMethod& shippingMethod) |
| { |
| ASSERT(m_state == State::Active); |
| |
| m_state = State::ShippingMethodSelected; |
| m_webPageProxy.send(Messages::WebPaymentCoordinator::DidSelectShippingMethod(shippingMethod)); |
| } |
| |
| void WebPaymentCoordinatorProxy::didSelectShippingContact(const WebCore::PaymentContact& shippingContact) |
| { |
| ASSERT(m_state == State::Active); |
| |
| m_state = State::ShippingContactSelected; |
| m_webPageProxy.send(Messages::WebPaymentCoordinator::DidSelectShippingContact(shippingContact)); |
| } |
| |
| void WebPaymentCoordinatorProxy::didSelectPaymentMethod(const WebCore::PaymentMethod& paymentMethod) |
| { |
| ASSERT(m_state == State::Active); |
| |
| m_state = State::PaymentMethodSelected; |
| m_webPageProxy.send(Messages::WebPaymentCoordinator::DidSelectPaymentMethod(paymentMethod)); |
| } |
| |
| bool WebPaymentCoordinatorProxy::canBegin() const |
| { |
| switch (m_state) { |
| case State::Idle: |
| return true; |
| |
| case State::Activating: |
| case State::Active: |
| case State::Authorized: |
| case State::ShippingMethodSelected: |
| case State::ShippingContactSelected: |
| case State::PaymentMethodSelected: |
| return false; |
| } |
| } |
| |
| bool WebPaymentCoordinatorProxy::canCancel() const |
| { |
| switch (m_state) { |
| case State::Activating: |
| case State::Active: |
| case State::Authorized: |
| case State::ShippingMethodSelected: |
| case State::ShippingContactSelected: |
| case State::PaymentMethodSelected: |
| return true; |
| |
| case State::Idle: |
| return false; |
| } |
| } |
| |
| bool WebPaymentCoordinatorProxy::canCompletePayment() const |
| { |
| switch (m_state) { |
| case State::Authorized: |
| return true; |
| |
| case State::Idle: |
| case State::Activating: |
| case State::Active: |
| case State::ShippingMethodSelected: |
| case State::ShippingContactSelected: |
| case State::PaymentMethodSelected: |
| return false; |
| } |
| } |
| |
| bool WebPaymentCoordinatorProxy::canAbort() const |
| { |
| switch (m_state) { |
| case State::Activating: |
| case State::Active: |
| case State::Authorized: |
| case State::ShippingMethodSelected: |
| case State::ShippingContactSelected: |
| case State::PaymentMethodSelected: |
| return true; |
| |
| case State::Idle: |
| return false; |
| } |
| } |
| |
| void WebPaymentCoordinatorProxy::didReachFinalState() |
| { |
| m_state = State::Idle; |
| m_merchantValidationState = MerchantValidationState::Idle; |
| |
| ASSERT(activePaymentCoordinatorProxy == this); |
| activePaymentCoordinatorProxy = nullptr; |
| } |
| |
| } |
| |
| #endif |