/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
 *
 * 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/forms/listed_element.h"

#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/id_target_observer.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/html/custom/element_internals.h"
#include "third_party/blink/renderer/core/html/forms/form_controller.h"
#include "third_party/blink/renderer/core/html/forms/html_data_list_element.h"
#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/html_legend_element.h"
#include "third_party/blink/renderer/core/html/forms/validity_state.h"
#include "third_party/blink/renderer/core/html/html_object_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/validation_message_client.h"
#include "third_party/blink/renderer/platform/text/bidi_text_run.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

using namespace html_names;

class FormAttributeTargetObserver : public IdTargetObserver {
 public:
  static FormAttributeTargetObserver* Create(const AtomicString& id,
                                             ListedElement*);

  FormAttributeTargetObserver(const AtomicString& id, ListedElement*);

  void Trace(blink::Visitor*) override;
  void IdTargetChanged() override;

 private:
  Member<ListedElement> element_;
};

ListedElement::ListedElement()
    : has_validation_message_(false),
      form_was_set_by_parser_(false),
      will_validate_initialized_(false),
      will_validate_(true),
      is_valid_(true),
      validity_is_dirty_(false) {}

ListedElement::~ListedElement() {
  // We can't call setForm here because it contains virtual calls.
}

void ListedElement::Trace(blink::Visitor* visitor) {
  visitor->Trace(form_attribute_target_observer_);
  visitor->Trace(form_);
  visitor->Trace(validity_state_);
}

ValidityState* ListedElement::validity() {
  if (!validity_state_)
    validity_state_ = ValidityState::Create(this);

  return validity_state_.Get();
}

void ListedElement::DidMoveToNewDocument(Document& old_document) {
  HTMLElement* element = ToHTMLElement(this);
  if (element->FastHasAttribute(kFormAttr))
    SetFormAttributeTargetObserver(nullptr);
}

void ListedElement::InsertedInto(ContainerNode& insertion_point) {
  ancestor_disabled_state_ = AncestorDisabledState::kUnknown;
  // Force traversal to find ancestor
  may_have_field_set_ancestor_ = true;
  data_list_ancestor_state_ = DataListAncestorState::kUnknown;
  UpdateWillValidateCache();

  if (!form_was_set_by_parser_ || !form_ ||
      NodeTraversal::HighestAncestorOrSelf(insertion_point) !=
          NodeTraversal::HighestAncestorOrSelf(*form_.Get()))
    ResetFormOwner();

  HTMLElement* element = ToHTMLElement(this);
  if (insertion_point.isConnected()) {
    if (element->FastHasAttribute(kFormAttr))
      ResetFormAttributeTargetObserver();
  }

  FieldSetAncestorsSetNeedsValidityCheck(&insertion_point);
  DisabledStateMightBeChanged();

  if (IsFormControlElementWithState() && insertion_point.isConnected() &&
      !element->ContainingShadowRoot()) {
    element->GetDocument()
        .GetFormController()
        .InvalidateStatefulFormControlList();
  }

  // Trigger for elements outside of forms.
  if (!form_ && insertion_point.isConnected())
    element->GetDocument().DidAssociateFormControl(element);
}

void ListedElement::RemovedFrom(ContainerNode& insertion_point) {
  FieldSetAncestorsSetNeedsValidityCheck(&insertion_point);
  HideVisibleValidationMessage();
  has_validation_message_ = false;
  ancestor_disabled_state_ = AncestorDisabledState::kUnknown;
  data_list_ancestor_state_ = DataListAncestorState::kUnknown;
  UpdateWillValidateCache();

  HTMLElement* element = ToHTMLElement(this);
  if (insertion_point.isConnected() && element->FastHasAttribute(kFormAttr)) {
    SetFormAttributeTargetObserver(nullptr);
    ResetFormOwner();
    return;
  }
  // If the form and element are both in the same tree, preserve the connection
  // to the form.  Otherwise, null out our form and remove ourselves from the
  // form's list of elements.
  if (form_ && NodeTraversal::HighestAncestorOrSelf(*element) !=
                   NodeTraversal::HighestAncestorOrSelf(*form_.Get()))
    ResetFormOwner();

  DisabledStateMightBeChanged();

  if (IsFormControlElementWithState() && insertion_point.isConnected() &&
      !element->ContainingShadowRoot() &&
      !insertion_point.ContainingShadowRoot()) {
    element->GetDocument()
        .GetFormController()
        .InvalidateStatefulFormControlList();
  }
}

