/*
 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 *  Copyright (C) 2003-2021 Apple Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "JSEventListener.h"

#include "BeforeUnloadEvent.h"
#include "ContentSecurityPolicy.h"
#include "EventNames.h"
#include "Frame.h"
#include "HTMLElement.h"
#include "JSDOMConvertNullable.h"
#include "JSDOMConvertStrings.h"
#include "JSDOMGlobalObject.h"
#include "JSDocument.h"
#include "JSEvent.h"
#include "JSEventTarget.h"
#include "JSExecState.h"
#include "JSExecStateInstrumentation.h"
#include "JSWorkerGlobalScope.h"
#include "ScriptController.h"
#include "WorkerGlobalScope.h"
#include <JavaScriptCore/ExceptionHelpers.h>
#include <JavaScriptCore/JSLock.h>
#include <JavaScriptCore/VMEntryScope.h>
#include <JavaScriptCore/Watchdog.h>
#include <wtf/Ref.h>
#include <wtf/Scope.h>

namespace WebCore {
using namespace JSC;

JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isAttribute, DOMWrapperWorld& isolatedWorld)
    : EventListener(JSEventListenerType)
    , m_wrapper(wrapper)
    , m_isAttribute(isAttribute)
    , m_isolatedWorld(isolatedWorld)
{
    if (function) {
        ASSERT(wrapper);
        m_jsFunction = JSC::Weak<JSC::JSObject>(function);
        m_isInitialized = true;
    }
}

JSEventListener::~JSEventListener() = default;

Ref<JSEventListener> JSEventListener::create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world)
{
    return adoptRef(*new JSEventListener(&listener, &wrapper, isAttribute, world));
}

RefPtr<JSEventListener> JSEventListener::create(JSC::JSValue listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world)
{
    if (UNLIKELY(!listener.isObject()))
        return nullptr;

    return adoptRef(*new JSEventListener(asObject(listener), &wrapper, isAttribute, world));
}

JSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext&) const
{
    return nullptr;
}

void JSEventListener::replaceJSFunctionForAttributeListener(JSObject* function, JSObject* wrapper)
{
    ASSERT(m_isAttribute);
    ASSERT(function);
    ASSERT(wrapper);

    m_jsFunction = Weak { function };
    if (UNLIKELY(!m_isInitialized)) {
        m_wrapper = Weak { wrapper };
        auto& vm = m_isolatedWorld->vm();
        vm.writeBarrier(wrapper, function);
        m_isInitialized = true;
    }
}

JSValue eventHandlerAttribute(EventTarget& eventTarget, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
{
    if (auto* jsListener = eventTarget.attributeEventListener(eventType, isolatedWorld)) {
        if (auto* context = eventTarget.scriptExecutionContext()) {
            if (auto* jsFunction = jsListener->ensureJSFunction(*context))
                return jsFunction;
        }
    }

    return jsNull();
}

template<typename Visitor>
inline void JSEventListener::visitJSFunctionImpl(Visitor& visitor)
{
    // If m_wrapper is null, we are not keeping m_jsFunction alive.
    if (!m_wrapper)
        return;

    visitor.append(m_jsFunction);
}

void JSEventListener::visitJSFunction(AbstractSlotVisitor& visitor) { visitJSFunctionImpl(visitor); }
void JSEventListener::visitJSFunction(SlotVisitor& visitor) { visitJSFunctionImpl(visitor); }

static void handleBeforeUnloadEventReturnValue(BeforeUnloadEvent& event, const String& returnValue)
{
    if (returnValue.isNull())
        return;

    event.preventDefault();
    if (event.returnValue().isEmpty())
        event.setReturnValue(returnValue);
}

void JSEventListener::handleEvent(ScriptExecutionContext& scriptExecutionContext, Event& event)
{
    if (scriptExecutionContext.isJSExecutionForbidden())
        return;

    VM& vm = scriptExecutionContext.vm();
    JSLockHolder lock(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    // See https://dom.spec.whatwg.org/#dispatching-events spec on calling handleEvent.
    // "If this throws an exception, report the exception." It should not propagate the
    // exception.

    JSObject* jsFunction = ensureJSFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld);
    if (!globalObject)
        return;

    if (scriptExecutionContext.isDocument()) {
        JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject);
        if (!window->wrapped().isCurrentlyDisplayedInFrame())
            return;
        if (wasCreatedFromMarkup()) {
            Element* element = event.target()->isNode() && !downcast<Node>(*event.target()).isDocumentNode() ? dynamicDowncast<Element>(*event.target()) : nullptr;
            if (!scriptExecutionContext.contentSecurityPolicy()->allowInlineEventHandlers(sourceURL().string(), sourcePosition().m_line, code(), element))
                return;
        }
        // FIXME: Is this check needed for other contexts?
        ScriptController& script = window->wrapped().frame()->script();
        if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused())
            return;
    }

    RefPtr<Event> savedEvent;
    auto* jsFunctionWindow = jsDynamicCast<JSDOMWindow*>(vm, jsFunction->globalObject(vm));
    if (jsFunctionWindow) {
        savedEvent = jsFunctionWindow->currentEvent();

        // window.event should not be set when the target is inside a shadow tree, as per the DOM specification.
        if (!event.currentTargetIsInShadowTree())
            jsFunctionWindow->setCurrentEvent(&event);
    }

    auto restoreCurrentEventOnExit = makeScopeExit([&] {
        if (jsFunctionWindow)
            jsFunctionWindow->setCurrentEvent(savedEvent.get());
    });

    JSGlobalObject* lexicalGlobalObject = jsFunction->globalObject();

    JSValue handleEventFunction = jsFunction;

    auto callData = getCallData(vm, handleEventFunction);

    // If jsFunction is not actually a function and this is an EventListener, see if it implements callback interface.
    if (callData.type == CallData::Type::None) {
        if (m_isAttribute)
            return;

        handleEventFunction = jsFunction->get(lexicalGlobalObject, Identifier::fromString(vm, "handleEvent"));
        if (UNLIKELY(scope.exception())) {
            auto* exception = scope.exception();
            scope.clearException();
            event.target()->uncaughtExceptionInEventHandler();
            reportException(lexicalGlobalObject, exception);
            return;
        }
        callData = getCallData(vm, handleEventFunction);
        if (callData.type == CallData::Type::None) {
            event.target()->uncaughtExceptionInEventHandler();
            reportException(lexicalGlobalObject, createTypeError(lexicalGlobalObject, "'handleEvent' property of event listener should be callable"_s));
            return;
        }
    }

    Ref<JSEventListener> protectedThis(*this);

    MarkedArgumentBuffer args;
    args.append(toJS(lexicalGlobalObject, globalObject, &event));
    ASSERT(!args.hasOverflowed());

    VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : lexicalGlobalObject);

    JSExecState::instrumentFunction(&scriptExecutionContext, callData);

    JSValue thisValue = handleEventFunction == jsFunction ? toJS(lexicalGlobalObject, globalObject, event.currentTarget()) : jsFunction;
    NakedPtr<JSC::Exception> uncaughtException;
    JSValue retval = JSExecState::profiledCall(lexicalGlobalObject, JSC::ProfilingReason::Other, handleEventFunction, callData, thisValue, args, uncaughtException);

    InspectorInstrumentation::didCallFunction(&scriptExecutionContext);

    auto handleExceptionIfNeeded = [&] (JSC::Exception* exception) -> bool {
        if (is<WorkerGlobalScope>(scriptExecutionContext)) {
            auto* scriptController = downcast<WorkerGlobalScope>(scriptExecutionContext).script();
            bool terminatorCausedException = (exception && vm.isTerminationException(exception));
            if (terminatorCausedException || (scriptController && scriptController->isTerminatingExecution()))
                scriptController->forbidExecution();
        }

        if (exception) {
            event.target()->uncaughtExceptionInEventHandler();
            reportException(lexicalGlobalObject, exception);
            return true;
        }
        return false;
    };

    if (handleExceptionIfNeeded(uncaughtException))
        return;

    if (!m_isAttribute) {
        // This is an EventListener and there is therefore no need for any return value handling.
        return;
    }

    // Do return value handling for event handlers (https://html.spec.whatwg.org/#the-event-handler-processing-algorithm).

    if (event.type() == eventNames().beforeunloadEvent) {
        // This is a OnBeforeUnloadEventHandler, and therefore the return value must be coerced into a String.
        if (is<BeforeUnloadEvent>(event)) {
            String resultStr = convert<IDLNullable<IDLDOMString>>(*lexicalGlobalObject, retval);
            if (UNLIKELY(scope.exception())) {
                if (handleExceptionIfNeeded(scope.exception()))
                    return;
            }
            handleBeforeUnloadEventReturnValue(downcast<BeforeUnloadEvent>(event), resultStr);
        }
        return;
    }

    if (retval.isFalse())
        event.preventDefault();
}

bool JSEventListener::operator==(const EventListener& listener) const
{
    if (!is<JSEventListener>(listener))
        return false;
    auto& other = downcast<JSEventListener>(listener);
    return m_jsFunction == other.m_jsFunction && m_isAttribute == other.m_isAttribute;
}

String JSEventListener::functionName() const
{
    if (!m_wrapper || !m_jsFunction)
        return { };

    auto& vm = isolatedWorld().vm();
    JSC::JSLockHolder lock(vm);

    auto* handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(vm, m_jsFunction.get());
    if (!handlerFunction)
        return { };

    return handlerFunction->name(vm);
}

} // namespace WebCore
