/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann
 * <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
 * Copyright (C) 2012 University of Szeged
 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/svg/SVGUseElement.h"

#include "core/SVGNames.h"
#include "core/XLinkNames.h"
#include "core/dom/Document.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/IdTargetObserver.h"
#include "core/dom/StyleChangeReason.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/events/Event.h"
#include "core/layout/svg/LayoutSVGTransformableContainer.h"
#include "core/svg/SVGGElement.h"
#include "core/svg/SVGLengthContext.h"
#include "core/svg/SVGSVGElement.h"
#include "core/svg/SVGSymbolElement.h"
#include "core/svg/SVGTitleElement.h"
#include "core/xml/parser/XMLDocumentParser.h"
#include "platform/loader/fetch/FetchParameters.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/loader/fetch/ResourceLoaderOptions.h"
#include "platform/wtf/Vector.h"

namespace blink {

inline SVGUseElement::SVGUseElement(Document& document)
    : SVGGraphicsElement(SVGNames::useTag, document),
      SVGURIReference(this),
      x_(SVGAnimatedLength::Create(this,
                                   SVGNames::xAttr,
                                   SVGLength::Create(SVGLengthMode::kWidth),
                                   CSSPropertyX)),
      y_(SVGAnimatedLength::Create(this,
                                   SVGNames::yAttr,
                                   SVGLength::Create(SVGLengthMode::kHeight),
                                   CSSPropertyY)),
      width_(
          SVGAnimatedLength::Create(this,
                                    SVGNames::widthAttr,
                                    SVGLength::Create(SVGLengthMode::kWidth))),
      height_(
          SVGAnimatedLength::Create(this,
                                    SVGNames::heightAttr,
                                    SVGLength::Create(SVGLengthMode::kHeight))),
      element_identifier_is_local_(true),
      have_fired_load_event_(false),
      needs_shadow_tree_recreation_(false) {
  DCHECK(HasCustomStyleCallbacks());

  AddToPropertyMap(x_);
  AddToPropertyMap(y_);
  AddToPropertyMap(width_);
  AddToPropertyMap(height_);
}

SVGUseElement* SVGUseElement::Create(Document& document) {
  // Always build a user agent #shadow-root for SVGUseElement.
  SVGUseElement* use = new SVGUseElement(document);
  use->EnsureShadow().AddShadowRoot(*use, ShadowRootType::kClosed);
  return use;
}

SVGUseElement::~SVGUseElement() {}

void SVGUseElement::Dispose() {
  SetDocumentResource(nullptr);
}

DEFINE_TRACE(SVGUseElement) {
  visitor->Trace(x_);
  visitor->Trace(y_);
  visitor->Trace(width_);
  visitor->Trace(height_);
  visitor->Trace(target_element_instance_);
  visitor->Trace(target_id_observer_);
  visitor->Trace(resource_);
  SVGGraphicsElement::Trace(visitor);
  SVGURIReference::Trace(visitor);
  DocumentResourceClient::Trace(visitor);
}

#if DCHECK_IS_ON()
static inline bool IsWellFormedDocument(Document* document) {
  if (document->IsXMLDocument())
    return static_cast<XMLDocumentParser*>(document->Parser())->WellFormed();
  return true;
}
#endif

Node::InsertionNotificationRequest SVGUseElement::InsertedInto(
    ContainerNode* root_parent) {
  // This functions exists to assure assumptions made in the code regarding
  // SVGElementInstance creation/destruction are satisfied.
  SVGGraphicsElement::InsertedInto(root_parent);
  if (!root_parent->isConnected())
    return kInsertionDone;
#if DCHECK_IS_ON()
  DCHECK(!target_element_instance_ || !IsWellFormedDocument(&GetDocument()));
  DCHECK(!HasPendingResources() || !IsWellFormedDocument(&GetDocument()));
#endif
  InvalidateShadowTree();
  return kInsertionDone;
}

void SVGUseElement::RemovedFrom(ContainerNode* root_parent) {
  SVGGraphicsElement::RemovedFrom(root_parent);
  if (root_parent->isConnected()) {
    ClearResourceReference();
    CancelShadowTreeRecreation();
  }
}

static void TransferUseWidthAndHeightIfNeeded(
    const SVGUseElement& use,
    SVGElement& shadow_element,
    const SVGElement& original_element) {
  DEFINE_STATIC_LOCAL(const AtomicString, hundred_percent_string, ("100%"));
  // Use |originalElement| for checking the element type, because we will
  // have replaced a <symbol> with an <svg> in the instance tree.
  if (isSVGSymbolElement(original_element)) {
    // Spec (<use> on <symbol>): This generated 'svg' will always have
    // explicit values for attributes width and height.  If attributes
    // width and/or height are provided on the 'use' element, then these
    // attributes will be transferred to the generated 'svg'. If attributes
    // width and/or height are not specified, the generated 'svg' element
    // will use values of 100% for these attributes.
    shadow_element.setAttribute(
        SVGNames::widthAttr,
        use.width()->IsSpecified()
            ? AtomicString(use.width()->CurrentValue()->ValueAsString())
            : hundred_percent_string);
    shadow_element.setAttribute(
        SVGNames::heightAttr,
        use.height()->IsSpecified()
            ? AtomicString(use.height()->CurrentValue()->ValueAsString())
            : hundred_percent_string);
  } else if (isSVGSVGElement(original_element)) {
    // Spec (<use> on <svg>): If attributes width and/or height are
    // provided on the 'use' element, then these values will override the
    // corresponding attributes on the 'svg' in the generated tree.
    shadow_element.setAttribute(
        SVGNames::widthAttr,
        use.width()->IsSpecified()
            ? AtomicString(use.width()->CurrentValue()->ValueAsString())
            : original_element.getAttribute(SVGNames::widthAttr));
    shadow_element.setAttribute(
        SVGNames::heightAttr,
        use.height()->IsSpecified()
            ? AtomicString(use.height()->CurrentValue()->ValueAsString())
            : original_element.getAttribute(SVGNames::heightAttr));
  }
}

void SVGUseElement::CollectStyleForPresentationAttribute(
    const QualifiedName& name,
    const AtomicString& value,
    MutableStylePropertySet* style) {
  SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
  if (property == x_) {
    AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
                                            x_->CssValue());
  } else if (property == y_) {
    AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
                                            y_->CssValue());
  } else {
    SVGGraphicsElement::CollectStyleForPresentationAttribute(name, value,
                                                             style);
  }
}

