/*
 * Copyright (C) 2014-2021 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 "InspectorFrontendAPIDispatcher.h"

#include "Frame.h"
#include "InspectorController.h"
#include "JSDOMPromise.h"
#include "Page.h"
#include "ScriptController.h"
#include "ScriptDisallowedScope.h"
#include "ScriptSourceCode.h"
#include "ScriptState.h"
#include <JavaScriptCore/FrameTracers.h>
#include <JavaScriptCore/JSPromise.h>
#include <wtf/RunLoop.h>

namespace WebCore {

using EvaluationError = InspectorFrontendAPIDispatcher::EvaluationError;

InspectorFrontendAPIDispatcher::InspectorFrontendAPIDispatcher(Page& frontendPage)
    : m_frontendPage(frontendPage)
{
}

InspectorFrontendAPIDispatcher::~InspectorFrontendAPIDispatcher()
{
    invalidateQueuedExpressions();
    invalidatePendingResponses();
}

void InspectorFrontendAPIDispatcher::reset()
{
    m_frontendLoaded = false;
    m_suspended = false;

    invalidateQueuedExpressions();
    invalidatePendingResponses();
}

void InspectorFrontendAPIDispatcher::frontendLoaded()
{
    ASSERT(m_frontendPage);
    m_frontendLoaded = true;

    // In some convoluted WebKitLegacy-only scenarios, the backend may try to dispatch events to the frontend
    // underneath InspectorFrontendHost::loaded() when it is unsafe to execute script, causing suspend() to
    // be called before the frontend has fully loaded. See <https://bugs.webkit.org/show_bug.cgi?id=218840>.
    if (!m_suspended)
        evaluateQueuedExpressions();
}

void InspectorFrontendAPIDispatcher::suspend(UnsuspendSoon unsuspendSoon)
{
    if (m_suspended)
        return;

    m_suspended = true;

    if (unsuspendSoon == UnsuspendSoon::Yes) {
        RunLoop::main().dispatch([protectedThis = Ref { *this }] {
            // If the frontend page has been deallocated, there's nothing to do.
            if (!protectedThis->m_frontendPage)
                return;

            protectedThis->unsuspend();
        });
    }
}

void InspectorFrontendAPIDispatcher::unsuspend()
{
    if (!m_suspended)
        return;

    m_suspended = false;

    if (m_frontendLoaded)
        evaluateQueuedExpressions();
}

JSDOMGlobalObject* InspectorFrontendAPIDispatcher::frontendGlobalObject()
{
    if (!m_frontendPage)
        return nullptr;
    
    return m_frontendPage->mainFrame().script().globalObject(mainThreadNormalWorld());
}

static String expressionForEvaluatingCommand(const String& command, Vector<Ref<JSON::Value>>&& arguments)
{
    StringBuilder expression;
    expression.append("InspectorFrontendAPI.dispatch([\"", command, '"');
    for (auto& argument : arguments) {
        expression.append(", ");
        argument->writeJSON(expression);
    }
    expression.append("])");
    return expression.toString();
}

InspectorFrontendAPIDispatcher::EvaluationResult InspectorFrontendAPIDispatcher::dispatchCommandWithResultSync(const String& command, Vector<Ref<JSON::Value>>&& arguments)
{
    if (m_suspended)
        return makeUnexpected(EvaluationError::ExecutionSuspended);

    return evaluateExpression(expressionForEvaluatingCommand(command, WTFMove(arguments)));
}

void InspectorFrontendAPIDispatcher::dispatchCommandWithResultAsync(const String& command, Vector<Ref<JSON::Value>>&& arguments, EvaluationResultHandler&& resultHandler)
{
    evaluateOrQueueExpression(expressionForEvaluatingCommand(command, WTFMove(arguments)), WTFMove(resultHandler));
}

void InspectorFrontendAPIDispatcher::dispatchMessageAsync(const String& message)
{
    evaluateOrQueueExpression(makeString("InspectorFrontendAPI.dispatchMessageAsync(", message, ")"));
}

void InspectorFrontendAPIDispatcher::evaluateOrQueueExpression(const String& expression, EvaluationResultHandler&& optionalResultHandler)
{
    // If the frontend page has been deallocated, then there is nothing to do.
    if (!m_frontendPage) {
        if (optionalResultHandler)
            optionalResultHandler(makeUnexpected(EvaluationError::ContextDestroyed));

        return;
    }

    // Sometimes we get here by sending messages for events triggered by DOM mutations earlier in the call stack.
    // If this is the case, then it's not safe to evaluate script synchronously, so do it later. This only affects
    // WebKit1 and some layout tests that use a single web process for both the inspector and inspected page.
    if (!ScriptDisallowedScope::InMainThread::isScriptAllowed())
        suspend(UnsuspendSoon::Yes);

    if (!m_frontendLoaded || m_suspended) {
        m_queuedEvaluations.append(std::make_pair(expression, WTFMove(optionalResultHandler)));
        return;
    }

    ValueOrException result = evaluateExpression(expression);
    if (!optionalResultHandler)
        return;

    if (!result.has_value()) {
        optionalResultHandler(result);
        return;
    }

    JSDOMGlobalObject* globalObject = frontendGlobalObject();
    if (!globalObject) {
        optionalResultHandler(makeUnexpected(EvaluationError::ContextDestroyed));
        return;
    }
    
    JSC::JSLockHolder lock(globalObject);
    
    auto& vm = globalObject->vm();
    auto* castedPromise = JSC::jsDynamicCast<JSC::JSPromise*>(vm, result.value());
    if (!castedPromise) {
        // Simple case: result is NOT a promise, just return the JSValue.
        optionalResultHandler(result);
        return;
    }

    // If the result is a promise, call the result handler when the promise settles.
    Ref<DOMPromise> promise = DOMPromise::create(*globalObject, *castedPromise);
    m_pendingResponses.set(promise.copyRef(), WTFMove(optionalResultHandler));
    auto isRegistered = promise->whenSettled([promise = promise.copyRef(), weakThis = WeakPtr { *this }] {
        // If `this` is cleared or the responses map is empty, then the promise settled
        // beyond the time when we care about its result. Ignore late-settled promises.
        // We clear out completion handlers for pending responses during teardown.
        if (!weakThis)
            return;

        Ref strongThis = { *weakThis };
        if (!strongThis->m_pendingResponses.size())
            return;

        EvaluationResultHandler resultHandler = strongThis->m_pendingResponses.take(promise);
        ASSERT(resultHandler);
        
        JSDOMGlobalObject* globalObject = strongThis->frontendGlobalObject();
        if (!globalObject) {
            resultHandler(makeUnexpected(EvaluationError::ContextDestroyed));
            return;
        }

        resultHandler({ promise->promise()->result(globalObject->vm()) });
    });

    if (isRegistered == DOMPromise::IsCallbackRegistered::No)
        optionalResultHandler(makeUnexpected(EvaluationError::InternalError));
}

void InspectorFrontendAPIDispatcher::invalidateQueuedExpressions()
{
    auto queuedEvaluations = std::exchange(m_queuedEvaluations, { });
    for (auto& pair : queuedEvaluations) {
        auto resultHandler = WTFMove(pair.second);
        if (resultHandler)
            resultHandler(makeUnexpected(EvaluationError::ContextDestroyed));
    }
}

void InspectorFrontendAPIDispatcher::invalidatePendingResponses()
{
    auto pendingResponses = std::exchange(m_pendingResponses, { });
    for (auto& callback : pendingResponses.values())
        callback(makeUnexpected(EvaluationError::ContextDestroyed));

    // No more pending responses should have been added while erroring out the callbacks.
    ASSERT(m_pendingResponses.isEmpty());
}

void InspectorFrontendAPIDispatcher::evaluateQueuedExpressions()
{
    // If the frontend page has been deallocated, then there is nothing to do.
    if (!m_frontendPage)
        return;

    if (m_queuedEvaluations.isEmpty())
        return;

    auto queuedEvaluations = std::exchange(m_queuedEvaluations, { });
    for (auto& pair : queuedEvaluations) {
        auto result = evaluateExpression(pair.first);
        if (auto resultHandler = WTFMove(pair.second))
            resultHandler(result);
    }
}

ValueOrException InspectorFrontendAPIDispatcher::evaluateExpression(const String& expression)
{
    ASSERT(m_frontendPage);
    ASSERT(!m_suspended);
    ASSERT(m_queuedEvaluations.isEmpty());

    JSC::SuspendExceptionScope scope(&m_frontendPage->inspectorController().vm());
    return m_frontendPage->mainFrame().script().evaluateInWorld(ScriptSourceCode(expression), mainThreadNormalWorld());
}

void InspectorFrontendAPIDispatcher::evaluateExpressionForTesting(const String& expression)
{
    evaluateOrQueueExpression(expression);
}

} // namespace WebKit
