/*
 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. 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 COMPUTER, INC. ``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 COMPUTER, INC. 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 "core/html/HTMLCanvasElement.h"

#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptController.h"
#include "core/HTMLNames.h"
#include "core/InputTypeNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/fileapi/File.h"
#include "core/frame/ImageBitmap.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/html/ImageData.h"
#include "core/html/canvas/CanvasAsyncBlobCreator.h"
#include "core/html/canvas/CanvasContextCreationAttributes.h"
#include "core/html/canvas/CanvasFontCache.h"
#include "core/html/canvas/CanvasRenderingContext.h"
#include "core/html/canvas/CanvasRenderingContextFactory.h"
#include "core/imagebitmap/ImageBitmapOptions.h"
#include "core/layout/HitTestCanvasResult.h"
#include "core/layout/LayoutHTMLCanvas.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/PaintTiming.h"
#include "platform/Histogram.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/Canvas2DImageBufferSurface.h"
#include "platform/graphics/CanvasMetrics.h"
#include "platform/graphics/CanvasSurfaceLayerBridgeClientImpl.h"
#include "platform/graphics/ExpensiveCanvasHeuristicParameters.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/RecordingImageBufferSurface.h"
#include "platform/graphics/StaticBitmapImage.h"
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
#include "platform/transforms/AffineTransform.h"
#include "public/platform/Platform.h"
#include "public/platform/WebTraceLocation.h"
#include "wtf/CheckedNumeric.h"
#include "wtf/PtrUtil.h"
#include <math.h>
#include <memory>
#include <v8.h>

namespace blink {

using namespace HTMLNames;

namespace {

// These values come from the WhatWG spec.
const int DefaultWidth = 300;
const int DefaultHeight = 150;

#if OS(ANDROID)
// We estimate that the max limit for android phones is a quarter of that for
// desktops based on local experimental results on Android One.
const int MaxGlobalAcceleratedImageBufferCount = 25;
#else
const int MaxGlobalAcceleratedImageBufferCount = 100;
#endif

// We estimate the max limit of GPU allocated memory for canvases before Chrome
// becomes laggy by setting the total allocated memory for accelerated canvases
// to be equivalent to memory used by 100 accelerated canvases, each has a size
// of 1000*500 and 2d context.
// Each such canvas occupies 4000000 = 1000 * 500 * 2 * 4 bytes, where 2 is the
// gpuBufferCount in ImageBuffer::updateGPUMemoryUsage() and 4 means four bytes
// per pixel per buffer.
const int MaxGlobalGPUMemoryUsage = 4000000 * MaxGlobalAcceleratedImageBufferCount;

// A default value of quality argument for toDataURL and toBlob
// It is in an invalid range (outside 0.0 - 1.0) so that it will not be
// misinterpreted as a user-input value
const int UndefinedQualityValue = -1.0;

// Default image mime type for toDataURL and toBlob functions
const char DefaultMimeType[] = "image/png";

PassRefPtr<Image> createTransparentImage(const IntSize& size)
{
    DCHECK(ImageBuffer::canCreateImageBuffer(size));
    sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(size.width(), size.height());
    return StaticBitmapImage::create(surface->makeImageSnapshot());
}

} // namespace

inline HTMLCanvasElement::HTMLCanvasElement(Document& document)
    : HTMLElement(canvasTag, document)
    , ContextLifecycleObserver(&document)
    , PageVisibilityObserver(document.page())
    , m_size(DefaultWidth, DefaultHeight)
    , m_ignoreReset(false)
    , m_externallyAllocatedMemory(0)
    , m_originClean(true)
    , m_didFailToCreateImageBuffer(false)
    , m_imageBufferIsClear(false)
    , m_numFramesSinceLastRenderingModeSwitch(0)
    , m_pendingRenderingModeSwitch(false)
{
    CanvasMetrics::countCanvasContextUsage(CanvasMetrics::CanvasCreated);
    UseCounter::count(document, UseCounter::HTMLCanvasElement);
}

DEFINE_NODE_FACTORY(HTMLCanvasElement)

HTMLCanvasElement::~HTMLCanvasElement()
{
    v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
}

void HTMLCanvasElement::dispose()
{
    if (m_context) {
        m_context->detachCanvas();
        m_context = nullptr;
    }
}

void HTMLCanvasElement::parseAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& value)
{
    if (name == widthAttr || name == heightAttr)
        reset();
    HTMLElement::parseAttribute(name, oldValue, value);
}

LayoutObject* HTMLCanvasElement::createLayoutObject(const ComputedStyle& style)
{
    LocalFrame* frame = document().frame();
    if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript))
        return new LayoutHTMLCanvas(this);
    return HTMLElement::createLayoutObject(style);
}

Node::InsertionNotificationRequest HTMLCanvasElement::insertedInto(ContainerNode* node)
{
    setIsInCanvasSubtree(true);
    return HTMLElement::insertedInto(node);
}

void HTMLCanvasElement::setHeight(int value)
{
    setIntegralAttribute(heightAttr, value);
}

void HTMLCanvasElement::setWidth(int value)
{
    setIntegralAttribute(widthAttr, value);
}

HTMLCanvasElement::ContextFactoryVector& HTMLCanvasElement::renderingContextFactories()
{
    DCHECK(isMainThread());
    DEFINE_STATIC_LOCAL(ContextFactoryVector, s_contextFactories, (CanvasRenderingContext::ContextTypeCount));
    return s_contextFactories;
}

CanvasRenderingContextFactory* HTMLCanvasElement::getRenderingContextFactory(int type)
{
    DCHECK(type < CanvasRenderingContext::ContextTypeCount);
    return renderingContextFactories()[type].get();
}

void HTMLCanvasElement::registerRenderingContextFactory(std::unique_ptr<CanvasRenderingContextFactory> renderingContextFactory)
{
    CanvasRenderingContext::ContextType type = renderingContextFactory->getContextType();
    DCHECK(type < CanvasRenderingContext::ContextTypeCount);
    DCHECK(!renderingContextFactories()[type]);
    renderingContextFactories()[type] = std::move(renderingContextFactory);
}

CanvasRenderingContext* HTMLCanvasElement::getCanvasRenderingContext(const String& type, const CanvasContextCreationAttributes& attributes)
{
    CanvasRenderingContext::ContextType contextType = CanvasRenderingContext::contextTypeFromId(type);

    // Unknown type.
    if (contextType == CanvasRenderingContext::ContextTypeCount)
        return nullptr;

    // Log the aliased context type used.
    if (!m_context) {
        DEFINE_STATIC_LOCAL(EnumerationHistogram, contextTypeHistogram, ("Canvas.ContextType", CanvasRenderingContext::ContextTypeCount));
        contextTypeHistogram.count(contextType);
    }

    contextType = CanvasRenderingContext::resolveContextTypeAliases(contextType);

    CanvasRenderingContextFactory* factory = getRenderingContextFactory(contextType);
    if (!factory)
        return nullptr;

    // FIXME - The code depends on the context not going away once created, to prevent JS from
    // seeing a dangling pointer. So for now we will disallow the context from being changed
    // once it is created.
    if (m_context) {
        if (m_context->getContextType() == contextType)
            return m_context.get();

        factory->onError(this, "Canvas has an existing context of a different type");
        return nullptr;
    }

    m_context = factory->create(this, attributes, document());
    if (!m_context)
        return nullptr;

    if (m_context->is3d()) {
        updateExternallyAllocatedMemory();
    }
    setNeedsCompositingUpdate();

    return m_context.get();
}

bool HTMLCanvasElement::shouldBeDirectComposited() const
{
    return (m_context && m_context->isAccelerated()) || (hasImageBuffer() && buffer()->isExpensiveToPaint()) || (!!m_surfaceLayerBridge);
}

bool HTMLCanvasElement::isPaintable() const
{
    return (m_context && m_context->isPaintable()) || ImageBuffer::canCreateImageBuffer(size());
}

void HTMLCanvasElement::didDraw(const FloatRect& rect)
{
    if (rect.isEmpty())
        return;
    m_imageBufferIsClear = false;
    clearCopiedImage();
    if (layoutObject())
        layoutObject()->setMayNeedPaintInvalidation();
    if (m_context && m_context->is2d() && m_context->shouldAntialias() && page() && page()->deviceScaleFactor() > 1.0f) {
        FloatRect inflatedRect = rect;
        inflatedRect.inflate(1);
        m_dirtyRect.unite(inflatedRect);
    } else {
        m_dirtyRect.unite(rect);
    }
    if (m_context && m_context->is2d() && hasImageBuffer())
        buffer()->didDraw(rect);
}

void HTMLCanvasElement::didFinalizeFrame()
{
    notifyListenersCanvasChanged();

    if (m_dirtyRect.isEmpty())
        return;

    // Propagate the m_dirtyRect accumulated so far to the compositor
    // before restarting with a blank dirty rect.
    FloatRect srcRect(0, 0, size().width(), size().height());
    m_dirtyRect.intersect(srcRect);
    LayoutBox* ro = layoutBox();
    // Canvas content updates do not need to be propagated as
    // paint invalidations if the canvas is accelerated, since
    // the canvas contents are sent separately through a texture layer.
    if (ro && (!m_context || !m_context->isAccelerated())) {
        LayoutRect mappedDirtyRect(enclosingIntRect(mapRect(m_dirtyRect, srcRect, FloatRect(ro->contentBoxRect()))));
        // For querying PaintLayer::compositingState()
        // FIXME: is this invalidation using the correct compositing state?
        DisableCompositingQueryAsserts disabler;
        ro->invalidatePaintRectangle(mappedDirtyRect);
    }
    m_dirtyRect = FloatRect();

    m_numFramesSinceLastRenderingModeSwitch++;
    if (RuntimeEnabledFeatures::enableCanvas2dDynamicRenderingModeSwitchingEnabled()
        && !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) {
        if (m_context->is2d() && buffer()->isAccelerated()
            && m_numFramesSinceLastRenderingModeSwitch >= ExpensiveCanvasHeuristicParameters::MinFramesBeforeSwitch
            && !m_pendingRenderingModeSwitch) {
            if (!m_context->isAccelerationOptimalForCanvasContent()) {
                // The switch must be done asynchronously in order to avoid switching during the paint invalidation step.
                Platform::current()->currentThread()->getWebTaskRunner()->postTask(
                    BLINK_FROM_HERE,
                    WTF::bind([](WeakPtr<ImageBuffer> buffer) {
                        if (buffer) {
                            buffer->disableAcceleration();
                        }
                    },
                    m_imageBuffer->m_weakPtrFactory.createWeakPtr()));
                m_numFramesSinceLastRenderingModeSwitch = 0;
                m_pendingRenderingModeSwitch = true;
            }
        }
    }

    if (m_pendingRenderingModeSwitch && !buffer()->isAccelerated()) {
        m_pendingRenderingModeSwitch = false;
    }

    m_context->incrementFrameCount();
}

void HTMLCanvasElement::didDisableAcceleration()
{
    // We must force a paint invalidation on the canvas even if it's
    // content did not change because it layer was destroyed.
    didDraw(FloatRect(0, 0, size().width(), size().height()));
}

void HTMLCanvasElement::restoreCanvasMatrixClipStack(SkCanvas* canvas) const
{
    if (m_context)
        m_context->restoreCanvasMatrixClipStack(canvas);
}

void HTMLCanvasElement::doDeferredPaintInvalidation()
{
    DCHECK(!m_dirtyRect.isEmpty());
    if (!m_context->is2d()) {
        didFinalizeFrame();
    } else {
        DCHECK(hasImageBuffer());
        FloatRect srcRect(0, 0, size().width(), size().height());
        m_dirtyRect.intersect(srcRect);
        LayoutBox* lb = layoutBox();
        if (lb) {
            FloatRect mappedDirtyRect = mapRect(m_dirtyRect, srcRect, FloatRect(lb->contentBoxRect()));
            if (m_context->isAccelerated()) {
                // Accelerated 2D canvases need the dirty rect to be expressed relative to the
                // content box, as opposed to the layout box.
                mappedDirtyRect.move(-lb->contentBoxOffset());
            }
            m_imageBuffer->finalizeFrame(mappedDirtyRect);
        } else {
            m_imageBuffer->finalizeFrame(m_dirtyRect);
        }
    }
    DCHECK(m_dirtyRect.isEmpty());
}

void HTMLCanvasElement::reset()
{
    if (m_ignoreReset)
        return;

    m_dirtyRect = FloatRect();

    bool ok;
    bool hadImageBuffer = hasImageBuffer();

    int w = getAttribute(widthAttr).toInt(&ok);
    if (!ok || w < 0)
        w = DefaultWidth;

    int h = getAttribute(heightAttr).toInt(&ok);
    if (!ok || h < 0)
        h = DefaultHeight;

    if (m_context && m_context->is2d())
        m_context->reset();

    IntSize oldSize = size();
    IntSize newSize(w, h);

    // If the size of an existing buffer matches, we can just clear it instead of reallocating.
    // This optimization is only done for 2D canvases for now.
    if (hadImageBuffer && oldSize == newSize && m_context && m_context->is2d() && !buffer()->isRecording()) {
        if (!m_imageBufferIsClear) {
            m_imageBufferIsClear = true;
            m_context->clearRect(0, 0, width(), height());
        }
        return;
    }

    setSurfaceSize(newSize);

    if (m_context && m_context->is3d() && oldSize != size())
        m_context->reshape(width(), height());

    if (LayoutObject* layoutObject = this->layoutObject()) {
        if (layoutObject->isCanvas()) {
            if (oldSize != size()) {
                toLayoutHTMLCanvas(layoutObject)->canvasSizeChanged();
                if (layoutBox() && layoutBox()->hasAcceleratedCompositing())
                    layoutBox()->contentChanged(CanvasChanged);
            }
            if (hadImageBuffer)
                layoutObject->setShouldDoFullPaintInvalidation();
        }
    }
}

bool HTMLCanvasElement::paintsIntoCanvasBuffer() const
{
    DCHECK(m_context);

    if (!m_context->isAccelerated())
        return true;
    if (layoutBox() && layoutBox()->hasAcceleratedCompositing())
        return false;

    return true;
}

void HTMLCanvasElement::notifyListenersCanvasChanged()
{
    if (m_listeners.size() == 0)
        return;

    if (!originClean()) {
        m_listeners.clear();
        return;
    }

    bool listenerNeedsNewFrameCapture = false;
    for (const CanvasDrawListener* listener : m_listeners) {
        if (listener->needsNewFrame()) {
            listenerNeedsNewFrameCapture = true;
        }
    }

    if (listenerNeedsNewFrameCapture) {
        SourceImageStatus status;
        RefPtr<Image> sourceImage = getSourceImageForCanvas(&status, PreferNoAcceleration, SnapshotReasonCanvasListenerCapture, FloatSize());
        if (status != NormalSourceImageStatus)
            return;
        sk_sp<SkImage> image = sourceImage->imageForCurrentFrame();
        for (CanvasDrawListener* listener : m_listeners) {
            if (listener->needsNewFrame()) {
                listener->sendNewFrame(image);
            }
        }
    }

}

void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r)
{
    // FIXME: crbug.com/438240; there is a bug with the new CSS blending and compositing feature.
    if (!m_context)
        return;

    const ComputedStyle* style = ensureComputedStyle();
    SkFilterQuality filterQuality = (style && style->imageRendering() == ImageRenderingPixelated) ? kNone_SkFilterQuality : kLow_SkFilterQuality;

    if (is3D()) {
        m_context->setFilterQuality(filterQuality);
    } else if (hasImageBuffer()) {
        m_imageBuffer->setFilterQuality(filterQuality);
    }

    if (hasImageBuffer() && !m_imageBufferIsClear)
        PaintTiming::from(document()).markFirstContentfulPaint();

    if (!paintsIntoCanvasBuffer() && !document().printing())
        return;

    // TODO(junov): Paint is currently only implemented by ImageBitmap contexts.
    // We could improve the abstraction by making all context types paint
    // themselves (implement paint()).
    if (m_context->paint(context, pixelSnappedIntRect(r)))
        return;

    m_context->paintRenderingResultsToCanvas(FrontBuffer);
    if (hasImageBuffer()) {
        if (!context.contextDisabled()) {
            SkXfermode::Mode compositeOperator = !m_context || m_context->creationAttributes().alpha() ? SkXfermode::kSrcOver_Mode : SkXfermode::kSrc_Mode;
            buffer()->draw(context, pixelSnappedIntRect(r), 0, compositeOperator);
        }
    } else {
        // When alpha is false, we should draw to opaque black.
        if (!m_context->creationAttributes().alpha())
            context.fillRect(FloatRect(r), Color(0, 0, 0));
    }

    if (is3D() && paintsIntoCanvasBuffer())
        m_context->markLayerComposited();
}

bool HTMLCanvasElement::is3D() const
{
    return m_context && m_context->is3d();
}

bool HTMLCanvasElement::isAnimated2D() const
{
    return m_context && m_context->is2d() && hasImageBuffer() && m_imageBuffer->wasDrawnToAfterSnapshot();
}

void HTMLCanvasElement::setSurfaceSize(const IntSize& size)
{
    m_size = size;
    m_didFailToCreateImageBuffer = false;
    discardImageBuffer();
    clearCopiedImage();
    if (m_context && m_context->is2d() && m_context->isContextLost()) {
        m_context->didSetSurfaceSize();
    }
}

// This enum is used in a UMA histogram; the values should not be changed.
enum RequestedImageMimeType {
    RequestedImageMimeTypePng = 0,
    RequestedImageMimeTypeJpeg = 1,
    RequestedImageMimeTypeWebp = 2,
    RequestedImageMimeTypeGif = 3,
    RequestedImageMimeTypeBmp = 4,
    RequestedImageMimeTypeIco = 5,
    RequestedImageMimeTypeTiff = 6,
    RequestedImageMimeTypeUnknown = 7,
    NumberOfRequestedImageMimeTypes
};

String HTMLCanvasElement::toEncodingMimeType(const String& mimeType, const EncodeReason encodeReason)
{
    String lowercaseMimeType = mimeType.lower();
    if (mimeType.isNull())
        lowercaseMimeType = DefaultMimeType;

    RequestedImageMimeType imageFormat;
    if (lowercaseMimeType == "image/png") {
        imageFormat = RequestedImageMimeTypePng;
    } else if (lowercaseMimeType == "image/jpeg") {
        imageFormat = RequestedImageMimeTypeJpeg;
    } else if (lowercaseMimeType == "image/webp") {
        imageFormat = RequestedImageMimeTypeWebp;
    } else if (lowercaseMimeType == "image/gif") {
        imageFormat = RequestedImageMimeTypeGif;
    } else if (lowercaseMimeType == "image/bmp" || lowercaseMimeType == "image/x-windows-bmp") {
        imageFormat = RequestedImageMimeTypeBmp;
    } else if (lowercaseMimeType == "image/x-icon") {
        imageFormat = RequestedImageMimeTypeIco;
    } else if (lowercaseMimeType == "image/tiff" || lowercaseMimeType == "image/x-tiff") {
        imageFormat = RequestedImageMimeTypeTiff;
    } else {
        imageFormat = RequestedImageMimeTypeUnknown;
    }

    if (encodeReason == EncodeReasonToDataURL) {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, toDataURLImageFormatHistogram, new EnumerationHistogram("Canvas.RequestedImageMimeTypes_toDataURL", NumberOfRequestedImageMimeTypes));
        toDataURLImageFormatHistogram.count(imageFormat);
    } else if (encodeReason == EncodeReasonToBlobCallback) {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, toBlobCallbackImageFormatHistogram, new EnumerationHistogram("Canvas.RequestedImageMimeTypes_toBlobCallback", NumberOfRequestedImageMimeTypes));
        toBlobCallbackImageFormatHistogram.count(imageFormat);
    }

    // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this method to be used on a worker thread).
    if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(lowercaseMimeType))
        lowercaseMimeType = DefaultMimeType;
    return lowercaseMimeType;
}

const AtomicString HTMLCanvasElement::imageSourceURL() const
{
    return AtomicString(toDataURLInternal(DefaultMimeType, 0, FrontBuffer));
}

void HTMLCanvasElement::prepareSurfaceForPaintingIfNeeded() const
{
    DCHECK(m_context && m_context->is2d()); // This function is called by the 2d context
    if (buffer())
        m_imageBuffer->prepareSurfaceForPaintingIfNeeded();
}

ImageData* HTMLCanvasElement::toImageData(SourceDrawingBuffer sourceBuffer, SnapshotReason reason) const
{
    ImageData* imageData;
    if (is3D()) {
        // Get non-premultiplied data because of inaccurate premultiplied alpha conversion of buffer()->toDataURL().
        imageData = m_context->paintRenderingResultsToImageData(sourceBuffer);
        if (imageData)
            return imageData;

        m_context->paintRenderingResultsToCanvas(sourceBuffer);
        imageData = ImageData::create(m_size);
        sk_sp<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration, reason);
        if (snapshot) {
            SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);
            snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo.minRowBytes(), 0, 0);
        }
        return imageData;
    }

    imageData = ImageData::create(m_size);

    if (!m_context)
        return imageData;

    DCHECK(m_context->is2d());
    sk_sp<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration, reason);
    if (snapshot) {
        SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);
        snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo.minRowBytes(), 0, 0);
    }

    return imageData;
}

String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double& quality, SourceDrawingBuffer sourceBuffer) const
{
    if (!isPaintable())
        return String("data:,");

    String encodingMimeType = toEncodingMimeType(mimeType, EncodeReasonToDataURL);

    ImageData* imageData = toImageData(sourceBuffer, SnapshotReasonToDataURL);

    return ImageDataBuffer(imageData->size(), imageData->data()->data()).toDataURL(encodingMimeType, quality);
}

String HTMLCanvasElement::toDataURL(const String& mimeType, const ScriptValue& qualityArgument, ExceptionState& exceptionState) const
{
    if (!originClean()) {
        exceptionState.throwSecurityError("Tainted canvases may not be exported.");
        return String();
    }
    Optional<ScopedUsHistogramTimer> timer;
    String lowercaseMimeType = mimeType.lower();
    if (mimeType.isNull())
        lowercaseMimeType = DefaultMimeType;
    if (lowercaseMimeType == "image/png") {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterPNG, new CustomCountHistogram("Blink.Canvas.ToDataURL.PNG", 0, 10000000, 50));
        timer.emplace(scopedUsCounterPNG);
    } else if (lowercaseMimeType == "image/jpeg") {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterJPEG, new CustomCountHistogram("Blink.Canvas.ToDataURL.JPEG", 0, 10000000, 50));
        timer.emplace(scopedUsCounterJPEG);
    } else if (lowercaseMimeType == "image/webp") {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterWEBP, new CustomCountHistogram("Blink.Canvas.ToDataURL.WEBP", 0, 10000000, 50));
        timer.emplace(scopedUsCounterWEBP);
    } else if (lowercaseMimeType == "image/gif") {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterGIF, new CustomCountHistogram("Blink.Canvas.ToDataURL.GIF", 0, 10000000, 50));
        timer.emplace(scopedUsCounterGIF);
    } else if (lowercaseMimeType == "image/bmp" || lowercaseMimeType == "image/x-windows-bmp") {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterBMP, new CustomCountHistogram("Blink.Canvas.ToDataURL.BMP", 0, 10000000, 50));
        timer.emplace(scopedUsCounterBMP);
    } else if (lowercaseMimeType == "image/x-icon") {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterICON, new CustomCountHistogram("Blink.Canvas.ToDataURL.ICON", 0, 10000000, 50));
        timer.emplace(scopedUsCounterICON);
    } else if (lowercaseMimeType == "image/tiff" || lowercaseMimeType == "image/x-tiff") {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterTIFF, new CustomCountHistogram("Blink.Canvas.ToDataURL.TIFF", 0, 10000000, 50));
        timer.emplace(scopedUsCounterTIFF);
    } else {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scopedUsCounterUnknown, new CustomCountHistogram("Blink.Canvas.ToDataURL.Unknown", 0, 10000000, 50));
        timer.emplace(scopedUsCounterUnknown);
    }

    double quality = UndefinedQualityValue;
    if (!qualityArgument.isEmpty()) {
        v8::Local<v8::Value> v8Value = qualityArgument.v8Value();
        if (v8Value->IsNumber()) {
            quality = v8Value.As<v8::Number>()->Value();
        }
    }
    return toDataURLInternal(mimeType, quality, BackBuffer);
}

void HTMLCanvasElement::toBlob(BlobCallback* callback, const String& mimeType, const ScriptValue& qualityArgument, ExceptionState& exceptionState)
{
    if (!originClean()) {
        exceptionState.throwSecurityError("Tainted canvases may not be exported.");
        return;
    }

    if (!isPaintable()) {
        // If the canvas element's bitmap has no pixels
        TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, &document())->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(callback), nullptr));
        return;
    }

    double startTime = WTF::monotonicallyIncreasingTime();
    double quality = UndefinedQualityValue;
    if (!qualityArgument.isEmpty()) {
        v8::Local<v8::Value> v8Value = qualityArgument.v8Value();
        if (v8Value->IsNumber()) {
            quality = v8Value.As<v8::Number>()->Value();
        }
    }

    String encodingMimeType = toEncodingMimeType(mimeType, EncodeReasonToBlobCallback);

    ImageData* imageData = toImageData(BackBuffer, SnapshotReasonToBlob);

    CanvasAsyncBlobCreator* asyncCreator = CanvasAsyncBlobCreator::create(imageData->data(), encodingMimeType, imageData->size(), callback, startTime, document());

    bool useIdlePeriodScheduling = (encodingMimeType != "image/webp");
    asyncCreator->scheduleAsyncBlobCreation(useIdlePeriodScheduling, quality);
}

void HTMLCanvasElement::addListener(CanvasDrawListener* listener)
{
    m_listeners.add(listener);
}

void HTMLCanvasElement::removeListener(CanvasDrawListener* listener)
{
    m_listeners.remove(listener);
}

SecurityOrigin* HTMLCanvasElement::getSecurityOrigin() const
{
    return document().getSecurityOrigin();
}

bool HTMLCanvasElement::originClean() const
{
    if (document().settings() && document().settings()->disableReadingFromCanvas())
        return false;
    return m_originClean;
}

bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const
{
    if (m_context && !m_context->is2d())
        return false;

    if (RuntimeEnabledFeatures::forceDisplayList2dCanvasEnabled())
        return false;

    if (!RuntimeEnabledFeatures::accelerated2dCanvasEnabled())
        return false;

    // The following is necessary for handling the special case of canvases in the
    // dev tools overlay, which run in a process that supports accelerated 2d canvas
    // but in a special compositing context that does not.
    if (layoutBox() && !layoutBox()->hasAcceleratedCompositing())
        return false;

    CheckedNumeric<int> checkedCanvasPixelCount = size.width();
    checkedCanvasPixelCount *= size.height();
    if (!checkedCanvasPixelCount.IsValid())
        return false;
    int canvasPixelCount = checkedCanvasPixelCount.ValueOrDie();

    if (RuntimeEnabledFeatures::displayList2dCanvasEnabled()) {
#if 0
        // TODO(junov): re-enable this code once we solve the problem of recording
        // GPU-backed images to an SkPicture for cross-context rendering crbug.com/490328

        // If the compositor provides GPU acceleration to display list canvases, we
        // prefer that over direct acceleration.
        if (document().viewportDescription().matchesHeuristicsForGpuRasterization())
            return false;
#endif
        // If the GPU resources would be very expensive, prefer a display list.
        if (canvasPixelCount > ExpensiveCanvasHeuristicParameters::PreferDisplayListOverGpuSizeThreshold)
            return false;
    }

    // Do not use acceleration for small canvas.
    Settings* settings = document().settings();
    if (!settings || canvasPixelCount < settings->minimumAccelerated2dCanvasSize())
        return false;

    // When GPU allocated memory runs low (due to having created too many
    // accelerated canvases), the compositor starves and browser becomes laggy.
    // Thus, we should stop allocating more GPU memory to new canvases created
    // when the current memory usage exceeds the threshold.
    if (ImageBuffer::getGlobalGPUMemoryUsage() >= MaxGlobalGPUMemoryUsage)
        return false;

    // Allocating too many GPU resources can makes us run into the driver's
    // resource limits. So we need to keep the number of texture resources
    // under tight control
    if (ImageBuffer::getGlobalAcceleratedImageBufferCount() >= MaxGlobalAcceleratedImageBufferCount)
        return false;

    return true;
}

class UnacceleratedSurfaceFactory : public RecordingImageBufferFallbackSurfaceFactory {
public:
    virtual std::unique_ptr<ImageBufferSurface> createSurface(const IntSize& size, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace)
    {
        return wrapUnique(new UnacceleratedImageBufferSurface(size, opacityMode, InitializeImagePixels, colorSpace));
    }

    virtual ~UnacceleratedSurfaceFactory() { }
};

bool HTMLCanvasElement::shouldUseDisplayList(const IntSize& deviceSize)
{
    if (RuntimeEnabledFeatures::forceDisplayList2dCanvasEnabled())
        return true;

    if (!RuntimeEnabledFeatures::displayList2dCanvasEnabled())
        return false;

    return true;
}

std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createWebGLImageBufferSurface(const IntSize& deviceSize, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace)
{
    DCHECK(is3D());
    // If 3d, but the use of the canvas will be for non-accelerated content
    // then make a non-accelerated ImageBuffer. This means copying the internal
    // Image will require a pixel readback, but that is unavoidable in this case.
    auto surface = wrapUnique(new AcceleratedImageBufferSurface(deviceSize, opacityMode, std::move(colorSpace)));
    if (surface->isValid())
        return std::move(surface);
    return nullptr;
}

std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createAcceleratedImageBufferSurface(const IntSize& deviceSize, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace, int* msaaSampleCount)
{
    if (!shouldAccelerate(deviceSize))
        return nullptr;

    if (document().settings())
        *msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleCount();

    // Avoid creating |contextProvider| until we're sure we want to try use it,
    // since it costs us GPU memory.
    std::unique_ptr<WebGraphicsContext3DProvider> contextProvider(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (!contextProvider) {
        CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Accelerated2DCanvasGPUContextLost);
        return nullptr;
    }

    if (contextProvider->isSoftwareRendering())
        return nullptr; // Don't use accelerated canvas with swiftshader.

    std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new Canvas2DImageBufferSurface(std::move(contextProvider), deviceSize, *msaaSampleCount, opacityMode, Canvas2DLayerBridge::EnableAcceleration, std::move(colorSpace)));
    if (!surface->isValid()) {
        CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreationFailed);
        return nullptr;
    }

    CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreated);
    return surface;
}

std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createUnacceleratedImageBufferSurface(const IntSize& deviceSize, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace)
{
    if (shouldUseDisplayList(deviceSize)) {
        auto surface = wrapUnique(new RecordingImageBufferSurface(deviceSize, wrapUnique(new UnacceleratedSurfaceFactory), opacityMode, colorSpace));
        if (surface->isValid()) {
            CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DCanvasImageBufferCreated);
            return std::move(surface);
        }
        // We fallback to a non-display-list surface without recording a metric here.
    }

    auto surfaceFactory = wrapUnique(new UnacceleratedSurfaceFactory());
    auto surface = surfaceFactory->createSurface(deviceSize, opacityMode, std::move(colorSpace));
    if (surface->isValid()) {
        CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasImageBufferCreated);
        return surface;
    }

    CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasImageBufferCreationFailed);
    return nullptr;
}

void HTMLCanvasElement::createImageBuffer()
{
    createImageBufferInternal(nullptr);
    if (m_didFailToCreateImageBuffer && m_context->is2d() && !size().isEmpty())
        m_context->loseContext(CanvasRenderingContext::SyntheticLostContext);
}

void HTMLCanvasElement::createImageBufferInternal(std::unique_ptr<ImageBufferSurface> externalSurface)
{
    DCHECK(!m_imageBuffer);

    m_didFailToCreateImageBuffer = true;
    m_imageBufferIsClear = true;

    if (!ImageBuffer::canCreateImageBuffer(size()))
        return;

    OpacityMode opacityMode = !m_context || m_context->creationAttributes().alpha() ? NonOpaque : Opaque;
    int msaaSampleCount = 0;
    std::unique_ptr<ImageBufferSurface> surface;
    if (externalSurface) {
        if (externalSurface->isValid())
            surface = std::move(externalSurface);
    } else if (is3D()) {
        surface = createWebGLImageBufferSurface(size(), opacityMode, m_context->skColorSpace());
    } else {
        surface = createAcceleratedImageBufferSurface(size(), opacityMode, m_context->skColorSpace(), &msaaSampleCount);
        if (!surface)
            surface = createUnacceleratedImageBufferSurface(size(), opacityMode, m_context->skColorSpace());
    }
    if (!surface)
        return;
    DCHECK(surface->isValid());
    m_imageBuffer = ImageBuffer::create(std::move(surface));
    DCHECK(m_imageBuffer);
    m_imageBuffer->setClient(this);

    m_didFailToCreateImageBuffer = false;

    updateExternallyAllocatedMemory();

    if (is3D()) {
        // Early out for WebGL canvases
        return;
    }

    m_imageBuffer->setClient(this);
    // Enabling MSAA overrides a request to disable antialiasing. This is true regardless of whether the
    // rendering mode is accelerated or not. For consistency, we don't want to apply AA in accelerated
    // canvases but not in unaccelerated canvases.
    if (!msaaSampleCount && document().settings() && !document().settings()->antialiased2dCanvasEnabled())
        m_context->setShouldAntialias(false);

    if (m_context)
        setNeedsCompositingUpdate();
}

void HTMLCanvasElement::notifySurfaceInvalid()
{
    if (m_context && m_context->is2d())
        m_context->loseContext(CanvasRenderingContext::RealLostContext);
}

DEFINE_TRACE(HTMLCanvasElement)
{
    visitor->trace(m_listeners);
    visitor->trace(m_context);
    ContextLifecycleObserver::trace(visitor);
    PageVisibilityObserver::trace(visitor);
    HTMLElement::trace(visitor);
}

DEFINE_TRACE_WRAPPERS(HTMLCanvasElement)
{
    visitor->traceWrappers(m_context);
    HTMLElement::traceWrappers(visitor);
}

void HTMLCanvasElement::updateExternallyAllocatedMemory() const
{
    int bufferCount = 0;
    if (m_imageBuffer) {
        bufferCount++;
        if (m_imageBuffer->isAccelerated()) {
            // The number of internal GPU buffers vary between one (stable
            // non-displayed state) and three (triple-buffered animations).
            // Adding 2 is a pessimistic but relevant estimate.
            // Note: These buffers might be allocated in GPU memory.
            bufferCount += 2;
        }
    }
    if (m_copiedImage)
        bufferCount++;

    // Four bytes per pixel per buffer.
    CheckedNumeric<intptr_t> checkedExternallyAllocatedMemory = 4 * bufferCount;
    if (is3D())
        checkedExternallyAllocatedMemory += m_context->externallyAllocatedBytesPerPixel();

    checkedExternallyAllocatedMemory *= width();
    checkedExternallyAllocatedMemory *= height();
    intptr_t externallyAllocatedMemory = checkedExternallyAllocatedMemory.ValueOrDefault(std::numeric_limits<intptr_t>::max());

    // Subtracting two intptr_t that are known to be positive will never underflow.
    v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyAllocatedMemory - m_externallyAllocatedMemory);
    m_externallyAllocatedMemory = externallyAllocatedMemory;
}

SkCanvas* HTMLCanvasElement::drawingCanvas() const
{
    return buffer() ? m_imageBuffer->canvas() : nullptr;
}

void HTMLCanvasElement::disableDeferral(DisableDeferralReason reason) const
{
    if (buffer())
        m_imageBuffer->disableDeferral(reason);
}

SkCanvas* HTMLCanvasElement::existingDrawingCanvas() const
{
    if (!hasImageBuffer())
        return nullptr;

    return m_imageBuffer->canvas();
}

ImageBuffer* HTMLCanvasElement::buffer() const
{
    DCHECK(m_context);
    DCHECK(m_context->getContextType() != CanvasRenderingContext::ContextImageBitmap);
    if (!hasImageBuffer() && !m_didFailToCreateImageBuffer)
        const_cast<HTMLCanvasElement*>(this)->createImageBuffer();
    return m_imageBuffer.get();
}

void HTMLCanvasElement::createImageBufferUsingSurfaceForTesting(std::unique_ptr<ImageBufferSurface> surface)
{
    discardImageBuffer();
    setWidth(surface->size().width());
    setHeight(surface->size().height());
    createImageBufferInternal(std::move(surface));
}

void HTMLCanvasElement::ensureUnacceleratedImageBuffer()
{
    DCHECK(m_context);
    if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCreateImageBuffer)
        return;
    discardImageBuffer();
    OpacityMode opacityMode = m_context->creationAttributes().alpha() ? NonOpaque : Opaque;
    m_imageBuffer = ImageBuffer::create(size(), opacityMode);
    m_didFailToCreateImageBuffer = !m_imageBuffer;
}

PassRefPtr<Image> HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer, AccelerationHint hint) const
{
    if (!isPaintable())
        return nullptr;
    if (!m_context)
        return createTransparentImage(size());

    bool needToUpdate = !m_copiedImage;
    // The concept of SourceDrawingBuffer is valid on only WebGL.
    if (m_context->is3d())
        needToUpdate |= m_context->paintRenderingResultsToCanvas(sourceBuffer);
    if (needToUpdate && buffer()) {
        m_copiedImage = buffer()->newImageSnapshot(hint, SnapshotReasonGetCopiedImage);
        updateExternallyAllocatedMemory();
    }
    return m_copiedImage;
}

void HTMLCanvasElement::discardImageBuffer()
{
    m_imageBuffer.reset();
    m_dirtyRect = FloatRect();
    updateExternallyAllocatedMemory();
}

void HTMLCanvasElement::clearCopiedImage()
{
    if (m_copiedImage) {
        m_copiedImage.clear();
        updateExternallyAllocatedMemory();
    }
}

AffineTransform HTMLCanvasElement::baseTransform() const
{
    DCHECK(hasImageBuffer() && !m_didFailToCreateImageBuffer);
    return m_imageBuffer->baseTransform();
}

void HTMLCanvasElement::pageVisibilityChanged()
{
    if (!m_context)
        return;

    bool hidden = !page()->isPageVisible();
    m_context->setIsHidden(hidden);
    if (hidden) {
        clearCopiedImage();
        if (is3D()) {
            discardImageBuffer();
        }
    }
}

void HTMLCanvasElement::contextDestroyed()
{
    if (m_context)
        m_context->stop();
}

void HTMLCanvasElement::styleDidChange(const ComputedStyle* oldStyle, const ComputedStyle& newStyle)
{
    if (m_context)
        m_context->styleDidChange(oldStyle, newStyle);
}

void HTMLCanvasElement::didMoveToNewDocument(Document& oldDocument)
{
    ContextLifecycleObserver::setContext(&document());
    PageVisibilityObserver::setContext(document().page());
    HTMLElement::didMoveToNewDocument(oldDocument);
}

PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint hint, SnapshotReason reason, const FloatSize&) const
{
    if (!width() || !height()) {
        *status = ZeroSizeCanvasSourceImageStatus;
        return nullptr;
    }

    if (!isPaintable()) {
        *status = InvalidSourceImageStatus;
        return nullptr;
    }

    if (!m_context) {
        *status = NormalSourceImageStatus;
        return createTransparentImage(size());
    }

    sk_sp<SkImage> skImage;
    if (m_context->is3d()) {
        // Because WebGL sources always require making a copy of the back buffer, we
        // use paintRenderingResultsToCanvas instead of getImage in order to keep a cached
        // copy of the backing in the canvas's ImageBuffer.
        renderingContext()->paintRenderingResultsToCanvas(BackBuffer);
        skImage = hasImageBuffer() ? buffer()->newSkImageSnapshot(hint, reason) : createTransparentImage(size())->imageForCurrentFrame();
    } else {
        RefPtr<blink::Image> image = renderingContext()->getImage(hint, reason);
        skImage = image ? image->imageForCurrentFrame() : createTransparentImage(size())->imageForCurrentFrame();
    }

    if (skImage) {
        *status = NormalSourceImageStatus;
        return StaticBitmapImage::create(std::move(skImage));
    }

    *status = InvalidSourceImageStatus;
    return nullptr;
}

bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const
{
    return !originClean();
}

FloatSize HTMLCanvasElement::elementSize(const FloatSize&) const
{
    return FloatSize(width(), height());
}

IntSize HTMLCanvasElement::bitmapSourceSize() const
{
    return IntSize(width(), height());
}

ScriptPromise HTMLCanvasElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState)
{
    DCHECK(eventTarget.toLocalDOMWindow());
    if ((cropRect && !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), exceptionState))
        || !ImageBitmap::isSourceSizeValid(bitmapSourceSize().width(), bitmapSourceSize().height(), exceptionState))
        return ScriptPromise();
    if (!ImageBitmap::isResizeOptionValid(options, exceptionState))
        return ScriptPromise();
    return ImageBitmapSource::fulfillImageBitmap(scriptState, isPaintable() ? ImageBitmap::create(this, cropRect, options) : nullptr);
}

bool HTMLCanvasElement::isOpaque() const
{
    return m_context && !m_context->creationAttributes().alpha();
}

bool HTMLCanvasElement::isSupportedInteractiveCanvasFallback(const Element& element)
{
    if (!element.isDescendantOf(this))
        return false;

    // An element is a supported interactive canvas fallback element if it is one of the following:
    // https://html.spec.whatwg.org/multipage/scripting.html#supported-interactive-canvas-fallback-element

    // An a element that represents a hyperlink and that does not have any img descendants.
    if (isHTMLAnchorElement(element))
        return !Traversal<HTMLImageElement>::firstWithin(element);

    // A button element
    if (isHTMLButtonElement(element))
        return true;

    // An input element whose type attribute is in one of the Checkbox or Radio Button states.
    // An input element that is a button but its type attribute is not in the Image Button state.
    if (isHTMLInputElement(element)) {
        const HTMLInputElement& inputElement = toHTMLInputElement(element);
        if (inputElement.type() == InputTypeNames::checkbox
            || inputElement.type() == InputTypeNames::radio
            || inputElement.isTextButton())
            return true;
    }

    // A select element with a multiple attribute or a display size greater than 1.
    if (isHTMLSelectElement(element)) {
        const HTMLSelectElement& selectElement = toHTMLSelectElement(element);
        if (selectElement.multiple() || selectElement.size() > 1)
            return true;
    }

    // An option element that is in a list of options of a select element with a multiple attribute or a display size greater than 1.
    if (isHTMLOptionElement(element) && element.parentNode() && isHTMLSelectElement(*element.parentNode())) {
        const HTMLSelectElement& selectElement = toHTMLSelectElement(*element.parentNode());
        if (selectElement.multiple() || selectElement.size() > 1)
            return true;
    }

    // An element that would not be interactive content except for having the tabindex attribute specified.
    if (element.fastHasAttribute(HTMLNames::tabindexAttr))
        return true;

    // A non-interactive table, caption, thead, tbody, tfoot, tr, td, or th element.
    if (isHTMLTableElement(element)
        || element.hasTagName(HTMLNames::captionTag)
        || element.hasTagName(HTMLNames::theadTag)
        || element.hasTagName(HTMLNames::tbodyTag)
        || element.hasTagName(HTMLNames::tfootTag)
        || element.hasTagName(HTMLNames::trTag)
        || element.hasTagName(HTMLNames::tdTag)
        || element.hasTagName(HTMLNames::thTag))
        return true;

    return false;
}

HitTestCanvasResult* HTMLCanvasElement::getControlAndIdIfHitRegionExists(const LayoutPoint& location)
{
    if (m_context && m_context->is2d())
        return m_context->getControlAndIdIfHitRegionExists(location);
    return HitTestCanvasResult::create(String(), nullptr);
}

String HTMLCanvasElement::getIdFromControl(const Element* element)
{
    if (m_context)
        return m_context->getIdFromControl(element);
    return String();
}

bool HTMLCanvasElement::createSurfaceLayer()
{
    DCHECK(!m_surfaceLayerBridge);
    std::unique_ptr<CanvasSurfaceLayerBridgeClient> bridgeClient = wrapUnique(new CanvasSurfaceLayerBridgeClientImpl());
    m_surfaceLayerBridge = wrapUnique(new CanvasSurfaceLayerBridge(std::move(bridgeClient)));
    return m_surfaceLayerBridge->createSurfaceLayer(this->width(), this->height());
}

} // namespace blink