bool SVGUseElement::IsStructurallyExternal() const {
  return !element_identifier_is_local_;
}

void SVGUseElement::UpdateTargetReference() {
  SVGURLReferenceResolver resolver(HrefString(), GetDocument());
  element_identifier_ = resolver.FragmentIdentifier();
  element_identifier_is_local_ = resolver.IsLocal();
  if (element_identifier_is_local_) {
    SetDocumentResource(nullptr);
    return;
  }
  KURL resolved_url = resolver.AbsoluteUrl();
  if (element_identifier_.IsEmpty() ||
      (resource_ &&
       EqualIgnoringFragmentIdentifier(resolved_url, resource_->Url())))
    return;

  ResourceLoaderOptions options;
  options.initiator_info.name = localName();
  FetchParameters params(ResourceRequest(resolved_url), options);
  SetDocumentResource(
      DocumentResource::FetchSVGDocument(params, GetDocument().Fetcher()));
}

void SVGUseElement::SvgAttributeChanged(const QualifiedName& attr_name) {
  if (attr_name == SVGNames::xAttr || attr_name == SVGNames::yAttr ||
      attr_name == SVGNames::widthAttr || attr_name == SVGNames::heightAttr) {
    SVGElement::InvalidationGuard invalidation_guard(this);

    if (attr_name == SVGNames::xAttr || attr_name == SVGNames::yAttr) {
      InvalidateSVGPresentationAttributeStyle();
      SetNeedsStyleRecalc(
          kLocalStyleChange,
          StyleChangeReasonForTracing::FromAttribute(attr_name));
    }

    UpdateRelativeLengthsInformation();
    if (target_element_instance_) {
      DCHECK(target_element_instance_->CorrespondingElement());
      TransferUseWidthAndHeightIfNeeded(
          *this, *target_element_instance_,
          *target_element_instance_->CorrespondingElement());
    }

    LayoutObject* object = this->GetLayoutObject();
    if (object)
      MarkForLayoutAndParentResourceInvalidation(object);
    return;
  }

  if (SVGURIReference::IsKnownAttribute(attr_name)) {
    SVGElement::InvalidationGuard invalidation_guard(this);
    UpdateTargetReference();
    InvalidateShadowTree();
    return;
  }

  SVGGraphicsElement::SvgAttributeChanged(attr_name);
}

