/*
 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004, 2006, 2007, 2012 Apple Inc. All rights reserved.
 *
 * 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 "third_party/blink/renderer/core/css/css_style_sheet.h"

#include "third_party/blink/renderer/bindings/core/v8/media_list_or_string.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/css_import_rule.h"
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/css_style_sheet_init.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_impl.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html/html_style_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/svg/svg_style_element.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

namespace blink {

using namespace html_names;

class StyleSheetCSSRuleList final : public CSSRuleList {
 public:
  static StyleSheetCSSRuleList* Create(CSSStyleSheet* sheet) {
    return MakeGarbageCollected<StyleSheetCSSRuleList>(sheet);
  }

  StyleSheetCSSRuleList(CSSStyleSheet* sheet) : style_sheet_(sheet) {}

  void Trace(blink::Visitor* visitor) override {
    visitor->Trace(style_sheet_);
    CSSRuleList::Trace(visitor);
  }

 private:
  unsigned length() const override { return style_sheet_->length(); }
  CSSRule* item(unsigned index) const override {
    return style_sheet_->item(index);
  }

  CSSStyleSheet* GetStyleSheet() const override { return style_sheet_; }

  TraceWrapperMember<CSSStyleSheet> style_sheet_;
};

#if DCHECK_IS_ON()
static bool IsAcceptableCSSStyleSheetParent(const Node& parent_node) {
  // Only these nodes can be parents of StyleSheets, and they need to call
  // clearOwnerNode() when moved out of document. Note that destructor of
  // the nodes don't call clearOwnerNode() with Oilpan.
  return parent_node.IsDocumentNode() || IsHTMLLinkElement(parent_node) ||
         IsHTMLStyleElement(parent_node) || IsSVGStyleElement(parent_node) ||
         parent_node.getNodeType() == Node::kProcessingInstructionNode;
}
#endif

// static
const Document* CSSStyleSheet::SingleOwnerDocument(
    const CSSStyleSheet* style_sheet) {
  if (style_sheet)
    return StyleSheetContents::SingleOwnerDocument(style_sheet->Contents());
  return nullptr;
}

CSSStyleSheet* CSSStyleSheet::Create(Document& document,
                                     ExceptionState& exception_state) {
  return CSSStyleSheet::Create(document, CSSStyleSheetInit::Create(),
                               exception_state);
}

CSSStyleSheet* CSSStyleSheet::Create(Document& document,
                                     const CSSStyleSheetInit* options,
                                     ExceptionState& exception_state) {
  if (!RuntimeEnabledFeatures::ConstructableStylesheetsEnabled()) {
    exception_state.ThrowTypeError("Illegal constructor");
    return nullptr;
  }
  // Folowing steps at spec draft
  // https://wicg.github.io/construct-stylesheets/#dom-cssstylesheet-cssstylesheet
  CSSParserContext* parser_context = CSSParserContext::Create(document);
  StyleSheetContents* contents = StyleSheetContents::Create(parser_context);
  CSSStyleSheet* sheet = MakeGarbageCollected<CSSStyleSheet>(contents, nullptr);
  sheet->SetAssociatedDocument(&document);
  sheet->SetIsConstructed(true);
  sheet->SetTitle(options->title());
  sheet->ClearOwnerNode();
  sheet->ClearOwnerRule();
  contents->RegisterClient(sheet);
  scoped_refptr<MediaQuerySet> media_query_set;
  if (options->media().IsString())
    media_query_set = MediaQuerySet::Create(options->media().GetAsString());
  else
    media_query_set = options->media().GetAsMediaList()->Queries()->Copy();
  MediaList* media_list =
      MediaList::Create(media_query_set, const_cast<CSSStyleSheet*>(sheet));
  sheet->SetMedia(media_list);
  if (options->alternate())
    sheet->SetAlternateFromConstructor(true);
  if (options->disabled())
    sheet->setDisabled(true);
  return sheet;
}

CSSStyleSheet* CSSStyleSheet::Create(StyleSheetContents* sheet,
                                     CSSImportRule* owner_rule) {
  return MakeGarbageCollected<CSSStyleSheet>(sheet, owner_rule);
}

CSSStyleSheet* CSSStyleSheet::Create(StyleSheetContents* sheet,
                                     Node& owner_node) {
  return MakeGarbageCollected<CSSStyleSheet>(sheet, owner_node, false,
                                             TextPosition::MinimumPosition());
}

CSSStyleSheet* CSSStyleSheet::CreateInline(StyleSheetContents* sheet,
                                           Node& owner_node,
                                           const TextPosition& start_position) {
  DCHECK(sheet);
  return MakeGarbageCollected<CSSStyleSheet>(sheet, owner_node, true,
                                             start_position);
}

CSSStyleSheet* CSSStyleSheet::CreateInline(Node& owner_node,
                                           const KURL& base_url,
                                           const TextPosition& start_position,
                                           const WTF::TextEncoding& encoding) {
  CSSParserContext* parser_context = CSSParserContext::Create(
      owner_node.GetDocument(), owner_node.GetDocument().BaseURL(),
      true /* origin_clean */, owner_node.GetDocument().GetReferrerPolicy(),
      encoding);
  StyleSheetContents* sheet =
      StyleSheetContents::Create(base_url.GetString(), parser_context);
  return MakeGarbageCollected<CSSStyleSheet>(sheet, owner_node, true,
                                             start_position);
}

