// Copyright 2014 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/dom/html_element.h"

#include <algorithm>
#include <map>
#include <memory>
#include <utility>

#include "base/lazy_instance.h"
#include "base/message_loop/message_loop_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cobalt/base/console_log.h"
#include "cobalt/base/tokens.h"
#include "cobalt/cssom/absolute_url_value.h"
#include "cobalt/cssom/cascaded_style.h"
#include "cobalt/cssom/computed_style.h"
#include "cobalt/cssom/css_parser.h"
#include "cobalt/cssom/css_style_sheet.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/property_list_value.h"
#include "cobalt/cssom/selector_tree.h"
#include "cobalt/cssom/viewport_size.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_animatable.h"
#include "cobalt/dom/dom_string_map.h"
#include "cobalt/dom/focus_event.h"
#include "cobalt/dom/html_anchor_element.h"
#include "cobalt/dom/html_audio_element.h"
#include "cobalt/dom/html_body_element.h"
#include "cobalt/dom/html_br_element.h"
#include "cobalt/dom/html_div_element.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/html_element_factory.h"
#include "cobalt/dom/html_head_element.h"
#include "cobalt/dom/html_heading_element.h"
#include "cobalt/dom/html_html_element.h"
#include "cobalt/dom/html_image_element.h"
#include "cobalt/dom/html_link_element.h"
#include "cobalt/dom/html_meta_element.h"
#include "cobalt/dom/html_paragraph_element.h"
#include "cobalt/dom/html_script_element.h"
#include "cobalt/dom/html_span_element.h"
#include "cobalt/dom/html_style_element.h"
#include "cobalt/dom/html_title_element.h"
#include "cobalt/dom/html_unknown_element.h"
#include "cobalt/dom/html_video_element.h"
#include "cobalt/dom/lottie_player.h"
#include "cobalt/dom/rule_matching.h"
#include "cobalt/dom/text.h"
#include "cobalt/loader/image/animated_image_tracker.h"
#include "cobalt/loader/resource_cache.h"
#include "cobalt/math/clamp.h"
#include "cobalt/web/csp_delegate.h"
#include "starboard/common/time.h"
#include "third_party/icu/source/common/unicode/uchar.h"
#include "third_party/icu/source/common/unicode/utf8.h"

using cobalt::cssom::ViewportSize;

namespace cobalt {
namespace dom {

namespace {

// If an element has a "tabindex" attribute less than -1, it will be considered
// a UI navigation focus item. The web spec states that all negative tabindex
// values are treated the same. However, since some apps may want to treat
// certain elements as HTML focusable but not UI navigation focus items, the
// commonly used value of -1 is reserved.
// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
const int32 kUiNavFocusTabIndexThreshold = -2;

// This custom data attribute can be used to force UI navigation to remain
// focused on the element for a specified duration.
const char kUiNavFocusDurationAttribute[] = "data-cobalt-ui-nav-focus-duration";

// https://www.w3.org/TR/resource-timing-1/#dom-performanceresourcetiming-initiatortype
const char* kPerformanceResourceTimingInitiatorType = "img";

void UiNavCallbackHelper(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    base::Callback<void(int64_t)> callback) {
  task_runner->PostTask(
      FROM_HERE, base::Bind(callback, starboard::CurrentMonotonicTime()));
}

struct NonTrivialStaticFields {
  NonTrivialStaticFields() {
    cssom::PropertyKeyVector computed_style_invalidation_properties;
    cssom::PropertyKeyVector layout_box_invalidation_properties;
    cssom::PropertyKeyVector size_invalidation_properties;
    cssom::PropertyKeyVector cross_references_invalidation_properties;

    for (int i = 0; i <= cssom::kMaxLonghandPropertyKey; ++i) {
      cssom::PropertyKey property_key = static_cast<cssom::PropertyKey>(i);

      if (cssom::GetPropertyImpactsChildComputedStyle(property_key) ==
          cssom::kImpactsChildComputedStyleYes) {
        computed_style_invalidation_properties.push_back(property_key);
      }

      // TODO: Revisit inherited property handling. Currently, all boxes are
      // invalidated if an inherited property changes, but now that inherited
      // properties dynamically update, this is likely no longer necessary.
      if (cssom::GetPropertyInheritance(property_key) == cssom::kInheritedYes ||
          cssom::GetPropertyImpactsBoxGeneration(property_key) ==
              cssom::kImpactsBoxGenerationYes) {
        layout_box_invalidation_properties.push_back(property_key);
      } else {
        if (cssom::GetPropertyImpactsBoxSizes(property_key) ==
            cssom::kImpactsBoxSizesYes) {
          size_invalidation_properties.push_back(property_key);
        }
        if (cssom::GetPropertyImpactsBoxCrossReferences(property_key) ==
            cssom::kImpactsBoxCrossReferencesYes) {
          cross_references_invalidation_properties.push_back(property_key);
        }
      }
    }

    computed_style_invalidation_property_checker =
        cssom::CSSComputedStyleData::PropertySetMatcher(
            computed_style_invalidation_properties);
    layout_box_invalidation_property_checker =
        cssom::CSSComputedStyleData::PropertySetMatcher(
            layout_box_invalidation_properties);
    size_invalidation_property_checker =
        cssom::CSSComputedStyleData::PropertySetMatcher(
            size_invalidation_properties);
    cross_references_invalidation_property_checker =
        cssom::CSSComputedStyleData::PropertySetMatcher(
            cross_references_invalidation_properties);
  }

  cssom::CSSComputedStyleData::PropertySetMatcher
      computed_style_invalidation_property_checker;
  cssom::CSSComputedStyleData::PropertySetMatcher
      layout_box_invalidation_property_checker;
  cssom::CSSComputedStyleData::PropertySetMatcher
      size_invalidation_property_checker;
  cssom::CSSComputedStyleData::PropertySetMatcher
      cross_references_invalidation_property_checker;

 private:
  DISALLOW_COPY_AND_ASSIGN(NonTrivialStaticFields);
};

base::LazyInstance<NonTrivialStaticFields>::DestructorAtExit
    non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;

void InvalidateScrollAreaCacheOfAncestors(Node* node) {
  for (Node* ancestor_node = node; ancestor_node;
       ancestor_node = ancestor_node->parent_node()) {
    Element* ancestor_element = ancestor_node->AsElement();
    if (!ancestor_element) {
      continue;
    }
    HTMLElement* ancestor_html_element = ancestor_element->AsHTMLElement();
    if (!ancestor_html_element) {
      continue;
    }
    if (ancestor_html_element->layout_boxes())
      ancestor_html_element->layout_boxes()->scroll_area_cache().reset();
  }
}

}  // namespace

void HTMLElement::RuleMatchingState::Clear() {
  if (is_set) {
    is_set = false;

    parent_matching_nodes.clear();
    parent_descendant_nodes.clear();

    previous_sibling_matching_nodes.clear();
    previous_sibling_following_sibling_nodes.clear();

    matching_nodes_parent_nodes.clear();
    matching_nodes.clear();

    are_descendant_nodes_dirty = true;
    descendant_nodes.clear();

    are_following_sibling_nodes_dirty = true;
    following_sibling_nodes.clear();
  }
}

std::string HTMLElement::dir() const {
  // The dir attribute is limited to only known values. On getting, dir must
  // return the conforming value associated with the state the attribute is in,
  // or the empty string if the attribute is in a state with no associated
  // keyword value.
  // https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-dir-attribute
  if (dir_ == kDirAuto) {
    return "auto";
  } else if (dir_ == kDirLeftToRight) {
    return "ltr";
  } else if (dir_ == kDirRightToLeft) {
    return "rtl";
  } else {
    return "";
  }
}

void HTMLElement::set_dir(const std::string& value) {
  // Funnel through OnSetAttribute.
  SetAttribute("dir", value);
}

scoped_refptr<DOMStringMap> HTMLElement::dataset() {
  scoped_refptr<DOMStringMap> dataset(dataset_);
  if (!dataset) {
    // Create a new instance and store a weak reference.
    dataset = new DOMStringMap(this);
    dataset_ = dataset->AsWeakPtr();
  }
  return dataset;
}

int32 HTMLElement::tab_index() const {
  if (tabindex_) {
    return *tabindex_;
  }
  LOG(WARNING) << "Element's tabindex is not valid.";
  // The default value is 0 for focusable elements.
  // https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex
  return 0;
}

void HTMLElement::set_tab_index(int32 tab_index) {
  SetAttribute("tabindex", base::Int32ToString(tab_index));
}

// Algorithm for Focus:
//   https://www.w3.org/TR/html50/editing.html#dom-focus
void HTMLElement::Focus() {
  // 1. If the element is marked as locked for focus, then abort these steps.
  if (locked_for_focus_) {
    return;
  }

  // 2. Mark the element as locked for focus.
  locked_for_focus_ = true;

  // 3. Run the focusing steps for the element.
  RunFocusingSteps();

  // 4. Unmark the element as locked for focus.
  locked_for_focus_ = false;

  // Custom, not in any spec.
  Document* document = node_document();
  if (document) {
    document->OnFocusChange();
  }
}

// Algorithm for Blur:
//   https://www.w3.org/TR/html50/editing.html#dom-blur
void HTMLElement::Blur() {
  // The blur() method, when invoked, should run the unfocusing steps for the
  // element on which the method was called instead. User agents may selectively
  // or uniformly ignore calls to this method for usability reasons.
  RunUnFocusingSteps();

  // Custom, not in any spec.
  Document* document = node_document();
  if (document) {
    document->OnFocusChange();
  }
}

// Algorithm for GetClientRects:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-element-getclientrects
scoped_refptr<DOMRectList> HTMLElement::GetClientRects() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element on which it was invoked does not have an associated
  // layout box return an empty DOMRectList object and stop this algorithm.
  if (!layout_boxes_) {
    return base::WrapRefCounted(new DOMRectList());
  }

  // The remaining steps are implemented in LayoutBoxes::GetClientRects().
  return layout_boxes_->GetClientRects();
}

// Algorithm for client_top:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-element-clienttop
float HTMLElement::client_top() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element has no associated CSS layout box or if the CSS layout box
  // is inline, return zero.
  if (!layout_boxes_ || layout_boxes_->IsInline()) {
    return 0.0f;
  }
  // 2. Return the computed value of the 'border-top-width' property plus the
  // height of any scrollbar rendered between the top padding edge and the top
  // border edge, ignoring any transforms that apply to the element and its
  // ancestors.
  return layout_boxes_->GetBorderTopWidth();
}

// Algorithm for client_left:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-element-clientleft
float HTMLElement::client_left() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element has no associated CSS layout box or if the CSS layout box
  // is inline, return zero.
  if (!layout_boxes_ || layout_boxes_->IsInline()) {
    return 0.0f;
  }
  // 2. Return the computed value of the 'border-left-width' property plus the
  // width of any scrollbar rendered between the left padding edge and the left
  // border edge, ignoring any transforms that apply to the element and its
  // ancestors.
  return layout_boxes_->GetBorderLeftWidth();
}

