chromium/third_party/blink/renderer/core/html/html_element.cc

/*
 * Copyright (C) 1999 Lars Knoll ([email protected])
 *           (C) 1999 Antti Koivisto ([email protected])
 * Copyright (C) 2004-2008, 2013, 2014 Apple Inc. All rights reserved.
 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (C) 2011 Motorola Mobility. 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.
 *
 */

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "third_party/blink/renderer/core/html/html_element.h"

#include "base/containers/enum_set.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/forms/form_control_type.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_stringlegacynulltoemptystring_trustedscript.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/css_color.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_ratio_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element_rare_data_vector.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/dom/id_target_observer.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/popover_data.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/slot_assignment.h"
#include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
#include "third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/serializers/markup_accumulator.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/events/toggle_event.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/html/anchor_element_observer.h"
#include "third_party/blink/renderer/core/html/custom/custom_element.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
#include "third_party/blink/renderer/core/html/custom/element_internals.h"
#include "third_party/blink/renderer/core/html/forms/html_button_element.h"
#include "third_party/blink/renderer/core/html/forms/html_data_list_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_element.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_label_element.h"
#include "third_party/blink/renderer/core/html/forms/html_listbox_element.h"
#include "third_party/blink/renderer/core/html/forms/labels_node_list.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/html/html_bdi_element.h"
#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html/html_br_element.h"
#include "third_party/blink/renderer/core/html/html_dialog_element.h"
#include "third_party/blink/renderer/core/html/html_dimension.h"
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/html/html_template_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/keywords.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/mathml/mathml_element.h"
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
#include "third_party/blink/renderer/core/xml_names.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"

