/*
 * Copyright (C) 2017 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 "InspectorCanvasAgent.h"

#include "CanvasRenderingContext.h"
#include "CanvasRenderingContext2D.h"
#include "Document.h"
#include "Element.h"
#include "Frame.h"
#include "ImageBitmapRenderingContext.h"
#include "InspectorDOMAgent.h"
#include "InstrumentingAgents.h"
#include "JSCanvasRenderingContext2D.h"
#include "JSImageBitmapRenderingContext.h"
#include "JSMainThreadExecState.h"
#include "OffscreenCanvas.h"
#include "ScriptState.h"
#include "StringAdaptors.h"
#include <JavaScriptCore/IdentifiersFactory.h>
#include <JavaScriptCore/InjectedScript.h>
#include <JavaScriptCore/InjectedScriptManager.h>
#include <JavaScriptCore/InspectorProtocolObjects.h>
#include <JavaScriptCore/JSCInlines.h>

#if ENABLE(WEBGL)
#include "JSWebGLRenderingContext.h"
#include "WebGLProgram.h"
#include "WebGLShader.h"
#endif

#if ENABLE(WEBGL2)
#include "JSWebGL2RenderingContext.h"
#endif

#if ENABLE(WEBGPU)
#include "JSWebGPURenderingContext.h"
#endif


namespace WebCore {

using namespace Inspector;

InspectorCanvasAgent::InspectorCanvasAgent(WebAgentContext& context)
    : InspectorAgentBase(ASCIILiteral("Canvas"), context)
    , m_frontendDispatcher(std::make_unique<Inspector::CanvasFrontendDispatcher>(context.frontendRouter))
    , m_backendDispatcher(Inspector::CanvasBackendDispatcher::create(context.backendDispatcher, this))
    , m_injectedScriptManager(context.injectedScriptManager)
    , m_canvasDestroyedTimer(*this, &InspectorCanvasAgent::canvasDestroyedTimerFired)
    , m_canvasRecordingTimer(*this, &InspectorCanvasAgent::canvasRecordingTimerFired)
{
}

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

void InspectorCanvasAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason)
{
    ErrorString ignored;
    disable(ignored);
}

void InspectorCanvasAgent::discardAgent()
{
    clearCanvasData();
}

void InspectorCanvasAgent::enable(ErrorString&)
{
    if (m_enabled)
        return;

    m_enabled = true;

    const bool captureBacktrace = false;
    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
        m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(m_instrumentingAgents, captureBacktrace));

#if ENABLE(WEBGL)
        if (is<WebGLRenderingContextBase>(inspectorCanvas->context())) {
            WebGLRenderingContextBase& contextWebGL = downcast<WebGLRenderingContextBase>(inspectorCanvas->context());
            if (std::optional<Vector<String>> extensions = contextWebGL.getSupportedExtensions()) {
                for (const String& extension : *extensions) {
                    if (contextWebGL.extensionIsEnabled(extension))
                        m_frontendDispatcher->extensionEnabled(inspectorCanvas->identifier(), extension);
                }
            }
        }
#endif
    }

#if ENABLE(WEBGL)
    for (auto& inspectorProgram : m_identifierToInspectorProgram.values()) {
        auto& inspectorCanvas = inspectorProgram->canvas();
        m_frontendDispatcher->programCreated(inspectorCanvas.identifier(), inspectorProgram->identifier());
    }
#endif
}

void InspectorCanvasAgent::disable(ErrorString&)
{
    if (!m_enabled)
        return;

    if (m_canvasDestroyedTimer.isActive())
        m_canvasDestroyedTimer.stop();

    m_removedCanvasIdentifiers.clear();

    if (m_canvasRecordingTimer.isActive())
        m_canvasRecordingTimer.stop();

    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values())
        inspectorCanvas->resetRecordingData();

    m_enabled = false;
}

void InspectorCanvasAgent::requestNode(ErrorString& errorString, const String& canvasId, int* nodeId)
{
    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    if (!inspectorCanvas)
        return;

    auto* node = inspectorCanvas->canvasElement();
    if (!node) {
        errorString = ASCIILiteral("No node for canvas");
        return;
    }

    int documentNodeId = m_instrumentingAgents.inspectorDOMAgent()->boundNodeId(&node->document());
    if (!documentNodeId) {
        errorString = ASCIILiteral("Document has not been requested");
        return;
    }

    *nodeId = m_instrumentingAgents.inspectorDOMAgent()->pushNodeToFrontend(errorString, documentNodeId, node);
}

void InspectorCanvasAgent::requestContent(ErrorString& errorString, const String& canvasId, String* content)
{
    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    if (!inspectorCanvas)
        return;

    // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations

    if (auto* node = inspectorCanvas->canvasElement()) {
        if (is<CanvasRenderingContext2D>(inspectorCanvas->context()) || is<ImageBitmapRenderingContext>(inspectorCanvas->context())) {
            auto result = node->toDataURL(ASCIILiteral("image/png"));
            if (result.hasException()) {
                errorString = result.releaseException().releaseMessage();
                return;
            }
            *content = result.releaseReturnValue().string;
            return;
        }

#if ENABLE(WEBGL)
        if (is<WebGLRenderingContextBase>(inspectorCanvas->context())) {
            WebGLRenderingContextBase& contextWebGLBase = downcast<WebGLRenderingContextBase>(inspectorCanvas->context());

            contextWebGLBase.setPreventBufferClearForInspector(true);
            auto result = node->toDataURL(ASCIILiteral("image/png"));
            contextWebGLBase.setPreventBufferClearForInspector(false);

            if (result.hasException()) {
                errorString = result.releaseException().releaseMessage();
                return;
            }
            *content = result.releaseReturnValue().string;
            return;
        }
#endif
    }

    // FIXME: <https://webkit.org/b/173621> Web Inspector: Support getting the content of WebGPU context;
    errorString = ASCIILiteral("Unsupported canvas context type");
}

void InspectorCanvasAgent::requestCSSCanvasClientNodes(ErrorString& errorString, const String& canvasId, RefPtr<JSON::ArrayOf<int>>& result)
{
    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    if (!inspectorCanvas)
        return;

    result = JSON::ArrayOf<int>::create();
    for (auto* client : inspectorCanvas->context().canvasBase().cssCanvasClients()) {
        if (int documentNodeId = m_instrumentingAgents.inspectorDOMAgent()->boundNodeId(&client->document()))
            result->addItem(m_instrumentingAgents.inspectorDOMAgent()->pushNodeToFrontend(errorString, documentNodeId, client));
    }
}

static JSC::JSValue contextAsScriptValue(JSC::ExecState& state, CanvasRenderingContext& context)
{
    JSC::JSLockHolder lock(&state);

    if (is<CanvasRenderingContext2D>(context))
        return toJS(&state, deprecatedGlobalObjectForPrototype(&state), downcast<CanvasRenderingContext2D>(context));
#if ENABLE(WEBGL)
    if (is<WebGLRenderingContext>(context))
        return toJS(&state, deprecatedGlobalObjectForPrototype(&state), downcast<WebGLRenderingContext>(context));
#endif
#if ENABLE(WEBGL2)
    if (is<WebGL2RenderingContext>(context))
        return toJS(&state, deprecatedGlobalObjectForPrototype(&state), downcast<WebGL2RenderingContext>(context));
#endif
#if ENABLE(WEBGPU)
    if (is<WebGPURenderingContext>(context))
        return toJS(&state, deprecatedGlobalObjectForPrototype(&state), downcast<WebGPURenderingContext>(context));
#endif
    if (is<ImageBitmapRenderingContext>(context))
        return toJS(&state, deprecatedGlobalObjectForPrototype(&state), downcast<ImageBitmapRenderingContext>(context));

    return { };
}

void InspectorCanvasAgent::resolveCanvasContext(ErrorString& errorString, const String& canvasId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
{
    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    if (!inspectorCanvas)
        return;

    auto& state = *inspectorCanvas->context().canvasBase().scriptExecutionContext()->execState();
    auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state);
    ASSERT(!injectedScript.hasNoValue());

    JSC::JSValue value = contextAsScriptValue(state, inspectorCanvas->context());
    if (!value) {
        ASSERT_NOT_REACHED();
        errorString = ASCIILiteral("Unknown context type");
        return;
    }

    String objectGroupName = objectGroup ? *objectGroup : String();
    result = injectedScript.wrapObject(value, objectGroupName);
}

void InspectorCanvasAgent::startRecording(ErrorString& errorString, const String& canvasId, const bool* singleFrame, const int* memoryLimit)
{
    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    if (!inspectorCanvas)
        return;

    if (inspectorCanvas->context().callTracingActive()) {
        errorString = ASCIILiteral("Already recording canvas");
        return;
    }

    inspectorCanvas->resetRecordingData();
    if (singleFrame)
        inspectorCanvas->setSingleFrame(*singleFrame);
    if (memoryLimit)
        inspectorCanvas->setBufferLimit(*memoryLimit);

    inspectorCanvas->context().setCallTracingActive(true);
}

void InspectorCanvasAgent::stopRecording(ErrorString& errorString, const String& canvasId)
{
    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    if (!inspectorCanvas)
        return;

    if (!inspectorCanvas->context().callTracingActive()) {
        errorString = ASCIILiteral("No active recording for canvas");
        return;
    }

    didFinishRecordingCanvasFrame(inspectorCanvas->context(), true);
}

void InspectorCanvasAgent::requestShaderSource(ErrorString& errorString, const String& programId, const String& shaderType, String* content)
{
#if ENABLE(WEBGL)
    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
    if (!inspectorProgram)
        return;

    auto* shader = inspectorProgram->shaderForType(shaderType);
    if (!shader) {
        errorString = ASCIILiteral("No shader for given type.");
        return;
    }

    *content = shader->getSource();
#else
    UNUSED_PARAM(programId);
    UNUSED_PARAM(shaderType);
    UNUSED_PARAM(content);
    errorString = ASCIILiteral("WebGL is not supported.");
#endif
}

void InspectorCanvasAgent::updateShader(ErrorString& errorString, const String& programId, const String& shaderType, const String& source)
{
#if ENABLE(WEBGL)
    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
    if (!inspectorProgram)
        return;

    auto* shader = inspectorProgram->shaderForType(shaderType);
    if (!shader) {
        errorString = ASCIILiteral("No shader for given type.");
        return;
    }

    WebGLRenderingContextBase& contextWebGL = inspectorProgram->context();
    contextWebGL.shaderSource(shader, source);
    contextWebGL.compileShader(shader);

    if (!shader->isValid()) {
        errorString = ASCIILiteral("Shader compilation failed.");
        return;
    }

    contextWebGL.linkProgramWithoutInvalidatingAttribLocations(&inspectorProgram->program());
#else
    UNUSED_PARAM(programId);
    UNUSED_PARAM(shaderType);
    UNUSED_PARAM(source);
    errorString = ASCIILiteral("WebGL is not supported.");
#endif
}

void InspectorCanvasAgent::setShaderProgramDisabled(ErrorString& errorString, const String& programId, bool disabled)
{
#if ENABLE(WEBGL)
    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
    if (!inspectorProgram)
        return;

    inspectorProgram->setDisabled(disabled);
#else
    UNUSED_PARAM(programId);
    UNUSED_PARAM(disabled);
    errorString = ASCIILiteral("WebGL is not supported.");
#endif
}

void InspectorCanvasAgent::setShaderProgramHighlighted(ErrorString& errorString, const String& programId, bool highlighted)
{
#if ENABLE(WEBGL)
    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
    if (!inspectorProgram)
        return;

    inspectorProgram->setHighlighted(highlighted);
#else
    UNUSED_PARAM(programId);
    UNUSED_PARAM(highlighted);
    errorString = ASCIILiteral("WebGL is not supported.");
#endif
}

void InspectorCanvasAgent::frameNavigated(Frame& frame)
{
    if (frame.isMainFrame()) {
        clearCanvasData();
        return;
    }

    Vector<InspectorCanvas*> inspectorCanvases;
    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
        if (auto* canvasElement = inspectorCanvas->canvasElement()) {
            if (canvasElement->document().frame() == &frame)
                inspectorCanvases.append(inspectorCanvas.get());
        }
    }

    for (auto* inspectorCanvas : inspectorCanvases) {
        inspectorCanvas->context().canvasBase().removeObserver(*this);

        String identifier = unbindCanvas(*inspectorCanvas);
        if (m_enabled)
            m_frontendDispatcher->canvasRemoved(identifier);
    }
}

void InspectorCanvasAgent::didChangeCSSCanvasClientNodes(CanvasBase& canvasBase)
{
    auto* context = canvasBase.renderingContext();
    if (!context) {
        ASSERT_NOT_REACHED();
        return;
    }

    auto* inspectorCanvas = findInspectorCanvas(*context);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    m_frontendDispatcher->cssCanvasClientNodesChanged(inspectorCanvas->identifier());
}

void InspectorCanvasAgent::didCreateCanvasRenderingContext(CanvasRenderingContext& context)
{
    if (findInspectorCanvas(context)) {
        ASSERT_NOT_REACHED();
        return;
    }

    context.canvasBase().addObserver(*this);

    auto inspectorCanvas = InspectorCanvas::create(context);

    if (m_enabled) {
        const bool captureBacktrace = true;
        m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(m_instrumentingAgents, captureBacktrace));
    }

    m_identifierToInspectorCanvas.set(inspectorCanvas->identifier(), WTFMove(inspectorCanvas));
}

void InspectorCanvasAgent::didChangeCanvasMemory(CanvasRenderingContext& context)
{
    auto* inspectorCanvas = findInspectorCanvas(context);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations

    if (auto* node = inspectorCanvas->canvasElement())
        m_frontendDispatcher->canvasMemoryChanged(inspectorCanvas->identifier(), node->memoryCost());
}

void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters)
{
    auto* inspectorCanvas = findInspectorCanvas(canvasRenderingContext);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    ASSERT(canvasRenderingContext.callTracingActive());
    if (!canvasRenderingContext.callTracingActive())
        return;

    inspectorCanvas->recordAction(name, WTFMove(parameters));

    if (!m_canvasRecordingTimer.isActive())
        m_canvasRecordingTimer.startOneShot(0_s);

    if (!inspectorCanvas->hasBufferSpace())
        didFinishRecordingCanvasFrame(inspectorCanvas->context(), true);
}

void InspectorCanvasAgent::canvasDestroyed(CanvasBase& canvasBase)
{
    auto* context = canvasBase.renderingContext();
    if (!context)
        return;

    auto* inspectorCanvas = findInspectorCanvas(*context);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    String identifier = unbindCanvas(*inspectorCanvas);
    if (!m_enabled)
        return;

    // WebCore::CanvasObserver::canvasDestroyed is called in response to the GC destroying the CanvasBase.
    // Due to the single-process model used in WebKit1, the event must be dispatched from a timer to prevent
    // the frontend from making JS allocations while the GC is still active.
    m_removedCanvasIdentifiers.append(identifier);

    if (!m_canvasDestroyedTimer.isActive())
        m_canvasDestroyedTimer.startOneShot(0_s);
}

void InspectorCanvasAgent::didFinishRecordingCanvasFrame(CanvasRenderingContext& context, bool forceDispatch)
{
    auto* inspectorCanvas = findInspectorCanvas(context);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    if (!inspectorCanvas->context().callTracingActive())
        return;

    if (!inspectorCanvas->hasRecordingData()) {
        if (forceDispatch) {
            m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), nullptr);

            inspectorCanvas->resetRecordingData();
        }
        return;
    }

    if (forceDispatch)
        inspectorCanvas->markCurrentFrameIncomplete();

    inspectorCanvas->finalizeFrame();
    if (inspectorCanvas->currentFrameHasData())
        m_frontendDispatcher->recordingProgress(inspectorCanvas->identifier(), inspectorCanvas->releaseFrames(), inspectorCanvas->bufferUsed());

    if (!forceDispatch && !inspectorCanvas->singleFrame())
        return;

    // FIXME: <https://webkit.org/b/176008> Web Inspector: Record actions performed on WebGL2RenderingContext

    Inspector::Protocol::Recording::Type type;
    if (is<CanvasRenderingContext2D>(inspectorCanvas->context()))
        type = Inspector::Protocol::Recording::Type::Canvas2D;
#if ENABLE(WEBGL)
    else if (is<WebGLRenderingContext>(inspectorCanvas->context()))
        type = Inspector::Protocol::Recording::Type::CanvasWebGL;
#endif
    else {
        ASSERT_NOT_REACHED();
        type = Inspector::Protocol::Recording::Type::Canvas2D;
    }

    auto recording = Inspector::Protocol::Recording::Recording::create()
        .setVersion(1)
        .setType(type)
        .setInitialState(inspectorCanvas->releaseInitialState())
        .setData(inspectorCanvas->releaseData())
        .release();

    const String& name = inspectorCanvas->recordingName();
    if (!name.isEmpty())
        recording->setName(name);

    m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), WTFMove(recording));

    inspectorCanvas->resetRecordingData();
}

void InspectorCanvasAgent::consoleStartRecordingCanvas(CanvasRenderingContext& context, JSC::ExecState& exec, JSC::JSObject* options)
{
    auto* inspectorCanvas = findInspectorCanvas(context);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    if (inspectorCanvas->context().callTracingActive())
        return;

    inspectorCanvas->resetRecordingData();

    if (options) {
        if (JSC::JSValue optionName = options->get(&exec, JSC::Identifier::fromString(&exec, "name")))
            inspectorCanvas->setRecordingName(optionName.toWTFString(&exec));
        if (JSC::JSValue optionSingleFrame = options->get(&exec, JSC::Identifier::fromString(&exec, "singleFrame")))
            inspectorCanvas->setSingleFrame(optionSingleFrame.toBoolean(&exec));
        if (JSC::JSValue optionMemoryLimit = options->get(&exec, JSC::Identifier::fromString(&exec, "memoryLimit")))
            inspectorCanvas->setBufferLimit(optionMemoryLimit.toNumber(&exec));
    }

    inspectorCanvas->context().setCallTracingActive(true);
}

#if ENABLE(WEBGL)
void InspectorCanvasAgent::didEnableExtension(WebGLRenderingContextBase& context, const String& extension)
{
    auto* inspectorCanvas = findInspectorCanvas(context);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    m_frontendDispatcher->extensionEnabled(inspectorCanvas->identifier(), extension);
}

void InspectorCanvasAgent::didCreateProgram(WebGLRenderingContextBase& context, WebGLProgram& program)
{
    auto* inspectorCanvas = findInspectorCanvas(context);
    ASSERT(inspectorCanvas);
    if (!inspectorCanvas)
        return;

    auto inspectorProgram = InspectorShaderProgram::create(program, *inspectorCanvas);
    String programIdentifier = inspectorProgram->identifier();
    m_identifierToInspectorProgram.set(programIdentifier, WTFMove(inspectorProgram));

    if (m_enabled)
        m_frontendDispatcher->programCreated(inspectorCanvas->identifier(), programIdentifier);
}

void InspectorCanvasAgent::willDeleteProgram(WebGLProgram& program)
{
    auto* inspectorProgram = findInspectorProgram(program);
    if (!inspectorProgram)
        return;

    String identifier = unbindProgram(*inspectorProgram);
    if (m_enabled)
        m_frontendDispatcher->programDeleted(identifier);
}

bool InspectorCanvasAgent::isShaderProgramDisabled(WebGLProgram& program)
{
    auto* inspectorProgram = findInspectorProgram(program);
    if (!inspectorProgram)
        return false;

    return inspectorProgram->disabled();
}

bool InspectorCanvasAgent::isShaderProgramHighlighted(WebGLProgram& program)
{
    auto* inspectorProgram = findInspectorProgram(program);
    if (!inspectorProgram)
        return false;

    return inspectorProgram->highlighted();
}
#endif

void InspectorCanvasAgent::canvasDestroyedTimerFired()
{
    if (!m_removedCanvasIdentifiers.size())
        return;

    if (m_enabled) {
        for (auto& identifier : m_removedCanvasIdentifiers)
            m_frontendDispatcher->canvasRemoved(identifier);
    }

    m_removedCanvasIdentifiers.clear();
}

void InspectorCanvasAgent::canvasRecordingTimerFired()
{
    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
        if (!inspectorCanvas->context().callTracingActive())
            continue;

        didFinishRecordingCanvasFrame(inspectorCanvas->context());
    }
}

void InspectorCanvasAgent::clearCanvasData()
{
    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values())
        inspectorCanvas->context().canvasBase().removeObserver(*this);

    m_identifierToInspectorCanvas.clear();
    m_removedCanvasIdentifiers.clear();
#if ENABLE(WEBGL)
    m_identifierToInspectorProgram.clear();
#endif

    if (m_canvasRecordingTimer.isActive())
        m_canvasRecordingTimer.stop();

    if (m_canvasDestroyedTimer.isActive())
        m_canvasDestroyedTimer.stop();
}

String InspectorCanvasAgent::unbindCanvas(InspectorCanvas& inspectorCanvas)
{
#if ENABLE(WEBGL)
    Vector<InspectorShaderProgram*> programsToRemove;
    for (auto& inspectorProgram : m_identifierToInspectorProgram.values()) {
        if (&inspectorProgram->canvas() == &inspectorCanvas)
            programsToRemove.append(inspectorProgram.get());
    }

    for (auto* inspectorProgram : programsToRemove)
        unbindProgram(*inspectorProgram);
#endif

    String identifier = inspectorCanvas.identifier();
    m_identifierToInspectorCanvas.remove(identifier);

    return identifier;
}

InspectorCanvas* InspectorCanvasAgent::assertInspectorCanvas(ErrorString& errorString, const String& identifier)
{
    RefPtr<InspectorCanvas> inspectorCanvas = m_identifierToInspectorCanvas.get(identifier);
    if (!inspectorCanvas) {
        errorString = ASCIILiteral("No canvas for given identifier.");
        return nullptr;
    }

    return inspectorCanvas.get();
}

InspectorCanvas* InspectorCanvasAgent::findInspectorCanvas(CanvasRenderingContext& context)
{
    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
        if (&inspectorCanvas->context() == &context)
            return inspectorCanvas.get();
    }

    return nullptr;
}

#if ENABLE(WEBGL)
String InspectorCanvasAgent::unbindProgram(InspectorShaderProgram& inspectorProgram)
{
    String identifier = inspectorProgram.identifier();
    m_identifierToInspectorProgram.remove(identifier);

    return identifier;
}

InspectorShaderProgram* InspectorCanvasAgent::assertInspectorProgram(ErrorString& errorString, const String& identifier)
{
    RefPtr<InspectorShaderProgram> inspectorProgram = m_identifierToInspectorProgram.get(identifier);
    if (!inspectorProgram) {
        errorString = ASCIILiteral("No shader program for given identifier.");
        return nullptr;
    }

    return inspectorProgram.get();
}

InspectorShaderProgram* InspectorCanvasAgent::findInspectorProgram(WebGLProgram& program)
{
    for (auto& inspectorProgram : m_identifierToInspectorProgram.values()) {
        if (&inspectorProgram->program() == &program)
            return inspectorProgram.get();
    }

    return nullptr;
}
#endif

} // namespace WebCore