// Algorithm for client_width:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-element-clientwidth
float HTMLElement::client_width() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element has no associated CSS layout box or if the CSS layout box
  // is inline, return zero.
  if (!layout_boxes_ || layout_boxes_->IsInline()) {
    return 0.0f;
  }

  // 2. If the element is the root element, return the viewport width.
  if (IsRootElement()) {
    return layout_boxes_->GetMarginEdgeWidth();
  }

  // 3. Return the width of the padding edge, ignoring any transforms that apply
  // to the element and its ancestors.
  return layout_boxes_->GetPaddingEdgeWidth();
}

// Algorithm for client_height:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-element-clientheight
float HTMLElement::client_height() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element has no associated CSS layout box or if the CSS layout box
  // is inline, return zero.
  if (!layout_boxes_ || layout_boxes_->IsInline()) {
    return 0.0f;
  }

  // 2. If the element is the root element, return the viewport height.
  if (IsRootElement()) {
    return layout_boxes_->GetMarginEdgeHeight();
  }

  // Return the height of the padding edge, ignoring any transforms that apply
  // to the element and its ancestors.
  return layout_boxes_->GetPaddingEdgeHeight();
}

// Algorithm for scrollWidth:
//   https://www.w3.org/TR/cssom-view-1/#dom-element-scrollwidth
int32 HTMLElement::scroll_width() {
  // 1. Let document be the element's node document.
  // 2. If document is not the active document, return zero and terminate
  //    these steps.
  if (!node_document() || !node_document()->window()) {
    return 0;
  }

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  int32 element_scroll_width = 0;
  if (layout_boxes_) {
    element_scroll_width = static_cast<int32>(
        layout_boxes_->GetScrollArea(directionality()).width());
  }

  // 3. Let viewport width be the width of the viewport excluding the width of
  //    the scroll bar, if any, or zero if there is no viewport.
  // 4. If the element is the root element and document is not in quirks mode
  //    return max(viewport scrolling area width, viewport width).
  // 5. If the element is the HTML body element, document is in quirks mode
  //    and the element is not potentially scrollable, return max(viewport
  //    scrolling area width, viewport width).
  if (IsRootElement()) {
    return std::max(node_document()->viewport_size().width(),
                    element_scroll_width);
  }

  // 6. If the element does not have any associated CSS layout box return zero
  //    and terminate these steps.
  // 7. Return the width of the element's scrolling area.
  return element_scroll_width;
}

// Algorithm for scrollHeight:
//   https://www.w3.org/TR/cssom-view-1/#dom-element-scrollheight
int32 HTMLElement::scroll_height() {
  // 1. Let document be the element's node document.
  // 2. If document is not the active document, return zero and terminate
  //    these steps.
  if (!node_document() || !node_document()->window()) {
    return 0;
  }

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  int32 element_scroll_height = 0;
  if (layout_boxes_) {
    element_scroll_height = static_cast<int32>(
        layout_boxes_->GetScrollArea(directionality()).height());
  }

  // 3. Let viewport height be the height of the viewport excluding the height
  //    of the scroll bar, if any, or zero if there is no viewport.
  // 4. If the element is the root element and document is not in quirks mode
  //    return max(viewport scrolling area height, viewport height).
  // 5. If the element is the HTML body element, document is in quirks mode
  //    and the element is not potentially scrollable, return max(viewport
  //    scrolling area height, viewport height).
  if (IsRootElement()) {
    return std::max(node_document()->viewport_size().height(),
                    element_scroll_height);
  }

  // 6. If the element does not have any associated CSS layout box return zero
  //    and terminate these steps.
  // 7. Return the height of the element's scrolling area.
  return element_scroll_height;
}

// Algorithm for scrollLeft:
//   https://www.w3.org/TR/cssom-view-1/#dom-element-scrollleft
// For RTL, the rightmost content is visible when scrollLeft == 0, and
// scrollLeft values are <= 0. Chrome does not behave this way currently, but
// it is the spec that has been adopted.
//   https://readable-email.org/list/www-style/topic/cssom-view-value-of-scrollleft-in-rtl-situations-is-completely-busted-across-browsers
float HTMLElement::scroll_left() {
  // This is only partially implemented and will only work for elements with
  // UI navigation containers.

  // 1. Let document be the element's node document.
  // 2. If document is not the active document, return zero and terminate these
  //    steps.
  // 3. Let window be the value of document's defaultView attribute.
  // 4. If window is null, return zero and terminate these steps.
  if (!node_document() || !node_document()->window()) {
    return 0.0f;
  }

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  if (!ui_nav_item_ || !ui_nav_item_->IsContainer()) {
    return 0.0f;
  }

  // 5. If the element is the root element and document is in quirks mode,
  //    return zero and terminate these steps.
  // 6. If the element is the root element return the value of scrollX on
  //    window.
  // 7. If the element is the HTML body element, document is in quirks mode, and
  //    the element is not potentially scrollable, return the value of scrollX
  //    on window.

  // 8. If the element does not have any associated CSS layout box, return zero
  //    and terminate these steps.
  if (!layout_boxes_) {
    return 0.0f;
  }

  // 9. Return the x-coordinate of the scrolling area at the alignment point
  //    with the left of the padding edge of the element.
  float left, top;
  ui_nav_item_->GetContentOffset(&left, &top);
  return left;
}

// Algorithm for scrollTop:
//   https://www.w3.org/TR/cssom-view-1/#dom-element-scrolltop
float HTMLElement::scroll_top() {
  // This is only partially implemented and will only work for elements with
  // UI navigation containers.

  // 1. Let document be the element's node document.
  // 2. If document is not the active document, return zero and terminate these
  //    steps.
  // 3. Let window be the value of document's defaultView attribute.
  // 4. If window is null, return zero and terminate these steps.
  if (!node_document() || !node_document()->window()) {
    return 0.0f;
  }

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  if (!ui_nav_item_ || !ui_nav_item_->IsContainer()) {
    return 0.0f;
  }

  // 5. If the element is the root element and document is in quirks mode,
  //    return zero and terminate these steps.
  // 6. If the element is the root element return the value of scrollY on
  //    window.
  // 7. If the element is the HTML body element, document is in quirks mode, and
  //    the element is not potentially scrollable, return the value of scrollY
  //    on window.

  // 8. If the element does not have any associated CSS layout box, return zero
  //    and terminate these steps.
  if (!layout_boxes_) {
    return 0.0f;
  }

  // 9. Return the y-coordinate of the scrolling area at the alignment point
  //    with the top of the padding edge of the element.
  float left, top;
  ui_nav_item_->GetContentOffset(&left, &top);
  return top;
}

// Algorithm for scrollLeft:
//   https://www.w3.org/TR/cssom-view-1/#dom-element-scrollleft
void HTMLElement::set_scroll_left(float x) {
  // This is only partially implemented and will only work for elements with
  // UI navigation containers.

  // 1. Let x be the given value.
  // 2. Normalize non-finite values for x.

  // 3. Let document be the element's node document.
  // 4. If document is not the active document, terminate these steps.
  // 5. Let window be the value of document's defaultView attribute.
  // 6. If window is null, terminate these steps.
  if (!node_document() || !node_document()->window()) {
    return;
  }

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  if (!ui_nav_item_ || !ui_nav_item_->IsContainer()) {
    CLOG(WARNING, debugger_hooks())
        << "scrollLeft only works on HTML elements with 'overflow' set to "
        << "'scroll' or 'auto'";
    return;
  }

  // 7. If the element is the root element and document is in quirks mode,
  //    terminate these steps.
  // 8. If the element is the root element invoke scroll() on window with x as
  //    first argument and scrollY on window as second argument, and terminate
  //    these steps.
  // 9. If the element is the HTML body element, document is in quirks mode, and
  //    the element is not potentially scrollable, invoke scroll() on window
  //    with x as first argument and scrollY on window as second argument, and
  //    terminate these steps.

  // 10. If the element does not have any associated CSS layout box, the element
  //     has no associated scrolling box, or the element has no overflow,
  //     terminate these steps.
  if (!layout_boxes_ ||
      scroll_width() <= layout_boxes_->GetPaddingEdgeWidth()) {
    // Make sure the UI navigation container is set to the expected 0.
    x = 0.0f;
  }

  // 11. Scroll the element to x,scrollTop, with the scroll behavior being
  //     "auto".
  node_document()->window()->CancelScroll(ui_nav_item_);
  float left, top;
  ui_nav_item_->GetContentOffset(&left, &top);

  float throwaway, min = x, max = x;
  ui_nav_item_->GetBounds(&throwaway, &min, &throwaway, &max);
  x = math::Clamp(x, min, max);
  ui_nav_item_->SetContentOffset(x, top);
}

// Algorithm for scrollTop:
//   https://www.w3.org/TR/cssom-view-1/#dom-element-scrolltop
void HTMLElement::set_scroll_top(float y) {
  // This is only partially implemented and will only work for elements with
  // UI navigation containers.

  // 1. Let y be the given value.
  // 2. Normalize non-finite values for y.

  // 3. Let document be the element's node document.
  // 4. If document is not the active document, terminate these steps.
  // 5. Let window be the value of document's defaultView attribute.
  // 6. If window is null, terminate these steps.
  if (!node_document() || !node_document()->window()) {
    return;
  }

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  if (!ui_nav_item_ || !ui_nav_item_->IsContainer()) {
    CLOG(WARNING, debugger_hooks())
        << "scrollTop only works on HTML elements with 'overflow' set to "
        << "'scroll' or 'auto'";
    return;
  }

  // 7. If the element is the root element and document is in quirks mode,
  //    terminate these steps.
  // 8. If the element is the root element invoke scroll() on window with
  //    scrollX on window as first argument and y as second argument, and
  //    terminate these steps.
  // 9. If the element is the HTML body element, document is in quirks mode, and
  //    the element is not potentially scrollable, invoke scroll() on window
  //    with scrollX as first argument and y as second argument, and terminate
  //    these steps.

  // 10. If the element does not have any associated CSS layout box, the element
  //     has no associated scrolling box, or the element has no overflow,
  //     terminate these steps.
  if (!layout_boxes_ ||
      scroll_height() <= layout_boxes_->GetPaddingEdgeHeight()) {
    // Make sure the UI navigation container is set to the expected 0.
    y = 0.0f;
  }

  // 11. Scroll the element to scrollLeft,y, with the scroll behavior being
  //     "auto".
  node_document()->window()->CancelScroll(ui_nav_item_);
  float left, top;
  ui_nav_item_->GetContentOffset(&left, &top);

  float throwaway, min = y, max = y;
  ui_nav_item_->GetBounds(&min, &throwaway, &max, &throwaway);
  y = math::Clamp(y, min, max);
  ui_nav_item_->SetContentOffset(left, y);
}