HTMLFormElement* ListedElement::FindAssociatedForm(
    const HTMLElement* element,
    const AtomicString& form_id,
    HTMLFormElement* form_ancestor) {
  // 3. If the element is reassociateable, has a form content attribute, and
  // is itself in a Document, then run these substeps:
  if (!form_id.IsNull() && element->isConnected()) {
    // 3.1. If the first element in the Document to have an ID that is
    // case-sensitively equal to the element's form content attribute's
    // value is a form element, then associate the form-associated element
    // with that form element.
    // 3.2. Abort the "reset the form owner" steps.
    Element* new_form_candidate =
        element->GetTreeScope().getElementById(form_id);
    return ToHTMLFormElementOrNull(new_form_candidate);
  }
  // 4. Otherwise, if the form-associated element in question has an ancestor
  // form element, then associate the form-associated element with the nearest
  // such ancestor form element.
  return form_ancestor;
}

void ListedElement::FormRemovedFromTree(const Node& form_root) {
  DCHECK(form_);
  if (NodeTraversal::HighestAncestorOrSelf(ToHTMLElement(*this)) == form_root)
    return;
  ResetFormOwner();
}

void ListedElement::AssociateByParser(HTMLFormElement* form) {
  if (form && form->isConnected()) {
    form_was_set_by_parser_ = true;
    SetForm(form);
    form->DidAssociateByParser();
  }
}

void ListedElement::SetForm(HTMLFormElement* new_form) {
  if (form_.Get() == new_form)
    return;
  WillChangeForm();
  if (form_)
    form_->Disassociate(*this);
  if (new_form) {
    form_ = new_form;
    form_->Associate(*this);
  } else {
    form_ = nullptr;
  }
  DidChangeForm();
}

void ListedElement::WillChangeForm() {
  FormOwnerSetNeedsValidityCheck();
}

void ListedElement::DidChangeForm() {
  if (!form_was_set_by_parser_ && form_ && form_->isConnected()) {
    HTMLElement* element = ToHTMLElement(this);
    element->GetDocument().DidAssociateFormControl(element);
  }
  FormOwnerSetNeedsValidityCheck();
}

void ListedElement::FormOwnerSetNeedsValidityCheck() {
  if (HTMLFormElement* form = Form()) {
    form->PseudoStateChanged(CSSSelector::kPseudoValid);
    form->PseudoStateChanged(CSSSelector::kPseudoInvalid);
  }
}

void ListedElement::FieldSetAncestorsSetNeedsValidityCheck(Node* node) {
  if (!node)
    return;
  if (!may_have_field_set_ancestor_)
    return;
  for (auto* field_set =
           Traversal<HTMLFieldSetElement>::FirstAncestorOrSelf(*node);
       field_set;
       field_set = Traversal<HTMLFieldSetElement>::FirstAncestor(*field_set)) {
    field_set->PseudoStateChanged(CSSSelector::kPseudoValid);
    field_set->PseudoStateChanged(CSSSelector::kPseudoInvalid);
  }
}

void ListedElement::ResetFormOwner() {
  form_was_set_by_parser_ = false;
  HTMLElement* element = ToHTMLElement(this);
  const AtomicString& form_id(element->FastGetAttribute(kFormAttr));
  HTMLFormElement* nearest_form = element->FindFormAncestor();
  // 1. If the element's form owner is not null, and either the element is not
  // reassociateable or its form content attribute is not present, and the
  // element's form owner is its nearest form element ancestor after the
  // change to the ancestor chain, then do nothing, and abort these steps.
  if (form_ && form_id.IsNull() && form_.Get() == nearest_form)
    return;

  SetForm(FindAssociatedForm(element, form_id, nearest_form));
}

