/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 * Copyright (C) 2015 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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 "InspectorDOMDebuggerAgent.h"

#include "Event.h"
#include "EventTarget.h"
#include "InspectorDOMAgent.h"
#include "InstrumentingAgents.h"
#include "JSEvent.h"
#include "RegisteredEventListener.h"
#include "ScriptExecutionContext.h"
#include <JavaScriptCore/ContentSearchUtilities.h>
#include <JavaScriptCore/InjectedScript.h>
#include <JavaScriptCore/InjectedScriptManager.h>
#include <JavaScriptCore/InspectorFrontendDispatchers.h>
#include <JavaScriptCore/RegularExpression.h>
#include <wtf/JSONValues.h>

namespace WebCore {

using namespace Inspector;

InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent(WebAgentContext& context, InspectorDebuggerAgent* debuggerAgent)
    : InspectorAgentBase("DOMDebugger"_s, context)
    , m_debuggerAgent(debuggerAgent)
    , m_backendDispatcher(Inspector::DOMDebuggerBackendDispatcher::create(context.backendDispatcher, this))
    , m_injectedScriptManager(context.injectedScriptManager)
{
    m_debuggerAgent->addListener(*this);
}

InspectorDOMDebuggerAgent::~InspectorDOMDebuggerAgent() = default;

bool InspectorDOMDebuggerAgent::enabled() const
{
    return m_instrumentingAgents.inspectorDOMDebuggerAgent() == this;
}

void InspectorDOMDebuggerAgent::enable()
{
    m_instrumentingAgents.setInspectorDOMDebuggerAgent(this);
}

void InspectorDOMDebuggerAgent::disable()
{
    m_instrumentingAgents.setInspectorDOMDebuggerAgent(nullptr);

    m_listenerBreakpoints.clear();
    m_urlBreakpoints.clear();
    m_pauseOnAllIntervalsEnabled = false;
    m_pauseOnAllListenersEnabled = false;
    m_pauseOnAllTimeoutsEnabled = false;
    m_pauseOnAllURLsEnabled = false;
}

// Browser debugger agent enabled only when JS debugger is enabled.
void InspectorDOMDebuggerAgent::debuggerWasEnabled()
{
    ASSERT(!enabled());
    enable();
}

void InspectorDOMDebuggerAgent::debuggerWasDisabled()
{
    ASSERT(enabled());
    disable();
}

void InspectorDOMDebuggerAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
{
}

void InspectorDOMDebuggerAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
{
    disable();
}

void InspectorDOMDebuggerAgent::discardAgent()
{
    m_debuggerAgent->removeListener(*this);
    m_debuggerAgent = nullptr;
}

void InspectorDOMDebuggerAgent::setEventBreakpoint(ErrorString& errorString, const String& breakpointTypeString, const String* eventName)
{
    if (breakpointTypeString.isEmpty()) {
        errorString = "breakpointType is empty"_s;
        return;
    }

    auto breakpointType = Inspector::Protocol::InspectorHelpers::parseEnumValueFromString<Inspector::Protocol::DOMDebugger::EventBreakpointType>(breakpointTypeString);
    if (!breakpointType) {
        errorString = makeString("Unknown breakpointType: "_s, breakpointTypeString);
        return;
    }

    if (eventName && !eventName->isEmpty()) {
        if (breakpointType.value() == Inspector::Protocol::DOMDebugger::EventBreakpointType::Listener) {
            if (!m_listenerBreakpoints.add(*eventName))
                errorString = "Breakpoint with eventName already exists"_s;
            return;
        }

        errorString = "Unexpected eventName"_s;
        return;
    }

    switch (breakpointType.value()) {
    case Inspector::Protocol::DOMDebugger::EventBreakpointType::AnimationFrame:
        setAnimationFrameBreakpoint(errorString, true);
        break;

    case Inspector::Protocol::DOMDebugger::EventBreakpointType::Interval:
        if (m_pauseOnAllIntervalsEnabled)
            errorString = "Breakpoint for Interval already exists"_s;
        m_pauseOnAllIntervalsEnabled = true;
        break;

    case Inspector::Protocol::DOMDebugger::EventBreakpointType::Listener:
        if (m_pauseOnAllListenersEnabled)
            errorString = "Breakpoint for Listener already exists"_s;
        m_pauseOnAllListenersEnabled = true;
        break;

    case Inspector::Protocol::DOMDebugger::EventBreakpointType::Timeout:
        if (m_pauseOnAllTimeoutsEnabled)
            errorString = "Breakpoint for Timeout already exists"_s;
        m_pauseOnAllTimeoutsEnabled = true;
        break;
    }
}

void InspectorDOMDebuggerAgent::removeEventBreakpoint(ErrorString& errorString, const String& breakpointTypeString, const String* eventName)
{
    if (breakpointTypeString.isEmpty()) {
        errorString = "breakpointType is empty"_s;
        return;
    }

    auto breakpointType = Inspector::Protocol::InspectorHelpers::parseEnumValueFromString<Inspector::Protocol::DOMDebugger::EventBreakpointType>(breakpointTypeString);
    if (!breakpointType) {
        errorString = makeString("Unknown breakpointType: "_s, breakpointTypeString);
        return;
    }

    if (eventName && !eventName->isEmpty()) {
        if (breakpointType.value() == Inspector::Protocol::DOMDebugger::EventBreakpointType::Listener) {
            if (!m_listenerBreakpoints.remove(*eventName))
                errorString = "Breakpoint for given eventName missing"_s;
            return;
        }

        errorString = "Unexpected eventName"_s;
        return;
    }

    switch (breakpointType.value()) {
    case Inspector::Protocol::DOMDebugger::EventBreakpointType::AnimationFrame:
        setAnimationFrameBreakpoint(errorString, false);
        break;

    case Inspector::Protocol::DOMDebugger::EventBreakpointType::Interval:
        if (!m_pauseOnAllIntervalsEnabled)
            errorString = "Breakpoint for Intervals missing"_s;
        m_pauseOnAllIntervalsEnabled = false;
        break;

    case Inspector::Protocol::DOMDebugger::EventBreakpointType::Listener:
        if (!m_pauseOnAllListenersEnabled)
            errorString = "Breakpoint for Listeners missing"_s;
        m_pauseOnAllListenersEnabled = false;
        break;

    case Inspector::Protocol::DOMDebugger::EventBreakpointType::Timeout:
        if (!m_pauseOnAllTimeoutsEnabled)
            errorString = "Breakpoint for Timeouts missing"_s;
        m_pauseOnAllTimeoutsEnabled = false;
        break;
    }
}

void InspectorDOMDebuggerAgent::willHandleEvent(Event& event, const RegisteredEventListener& registeredEventListener)
{
    if (!m_debuggerAgent->breakpointsActive())
        return;

    auto state = event.target()->scriptExecutionContext()->execState();
    auto injectedScript = m_injectedScriptManager.injectedScriptFor(state);
    ASSERT(!injectedScript.hasNoValue());
    {
        JSC::JSLockHolder lock(state);

        injectedScript.setEventValue(toJS(state, deprecatedGlobalObjectForPrototype(state), event));
    }

    auto* domAgent = m_instrumentingAgents.inspectorDOMAgent();

    bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_pauseOnAllListenersEnabled || m_listenerBreakpoints.contains(event.type());
    if (!shouldPause && domAgent)
        shouldPause = domAgent->hasBreakpointForEventListener(*event.currentTarget(), event.type(), registeredEventListener.callback(), registeredEventListener.useCapture());
    if (!shouldPause)
        return;

    Ref<JSON::Object> eventData = JSON::Object::create();
    eventData->setString("eventName"_s, event.type());
    if (domAgent) {
        int eventListenerId = domAgent->idForEventListener(*event.currentTarget(), event.type(), registeredEventListener.callback(), registeredEventListener.useCapture());
        if (eventListenerId)
            eventData->setInteger("eventListenerId"_s, eventListenerId);
    }

    m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::Listener, WTFMove(eventData));
}