// Algorithm for offsetParent:
//   https://drafts.csswg.org/date/2019-10-11/cssom-view/#extensions-to-the-htmlelement-interface
Element* HTMLElement::offset_parent() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If any of the following holds true return null and terminate this
  //    algorithm:
  //    . The element does not have an associated CSS layout box.
  //    . The element is the root element.
  //    . The element is the HTML body element.
  //    . The element's computed value of the 'position' property is 'fixed'.
  if (!layout_boxes_ || IsRootElement() || AsHTMLBodyElement() ||
      !computed_style() ||
      computed_style()->position() == cssom::KeywordValue::GetFixed()) {
    return NULL;
  }

  // 2. Return the nearest ancestor element of the element for which at least
  //    one of the following is true and terminate this algorithm if such an
  //    ancestor is found:
  //    . The element is a containing block of absolutely-positioned descendants
  //      (regardless of whether there are any absolutely-positioned
  //       descendants).
  //    . It is the HTML body element.
  for (Node* ancestor_node = parent_node(); ancestor_node;
       ancestor_node = ancestor_node->parent_node()) {
    Element* ancestor_element = ancestor_node->AsElement();
    if (!ancestor_element) {
      continue;
    }
    HTMLElement* ancestor_html_element = ancestor_element->AsHTMLElement();
    if (!ancestor_html_element) {
      continue;
    }
    DCHECK(ancestor_html_element->computed_style());
    if (ancestor_html_element->AsHTMLBodyElement() ||
        ancestor_html_element->computed_style()
            ->IsContainingBlockForPositionAbsoluteElements()) {
      return ancestor_element;
    }
  }

  // 3. Return null.
  return NULL;
}

// Algorithm for offset_top:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-htmlelement-offsettop
float HTMLElement::offset_top() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element is the HTML body element or does not have any associated
  // CSS layout box return zero and terminate this algorithm.
  if (!layout_boxes_ || AsHTMLBodyElement()) {
    return 0.0f;
  }

  // 2. If the offsetParent of the element is null return the y-coordinate of
  // the top border edge of the first CSS layout box associated with the
  // element, relative to the initial containing block origin, ignoring any
  // transforms that apply to the element and its ancestors, and terminate this
  // algorithm.
  scoped_refptr<Element> offset_parent_element = offset_parent();
  if (!offset_parent_element) {
    return layout_boxes_->GetBorderEdgeTop();
  }

  // 3. Return the result of subtracting the y-coordinate of the top padding
  // edge of the first CSS layout box associated with the offsetParent of the
  // element from the y-coordinate of the top border edge of the first CSS
  // layout box associated with the element, relative to the initial containing
  // block origin, ignoring any transforms that apply to the element and its
  // ancestors.
  scoped_refptr<HTMLElement> offset_parent_html_element =
      offset_parent_element->AsHTMLElement();
  if (!offset_parent_html_element) {
    return layout_boxes_->GetBorderEdgeTop();
  }

  DCHECK(offset_parent_html_element->layout_boxes());
  return layout_boxes_->GetBorderEdgeTop() -
         offset_parent_html_element->layout_boxes()->GetPaddingEdgeOffset().y();
}

// Algorithm for offset_left:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-htmlelement-offsetleft
float HTMLElement::offset_left() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element is the HTML body element or does not have any associated
  // CSS layout box return zero and terminate this algorithm.
  if (!layout_boxes_ || AsHTMLBodyElement()) {
    return 0.0f;
  }

  // 2. If the offsetParent of the element is null return the x-coordinate of
  // the left border edge of the first CSS layout box associated with the
  // element, relative to the initial containing block origin, ignoring any
  // transforms that apply to the element and its ancestors, and terminate this
  // algorithm.
  scoped_refptr<Element> offset_parent_element = offset_parent();
  if (!offset_parent_element) {
    return layout_boxes_->GetBorderEdgeLeft();
  }

  // 3. Return the result of subtracting the x-coordinate of the left padding
  // edge of the first CSS layout box associated with the offsetParent of the
  // element from the x-coordinate of the left border edge of the first CSS
  // layout box associated with the element, relative to the initial containing
  // block origin, ignoring any transforms that apply to the element and its
  // ancestors.
  scoped_refptr<HTMLElement> offset_parent_html_element =
      offset_parent_element->AsHTMLElement();
  if (!offset_parent_html_element) {
    return layout_boxes_->GetBorderEdgeLeft();
  }

  DCHECK(offset_parent_html_element->layout_boxes());
  return layout_boxes_->GetBorderEdgeLeft() -
         offset_parent_html_element->layout_boxes()->GetPaddingEdgeOffset().x();
}

// Algorithm for offset_width:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-htmlelement-offsetwidth
float HTMLElement::offset_width() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element does not have any associated CSS layout box return zero
  // and terminate this algorithm.
  if (!layout_boxes_) {
    if (IsRootElement()) {
      node_document()->OnRootElementUnableToProvideOffsetDimensions();
    }
    return 0.0f;
  }

  // 2. Return the border edge width of the first CSS layout box associated with
  // the element, ignoring any transforms that apply to the element and its
  // ancestors.
  return layout_boxes_->GetBorderEdgeWidth();
}

// Algorithm for offset_height:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-htmlelement-offsetheight
float HTMLElement::offset_height() {
  DCHECK(node_document());
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  node_document()->DoSynchronousLayout();

  // 1. If the element does not have any associated CSS layout box return zero
  // and terminate this algorithm.
  if (!layout_boxes_) {
    if (IsRootElement()) {
      node_document()->OnRootElementUnableToProvideOffsetDimensions();
    }
    return 0.0f;
  }

  // 2. Return the border edge height of the first CSS layout box associated
  // with the element, ignoring any transforms that apply to the element and its
  // ancestors.
  return layout_boxes_->GetBorderEdgeHeight();
}

scoped_refptr<Node> HTMLElement::Duplicate() const {
  Document* document = node_document();
  DCHECK(document->html_element_context()->html_element_factory());
  scoped_refptr<HTMLElement> new_html_element =
      document->html_element_context()
          ->html_element_factory()
          ->CreateHTMLElement(document, local_name());
  new_html_element->CopyAttributes(*this);
  new_html_element->style_->AssignFrom(*this->style_);

  // Copy cached attributes.
  new_html_element->tabindex_ = tabindex_;
  new_html_element->dir_ = dir_;

  return new_html_element;
}

base::Optional<std::string> HTMLElement::GetStyleAttribute() const {
  base::Optional<std::string> value = Element::GetStyleAttribute();
  return value.value_or(style_->css_text(NULL));
}

void HTMLElement::SetStyleAttribute(const std::string& value) {
  Document* document = node_document();
  web::CspDelegate* csp_delegate = document->GetCSPDelegate();
  if (value.empty() ||
      csp_delegate->AllowInline(
          web::CspDelegate::kStyle,
          base::SourceLocation(GetSourceLocationName(), 1, 1), value)) {
    style_->set_css_text(value, NULL);
    Element::SetStyleAttribute(value);
  } else {
    // Report a violation.
    PostToDispatchEventName(FROM_HERE, base::Tokens::error());
  }
}

void HTMLElement::RemoveStyleAttribute() {
  style_->set_css_text("", NULL);
  Element::RemoveStyleAttribute();
}

void HTMLElement::OnCSSMutation() {
  // Invalidate the computed style of this node.
  computed_style_valid_ = false;
  descendant_computed_styles_valid_ = false;

  // Remove the style attribute value from the Element.
  Element::RemoveStyleAttribute();

  node_document()->OnElementInlineStyleMutation();
}

scoped_refptr<HTMLAnchorElement> HTMLElement::AsHTMLAnchorElement() {
  return NULL;
}

scoped_refptr<HTMLAudioElement> HTMLElement::AsHTMLAudioElement() {
  return NULL;
}

scoped_refptr<HTMLBodyElement> HTMLElement::AsHTMLBodyElement() { return NULL; }

scoped_refptr<HTMLBRElement> HTMLElement::AsHTMLBRElement() { return NULL; }

scoped_refptr<HTMLDivElement> HTMLElement::AsHTMLDivElement() { return NULL; }

scoped_refptr<HTMLHeadElement> HTMLElement::AsHTMLHeadElement() { return NULL; }

scoped_refptr<HTMLHeadingElement> HTMLElement::AsHTMLHeadingElement() {
  return NULL;
}

scoped_refptr<HTMLHtmlElement> HTMLElement::AsHTMLHtmlElement() { return NULL; }

scoped_refptr<HTMLImageElement> HTMLElement::AsHTMLImageElement() {
  return NULL;
}

scoped_refptr<HTMLLinkElement> HTMLElement::AsHTMLLinkElement() { return NULL; }

scoped_refptr<HTMLMetaElement> HTMLElement::AsHTMLMetaElement() { return NULL; }

scoped_refptr<HTMLMediaElement> HTMLElement::AsHTMLMediaElement() {
  return NULL;
}

scoped_refptr<HTMLParagraphElement> HTMLElement::AsHTMLParagraphElement() {
  return NULL;
}

scoped_refptr<HTMLScriptElement> HTMLElement::AsHTMLScriptElement() {
  return NULL;
}

scoped_refptr<HTMLSpanElement> HTMLElement::AsHTMLSpanElement() { return NULL; }

scoped_refptr<HTMLStyleElement> HTMLElement::AsHTMLStyleElement() {
  return NULL;
}

scoped_refptr<HTMLTitleElement> HTMLElement::AsHTMLTitleElement() {
  return NULL;
}

scoped_refptr<HTMLUnknownElement> HTMLElement::AsHTMLUnknownElement() {
  return NULL;
}

scoped_refptr<HTMLVideoElement> HTMLElement::AsHTMLVideoElement() {
  return NULL;
}

scoped_refptr<LottiePlayer> HTMLElement::AsLottiePlayer() { return NULL; }

void HTMLElement::ClearRuleMatchingState() {
  ClearRuleMatchingStateInternal(true /*invalidate_descendants*/);
}

void HTMLElement::ClearRuleMatchingStateInternal(bool invalidate_descendants) {
  rule_matching_state_.Clear();
  matching_rules_valid_ = false;

  if (invalidate_descendants) {
    InvalidateMatchingRulesRecursivelyInternal(true /*is_initial_element*/);
  }
}

void HTMLElement::ClearRuleMatchingStateOnElementAndAncestors(
    bool invalidate_matching_rules) {
  Element* parent_element = this->parent_element();
  HTMLElement* parent_html_element =
      parent_element ? parent_element->AsHTMLElement() : NULL;
  if (parent_html_element) {
    parent_html_element->ClearRuleMatchingStateOnElementAndAncestors(
        invalidate_matching_rules);
  }
  ClearRuleMatchingStateInternal(invalidate_matching_rules &&
                                 parent_html_element == NULL);
}