void ListedElement::FormAttributeChanged() {
  ResetFormOwner();
  ResetFormAttributeTargetObserver();
}

bool ListedElement::RecalcWillValidate() const {
  const HTMLElement& element = ToHTMLElement(*this);
  if (data_list_ancestor_state_ == DataListAncestorState::kUnknown) {
    if (Traversal<HTMLDataListElement>::FirstAncestor(element))
      data_list_ancestor_state_ = DataListAncestorState::kInsideDataList;
    else
      data_list_ancestor_state_ = DataListAncestorState::kNotInsideDataList;
  }
  return data_list_ancestor_state_ ==
             DataListAncestorState::kNotInsideDataList &&
         !element.IsDisabledFormControl() &&
         !element.FastHasAttribute(html_names::kReadonlyAttr);
}

bool ListedElement::WillValidate() const {
  if (!will_validate_initialized_ ||
      data_list_ancestor_state_ == DataListAncestorState::kUnknown) {
    const_cast<ListedElement*>(this)->UpdateWillValidateCache();
  } else {
    // If the following assertion fails, UpdateWillValidateCache() is not
    // called correctly when something which changes RecalcWillValidate() result
    // is updated.
    DCHECK_EQ(will_validate_, RecalcWillValidate());
  }
  return will_validate_;
}

void ListedElement::UpdateWillValidateCache() {
  // We need to recalculate willValidate immediately because willValidate change
  // can causes style change.
  bool new_will_validate = RecalcWillValidate();
  if (will_validate_initialized_ && will_validate_ == new_will_validate)
    return;
  will_validate_initialized_ = true;
  will_validate_ = new_will_validate;
  // Needs to force SetNeedsValidityCheck() to invalidate validity state of
  // FORM/FIELDSET. If this element updates willValidate twice and
  // IsValidElement() is not called between them, the second call of this
  // function still has validity_is_dirty_==true, which means
  // SetNeedsValidityCheck() doesn't invalidate validity state of
  // FORM/FIELDSET.
  validity_is_dirty_ = false;
  SetNeedsValidityCheck();
  // No need to trigger style recalculation here because
  // SetNeedsValidityCheck() does it in the right away. This relies on
  // the assumption that Valid() is always true if willValidate() is false.

  if (!will_validate_)
    HideVisibleValidationMessage();
}

bool ListedElement::CustomError() const {
  const HTMLElement* element = ToHTMLElement(this);
  return element->willValidate() && !custom_validation_message_.IsEmpty();
}

bool ListedElement::HasBadInput() const {
  return false;
}

bool ListedElement::PatternMismatch() const {
  return false;
}

bool ListedElement::RangeOverflow() const {
  return false;
}

bool ListedElement::RangeUnderflow() const {
  return false;
}

bool ListedElement::StepMismatch() const {
  return false;
}

bool ListedElement::TooLong() const {
  return false;
}

bool ListedElement::TooShort() const {
  return false;
}

bool ListedElement::TypeMismatch() const {
  return false;
}

bool ListedElement::Valid() const {
  bool some_error = TypeMismatch() || StepMismatch() || RangeUnderflow() ||
                    RangeOverflow() || TooLong() || TooShort() ||
                    PatternMismatch() || ValueMissing() || HasBadInput() ||
                    CustomError();
  return !some_error;
}

bool ListedElement::ValueMissing() const {
  return false;
}

String ListedElement::CustomValidationMessage() const {
  return custom_validation_message_;
}

void ListedElement::SetCustomValidationMessage(const String& message) {
  custom_validation_message_ = message;
}

String ListedElement::validationMessage() const {
  return CustomError() ? custom_validation_message_ : String();
}

String ListedElement::ValidationSubMessage() const {
  return String();
}

void ListedElement::setCustomValidity(const String& error) {
  SetCustomValidationMessage(error);
  SetNeedsValidityCheck();
}