namespace blink {

AttributeChangedFunction;
FormControlType;

struct AttributeTriggers {};

namespace {

// https://html.spec.whatwg.org/multipage/interaction.html#editing-host
// An editing host is either an HTML element with its contenteditable attribute
// in the true state, or a child HTML element of a Document whose design mode
// enabled is true.
// https://w3c.github.io/editing/execCommand.html#editable
// Something is editable if it is a node; it is not an editing host; it does not
// have a contenteditable attribute set to the false state; its parent is an
// editing host or editable; and either it is an HTML element, or it is an svg
// or math element, or it is not an Element and its parent is an HTML element.
bool IsEditableOrEditingHost(const Node& node) {}

const WebFeature kNoWebFeature =;

class PopoverCloseWatcherEventListener : public NativeEventListener {};

class NameInHeapSnapshotBuilder : public MarkupAccumulator {};

}  // anonymous namespace

String HTMLElement::nodeName() const {}

const char* HTMLElement::NameInHeapSnapshot() const {}

bool HTMLElement::ShouldSerializeEndTag() const {}

static inline CSSValueID UnicodeBidiAttributeForDirAuto(HTMLElement* element) {}

unsigned HTMLElement::ParseBorderWidthAttribute(
    const AtomicString& value) const {}

void HTMLElement::ApplyBorderAttributeToStyle(
    const AtomicString& value,
    MutableCSSPropertyValueSet* style) {}

bool HTMLElement::IsPresentationAttribute(const QualifiedName& name) const {}

bool HTMLElement::IsValidDirAttribute(const AtomicString& value) {}

void HTMLElement::CollectStyleForPresentationAttribute(
    const QualifiedName& name,
    const AtomicString& value,
    MutableCSSPropertyValueSet* style) {}

// static
AttributeTriggers* HTMLElement::TriggersForAttributeName(
    const QualifiedName& attr_name) {}

// static
const AtomicString& HTMLElement::EventNameForAttributeName(
    const QualifiedName& attr_name) {}

void HTMLElement::AttributeChanged(const AttributeModificationParams& params) {}

void HTMLElement::ParseAttribute(const AttributeModificationParams& params) {}

DocumentFragment* HTMLElement::TextToFragment(const String& text,
                                              ExceptionState& exception_state) {}

V8UnionStringLegacyNullToEmptyStringOrTrustedScript*
HTMLElement::innerTextForBinding() {}

void HTMLElement::setInnerTextForBinding(
    const V8UnionStringLegacyNullToEmptyStringOrTrustedScript*
        string_or_trusted_script,
    ExceptionState& exception_state) {}

void HTMLElement::setInnerText(const String& text) {}

void HTMLElement::setOuterText(const String& text,
                               ExceptionState& exception_state) {}

void HTMLElement::ApplyAspectRatioToStyle(const AtomicString& width,
                                          const AtomicString& height,
                                          MutableCSSPropertyValueSet* style) {}

void HTMLElement::ApplyIntegerAspectRatioToStyle(
    const AtomicString& width,
    const AtomicString& height,
    MutableCSSPropertyValueSet* style) {}

void HTMLElement::ApplyAspectRatioToStyle(double width,
                                          double height,
                                          MutableCSSPropertyValueSet* style) {}

void HTMLElement::ApplyAlignmentAttributeToStyle(
    const AtomicString& alignment,
    MutableCSSPropertyValueSet* style) {}

bool HTMLElement::HasCustomFocusLogic() const {}

ContentEditableType HTMLElement::contentEditableNormalized() const {}

String HTMLElement::contentEditable() const {}

void HTMLElement::setContentEditable(const String& enabled,
                                     ExceptionState& exception_state) {}

V8UnionBooleanOrStringOrUnrestrictedDouble* HTMLElement::hidden() const {}

void HTMLElement::setHidden(
    const V8UnionBooleanOrStringOrUnrestrictedDouble* value) {}

namespace {

PopoverValueType GetPopoverTypeFromAttributeValue(const AtomicString& value) {}
}  // namespace

void HTMLElement::UpdatePopoverAttribute(const AtomicString& value) {}

bool HTMLElement::HasPopoverAttribute() const {}

AtomicString HTMLElement::popover() const {}
void HTMLElement::setPopover(const AtomicString& value) {}

PopoverValueType HTMLElement::PopoverType() const {}

// This should be true when `:popover-open` should match.
bool HTMLElement::popoverOpen() const {}

bool HTMLElement::IsPopoverReady(PopoverTriggerAction action,
                                 ExceptionState* exception_state,
                                 bool include_event_handler_text,
                                 Document* expected_document) const {}

namespace {
// We have to mark *all* invokers for the given popover dirty in the
// ax tree, since they all should now have an updated expanded state.
void MarkPopoverInvokersDirty(const HTMLElement& popover) {}
}  // namespace

bool HTMLElement::togglePopover(ExceptionState& exception_state) {}

bool HTMLElement::togglePopover(bool force, ExceptionState& exception_state) {}

void HTMLElement::showPopover(ExceptionState& exception_state) {}

void HTMLElement::ShowPopoverInternal(Element* invoker,
                                      ExceptionState* exception_state) {}

// static
void HTMLElement::CloseEntirePopoverStack(
    HTMLDocument::PopoverStack& stack,
    HidePopoverFocusBehavior focus_behavior,
    HidePopoverTransitionBehavior transition_behavior) {}

// static
// All popovers up to, but not including, |endpoint|, will be hidden. If
// endpoint is nullptr, all popover stacks will be closed. If endpoint is in
// the hint stack, it'll be closed up to endpoint, and the auto stack will be
// left as-is. Otherwise the entire hint stack will be closed, and the same
// check will be made against the auto stack.
void HTMLElement::HideAllPopoversUntil(
    const HTMLElement* endpoint,
    Document& document,
    HidePopoverFocusBehavior focus_behavior,
    HidePopoverTransitionBehavior transition_behavior) {}

void HTMLElement::hidePopover(ExceptionState& exception_state) {}

void HTMLElement::HidePopoverInternal(
    HidePopoverFocusBehavior focus_behavior,
    HidePopoverTransitionBehavior transition_behavior,
    ExceptionState* exception_state) {}

void HTMLElement::SetPopoverFocusOnShow() {}

namespace {

// Remember to keep kMinValue and kMaxValue in sync.
enum class PopoverAncestorOptions {};
PopoverAncestorOptionsSet;

template <typename UnaryPredicate>
const HTMLElement* NearestMatchingAncestor(
    const Node* original_node,
    const PopoverAncestorOptionsSet ancestor_options,
    const UnaryPredicate get_candidate_popover) {}

const HTMLElement* NearestOpenPopover(
    const Node* node,
    const PopoverAncestorOptionsSet ancestor_options =
        PopoverAncestorOptionsSet()) {}

const HTMLElement* NearestTargetPopoverForInvoker(
    const Node* node,
    const PopoverAncestorOptionsSet ancestor_options =
        PopoverAncestorOptionsSet()) {}

}  // namespace

// static
// This function will return the topmost (highest in the popover stack)
// ancestral popover for the provided popover. Popovers can be related to each
// other in several ways, creating a tree of popovers. There are three paths
// through which one popover (call it the "child" popover) can have an ancestor
// popover (call it the "parent" popover):
//  1. the popovers are nested within each other in the DOM tree. In this case,
//     the descendant popover is the "child" and its ancestor popover is the
//     "parent".
//  2. a popover has an `anchor` attribute pointing to another element in the
//     DOM. In this case, the popover is the "child", and the DOM-contained
//     popover of its anchor element is the "parent". If the anchor doesn't
//     point to an element, or that element isn't contained within a popover, no
//     such relationship exists.
//  3. an invoking element (e.g. a <button>) has a `popovertarget` attribute
//     pointing to a popover. In this case, the popover is the "child", and the
//     DOM-contained popover of the invoking element is the "parent". As with
//     anchor, the invoker must be in a popover and reference an open popover.
// In each of the relationships formed above, the parent popover must be
// strictly lower in the popover stack than the child popover, or it does not
// form a valid ancestral relationship. This eliminates non-showing popovers and
// self-pointers (e.g. a popover with an anchor attribute that points back to
// the same popover), and it allows for the construction of a well-formed tree
// from the (possibly cyclic) graph of connections. For example, if two popovers
// have anchors pointing to each other, the only valid relationship is that the
// first one to open is the "parent" and the second is the "child".
// Additionally, a `popover=hint` cannot be the ancestor of a `popover=auto`.
const HTMLElement* HTMLElement::FindTopmostPopoverAncestor(
    Element& new_popover_or_top_layer_element,
    HTMLDocument::PopoverStack& stack_to_check,
    Element* new_popovers_invoker,
    TopLayerElementType top_layer_element_type) {}

// static
const HTMLElement* HTMLElement::TopLayerElementPopoverAncestor(
    Element& top_layer_element,
    TopLayerElementType top_layer_element_type) {}

namespace {
// For light dismiss, we need to find the closest popover that the user has
// clicked. For hover triggering, we need to find the closest popover that is
// related to a hovered node. In both cases, this is the nearest DOM ancestor
// that is either a popover or the invoking element for a popover. It is
// possible both exist, in which case the topmost one (highest on the popover
// stack) is returned.
const HTMLElement* FindTopmostRelatedPopover(
    const Node& node,
    const PopoverAncestorOptionsSet& ancestor_options =
        PopoverAncestorOptionsSet()) {}
}  // namespace

// static
void HTMLElement::HandlePopoverLightDismiss(const Event& event,
                                            const Node& target_node) {}

void HTMLElement::InvokePopover(Element& invoker) {}

// Must be called on an Element that is a popover. Returns true if |node| is a
// descendant of this popover. This includes the case where |node| is contained
// within another popover, and the container popover is a descendant of this
// popover. This also includes "indirect" relationships that the popover API
// provides, such as through invoking elements or via the anchor attribute.
// Note that in the special case of popover=manual popovers, which do not
// usually have ancestral relationships, this function *will* check for invoker
// and anchor relationships to form descendant edges. This is important for the
// `popover-hide-delay` CSS property, which works for all popover types, and
// needs to keep popovers open when a descendant is hovered.
bool HTMLElement::IsNodePopoverDescendant(const Node& node) const {}

void HTMLElement::MaybeQueuePopoverHideEvent() {}

// static
void HTMLElement::HoveredElementChanged(Element* old_element,
                                        Element* new_element) {}

void HTMLElement::SetInternalImplicitAnchor(HTMLElement* element) {}

HTMLElement* HTMLElement::internalImplicitAnchor() const {}

bool HTMLElement::DispatchFocusEvent(
    Element* old_focused_element,
    mojom::blink::FocusType type,
    InputDeviceCapabilities* source_capabilities) {}

bool HTMLElement::IsValidCommand(HTMLElement& invoker,
                                 CommandEventType command) {}

bool HTMLElement::HandleCommandInternal(HTMLElement& invoker,
                                        CommandEventType command) {}

const AtomicString& HTMLElement::autocapitalize() const {}

void HTMLElement::setAutocapitalize(const AtomicString& value) {}

bool HTMLElement::isContentEditableForBinding() const {}

bool HTMLElement::draggable() const {}

void HTMLElement::setDraggable(bool value) {}

bool HTMLElement::spellcheck() const {}

void HTMLElement::setSpellcheck(bool enable) {}

void HTMLElement::click() {}

void HTMLElement::AccessKeyAction(SimulatedClickCreationScope creation_scope) {}

String HTMLElement::title() const {}

TranslateAttributeMode HTMLElement::GetTranslateAttributeMode() const {}

bool HTMLElement::translate() const {}

void HTMLElement::setTranslate(bool enable) {}

// Returns the conforming 'dir' value associated with the state the attribute is
// in (in its canonical case), if any, or the empty string if the attribute is
// in a state that has no associated keyword value or if the attribute is not in
// a defined state (e.g. the attribute is missing and there is no missing value
// default).
// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#limited-to-only-known-values
static inline const AtomicString& ToValidDirValue(const AtomicString& value) {}

const AtomicString& HTMLElement::dir() {}

void HTMLElement::setDir(const AtomicString& value) {}

HTMLFormElement* HTMLElement::formOwner() const {}

HTMLFormElement* HTMLElement::FindFormAncestor() const {}

bool HTMLElement::ElementAffectsDirectionality(const Node* node) {}

bool HTMLElement::HasDirectionAuto() const {}

const TextControlElement*
HTMLElement::ElementIfAutoDirectionalityFormAssociatedOrNull(
    const Element* element) {}

bool HTMLElement::CalculateAndAdjustAutoDirectionality() {}

void HTMLElement::UpdateDirectionalityAfterInputTypeChange(
    const AtomicString& old_value,
    const AtomicString& new_value) {}

void HTMLElement::AdjustDirectionAutoAfterRecalcAssignedNodes() {}

Node::InsertionNotificationRequest HTMLElement::InsertedInto(
    ContainerNode& insertion_point) {}

void HTMLElement::RemovedFrom(ContainerNode& insertion_point) {}

void HTMLElement::DidMoveToNewDocument(Document& old_document) {}

void HTMLElement::AddHTMLLengthToStyle(MutableCSSPropertyValueSet* style,
                                       CSSPropertyID property_id,
                                       const String& value,
                                       AllowPercentage allow_percentage,
                                       AllowZero allow_zero) {}

static Color ParseColorStringWithCrazyLegacyRules(const String& color_string) {}

// Color parsing that matches HTML's "rules for parsing a legacy color value"
bool HTMLElement::ParseColorWithLegacyRules(const String& attribute_value,
                                            Color& parsed_color) {}

void HTMLElement::AddHTMLColorToStyle(MutableCSSPropertyValueSet* style,
                                      CSSPropertyID property_id,
                                      const String& attribute_value) {}

void HTMLElement::AddHTMLBackgroundImageToStyle(
    MutableCSSPropertyValueSet* style,
    const String& url_value,
    const AtomicString& initiator_name) {}

LabelsNodeList* HTMLElement::labels() {}

bool HTMLElement::IsInteractiveContent() const {}

void HTMLElement::DefaultEventHandler(Event& event) {}

bool HTMLElement::HandleKeyboardActivation(Event& event) {}

bool HTMLElement::MatchesReadOnlyPseudoClass() const {}

// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-read-write
// The :read-write pseudo-class must match ... elements that are editing hosts
// or editable and are neither input elements nor textarea elements
bool HTMLElement::MatchesReadWritePseudoClass() const {}

void HTMLElement::HandleKeypressEvent(KeyboardEvent& event) {}

int HTMLElement::AdjustedOffsetForZoom(LayoutUnit offset) {}

int HTMLElement::OffsetTopOrLeft(bool top) {}

int HTMLElement::offsetLeftForBinding() {}

int HTMLElement::offsetTopForBinding() {}

int HTMLElement::offsetWidthForBinding() {}

DISABLE_CFI_PERF
int HTMLElement::offsetHeightForBinding() {}

Element* HTMLElement::unclosedOffsetParent() {}

void HTMLElement::OnDirAttrChanged(const AttributeModificationParams& params) {}

void HTMLElement::OnPopoverChanged(const AttributeModificationParams& params) {}

void HTMLElement::OnFormAttrChanged(const AttributeModificationParams& params) {}

void HTMLElement::OnLangAttrChanged(const AttributeModificationParams& params) {}

void HTMLElement::OnNonceAttrChanged(
    const AttributeModificationParams& params) {}

ElementInternals* HTMLElement::attachInternals(
    ExceptionState& exception_state) {}

bool HTMLElement::IsFormAssociatedCustomElement() const {}

FocusableState HTMLElement::SupportsFocus(
    UpdateBehavior update_behavior) const {}

bool HTMLElement::IsDisabledFormControl() const {}

bool HTMLElement::MatchesEnabledPseudoClass() const {}

bool HTMLElement::MatchesValidityPseudoClasses() const {}

bool HTMLElement::willValidate() const {}

bool HTMLElement::IsValidElement() {}

bool HTMLElement::IsLabelable() const {}

bool HTMLElement::HasActiveLabel() const {}

void HTMLElement::FinishParsingChildren() {}

AtomicString HTMLElement::writingSuggestions() const {}

void HTMLElement::setWritingSuggestions(const AtomicString& value) {}

}  // namespace blink

#ifndef NDEBUG

// For use in the debugger
void dumpInnerHTML(blink::HTMLElement*);

void dumpInnerHTML(blink::HTMLElement* element) {}

#endif