/*
 * Copyright (C) 2010 Google 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 "DebuggerAgentManager.h"

#include "DebuggerAgentImpl.h"
#include "Frame.h"
#include "PageGroupLoadDeferrer.h"
#include "PageScriptDebugServer.h"
#include "V8Proxy.h"
#include "WebDevToolsAgentImpl.h"
#include "WebFrameImpl.h"
#include "WebViewImpl.h"
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
#include <wtf/text/StringConcatenate.h>

namespace WebKit {

WebDevToolsAgent::MessageLoopDispatchHandler DebuggerAgentManager::s_messageLoopDispatchHandler = 0;

bool DebuggerAgentManager::s_inHostDispatchHandler = false;

DebuggerAgentManager::DeferrersMap DebuggerAgentManager::s_pageDeferrers;

bool DebuggerAgentManager::s_exposeV8DebuggerProtocol = false;

namespace {

class CallerIdWrapper : public v8::Debug::ClientData {
    WTF_MAKE_NONCOPYABLE(CallerIdWrapper);
public:
    CallerIdWrapper() : m_callerIsMananager(true), m_callerId(0) { }
    explicit CallerIdWrapper(int callerId)
        : m_callerIsMananager(false)
        , m_callerId(callerId) { }
    ~CallerIdWrapper() { }
    bool callerIsMananager() const { return m_callerIsMananager; }
    int callerId() const { return m_callerId; }
private:
    bool m_callerIsMananager;
    int m_callerId;
};

} // namespace


void DebuggerAgentManager::debugHostDispatchHandler()
{
    if (!s_messageLoopDispatchHandler || !s_attachedAgentsMap)
        return;

    if (s_inHostDispatchHandler)
        return;

    s_inHostDispatchHandler = true;

    Vector<WebViewImpl*> views;
    // 1. Disable active objects and input events.
    for (AttachedAgentsMap::iterator it = s_attachedAgentsMap->begin(); it != s_attachedAgentsMap->end(); ++it) {
        DebuggerAgentImpl* agent = it->second;
        s_pageDeferrers.set(agent->webView(), new WebCore::PageGroupLoadDeferrer(agent->page(), true));
        views.append(agent->webView());
        agent->webView()->setIgnoreInputEvents(true);
    }

    // 2. Process messages.
    s_messageLoopDispatchHandler();

    // 3. Bring things back.
    for (Vector<WebViewImpl*>::iterator it = views.begin(); it != views.end(); ++it) {
        if (s_pageDeferrers.contains(*it)) {
            // The view was not closed during the dispatch.
            (*it)->setIgnoreInputEvents(false);
        }
    }
    deleteAllValues(s_pageDeferrers);
    s_pageDeferrers.clear();

    s_inHostDispatchHandler = false;
    if (!s_attachedAgentsMap) {
        // Remove handlers if all agents were detached within host dispatch.
        v8::Debug::SetMessageHandler(0);
        v8::Debug::SetHostDispatchHandler(0);
    }
}

DebuggerAgentManager::AttachedAgentsMap* DebuggerAgentManager::s_attachedAgentsMap = 0;

void DebuggerAgentManager::debugAttach(DebuggerAgentImpl* debuggerAgent)
{
    if (!s_exposeV8DebuggerProtocol)
        return;
    if (!s_attachedAgentsMap) {
        s_attachedAgentsMap = new AttachedAgentsMap();
        v8::Debug::SetMessageHandler2(&DebuggerAgentManager::onV8DebugMessage);
        v8::Debug::SetHostDispatchHandler(&DebuggerAgentManager::debugHostDispatchHandler, 100 /* ms */);
    }
    int hostId = debuggerAgent->webdevtoolsAgent()->hostId();
    ASSERT(hostId);
    s_attachedAgentsMap->set(hostId, debuggerAgent);
}

void DebuggerAgentManager::debugDetach(DebuggerAgentImpl* debuggerAgent)
{
    if (!s_exposeV8DebuggerProtocol)
        return;
    if (!s_attachedAgentsMap) {
        ASSERT_NOT_REACHED();
        return;
    }
    int hostId = debuggerAgent->webdevtoolsAgent()->hostId();
    ASSERT(s_attachedAgentsMap->get(hostId) == debuggerAgent);
    bool isOnBreakpoint = (findAgentForCurrentV8Context() == debuggerAgent);
    s_attachedAgentsMap->remove(hostId);

    if (s_attachedAgentsMap->isEmpty()) {
        delete s_attachedAgentsMap;
        s_attachedAgentsMap = 0;
        // Note that we do not empty handlers while in dispatch - we schedule
        // continue and do removal once we are out of the dispatch. Also there is
        // no need to send continue command in this case since removing message
        // handler will cause debugger unload and all breakpoints will be cleared.
        if (!s_inHostDispatchHandler) {
            v8::Debug::SetMessageHandler2(0);
            v8::Debug::SetHostDispatchHandler(0);
        }
    } else {
      // Remove all breakpoints set by the agent.
      String clearBreakpointGroupCmd = makeString(
          "{\"seq\":1,\"type\":\"request\",\"command\":\"clearbreakpointgroup\","
              "\"arguments\":{\"groupId\":", String::number(hostId), "}}");
      sendCommandToV8(clearBreakpointGroupCmd, new CallerIdWrapper());

      if (isOnBreakpoint) {
          // Force continue if detach happened in nessted message loop while
          // debugger was paused on a breakpoint(as long as there are other
          // attached agents v8 will wait for explicit'continue' message).
          sendContinueCommandToV8();
      }
    }
}