CSSStyleSheet::CSSStyleSheet(StyleSheetContents* contents,
                             CSSImportRule* owner_rule)
    : contents_(contents),
      owner_rule_(owner_rule),
      start_position_(TextPosition::MinimumPosition()) {
  contents_->RegisterClient(this);
}

CSSStyleSheet::CSSStyleSheet(StyleSheetContents* contents,
                             Node& owner_node,
                             bool is_inline_stylesheet,
                             const TextPosition& start_position)
    : contents_(contents),
      is_inline_stylesheet_(is_inline_stylesheet),
      owner_node_(&owner_node),
      start_position_(start_position) {
#if DCHECK_IS_ON()
  DCHECK(IsAcceptableCSSStyleSheetParent(owner_node));
#endif
  contents_->RegisterClient(this);
}

CSSStyleSheet::~CSSStyleSheet() = default;

void CSSStyleSheet::WillMutateRules() {
  // If we are the only client it is safe to mutate.
  if (!contents_->IsUsedFromTextCache() &&
      !contents_->IsReferencedFromResource()) {
    contents_->ClearRuleSet();
    contents_->SetMutable();
    return;
  }
  // Only cacheable stylesheets should have multiple clients.
  DCHECK(contents_->IsCacheableForStyleElement() ||
         contents_->IsCacheableForResource());

  // Copy-on-write.
  contents_->UnregisterClient(this);
  contents_ = contents_->Copy();
  contents_->RegisterClient(this);

  contents_->SetMutable();

  // Any existing CSSOM wrappers need to be connected to the copied child rules.
  ReattachChildRuleCSSOMWrappers();
}

void CSSStyleSheet::DidMutateRules() {
  DCHECK(contents_->IsMutable());
  DCHECK_LE(contents_->ClientSize(), 1u);

  Document* owner = OwnerDocument();

  if ((associated_document_ || owner) && !custom_element_tag_names_.IsEmpty()) {
    Document* document =
        associated_document_ ? associated_document_.Get() : owner;
    document->GetStyleEngine().ScheduleCustomElementInvalidations(
        custom_element_tag_names_);
  }

  if (owner && ownerNode() && ownerNode()->isConnected()) {
    owner->GetStyleEngine().SetNeedsActiveStyleUpdate(
        ownerNode()->GetTreeScope());
    if (StyleResolver* resolver = owner->GetStyleEngine().Resolver())
      resolver->InvalidateMatchedPropertiesCache();
  } else if (!adopted_tree_scopes_.IsEmpty()) {
    for (auto tree_scope : adopted_tree_scopes_) {
      tree_scope->GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate(
          *tree_scope);
      if (StyleResolver* resolver =
              tree_scope->GetDocument().GetStyleEngine().Resolver())
        resolver->InvalidateMatchedPropertiesCache();
    }
  }
}

void CSSStyleSheet::DidMutate() {
  Document* owner = OwnerDocument();
  if (!owner)
    return;
  if (ownerNode() && ownerNode()->isConnected())
    owner->GetStyleEngine().SetNeedsActiveStyleUpdate(
        ownerNode()->GetTreeScope());
}

void CSSStyleSheet::EnableRuleAccessForInspector() {
  enable_rule_access_for_inspector_ = true;
}
void CSSStyleSheet::DisableRuleAccessForInspector() {
  enable_rule_access_for_inspector_ = false;
}