void HTMLElement::ClearRuleMatchingStateOnElementAndDescendants() {
  ClearRuleMatchingStateInternal(false /* invalidate_descendants*/);
  for (Element* element = first_element_child(); element;
       element = element->next_element_sibling()) {
    HTMLElement* html_element = element->AsHTMLElement();
    if (html_element) {
      html_element->ClearRuleMatchingStateOnElementAndDescendants();
    }
  }
}

void HTMLElement::ClearRuleMatchingStateOnElementAndSiblingsAndDescendants() {
  HTMLElement::ClearRuleMatchingStateOnElementAndDescendants();
  for (Element* element = previous_element_sibling(); element;
       element = element->previous_element_sibling()) {
    HTMLElement* html_element = element->AsHTMLElement();
    if (html_element) {
      html_element->ClearRuleMatchingStateOnElementAndDescendants();
    }
  }
  for (Element* element = next_element_sibling(); element;
       element = element->next_element_sibling()) {
    HTMLElement* html_element = element->AsHTMLElement();
    if (html_element) {
      html_element->ClearRuleMatchingStateOnElementAndDescendants();
    }
  }
}

void HTMLElement::InvalidateMatchingRulesRecursively() {
  InvalidateMatchingRulesRecursivelyInternal(true /*is_initial_element*/);
}

void HTMLElement::InvalidateMatchingRulesRecursivelyInternal(
    bool is_initial_element) {
  matching_rules_valid_ = false;

  // Invalidate matching rules on all children.
  for (Element* element = first_element_child(); element;
       element = element->next_element_sibling()) {
    HTMLElement* html_element = element->AsHTMLElement();
    if (html_element) {
      html_element->InvalidateMatchingRulesRecursivelyInternal(
          false /*is_initial_element*/);
    }
  }

  // Invalidate matching rules on all following siblings if this is the initial
  // element and sibling combinators are used; if this is not the initial
  // element, then these will already be handled by a previous call.
  if (is_initial_element &&
      node_document()->selector_tree()->has_sibling_combinators()) {
    for (Element* element = next_element_sibling(); element;
         element = element->next_element_sibling()) {
      HTMLElement* html_element = element->AsHTMLElement();
      if (html_element) {
        html_element->InvalidateMatchingRulesRecursivelyInternal(
            false /*is_initial_element*/);
      }
    }
  }
}

void HTMLElement::UpdateMatchingRules() { UpdateElementMatchingRules(this); }

void HTMLElement::UpdateMatchingRulesRecursively() {
  UpdateMatchingRules();
  for (Element* element = first_element_child(); element;
       element = element->next_element_sibling()) {
    HTMLElement* html_element = element->AsHTMLElement();
    if (html_element) {
      html_element->UpdateMatchingRulesRecursively();
    }
  }
}

void HTMLElement::OnMatchingRulesModified() {
  dom_stat_tracker_->OnUpdateMatchingRules();
  computed_style_valid_ = false;
}

void HTMLElement::OnPseudoElementMatchingRulesModified() {
  pseudo_elements_computed_styles_valid_ = false;
}

void HTMLElement::UpdateComputedStyleRecursively(
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        parent_computed_style_declaration,
    const scoped_refptr<const cssom::CSSComputedStyleData>& root_computed_style,
    const base::TimeDelta& style_change_event_time, bool ancestors_were_valid,
    int current_element_depth) {
  int max_depth = node_document()->dom_max_element_depth();
  if (max_depth > 0 && current_element_depth >= max_depth) {
    return;
  }

  // Update computed styles for this element if any aren't valid.
  bool is_valid = ancestors_were_valid && AreComputedStylesValid();
  if (!is_valid) {
    UpdateComputedStyle(parent_computed_style_declaration, root_computed_style,
                        style_change_event_time, kAncestorsAreDisplayed);
    UpdateUiNavigation();
    node_document()->set_ui_nav_needs_layout(true);
  } else if (ui_nav_needs_update_) {
    UpdateUiNavigation();
  }

  // Do not update computed style for descendants of "display: none" elements,
  // since they do not participate in layout. Note the "display: none" elements
  // themselves still need to have their computed style updated, in case the
  // value of display is changed.
  if (computed_style()->display() == cssom::KeywordValue::GetNone()) {
    return;
  }

  // Update computed style for this element's descendants. Note that if
  // descendant_computed_styles_valid_ flag is not set, the ancestors should
  // still be considered invalid, which forces the computes styles to be updated
  // on all children.
  for (Element* element = first_element_child(); element;
       element = element->next_element_sibling()) {
    HTMLElement* html_element = element->AsHTMLElement();
    if (html_element) {
      html_element->UpdateComputedStyleRecursively(
          css_computed_style_declaration(), root_computed_style,
          style_change_event_time,
          is_valid && descendant_computed_styles_valid_,
          current_element_depth + 1);
    }
  }

  descendant_computed_styles_valid_ = true;
}

void HTMLElement::MarkNotDisplayedOnNodeAndDescendants() {
  // While we do want to clear the animations immediately, we also want to
  // ensure that they are also reset starting with the next computed style
  // update.  This ensures that for example a transition will not be triggered
  // on the next computed style update.
  ancestors_are_displayed_ = kAncestorsAreNotDisplayed;

  PurgeCachedBackgroundImages();

  if (!css_animations_.empty() || !css_transitions_.empty()) {
    css_transitions_.Clear();
    css_animations_.Clear();
    computed_style_valid_ = false;
    descendant_computed_styles_valid_ = false;
  }

  // Also clear out all animations/transitions on pseudo elements.
  for (auto& pseudo_element : pseudo_elements_) {
    if (pseudo_element) {
      pseudo_element->css_transitions()->Clear();
      pseudo_element->css_animations()->Clear();
    }
  }

  ReleaseUiNavigationItem();
  MarkNotDisplayedOnDescendants();
}

void HTMLElement::PurgeCachedBackgroundImagesOfNodeAndDescendants() {
  PurgeCachedBackgroundImages();
  PurgeCachedBackgroundImagesOfDescendants();
}

void HTMLElement::PurgeCachedBackgroundImages() {
  ClearActiveBackgroundImages();
  if (!cached_background_images_.empty()) {
    ClearCachedBackgroundImages();
    computed_style_valid_ = false;
    descendant_computed_styles_valid_ = false;
  }
}

bool HTMLElement::IsDisplayed() const {
  return ancestors_are_displayed_ == kAncestorsAreDisplayed &&
         computed_style()->display() != cssom::KeywordValue::GetNone();
}

bool HTMLElement::IsRootElement() {
  // The html element represents the root of an HTML document.
  //   https://www.w3.org/TR/2014/REC-html5-20141028/semantics.html#the-root-element
  return AsHTMLHtmlElement().get() != NULL;
}

void HTMLElement::InvalidateComputedStylesOfNodeAndDescendants() {
  computed_style_valid_ = false;
  descendant_computed_styles_valid_ = false;
  InvalidateComputedStylesOfDescendants();
}

void HTMLElement::InvalidateLayoutBoxesOfNodeAndAncestors() {
  InvalidateLayoutBoxes();
  InvalidateLayoutBoxesOfAncestors();
}

void HTMLElement::InvalidateLayoutBoxesOfNodeAndDescendants() {
  InvalidateLayoutBoxes();
  InvalidateLayoutBoxesOfDescendants();
}

void HTMLElement::InvalidateLayoutBoxSizes() {
  InvalidateScrollAreaCacheOfAncestors(parent_node());
  if (layout_boxes_) {
    layout_boxes_->InvalidateSizes();

    for (auto& pseudo_element : pseudo_elements_) {
      if (pseudo_element && pseudo_element->layout_boxes()) {
        pseudo_element->layout_boxes()->InvalidateSizes();
      }
    }
  }
}

void HTMLElement::InvalidateLayoutBoxCrossReferences() {
  if (layout_boxes_) {
    layout_boxes_->InvalidateCrossReferences();

    for (auto& pseudo_element : pseudo_elements_) {
      if (pseudo_element && pseudo_element->layout_boxes()) {
        pseudo_element->layout_boxes()->InvalidateCrossReferences();
      }
    }
  }
}

void HTMLElement::InvalidateLayoutBoxRenderTreeNodes() {
  if (layout_boxes_) {
    layout_boxes_->InvalidateRenderTreeNodes();

    for (auto& pseudo_element : pseudo_elements_) {
      if (pseudo_element && pseudo_element->layout_boxes()) {
        pseudo_element->layout_boxes()->InvalidateRenderTreeNodes();
      }
    }
  }
}

void HTMLElement::InvalidateLayoutBoxes() {
  layout_boxes_.reset();
  for (auto& pseudo_element : pseudo_elements_) {
    if (pseudo_element) {
      pseudo_element->reset_layout_boxes();
    }
  }
  directionality_ = base::nullopt;
}

void HTMLElement::OnUiNavBlur(int64_t monotonic_time) {
  if (node_document() && node_document()->ui_nav_focus_element() == this) {
    if (node_document()->TrySetUiNavFocusElement(nullptr, monotonic_time)) {
      Blur();
    }
  }
}

void HTMLElement::OnUiNavFocus(int64_t monotonic_time) {
  // Suppress the focus event if this is already focused -- i.e. the HTMLElement
  // initiated the focus change that resulted in this call to OnUiNavFocus.
  if (node_document() && node_document()->ui_nav_focus_element() != this) {
    if (node_document()->TrySetUiNavFocusElement(this, monotonic_time)) {
      Focus();
    }
  }
}

void HTMLElement::OnUiNavScroll(int64_t /* monotonic_time */) {
  Document* document = node_document();
  if (document->hidden()) {
    return;
  }
  scoped_refptr<Window> window(document ? document->window() : nullptr);
  DispatchEvent(new UIEvent(base::Tokens::scroll(), web::Event::kNotBubbles,
                            web::Event::kNotCancelable, window));
}

HTMLElement::HTMLElement(Document* document, base::Token local_name)
    : Element(document, local_name),
      dom_stat_tracker_(document->html_element_context()->dom_stat_tracker()),
      locked_for_focus_(false),
      dir_(kDirNotDefined),
      style_(new cssom::CSSDeclaredStyleDeclaration(
          document->html_element_context()->css_parser())),
      computed_style_valid_(false),
      pseudo_elements_computed_styles_valid_(false),
      descendant_computed_styles_valid_(false),
      ancestors_are_displayed_(kAncestorsAreDisplayed),
      css_computed_style_declaration_(new cssom::CSSComputedStyleDeclaration()),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          transitions_adapter_(new DOMAnimatable(this))),
      css_transitions_(&transitions_adapter_),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          animations_adapter_(new DOMAnimatable(this))),
      css_animations_(&animations_adapter_),
      matching_rules_valid_(false) {
  css_computed_style_declaration_->set_animations(animations());
  style_->set_mutation_observer(this);
  dom_stat_tracker_->OnHtmlElementCreated();
}

