/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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/html/html_script_element.h"

#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/script/script_loader.h"
#include "third_party/blink/renderer/core/script/script_runner.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"

namespace blink {

HTMLScriptElement::HTMLScriptElement(Document& document,
                                     const CreateElementFlags flags)
    : HTMLElement(html_names::kScriptTag, document),
      children_changed_by_api_(false),
      loader_(InitializeScriptLoader(flags)) {}

const AttrNameToTrustedType& HTMLScriptElement::GetCheckedAttributeTypes()
    const {
  DEFINE_STATIC_LOCAL(AttrNameToTrustedType, attribute_map,
                      ({{"src", SpecificTrustedType::kScriptURL}}));
  return attribute_map;
}

bool HTMLScriptElement::IsURLAttribute(const Attribute& attribute) const {
  return attribute.GetName() == html_names::kSrcAttr ||
         HTMLElement::IsURLAttribute(attribute);
}

bool HTMLScriptElement::HasLegalLinkAttribute(const QualifiedName& name) const {
  return name == html_names::kSrcAttr ||
         HTMLElement::HasLegalLinkAttribute(name);
}

const QualifiedName& HTMLScriptElement::SubResourceAttributeName() const {
  return html_names::kSrcAttr;
}

void HTMLScriptElement::ChildrenChanged(const ChildrenChange& change) {
  HTMLElement::ChildrenChanged(change);
  if (change.IsChildInsertion())
    loader_->ChildrenChanged();

  // We'll record whether the script element children were ever changed by
  // the API (as opposed to the parser).
  children_changed_by_api_ |= !change.ByParser();
}

void HTMLScriptElement::DidMoveToNewDocument(Document& old_document) {
  ScriptRunner::MovePendingScript(old_document, GetDocument(), loader_.Get());
  HTMLElement::DidMoveToNewDocument(old_document);
}

void HTMLScriptElement::ParseAttribute(
    const AttributeModificationParams& params) {
  if (params.name == html_names::kSrcAttr) {
    loader_->HandleSourceAttribute(params.new_value);
    LogUpdateAttributeIfIsolatedWorldAndInDocument("script", params);
  } else if (params.name == html_names::kAsyncAttr) {
    loader_->HandleAsyncAttribute();
  } else if (params.name == html_names::kImportanceAttr &&
             RuntimeEnabledFeatures::PriorityHintsEnabled(
                 GetExecutionContext())) {
    // The only thing we need to do for the the importance attribute/Priority
    // Hints is count usage upon parsing. Processing the value happens when the
    // element loads.
    UseCounter::Count(GetDocument(), WebFeature::kPriorityHints);
  } else {
    HTMLElement::ParseAttribute(params);
  }
}

Node::InsertionNotificationRequest HTMLScriptElement::InsertedInto(
    ContainerNode& insertion_point) {
  if (insertion_point.isConnected() && HasSourceAttribute() &&
      ScriptLoader::GetScriptTypeAtPrepare(
          TypeAttributeValue(), LanguageAttributeValue(),
          ScriptLoader::kDisallowLegacyTypeInTypeAttribute) ==
          ScriptLoader::ScriptTypeAtPrepare::kInvalid) {
    UseCounter::Count(GetDocument(),
                      WebFeature::kScriptElementWithInvalidTypeHasSrc);
  }
  HTMLElement::InsertedInto(insertion_point);
  LogAddElementIfIsolatedWorldAndInDocument("script", html_names::kSrcAttr);

  return kInsertionShouldCallDidNotifySubtreeInsertions;
}

void HTMLScriptElement::DidNotifySubtreeInsertionsToDocument() {
  loader_->DidNotifySubtreeInsertionsToDocument();
}

void HTMLScriptElement::setText(const String& string) {
  setTextContent(string);
}

void HTMLScriptElement::text(StringOrTrustedScript& result) {
  result.SetString(TextFromChildren());
}

void HTMLScriptElement::setInnerText(
    const StringOrTrustedScript& string_or_trusted_script,
    ExceptionState& exception_state) {
  String value = TrustedTypesCheckForScript(
      string_or_trusted_script, GetExecutionContext(), exception_state);
  if (!exception_state.HadException()) {
    // https://w3c.github.io/webappsec-trusted-types/dist/spec/#setting-slot-values
    // On setting, the innerText [...] perform the regular steps, and then set
    // content object's [[ScriptText]] internal slot value [...].
    HTMLElement::setInnerText(value, exception_state);
    script_text_internal_slot_ = ParkableString(value.Impl());
  }
}

void HTMLScriptElement::setTextContent(const String& string) {
  // https://w3c.github.io/webappsec-trusted-types/dist/spec/#setting-slot-values
  // On setting, [..] textContent [..] perform the regular steps, and then set
  // content object's [[ScriptText]] internal slot value [...].
  Node::setTextContent(string);
  script_text_internal_slot_ = ParkableString(string.Impl());
}

void HTMLScriptElement::setTextContent(
    const StringOrTrustedScript& string_or_trusted_script,
    ExceptionState& exception_state) {
  String value = TrustedTypesCheckForScript(
      string_or_trusted_script, GetExecutionContext(), exception_state);
  if (!exception_state.HadException()) {
    // https://w3c.github.io/webappsec-trusted-types/dist/spec/#setting-slot-values
    // On setting, [..] textContent [..] perform the regular steps, and then set
    // content object's [[ScriptText]] internal slot value [...].
    Node::setTextContent(value);
    script_text_internal_slot_ = ParkableString(value.Impl());
  }
}

void HTMLScriptElement::setAsync(bool async) {
  SetBooleanAttribute(html_names::kAsyncAttr, async);
  loader_->HandleAsyncAttribute();
}

void HTMLScriptElement::FinishParsingChildren() {
  Element::FinishParsingChildren();

  // We normally expect the parser to finish parsing before any script gets
  // a chance to manipulate the script. However, if script parsing gets
  // deferrred (or similar; see crbug.com/1033101) then a script might get
  // access to the HTMLScriptElement before. In this case, we cannot blindly
  // accept the current TextFromChildren as a parser result.
  DCHECK(children_changed_by_api_ || !script_text_internal_slot_.length());
  if (!children_changed_by_api_)
    script_text_internal_slot_ = ParkableString(TextFromChildren().Impl());
}

bool HTMLScriptElement::async() const {
  return FastHasAttribute(html_names::kAsyncAttr) || loader_->IsNonBlocking();
}

String HTMLScriptElement::SourceAttributeValue() const {
  return FastGetAttribute(html_names::kSrcAttr).GetString();
}

String HTMLScriptElement::CharsetAttributeValue() const {
  return FastGetAttribute(html_names::kCharsetAttr).GetString();
}

String HTMLScriptElement::TypeAttributeValue() const {
  return FastGetAttribute(html_names::kTypeAttr).GetString();
}

String HTMLScriptElement::LanguageAttributeValue() const {
  return FastGetAttribute(html_names::kLanguageAttr).GetString();
}

bool HTMLScriptElement::NomoduleAttributeValue() const {
  return FastHasAttribute(html_names::kNomoduleAttr);
}

String HTMLScriptElement::ForAttributeValue() const {
  return FastGetAttribute(html_names::kForAttr).GetString();
}

String HTMLScriptElement::EventAttributeValue() const {
  return FastGetAttribute(html_names::kEventAttr).GetString();
}

String HTMLScriptElement::CrossOriginAttributeValue() const {
  return FastGetAttribute(html_names::kCrossoriginAttr);
}

String HTMLScriptElement::IntegrityAttributeValue() const {
  return FastGetAttribute(html_names::kIntegrityAttr);
}

String HTMLScriptElement::ReferrerPolicyAttributeValue() const {
  return FastGetAttribute(html_names::kReferrerpolicyAttr);
}

String HTMLScriptElement::ImportanceAttributeValue() const {
  return FastGetAttribute(html_names::kImportanceAttr);
}

String HTMLScriptElement::ChildTextContent() {
  return TextFromChildren();
}

String HTMLScriptElement::ScriptTextInternalSlot() const {
  return script_text_internal_slot_.ToString();
}

bool HTMLScriptElement::AsyncAttributeValue() const {
  return FastHasAttribute(html_names::kAsyncAttr);
}

bool HTMLScriptElement::DeferAttributeValue() const {
  return FastHasAttribute(html_names::kDeferAttr);
}

bool HTMLScriptElement::HasSourceAttribute() const {
  return FastHasAttribute(html_names::kSrcAttr);
}

bool HTMLScriptElement::IsConnected() const {
  return Node::isConnected();
}

bool HTMLScriptElement::HasChildren() const {
  return Node::hasChildren();
}

const AtomicString& HTMLScriptElement::GetNonceForElement() const {
  return ContentSecurityPolicy::IsNonceableElement(this) ? nonce()
                                                         : g_null_atom;
}

bool HTMLScriptElement::AllowInlineScriptForCSP(
    const AtomicString& nonce,
    const WTF::OrdinalNumber& context_line,
    const String& script_content) {
  return GetExecutionContext()
      ->GetContentSecurityPolicyForCurrentWorld()
      ->AllowInline(ContentSecurityPolicy::InlineType::kScript, this,
                    script_content, nonce, GetDocument().Url(), context_line);
}

Document& HTMLScriptElement::GetDocument() const {
  return Node::GetDocument();
}

ExecutionContext* HTMLScriptElement::GetExecutionContext() const {
  return Node::GetExecutionContext();
}

void HTMLScriptElement::DispatchLoadEvent() {
  DispatchEvent(*Event::Create(event_type_names::kLoad));
}

void HTMLScriptElement::DispatchErrorEvent() {
  DispatchEvent(*Event::Create(event_type_names::kError));
}

void HTMLScriptElement::SetScriptElementForBinding(
    HTMLScriptElementOrSVGScriptElement& element) {
  if (!IsInShadowTree())
    element.SetHTMLScriptElement(this);
}

ScriptElementBase::Type HTMLScriptElement::GetScriptElementType() {
  return ScriptElementBase::Type::kHTMLScriptElement;
}

Element& HTMLScriptElement::CloneWithoutAttributesAndChildren(
    Document& factory) const {
  CreateElementFlags flags =
      CreateElementFlags::ByCloneNode().SetAlreadyStarted(
          loader_->AlreadyStarted());
  return *factory.CreateElement(TagQName(), flags, IsValue());
}

void HTMLScriptElement::Trace(Visitor* visitor) const {
  visitor->Trace(loader_);
  HTMLElement::Trace(visitor);
  ScriptElementBase::Trace(visitor);
}

}  // namespace blink
