/*
 * Copyright (C) 2009 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 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 "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"

#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"

namespace blink {

CanvasRenderingContext::CanvasRenderingContext(
    CanvasRenderingContextHost* host,
    const CanvasContextCreationAttributesCore& attrs)
    : host_(host),
      color_params_(attrs.color_space, attrs.pixel_format, attrs.alpha),
      creation_attributes_(attrs) {}

void CanvasRenderingContext::Dispose() {
  StopListeningForDidProcessTask();

  // HTMLCanvasElement and CanvasRenderingContext have a circular reference.
  // When the pair is no longer reachable, their destruction order is non-
  // deterministic, so the first of the two to be destroyed needs to notify
  // the other in order to break the circular reference.  This is to avoid
  // an error when CanvasRenderingContext::DidProcessTask() is invoked
  // after the HTMLCanvasElement is destroyed.
  if (Host()) {
    Host()->DetachContext();
    host_ = nullptr;
  }
}

void CanvasRenderingContext::DidDraw(const SkIRect& dirty_rect) {
  Host()->DidDraw(SkRect::Make(dirty_rect));
  StartListeningForDidProcessTask();
}

void CanvasRenderingContext::DidDraw() {
  Host()->DidDraw();
  StartListeningForDidProcessTask();
}

void CanvasRenderingContext::DidProcessTask(
    const base::PendingTask& /* pending_task */) {
  StopListeningForDidProcessTask();

  // The end of a script task that drew content to the canvas is the point
  // at which the current frame may be considered complete.
  if (Host())
    Host()->PreFinalizeFrame();
  FinalizeFrame();
  if (Host())
    Host()->PostFinalizeFrame();
}

void CanvasRenderingContext::RecordUKMCanvasRenderingAPI(
    CanvasRenderingAPI canvasRenderingAPI) {
  DCHECK(Host());
  const auto& ukm_params = Host()->GetUkmParameters();
  if (Host()->IsOffscreenCanvas()) {
    ukm::builders::ClientRenderingAPI(ukm_params.source_id)
        .SetOffscreenCanvas_RenderingContext(
            static_cast<int>(canvasRenderingAPI))
        .Record(ukm_params.ukm_recorder);
  } else {
    ukm::builders::ClientRenderingAPI(ukm_params.source_id)
        .SetCanvas_RenderingContext(static_cast<int>(canvasRenderingAPI))
        .Record(ukm_params.ukm_recorder);
  }
}

void CanvasRenderingContext::RecordUKMCanvasDrawnToRenderingAPI(
    CanvasRenderingAPI canvasRenderingAPI) {
  DCHECK(Host());
  const auto& ukm_params = Host()->GetUkmParameters();
  if (Host()->IsOffscreenCanvas()) {
    ukm::builders::ClientRenderingAPI(ukm_params.source_id)
        .SetOffscreenCanvas_RenderingContextDrawnTo(
            static_cast<int>(canvasRenderingAPI))
        .Record(ukm_params.ukm_recorder);
  } else {
    ukm::builders::ClientRenderingAPI(ukm_params.source_id)
        .SetCanvas_RenderingContextDrawnTo(static_cast<int>(canvasRenderingAPI))
        .Record(ukm_params.ukm_recorder);
  }
}

CanvasRenderingContext::ContextType CanvasRenderingContext::ContextTypeFromId(
    const String& id) {
  if (id == "2d")
    return kContext2D;
  if (id == "experimental-webgl")
    return kContextExperimentalWebgl;
  if (id == "webgl")
    return kContextWebgl;
  if (id == "webgl2")
    return kContextWebgl2;
  if (id == "bitmaprenderer")
    return kContextImageBitmap;
  if (id == "gpupresent" && RuntimeEnabledFeatures::WebGPUEnabled())
    return kContextGPUPresent;
  return kContextTypeUnknown;
}

CanvasRenderingContext::ContextType
CanvasRenderingContext::ResolveContextTypeAliases(
    CanvasRenderingContext::ContextType type) {
  if (type == kContextExperimentalWebgl)
    return kContextWebgl;
  return type;
}

bool CanvasRenderingContext::WouldTaintOrigin(CanvasImageSource* image_source) {
  // Don't taint the canvas on data URLs. This special case is needed here
  // because CanvasImageSource::WouldTaintOrigin() can return false for data
  // URLs due to restrictions on SVG foreignObject nodes as described in
  // https://crbug.com/294129.
  // TODO(crbug.com/294129): Remove the restriction on foreignObject nodes, then
  // this logic isn't needed, CanvasImageSource::SourceURL() isn't needed, and
  // this function can just be image_source->WouldTaintOrigin().
  const KURL& source_url = image_source->SourceURL();
  const bool has_url = (source_url.IsValid() && !source_url.IsAboutBlankURL());
  if (has_url && source_url.ProtocolIsData())
    return false;

  return image_source->WouldTaintOrigin();
}

void CanvasRenderingContext::Trace(Visitor* visitor) const {
  visitor->Trace(host_);
  ScriptWrappable::Trace(visitor);
}

void CanvasRenderingContext::StartListeningForDidProcessTask() {
  if (listening_for_did_process_task_)
    return;

  listening_for_did_process_task_ = true;
  Thread::Current()->AddTaskObserver(this);
}

void CanvasRenderingContext::StopListeningForDidProcessTask() {
  if (!listening_for_did_process_task_)
    return;

  Thread::Current()->RemoveTaskObserver(this);
  listening_for_did_process_task_ = false;
}

}  // namespace blink