void ListedElement::FindCustomValidationMessageTextDirection(
    const String& message,
    TextDirection& message_dir,
    String& sub_message,
    TextDirection& sub_message_dir) {
  message_dir = DetermineDirectionality(message);
  if (!sub_message.IsEmpty()) {
    sub_message_dir =
        ToHTMLElement(*this).GetLayoutObject()->Style()->Direction();
  }
}

void ListedElement::UpdateVisibleValidationMessage() {
  HTMLElement& element = ToHTMLElement(*this);
  Page* page = element.GetDocument().GetPage();
  if (!page || !page->IsPageVisible() || element.GetDocument().UnloadStarted())
    return;
  if (page->Paused())
    return;
  String message;
  if (element.GetLayoutObject() && WillValidate())
    message = validationMessage().StripWhiteSpace();

  has_validation_message_ = true;
  ValidationMessageClient* client = &page->GetValidationMessageClient();
  TextDirection message_dir = TextDirection::kLtr;
  TextDirection sub_message_dir = TextDirection::kLtr;
  String sub_message = ValidationSubMessage().StripWhiteSpace();
  if (message.IsEmpty()) {
    client->HideValidationMessage(element);
  } else {
    FindCustomValidationMessageTextDirection(message, message_dir, sub_message,
                                             sub_message_dir);
  }
  client->ShowValidationMessage(element, message, message_dir, sub_message,
                                sub_message_dir);
}

void ListedElement::HideVisibleValidationMessage() {
  if (!has_validation_message_)
    return;

  if (auto* client = GetValidationMessageClient())
    client->HideValidationMessage(ToHTMLElement(*this));
}

bool ListedElement::IsValidationMessageVisible() const {
  if (!has_validation_message_)
    return false;

  if (auto* client = GetValidationMessageClient())
    return client->IsValidationMessageVisible(ToHTMLElement(*this));
  return false;
}

ValidationMessageClient* ListedElement::GetValidationMessageClient() const {
  if (Page* page = ToHTMLElement(*this).GetDocument().GetPage())
    return &page->GetValidationMessageClient();
  return nullptr;
}

bool ListedElement::checkValidity(List* unhandled_invalid_controls) {
  if (IsNotCandidateOrValid())
    return true;
  HTMLElement& element = ToHTMLElement(*this);
  Document* original_document = &element.GetDocument();
  DispatchEventResult dispatch_result = element.DispatchEvent(
      *Event::CreateCancelable(event_type_names::kInvalid));
  if (dispatch_result == DispatchEventResult::kNotCanceled &&
      unhandled_invalid_controls && element.isConnected() &&
      original_document == element.GetDocument())
    unhandled_invalid_controls->push_back(this);
  return false;
}

void ListedElement::ShowValidationMessage() {
  HTMLElement& element = ToHTMLElement(*this);
  element.scrollIntoViewIfNeeded(false);
  element.focus();
  UpdateVisibleValidationMessage();
}

bool ListedElement::reportValidity() {
  List unhandled_invalid_controls;
  bool is_valid = checkValidity(&unhandled_invalid_controls);
  if (is_valid || unhandled_invalid_controls.IsEmpty())
    return is_valid;
  DCHECK_EQ(unhandled_invalid_controls.size(), 1u);
  DCHECK_EQ(unhandled_invalid_controls[0].Get(), this);
  // Update layout now before calling IsFocusable(), which has
  // !LayoutObject()->NeedsLayout() assertion.
  HTMLElement& element = ToHTMLElement(*this);
  element.GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
  if (element.IsFocusable()) {
    ShowValidationMessage();
    return false;
  }
  if (element.GetDocument().GetFrame()) {
    String message(
        "An invalid form control with name='%name' is not focusable.");
    message.Replace("%name", GetName());
    element.GetDocument().AddConsoleMessage(ConsoleMessage::Create(
        kRenderingMessageSource, kErrorMessageLevel, message));
  }
  return false;
}