HTMLElement::~HTMLElement() {
  ReleaseUiNavigationItem();

  if (IsInDocument()) {
    dom_stat_tracker_->OnHtmlElementRemovedFromDocument();
  }
  dom_stat_tracker_->OnHtmlElementDestroyed();

  style_->set_mutation_observer(NULL);
}

void HTMLElement::OnInsertedIntoDocument() {
  Node::OnInsertedIntoDocument();
  dom_stat_tracker_->OnHtmlElementInsertedIntoDocument();
}

void HTMLElement::OnRemovedFromDocument() {
  Node::OnRemovedFromDocument();
  dom_stat_tracker_->OnHtmlElementRemovedFromDocument();

  // When an element that is focused stops being a focusable element, or stops
  // being focused without another element being explicitly focused in its
  // stead, the user agent should synchronously run the unfocusing steps for the
  // affected element only.
  // For example, this might happen because the element is removed from its
  // Document, or has a hidden attribute added. It would also happen to an input
  // element when the element gets disabled.
  //   https://www.w3.org/TR/html50/editing.html#unfocusing-steps
  Document* document = node_document();
  DCHECK(document);
  if (document->active_element() == this->AsElement()) {
    RunUnFocusingSteps();
    document->OnFocusChange();
  }

  // Only clear the rule matching on this element. Descendants will be handled
  // by OnRemovedFromDocument() being called on them from
  // Node::OnRemovedFromDocument().
  ClearRuleMatchingStateInternal(false /*invalidate_descendants*/);

  ReleaseUiNavigationItem();
}

void HTMLElement::OnMutation() { InvalidateMatchingRulesRecursively(); }

void HTMLElement::OnSetAttribute(const std::string& name,
                                 const std::string& value) {
  // Be sure to update HTMLElement::Duplicate() to copy over values as needed.
  if (name == "dir") {
    SetDir(value);
  } else if (name == "tabindex") {
    SetTabIndex(value);
  } else if (name == kUiNavFocusDurationAttribute) {
    SetUiNavFocusDuration(value);
  }

  // Always clear the matching state when an attribute changes. Any attribute
  // changing can potentially impact the matching rules.
  ClearRuleMatchingState();
}

void HTMLElement::OnRemoveAttribute(const std::string& name) {
  if (name == "dir") {
    SetDir("");
  } else if (name == "tabindex") {
    SetTabIndex("");
  } else if (name == kUiNavFocusDurationAttribute) {
    SetUiNavFocusDuration("");
  }

  // Always clear the matching state when an attribute changes. Any attribute
  // changing can potentially impact the matching rules.
  ClearRuleMatchingState();
}

// Algorithm for IsFocusable:
//   https://www.w3.org/TR/html50/editing.html#focusable
bool HTMLElement::IsFocusable() {
  return HasTabindexFocusFlag() && IsBeingRendered();
}

// Algorithm for HasTabindexFocusFlag:
//  https://www.w3.org/TR/html50/editing.html#specially-focusable
bool HTMLElement::HasTabindexFocusFlag() const { return tabindex_.has_value(); }

// An element is being rendered if it has any associated CSS layout boxes, SVG
// layout boxes, or some equivalent in other styling languages.
//   https://www.w3.org/TR/html50/rendering.html#being-rendered
bool HTMLElement::IsBeingRendered() {
  Document* document = node_document();
  if (!document) {
    return false;
  }

  if (!document->UpdateComputedStyleOnElementAndAncestor(this)) {
    return false;
  }
  DCHECK(computed_style());

  return IsDisplayed() &&
         computed_style()->visibility() == cssom::KeywordValue::GetVisible();
}

// Algorithm for RunFocusingSteps:
//   https://www.w3.org/TR/html50/editing.html#focusing-steps
void HTMLElement::RunFocusingSteps() {
  // 1. If the element is not in a Document, or if the element's Document has
  // no browsing context, or if the element's Document's browsing context has no
  // top-level browsing context, or if the element is not focusable, or if the
  // element is already focused, then abort these steps.
  Document* document = node_document();
  if (!document || !document->HasBrowsingContext() || !IsFocusable()) {
    return;
  }
  Element* old_active_element = document->active_element();
  if (old_active_element == this) {
    return;
  }

  // 2. If focusing the element will remove the focus from another element,
  // then run the unfocusing steps for that element.
  if (old_active_element && old_active_element->AsHTMLElement()) {
    old_active_element->AsHTMLElement()->RunUnFocusingSteps();
  }

  // focusin: A user agent MUST dispatch this event when an event target is
  // about to receive focus. This event type MUST be dispatched before the
  // element is given focus. The event target MUST be the element which is about
  // to receive focus. This event type is similar to focus, but is dispatched
  // before focus is shifted, and does bubble.
  //   https://www.w3.org/TR/2016/WD-uievents-20160804/#event-type-focusin
  DispatchEvent(new FocusEvent(base::Tokens::focusin(), web::Event::kBubbles,
                               web::Event::kNotCancelable, document->window(),
                               this));

  // 3. Make the element the currently focused element in its top-level browsing
  // context.
  document->SetActiveElement(this);

  // 4. Not needed by Cobalt.

  // 5. Fire a simple event named focus at the element.
  // focus: A user agent MUST dispatch this event when an event target receives
  // focus. The focus MUST be given to the element before the dispatch of this
  // event type. This event type is similar to focusin, but is dispatched after
  // focus is shifted, and does not bubble.
  //   https://www.w3.org/TR/2016/WD-uievents-20160804/#event-type-focus
  DispatchEvent(new FocusEvent(base::Tokens::focus(), web::Event::kNotBubbles,
                               web::Event::kNotCancelable, document->window(),
                               this));

  // Custom, not in any spec.
  ClearRuleMatchingState();
}

// Algorithm for RunUnFocusingSteps:
//   https://www.w3.org/TR/html50/editing.html#unfocusing-steps
void HTMLElement::RunUnFocusingSteps() {
  // 1. Not needed by Cobalt.

  // focusout: A user agent MUST dispatch this event when an event target is
  // about to lose focus. This event type MUST be dispatched before the element
  // loses focus. The event target MUST be the element which is about to lose
  // focus. This event type is similar to blur, but is dispatched before focus
  // is shifted, and does bubble.
  //   https://www.w3.org/TR/2016/WD-uievents-20160804/#event-type-focusout
  Document* document = node_document();
  scoped_refptr<Window> window(document ? document->window() : NULL);
  DispatchEvent(new FocusEvent(base::Tokens::focusout(), web::Event::kBubbles,
                               web::Event::kNotCancelable, window, this));

  // 2. Unfocus the element.
  if (document && document->active_element() == this->AsElement()) {
    document->SetActiveElement(NULL);
  }

  // 3. Fire a simple event named blur at the element.
  // blur: A user agent MUST dispatch this event when an event target loses
  // focus. The focus MUST be taken from the element before the dispatch of this
  // event type. This event type is similar to focusout, but is dispatched after
  // focus is shifted, and does not bubble.
  //   https://www.w3.org/TR/2016/WD-uievents-20160804/#event-type-blur
  DispatchEvent(new FocusEvent(base::Tokens::blur(), web::Event::kNotBubbles,
                               web::Event::kNotCancelable, document->window(),
                               this));

  // Custom, not in any spec.
  ClearRuleMatchingState();
}

void HTMLElement::UpdateUiNavigationFocus() {
  if (!node_document()) {
    return;
  }

  // Set the focus item for the UI navigation system. Search up the DOM tree to
  // find the nearest ancestor that is a UI navigation item if needed. Do this
  // step before dispatching events as the event handlers may make UI navigation
  // changes.
  for (Node* node = this; node; node = node->parent_node()) {
    Element* element = node->AsElement();
    if (!element) {
      continue;
    }
    HTMLElement* html_element = element->AsHTMLElement();
    if (!html_element) {
      continue;
    }
    if (!html_element->ui_nav_item_ ||
        html_element->ui_nav_item_->IsContainer()) {
      continue;
    }

    // Updating the UI navigation focus element has the additional effect of
    // suppressing the Blur call for the previously focused HTMLElement and the
    // Focus call for this HTMLElement as a result of OnUiNavBlur / OnUiNavFocus
    // callbacks that result from initiating the UI navigation focus change.
    if (node_document()->TrySetUiNavFocusElement(
            html_element, starboard::CurrentMonotonicTime())) {
      html_element->ui_nav_item_->Focus();
    }
    break;
  }
}

void HTMLElement::SetUiNavItemBounds() {
  if (!ui_nav_item_->IsContainer()) {
    return;
  }

  DirState dir = GetUsedDirState();
  if (dir == DirState::kDirNotDefined) {
    Document* document = node_document();
    if (document && document->html()) {
      dir = document->html()->GetUsedDirState();
    }
  }

  float scrollable_width = scroll_width() - client_width();
  float scroll_top_lower_bound = 0.0f;
  float scroll_left_lower_bound =
      dir == DirState::kDirRightToLeft ? -scrollable_width : 0.0f;
  float scroll_top_upper_bound = scroll_height() - client_height();
  float scroll_left_upper_bound =
      dir == DirState::kDirRightToLeft ? 0.0f : scrollable_width;
  ui_nav_item_->SetBounds(scroll_top_lower_bound, scroll_left_lower_bound,
                          scroll_top_upper_bound, scroll_left_upper_bound);
}

void HTMLElement::SetDir(const std::string& value) {
  // https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-dir-attribute
  auto previous_dir = dir_;
  if (value == "auto") {
    dir_ = kDirAuto;
  } else if (value == "ltr") {
    dir_ = kDirLeftToRight;
  } else if (value == "rtl") {
    dir_ = kDirRightToLeft;
  } else {
    dir_ = kDirNotDefined;

    // Reset the attribute so that element.getAttribute('dir') returns the
    // same thing as element.dir.
    if (value.size() > 0) {
      LOG(WARNING) << "Unsupported value '" << value << "' for attribute 'dir'";
      SetAttribute("dir", "");
    }
  }

  if (dir_ != previous_dir) {
    InvalidateLayoutBoxesOfNodeAndAncestors();
    InvalidateLayoutBoxesOfDescendants();
  }
}

void HTMLElement::SetTabIndex(const std::string& value) {
  int32 tabindex;
  if (base::StringToInt32(value, &tabindex)) {
    tabindex_ = tabindex;
  } else {
    tabindex_ = base::nullopt;
  }

  // Changing the tabindex may trigger a UI navigation change.
  ui_nav_needs_update_ = true;
}