static bool IsDisallowedElement(const Element& element) {
  // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is
  // potentially a template object that can be re-used (i.e., "instanced") in
  // the SVG document via a 'use' element." "Graphics Element" is defined as
  // 'circle', 'ellipse', 'image', 'line', 'path', 'polygon', 'polyline',
  // 'rect', 'text' Excluded are anything that is used by reference or that only
  // make sense to appear once in a document.
  if (!element.IsSVGElement())
    return true;

  DEFINE_STATIC_LOCAL(
      HashSet<QualifiedName>, allowed_element_tags,
      ({
          SVGNames::aTag,       SVGNames::circleTag,   SVGNames::descTag,
          SVGNames::ellipseTag, SVGNames::gTag,        SVGNames::imageTag,
          SVGNames::lineTag,    SVGNames::metadataTag, SVGNames::pathTag,
          SVGNames::polygonTag, SVGNames::polylineTag, SVGNames::rectTag,
          SVGNames::svgTag,     SVGNames::switchTag,   SVGNames::symbolTag,
          SVGNames::textTag,    SVGNames::textPathTag, SVGNames::titleTag,
          SVGNames::tspanTag,   SVGNames::useTag,
      }));
  return !allowed_element_tags.Contains<SVGAttributeHashTranslator>(
      element.TagQName());
}

void SVGUseElement::ScheduleShadowTreeRecreation() {
  if (InUseShadowTree())
    return;
  needs_shadow_tree_recreation_ = true;
  GetDocument().ScheduleUseShadowTreeUpdate(*this);
}

void SVGUseElement::CancelShadowTreeRecreation() {
  needs_shadow_tree_recreation_ = false;
  GetDocument().UnscheduleUseShadowTreeUpdate(*this);
}

void SVGUseElement::ClearInstanceRoot() {
  target_element_instance_ = nullptr;
}

void SVGUseElement::ClearResourceReference() {
  UnobserveTarget(target_id_observer_);
  ClearInstanceRoot();
  RemoveAllOutgoingReferences();
}

Element* SVGUseElement::ResolveTargetElement(ObserveBehavior observe_behavior) {
  if (element_identifier_.IsEmpty())
    return nullptr;
  if (element_identifier_is_local_) {
    if (observe_behavior == kDontAddObserver)
      return GetTreeScope().getElementById(element_identifier_);
    return ObserveTarget(target_id_observer_, GetTreeScope(),
                         element_identifier_,
                         WTF::Bind(&SVGUseElement::InvalidateShadowTree,
                                   WrapWeakPersistent(this)));
  }
  if (!ResourceIsValid())
    return nullptr;
  return resource_->GetDocument()->getElementById(element_identifier_);
}

void SVGUseElement::BuildPendingResource() {
  if (InUseShadowTree())
    return;
  // FIXME: We should try to optimize this, to at least allow partial reclones.
  UseShadowRoot().RemoveChildren(kOmitSubtreeModifiedEvent);
  ClearResourceReference();
  CancelShadowTreeRecreation();
  if (!isConnected())
    return;
  Element* target = ResolveTargetElement(kAddObserver);
  // TODO(fs): Why would the Element not be "connected" at this point?
  if (target && target->isConnected() && target->IsSVGElement()) {
    BuildShadowAndInstanceTree(ToSVGElement(*target));
    InvalidateDependentShadowTrees();
  }

  DCHECK(!needs_shadow_tree_recreation_);
}