void DebuggerAgentManager::onV8DebugMessage(const v8::Debug::Message& message)
{
    v8::HandleScope scope;
    v8::String::Value value(message.GetJSON());
    WTF::String out(reinterpret_cast<const UChar*>(*value), value.length());

    // If callerData is not 0 the message is a response to a debugger command.
    if (v8::Debug::ClientData* callerData = message.GetClientData()) {
        CallerIdWrapper* wrapper = static_cast<CallerIdWrapper*>(callerData);
        if (wrapper->callerIsMananager()) {
            // Just ignore messages sent by this manager.
            return;
        }
        DebuggerAgentImpl* debuggerAgent = debuggerAgentForHostId(wrapper->callerId());
        if (debuggerAgent)
            debuggerAgent->debuggerOutput(out);
        else if (!message.WillStartRunning()) {
            // Autocontinue execution if there is no handler.
            sendContinueCommandToV8();
        }
        return;
    } // Otherwise it's an event message.
    ASSERT(message.IsEvent());

    // Ignore unsupported event types.
    if (message.GetEvent() != v8::AfterCompile && message.GetEvent() != v8::Break && message.GetEvent() != v8::Exception)
        return;

    v8::Handle<v8::Context> context = message.GetEventContext();
    // If the context is from one of the inpected tabs it should have its context
    // data.
    if (context.IsEmpty()) {
        // Unknown context, skip the event.
        return;
    }

    // If the context is from one of the inpected tabs or injected extension
    // scripts it must have hostId in the data field.
    int hostId = WebCore::V8Proxy::contextDebugId(context);
    if (hostId != -1) {
        DebuggerAgentImpl* agent = debuggerAgentForHostId(hostId);
        if (agent) {
            if (agent->autoContinueOnException()
                && message.GetEvent() == v8::Exception) {
                sendContinueCommandToV8();
                return;
            }

            agent->debuggerOutput(out);
            return;
        }
    }

    if (!message.WillStartRunning()) {
        // Autocontinue execution on break and exception  events if there is no
        // handler.
        sendContinueCommandToV8();
    }
}

void DebuggerAgentManager::pauseScript()
{
    v8::Debug::DebugBreak();
}

void DebuggerAgentManager::executeDebuggerCommand(const WTF::String& command, int callerId)
{
    sendCommandToV8(command, new CallerIdWrapper(callerId));
}

void DebuggerAgentManager::setMessageLoopDispatchHandler(WebDevToolsAgent::MessageLoopDispatchHandler handler)
{
    s_messageLoopDispatchHandler = handler;
}

void DebuggerAgentManager::setExposeV8DebuggerProtocol(bool value)
{
    s_exposeV8DebuggerProtocol = value;
    WebCore::PageScriptDebugServer::shared().setEnabled(!s_exposeV8DebuggerProtocol);
}

void DebuggerAgentManager::setHostId(WebFrameImpl* webframe, int hostId)
{
    ASSERT(hostId > 0);
    WebCore::V8Proxy* proxy = WebCore::V8Proxy::retrieve(webframe->frame());
    if (proxy)
        proxy->setContextDebugId(hostId);
}

void DebuggerAgentManager::onWebViewClosed(WebViewImpl* webview)
{
    if (s_pageDeferrers.contains(webview)) {
        delete s_pageDeferrers.get(webview);
        s_pageDeferrers.remove(webview);
    }
}

void DebuggerAgentManager::onNavigate()
{
    if (s_inHostDispatchHandler)
        DebuggerAgentManager::sendContinueCommandToV8();
}

void DebuggerAgentManager::sendCommandToV8(const WTF::String& cmd, v8::Debug::ClientData* data)
{
    v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), data);
}

void DebuggerAgentManager::sendContinueCommandToV8()
{
    WTF::String continueCmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\"}");
    sendCommandToV8(continueCmd, new CallerIdWrapper());
}

DebuggerAgentImpl* DebuggerAgentManager::findAgentForCurrentV8Context()
{
    if (!s_attachedAgentsMap)
        return 0;
    ASSERT(!s_attachedAgentsMap->isEmpty());

    WebCore::Frame* frame = WebCore::V8Proxy::retrieveFrameForEnteredContext();
    if (!frame)
        return 0;
    WebCore::Page* page = frame->page();
    for (AttachedAgentsMap::iterator it = s_attachedAgentsMap->begin(); it != s_attachedAgentsMap->end(); ++it) {
        if (it->second->page() == page)
            return it->second;
    }
    return 0;
}

DebuggerAgentImpl* DebuggerAgentManager::debuggerAgentForHostId(int hostId)
{
    if (!s_attachedAgentsMap)
        return 0;
    return s_attachedAgentsMap->get(hostId);
}

} // namespace WebKit