void HTMLElement::SetUiNavFocusDuration(const std::string& value) {
  double duration;
  if (base::StringToDouble(value, &duration)) {
    ui_nav_focus_duration_ = static_cast<float>(duration);
    if (!std::isfinite(*ui_nav_focus_duration_) ||
        *ui_nav_focus_duration_ < 0.0f) {
      ui_nav_focus_duration_ = 0.0f;
    }
    if (ui_nav_item_) {
      ui_nav_item_->SetFocusDuration(*ui_nav_focus_duration_);
    }
  } else {
    ui_nav_focus_duration_ = base::nullopt;
    if (ui_nav_item_) {
      ui_nav_item_->SetFocusDuration(0.0f);
    }
  }
}

namespace {
// This is similar to base rtl.h's GetStringDirection; however, this takes a
// utf8 string and only pays attention to L, AL, and R character types.
HTMLElement::DirState GetStringDirection(const std::string& utf8_string) {
  int32_t length = static_cast<int32_t>(utf8_string.length());
  for (int32_t index = 0; index < length;) {
    int32_t ch;
    U8_NEXT(utf8_string.data(), index, length, ch);
    if (ch < 0) {
      LOG(ERROR) << "Unable to determine directionality of " << utf8_string;
      break;
    }

    int32_t property = u_getIntPropertyValue(ch, UCHAR_BIDI_CLASS);
    if (property == U_LEFT_TO_RIGHT) {
      return HTMLElement::kDirLeftToRight;
    }
    if (property == U_RIGHT_TO_LEFT || property == U_RIGHT_TO_LEFT_ARABIC) {
      return HTMLElement::kDirRightToLeft;
    }
  }
  return HTMLElement::kDirNotDefined;
}
}  // namespace

// This is similar to dir_state() except it will resolve kDirAuto to
// kDirLeftToRight or kDirRightToLeft according to the spec:
//   https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-directionality
// If "dir" was not defined for this element, then this function will return
// kDirNotDefined.
HTMLElement::DirState HTMLElement::GetUsedDirState() {
  // If the element's dir attribute is in the auto state
  // If the element is a bdi element and the dir attribute is not in a defined
  //   state (i.e. it is not present or has an invalid value)
  if (dir_ != kDirAuto) {
    return dir_;
  }

  // Find the first character in tree order that matches the following criteria:
  //   The character is from a Text node that is a descendant of the element
  //     whose directionality is being determined.
  //   The character is of bidirectional character type L, AL, or R. [BIDI]
  //   The character is not in a Text node that has an ancestor element that is
  //     a descendant of the element whose directionality is being determined
  //     and that is either:
  //       A bdi element.
  //       A script element.
  //       A style element.
  //       A textarea element.
  //       An element with a dir attribute in a defined state.
  //   If such a character is found and it is of bidirectional character type
  //     AL or R, the directionality of the element is 'rtl'.
  //   If such a character is found and it is of bidirectional character type
  //     L, the directionality of the element is 'ltr'.

  // A tree is a finite hierarchical tree structure. In tree order is preorder,
  // depth-first traversal of a tree.
  //   https://dom.spec.whatwg.org/#concept-tree-order
  std::vector<Node*> stack;

  // Add children in reverse order so that pop_back() will result in preorder
  // depth-first traversal.
  for (Node* child_node = last_child(); child_node;
       child_node = child_node->previous_sibling()) {
    stack.push_back(child_node);
  }

  while (!stack.empty()) {
    Node* node = stack.back();
    stack.pop_back();

    Text* text = node->AsText();
    if (text) {
      // If the text has strong directionality, then return it.
      DirState dir = GetStringDirection(text->text());
      if (dir != kDirNotDefined) {
        return dir;
      }
    }

    // Traverse children only if this is not:
    //   A bdi element.
    //   A script element.
    //   A style element.
    //   A textarea element.
    //   An element with a dir attribute in a defined state.
    Element* element = node->AsElement();
    if (element) {
      HTMLElement* html_element = element->AsHTMLElement();
      if (html_element) {
        if (html_element->AsHTMLScriptElement() ||
            html_element->AsHTMLStyleElement() ||
            html_element->dir_state() != kDirNotDefined) {
          continue;
        }
      }
    }

    for (Node* child_node = node->last_child(); child_node;
         child_node = child_node->previous_sibling()) {
      stack.push_back(child_node);
    }
  }

  // Otherwise, if the element is a document element, the directionality of
  //   the element is 'ltr'.
  if (IsDocumentElement()) {
    return kDirLeftToRight;
  }

// Although the spec says to use the parent's directionality, the W3C test
// (the-dir-attribute-069.html) says to default to LTR. Chrome follows the
// W3C expectation, so follow Chrome. Additional discussion here:
//   https://github.com/w3c/i18n-drafts/issues/235
// The following code block which implements the spec is left for reference.
#if 0
  // Otherwise, the directionality of the element is the same as the element's
  //   parent element's directionality.
  for (Node* ancestor_node = parent_node(); ancestor_node;
       ancestor_node = ancestor_node->parent_node()) {
    Element* ancestor_element = ancestor_node->AsElement();
    if (!ancestor_element) {
      continue;
    }
    HTMLElement* ancestor_html_element = ancestor_element->AsHTMLElement();
    if (!ancestor_html_element) {
      continue;
    }
    if (ancestor_html_element->dir_state() == kDirNotDefined) {
      continue;
    }
    return ancestor_html_element->GetUsedDirState();
  }
#endif

  return kDirLeftToRight;
}

// Algorithm:
//   https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-directionality
Directionality HTMLElement::directionality() {
  // Use the cached value if available.
  if (directionality_) {
    return *directionality_;
  }

  // The directionality of an element (any element, not just an HTML element)
  // is either 'ltr' or 'rtl', and is determined as per the first appropriate
  // set of steps from the following list:

  // If the element's dir attribute is in the ltr state
  // If the element is a document element and the dir attribute is not in a
  //   defined state (i.e. it is not present or has an invalid value)
  // If the element is an input element whose type attribute is in the
  //   Telephone state, and the dir attribute is not in a defined state (i.e.
  //   it is not present or has an invalid value)
  // --> The directionality of the element is 'ltr'.
  if (dir_ == kDirLeftToRight) {
    directionality_ = kLeftToRightDirectionality;
    return *directionality_;
  }
  // [Case of undefined 'dir' is handled later in this function.]

  // If the element's dir attribute is in the rtl state
  // --> The directionality of the element is 'rtl'.
  if (dir_ == kDirRightToLeft) {
    directionality_ = kRightToLeftDirectionality;
    return *directionality_;
  }

  // If the element is an input element whose type attribute is in the Text,
  //   Search, Telephone, URL, or E-mail state, and the dir attribute is in the
  //   auto state
  // If the element is a textarea element and the dir attribute is in the auto
  //   state
  // --> Cobalt does not support these element types.

  // If the element's dir attribute is in the auto state
  // If the element is a bdi element and the dir attribute is not in a defined
  //   state (i.e. it is not present or has an invalid value)
  // --> Find the first character in tree order that matches the following
  //       criteria:
  //       The character is from a Text node that is a descendant of the
  //         element whose directionality is being determined.
  //       The character is of bidirectional character type L, AL, or R. [BIDI]
  //       The character is not in a Text node that has an ancestor element
  //         that is a descendant of the element whose directionality is being
  //         determined and that is either:
  //           A bdi element.
  //           A script element.
  //           A style element.
  //           A textarea element.
  //           An element with a dir attribute in a defined state.
  //     If such a character is found and it is of bidirectional character type
  //       AL or R, the directionality of the element is 'rtl'.
  //     If such a character is found and it is of bidirectional character type
  //       L, the directionality of the element is 'ltr'.
  //     Otherwise, if the element is a document element, the directionality of
  //       the element is 'ltr'.
  //     Otherwise, the directionality of the element is the same as the
  //       element's parent element's directionality.

  // If the element has a parent element and the dir attribute is not in a
  //   defined state (i.e. it is not present or has an invalid value)
  // --> The directionality of the element is the same as the element's parent
  //       element's directionality.
  for (Node* ancestor_node = parent_node(); ancestor_node;
       ancestor_node = ancestor_node->parent_node()) {
    Element* ancestor_element = ancestor_node->AsElement();
    if (!ancestor_element) {
      continue;
    }
    HTMLElement* ancestor_html_element = ancestor_element->AsHTMLElement();
    if (!ancestor_html_element) {
      continue;
    }
    directionality_ = ancestor_html_element->directionality();
    return *directionality_;
  }

  directionality_ = kLeftToRightDirectionality;
  return *directionality_;
}

namespace {

scoped_refptr<cssom::CSSComputedStyleData> PromoteMatchingRulesToComputedStyle(
    cssom::RulesWithCascadePrecedence* matching_rules,
    cssom::GURLMap* property_key_to_base_url_map,
    const scoped_refptr<const cssom::CSSDeclaredStyleData>& inline_style,
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        parent_computed_style_declaration,
    const scoped_refptr<const cssom::CSSComputedStyleData>& root_computed_style,
    const ViewportSize& viewport_size) {
  // Select the winning value for each property by performing the cascade,
  // that is, apply values from matching rules on top of inline style, taking
  // into account rule specificity and location in the source file, as well as
  // property declaration importance.
  scoped_refptr<cssom::MutableCSSComputedStyleData> computed_style =
      PromoteToCascadedStyle(inline_style, matching_rules,
                             property_key_to_base_url_map);

  // Lastly, absolutize the values, if possible. Start by resolving "initial"
  // and "inherit" keywords (which gives us what the specification refers to
  // as "specified style").  Then, convert length units and percentages into
  // pixels, convert color keywords into RGB triplets, and so on.  For certain
  // properties, like "font-family", computed value is the same as specified
  // value. Declarations that cannot be absolutized easily, like "width: auto;",
  // will be resolved during layout.
  cssom::PromoteToComputedStyle(
      computed_style, parent_computed_style_declaration, root_computed_style,
      viewport_size.width_height(), property_key_to_base_url_map);

  return computed_style;
}

void PossiblyActivateAnimations(
    const scoped_refptr<const cssom::CSSComputedStyleData>&
        previous_computed_style,
    const scoped_refptr<const cssom::CSSComputedStyleData>& new_computed_style,
    const base::TimeDelta& style_change_event_time,
    cssom::TransitionSet* css_transitions, cssom::AnimationSet* css_animations,
    const cssom::CSSKeyframesRule::NameMap& keyframes_map,
    HTMLElement::AncestorsAreDisplayed old_ancestors_are_displayed,
    HTMLElement::AncestorsAreDisplayed new_ancestors_are_displayed,
    bool* animations_modified) {
  // Calculate some helper values to help determine if we are transitioning from
  // not being displayed to being displayed, or vice-versa.  Animations should
  // not be playing if we are not being displayed.
  bool old_is_displayed =
      old_ancestors_are_displayed == HTMLElement::kAncestorsAreDisplayed &&
      (previous_computed_style &&
       previous_computed_style->display() != cssom::KeywordValue::GetNone());
  bool new_is_displayed =
      new_ancestors_are_displayed == HTMLElement::kAncestorsAreDisplayed &&
      new_computed_style->display() != cssom::KeywordValue::GetNone();

  if (new_is_displayed) {
    // Don't start any transitions if we are transitioning from display: none.
    if (previous_computed_style && old_is_displayed) {
      // Now that we have updated our computed style, compare it to the previous
      // style and see if we need to adjust our animations.
      css_transitions->UpdateTransitions(style_change_event_time,
                                         *previous_computed_style,
                                         *new_computed_style);
    }
    // Update the set of currently running animations and track whether or not
    // the animations changed.
    *animations_modified = css_animations->Update(
        style_change_event_time, *new_computed_style, keyframes_map);
  } else {
    if (old_is_displayed) {
      css_transitions->Clear();
      css_animations->Clear();
    } else {
      DCHECK(css_transitions->empty());
      DCHECK(css_animations->empty());
    }
  }
}

// Flags tracking which cached values must be invalidated.
struct UpdateComputedStyleInvalidationFlags {
  UpdateComputedStyleInvalidationFlags()
      : mark_descendants_as_display_none(false),
        invalidate_computed_styles_of_descendants(false),
        invalidate_layout_boxes(false),
        invalidate_sizes(false),
        invalidate_cross_references(false),
        invalidate_render_tree_nodes(false) {}