String SVGUseElement::title() const {
  // Find the first <title> child in <use> which doesn't cover shadow tree.
  if (Element* title_element = Traversal<SVGTitleElement>::FirstChild(*this))
    return title_element->innerText();

  // If there is no <title> child in <use>, we lookup first <title> child in
  // shadow tree.
  if (target_element_instance_) {
    if (Element* title_element =
            Traversal<SVGTitleElement>::FirstChild(*target_element_instance_))
      return title_element->innerText();
  }
  // Otherwise return a null string.
  return String();
}

static void AssociateCorrespondingElements(SVGElement& target_root,
                                           SVGElement& instance_root) {
  auto target_range =
      Traversal<SVGElement>::InclusiveDescendantsOf(target_root);
  auto target_iterator = target_range.begin();
  for (SVGElement& instance :
       Traversal<SVGElement>::InclusiveDescendantsOf(instance_root)) {
    DCHECK(!instance.CorrespondingElement());
    instance.SetCorrespondingElement(&*target_iterator);
    ++target_iterator;
  }
  DCHECK(!(target_iterator != target_range.end()));
}

// We don't walk the target tree element-by-element, and clone each element,
// but instead use cloneNode(deep=true). This is an optimization for the common
// case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
// Though if there are disallowed elements in the subtree, we have to remove
// them.  For instance: <use> on <g> containing <foreignObject> (indirect
// case).
static inline void RemoveDisallowedElementsFromSubtree(SVGElement& subtree) {
  DCHECK(!subtree.isConnected());
  Element* element = ElementTraversal::FirstWithin(subtree);
  while (element) {
    if (IsDisallowedElement(*element)) {
      Element* next =
          ElementTraversal::NextSkippingChildren(*element, &subtree);
      // The subtree is not in document so this won't generate events that could
      // mutate the tree.
      element->parentNode()->RemoveChild(element);
      element = next;
    } else {
      element = ElementTraversal::Next(*element, &subtree);
    }
  }
}

static void MoveChildrenToReplacementElement(ContainerNode& source_root,
                                             ContainerNode& destination_root) {
  for (Node* child = source_root.firstChild(); child;) {
    Node* next_child = child->nextSibling();
    destination_root.AppendChild(child);
    child = next_child;
  }
}

Element* SVGUseElement::CreateInstanceTree(SVGElement& target_root) const {
  Element* instance_root = target_root.CloneElementWithChildren();
  DCHECK(instance_root->IsSVGElement());
  if (isSVGSymbolElement(target_root)) {
    // Spec: The referenced 'symbol' and its contents are deep-cloned into
    // the generated tree, with the exception that the 'symbol' is replaced
    // by an 'svg'. This generated 'svg' will always have explicit values
    // for attributes width and height. If attributes width and/or height
    // are provided on the 'use' element, then these attributes will be
    // transferred to the generated 'svg'. If attributes width and/or
    // height are not specified, the generated 'svg' element will use
    // values of 100% for these attributes.
    SVGSVGElement* svg_element =
        SVGSVGElement::Create(target_root.GetDocument());
    // Transfer all data (attributes, etc.) from the <symbol> to the new
    // <svg> element.
    svg_element->CloneDataFromElement(*instance_root);
    // Move already cloned elements to the new <svg> element.
    MoveChildrenToReplacementElement(*instance_root, *svg_element);
    instance_root = svg_element;
  }
  TransferUseWidthAndHeightIfNeeded(*this, ToSVGElement(*instance_root),
                                    target_root);
  AssociateCorrespondingElements(target_root, ToSVGElement(*instance_root));
  RemoveDisallowedElementsFromSubtree(ToSVGElement(*instance_root));
  return instance_root;
}

