// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/offscreencanvas/OffscreenCanvas.h"

#include <memory>
#include "core/dom/ExceptionCode.h"
#include "core/fileapi/Blob.h"
#include "core/frame/ImageBitmap.h"
#include "core/html/ImageData.h"
#include "core/html/canvas/CanvasAsyncBlobCreator.h"
#include "core/html/canvas/CanvasContextCreationAttributes.h"
#include "core/html/canvas/CanvasRenderingContext.h"
#include "core/html/canvas/CanvasRenderingContextFactory.h"
#include "platform/graphics/Image.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/OffscreenCanvasFrameDispatcherImpl.h"
#include "platform/graphics/StaticBitmapImage.h"
#include "platform/image-encoders/ImageEncoderUtils.h"
#include "public/platform/Platform.h"
#include "wtf/MathExtras.h"

namespace blink {

OffscreenCanvas::OffscreenCanvas(const IntSize& size) : m_size(size) {}

OffscreenCanvas* OffscreenCanvas::create(unsigned width, unsigned height) {
  return new OffscreenCanvas(
      IntSize(clampTo<int>(width), clampTo<int>(height)));
}

OffscreenCanvas::~OffscreenCanvas() {}

void OffscreenCanvas::dispose() {
  if (m_context) {
    m_context->detachOffscreenCanvas();
    m_context = nullptr;
  }
  if (m_commitPromiseResolver) {
    // keepAliveWhilePending() guarantees the promise resolver is never
    // GC-ed before the OffscreenCanvas
    m_commitPromiseResolver->reject();
    m_commitPromiseResolver.clear();
  }
}

void OffscreenCanvas::setWidth(unsigned width) {
  IntSize newSize = m_size;
  newSize.setWidth(clampTo<int>(width));
  setSize(newSize);
}

void OffscreenCanvas::setHeight(unsigned height) {
  IntSize newSize = m_size;
  newSize.setHeight(clampTo<int>(height));
  setSize(newSize);
}

void OffscreenCanvas::setSize(const IntSize& size) {
  if (m_context) {
    if (m_context->is3d()) {
      if (size != m_size)
        m_context->reshape(size.width(), size.height());
    } else if (m_context->is2d()) {
      m_context->reset();
    }
  }
  m_size = size;
  if (m_frameDispatcher) {
    m_frameDispatcher->reshape(m_size.width(), m_size.height());
  }
}

void OffscreenCanvas::setNeutered() {
  ASSERT(!m_context);
  m_isNeutered = true;
  m_size.setWidth(0);
  m_size.setHeight(0);
}

ImageBitmap* OffscreenCanvas::transferToImageBitmap(
    ScriptState* scriptState,
    ExceptionState& exceptionState) {
  if (m_isNeutered) {
    exceptionState.throwDOMException(
        InvalidStateError,
        "Cannot transfer an ImageBitmap from a detached OffscreenCanvas");
    return nullptr;
  }
  if (!m_context) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "Cannot transfer an ImageBitmap from an "
                                     "OffscreenCanvas with no context");
    return nullptr;
  }
  ImageBitmap* image = m_context->transferToImageBitmap(scriptState);
  if (!image) {
    // Undocumented exception (not in spec)
    exceptionState.throwDOMException(V8Error, "Out of memory");
  }
  return image;
}

PassRefPtr<Image> OffscreenCanvas::getSourceImageForCanvas(
    SourceImageStatus* status,
    AccelerationHint hint,
    SnapshotReason reason,
    const FloatSize& size) const {
  if (!m_context) {
    *status = InvalidSourceImageStatus;
    sk_sp<SkSurface> surface =
        SkSurface::MakeRasterN32Premul(m_size.width(), m_size.height());
    return surface ? StaticBitmapImage::create(surface->makeImageSnapshot())
                   : nullptr;
  }
  if (!size.width() || !size.height()) {
    *status = ZeroSizeCanvasSourceImageStatus;
    return nullptr;
  }
  RefPtr<Image> image = m_context->getImage(hint, reason);
  if (!image) {
    *status = InvalidSourceImageStatus;
  } else {
    *status = NormalSourceImageStatus;
  }
  return image.release();
}

IntSize OffscreenCanvas::bitmapSourceSize() const {
  return m_size;
}