void InspectorDOMDebuggerAgent::didHandleEvent()
{
    m_injectedScriptManager.clearEventValue();
}

void InspectorDOMDebuggerAgent::willFireTimer(bool oneShot)
{
    if (!m_debuggerAgent->breakpointsActive())
        return;

    bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || (oneShot ? m_pauseOnAllTimeoutsEnabled : m_pauseOnAllIntervalsEnabled);
    if (!shouldPause)
        return;

    auto breakReason = oneShot ? Inspector::DebuggerFrontendDispatcher::Reason::Timeout : Inspector::DebuggerFrontendDispatcher::Reason::Interval;
    m_debuggerAgent->schedulePauseOnNextStatement(breakReason, nullptr);
}

void InspectorDOMDebuggerAgent::setURLBreakpoint(ErrorString& errorString, const String& url, const bool* optionalIsRegex)
{
    if (url.isEmpty()) {
        if (m_pauseOnAllURLsEnabled)
            errorString = "Breakpoint for all URLs already exists"_s;
        m_pauseOnAllURLsEnabled = true;
        return;
    }

    bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
    auto result = m_urlBreakpoints.set(url, isRegex ? URLBreakpointType::RegularExpression : URLBreakpointType::Text);
    if (!result.isNewEntry)
        errorString = "Breakpoint for given url already exists"_s;
}