void SVGUseElement::BuildShadowAndInstanceTree(SVGElement& target) {
  DCHECK(!target_element_instance_);
  DCHECK(!needs_shadow_tree_recreation_);

  // <use> creates a closed shadow root. Do not build the shadow/instance
  // tree for <use> elements living in a closed tree because they
  // will get expanded in a second pass -- see expandUseElementsInShadowTree().
  if (InUseShadowTree())
    return;

  // Do not allow self-referencing.
  if (&target == this || IsDisallowedElement(target))
    return;

  // Set up root SVG element in shadow tree.
  // Clone the target subtree into the shadow tree, not handling <use> and
  // <symbol> yet.
  Element* instance_root = CreateInstanceTree(target);
  target_element_instance_ = ToSVGElement(instance_root);
  ShadowRoot& shadow_root = UseShadowRoot();
  shadow_root.AppendChild(instance_root);

  AddReferencesToFirstDegreeNestedUseElements(target);

  if (InstanceTreeIsLoading()) {
    CloneNonMarkupEventListeners();
    return;
  }

  // Assure shadow tree building was successful.
  DCHECK(target_element_instance_);
  DCHECK_EQ(target_element_instance_->CorrespondingUseElement(), this);
  DCHECK_EQ(target_element_instance_->CorrespondingElement(), &target);

  // Expand all <use> elements in the shadow tree.
  // Expand means: replace the actual <use> element by what it references.
  if (!ExpandUseElementsInShadowTree()) {
    shadow_root.RemoveChildren(kOmitSubtreeModifiedEvent);
    ClearResourceReference();
    return;
  }

  // If the instance root was a <use>, it could have been replaced now, so
  // reset |m_targetElementInstance|.
  target_element_instance_ = ToSVGElementOrDie(shadow_root.firstChild());
  DCHECK_EQ(target_element_instance_->parentNode(), shadow_root);

  CloneNonMarkupEventListeners();

  // Update relative length information.
  UpdateRelativeLengthsInformation();
}

LayoutObject* SVGUseElement::CreateLayoutObject(const ComputedStyle&) {
  return new LayoutSVGTransformableContainer(this);
}

static bool IsDirectReference(const SVGElement& element) {
  return isSVGPathElement(element) || isSVGRectElement(element) ||
         isSVGCircleElement(element) || isSVGEllipseElement(element) ||
         isSVGPolygonElement(element) || isSVGPolylineElement(element) ||
         isSVGTextElement(element);
}

void SVGUseElement::ToClipPath(Path& path) const {
  DCHECK(path.IsEmpty());

  const SVGGraphicsElement* element = VisibleTargetGraphicsElementForClipping();

  if (!element)
    return;

  if (element->IsSVGGeometryElement()) {
    ToSVGGeometryElement(*element).ToClipPath(path);
    // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
    SVGLengthContext length_context(this);
    path.Translate(FloatSize(x_->CurrentValue()->Value(length_context),
                             y_->CurrentValue()->Value(length_context)));
    path.Transform(CalculateTransform(SVGElement::kIncludeMotionTransform));
  }
}

SVGGraphicsElement* SVGUseElement::VisibleTargetGraphicsElementForClipping()
    const {
  Node* n = UseShadowRoot().firstChild();
  if (!n || !n->IsSVGElement())
    return nullptr;

  SVGElement& element = ToSVGElement(*n);

  if (!element.IsSVGGraphicsElement())
    return nullptr;

  // Spec: "If a <use> element is a child of a clipPath element, it must
  // directly reference <path>, <text> or basic shapes elements. Indirect
  // references are an error and the clipPath element must be ignored."
  // http://dev.w3.org/fxtf/css-masking-1/#the-clip-path
  if (!IsDirectReference(element)) {
    // Spec: Indirect references are an error (14.3.5)
    return nullptr;
  }

  return &ToSVGGraphicsElement(element);
}

void SVGUseElement::AddReferencesToFirstDegreeNestedUseElements(
    SVGElement& target) {
  // Don't track references to external documents.
  if (IsStructurallyExternal())
    return;
  // We only need to track first degree <use> dependencies. Indirect
  // references are handled as the invalidation bubbles up the dependency
  // chain.
  SVGUseElement* use_element =
      isSVGUseElement(target) ? toSVGUseElement(&target)
                              : Traversal<SVGUseElement>::FirstWithin(target);
  for (; use_element;
       use_element = Traversal<SVGUseElement>::NextSkippingChildren(
           *use_element, &target))
    AddReferenceTo(use_element);
}