ScriptPromise OffscreenCanvas::createImageBitmap(
    ScriptState* scriptState,
    EventTarget&,
    Optional<IntRect> cropRect,
    const ImageBitmapOptions& options,
    ExceptionState& exceptionState) {
  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 OffscreenCanvas::isOpaque() const {
  if (!m_context)
    return false;
  return !m_context->creationAttributes().hasAlpha();
}

CanvasRenderingContext* OffscreenCanvas::getCanvasRenderingContext(
    ScriptState* scriptState,
    const String& id,
    const CanvasContextCreationAttributes& attributes) {
  CanvasRenderingContext::ContextType contextType =
      CanvasRenderingContext::contextTypeFromId(id);

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

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

  if (m_context) {
    if (m_context->getContextType() != contextType) {
      factory->onError(
          this, "OffscreenCanvas has an existing context of a different type");
      return nullptr;
    }
  } else {
    m_context = factory->create(scriptState, this, attributes);
  }

  return m_context.get();
}

OffscreenCanvas::ContextFactoryVector&
OffscreenCanvas::renderingContextFactories() {
  DEFINE_STATIC_LOCAL(ContextFactoryVector, s_contextFactories,
                      (CanvasRenderingContext::ContextTypeCount));
  return s_contextFactories;
}

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

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

bool OffscreenCanvas::originClean() const {
  return m_originClean && !m_disableReadingFromCanvas;
}

bool OffscreenCanvas::isPaintable() const {
  if (!m_context)
    return ImageBuffer::canCreateImageBuffer(m_size);
  return m_context->isPaintable() && m_size.width() && m_size.height();
}

bool OffscreenCanvas::isAccelerated() const {
  return m_context && m_context->isAccelerated();
}

OffscreenCanvasFrameDispatcher* OffscreenCanvas::getOrCreateFrameDispatcher() {
  if (!m_frameDispatcher) {
    // The frame dispatcher connects the current thread of OffscreenCanvas
    // (either main or worker) to the browser process and remains unchanged
    // throughout the lifetime of this OffscreenCanvas.
    m_frameDispatcher = WTF::wrapUnique(new OffscreenCanvasFrameDispatcherImpl(
        this, m_clientId, m_sinkId, m_placeholderCanvasId, m_size.width(),
        m_size.height()));
  }
  return m_frameDispatcher.get();
}

ScriptPromise OffscreenCanvas::commit(RefPtr<StaticBitmapImage> image,
                                      bool isWebGLSoftwareRendering,
                                      ScriptState* scriptState) {
  getOrCreateFrameDispatcher()->setNeedsBeginFrame(true);

  if (!m_commitPromiseResolver) {
    m_commitPromiseResolver = ScriptPromiseResolver::create(scriptState);
    m_commitPromiseResolver->keepAliveWhilePending();

    if (image) {
      // We defer the submission of commit frames at the end of JS task
      m_currentFrame = std::move(image);
      m_currentFrameIsWebGLSoftwareRendering = isWebGLSoftwareRendering;
      m_context->needsFinalizeFrame();
    }
  } else if (image) {
    // Two possible scenarios:
    // 1. An override of m_currentFrame can happen when there are multiple
    // frames committed before JS task finishes. (m_currentFrame!=nullptr)
    // 2. The current frame has been dispatched but the promise is not
    // resolved yet. (m_currentFrame==nullptr)
    m_currentFrame = std::move(image);
    m_currentFrameIsWebGLSoftwareRendering = isWebGLSoftwareRendering;
  }

  return m_commitPromiseResolver->promise();
}

void OffscreenCanvas::finalizeFrame() {
  if (m_currentFrame) {
    // TODO(eseckler): OffscreenCanvas shouldn't dispatch CompositorFrames
    // without a prior BeginFrame.
    doCommit(std::move(m_currentFrame), m_currentFrameIsWebGLSoftwareRendering);
  }
}

void OffscreenCanvas::doCommit(RefPtr<StaticBitmapImage> image,
                               bool isWebGLSoftwareRendering) {
  double commitStartTime = WTF::monotonicallyIncreasingTime();
  getOrCreateFrameDispatcher()->dispatchFrame(std::move(image), commitStartTime,
                                              isWebGLSoftwareRendering);
}

void OffscreenCanvas::beginFrame() {
  if (m_currentFrame) {
    // TODO(eseckler): beginFrame() shouldn't be used as confirmation of
    // CompositorFrame activation.
    // If we have an overdraw backlog, push the frame from the backlog
    // first and save the promise resolution for later.
    // Then we need to wait for one more frame time to resolve the existing
    // promise.
    doCommit(std::move(m_currentFrame), m_currentFrameIsWebGLSoftwareRendering);
  } else if (m_commitPromiseResolver) {
    m_commitPromiseResolver->resolve();
    m_commitPromiseResolver.clear();
    // We need to tell parent frame to stop sending signals on begin frame to
    // avoid overhead once we resolve the promise.
    getOrCreateFrameDispatcher()->setNeedsBeginFrame(false);
  }
}

ScriptPromise OffscreenCanvas::convertToBlob(ScriptState* scriptState,
                                             const ImageEncodeOptions& options,
                                             ExceptionState& exceptionState) {
  if (this->isNeutered()) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "OffscreenCanvas object is detached.");
    return exceptionState.reject(scriptState);
  }

  if (!this->originClean()) {
    exceptionState.throwSecurityError(
        "Tainted OffscreenCanvas may not be exported.");
    return exceptionState.reject(scriptState);
  }

  if (!this->isPaintable()) {
    exceptionState.throwDOMException(
        IndexSizeError, "The size of the OffscreenCanvas is zero.");
    return exceptionState.reject(scriptState);
  }

  double startTime = WTF::monotonicallyIncreasingTime();
  String encodingMimeType = ImageEncoderUtils::toEncodingMimeType(
      options.type(), ImageEncoderUtils::EncodeReasonConvertToBlobPromise);

  ImageData* imageData = nullptr;
  if (this->renderingContext()) {
    imageData = this->renderingContext()->toImageData(SnapshotReasonUnknown);
  }
  if (!imageData) {
    exceptionState.throwDOMException(
        InvalidStateError, "OffscreenCanvas object has no rendering contexts");
    return exceptionState.reject(scriptState);
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);

  Document* document =
      scriptState->getExecutionContext()->isDocument()
          ? static_cast<Document*>(scriptState->getExecutionContext())
          : nullptr;

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

  asyncCreator->scheduleAsyncBlobCreation(options.quality());

  return resolver->promise();
}

DEFINE_TRACE(OffscreenCanvas) {
  visitor->trace(m_context);
  visitor->trace(m_executionContext);
  visitor->trace(m_commitPromiseResolver);
  EventTargetWithInlineData::trace(visitor);
}

}  // namespace blink
