/*
 * Copyright (C) 2011 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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/dom/ShadowRoot.h"

#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/string_or_trusted_html.h"
#include "core/css/StyleEngine.h"
#include "core/css/StyleSheetList.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/ElementShadow.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/ShadowRootRareDataV0.h"
#include "core/dom/SlotAssignment.h"
#include "core/dom/Text.h"
#include "core/dom/V0InsertionPoint.h"
#include "core/dom/WhitespaceAttacher.h"
#include "core/dom/trustedtypes/TrustedHTML.h"
#include "core/editing/serializers/Serialization.h"
#include "core/html/HTMLShadowElement.h"
#include "core/html/HTMLSlotElement.h"
#include "core/layout/LayoutObject.h"
#include "public/platform/Platform.h"

namespace blink {

struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope {
  char empty_class_fields_due_to_gc_mixin_marker[1];
  Member<void*> willbe_member[3];
  unsigned counters_and_flags[1];
};

static_assert(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot),
              "ShadowRoot should stay small");

ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
    : DocumentFragment(nullptr, kCreateShadowRoot),
      TreeScope(*this, document),
      style_sheet_list_(nullptr),
      child_shadow_root_count_(0),
      type_(static_cast<unsigned>(type)),
      registered_with_parent_shadow_root_(false),
      descendant_insertion_points_is_valid_(false),
      delegates_focus_(false) {}

ShadowRoot::~ShadowRoot() {}

ShadowRoot* ShadowRoot::YoungerShadowRoot() const {
  if (GetType() == ShadowRootType::V0 && shadow_root_rare_data_v0_)
    return shadow_root_rare_data_v0_->YoungerShadowRoot();
  return nullptr;
}

ShadowRoot* ShadowRoot::OlderShadowRoot() const {
  if (GetType() == ShadowRootType::V0 && shadow_root_rare_data_v0_)
    return shadow_root_rare_data_v0_->OlderShadowRoot();
  return nullptr;
}

void ShadowRoot::SetYoungerShadowRoot(ShadowRoot& root) {
  DCHECK_EQ(GetType(), ShadowRootType::V0);
  EnsureShadowRootRareDataV0().SetYoungerShadowRoot(root);
}

void ShadowRoot::SetOlderShadowRoot(ShadowRoot& root) {
  DCHECK_EQ(GetType(), ShadowRootType::V0);
  EnsureShadowRootRareDataV0().SetOlderShadowRoot(root);
}

SlotAssignment& ShadowRoot::EnsureSlotAssignment() {
  if (!slot_assignment_)
    slot_assignment_ = SlotAssignment::Create(*this);
  return *slot_assignment_;
}

HTMLSlotElement* ShadowRoot::AssignedSlotFor(const Node& node) {
  if (!slot_assignment_)
    return nullptr;
  return slot_assignment_->FindSlot(node);
}

void ShadowRoot::DidAddSlot(HTMLSlotElement& slot) {
  DCHECK(IsV1());
  EnsureSlotAssignment().DidAddSlot(slot);
}

void ShadowRoot::DidChangeHostChildSlotName(const AtomicString& old_value,
                                            const AtomicString& new_value) {
  if (!slot_assignment_)
    return;
  slot_assignment_->DidChangeHostChildSlotName(old_value, new_value);
}

Node* ShadowRoot::cloneNode(bool, ExceptionState& exception_state) {
  exception_state.ThrowDOMException(kNotSupportedError,
                                    "ShadowRoot nodes are not clonable.");
  return nullptr;
}

String ShadowRoot::InnerHTMLAsString() const {
  return CreateMarkup(this, kChildrenOnly);
}

void ShadowRoot::innerHTML(StringOrTrustedHTML& result) const {
  result.SetString(InnerHTMLAsString());
}

void ShadowRoot::SetInnerHTMLFromString(const String& markup,
                                        ExceptionState& exception_state) {
  if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
          markup, &host(), kAllowScriptingContent, "innerHTML",
          exception_state))
    ReplaceChildrenWithFragment(this, fragment, exception_state);
}

void ShadowRoot::setInnerHTML(const StringOrTrustedHTML& stringOrHtml,
                              ExceptionState& exception_state) {
  DCHECK(stringOrHtml.IsString() ||
         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());

  if (stringOrHtml.IsString() && GetDocument().RequireTrustedTypes()) {
    exception_state.ThrowTypeError(
        "This document requires `TrustedHTML` assignment.");
    return;
  }

  String html = stringOrHtml.IsString()
                    ? stringOrHtml.GetAsString()
                    : stringOrHtml.GetAsTrustedHTML()->toString();

  // TODO(mkwst): This is an ugly hack that will be resolved once `TreatNullAs`
  // is treated as an extended attribute on the `DOMString` type rather than
  // as an extended attribute on the attribute. https://crbug.com/714866
  if (html == "null")
    html = "";

  SetInnerHTMLFromString(html, exception_state);
}

void ShadowRoot::RecalcStyle(StyleRecalcChange change) {
  // ShadowRoot doesn't support custom callbacks.
  DCHECK(!HasCustomStyleCallbacks());

  if (GetStyleChangeType() >= kSubtreeStyleChange) {
    change = kForce;
    if (NeedsAttach())
      SetNeedsReattachLayoutTree();
  }

  // There's no style to update so just calling recalcStyle means we're updated.
  ClearNeedsStyleRecalc();

  RecalcDescendantStyles(change);
  ClearChildNeedsStyleRecalc();
}

void ShadowRoot::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
  ClearNeedsReattachLayoutTree();
  RebuildChildrenLayoutTrees(whitespace_attacher);
  ClearChildNeedsReattachLayoutTree();
}

void ShadowRoot::AttachLayoutTree(AttachContext& context) {
  DocumentFragment::AttachLayoutTree(context);
}

void ShadowRoot::DetachLayoutTree(const AttachContext& context) {
  if (context.clear_invalidation) {
    GetDocument().GetStyleEngine().GetStyleInvalidator().ClearInvalidation(
        *this);
  }
  DocumentFragment::DetachLayoutTree(context);
}

Node::InsertionNotificationRequest ShadowRoot::InsertedInto(
    ContainerNode* insertion_point) {
  DocumentFragment::InsertedInto(insertion_point);

  if (!insertion_point->isConnected() || !IsOldest())
    return kInsertionDone;

  // FIXME: When parsing <video controls>, insertedInto() is called many times
  // without invoking removedFrom.  For now, we check
  // m_registeredWithParentShadowroot. We would like to
  // DCHECK(!m_registeredShadowRoot) here.
  // https://bugs.webkit.org/show_bug.cig?id=101316
  if (registered_with_parent_shadow_root_)
    return kInsertionDone;

  if (ShadowRoot* root = host().ContainingShadowRoot()) {
    root->AddChildShadowRoot();
    registered_with_parent_shadow_root_ = true;
  }

  return kInsertionDone;
}

void ShadowRoot::RemovedFrom(ContainerNode* insertion_point) {
  if (insertion_point->isConnected()) {
    GetDocument().GetStyleEngine().ShadowRootRemovedFromDocument(this);
    if (registered_with_parent_shadow_root_) {
      ShadowRoot* root = host().ContainingShadowRoot();
      if (!root)
        root = insertion_point->ContainingShadowRoot();
      if (root)
        root->RemoveChildShadowRoot();
      registered_with_parent_shadow_root_ = false;
    }
    if (NeedsStyleInvalidation()) {
      GetDocument().GetStyleEngine().GetStyleInvalidator().ClearInvalidation(
          *this);
    }
  }

  DocumentFragment::RemovedFrom(insertion_point);
}

void ShadowRoot::ChildrenChanged(const ChildrenChange& change) {
  ContainerNode::ChildrenChanged(change);

  if (change.IsChildElementChange()) {
    CheckForSiblingStyleChanges(
        change.type == kElementRemoved ? kSiblingElementRemoved
                                       : kSiblingElementInserted,
        ToElement(change.sibling_changed), change.sibling_before_change,
        change.sibling_after_change);
  }

  if (V0InsertionPoint* point = ShadowInsertionPointOfYoungerShadowRoot()) {
    if (ShadowRoot* root = point->ContainingShadowRoot())
      root->Owner()->SetNeedsDistributionRecalc();
  }
}

ShadowRootRareDataV0& ShadowRoot::EnsureShadowRootRareDataV0() {
  if (shadow_root_rare_data_v0_)
    return *shadow_root_rare_data_v0_;

  shadow_root_rare_data_v0_ = new ShadowRootRareDataV0;
  return *shadow_root_rare_data_v0_;
}

bool ShadowRoot::ContainsShadowElements() const {
  return shadow_root_rare_data_v0_
             ? shadow_root_rare_data_v0_->ContainsShadowElements()
             : false;
}

bool ShadowRoot::ContainsContentElements() const {
  return shadow_root_rare_data_v0_
             ? shadow_root_rare_data_v0_->ContainsContentElements()
             : false;
}

unsigned ShadowRoot::DescendantShadowElementCount() const {
  return shadow_root_rare_data_v0_
             ? shadow_root_rare_data_v0_->DescendantShadowElementCount()
             : 0;
}

HTMLShadowElement* ShadowRoot::ShadowInsertionPointOfYoungerShadowRoot() const {
  return shadow_root_rare_data_v0_
             ? shadow_root_rare_data_v0_
                   ->ShadowInsertionPointOfYoungerShadowRoot()
             : nullptr;
}

void ShadowRoot::SetShadowInsertionPointOfYoungerShadowRoot(
    HTMLShadowElement* shadow_insertion_point) {
  if (!shadow_root_rare_data_v0_ && !shadow_insertion_point)
    return;
  EnsureShadowRootRareDataV0().SetShadowInsertionPointOfYoungerShadowRoot(
      shadow_insertion_point);
}

void ShadowRoot::DidAddInsertionPoint(V0InsertionPoint* insertion_point) {
  EnsureShadowRootRareDataV0().DidAddInsertionPoint(insertion_point);
  InvalidateDescendantInsertionPoints();
}

void ShadowRoot::DidRemoveInsertionPoint(V0InsertionPoint* insertion_point) {
  shadow_root_rare_data_v0_->DidRemoveInsertionPoint(insertion_point);
  InvalidateDescendantInsertionPoints();
}

void ShadowRoot::InvalidateDescendantInsertionPoints() {
  descendant_insertion_points_is_valid_ = false;
  shadow_root_rare_data_v0_->ClearDescendantInsertionPoints();
}

const HeapVector<Member<V0InsertionPoint>>&
ShadowRoot::DescendantInsertionPoints() {
  DEFINE_STATIC_LOCAL(HeapVector<Member<V0InsertionPoint>>, empty_list,
                      (new HeapVector<Member<V0InsertionPoint>>));
  if (shadow_root_rare_data_v0_ && descendant_insertion_points_is_valid_)
    return shadow_root_rare_data_v0_->DescendantInsertionPoints();

  descendant_insertion_points_is_valid_ = true;

  if (!ContainsInsertionPoints())
    return empty_list;

  HeapVector<Member<V0InsertionPoint>> insertion_points;
  for (V0InsertionPoint& insertion_point :
       Traversal<V0InsertionPoint>::DescendantsOf(*this))
    insertion_points.push_back(&insertion_point);

  EnsureShadowRootRareDataV0().SetDescendantInsertionPoints(insertion_points);

  return shadow_root_rare_data_v0_->DescendantInsertionPoints();
}

StyleSheetList& ShadowRoot::StyleSheets() {
  if (!style_sheet_list_)
    SetStyleSheets(StyleSheetList::Create(this));
  return *style_sheet_list_;
}

void ShadowRoot::DistributeV1() {
  EnsureSlotAssignment().ResolveDistribution();
}

void ShadowRoot::Trace(blink::Visitor* visitor) {
  visitor->Trace(shadow_root_rare_data_v0_);
  visitor->Trace(slot_assignment_);
  visitor->Trace(style_sheet_list_);
  TreeScope::Trace(visitor);
  DocumentFragment::Trace(visitor);
}

void ShadowRoot::TraceWrappers(const ScriptWrappableVisitor* visitor) const {
  visitor->TraceWrappers(style_sheet_list_);
  DocumentFragment::TraceWrappers(visitor);
}

std::ostream& operator<<(std::ostream& ostream, const ShadowRootType& type) {
  switch (type) {
    case ShadowRootType::kUserAgent:
      ostream << "ShadowRootType::UserAgent";
      break;
    case ShadowRootType::V0:
      ostream << "ShadowRootType::V0";
      break;
    case ShadowRootType::kOpen:
      ostream << "ShadowRootType::Open";
      break;
    case ShadowRootType::kClosed:
      ostream << "ShadowRootType::Closed";
      break;
  }
  return ostream;
}

}  // namespace blink