CSSStyleSheet::InspectorMutationScope::InspectorMutationScope(
    CSSStyleSheet* sheet)
    : style_sheet_(sheet) {
  style_sheet_->EnableRuleAccessForInspector();
}

CSSStyleSheet::InspectorMutationScope::~InspectorMutationScope() {
  style_sheet_->DisableRuleAccessForInspector();
}

void CSSStyleSheet::ReattachChildRuleCSSOMWrappers() {
  for (unsigned i = 0; i < child_rule_cssom_wrappers_.size(); ++i) {
    if (!child_rule_cssom_wrappers_[i])
      continue;
    child_rule_cssom_wrappers_[i]->Reattach(contents_->RuleAt(i));
  }
}

void CSSStyleSheet::setDisabled(bool disabled) {
  if (disabled == is_disabled_)
    return;
  is_disabled_ = disabled;

  DidMutate();
}

void CSSStyleSheet::SetMediaQueries(
    scoped_refptr<MediaQuerySet> media_queries) {
  media_queries_ = std::move(media_queries);
  if (media_cssom_wrapper_ && media_queries_)
    media_cssom_wrapper_->Reattach(media_queries_.get());
}

bool CSSStyleSheet::MatchesMediaQueries(const MediaQueryEvaluator& evaluator) {
  viewport_dependent_media_query_results_.clear();
  device_dependent_media_query_results_.clear();

  if (!media_queries_)
    return true;
  return evaluator.Eval(*media_queries_,
                        &viewport_dependent_media_query_results_,
                        &device_dependent_media_query_results_);
}

unsigned CSSStyleSheet::length() const {
  return contents_->RuleCount();
}

CSSRule* CSSStyleSheet::item(unsigned index) {
  unsigned rule_count = length();
  if (index >= rule_count)
    return nullptr;

  if (child_rule_cssom_wrappers_.IsEmpty())
    child_rule_cssom_wrappers_.Grow(rule_count);
  DCHECK_EQ(child_rule_cssom_wrappers_.size(), rule_count);

  TraceWrapperMember<CSSRule>& css_rule = child_rule_cssom_wrappers_[index];
  if (!css_rule)
    css_rule = contents_->RuleAt(index)->CreateCSSOMWrapper(this);
  return css_rule.Get();
}

void CSSStyleSheet::ClearOwnerNode() {
  DidMutate();
  if (owner_node_)
    contents_->UnregisterClient(this);
  owner_node_ = nullptr;
}

bool CSSStyleSheet::CanAccessRules() const {
  return enable_rule_access_for_inspector_ || contents_->IsOriginClean();
}

CSSRuleList* CSSStyleSheet::rules(ExceptionState& exception_state) {
  return cssRules(exception_state);
}

unsigned CSSStyleSheet::insertRule(const String& rule_string,
                                   unsigned index,
                                   ExceptionState& exception_state) {
  if (!CanAccessRules()) {
    exception_state.ThrowSecurityError(
        "Cannot access StyleSheet to insertRule");
    return 0;
  }

  if (is_constructed_ && resolver_) {
    // We can't access rules on a constructed stylesheet if it's still waiting
    // for some imports to load (|resolver_| is still set).
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotAllowedError,
        "Can't modify rules while the sheet is waiting for some @imports.");
    return 0;
  }
  DCHECK(child_rule_cssom_wrappers_.IsEmpty() ||
         child_rule_cssom_wrappers_.size() == contents_->RuleCount());

  if (index > length()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kIndexSizeError,
        "The index provided (" + String::Number(index) +
            ") is larger than the maximum index (" + String::Number(length()) +
            ").");
    return 0;
  }
  const CSSParserContext* context =
      CSSParserContext::CreateWithStyleSheet(contents_->ParserContext(), this);
  StyleRuleBase* rule =
      CSSParser::ParseRule(context, contents_.Get(), rule_string);

  if (!rule) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kSyntaxError,
        "Failed to parse the rule '" + rule_string + "'.");
    return 0;
  }
  RuleMutationScope mutation_scope(this);
  if (rule->IsImportRule() && is_constructed_) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotAllowedError,
        "Can't insert @import rules to a constructed stylesheet.");
    return 0;
  }
  bool success = contents_->WrapperInsertRule(rule, index);
  if (!success) {
    if (rule->IsNamespaceRule())
      exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                        "Failed to insert the rule");
    else
      exception_state.ThrowDOMException(
          DOMExceptionCode::kHierarchyRequestError,
          "Failed to insert the rule.");
    return 0;
  }
  if (!child_rule_cssom_wrappers_.IsEmpty())
    child_rule_cssom_wrappers_.insert(index, Member<CSSRule>(nullptr));

  return index;
}

