/*
 * Copyright (C) 2007-2021 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 *
 * 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.
 * 3.  Neither the name of Apple Inc. ("Apple") 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 APPLE 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 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 "InspectorFrontendHost.h"

#include "CertificateInfo.h"
#include "ContextMenu.h"
#include "ContextMenuController.h"
#include "ContextMenuItem.h"
#include "ContextMenuProvider.h"
#include "DOMWrapperWorld.h"
#include "Document.h"
#include "Editor.h"
#include "Event.h"
#include "FloatRect.h"
#include "FocusController.h"
#include "Frame.h"
#include "HTMLIFrameElement.h"
#include "HitTestResult.h"
#include "InspectorController.h"
#include "InspectorDebuggableType.h"
#include "InspectorFrontendClient.h"
#include "JSDOMConvertInterface.h"
#include "JSDOMExceptionHandling.h"
#include "JSExecState.h"
#include "JSInspectorFrontendHost.h"
#include "MouseEvent.h"
#include "Node.h"
#include "Page.h"
#include "PagePasteboardContext.h"
#include "Pasteboard.h"
#include "ScriptState.h"
#include "Settings.h"
#include "SystemSoundManager.h"
#include "UserGestureIndicator.h"
#include <JavaScriptCore/ScriptFunctionCall.h>
#include <pal/system/Sound.h>
#include <wtf/JSONValues.h>
#include <wtf/StdLibExtras.h>
#include <wtf/persistence/PersistentDecoder.h>
#include <wtf/text/Base64.h>

namespace WebCore {

using namespace Inspector;
using ValueOrException = Expected<JSC::JSValue, ExceptionDetails>;

#if ENABLE(CONTEXT_MENUS)
class FrontendMenuProvider : public ContextMenuProvider {
public:
    static Ref<FrontendMenuProvider> create(InspectorFrontendHost* frontendHost, Deprecated::ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
    {
        return adoptRef(*new FrontendMenuProvider(frontendHost, frontendApiObject, items));
    }
    
    void disconnect()
    {
        m_frontendApiObject = { };
        m_frontendHost = nullptr;
    }
    
private:
    FrontendMenuProvider(InspectorFrontendHost* frontendHost, Deprecated::ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
        : m_frontendHost(frontendHost)
        , m_frontendApiObject(frontendApiObject)
        , m_items(items)
    {
    }

    ~FrontendMenuProvider() override
    {
        contextMenuCleared();
    }
    
    void populateContextMenu(ContextMenu* menu) override
    {
        for (auto& item : m_items)
            menu->appendItem(item);
    }
    
    void contextMenuItemSelected(ContextMenuAction action, const String&) override
    {
        if (m_frontendHost) {
            UserGestureIndicator gestureIndicator(ProcessingUserGesture);
            int itemNumber = action - ContextMenuItemBaseCustomTag;

            Deprecated::ScriptFunctionCall function(m_frontendApiObject, "contextMenuItemSelected", WebCore::functionCallHandlerFromAnyThread);
            function.appendArgument(itemNumber);
            function.call();
        }
    }
    
    void contextMenuCleared() override
    {
        if (m_frontendHost) {
            Deprecated::ScriptFunctionCall function(m_frontendApiObject, "contextMenuCleared", WebCore::functionCallHandlerFromAnyThread);
            function.call();

            m_frontendHost->m_menuProvider = nullptr;
        }
        m_items.clear();
    }

    InspectorFrontendHost* m_frontendHost;
    Deprecated::ScriptObject m_frontendApiObject;
    Vector<ContextMenuItem> m_items;
};
#endif

InspectorFrontendHost::InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage)
    : m_client(client)
    , m_frontendPage(frontendPage)
#if ENABLE(CONTEXT_MENUS)
    , m_menuProvider(nullptr)
#endif
{
}

InspectorFrontendHost::~InspectorFrontendHost()
{
    ASSERT(!m_client);
}

void InspectorFrontendHost::disconnectClient()
{
    m_client = nullptr;
#if ENABLE(CONTEXT_MENUS)
    if (m_menuProvider)
        m_menuProvider->disconnect();
#endif
    m_frontendPage = nullptr;
}

void InspectorFrontendHost::addSelfToGlobalObjectInWorld(DOMWrapperWorld& world)
{
    auto& lexicalGlobalObject = *globalObject(world, m_frontendPage ? &m_frontendPage->mainFrame() : nullptr);
    auto& vm = lexicalGlobalObject.vm();
    JSC::JSLockHolder lock(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject);
    globalObject.putDirect(vm, JSC::Identifier::fromString(vm, "InspectorFrontendHost"), toJS<IDLInterface<InspectorFrontendHost>>(lexicalGlobalObject, globalObject, *this));
    if (UNLIKELY(scope.exception()))
        reportException(&lexicalGlobalObject, scope.exception());
}

void InspectorFrontendHost::loaded()
{
    if (m_client)
        m_client->frontendLoaded();
}

static std::optional<InspectorFrontendClient::DockSide> dockSideFromString(const String& dockSideString)
{
    if (dockSideString == "undocked")
        return InspectorFrontendClient::DockSide::Undocked;
    if (dockSideString == "right")
        return InspectorFrontendClient::DockSide::Right;
    if (dockSideString == "left")
        return InspectorFrontendClient::DockSide::Left;
    if (dockSideString == "bottom")
        return InspectorFrontendClient::DockSide::Bottom;
    return std::nullopt;
}

bool InspectorFrontendHost::supportsDockSide(const String& dockSideString)
{
    if (!m_client)
        return false;

    auto dockSide = dockSideFromString(dockSideString);
    if (!dockSide)
        return false;

    return m_client->supportsDockSide(dockSide.value());
}

void InspectorFrontendHost::requestSetDockSide(const String& dockSideString)
{
    if (!m_client)
        return;

    auto dockSide = dockSideFromString(dockSideString);
    if (!dockSide)
        return;

    m_client->requestSetDockSide(dockSide.value());
}

void InspectorFrontendHost::closeWindow()
{
    if (m_client) {
        m_client->closeWindow();
        disconnectClient(); // Disconnect from client.
    }
}

void InspectorFrontendHost::reopen()
{
    if (m_client)
        m_client->reopen();
}

void InspectorFrontendHost::reset()
{
    if (m_client)
        m_client->resetState();
    reopen();
}

void InspectorFrontendHost::bringToFront()
{
    if (m_client)
        m_client->bringToFront();
}

void InspectorFrontendHost::inspectedURLChanged(const String& newURL)
{
    if (m_client)
        m_client->inspectedURLChanged(newURL);
}

void InspectorFrontendHost::setZoomFactor(float zoom)
{
    if (m_frontendPage)
        m_frontendPage->mainFrame().setPageAndTextZoomFactors(zoom, 1);
}

float InspectorFrontendHost::zoomFactor()
{
    if (m_frontendPage)
        return m_frontendPage->mainFrame().pageZoomFactor();

    return 1.0;
}

void InspectorFrontendHost::setForcedAppearance(String appearance)
{
    if (appearance == "light"_s) {
        if (m_frontendPage)
            m_frontendPage->setUseDarkAppearanceOverride(false);
        if (m_client)
            m_client->setForcedAppearance(InspectorFrontendClient::Appearance::Light);
        return;
    }

    if (appearance == "dark"_s) {
        if (m_frontendPage)
            m_frontendPage->setUseDarkAppearanceOverride(true);
        if (m_client)
            m_client->setForcedAppearance(InspectorFrontendClient::Appearance::Dark);
        return;
    }

    if (m_frontendPage)
        m_frontendPage->setUseDarkAppearanceOverride(std::nullopt);
    if (m_client)
        m_client->setForcedAppearance(InspectorFrontendClient::Appearance::System);
}

String InspectorFrontendHost::userInterfaceLayoutDirection()
{
    if (m_client && m_client->userInterfaceLayoutDirection() == UserInterfaceLayoutDirection::RTL)
        return "rtl"_s;

    return "ltr"_s;
}

void InspectorFrontendHost::setAttachedWindowHeight(unsigned height)
{
    if (m_client)
        m_client->changeAttachedWindowHeight(height);
}

void InspectorFrontendHost::setAttachedWindowWidth(unsigned width)
{
    if (m_client)
        m_client->changeAttachedWindowWidth(width);
}

void InspectorFrontendHost::setSheetRect(float x, float y, unsigned width, unsigned height)
{
    if (m_client)
        m_client->changeSheetRect(FloatRect(x, y, width, height));
}

void InspectorFrontendHost::startWindowDrag()
{
    if (m_client)
        m_client->startWindowDrag();
}

void InspectorFrontendHost::moveWindowBy(float x, float y) const
{
    if (m_client)
        m_client->moveWindowBy(x, y);
}

bool InspectorFrontendHost::isRemote() const
{
    return m_client && m_client->isRemote();
}

String InspectorFrontendHost::localizedStringsURL() const
{
    return m_client ? m_client->localizedStringsURL() : String();
}

String InspectorFrontendHost::backendCommandsURL() const
{
    return m_client ? m_client->backendCommandsURL() : String();
}

static String debuggableTypeToString(DebuggableType debuggableType)
{
    switch (debuggableType) {
    case DebuggableType::ITML:
        return "itml"_s;
    case DebuggableType::JavaScript:
        return "javascript"_s;
    case DebuggableType::Page:
        return "page"_s;
    case DebuggableType::ServiceWorker:
        return "service-worker"_s;
    case DebuggableType::WebPage:
        return "web-page"_s;
    }

    ASSERT_NOT_REACHED();
    return String();
}

InspectorFrontendHost::DebuggableInfo InspectorFrontendHost::debuggableInfo() const
{
    if (!m_client)
        return {debuggableTypeToString(DebuggableType::JavaScript), "Unknown"_s, "Unknown"_s, "Unknown"_s, false};

    return {
        debuggableTypeToString(m_client->debuggableType()),
        m_client->targetPlatformName(),
        m_client->targetBuildVersion(),
        m_client->targetProductVersion(),
        m_client->targetIsSimulator(),
    };
}

unsigned InspectorFrontendHost::inspectionLevel() const
{
    return m_client ? m_client->inspectionLevel() : 1;
}

String InspectorFrontendHost::platform() const
{
#if PLATFORM(COCOA)
    return "mac"_s;
#elif OS(WINDOWS)
    return "windows"_s;
#elif OS(LINUX)
    return "linux"_s;
#elif OS(FREEBSD)
    return "freebsd"_s;
#elif OS(OPENBSD)
    return "openbsd"_s;
#else
    return "unknown"_s;
#endif
}

String InspectorFrontendHost::platformVersionName() const
{
#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
    return "monterey"_s;
#elif PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 110000
    return "big-sur"_s;
#elif PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500
    return "catalina"_s;
#else
    return emptyString();
#endif
}

String InspectorFrontendHost::port() const
{
#if PLATFORM(GTK)
    return "gtk"_s;
#else
    return "unknown"_s;
#endif
}

void InspectorFrontendHost::copyText(const String& text)
{
    auto pageID = m_frontendPage ? m_frontendPage->mainFrame().pageID() : std::nullopt;
    Pasteboard::createForCopyAndPaste(PagePasteboardContext::create(WTFMove(pageID)))->writePlainText(text, Pasteboard::CannotSmartReplace);
}

void InspectorFrontendHost::killText(const String& text, bool shouldPrependToKillRing, bool shouldStartNewSequence)
{
    if (!m_frontendPage)
        return;

    Editor& editor = m_frontendPage->focusController().focusedOrMainFrame().editor();
    editor.setStartNewKillRingSequence(shouldStartNewSequence);
    Editor::KillRingInsertionMode insertionMode = shouldPrependToKillRing ? Editor::KillRingInsertionMode::PrependText : Editor::KillRingInsertionMode::AppendText;
    editor.addTextToKillRing(text, insertionMode);
}

void InspectorFrontendHost::openURLExternally(const String& url)
{
    if (WTF::protocolIsJavaScript(url))
        return;

    if (m_client)
        m_client->openURLExternally(url);
}

bool InspectorFrontendHost::canSave()
{
    if (m_client)
        return m_client->canSave();
    return false;
}

void InspectorFrontendHost::save(const String& url, const String& content, bool base64Encoded, bool forceSaveAs)
{
    if (m_client)
        m_client->save(url, content, base64Encoded, forceSaveAs);
}

void InspectorFrontendHost::append(const String& url, const String& content)
{
    if (m_client)
        m_client->append(url, content);
}

void InspectorFrontendHost::close(const String&)
{
}

void InspectorFrontendHost::sendMessageToBackend(const String& message)
{
    if (m_client)
        m_client->sendMessageToBackend(message);
}

#if ENABLE(CONTEXT_MENUS)

static void populateContextMenu(Vector<InspectorFrontendHost::ContextMenuItem>&& items, ContextMenu& menu)
{
    for (auto& item : items) {
        if (item.type == "separator") {
            menu.appendItem({ SeparatorType, ContextMenuItemTagNoAction, { } });
            continue;
        }

        if (item.type == "subMenu" && item.subItems) {
            ContextMenu subMenu;
            populateContextMenu(WTFMove(*item.subItems), subMenu);

            menu.appendItem({ SubmenuType, ContextMenuItemTagNoAction, item.label, &subMenu });
            continue;
        }

        auto type = item.type == "checkbox" ? CheckableActionType : ActionType;
        auto action = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + item.id.value_or(0));
        ContextMenuItem menuItem = { type, action, item.label };
        if (item.enabled)
            menuItem.setEnabled(*item.enabled);
        if (item.checked)
            menuItem.setChecked(*item.checked);
        menu.appendItem(menuItem);
    }
}
#endif

void InspectorFrontendHost::showContextMenu(Event& event, Vector<ContextMenuItem>&& items)
{
#if ENABLE(CONTEXT_MENUS)
    ASSERT(m_frontendPage);

    auto& lexicalGlobalObject = *globalObject(debuggerWorld(), &m_frontendPage->mainFrame());
    auto& vm = lexicalGlobalObject.vm();
    auto value = lexicalGlobalObject.get(&lexicalGlobalObject, JSC::Identifier::fromString(vm, "InspectorFrontendAPI"));
    ASSERT(value);
    ASSERT(value.isObject());
    auto* frontendAPIObject = asObject(value);
    
    ContextMenu menu;
    populateContextMenu(WTFMove(items), menu);

    auto menuProvider = FrontendMenuProvider::create(this, { &lexicalGlobalObject, frontendAPIObject }, menu.items());
    m_menuProvider = menuProvider.ptr();
    m_frontendPage->contextMenuController().showContextMenu(event, menuProvider);
#else
    UNUSED_PARAM(event);
    UNUSED_PARAM(items);
#endif
}

void InspectorFrontendHost::dispatchEventAsContextMenuEvent(Event& event)
{
#if ENABLE(CONTEXT_MENUS) && USE(ACCESSIBILITY_CONTEXT_MENUS)
    if (!is<MouseEvent>(event))
        return;

    auto& mouseEvent = downcast<MouseEvent>(event);
    auto& frame = *downcast<Node>(mouseEvent.target())->document().frame();
    m_frontendPage->contextMenuController().showContextMenuAt(frame, roundedIntPoint(mouseEvent.absoluteLocation()));
#else
    UNUSED_PARAM(event);
#endif
}

bool InspectorFrontendHost::isUnderTest()
{
    return m_client && m_client->isUnderTest();
}

bool InspectorFrontendHost::isExperimentalBuild()
{
#if ENABLE(EXPERIMENTAL_FEATURES)
    return true;
#else
    return false;
#endif
}

void InspectorFrontendHost::unbufferedLog(const String& message)
{
    // This is used only for debugging inspector tests.
    WTFLogAlways("%s", message.utf8().data());
}

void InspectorFrontendHost::beep()
{
    SystemSoundManager::singleton().systemBeep();
}

void InspectorFrontendHost::inspectInspector()
{
    setAllowsInspectingInspector(true);

    if (m_frontendPage)
        m_frontendPage->inspectorController().show();
}

bool InspectorFrontendHost::isBeingInspected()
{
    if (!m_frontendPage)
        return false;

    InspectorController& inspectorController = m_frontendPage->inspectorController();
    return inspectorController.hasLocalFrontend() || inspectorController.hasRemoteFrontend();
}

void InspectorFrontendHost::setAllowsInspectingInspector(bool allow)
{
    if (m_frontendPage)
        m_frontendPage->settings().setDeveloperExtrasEnabled(allow);
}

bool InspectorFrontendHost::supportsShowCertificate() const
{
#if PLATFORM(COCOA)
    return true;
#else
    return false;
#endif
}

bool InspectorFrontendHost::showCertificate(const String& serializedCertificate)
{
    if (!m_client)
        return false;

    auto data = base64Decode(serializedCertificate);
    if (!data)
        return false;

    WTF::Persistence::Decoder decoder({ data->data(), data->size() });
    std::optional<CertificateInfo> certificateInfo;
    decoder >> certificateInfo;
    if (!certificateInfo)
        return false;

    if (certificateInfo->isEmpty())
        return false;

    m_client->showCertificate(*certificateInfo);
    return true;
}

bool InspectorFrontendHost::supportsDiagnosticLogging()
{
#if ENABLE(INSPECTOR_TELEMETRY)
    return m_client && m_client->supportsDiagnosticLogging();
#else
    return false;
#endif
}

#if ENABLE(INSPECTOR_TELEMETRY)
bool InspectorFrontendHost::diagnosticLoggingAvailable()
{
    return m_client && m_client->diagnosticLoggingAvailable();
}

static std::optional<DiagnosticLoggingClient::ValuePayload> valuePayloadFromJSONValue(Ref<JSON::Value>&& value)
{
    switch (value->type()) {
    case JSON::Value::Type::Array:
    case JSON::Value::Type::Null:
    case JSON::Value::Type::Object:
        ASSERT_NOT_REACHED();
        return std::nullopt;

    case JSON::Value::Type::Boolean:
        return DiagnosticLoggingClient::ValuePayload(value->asBoolean().value_or(false));

    case JSON::Value::Type::Double:
        return DiagnosticLoggingClient::ValuePayload(value->asDouble().value_or(0));

    case JSON::Value::Type::Integer:
        return DiagnosticLoggingClient::ValuePayload(static_cast<long long>(value->asInteger().value_or(0)));

    case JSON::Value::Type::String:
        return DiagnosticLoggingClient::ValuePayload(value->asString());
    }

    ASSERT_NOT_REACHED();
    return std::nullopt;
}

void InspectorFrontendHost::logDiagnosticEvent(const String& eventName, const String& payloadString)
{
    if (!supportsDiagnosticLogging())
        return;

    auto payloadValue = JSON::Value::parseJSON(payloadString);
    if (!payloadValue)
        return;

    auto payloadObject = payloadValue->asObject();
    if (!payloadObject)
        return;

    DiagnosticLoggingClient::ValueDictionary dictionary;
    for (auto& [key, value] : *payloadObject) {
        if (auto valuePayload = valuePayloadFromJSONValue(WTFMove(value)))
            dictionary.set(key, WTFMove(valuePayload.value()));
    }

    m_client->logDiagnosticEvent(makeString("WebInspector."_s, eventName), dictionary);
}
#endif // ENABLE(INSPECTOR_TELEMETRY)

bool InspectorFrontendHost::supportsWebExtensions()
{
#if ENABLE(INSPECTOR_EXTENSIONS)
    return m_client && m_client->supportsWebExtensions();
#else
    return false;
#endif
}

#if ENABLE(INSPECTOR_EXTENSIONS)
void InspectorFrontendHost::didShowExtensionTab(const String& extensionID, const String& extensionTabID)
{
    if (!m_client)
        return;
    
    m_client->didShowExtensionTab(extensionID, extensionTabID);
}

void InspectorFrontendHost::didHideExtensionTab(const String& extensionID, const String& extensionTabID)
{
    if (!m_client)
        return;
    
    m_client->didHideExtensionTab(extensionID, extensionTabID);
}

void InspectorFrontendHost::inspectedPageDidNavigate(const String& newURLString)
{
    if (!m_client)
        return;
    
    m_client->inspectedPageDidNavigate({ URL(), newURLString });
}

ExceptionOr<JSC::JSValue> InspectorFrontendHost::evaluateScriptInExtensionTab(HTMLIFrameElement& extensionFrameElement, const String& scriptSource)
{
    Frame* frame = extensionFrameElement.contentFrame();
    if (!frame)
        return Exception { InvalidStateError, "Unable to find global object for <iframe>"_s };

    Ref<Frame> protectedFrame(*frame);

    JSDOMGlobalObject* frameGlobalObject = frame->script().globalObject(mainThreadNormalWorld());
    if (!frameGlobalObject)
        return Exception { InvalidStateError, "Unable to find global object for <iframe>"_s };

    JSC::SuspendExceptionScope scope(&frameGlobalObject->vm());
    ValueOrException result = frame->script().evaluateInWorld(ScriptSourceCode(scriptSource), mainThreadNormalWorld());
    
    if (!result)
        return Exception { InvalidStateError, result.error().message };

    return WTFMove(result.value());
}

#endif // ENABLE(INSPECTOR_EXTENSIONS)


} // namespace WebCore
