/*
 * Copyright (C) 2017-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 "PaymentRequest.h"

#if ENABLE(PAYMENT_REQUEST)

#include "ApplePayPaymentHandler.h"
#include "Document.h"
#include "EventNames.h"
#include "JSDOMPromise.h"
#include "JSDOMPromiseDeferred.h"
#include "JSPaymentDetailsUpdate.h"
#include "JSPaymentResponse.h"
#include "Page.h"
#include "PaymentAddress.h"
#include "PaymentCoordinator.h"
#include "PaymentCurrencyAmount.h"
#include "PaymentDetailsInit.h"
#include "PaymentHandler.h"
#include "PaymentMethodChangeEvent.h"
#include "PaymentMethodData.h"
#include "PaymentOptions.h"
#include "PaymentRequestUpdateEvent.h"
#include "PaymentRequestUtilities.h"
#include "PaymentValidationErrors.h"
#include "ScriptController.h"
#include <JavaScriptCore/JSONObject.h>
#include <JavaScriptCore/ThrowScope.h>
#include <wtf/ASCIICType.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/RunLoop.h>
#include <wtf/Scope.h>
#include <wtf/UUID.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(PaymentRequest);

// Implements the IsWellFormedCurrencyCode abstract operation from ECMA 402
// https://tc39.github.io/ecma402/#sec-iswellformedcurrencycode
static bool isWellFormedCurrencyCode(const String& currency)
{
    if (currency.length() == 3)
        return currency.isAllSpecialCharacters<isASCIIAlpha>();
    return false;
}

template<typename T>
static ExceptionOr<String> checkAndCanonicalizeData(ScriptExecutionContext& context, T& value)
{
    String serializedData;
    if (value.data) {
        auto* globalObject = context.globalObject();
        auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
        serializedData = JSONStringify(globalObject, value.data.get(), 0);
        if (scope.exception())
            return Exception { ExistingExceptionError };
        value.data.clear();
    }
    return { WTFMove(serializedData) };
}

// Implements the "check and canonicalize amount" validity checker
// https://www.w3.org/TR/payment-request/#dfn-check-and-canonicalize-amount
static ExceptionOr<void> checkAndCanonicalizeAmount(PaymentCurrencyAmount& amount)
{
    if (!isWellFormedCurrencyCode(amount.currency))
        return Exception { RangeError, makeString("\"", amount.currency, "\" is not a valid currency code.") };

    if (!isValidDecimalMonetaryValue(amount.value))
        return Exception { TypeError, makeString("\"", amount.value, "\" is not a valid decimal monetary value.") };

    amount.currency = amount.currency.convertToASCIIUppercase();
    return { };
}

enum class NegativeAmountAllowed { Yes, No };
static ExceptionOr<void> checkAndCanonicalizePaymentItem(PaymentItem& item, NegativeAmountAllowed negativeAmountAllowed)
{
    auto exception = checkAndCanonicalizeAmount(item.amount);
    if (exception.hasException())
        return exception.releaseException();

    if (negativeAmountAllowed == NegativeAmountAllowed::No && item.amount.value[0] == '-')
        return Exception { TypeError, "Total currency values cannot be negative."_s };

    return { };
}

// Implements the "check and canonicalize total" validity checker
// https://www.w3.org/TR/payment-request/#dfn-check-and-canonicalize-total
static ExceptionOr<void> checkAndCanonicalizeTotal(PaymentItem& total)
{
    return checkAndCanonicalizePaymentItem(total, NegativeAmountAllowed::No);
}

// Implements "validate a standardized payment method identifier"
// https://www.w3.org/TR/payment-method-id/#validity-0
static bool isValidStandardizedPaymentMethodIdentifier(StringView identifier)
{
    enum class State {
        Start,
        Hyphen,
        LowerAlpha,
        Digit,
    };

    auto state = State::Start;
    for (auto character : identifier.codeUnits()) {
        switch (state) {
        case State::Start:
        case State::Hyphen:
            if (isASCIILower(character)) {
                state = State::LowerAlpha;
                break;
            }

            return false;

        case State::LowerAlpha:
        case State::Digit:
            if (isASCIILower(character)) {
                state = State::LowerAlpha;
                break;
            }

            if (isASCIIDigit(character)) {
                state = State::Digit;
                break;
            }

            if (character == '-') {
                state = State::Hyphen;
                break;
            }

            return false;
        }
    }

    return state == State::LowerAlpha || state == State::Digit;
}

// Implements "validate a URL-based payment method identifier"
// https://www.w3.org/TR/payment-method-id/#validation
static bool isValidURLBasedPaymentMethodIdentifier(const URL& url)
{
    return url.protocolIs("https") && !url.hasCredentials();
}

// Implements "validate a payment method identifier"
// https://www.w3.org/TR/payment-method-id/#validity
std::optional<PaymentRequest::MethodIdentifier> convertAndValidatePaymentMethodIdentifier(const String& identifier)
{
    URL url { URL(), identifier };
    if (!url.isValid()) {
        if (isValidStandardizedPaymentMethodIdentifier(identifier))
            return { identifier };
        return std::nullopt;
    }

    if (isValidURLBasedPaymentMethodIdentifier(url))
        return { WTFMove(url) };

    return std::nullopt;
}

enum class IsUpdate {
    No,
    Yes,
};

static ExceptionOr<std::tuple<String, Vector<String>>> checkAndCanonicalizeDetails(ScriptExecutionContext& context, PaymentDetailsBase& details, bool requestShipping, IsUpdate isUpdate)
{
    if (details.displayItems) {
        for (auto& item : *details.displayItems) {
            auto paymentItemResult = checkAndCanonicalizePaymentItem(item, NegativeAmountAllowed::Yes);
            if (paymentItemResult.hasException())
                return paymentItemResult.releaseException();
        }
    }

    String selectedShippingOption;
    if (requestShipping) {
        if (details.shippingOptions) {
            HashSet<String> seenShippingOptionIDs;
            bool didLog = false;
            for (auto& shippingOption : *details.shippingOptions) {
                auto exception = checkAndCanonicalizeAmount(shippingOption.amount);
                if (exception.hasException())
                    return exception.releaseException();

                auto addResult = seenShippingOptionIDs.add(shippingOption.id);
                if (!addResult.isNewEntry)
                    return Exception { TypeError, "Shipping option IDs must be unique." };

#if ENABLE(PAYMENT_REQUEST_SELECTED_SHIPPING_OPTION)
                if (shippingOption.selected)
                    selectedShippingOption = shippingOption.id;
                UNUSED_PARAM(context);
                UNUSED_VARIABLE(didLog);
#else
                if (!selectedShippingOption)
                    selectedShippingOption = shippingOption.id;
                else if (!didLog && shippingOption.selected) {
                    context.addConsoleMessage(JSC::MessageSource::PaymentRequest, JSC::MessageLevel::Warning, "WebKit currently uses the first shipping option even if other shipping options are marked as selected."_s);
                    didLog = true;
                }
#endif
            }
        } else if (isUpdate == IsUpdate::No)
            details.shippingOptions = { { } };
    } else if (isUpdate == IsUpdate::No)
        details.shippingOptions = std::nullopt;

    Vector<String> serializedModifierData;
    if (details.modifiers) {
        serializedModifierData.reserveInitialCapacity(details.modifiers->size());
        for (auto& modifier : *details.modifiers) {
            if (isUpdate == IsUpdate::Yes) {
                auto paymentMethodIdentifier = convertAndValidatePaymentMethodIdentifier(modifier.supportedMethods);
                if (!paymentMethodIdentifier)
                    return Exception { RangeError, makeString('"', modifier.supportedMethods, "\" is an invalid payment method identifier.") };
            }

            if (modifier.total) {
                auto totalResult = checkAndCanonicalizeTotal(*modifier.total);
                if (totalResult.hasException())
                    return totalResult.releaseException();
            }

            for (auto& item : modifier.additionalDisplayItems) {
                auto paymentItemResult = checkAndCanonicalizePaymentItem(item, NegativeAmountAllowed::Yes);
                if (paymentItemResult.hasException())
                    return paymentItemResult.releaseException();
            }

            String serializedData;
            if (modifier.data) {
                auto dataResult = checkAndCanonicalizeData(context, modifier);
                if (dataResult.hasException())
                    return dataResult.releaseException();

                serializedData = dataResult.releaseReturnValue();
            }
            serializedModifierData.uncheckedAppend(WTFMove(serializedData));
        }
    } else if (isUpdate == IsUpdate::No)
        details.modifiers = { { } };

    return std::make_tuple(WTFMove(selectedShippingOption), WTFMove(serializedModifierData));
}

static ExceptionOr<JSC::JSValue> parse(ScriptExecutionContext& context, const String& string)
{
    auto scope = DECLARE_THROW_SCOPE(context.vm());
    JSC::JSValue data = JSONParse(context.globalObject(), string);
    if (scope.exception())
        return Exception { ExistingExceptionError };
    return data;
}

static String stringify(const PaymentRequest::MethodIdentifier& identifier)
{
    return WTF::switchOn(identifier,
        [] (const String& string) { return string; },
        [] (const URL& url) { return url.string(); }
    );
}

// Implements the PaymentRequest Constructor
// https://www.w3.org/TR/payment-request/#constructor
ExceptionOr<Ref<PaymentRequest>> PaymentRequest::create(Document& document, Vector<PaymentMethodData>&& methodData, PaymentDetailsInit&& details, PaymentOptions&& options)
{
    auto canCreateSession = PaymentHandler::canCreateSession(document);
    if (canCreateSession.hasException())
        return canCreateSession.releaseException();

    if (details.id.isNull())
        details.id = createCanonicalUUIDString();

    if (methodData.isEmpty())
        return Exception { TypeError, "At least one payment method is required."_s };

    Vector<Method> serializedMethodData;
    serializedMethodData.reserveInitialCapacity(methodData.size());
    HashSet<String> seenMethodIDs;
    for (auto& paymentMethod : methodData) {
        auto identifier = convertAndValidatePaymentMethodIdentifier(paymentMethod.supportedMethods);
        if (!identifier)
            return Exception { RangeError, makeString('"', paymentMethod.supportedMethods, "\" is an invalid payment method identifier.") };

        if (!seenMethodIDs.add(stringify(*identifier)))
            return Exception { RangeError, "Payment method IDs must be unique."_s };

        String serializedData;
        if (paymentMethod.data) {
            auto scope = DECLARE_THROW_SCOPE(document.globalObject()->vm());
            serializedData = JSONStringify(document.globalObject(), paymentMethod.data.get(), 0);
            if (scope.exception())
                return Exception { ExistingExceptionError };
            
            auto parsedDataOrException = parse(document, serializedData);
            if (parsedDataOrException.hasException())
                return parsedDataOrException.releaseException();
            
            auto exception = PaymentHandler::validateData(document, parsedDataOrException.releaseReturnValue(), *identifier);
            if (exception.hasException())
                return exception.releaseException();
        }
        serializedMethodData.uncheckedAppend({ WTFMove(*identifier), WTFMove(serializedData) });
    }

    auto totalResult = checkAndCanonicalizeTotal(details.total);
    if (totalResult.hasException())
        return totalResult.releaseException();

    auto detailsResult = checkAndCanonicalizeDetails(document, details, options.requestShipping, IsUpdate::No);
    if (detailsResult.hasException())
        return detailsResult.releaseException();

    auto shippingOptionAndModifierData = detailsResult.releaseReturnValue();
    return adoptRef(*new PaymentRequest(document, WTFMove(options), WTFMove(details), WTFMove(std::get<1>(shippingOptionAndModifierData)), WTFMove(serializedMethodData), WTFMove(std::get<0>(shippingOptionAndModifierData))));
}

bool PaymentRequest::enabledForContext(ScriptExecutionContext& context)
{
    return PaymentHandler::enabledForContext(context);
}

PaymentRequest::PaymentRequest(Document& document, PaymentOptions&& options, PaymentDetailsInit&& details, Vector<String>&& serializedModifierData, Vector<Method>&& serializedMethodData, String&& selectedShippingOption)
    : ActiveDOMObject { document }
    , m_options { WTFMove(options) }
    , m_details { WTFMove(details) }
    , m_serializedModifierData { WTFMove(serializedModifierData) }
    , m_serializedMethodData { WTFMove(serializedMethodData) }
    , m_shippingOption { WTFMove(selectedShippingOption) }
{
    suspendIfNeeded();
}

PaymentRequest::~PaymentRequest()
{
    ASSERT(!hasPendingActivity());
    ASSERT(!m_activePaymentHandler);
}

// https://www.w3.org/TR/payment-request/#show-method
void PaymentRequest::show(Document& document, RefPtr<DOMPromise>&& detailsPromise, ShowPromise&& promise)
{
    if (!document.frame()) {
        promise.reject(Exception { AbortError });
        return;
    }

    auto* window = document.frame()->window();
    if (!window || !window->consumeTransientActivation()) {
        promise.reject(Exception { SecurityError, "show() must be triggered by user activation." });
        return;
    }

    if (m_state != State::Created) {
        promise.reject(Exception { InvalidStateError });
        return;
    }

    if (PaymentHandler::hasActiveSession(document)) {
        promise.reject(Exception { AbortError });
        m_state = State::Closed;
        return;
    }

    m_state = State::Interactive;
    ASSERT(!m_showPromise);
    m_showPromise = makeUnique<ShowPromise>(WTFMove(promise));

    RefPtr<PaymentHandler> selectedPaymentHandler;
    for (auto& paymentMethod : m_serializedMethodData) {
        auto data = parse(document, paymentMethod.serializedData);
        if (data.hasException()) {
            settleShowPromise(data.releaseException());
            return;
        }

        auto handler = PaymentHandler::create(document, *this, paymentMethod.identifier);
        if (!handler)
            continue;

        auto result = handler->convertData(data.releaseReturnValue());
        if (result.hasException()) {
            settleShowPromise(result.releaseException());
            return;
        }

        if (!selectedPaymentHandler)
            selectedPaymentHandler = WTFMove(handler);
    }

    if (!selectedPaymentHandler) {
        settleShowPromise(Exception { NotSupportedError });
        return;
    }

    auto exception = selectedPaymentHandler->show(document);
    if (exception.hasException()) {
        settleShowPromise(exception.releaseException());
        return;
    }

    ASSERT(!m_activePaymentHandler);
    m_activePaymentHandler = PaymentHandlerWithPendingActivity { selectedPaymentHandler.releaseNonNull(), makePendingActivity(*this) };

    if (!detailsPromise)
        return;

    exception = updateWith(UpdateReason::ShowDetailsResolved, detailsPromise.releaseNonNull());
    ASSERT(!exception.hasException());
}

void PaymentRequest::abortWithException(Exception&& exception)
{
    ASSERT(m_state == State::Interactive);
    closeActivePaymentHandler();

    if (m_response)
        m_response->abortWithException(WTFMove(exception));
    else
        settleShowPromise(WTFMove(exception));
}

void PaymentRequest::settleShowPromise(ExceptionOr<PaymentResponse&>&& result)
{
    if (auto showPromise = std::exchange(m_showPromise, nullptr))
        showPromise->settle(WTFMove(result));
}

void PaymentRequest::closeActivePaymentHandler()
{
    if (auto activePaymentHandler = std::exchange(m_activePaymentHandler, std::nullopt))
        activePaymentHandler->paymentHandler->hide();

    m_isUpdating = false;
    m_state = State::Closed;
}

void PaymentRequest::stop()
{
    closeActivePaymentHandler();
    settleShowPromise(Exception { AbortError });
}

void PaymentRequest::suspend(ReasonForSuspension reason)
{
    if (reason != ReasonForSuspension::BackForwardCache)
        return;

    if (!m_activePaymentHandler) {
        ASSERT(!m_showPromise);
        ASSERT(m_state != State::Interactive);
        return;
    }

    stop();
}

// https://www.w3.org/TR/payment-request/#abort()-method
void PaymentRequest::abort(AbortPromise&& promise)
{
    if (m_response && m_response->hasRetryPromise()) {
        promise.reject(Exception { InvalidStateError });
        return;
    }

    if (m_state != State::Interactive) {
        promise.reject(Exception { InvalidStateError });
        return;
    }

    if (m_activePaymentHandler && !activePaymentHandler()->canAbortSession()) {
        promise.reject(Exception { InvalidStateError });
        return;
    }

    abortWithException(Exception { AbortError });
    promise.resolve();
}

// https://www.w3.org/TR/payment-request/#canmakepayment()-method
void PaymentRequest::canMakePayment(Document& document, CanMakePaymentPromise&& promise)
{
    if (m_state != State::Created) {
        promise.reject(Exception { InvalidStateError });
        return;
    }

    for (auto& paymentMethod : m_serializedMethodData) {
        auto handler = PaymentHandler::create(document, *this, paymentMethod.identifier);
        if (!handler)
            continue;

        handler->canMakePayment(document, [promise = WTFMove(promise)](bool canMakePayment) mutable {
            promise.resolve(canMakePayment);
        });
        return;
    }

    promise.resolve(false);
}

const String& PaymentRequest::id() const
{
    return m_details.id;
}

std::optional<PaymentShippingType> PaymentRequest::shippingType() const
{
    if (m_options.requestShipping)
        return m_options.shippingType;
    return std::nullopt;
}

void PaymentRequest::shippingAddressChanged(Ref<PaymentAddress>&& shippingAddress)
{
    whenDetailsSettled([this, protectedThis = Ref { *this }, shippingAddress = WTFMove(shippingAddress)]() mutable {
        m_shippingAddress = WTFMove(shippingAddress);
        dispatchAndCheckUpdateEvent(PaymentRequestUpdateEvent::create(eventNames().shippingaddresschangeEvent));
    });
}

void PaymentRequest::shippingOptionChanged(const String& shippingOption)
{
    whenDetailsSettled([this, protectedThis = Ref { *this }, shippingOption]() mutable {
        m_shippingOption = shippingOption;
        dispatchAndCheckUpdateEvent(PaymentRequestUpdateEvent::create(eventNames().shippingoptionchangeEvent));
    });
}

void PaymentRequest::paymentMethodChanged(const String& methodName, PaymentMethodChangeEvent::MethodDetailsFunction&& methodDetailsFunction)
{
    whenDetailsSettled([this, protectedThis = Ref { *this }, methodName, methodDetailsFunction = WTFMove(methodDetailsFunction)]() mutable {
        auto& eventName = eventNames().paymentmethodchangeEvent;
        if (hasEventListeners(eventName))
            dispatchAndCheckUpdateEvent(PaymentMethodChangeEvent::create(eventName, methodName, WTFMove(methodDetailsFunction)));
        else
            activePaymentHandler()->detailsUpdated(UpdateReason::PaymentMethodChanged, { }, { }, { }, { });
    });
}

ExceptionOr<void> PaymentRequest::updateWith(UpdateReason reason, Ref<DOMPromise>&& promise)
{
    if (m_state != State::Interactive)
        return Exception { InvalidStateError };

    if (m_isUpdating)
        return Exception { InvalidStateError };

    m_isUpdating = true;

    ASSERT(!m_detailsPromise);
    m_detailsPromise = WTFMove(promise);
    m_detailsPromise->whenSettled([this, protectedThis = Ref { *this }, reason]() {
        settleDetailsPromise(reason);
    });

    return { };
}

ExceptionOr<void> PaymentRequest::completeMerchantValidation(Event& event, Ref<DOMPromise>&& merchantSessionPromise)
{
    if (m_state != State::Interactive)
        return Exception { InvalidStateError };

    event.stopPropagation();
    event.stopImmediatePropagation();

    m_merchantSessionPromise = WTFMove(merchantSessionPromise);
    m_merchantSessionPromise->whenSettled([this, protectedThis = Ref { *this }]() {
        if (m_state != State::Interactive)
            return;

        if (m_merchantSessionPromise->status() == DOMPromise::Status::Rejected) {
            abortWithException(Exception { AbortError });
            return;
        }

        auto exception = activePaymentHandler()->merchantValidationCompleted(m_merchantSessionPromise->result());
        if (exception.hasException()) {
            abortWithException(exception.releaseException());
            return;
        }
    });

    return { };
}

void PaymentRequest::dispatchAndCheckUpdateEvent(Ref<PaymentRequestUpdateEvent>&& event)
{
    dispatchEvent(event);

    if (event->didCallUpdateWith())
        return;

    scriptExecutionContext()->addConsoleMessage(JSC::MessageSource::PaymentRequest, JSC::MessageLevel::Warning, makeString("updateWith() should be called synchronously when handling \""_s, event->type(), "\"."_s));
}

void PaymentRequest::settleDetailsPromise(UpdateReason reason)
{
    auto scopeExit = makeScopeExit([&] {
        m_isUpdating = false;
        m_isCancelPending = false;
        m_detailsPromise = nullptr;
    });

    if (m_state != State::Interactive)
        return;

    if (m_isCancelPending || m_detailsPromise->status() == DOMPromise::Status::Rejected) {
        abortWithException(Exception { AbortError });
        return;
    }

    auto& context = *m_detailsPromise->scriptExecutionContext();
    auto throwScope = DECLARE_THROW_SCOPE(context.vm());
    auto detailsUpdate = convertDictionary<PaymentDetailsUpdate>(*context.globalObject(), m_detailsPromise->result());
    if (throwScope.exception()) {
        abortWithException(Exception { ExistingExceptionError });
        return;
    }

    if (detailsUpdate.total) {
        auto totalResult = checkAndCanonicalizeTotal(*detailsUpdate.total);
        if (totalResult.hasException()) {
            abortWithException(totalResult.releaseException());
            return;
        }
    }

    auto detailsResult = checkAndCanonicalizeDetails(context, detailsUpdate, m_options.requestShipping, IsUpdate::Yes);
    if (detailsResult.hasException()) {
        abortWithException(detailsResult.releaseException());
        return;
    }

    auto shippingOptionAndModifierData = detailsResult.releaseReturnValue();

    if (detailsUpdate.total)
        m_details.total = WTFMove(*detailsUpdate.total);
    if (detailsUpdate.displayItems)
        m_details.displayItems = WTFMove(*detailsUpdate.displayItems);
    if (detailsUpdate.shippingOptions && m_options.requestShipping) {
        m_details.shippingOptions = WTFMove(detailsUpdate.shippingOptions);
        m_shippingOption = WTFMove(std::get<0>(shippingOptionAndModifierData));
    }
    if (detailsUpdate.modifiers) {
        m_details.modifiers = WTFMove(*detailsUpdate.modifiers);
        m_serializedModifierData = WTFMove(std::get<1>(shippingOptionAndModifierData));
    }

    auto result = activePaymentHandler()->detailsUpdated(reason, WTFMove(detailsUpdate.error), WTFMove(detailsUpdate.shippingAddressErrors), WTFMove(detailsUpdate.payerErrors), detailsUpdate.paymentMethodErrors.get());
    if (result.hasException()) {
        abortWithException(result.releaseException());
        return;
    }
}

void PaymentRequest::whenDetailsSettled(std::function<void()>&& callback)
{
    auto whenSettledFunction = [this, callback = WTFMove(callback)] {
        ASSERT(m_state == State::Interactive);
        ASSERT(!m_isUpdating);
        ASSERT(!m_isCancelPending);
        ASSERT_UNUSED(this, this);
        callback();
    };

    if (!m_detailsPromise) {
        whenSettledFunction();
        return;
    }

    m_detailsPromise->whenSettled([this, protectedThis = Ref { *this }, whenSettledFunction = WTFMove(whenSettledFunction)] {
        if (m_state == State::Interactive)
            whenSettledFunction();
    });
}

void PaymentRequest::accept(const String& methodName, PaymentResponse::DetailsFunction&& detailsFunction)
{
    ASSERT(!m_isUpdating);
    ASSERT(m_state == State::Interactive);

    bool isRetry = m_response;
    if (!isRetry) {
        m_response = PaymentResponse::create(scriptExecutionContext(), *this);
        m_response->setRequestId(m_details.id);
    }

    m_response->setMethodName(methodName);
    m_response->setDetailsFunction(WTFMove(detailsFunction));
    m_response->setShippingAddress(nullptr);
    m_response->setShippingOption(nullString());
    m_response->setPayerName(nullString());
    m_response->setPayerEmail(nullString());
    m_response->setPayerPhone(nullString());

    if (!isRetry)
        settleShowPromise(*m_response);
    else {
        ASSERT(m_response->hasRetryPromise());
        m_response->settleRetryPromise();
    }

    m_state = State::Closed;
}

void PaymentRequest::accept(const String& methodName, PaymentResponse::DetailsFunction&& detailsFunction, Ref<PaymentAddress>&& shippingAddress, const String& payerName, const String& payerEmail, const String& payerPhone)
{
    ASSERT(!m_isUpdating);
    ASSERT(m_state == State::Interactive);

    bool isRetry = m_response;
    if (!isRetry) {
        m_response = PaymentResponse::create(scriptExecutionContext(), *this);
        m_response->setRequestId(m_details.id);
    }

    m_response->setMethodName(methodName);
    m_response->setDetailsFunction(WTFMove(detailsFunction));
    m_response->setShippingAddress(m_options.requestShipping ? shippingAddress.ptr() : nullptr);
    m_response->setShippingOption(m_options.requestShipping ? m_shippingOption : String { });
    m_response->setPayerName(m_options.requestPayerName ? payerName : String { });
    m_response->setPayerEmail(m_options.requestPayerEmail ? payerEmail : String { });
    m_response->setPayerPhone(m_options.requestPayerPhone ? payerPhone : String { });

    if (!isRetry)
        settleShowPromise(*m_response);
    else {
        ASSERT(m_response->hasRetryPromise());
        m_response->settleRetryPromise();
    }

    m_state = State::Closed;
}

void PaymentRequest::reject(Exception&& exception)
{
    abortWithException(WTFMove(exception));
}

ExceptionOr<void> PaymentRequest::complete(std::optional<PaymentComplete>&& result)
{
    ASSERT(m_state == State::Closed);
    if (!m_activePaymentHandler)
        return Exception { AbortError };

    activePaymentHandler()->complete(WTFMove(result));
    m_activePaymentHandler = std::nullopt;
    return { };
}

ExceptionOr<void> PaymentRequest::retry(PaymentValidationErrors&& errors)
{
    ASSERT(m_state == State::Closed);
    if (!m_activePaymentHandler)
        return Exception { AbortError };

    m_state = State::Interactive;
    return activePaymentHandler()->retry(WTFMove(errors));
}

void PaymentRequest::cancel()
{
    m_activePaymentHandler = std::nullopt;

    if (m_isUpdating) {
        m_isCancelPending = true;
        scriptExecutionContext()->addConsoleMessage(JSC::MessageSource::PaymentRequest, JSC::MessageLevel::Error, "payment request timed out while waiting for Promise given to show() or updateWith() to settle."_s);
        return;
    }

    abortWithException(Exception { AbortError });
}

} // namespace WebCore

#endif // ENABLE(PAYMENT_REQUEST)