void InspectorDOMDebuggerAgent::removeURLBreakpoint(ErrorString& errorString, const String& url)
{
    if (url.isEmpty()) {
        if (!m_pauseOnAllURLsEnabled)
            errorString = "Breakpoint for all URLs missing"_s;
        m_pauseOnAllURLsEnabled = false;
        return;
    }

    auto result = m_urlBreakpoints.remove(url);
    if (!result)
        errorString = "Breakpoint for given url missing"_s;
}

void InspectorDOMDebuggerAgent::breakOnURLIfNeeded(const String& url, URLBreakpointSource source)
{
    if (!m_debuggerAgent->breakpointsActive())
        return;

    String breakpointURL;
    if (m_pauseOnAllURLsEnabled)
        breakpointURL = emptyString();
    else {
        for (auto& entry : m_urlBreakpoints) {
            const auto& query = entry.key;
            bool isRegex = entry.value == URLBreakpointType::RegularExpression;
            auto regex = ContentSearchUtilities::createSearchRegex(query, false, isRegex);
            if (regex.match(url) != -1) {
                breakpointURL = query;
                break;
            }
        }
    }

    if (breakpointURL.isNull())
        return;

    Inspector::DebuggerFrontendDispatcher::Reason breakReason;
    if (source == URLBreakpointSource::Fetch)
        breakReason = Inspector::DebuggerFrontendDispatcher::Reason::Fetch;
    else if (source == URLBreakpointSource::XHR)
        breakReason = Inspector::DebuggerFrontendDispatcher::Reason::XHR;
    else {
        ASSERT_NOT_REACHED();
        breakReason = Inspector::DebuggerFrontendDispatcher::Reason::Other;
    }

    Ref<JSON::Object> eventData = JSON::Object::create();
    eventData->setString("breakpointURL", breakpointURL);
    eventData->setString("url", url);
    m_debuggerAgent->breakProgram(breakReason, WTFMove(eventData));
}

void InspectorDOMDebuggerAgent::willSendXMLHttpRequest(const String& url)
{
    breakOnURLIfNeeded(url, URLBreakpointSource::XHR);
}

void InspectorDOMDebuggerAgent::willFetch(const String& url)
{
    breakOnURLIfNeeded(url, URLBreakpointSource::Fetch);
}

} // namespace WebCore