void CSSStyleSheet::deleteRule(unsigned index,
                               ExceptionState& exception_state) {
  if (!CanAccessRules()) {
    exception_state.ThrowSecurityError(
        "Cannot access StyleSheet to deleteRule");
    return;
  }

  if (is_constructed_ && resolver_) {
    // We can't access rules on a constructed stylesheet if it's still waiting
    // for some imports to load (|resolver_| is still set).
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotAllowedError,
        "Can't modify rules while the sheet is waiting for some @imports.");
    return;
  }

  DCHECK(child_rule_cssom_wrappers_.IsEmpty() ||
         child_rule_cssom_wrappers_.size() == contents_->RuleCount());

  if (index >= length()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kIndexSizeError,
        "The index provided (" + String::Number(index) +
            ") is larger than the maximum index (" +
            String::Number(length() - 1) + ").");
    return;
  }
  RuleMutationScope mutation_scope(this);

  bool success = contents_->WrapperDeleteRule(index);
  if (!success) {
    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                      "Failed to delete rule");
    return;
  }

  if (!child_rule_cssom_wrappers_.IsEmpty()) {
    if (child_rule_cssom_wrappers_[index])
      child_rule_cssom_wrappers_[index]->SetParentStyleSheet(nullptr);
    child_rule_cssom_wrappers_.EraseAt(index);
  }
}

int CSSStyleSheet::addRule(const String& selector,
                           const String& style,
                           int index,
                           ExceptionState& exception_state) {
  StringBuilder text;
  text.Append(selector);
  text.Append(" { ");
  text.Append(style);
  if (!style.IsEmpty())
    text.Append(' ');
  text.Append('}');
  insertRule(text.ToString(), index, exception_state);

  // As per Microsoft documentation, always return -1.
  return -1;
}

int CSSStyleSheet::addRule(const String& selector,
                           const String& style,
                           ExceptionState& exception_state) {
  return addRule(selector, style, length(), exception_state);
}

ScriptPromise CSSStyleSheet::replace(ScriptState* script_state,
                                     const String& text,
                                     ExceptionState& exception_state) {
  if (!is_constructed_) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotAllowedError,
        "Can't call replace on non-constructed CSSStyleSheets.");
  }
  // Parses the text synchronously, loads import rules asynchronously.
  SetText(text, true /* allow_import_rules */, exception_state);
  if (!IsLoading())
    return ScriptPromise::Cast(script_state, ToV8(this, script_state));
  resolver_ = ScriptPromiseResolver::Create(script_state);
  return resolver_->Promise();
}

void CSSStyleSheet::replaceSync(const String& text,
                                ExceptionState& exception_state) {
  if (!is_constructed_) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotAllowedError,
        "Can't call replaceSync on non-constructed CSSStyleSheets.");
  }
  SetText(text, false /* allow_import_rules */, exception_state);
}

void CSSStyleSheet::ResolveReplacePromiseIfNeeded(bool load_error_occured) {
  if (!resolver_)
    return;
  if (load_error_occured) {
    resolver_->Reject(DOMException::Create(DOMExceptionCode::kNotAllowedError,
                                           "Loading @imports failed."));
  } else {
    resolver_->Resolve(this);
  }
  resolver_ = nullptr;
  DidMutateRules();
}

CSSRuleList* CSSStyleSheet::cssRules(ExceptionState& exception_state) {
  if (!CanAccessRules()) {
    exception_state.ThrowSecurityError("Cannot access rules");
    return nullptr;
  }
  if (!rule_list_cssom_wrapper_)
    rule_list_cssom_wrapper_ = StyleSheetCSSRuleList::Create(this);
  return rule_list_cssom_wrapper_.Get();
}

String CSSStyleSheet::href() const {
  return contents_->OriginalURL();
}

KURL CSSStyleSheet::BaseURL() const {
  return contents_->BaseURL();
}

bool CSSStyleSheet::IsLoading() const {
  return contents_->IsLoading();
}