bool ListedElement::IsValidElement() {
  if (validity_is_dirty_) {
    is_valid_ = !WillValidate() || Valid();
    validity_is_dirty_ = false;
  } else {
    // If the following assertion fails, SetNeedsValidityCheck() is not
    // called correctly when something which changes validity is updated.
    DCHECK_EQ(is_valid_, (!WillValidate() || Valid()));
  }
  return is_valid_;
}

bool ListedElement::IsNotCandidateOrValid() {
  // Apply Element::willValidate(), not ListedElement::WillValidate(), because
  // some elements override willValidate().
  return !ToHTMLElement(this)->willValidate() || IsValidElement();
}

void ListedElement::SetNeedsValidityCheck() {
  HTMLElement& element = ToHTMLElement(*this);
  if (!validity_is_dirty_) {
    validity_is_dirty_ = true;
    FormOwnerSetNeedsValidityCheck();
    FieldSetAncestorsSetNeedsValidityCheck(element.parentNode());
    element.PseudoStateChanged(CSSSelector::kPseudoValid);
    element.PseudoStateChanged(CSSSelector::kPseudoInvalid);
  }

  // Updates only if this control already has a validation message.
  if (IsValidationMessageVisible()) {
    // Calls UpdateVisibleValidationMessage() even if is_valid_ is not
    // changed because a validation message can be changed.
    element.GetDocument()
        .GetTaskRunner(TaskType::kDOMManipulation)
        ->PostTask(FROM_HERE,
                   WTF::Bind(&ListedElement::UpdateVisibleValidationMessage,
                             WrapPersistent(this)));
  }
}

void ListedElement::DisabledAttributeChanged() {
  UpdateWillValidateCache();
  HTMLElement& element = ToHTMLElement(*this);
  element.PseudoStateChanged(CSSSelector::kPseudoDisabled);
  element.PseudoStateChanged(CSSSelector::kPseudoEnabled);
  DisabledStateMightBeChanged();
}

void ListedElement::UpdateAncestorDisabledState() const {
  if (!may_have_field_set_ancestor_) {
    ancestor_disabled_state_ = AncestorDisabledState::kEnabled;
    return;
  }
  may_have_field_set_ancestor_ = false;
  // <fieldset> element of which |disabled| attribute affects the
  // target element.
  HTMLFieldSetElement* disabled_fieldset_ancestor = nullptr;
  ContainerNode* last_legend_ancestor = nullptr;
  for (HTMLElement* ancestor =
           Traversal<HTMLElement>::FirstAncestor(ToHTMLElement(*this));
       ancestor; ancestor = Traversal<HTMLElement>::FirstAncestor(*ancestor)) {
    if (IsHTMLLegendElement(*ancestor)) {
      last_legend_ancestor = ancestor;
      continue;
    }
    if (!IsHTMLFieldSetElement(*ancestor))
      continue;
    may_have_field_set_ancestor_ = true;
    if (ancestor->IsDisabledFormControl()) {
      auto* fieldset = ToHTMLFieldSetElement(ancestor);
      if (last_legend_ancestor && last_legend_ancestor == fieldset->Legend())
        continue;
      disabled_fieldset_ancestor = fieldset;
      break;
    }
  }
  ancestor_disabled_state_ = disabled_fieldset_ancestor
                                 ? AncestorDisabledState::kDisabled
                                 : AncestorDisabledState::kEnabled;
}

void ListedElement::AncestorDisabledStateWasChanged() {
  ancestor_disabled_state_ = AncestorDisabledState::kUnknown;
  DisabledAttributeChanged();
}

bool ListedElement::IsActuallyDisabled() const {
  if (ToHTMLElement(*this).FastHasAttribute(html_names::kDisabledAttr))
    return true;
  if (ancestor_disabled_state_ == AncestorDisabledState::kUnknown)
    UpdateAncestorDisabledState();
  return ancestor_disabled_state_ == AncestorDisabledState::kDisabled;
}

bool ListedElement::ShouldSaveAndRestoreFormControlState() const {
  return false;
}