void SVGUseElement::CloneNonMarkupEventListeners() {
  for (SVGElement& element :
       Traversal<SVGElement>::DescendantsOf(UseShadowRoot())) {
    if (EventTargetData* data =
            element.CorrespondingElement()->GetEventTargetData()) {
      data->event_listener_map.CopyEventListenersNotCreatedFromMarkupToTarget(
          &element);
    }
  }
}

bool SVGUseElement::HasCycleUseReferencing(SVGUseElement& use,
                                           const ContainerNode& target_instance,
                                           SVGElement*& new_target) const {
  Element* target_element = use.ResolveTargetElement(kDontAddObserver);
  new_target = 0;
  if (target_element && target_element->IsSVGElement())
    new_target = ToSVGElement(target_element);

  if (!new_target)
    return false;

  // Shortcut for self-references
  if (new_target == this)
    return true;

  AtomicString target_id = new_target->GetIdAttribute();
  ContainerNode* instance = target_instance.parentNode();
  while (instance && instance->IsSVGElement()) {
    SVGElement* element = ToSVGElement(instance);
    if (element->HasID() && element->GetIdAttribute() == target_id &&
        element->GetDocument() == new_target->GetDocument())
      return true;

    instance = instance->parentNode();
  }
  return false;
}

// Spec: In the generated content, the 'use' will be replaced by 'g', where all
// attributes from the 'use' element except for x, y, width, height and
// xlink:href are transferred to the generated 'g' element.
static void RemoveAttributesFromReplacementElement(
    SVGElement& replacement_element) {
  replacement_element.removeAttribute(SVGNames::xAttr);
  replacement_element.removeAttribute(SVGNames::yAttr);
  replacement_element.removeAttribute(SVGNames::widthAttr);
  replacement_element.removeAttribute(SVGNames::heightAttr);
  replacement_element.removeAttribute(SVGNames::hrefAttr);
  replacement_element.removeAttribute(XLinkNames::hrefAttr);
}

bool SVGUseElement::ExpandUseElementsInShadowTree() {
  // Why expand the <use> elements in the shadow tree here, and not just
  // do this directly in buildShadowTree, if we encounter a <use> element?
  //
  // Short answer: Because we may miss to expand some elements. For example, if
  // a <symbol> contains <use> tags, we'd miss them. So once we're done with
  // setting up the actual shadow tree (after the special case modification for
  // svg/symbol) we have to walk it completely and expand all <use> elements.
  ShadowRoot& shadow_root = UseShadowRoot();
  for (SVGUseElement* use = Traversal<SVGUseElement>::FirstWithin(shadow_root);
       use;) {
    DCHECK(!use->ResourceIsStillLoading());

    SVGUseElement& original_use = toSVGUseElement(*use->CorrespondingElement());
    SVGElement* target = nullptr;
    if (HasCycleUseReferencing(original_use, *use, target))
      return false;

    if (target && IsDisallowedElement(*target))
      return false;
    // Don't DCHECK(target) here, it may be "pending", too.
    // Setup sub-shadow tree root node
    SVGGElement* clone_parent = SVGGElement::Create(original_use.GetDocument());
    // Transfer all data (attributes, etc.) from <use> to the new <g> element.
    clone_parent->CloneDataFromElement(*use);
    clone_parent->SetCorrespondingElement(&original_use);

    RemoveAttributesFromReplacementElement(*clone_parent);

    // Move already cloned elements to the new <g> element.
    MoveChildrenToReplacementElement(*use, *clone_parent);

    if (target)
      clone_parent->AppendChild(use->CreateInstanceTree(*target));

    SVGElement* replacing_element(clone_parent);

    // Replace <use> with referenced content.
    use->parentNode()->ReplaceChild(clone_parent, use);

    use = Traversal<SVGUseElement>::Next(*replacing_element, &shadow_root);
  }
  return true;
}