  bool mark_descendants_as_display_none;
  bool invalidate_computed_styles_of_descendants;
  bool invalidate_layout_boxes;
  bool invalidate_sizes;
  bool invalidate_cross_references;
  bool invalidate_render_tree_nodes;
};

bool NewComputedStyleMarksDescendantsAsDisplayNone(
    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style) {
  return old_computed_style->display() != cssom::KeywordValue::GetNone() &&
         new_computed_style->display() == cssom::KeywordValue::GetNone();
}

bool NewComputedStyleInvalidatesComputedStylesOfDescendants(
    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style) {
  return !non_trivial_static_fields.Get()
              .computed_style_invalidation_property_checker
              .DoDeclaredPropertiesMatch(old_computed_style,
                                         new_computed_style);
}

bool NewComputedStyleInvalidatesLayoutBoxes(
    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style) {
  return !non_trivial_static_fields.Get()
              .layout_box_invalidation_property_checker
              .DoDeclaredPropertiesMatch(old_computed_style,
                                         new_computed_style);
}

bool NewComputedStyleInvalidatesSizes(
    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style) {
  return !non_trivial_static_fields.Get()
              .size_invalidation_property_checker.DoDeclaredPropertiesMatch(
                  old_computed_style, new_computed_style);
}

bool NewComputedStyleInvalidatesCrossReferences(
    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style) {
  return !non_trivial_static_fields.Get()
              .cross_references_invalidation_property_checker
              .DoDeclaredPropertiesMatch(old_computed_style,
                                         new_computed_style);
}

enum IsPseudoElement {
  kIsNotPseudoElement,
  kIsPseudoElement,
};

void UpdateInvalidationFlagsFromNewComputedStyle(
    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style,
    bool animations_modified, IsPseudoElement is_pseudo_element,
    UpdateComputedStyleInvalidationFlags* flags) {
  if (old_computed_style) {
    if (!flags->mark_descendants_as_display_none &&
        is_pseudo_element == kIsNotPseudoElement &&
        NewComputedStyleMarksDescendantsAsDisplayNone(old_computed_style,
                                                      new_computed_style)) {
      flags->mark_descendants_as_display_none = true;
    }
    if (!flags->invalidate_computed_styles_of_descendants &&
        NewComputedStyleInvalidatesComputedStylesOfDescendants(
            old_computed_style, new_computed_style)) {
      flags->invalidate_computed_styles_of_descendants = true;
      flags->invalidate_layout_boxes = true;
    } else if (!flags->invalidate_layout_boxes) {
      if (NewComputedStyleInvalidatesLayoutBoxes(old_computed_style,
                                                 new_computed_style)) {
        flags->invalidate_layout_boxes = true;
      } else {
        if (!flags->invalidate_sizes &&
            NewComputedStyleInvalidatesSizes(old_computed_style,
                                             new_computed_style)) {
          flags->invalidate_sizes = true;
          flags->invalidate_render_tree_nodes = true;
        }
        if (!flags->invalidate_cross_references &&
            NewComputedStyleInvalidatesCrossReferences(old_computed_style,
                                                       new_computed_style)) {
          flags->invalidate_cross_references = true;
          flags->invalidate_render_tree_nodes = true;
        }

        flags->invalidate_render_tree_nodes =
            flags->invalidate_render_tree_nodes || animations_modified ||
            !new_computed_style->DoDeclaredPropertiesMatch(old_computed_style);
      }
    }
  }
}

void DoComputedStyleUpdate(
    cssom::RulesWithCascadePrecedence* matching_rules,
    cssom::GURLMap* property_key_to_base_url_map,
    const scoped_refptr<const cssom::CSSDeclaredStyleData>& inline_style,
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        parent_computed_style_declaration,
    const scoped_refptr<const cssom::CSSComputedStyleData>& root_computed_style,
    const ViewportSize& viewport_size,
    const scoped_refptr<const cssom::CSSComputedStyleData>&
        previous_computed_style,
    const base::TimeDelta& style_change_event_time,
    cssom::TransitionSet* css_transitions, cssom::AnimationSet* css_animations,
    const cssom::CSSKeyframesRule::NameMap& keyframes_map,
    HTMLElement::AncestorsAreDisplayed old_ancestors_are_displayed,
    HTMLElement::AncestorsAreDisplayed new_ancestors_are_displayed,
    IsPseudoElement is_pseudo_element,
    UpdateComputedStyleInvalidationFlags* invalidation_flags,
    cssom::CSSComputedStyleDeclaration* css_computed_style_declaration) {
  bool animations_modified = false;

  scoped_refptr<cssom::CSSComputedStyleData> new_computed_style =
      PromoteMatchingRulesToComputedStyle(
          matching_rules, property_key_to_base_url_map, inline_style,
          parent_computed_style_declaration, root_computed_style,
          viewport_size);

  PossiblyActivateAnimations(previous_computed_style, new_computed_style,
                             style_change_event_time, css_transitions,
                             css_animations, keyframes_map,
                             old_ancestors_are_displayed,
                             new_ancestors_are_displayed, &animations_modified);

  UpdateInvalidationFlagsFromNewComputedStyle(
      previous_computed_style, new_computed_style, animations_modified,
      is_pseudo_element, invalidation_flags);

  css_computed_style_declaration->SetData(new_computed_style);
}
}  // namespace

void HTMLElement::UpdateComputedStyle(
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        parent_computed_style_declaration,
    const scoped_refptr<const cssom::CSSComputedStyleData>& root_computed_style,
    const base::TimeDelta& style_change_event_time,
    AncestorsAreDisplayed ancestors_are_displayed) {
  Document* document = node_document();
  DCHECK(document) << "Element should be attached to document in order to "
                      "participate in layout.";

  // Verify that the matching rules for this element are valid. They should have
  // been updated prior to UpdateComputedStyle() being called.
  DCHECK(matching_rules_valid_);
  // If there is no previous computed style, there should also be no layout
  // boxes.
  DCHECK(computed_style() || NULL == layout_boxes());

  dom_stat_tracker_->OnUpdateComputedStyle();

  // The computed style must be generated if either the computed style is
  // invalid or no computed style has been created yet.
  bool generate_computed_style = !computed_style_valid_ || !computed_style();

  // If any declared properties inherited from the parent are no longer valid,
  // then a new computed style must be generated with the updated inherited
  // values.
  if (!generate_computed_style &&
      !computed_style()->AreDeclaredPropertiesInheritedFromParentValid()) {
    generate_computed_style = true;
  }

  // It is possible for computed style to have been updated on this element even
  // if its ancestors were set to display: none.  If this has changed, we would
  // need to update our computed style again, even if nothing else has changed.
  if (!generate_computed_style &&
      ancestors_are_displayed_ == kAncestorsAreNotDisplayed &&
      ancestors_are_displayed == kAncestorsAreDisplayed) {
    generate_computed_style = true;
  }

  // TODO: It maybe helpful to generalize this mapping framework in the
  // future to allow more data and context about where a cssom::PropertyValue
  // came from.
  cssom::GURLMap property_key_to_base_url_map;
  property_key_to_base_url_map[cssom::kBackgroundImageProperty] =
      document->location()->url();

  // Flags tracking which cached values must be invalidated.
  UpdateComputedStyleInvalidationFlags invalidation_flags;

  // We record this now before we make changes to the computed style and use
  // it later for the pseudo element computed style updates.
  bool old_is_displayed = computed_style() && IsDisplayed();

  if (generate_computed_style) {
    dom_stat_tracker_->OnGenerateHtmlElementComputedStyle();
    DoComputedStyleUpdate(
        matching_rules(), &property_key_to_base_url_map, style_->data(),
        parent_computed_style_declaration, root_computed_style,
        document->viewport_size(), computed_style(), style_change_event_time,
        &css_transitions_, &css_animations_, document->keyframes_map(),
        ancestors_are_displayed_, ancestors_are_displayed, kIsNotPseudoElement,
        &invalidation_flags, css_computed_style_declaration_);

    // Update cached background images after resolving the urls in
    // background_image CSS property of the computed style, so we have all the
    // information to get the cached background images.
    UpdateCachedBackgroundImagesFromComputedStyle();
  } else {
    // Update the inherited data if a new style was not generated. The ancestor
    // data with inherited properties may have changed.
    css_computed_style_declaration_->UpdateInheritedData();
  }

  // Update the displayed status of our ancestors.
  ancestors_are_displayed_ = ancestors_are_displayed;

  // Process pseudo elements. They must have their computed style generated if
  // either their owning HTML element's style was just generated or their
  // computed style is invalid (this occurs when their matching rules change).
  for (int type = 0; type < kMaxPseudoElementType; ++type) {
    PseudoElement* type_pseudo_element =
        pseudo_element(PseudoElementType(type));
    if (type_pseudo_element) {
      if (generate_computed_style ||
          type_pseudo_element->computed_style_invalid()) {
        dom_stat_tracker_->OnGeneratePseudoElementComputedStyle();
        DoComputedStyleUpdate(
            type_pseudo_element->matching_rules(),
            &property_key_to_base_url_map, NULL,
            css_computed_style_declaration(), root_computed_style,
            document->viewport_size(), type_pseudo_element->computed_style(),
            style_change_event_time, type_pseudo_element->css_transitions(),
            type_pseudo_element->css_animations(), document->keyframes_map(),
            old_is_displayed ? kAncestorsAreDisplayed
                             : kAncestorsAreNotDisplayed,
            IsDisplayed() ? kAncestorsAreDisplayed : kAncestorsAreNotDisplayed,
            kIsPseudoElement, &invalidation_flags,
            type_pseudo_element->css_computed_style_declaration());
        type_pseudo_element->clear_computed_style_invalid();
      } else {
        // Update the inherited data if a new style was not generated. The
        // ancestor data with inherited properties may have changed.
        type_pseudo_element->css_computed_style_declaration()
            ->UpdateInheritedData();
      }
    }
  }

  if (invalidation_flags.mark_descendants_as_display_none) {
    MarkNotDisplayedOnDescendants();
  }
  if (invalidation_flags.invalidate_computed_styles_of_descendants) {
    InvalidateComputedStylesOfDescendants();
  }

  if (invalidation_flags.invalidate_layout_boxes) {
    InvalidateLayoutBoxesOfNodeAndAncestors();
    InvalidateLayoutBoxesOfDescendants();
  } else {
    if (invalidation_flags.invalidate_sizes) {
      InvalidateLayoutBoxSizes();
    }
    if (invalidation_flags.invalidate_cross_references) {
      InvalidateLayoutBoxCrossReferences();
    }
    if (invalidation_flags.invalidate_render_tree_nodes) {
      InvalidateLayoutBoxRenderTreeNodes();
    }
  }

  computed_style_valid_ = true;
  pseudo_elements_computed_styles_valid_ = true;
}