FormControlState ListedElement::SaveFormControlState() const {
  return FormControlState();
}

void ListedElement::RestoreFormControlState(const FormControlState& state) {}

void ListedElement::NotifyFormStateChanged() {
  Document& doc = ToHTMLElement(*this).GetDocument();
  // This can be called during fragment parsing as a result of option
  // selection before the document is active (or even in a frame).
  if (!doc.IsActive())
    return;
  doc.GetFrame()->Client()->DidUpdateCurrentHistoryItem();
}

void ListedElement::TakeStateAndRestore() {
  if (IsFormControlElementWithState()) {
    ToHTMLElement(*this)
        .GetDocument()
        .GetFormController()
        .RestoreControlStateFor(ToHTMLFormControlElementWithState(*this));
  }
}

void ListedElement::SetFormAttributeTargetObserver(
    FormAttributeTargetObserver* new_observer) {
  if (form_attribute_target_observer_)
    form_attribute_target_observer_->Unregister();
  form_attribute_target_observer_ = new_observer;
}

void ListedElement::ResetFormAttributeTargetObserver() {
  HTMLElement* element = ToHTMLElement(this);
  const AtomicString& form_id(element->FastGetAttribute(kFormAttr));
  if (!form_id.IsNull() && element->isConnected()) {
    SetFormAttributeTargetObserver(
        FormAttributeTargetObserver::Create(form_id, this));
  } else {
    SetFormAttributeTargetObserver(nullptr);
  }
}

void ListedElement::FormAttributeTargetChanged() {
  ResetFormOwner();
}

const AtomicString& ListedElement::GetName() const {
  const AtomicString& name = ToHTMLElement(this)->GetNameAttribute();
  return name.IsNull() ? g_empty_atom : name;
}

bool ListedElement::IsFormControlElementWithState() const {
  return false;
}

bool ListedElement::IsElementInternals() const {
  return false;
}

ListedElement* ListedElement::From(Element& element) {
  auto* html_element = ToHTMLElementOrNull(element);
  if (!html_element)
    return nullptr;
  if (html_element->IsFormControlElement())
    return ToHTMLFormControlElement(&element);
  if (html_element->IsFormAssociatedCustomElement())
    return &element.EnsureElementInternals();
  if (auto* object = ToHTMLObjectElementOrNull(html_element))
    return object;
  return nullptr;
}

const HTMLElement& ToHTMLElement(const ListedElement& listed_element) {
  if (listed_element.IsFormControlElement())
    return ToHTMLFormControlElement(listed_element);
  if (listed_element.IsElementInternals())
    return To<ElementInternals>(listed_element).Target();
  return ToHTMLObjectElementFromListedElement(listed_element);
}

const HTMLElement* ToHTMLElement(const ListedElement* listed_element) {
  DCHECK(listed_element);
  return &ToHTMLElement(*listed_element);
}

HTMLElement* ToHTMLElement(ListedElement* listed_element) {
  return const_cast<HTMLElement*>(
      ToHTMLElement(static_cast<const ListedElement*>(listed_element)));
}

HTMLElement& ToHTMLElement(ListedElement& listed_element) {
  return const_cast<HTMLElement&>(
      ToHTMLElement(static_cast<const ListedElement&>(listed_element)));
}

FormAttributeTargetObserver* FormAttributeTargetObserver::Create(
    const AtomicString& id,
    ListedElement* element) {
  return MakeGarbageCollected<FormAttributeTargetObserver>(id, element);
}

FormAttributeTargetObserver::FormAttributeTargetObserver(const AtomicString& id,
                                                         ListedElement* element)
    : IdTargetObserver(
          ToHTMLElement(element)->GetTreeScope().GetIdTargetObserverRegistry(),
          id),
      element_(element) {}

void FormAttributeTargetObserver::Trace(blink::Visitor* visitor) {
  visitor->Trace(element_);
  IdTargetObserver::Trace(visitor);
}

void FormAttributeTargetObserver::IdTargetChanged() {
  element_->FormAttributeTargetChanged();
}

}  // namespace blink