void SVGUseElement::InvalidateShadowTree() {
  if (!InActiveDocument() || needs_shadow_tree_recreation_)
    return;
  ClearInstanceRoot();
  ScheduleShadowTreeRecreation();
  InvalidateDependentShadowTrees();
}

void SVGUseElement::InvalidateDependentShadowTrees() {
  // Recursively invalidate dependent <use> shadow trees
  const HeapHashSet<WeakMember<SVGElement>>& raw_instances =
      InstancesForElement();
  HeapVector<Member<SVGElement>> instances;
  instances.AppendRange(raw_instances.begin(), raw_instances.end());
  for (auto& instance : instances) {
    if (SVGUseElement* element = instance->CorrespondingUseElement()) {
      DCHECK(element->isConnected());
      element->InvalidateShadowTree();
    }
  }
}

bool SVGUseElement::SelfHasRelativeLengths() const {
  if (x_->CurrentValue()->IsRelative() || y_->CurrentValue()->IsRelative() ||
      width_->CurrentValue()->IsRelative() ||
      height_->CurrentValue()->IsRelative())
    return true;

  if (!target_element_instance_)
    return false;

  return target_element_instance_->HasRelativeLengths();
}

FloatRect SVGUseElement::GetBBox() {
  DCHECK(GetLayoutObject());
  LayoutSVGTransformableContainer& transformable_container =
      ToLayoutSVGTransformableContainer(*GetLayoutObject());
  // Don't apply the additional translation if the oBB is invalid.
  if (!transformable_container.IsObjectBoundingBoxValid())
    return FloatRect();

  // TODO(fs): Preferably this would just use objectBoundingBox() (and hence
  // don't need to override SVGGraphicsElement::getBBox at all) and be
  // correct without additional work. That will not work out ATM without
  // additional quirks. The problem stems from including the additional
  // translation directly on the LayoutObject corresponding to the
  // SVGUseElement.
  FloatRect bbox = transformable_container.ObjectBoundingBox();
  bbox.Move(transformable_container.AdditionalTranslation());
  return bbox;
}

void SVGUseElement::DispatchPendingEvent() {
  DCHECK(IsStructurallyExternal());
  DCHECK(have_fired_load_event_);
  DispatchEvent(Event::Create(EventTypeNames::load));
}

void SVGUseElement::NotifyFinished(Resource* resource) {
  DCHECK_EQ(resource_, resource);
  if (!isConnected())
    return;

  InvalidateShadowTree();
  if (!ResourceIsValid()) {
    DispatchEvent(Event::Create(EventTypeNames::error));
  } else if (!resource->WasCanceled()) {
    if (have_fired_load_event_)
      return;
    if (!IsStructurallyExternal())
      return;
    DCHECK(!have_fired_load_event_);
    have_fired_load_event_ = true;
    TaskRunnerHelper::Get(TaskType::kDOMManipulation, &GetDocument())
        ->PostTask(BLINK_FROM_HERE,
                   WTF::Bind(&SVGUseElement::DispatchPendingEvent,
                             WrapPersistent(this)));
  }
}

bool SVGUseElement::ResourceIsStillLoading() const {
  return resource_ && resource_->IsLoading();
}

bool SVGUseElement::ResourceIsValid() const {
  return resource_ && resource_->IsLoaded() && !resource_->ErrorOccurred() &&
         resource_->GetDocument();
}

bool SVGUseElement::InstanceTreeIsLoading() const {
  for (const SVGUseElement& use_element :
       Traversal<SVGUseElement>::DescendantsOf(UseShadowRoot())) {
    if (use_element.ResourceIsStillLoading())
      return true;
  }
  return false;
}

void SVGUseElement::SetDocumentResource(DocumentResource* resource) {
  if (resource_ == resource)
    return;

  if (resource_)
    resource_->RemoveClient(this);

  resource_ = resource;
  if (resource_)
    resource_->AddClient(this);
}

}  // namespace blink
