/*
 * Copyright (C) 2006 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. 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. ``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
 * 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/svg/graphics/svg_image.h"

#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/svg/animation/smil_time_container.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h"
#include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/core/svg/svg_fe_image_element.h"
#include "third_party/blink/renderer/core/svg/svg_image_element.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/image_observer.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"

namespace blink {

// SVGImageLocalFrameClient is used to wait until SVG document's load event
// in the case where there are subresources asynchronously loaded.
//
// Reference cycle: SVGImage -(Persistent)-> Page -(Member)-> Frame -(Member)->
// FrameClient == SVGImageLocalFrameClient -(raw)-> SVGImage.
class SVGImage::SVGImageLocalFrameClient : public EmptyLocalFrameClient {
 public:
  SVGImageLocalFrameClient(SVGImage* image) : image_(image) {}

  void ClearImage() { image_ = nullptr; }

 private:
  std::unique_ptr<WebURLLoaderFactory> CreateURLLoaderFactory() override {
    return Platform::Current()->CreateDefaultURLLoaderFactory();
  }

  void DispatchDidHandleOnloadEvents() override {
    // The SVGImage was destructed before SVG load completion.
    if (!image_)
      return;

    image_->LoadCompleted();
  }

  // Cleared manually by SVGImage's destructor when |image_| is destructed.
  SVGImage* image_;
};

SVGImage::SVGImage(ImageObserver* observer, bool is_multipart)
    : Image(observer, is_multipart),
      paint_controller_(PaintController::Create()),
      has_pending_timeline_rewind_(false) {}

SVGImage::~SVGImage() {
  if (frame_client_)
    frame_client_->ClearImage();

  if (page_) {
    // Store m_page in a local variable, clearing m_page, so that
    // SVGImageChromeClient knows we're destructed.
    Page* current_page = page_.Release();
    // Break both the loader and view references to the frame
    current_page->WillBeDestroyed();
  }

  // Verify that page teardown destroyed the Chrome
  DCHECK(!chrome_client_ || !chrome_client_->GetImage());
}

bool SVGImage::IsInSVGImage(const Node* node) {
  DCHECK(node);

  Page* page = node->GetDocument().GetPage();
  if (!page)
    return false;

  return page->GetChromeClient().IsSVGImageChromeClient();
}

void SVGImage::CheckLoaded() const {
  CHECK(page_);

  LocalFrame* frame = ToLocalFrame(page_->MainFrame());

  // Failures of this assertion might result in wrong origin tainting checks,
  // because CurrentFrameHasSingleSecurityOrigin() assumes all subresources of
  // the SVG are loaded and thus ready for origin checks.
  CHECK(frame->GetDocument()->LoadEventFinished());
}

bool SVGImage::CurrentFrameHasSingleSecurityOrigin() const {
  if (!page_)
    return true;

  LocalFrame* frame = ToLocalFrame(page_->MainFrame());

  CheckLoaded();

  SVGSVGElement* root_element =
      frame->GetDocument()->AccessSVGExtensions().rootElement();
  if (!root_element)
    return true;

  // Don't allow foreignObject elements or images that are not known to be
  // single-origin since these can leak cross-origin information.
  for (Node* node = root_element; node; node = FlatTreeTraversal::Next(*node)) {
    if (IsSVGForeignObjectElement(*node))
      return false;
    if (auto* image = ToSVGImageElementOrNull(*node)) {
      if (!image->CurrentFrameHasSingleSecurityOrigin())
        return false;
    } else if (auto* fe_image = ToSVGFEImageElementOrNull(*node)) {
      if (!fe_image->CurrentFrameHasSingleSecurityOrigin())
        return false;
    }
  }

  // Because SVG image rendering disallows external resources and links, these
  // images effectively are restricted to a single security origin.
  return true;
}

static SVGSVGElement* SvgRootElement(Page* page) {
  if (!page)
    return nullptr;
  LocalFrame* frame = ToLocalFrame(page->MainFrame());
  return frame->GetDocument()->AccessSVGExtensions().rootElement();
}

IntSize SVGImage::ContainerSize() const {
  SVGSVGElement* root_element = SvgRootElement(page_.Get());
  if (!root_element)
    return IntSize();

  LayoutSVGRoot* layout_object =
      ToLayoutSVGRoot(root_element->GetLayoutObject());
  if (!layout_object)
    return IntSize();

  // If a container size is available it has precedence.
  IntSize container_size = layout_object->ContainerSize();
  if (!container_size.IsEmpty())
    return container_size;

  // Assure that a container size is always given for a non-identity zoom level.
  DCHECK_EQ(layout_object->StyleRef().EffectiveZoom(), 1);

  // No set container size; use concrete object size.
  return intrinsic_size_;
}

static float ResolveWidthForRatio(float height,
                                  const FloatSize& intrinsic_ratio) {
  return height * intrinsic_ratio.Width() / intrinsic_ratio.Height();
}

static float ResolveHeightForRatio(float width,
                                   const FloatSize& intrinsic_ratio) {
  return width * intrinsic_ratio.Height() / intrinsic_ratio.Width();
}

bool SVGImage::HasIntrinsicDimensions() const {
  return !ConcreteObjectSize(FloatSize()).IsEmpty();
}

bool SVGImage::HasIntrinsicSizingInfo() const {
  SVGSVGElement* svg = SvgRootElement(page_.Get());
  return svg && svg->GetLayoutObject();
}

bool SVGImage::GetIntrinsicSizingInfo(
    IntrinsicSizingInfo& intrinsic_sizing_info) const {
  SVGSVGElement* svg = SvgRootElement(page_.Get());
  if (!svg)
    return false;

  LayoutSVGRoot* layout_object = ToLayoutSVGRoot(svg->GetLayoutObject());
  if (!layout_object)
    return false;

  layout_object->UnscaledIntrinsicSizingInfo(intrinsic_sizing_info);
  return true;
}

FloatSize SVGImage::ConcreteObjectSize(
    const FloatSize& default_object_size) const {
  IntrinsicSizingInfo intrinsic_sizing_info;
  if (!GetIntrinsicSizingInfo(intrinsic_sizing_info))
    return FloatSize();

  // https://www.w3.org/TR/css3-images/#default-sizing
  if (intrinsic_sizing_info.has_width && intrinsic_sizing_info.has_height)
    return intrinsic_sizing_info.size;

  // We're not using an intrinsic aspect ratio to resolve a missing
  // intrinsic width or height when preserveAspectRatio is none.
  // (Ref: crbug.com/584172)
  SVGSVGElement* svg = SvgRootElement(page_.Get());
  if (svg->preserveAspectRatio()->CurrentValue()->Align() ==
      SVGPreserveAspectRatio::kSvgPreserveaspectratioNone)
    return default_object_size;

  if (intrinsic_sizing_info.has_width) {
    if (intrinsic_sizing_info.aspect_ratio.IsEmpty())
      return FloatSize(intrinsic_sizing_info.size.Width(),
                       default_object_size.Height());

    return FloatSize(intrinsic_sizing_info.size.Width(),
                     ResolveHeightForRatio(intrinsic_sizing_info.size.Width(),
                                           intrinsic_sizing_info.aspect_ratio));
  }

  if (intrinsic_sizing_info.has_height) {
    if (intrinsic_sizing_info.aspect_ratio.IsEmpty())
      return FloatSize(default_object_size.Width(),
                       intrinsic_sizing_info.size.Height());

    return FloatSize(ResolveWidthForRatio(intrinsic_sizing_info.size.Height(),
                                          intrinsic_sizing_info.aspect_ratio),
                     intrinsic_sizing_info.size.Height());
  }

  if (!intrinsic_sizing_info.aspect_ratio.IsEmpty()) {
    // "A contain constraint is resolved by setting the concrete object size to
    //  the largest rectangle that has the object's intrinsic aspect ratio and
    //  additionally has neither width nor height larger than the constraint
    //  rectangle's width and height, respectively."
    float solution_width = ResolveWidthForRatio(
        default_object_size.Height(), intrinsic_sizing_info.aspect_ratio);
    if (solution_width <= default_object_size.Width())
      return FloatSize(solution_width, default_object_size.Height());

    float solution_height = ResolveHeightForRatio(
        default_object_size.Width(), intrinsic_sizing_info.aspect_ratio);
    return FloatSize(default_object_size.Width(), solution_height);
  }

  return default_object_size;
}

template <typename Func>
void SVGImage::ForContainer(const FloatSize& container_size, Func&& func) {
  if (!page_)
    return;

  // Temporarily disable the image observer to prevent changeInRect() calls due
  // re-laying out the image.
  ImageObserverDisabler image_observer_disabler(this);

  IntSize rounded_container_size = RoundedIntSize(container_size);

  if (SVGSVGElement* root_element = SvgRootElement(page_.Get())) {
    if (LayoutSVGRoot* layout_object =
            ToLayoutSVGRoot(root_element->GetLayoutObject()))
      layout_object->SetContainerSize(rounded_container_size);
  }

  func(FloatSize(rounded_container_size.Width() / container_size.Width(),
                 rounded_container_size.Height() / container_size.Height()));
}

void SVGImage::DrawForContainer(cc::PaintCanvas* canvas,
                                const PaintFlags& flags,
                                const FloatSize& container_size,
                                float zoom,
                                const FloatRect& dst_rect,
                                const FloatRect& src_rect,
                                const KURL& url) {
  ForContainer(container_size, [&](const FloatSize& residual_scale) {
    FloatRect scaled_src = src_rect;
    scaled_src.Scale(1 / zoom);

    // Compensate for the container size rounding by adjusting the source rect.
    FloatSize adjusted_src_size = scaled_src.Size();
    adjusted_src_size.Scale(residual_scale.Width(), residual_scale.Height());
    scaled_src.SetSize(adjusted_src_size);

    DrawInternal(canvas, flags, dst_rect, scaled_src,
                 kDoNotRespectImageOrientation, kClampImageToSourceRect, url);
  });
}

PaintImage SVGImage::PaintImageForCurrentFrame() {
  auto builder =
      CreatePaintImageBuilder().set_completion_state(completion_state());
  PopulatePaintRecordForCurrentFrameForContainer(builder, NullURL(), Size());
  return builder.TakePaintImage();
}

void SVGImage::DrawPatternForContainer(GraphicsContext& context,
                                       const FloatSize container_size,
                                       float zoom,
                                       const FloatRect& src_rect,
                                       const FloatSize& tile_scale,
                                       const FloatPoint& phase,
                                       SkBlendMode composite_op,
                                       const FloatRect& dst_rect,
                                       const FloatSize& repeat_spacing,
                                       const KURL& url) {
  // Tile adjusted for scaling/stretch.
  FloatRect tile(src_rect);
  tile.Scale(tile_scale.Width(), tile_scale.Height());

  // Expand the tile to account for repeat spacing.
  FloatRect spaced_tile(tile);
  spaced_tile.Expand(FloatSize(repeat_spacing));

  PaintRecordBuilder builder(nullptr, &context);
  {
    DrawingRecorder recorder(builder.Context(), builder,
                             DisplayItem::Type::kSVGImage);
    // When generating an expanded tile, make sure we don't draw into the
    // spacing area.
    if (tile != spaced_tile)
      builder.Context().Clip(tile);
    PaintFlags flags;
    DrawForContainer(builder.Context().Canvas(), flags, container_size, zoom,
                     tile, src_rect, url);
  }
  sk_sp<PaintRecord> record = builder.EndRecording();

  SkMatrix pattern_transform;
  pattern_transform.setTranslate(phase.X() + spaced_tile.X(),
                                 phase.Y() + spaced_tile.Y());

  PaintFlags flags;
  flags.setShader(PaintShader::MakePaintRecord(
      record, spaced_tile, SkShader::kRepeat_TileMode,
      SkShader::kRepeat_TileMode, &pattern_transform));
  // If the shader could not be instantiated (e.g. non-invertible matrix),
  // draw transparent.
  // Note: we can't simply bail, because of arbitrary blend mode.
  if (!flags.HasShader())
    flags.setColor(SK_ColorTRANSPARENT);

  flags.setBlendMode(composite_op);
  flags.setColorFilter(sk_ref_sp(context.GetColorFilter()));
  context.DrawRect(dst_rect, flags);
}

sk_sp<PaintRecord> SVGImage::PaintRecordForContainer(
    const KURL& url,
    const IntSize& container_size,
    const IntRect& draw_src_rect,
    const IntRect& draw_dst_rect,
    bool flip_y) {
  if (!page_)
    return nullptr;

  PaintRecorder recorder;
  cc::PaintCanvas* canvas = recorder.beginRecording(draw_src_rect);
  if (flip_y) {
    canvas->translate(0, draw_dst_rect.Height());
    canvas->scale(1, -1);
  }
  DrawForContainer(canvas, PaintFlags(), FloatSize(container_size), 1,
                   FloatRect(draw_dst_rect), FloatRect(draw_src_rect), url);
  return recorder.finishRecordingAsPicture();
}

void SVGImage::PopulatePaintRecordForCurrentFrameForContainer(
    PaintImageBuilder& builder,
    const KURL& url,
    const IntSize& container_size) {
  if (!page_)
    return;

  const IntRect container_rect(IntPoint(), container_size);

  PaintRecorder recorder;
  cc::PaintCanvas* canvas = recorder.beginRecording(container_rect);
  DrawForContainer(canvas, PaintFlags(), FloatSize(container_rect.Size()), 1,
                   FloatRect(container_rect), FloatRect(container_rect), url);
  builder.set_paint_record(recorder.finishRecordingAsPicture(), container_rect,
                           PaintImage::GetNextContentId());
}

static bool DrawNeedsLayer(const PaintFlags& flags) {
  if (SkColorGetA(flags.getColor()) < 255)
    return true;

  return flags.getBlendMode() != SkBlendMode::kSrcOver;
}

bool SVGImage::ApplyShaderInternal(PaintFlags& flags,
                                   const SkMatrix& local_matrix,
                                   const KURL& url) {
  const IntSize size(ContainerSize());
  if (size.IsEmpty())
    return false;

  IntRect bounds(IntPoint(), size);

  flags.setShader(PaintShader::MakePaintRecord(
      PaintRecordForCurrentFrame(bounds, url), bounds,
      SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &local_matrix));

  // Animation is normally refreshed in draw() impls, which we don't reach when
  // painting via shaders.
  StartAnimation();

  return true;
}

bool SVGImage::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) {
  return ApplyShaderInternal(flags, local_matrix, NullURL());
}

bool SVGImage::ApplyShaderForContainer(const FloatSize& container_size,
                                       float zoom,
                                       const KURL& url,
                                       PaintFlags& flags,
                                       const SkMatrix& local_matrix) {
  bool result = false;
  ForContainer(container_size, [&](const FloatSize& residual_scale) {
    // Compensate for the container size rounding.
    auto adjusted_local_matrix = local_matrix;
    adjusted_local_matrix.preScale(zoom * residual_scale.Width(),
                                   zoom * residual_scale.Height());

    result = ApplyShaderInternal(flags, adjusted_local_matrix, url);
  });

  return result;
}

void SVGImage::Draw(
    cc::PaintCanvas* canvas,
    const PaintFlags& flags,
    const FloatRect& dst_rect,
    const FloatRect& src_rect,
    RespectImageOrientationEnum should_respect_image_orientation,
    ImageClampingMode clamp_mode,
    ImageDecodingMode) {
  if (!page_)
    return;

  DrawInternal(canvas, flags, dst_rect, src_rect,
               should_respect_image_orientation, clamp_mode, NullURL());
}

sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(
    const IntRect& bounds,
    const KURL& url,
    cc::PaintCanvas* canvas) {
  DCHECK(page_);
  LocalFrameView* view = ToLocalFrame(page_->MainFrame())->View();
  view->Resize(ContainerSize());
  page_->GetVisualViewport().SetSize(ContainerSize());

  // Always call processUrlFragment, even if the url is empty, because
  // there may have been a previous url/fragment that needs to be reset.
  view->ProcessUrlFragment(url);

  // If the image was reset, we need to rewind the timeline back to 0. This
  // needs to be done before painting, or else we wouldn't get the correct
  // reset semantics (we'd paint the "last" frame rather than the one at
  // time=0.) The reason we do this here and not in resetAnimation() is to
  // avoid setting timers from the latter.
  FlushPendingTimelineRewind();

  PaintRecordBuilder builder(nullptr, nullptr, paint_controller_.get());

  view->UpdateAllLifecyclePhasesExceptPaint();
  view->PaintWithLifecycleUpdate(builder.Context(), kGlobalPaintNormalPhase,
                                 CullRect(bounds));
  DCHECK(!view->NeedsLayout());

  if (canvas) {
    builder.EndRecording(*canvas);
    return nullptr;
  }
  return builder.EndRecording();
}

void SVGImage::DrawInternal(cc::PaintCanvas* canvas,
                            const PaintFlags& flags,
                            const FloatRect& dst_rect,
                            const FloatRect& src_rect,
                            RespectImageOrientationEnum,
                            ImageClampingMode,
                            const KURL& url) {
  {
    PaintCanvasAutoRestore ar(canvas, false);
    if (DrawNeedsLayer(flags)) {
      SkRect layer_rect = dst_rect;
      canvas->saveLayer(&layer_rect, &flags);
    }
    // We can only draw the entire frame, clipped to the rect we want. So
    // compute where the top left of the image would be if we were drawing
    // without clipping, and translate accordingly.
    FloatSize scale(dst_rect.Width() / src_rect.Width(),
                    dst_rect.Height() / src_rect.Height());
    FloatSize top_left_offset(src_rect.Location().X() * scale.Width(),
                              src_rect.Location().Y() * scale.Height());
    FloatPoint dest_offset = dst_rect.Location() - top_left_offset;
    AffineTransform transform =
        AffineTransform::Translation(dest_offset.X(), dest_offset.Y());
    transform.Scale(scale.Width(), scale.Height());

    canvas->save();
    canvas->clipRect(EnclosingIntRect(dst_rect));
    canvas->concat(AffineTransformToSkMatrix(transform));
    PaintRecordForCurrentFrame(EnclosingIntRect(src_rect), url, canvas);
    canvas->restore();
  }

  // Start any (SMIL) animations if needed. This will restart or continue
  // animations if preceded by calls to resetAnimation or stopAnimation
  // respectively.
  StartAnimation();
}

void SVGImage::ScheduleTimelineRewind() {
  has_pending_timeline_rewind_ = true;
}

void SVGImage::FlushPendingTimelineRewind() {
  if (!has_pending_timeline_rewind_)
    return;
  if (SVGSVGElement* root_element = SvgRootElement(page_.Get()))
    root_element->setCurrentTime(0);
  has_pending_timeline_rewind_ = false;
}

void SVGImage::StartAnimation() {
  SVGSVGElement* root_element = SvgRootElement(page_.Get());
  if (!root_element)
    return;
  chrome_client_->ResumeAnimation();
  if (root_element->animationsPaused())
    root_element->unpauseAnimations();
}

void SVGImage::StopAnimation() {
  SVGSVGElement* root_element = SvgRootElement(page_.Get());
  if (!root_element)
    return;
  chrome_client_->SuspendAnimation();
  root_element->pauseAnimations();
}

void SVGImage::ResetAnimation() {
  SVGSVGElement* root_element = SvgRootElement(page_.Get());
  if (!root_element)
    return;
  chrome_client_->SuspendAnimation();
  root_element->pauseAnimations();
  ScheduleTimelineRewind();
}

void SVGImage::RestoreAnimation() {
  // If the image has no animations then do nothing.
  if (!MaybeAnimated())
    return;
  // If there are no clients, or no client is going to render, then do nothing.
  ImageObserver* image_observer = GetImageObserver();
  if (!image_observer || image_observer->ShouldPauseAnimation(this))
    return;
  StartAnimation();
}

bool SVGImage::MaybeAnimated() {
  SVGSVGElement* root_element = SvgRootElement(page_.Get());
  if (!root_element)
    return false;
  return root_element->TimeContainer()->HasAnimations() ||
         ToLocalFrame(page_->MainFrame())
             ->GetDocument()
             ->Timeline()
             .HasPendingUpdates();
}

void SVGImage::ServiceAnimations(
    base::TimeTicks monotonic_animation_start_time) {
  if (!GetImageObserver())
    return;

  // If none of our observers (sic!) are visible, or for some other reason
  // does not want us to keep running animations, stop them until further
  // notice (next paint.)
  if (GetImageObserver()->ShouldPauseAnimation(this)) {
    StopAnimation();
    return;
  }

  // serviceScriptedAnimations runs requestAnimationFrame callbacks, but SVG
  // images can't have any so we assert there's no script.
  ScriptForbiddenScope forbid_script;

  // The calls below may trigger GCs, so set up the required persistent
  // reference on the ImageResourceContent which owns this SVGImage. By
  // transitivity, that will keep the associated SVGImageChromeClient object
  // alive.
  Persistent<ImageObserver> protect(GetImageObserver());
  page_->Animator().ServiceScriptedAnimations(monotonic_animation_start_time);

  // Do *not* update the paint phase. It's critical to paint only when
  // actually generating painted output, not only for performance reasons,
  // but to preserve correct coherence of the cache of the output with
  // the needsRepaint bits of the PaintLayers in the image.
  LocalFrameView* frame_view = ToLocalFrame(page_->MainFrame())->View();
  frame_view->UpdateAllLifecyclePhasesExceptPaint();

  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
      RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
    // For CAP/BGPT we run UpdateAnimations after the paint phase, but per the
    // above comment, we don't want to run lifecycle through to paint for SVG
    // images. Since we know SVG images never have composited animations we can
    // update animations directly without worrying about including
    // PaintArtifactCompositor analysis of whether animations should be
    // composited.
    base::Optional<CompositorElementIdSet> composited_element_ids;
    DocumentAnimations::UpdateAnimations(
        frame_view->GetLayoutView()->GetDocument(),
        DocumentLifecycle::kLayoutClean, composited_element_ids);

    // Notify observers for image change. In SPv1 this is done through window
    // rect invalidation during paint invalidation of the SVGImage's frame view.
    auto* layer = frame_view->GetLayoutView()->Layer();
    if (layer->NeedsRepaint()) {
      if (auto* observer = GetImageObserver())
        observer->Changed(this);
    }
  }
}

void SVGImage::AdvanceAnimationForTesting() {
  if (SVGSVGElement* root_element = SvgRootElement(page_.Get())) {
    root_element->TimeContainer()->AdvanceFrameForTesting();

    // The following triggers animation updates which can issue a new draw
    // but will not permanently change the animation timeline.
    // TODO(pdr): Actually advance the document timeline so CSS animations
    // can be properly tested.
    page_->Animator().ServiceScriptedAnimations(
        base::TimeTicks() +
        base::TimeDelta::FromSecondsD(root_element->getCurrentTime()));
    GetImageObserver()->Changed(this);
  }
}

SVGImageChromeClient& SVGImage::ChromeClientForTesting() {
  return *chrome_client_;
}

void SVGImage::UpdateUseCounters(const Document& document) const {
  if (SVGSVGElement* root_element = SvgRootElement(page_.Get())) {
    if (root_element->TimeContainer()->HasAnimations()) {
      UseCounter::Count(document,
                        WebFeature::kSVGSMILAnimationInImageRegardlessOfCache);
    }
  }
}

void SVGImage::LoadCompleted() {
  switch (load_state_) {
    case kInDataChanged:
      load_state_ = kLoadCompleted;
      break;

    case kWaitingForAsyncLoadCompletion:
      load_state_ = kLoadCompleted;

      // Because LoadCompleted() is called synchronously from
      // Document::ImplicitClose(), we defer AsyncLoadCompleted() to avoid
      // potential bugs and timing dependencies around ImplicitClose() and
      // to make LoadEventFinished() true when AsyncLoadCompleted() is called.
      ToLocalFrame(page_->MainFrame())
          ->GetTaskRunner(TaskType::kInternalLoading)
          ->PostTask(FROM_HERE, WTF::Bind(&SVGImage::NotifyAsyncLoadCompleted,
                                          scoped_refptr<SVGImage>(this)));
      break;

    case kDataChangedNotStarted:
    case kLoadCompleted:
      CHECK(false);
      break;
  }
}

void SVGImage::NotifyAsyncLoadCompleted() {
  if (GetImageObserver())
    GetImageObserver()->AsyncLoadCompleted(this);
}

Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) {
  TRACE_EVENT0("blink", "SVGImage::dataChanged");

  // Don't do anything if is an empty image.
  if (!Data()->size())
    return kSizeAvailable;

  if (!all_data_received)
    return page_ ? kSizeAvailable : kSizeUnavailable;

  CHECK(!page_);

  // SVGImage will fire events (and the default C++ handlers run) but doesn't
  // actually allow script to run so it's fine to call into it. We allow this
  // since it means an SVG data url can synchronously load like other image
  // types.
  EventDispatchForbiddenScope::AllowUserAgentEvents allow_user_agent_events;

  CHECK_EQ(load_state_, kDataChangedNotStarted);
  load_state_ = kInDataChanged;

  Page::PageClients page_clients;
  FillWithEmptyClients(page_clients);
  chrome_client_ = SVGImageChromeClient::Create(this);
  page_clients.chrome_client = chrome_client_.Get();

  // FIXME: If this SVG ends up loading itself, we might leak the world.
  // The Cache code does not know about ImageResources holding Frames and
  // won't know to break the cycle.
  // This will become an issue when SVGImage will be able to load other
  // SVGImage objects, but we're safe now, because SVGImage can only be
  // loaded by a top-level document.
  Page* page;
  {
    TRACE_EVENT0("blink", "SVGImage::dataChanged::createPage");
    page = Page::Create(page_clients);
    page->GetSettings().SetScriptEnabled(false);
    page->GetSettings().SetPluginsEnabled(false);

    // Because this page is detached, it can't get default font settings
    // from the embedder. Copy over font settings so we have sensible
    // defaults. These settings are fixed and will not update if changed.
    if (!Page::OrdinaryPages().IsEmpty()) {
      Settings& default_settings =
          (*Page::OrdinaryPages().begin())->GetSettings();
      page->GetSettings().GetGenericFontFamilySettings() =
          default_settings.GetGenericFontFamilySettings();
      page->GetSettings().SetMinimumFontSize(
          default_settings.GetMinimumFontSize());
      page->GetSettings().SetMinimumLogicalFontSize(
          default_settings.GetMinimumLogicalFontSize());
      page->GetSettings().SetDefaultFontSize(
          default_settings.GetDefaultFontSize());
      page->GetSettings().SetDefaultFixedFontSize(
          default_settings.GetDefaultFixedFontSize());
    }
  }

  LocalFrame* frame = nullptr;
  {
    TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame");
    DCHECK(!frame_client_);
    frame_client_ = MakeGarbageCollected<SVGImageLocalFrameClient>(this);
    frame = LocalFrame::Create(frame_client_, *page, nullptr);
    frame->SetView(LocalFrameView::Create(*frame));
    frame->Init();
  }

  FrameLoader& loader = frame->Loader();
  loader.ForceSandboxFlags(kSandboxAll);

  // SVG Images will always synthesize a viewBox, if it's not available, and
  // thus never see scrollbars.
  frame->View()->SetCanHaveScrollbars(false);
  // SVG Images are transparent.
  frame->View()->SetBaseBackgroundColor(Color::kTransparent);

  page_ = page;

  TRACE_EVENT0("blink", "SVGImage::dataChanged::load");

  frame->ForceSynchronousDocumentInstall("image/svg+xml", Data());

  // Set the concrete object size before a container size is available.
  intrinsic_size_ = RoundedIntSize(ConcreteObjectSize(FloatSize(
      LayoutReplaced::kDefaultWidth, LayoutReplaced::kDefaultHeight)));

  DCHECK(page_);
  switch (load_state_) {
    case kInDataChanged:
      load_state_ = kWaitingForAsyncLoadCompletion;
      return SvgRootElement(page_.Get())
                 ? kSizeAvailableAndLoadingAsynchronously
                 : kSizeUnavailable;

    case kLoadCompleted:
      return SvgRootElement(page_.Get()) ? kSizeAvailable : kSizeUnavailable;

    case kDataChangedNotStarted:
    case kWaitingForAsyncLoadCompletion:
      CHECK(false);
      break;
  }

  NOTREACHED();
  return kSizeAvailable;
}

String SVGImage::FilenameExtension() const {
  return "svg";
}

}  // namespace blink