MediaList* CSSStyleSheet::media() {
  if (!media_queries_)
    media_queries_ = MediaQuerySet::Create();

  if (!media_cssom_wrapper_)
    media_cssom_wrapper_ = MediaList::Create(media_queries_.get(),
                                             const_cast<CSSStyleSheet*>(this));
  return media_cssom_wrapper_.Get();
}

void CSSStyleSheet::SetMedia(MediaList* media_list) {
  media_cssom_wrapper_ = media_list;
}

CSSStyleSheet* CSSStyleSheet::parentStyleSheet() const {
  return owner_rule_ ? owner_rule_->parentStyleSheet() : nullptr;
}

Document* CSSStyleSheet::OwnerDocument() const {
  if (is_constructed_)
    return associated_document_;
  const CSSStyleSheet* root = this;
  while (root->parentStyleSheet())
    root = root->parentStyleSheet();
  return root->ownerNode() ? &root->ownerNode()->GetDocument() : nullptr;
}

void CSSStyleSheet::SetAllowRuleAccessFromOrigin(
    scoped_refptr<const SecurityOrigin> allowed_origin) {
  allow_rule_access_from_origin_ = std::move(allowed_origin);
}

bool CSSStyleSheet::SheetLoaded() {
  DCHECK(owner_node_);
  SetLoadCompleted(owner_node_->SheetLoaded());
  return load_completed_;
}

void CSSStyleSheet::StartLoadingDynamicSheet() {
  SetLoadCompleted(false);
  owner_node_->StartLoadingDynamicSheet();
}

void CSSStyleSheet::SetLoadCompleted(bool completed) {
  if (completed == load_completed_)
    return;

  load_completed_ = completed;

  if (completed)
    contents_->ClientLoadCompleted(this);
  else
    contents_->ClientLoadStarted(this);
}

void CSSStyleSheet::SetText(const String& text,
                            bool allow_import_rules,
                            ExceptionState& exception_state) {
  child_rule_cssom_wrappers_.clear();

  CSSStyleSheet::RuleMutationScope mutation_scope(this);
  contents_->ClearRules();
  if (contents_->ParseString(text, allow_import_rules) ==
      ParseSheetResult::kHasUnallowedImportRule) {
    exception_state.ThrowDOMException(DOMExceptionCode::kNotAllowedError,
                                      "@import rules are not allowed when "
                                      "creating stylesheet synchronously.");
  }
}

void CSSStyleSheet::SetAlternateFromConstructor(
    bool alternate_from_constructor) {
  alternate_from_constructor_ = alternate_from_constructor;
}

bool CSSStyleSheet::IsAlternate() const {
  if (owner_node_) {
    return owner_node_->IsElementNode() &&
           ToElement(owner_node_)->getAttribute(kRelAttr).Contains("alternate");
  }
  return alternate_from_constructor_;
}

bool CSSStyleSheet::CanBeActivated(
    const String& current_preferrable_name) const {
  if (disabled())
    return false;

  if (owner_node_ && owner_node_->IsInShadowTree()) {
    if (IsHTMLStyleElement(owner_node_) || IsSVGStyleElement(owner_node_))
      return true;
    if (IsHTMLLinkElement(owner_node_) &&
        ToHTMLLinkElement(owner_node_)->IsImport())
      return !IsAlternate();
  }

  if (!owner_node_ ||
      owner_node_->getNodeType() == Node::kProcessingInstructionNode ||
      !IsHTMLLinkElement(owner_node_) ||
      !ToHTMLLinkElement(owner_node_)->IsEnabledViaScript()) {
    if (!title_.IsEmpty() && title_ != current_preferrable_name)
      return false;
  }

  if (IsAlternate() && title_.IsEmpty())
    return false;

  return true;
}

void CSSStyleSheet::Trace(blink::Visitor* visitor) {
  visitor->Trace(contents_);
  visitor->Trace(owner_node_);
  visitor->Trace(owner_rule_);
  visitor->Trace(media_cssom_wrapper_);
  visitor->Trace(child_rule_cssom_wrappers_);
  visitor->Trace(rule_list_cssom_wrapper_);
  visitor->Trace(adopted_tree_scopes_);
  visitor->Trace(associated_document_);
  visitor->Trace(resolver_);
  StyleSheet::Trace(visitor);
}

}  // namespace blink