void HTMLElement::CollectHTMLMediaElementsRecursively(
    std::vector<HTMLMediaElement*>* html_media_elements,
    int current_element_depth) {
  int max_depth = node_document()->dom_max_element_depth();
  if (max_depth > 0 && current_element_depth >= max_depth) {
    return;
  }

  for (Element* element = first_element_child(); element;
       element = element->next_element_sibling()) {
    HTMLElement* html_element = element->AsHTMLElement();
    if (html_element) {
      HTMLMediaElement* media_html_element = html_element->AsHTMLMediaElement();
      if (media_html_element) {
        html_media_elements->push_back(media_html_element);
      }
      html_element->CollectHTMLMediaElementsRecursively(
          html_media_elements, current_element_depth + 1);
    }
  }
}

void HTMLElement::SetPseudoElement(
    PseudoElementType type, std::unique_ptr<PseudoElement> pseudo_element) {
  DCHECK_EQ(this, pseudo_element->parent_element());
  DCHECK(type < kMaxPseudoElementType);
  pseudo_elements_[type] = std::move(pseudo_element);
  pseudo_elements_computed_styles_valid_ = false;
}

bool HTMLElement::AreComputedStylesValid() const {
  return computed_style_valid_ && pseudo_elements_computed_styles_valid_;
}

bool HTMLElement::IsDesignated() const {
  Document* document = node_document();
  if (document) {
    scoped_refptr<Element> element = document->indicated_element();
    while (element) {
      if (element.get() == this) {
        return true;
      }
      // The parent of an element that is :hover is also in that state.
      //  https://www.w3.org/TR/selectors4/#hover-pseudo
      element = element->parent_element();
    }
  }
  return false;
}

bool HTMLElement::CanBeDesignatedByPointerIfDisplayed() const {
  return computed_style()->pointer_events() != cssom::KeywordValue::GetNone() &&
         computed_style()->visibility() == cssom::KeywordValue::GetVisible();
}

void HTMLElement::UpdateUiNavigation() {
  ui_nav_needs_update_ = false;

  base::Optional<ui_navigation::NativeItemType> ui_nav_item_type;
  if (tabindex_ && *tabindex_ <= kUiNavFocusTabIndexThreshold &&
      computed_style()->pointer_events() != cssom::KeywordValue::GetNone()) {
    ui_nav_item_type = ui_navigation::kNativeItemTypeFocus;
  } else if (computed_style()->overflow() == cssom::KeywordValue::GetAuto() ||
             computed_style()->overflow() == cssom::KeywordValue::GetScroll()) {
    ui_nav_item_type = ui_navigation::kNativeItemTypeContainer;
  }

  if (ui_nav_item_type && IsDisplayed() && node_document()) {
    ui_navigation::NativeItemDir ui_nav_item_dir;
    ui_nav_item_dir.is_left_to_right =
        directionality() == kLeftToRightDirectionality;
    ui_nav_item_dir.is_top_to_bottom = true;

    if (ui_nav_item_) {
      if (ui_nav_item_->GetType() == *ui_nav_item_type) {
        // Keep using the existing navigation item.
        ui_nav_item_->SetDir(ui_nav_item_dir);
        return;
      }
      // The current navigation item isn't of the correct type. Disable it so
      // that callbacks won't be invoked for it. The object will be destroyed
      // when all references to it are released.
      ReleaseUiNavigationItem();
    }

    ui_nav_item_ = new ui_navigation::NavItem(
        *ui_nav_item_type,
        base::Bind(
            &UiNavCallbackHelper, base::ThreadTaskRunnerHandle::Get(),
            base::Bind(&HTMLElement::OnUiNavBlur, base::AsWeakPtr(this))),
        base::Bind(
            &UiNavCallbackHelper, base::ThreadTaskRunnerHandle::Get(),
            base::Bind(&HTMLElement::OnUiNavFocus, base::AsWeakPtr(this))),
        base::Bind(
            &UiNavCallbackHelper, base::ThreadTaskRunnerHandle::Get(),
            base::Bind(&HTMLElement::OnUiNavScroll, base::AsWeakPtr(this))));
    ui_nav_item_->SetDir(ui_nav_item_dir);
    if (ui_nav_focus_duration_) {
      ui_nav_item_->SetFocusDuration(*ui_nav_focus_duration_);
    }

    node_document()->AddUiNavigationElement(this);
    node_document()->set_ui_nav_needs_layout(true);
    InvalidateLayoutBoxRenderTreeNodes();
    if (layout_boxes_) {
      layout_boxes_->SetUiNavItem(ui_nav_item_);
    }
  } else if (ui_nav_item_) {
    // This navigation item is no longer relevant.
    ReleaseUiNavigationItem();
    InvalidateLayoutBoxRenderTreeNodes();
    if (layout_boxes_) {
      layout_boxes_->SetUiNavItem(ui_nav_item_);
    }
  }
}

void HTMLElement::ReleaseUiNavigationItem() {
  if (ui_nav_item_) {
    // Disable the UI navigation item so it won't receive anymore callbacks
    // while being released.
    if (node_document()) {
      node_document()->RemoveUiNavigationElement(this);
      node_document()->set_ui_nav_needs_layout(true);
      if (node_document()->ui_nav_focus_element() == this) {
        if (node_document()->TrySetUiNavFocusElement(
                nullptr, starboard::CurrentMonotonicTime())) {
          ui_nav_item_->UnfocusAll();
        }
      }
    }
    ui_nav_item_->SetEnabled(false);
    ui_nav_item_ = nullptr;
  }
}

void HTMLElement::ClearActiveBackgroundImages() {
  if (html_element_context() &&
      html_element_context()->animated_image_tracker()) {
    for (std::vector<GURL>::iterator it = active_background_images_.begin();
         it != active_background_images_.end(); ++it) {
      html_element_context()->animated_image_tracker()->DecreaseURLCount(*it);
    }
  }
  active_background_images_.clear();
}

void HTMLElement::ClearCachedBackgroundImages() {
  // |cached_background_images_.clear()| cannot be used as it may lead to crash
  // due to GetLoadTimingInfoAndCreateResourceTiming() being called indirectly
  // from CachedImage dtor, and GetLoadTimingInfoAndCreateResourceTiming() loops
  // on the |cached_background_images_| being cleared.
  //
  // To move and clear() like below is more straight-forward but leads to more
  // in flight image loading performance timings get lost.
  //   auto images = std::move(cached_background_images_);
  //   DCHECK(cached_background_images_.empty());
  //   images.clear();
  //
  // So images are moved out and cleared one by one.
  while (!cached_background_images_.empty()) {
    auto image = std::move(cached_background_images_.back());
    DCHECK(!cached_background_images_.back());
    cached_background_images_.pop_back();
    // TODO(b/265089478): This implementation will lose the performance timing
    // of |image|, consider refining to record all performance timings.
    image = nullptr;
  }
}

void HTMLElement::UpdateCachedBackgroundImagesFromComputedStyle() {
  ClearActiveBackgroundImages();

  // Don't fetch or cache the image if the display of this element is turned
  // off.
  if (computed_style()->display() != cssom::KeywordValue::GetNone()) {
    scoped_refptr<cssom::PropertyValue> background_image =
        computed_style()->background_image();

    cssom::PropertyListValue* property_list_value =
        base::polymorphic_downcast<cssom::PropertyListValue*>(
            background_image.get());

    loader::image::CachedImageReferenceVector cached_images;
    for (size_t i = 0; i < property_list_value->value().size(); ++i) {
      // Skip this image if it is not an absolute URL.
      if (property_list_value->value()[i]->GetTypeId() !=
          base::GetTypeId<cssom::AbsoluteURLValue>()) {
        continue;
      }

      // Skip invalid URL.
      GURL absolute_url = base::polymorphic_downcast<cssom::AbsoluteURLValue*>(
                              property_list_value->value()[i].get())
                              ->value();
      if (!absolute_url.is_valid()) {
        continue;
      }

      active_background_images_.push_back(absolute_url);
      html_element_context()->animated_image_tracker()->IncreaseURLCount(
          absolute_url);

      scoped_refptr<loader::image::CachedImage> cached_image =
          html_element_context()->image_cache()->GetOrCreateCachedResource(
              absolute_url, loader::Origin());
      base::Closure loaded_callback = base::Bind(
          &HTMLElement::OnBackgroundImageLoaded, base::Unretained(this));
      cached_images.emplace_back(
          new loader::image::CachedImageReferenceWithCallbacks(
              cached_image, loaded_callback, base::Closure()));
    }

    ClearCachedBackgroundImages();
    cached_background_images_ = std::move(cached_images);
  } else {
    // Clear the previous cached background image if the display is "none".
    ClearCachedBackgroundImages();
  }
}

void HTMLElement::GetLoadTimingInfoAndCreateResourceTiming() {
  if (html_element_context()->performance() == nullptr) return;
  for (auto& cached_background_image : cached_background_images_) {
    scoped_refptr<loader::CachedResourceBase> cached_image =
        cached_background_image->GetCachedResource();
    if (cached_image == nullptr) continue;

    if (!cached_image->get_resource_timing_created_flag()) {
      html_element_context()->performance()->CreatePerformanceResourceTiming(
          cached_image->GetLoadTimingInfo(),
          kPerformanceResourceTimingInitiatorType, cached_image->url().spec());
      cached_image->set_resource_timing_created_flag(true);
    }
  }
}

void HTMLElement::OnBackgroundImageLoaded() {
  node_document()->RecordMutation();
  InvalidateLayoutBoxRenderTreeNodes();
  // GetLoadTimingInfo from cached resource and create resource timing.
  GetLoadTimingInfoAndCreateResourceTiming();
}

}  // namespace dom
}  // namespace cobalt
