/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
 * All rights reserved.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/css/resolver/StyleResolver.h"

#include "core/CSSPropertyNames.h"
#include "core/HTMLNames.h"
#include "core/MediaTypeNames.h"
#include "core/StylePropertyShorthand.h"
#include "core/animation/AnimationTimeline.h"
#include "core/animation/ElementAnimations.h"
#include "core/animation/InterpolationEnvironment.h"
#include "core/animation/InvalidatableInterpolation.h"
#include "core/animation/KeyframeEffect.h"
#include "core/animation/StyleInterpolation.h"
#include "core/animation/animatable/AnimatableValue.h"
#include "core/animation/css/CSSAnimatableValueFactory.h"
#include "core/animation/css/CSSAnimations.h"
#include "core/css/CSSCalculationValue.h"
#include "core/css/CSSCustomIdentValue.h"
#include "core/css/CSSDefaultStyleSheets.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/CSSIdentifierValue.h"
#include "core/css/CSSKeyframeRule.h"
#include "core/css/CSSKeyframesRule.h"
#include "core/css/CSSReflectValue.h"
#include "core/css/CSSRuleList.h"
#include "core/css/CSSSelector.h"
#include "core/css/CSSStyleRule.h"
#include "core/css/CSSValueList.h"
#include "core/css/ElementRuleCollector.h"
#include "core/css/FontFace.h"
#include "core/css/MediaQueryEvaluator.h"
#include "core/css/PageRuleCollector.h"
#include "core/css/StylePropertySet.h"
#include "core/css/StyleRuleImport.h"
#include "core/css/StyleSheetContents.h"
#include "core/css/resolver/AnimatedStyleBuilder.h"
#include "core/css/resolver/CSSVariableResolver.h"
#include "core/css/resolver/MatchResult.h"
#include "core/css/resolver/MediaQueryResult.h"
#include "core/css/resolver/ScopedStyleResolver.h"
#include "core/css/resolver/SelectorFilterParentScope.h"
#include "core/css/resolver/SharedStyleFinder.h"
#include "core/css/resolver/StyleAdjuster.h"
#include "core/css/resolver/StyleResolverState.h"
#include "core/css/resolver/StyleResolverStats.h"
#include "core/css/resolver/ViewportStyleResolver.h"
#include "core/dom/CSSSelectorWatch.h"
#include "core/dom/FirstLetterPseudoElement.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLSlotElement.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/layout/GeneratedChildren.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/style/StyleInheritedVariables.h"
#include "core/svg/SVGDocumentExtensions.h"
#include "core/svg/SVGElement.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "wtf/StdLibExtras.h"

namespace {

using namespace blink;

void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element) {
  // If any changes to CSS Animations were detected, stash the update away for
  // application after the layout object is updated if we're in the appropriate
  // scope.
  if (!state.animationUpdate().isEmpty())
    element.ensureElementAnimations().cssAnimations().setPendingUpdate(
        state.animationUpdate());
}

// Returns whether any @apply rule sets a custom property
bool cacheCustomPropertiesForApplyAtRules(StyleResolverState& state,
                                          const MatchedPropertiesRange& range) {
  bool ruleSetsCustomProperty = false;
  // TODO(timloh): @apply should also work with properties registered as
  // non-inherited.
  if (!state.style()->inheritedVariables())
    return false;
  for (const auto& matchedProperties : range) {
    const StylePropertySet& properties = *matchedProperties.properties;
    unsigned propertyCount = properties.propertyCount();
    for (unsigned i = 0; i < propertyCount; ++i) {
      StylePropertySet::PropertyReference current = properties.propertyAt(i);
      if (current.id() != CSSPropertyApplyAtRule)
        continue;
      AtomicString name(toCSSCustomIdentValue(current.value()).value());
      CSSVariableData* variableData =
          state.style()->inheritedVariables()->getVariable(name);
      if (!variableData)
        continue;
      StylePropertySet* customPropertySet = variableData->propertySet();
      if (!customPropertySet)
        continue;
      if (customPropertySet->findPropertyIndex(CSSPropertyVariable) != -1)
        ruleSetsCustomProperty = true;
      state.setCustomPropertySetForApplyAtRule(name, customPropertySet);
    }
  }
  return ruleSetsCustomProperty;
}

}  // namespace

namespace blink {

using namespace HTMLNames;

ComputedStyle* StyleResolver::s_styleNotYetAvailable;

static StylePropertySet* leftToRightDeclaration() {
  DEFINE_STATIC_LOCAL(MutableStylePropertySet, leftToRightDecl,
                      (MutableStylePropertySet::create(HTMLQuirksMode)));
  if (leftToRightDecl.isEmpty())
    leftToRightDecl.setProperty(CSSPropertyDirection, CSSValueLtr);
  return &leftToRightDecl;
}

static StylePropertySet* rightToLeftDeclaration() {
  DEFINE_STATIC_LOCAL(MutableStylePropertySet, rightToLeftDecl,
                      (MutableStylePropertySet::create(HTMLQuirksMode)));
  if (rightToLeftDecl.isEmpty())
    rightToLeftDecl.setProperty(CSSPropertyDirection, CSSValueRtl);
  return &rightToLeftDecl;
}

static void collectScopedResolversForHostedShadowTrees(
    const Element& element,
    HeapVector<Member<ScopedStyleResolver>, 8>& resolvers) {
  ElementShadow* shadow = element.shadow();
  if (!shadow)
    return;

  // Adding scoped resolver for active shadow roots for shadow host styling.
  for (ShadowRoot* shadowRoot = &shadow->youngestShadowRoot(); shadowRoot;
       shadowRoot = shadowRoot->olderShadowRoot()) {
    if (shadowRoot->numberOfStyles() > 0) {
      if (ScopedStyleResolver* resolver = shadowRoot->scopedStyleResolver())
        resolvers.append(resolver);
    }
  }
}

StyleResolver::StyleResolver(Document& document)
    : m_document(document),
      m_viewportStyleResolver(ViewportStyleResolver::create(document)),
      m_needCollectFeatures(false),
      m_printMediaType(false),
      m_styleSharingDepth(0) {
  FrameView* view = document.view();
  if (view) {
    m_medium = new MediaQueryEvaluator(&view->frame());
    m_printMediaType =
        equalIgnoringCase(view->mediaType(), MediaTypeNames::print);
  } else {
    m_medium = new MediaQueryEvaluator("all");
  }

  initWatchedSelectorRules();
}

StyleResolver::~StyleResolver() {}

void StyleResolver::dispose() {
  m_matchedPropertiesCache.clear();
}

void StyleResolver::initWatchedSelectorRules() {
  m_watchedSelectorsRules = nullptr;
  CSSSelectorWatch* watch = CSSSelectorWatch::fromIfExists(*m_document);
  if (!watch)
    return;
  const HeapVector<Member<StyleRule>>& watchedSelectors =
      watch->watchedCallbackSelectors();
  if (!watchedSelectors.size())
    return;
  m_watchedSelectorsRules = RuleSet::create();
  for (unsigned i = 0; i < watchedSelectors.size(); ++i)
    m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(),
                                          RuleHasNoSpecialState);
}

void StyleResolver::lazyAppendAuthorStyleSheets(
    unsigned firstNew,
    const HeapVector<Member<CSSStyleSheet>>& styleSheets) {
  unsigned size = styleSheets.size();
  for (unsigned i = firstNew; i < size; ++i)
    m_pendingStyleSheets.add(styleSheets[i].get());
}

void StyleResolver::removePendingAuthorStyleSheets(
    const HeapVector<Member<CSSStyleSheet>>& styleSheets) {
  for (unsigned i = 0; i < styleSheets.size(); ++i)
    m_pendingStyleSheets.remove(styleSheets[i].get());
}

void StyleResolver::appendCSSStyleSheet(CSSStyleSheet& cssSheet) {
  DCHECK(!cssSheet.disabled());
  DCHECK(cssSheet.ownerDocument());
  DCHECK(cssSheet.ownerNode());
  DCHECK(isHTMLStyleElement(cssSheet.ownerNode()) ||
         isSVGStyleElement(cssSheet.ownerNode()) ||
         cssSheet.ownerNode()->isConnected());

  if (cssSheet.mediaQueries() &&
      !m_medium->eval(cssSheet.mediaQueries(),
                      &m_viewportDependentMediaQueryResults,
                      &m_deviceDependentMediaQueryResults))
    return;

  TreeScope* treeScope = &cssSheet.ownerNode()->treeScope();
  // TODO(rune@opera.com): This is a workaround for crbug.com/559292
  // when we're in the middle of removing a subtree with a style element
  // and the treescope has been changed but inDocument and isInShadowTree
  // are not.
  //
  // This check can be removed when crbug.com/567021 is fixed.
  if (cssSheet.ownerNode()->isInShadowTree() &&
      treeScope->rootNode().isDocumentNode())
    return;

  // Sheets in the document scope of HTML imports apply to the main document
  // (m_document), so we override it for all document scoped sheets.
  if (treeScope->rootNode().isDocumentNode())
    treeScope = m_document;
  treeScope->ensureScopedStyleResolver().appendCSSStyleSheet(cssSheet,
                                                             *m_medium);
}

void StyleResolver::appendPendingAuthorStyleSheets() {
  for (const auto& styleSheet : m_pendingStyleSheets)
    appendCSSStyleSheet(*styleSheet);

  m_pendingStyleSheets.clear();
  finishAppendAuthorStyleSheets();
}

void StyleResolver::appendAuthorStyleSheets(
    const HeapVector<Member<CSSStyleSheet>>& styleSheets) {
  // This handles sheets added to the end of the stylesheet list only. In other
  // cases the style resolver needs to be reconstructed. To handle insertions
  // too the rule order numbers would need to be updated.
  for (const auto& styleSheet : styleSheets)
    appendCSSStyleSheet(*styleSheet);
}

void StyleResolver::finishAppendAuthorStyleSheets() {
  collectFeatures();

  if (!document().layoutViewItem().isNull() &&
      document().layoutViewItem().style())
    document().layoutViewItem().style()->font().update(
        document().styleEngine().fontSelector());

  m_viewportStyleResolver->collectViewportRules();

  document().styleEngine().resetCSSFeatureFlags(m_features);
}

void StyleResolver::resetRuleFeatures() {
  // Need to recreate RuleFeatureSet.
  m_features.clear();
  m_siblingRuleSet.clear();
  m_uncommonAttributeRuleSet.clear();
  m_needCollectFeatures = true;
}

void StyleResolver::addTreeBoundaryCrossingScope(ContainerNode& scope) {
  m_treeBoundaryCrossingScopes.add(&scope);
}

void StyleResolver::resetAuthorStyle(TreeScope& treeScope) {
  m_treeBoundaryCrossingScopes.remove(&treeScope.rootNode());

  ScopedStyleResolver* resolver = treeScope.scopedStyleResolver();
  if (!resolver)
    return;

  resetRuleFeatures();

  if (treeScope.rootNode().isDocumentNode()) {
    resolver->resetAuthorStyle();
    return;
  }

  // resolver is going to be freed below.
  treeScope.clearScopedStyleResolver();
}

static RuleSet* makeRuleSet(const HeapVector<RuleFeature>& rules) {
  size_t size = rules.size();
  if (!size)
    return nullptr;
  RuleSet* ruleSet = RuleSet::create();
  for (size_t i = 0; i < size; ++i)
    ruleSet->addRule(rules[i].rule, rules[i].selectorIndex,
                     rules[i].hasDocumentSecurityOrigin
                         ? RuleHasDocumentSecurityOrigin
                         : RuleHasNoSpecialState);
  return ruleSet;
}

void StyleResolver::collectFeatures() {
  m_features.clear();
  // Collect all ids and rules using sibling selectors (:first-child and
  // similar) in the current set of stylesheets. Style sharing code uses this
  // information to reject sharing candidates.
  CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
  if (defaultStyleSheets.defaultStyle()) {
    m_features.add(defaultStyleSheets.defaultStyle()->features());
    m_hasFullscreenUAStyle = defaultStyleSheets.fullscreenStyleSheet();
  }

  if (document().isViewSource())
    m_features.add(defaultStyleSheets.defaultViewSourceStyle()->features());

  if (m_watchedSelectorsRules)
    m_features.add(m_watchedSelectorsRules->features());

  document().styleEngine().collectScopedStyleFeaturesTo(m_features);

  m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
  m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
  m_needCollectFeatures = false;
}

bool StyleResolver::hasRulesForId(const AtomicString& id) const {
  return m_features.hasSelectorForId(id);
}

void StyleResolver::addToStyleSharingList(Element& element) {
  ASSERT(RuntimeEnabledFeatures::styleSharingEnabled());
  // Never add elements to the style sharing list if we're not in a recalcStyle,
  // otherwise we could leave stale pointers in there.
  if (!document().inStyleRecalc())
    return;
  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), sharedStyleCandidates,
                                1);
  StyleSharingList& list = styleSharingList();
  if (list.size() >= styleSharingListSize)
    list.removeLast();
  list.prepend(&element);
}

StyleSharingList& StyleResolver::styleSharingList() {
  m_styleSharingLists.resize(styleSharingMaxDepth);

  // We never put things at depth 0 into the list since that's only the <html>
  // element and it has no siblings or cousins to share with.
  unsigned depth =
      std::max(std::min(m_styleSharingDepth, styleSharingMaxDepth), 1u) - 1u;

  if (!m_styleSharingLists[depth])
    m_styleSharingLists[depth] = new StyleSharingList;
  return *m_styleSharingLists[depth];
}

void StyleResolver::clearStyleSharingList() {
  m_styleSharingLists.resize(0);
}

static inline ScopedStyleResolver* scopedResolverFor(const Element& element) {
  // Ideally, returning element->treeScope().scopedStyleResolver() should be
  // enough, but ::cue and custom pseudo elements like ::-webkit-meter-bar
  // pierce through a shadow dom boundary, yet they are not part of
  // m_treeBoundaryCrossingScopes.  The assumption here is that these rules only
  // pierce through one boundary and that the scope of these elements do not
  // have a style resolver due to the fact that VTT scopes and UA shadow trees
  // don't have <style> elements. This is backed up by the ASSERTs below.
  //
  // FIXME: Make ::cue and custom pseudo elements part of boundary crossing
  // rules when moving those rules to ScopedStyleResolver as part of issue
  // 401359.

  TreeScope* treeScope = &element.treeScope();
  if (ScopedStyleResolver* resolver = treeScope->scopedStyleResolver()) {
    ASSERT(element.shadowPseudoId().isEmpty());
    ASSERT(!element.isVTTElement());
    return resolver;
  }

  treeScope = treeScope->parentTreeScope();
  if (!treeScope)
    return nullptr;
  if (element.shadowPseudoId().isEmpty() && !element.isVTTElement())
    return nullptr;
  return treeScope->scopedStyleResolver();
}

static void matchHostRules(const Element& element,
                           ElementRuleCollector& collector) {
  ElementShadow* shadow = element.shadow();
  if (!shadow)
    return;

  for (ShadowRoot* shadowRoot = &shadow->oldestShadowRoot(); shadowRoot;
       shadowRoot = shadowRoot->youngerShadowRoot()) {
    if (!shadowRoot->numberOfStyles())
      continue;
    if (ScopedStyleResolver* resolver = shadowRoot->scopedStyleResolver()) {
      collector.clearMatchedRules();
      resolver->collectMatchingShadowHostRules(collector);
      collector.sortAndTransferMatchedRules();
      collector.finishAddingAuthorRulesForTreeScope();
    }
  }
}

static void matchSlottedRules(const Element& element,
                              ElementRuleCollector& collector) {
  HTMLSlotElement* slot = element.assignedSlot();
  if (!slot)
    return;

  HeapVector<Member<ScopedStyleResolver>> resolvers;
  for (; slot; slot = slot->assignedSlot()) {
    if (ScopedStyleResolver* resolver = slot->treeScope().scopedStyleResolver())
      resolvers.append(resolver);
  }
  for (auto it = resolvers.rbegin(); it != resolvers.rend(); ++it) {
    collector.clearMatchedRules();
    (*it)->collectMatchingTreeBoundaryCrossingRules(collector);
    collector.sortAndTransferMatchedRules();
    collector.finishAddingAuthorRulesForTreeScope();
  }
}

static void matchElementScopeRules(const Element& element,
                                   ScopedStyleResolver* elementScopeResolver,
                                   ElementRuleCollector& collector) {
  if (elementScopeResolver) {
    collector.clearMatchedRules();
    elementScopeResolver->collectMatchingAuthorRules(collector);
    elementScopeResolver->collectMatchingTreeBoundaryCrossingRules(collector);
    collector.sortAndTransferMatchedRules();
  }

  if (element.isStyledElement() && element.inlineStyle() &&
      !collector.isCollectingForPseudoElement()) {
    // Inline style is immutable as long as there is no CSSOM wrapper.
    bool isInlineStyleCacheable = !element.inlineStyle()->isMutable();
    collector.addElementStyleProperties(element.inlineStyle(),
                                        isInlineStyleCacheable);
  }

  collector.finishAddingAuthorRulesForTreeScope();
}

static bool shouldCheckScope(const Element& element,
                             const Node& scopingNode,
                             bool isInnerTreeScope) {
  if (isInnerTreeScope && element.treeScope() != scopingNode.treeScope()) {
    // Check if |element| may be affected by a ::content rule in |scopingNode|'s
    // style.  If |element| is a descendant of a shadow host which is ancestral
    // to |scopingNode|, the |element| should be included for rule collection.
    // Skip otherwise.
    const TreeScope* scope = &scopingNode.treeScope();
    while (scope && scope->parentTreeScope() != &element.treeScope())
      scope = scope->parentTreeScope();
    Element* shadowHost = scope ? scope->rootNode().ownerShadowHost() : nullptr;
    return shadowHost && element.isDescendantOf(shadowHost);
  }

  // When |element| can be distributed to |scopingNode| via <shadow>, ::content
  // rule can match, thus the case should be included.
  if (!isInnerTreeScope &&
      scopingNode.parentOrShadowHostNode() ==
          element.treeScope().rootNode().parentOrShadowHostNode())
    return true;

  // Obviously cases when ancestor scope has /deep/ or ::shadow rule should be
  // included.  Skip otherwise.
  return scopingNode.treeScope()
      .scopedStyleResolver()
      ->hasDeepOrShadowSelector();
}

void StyleResolver::matchScopedRules(const Element& element,
                                     ElementRuleCollector& collector) {
  // Match rules from treeScopes in the reverse tree-of-trees order, since the
  // cascading order for normal rules is such that when comparing rules from
  // different shadow trees, the rule from the tree which comes first in the
  // tree-of-trees order wins. From other treeScopes than the element's own
  // scope, only tree-boundary-crossing rules may match.

  ScopedStyleResolver* elementScopeResolver = scopedResolverFor(element);

  if (!document().mayContainV0Shadow()) {
    matchSlottedRules(element, collector);
    matchElementScopeRules(element, elementScopeResolver, collector);
    return;
  }

  bool matchElementScopeDone = !elementScopeResolver && !element.inlineStyle();

  for (auto it = m_treeBoundaryCrossingScopes.rbegin();
       it != m_treeBoundaryCrossingScopes.rend(); ++it) {
    const TreeScope& scope = (*it)->containingTreeScope();
    ScopedStyleResolver* resolver = scope.scopedStyleResolver();
    ASSERT(resolver);

    bool isInnerTreeScope =
        element.containingTreeScope().isInclusiveAncestorOf(scope);
    if (!shouldCheckScope(element, **it, isInnerTreeScope))
      continue;

    if (!matchElementScopeDone &&
        scope.isInclusiveAncestorOf(element.containingTreeScope())) {
      matchElementScopeDone = true;

      // At this point, the iterator has either encountered the scope for the
      // element itself (if that scope has boundary-crossing rules), or the
      // iterator has moved to a scope which appears before the element's scope
      // in the tree-of-trees order.  Try to match all rules from the element's
      // scope.

      matchElementScopeRules(element, elementScopeResolver, collector);
      if (resolver == elementScopeResolver) {
        // Boundary-crossing rules already collected in matchElementScopeRules.
        continue;
      }
    }

    collector.clearMatchedRules();
    resolver->collectMatchingTreeBoundaryCrossingRules(collector);
    collector.sortAndTransferMatchedRules();
    collector.finishAddingAuthorRulesForTreeScope();
  }

  if (!matchElementScopeDone)
    matchElementScopeRules(element, elementScopeResolver, collector);
}

void StyleResolver::matchAuthorRules(const Element& element,
                                     ElementRuleCollector& collector) {
  if (document().shadowCascadeOrder() != ShadowCascadeOrder::ShadowCascadeV1) {
    matchAuthorRulesV0(element, collector);
    return;
  }

  ASSERT(RuntimeEnabledFeatures::shadowDOMV1Enabled());
  matchHostRules(element, collector);
  matchScopedRules(element, collector);
}

void StyleResolver::matchAuthorRulesV0(const Element& element,
                                       ElementRuleCollector& collector) {
  collector.clearMatchedRules();

  CascadeOrder cascadeOrder = 0;
  HeapVector<Member<ScopedStyleResolver>, 8> resolversInShadowTree;
  collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree);

  // Apply :host and :host-context rules from inner scopes.
  for (int j = resolversInShadowTree.size() - 1; j >= 0; --j)
    resolversInShadowTree.at(j)->collectMatchingShadowHostRules(collector,
                                                                ++cascadeOrder);

  // Apply normal rules from element scope.
  if (ScopedStyleResolver* resolver = scopedResolverFor(element))
    resolver->collectMatchingAuthorRules(collector, ++cascadeOrder);

  // Apply /deep/ and ::shadow rules from outer scopes, and ::content from
  // inner.
  collectTreeBoundaryCrossingRules(element, collector);
  collector.sortAndTransferMatchedRules();
}

void StyleResolver::matchUARules(ElementRuleCollector& collector) {
  collector.setMatchingUARules(true);

  CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
  RuleSet* userAgentStyleSheet = m_printMediaType
                                     ? defaultStyleSheets.defaultPrintStyle()
                                     : defaultStyleSheets.defaultStyle();
  matchRuleSet(collector, userAgentStyleSheet);

  // In quirks mode, we match rules from the quirks user agent sheet.
  if (document().inQuirksMode())
    matchRuleSet(collector, defaultStyleSheets.defaultQuirksStyle());

  // If document uses view source styles (in view source mode or in xml viewer
  // mode), then we match rules from the view source style sheet.
  if (document().isViewSource())
    matchRuleSet(collector, defaultStyleSheets.defaultViewSourceStyle());

  collector.finishAddingUARules();
  collector.setMatchingUARules(false);
}

void StyleResolver::matchRuleSet(ElementRuleCollector& collector,
                                 RuleSet* rules) {
  collector.clearMatchedRules();
  collector.collectMatchingRules(MatchRequest(rules));
  collector.sortAndTransferMatchedRules();
}

void StyleResolver::matchAllRules(StyleResolverState& state,
                                  ElementRuleCollector& collector,
                                  bool includeSMILProperties) {
  matchUARules(collector);

  // Now check author rules, beginning first with presentational attributes
  // mapped from HTML.
  if (state.element()->isStyledElement()) {
    collector.addElementStyleProperties(
        state.element()->presentationAttributeStyle());

    // Now we check additional mapped declarations.
    // Tables and table cells share an additional mapped rule that must be
    // applied after all attributes, since their mapped style depends on the
    // values of multiple attributes.
    collector.addElementStyleProperties(
        state.element()->additionalPresentationAttributeStyle());

    if (state.element()->isHTMLElement()) {
      bool isAuto;
      TextDirection textDirection =
          toHTMLElement(state.element())
              ->directionalityIfhasDirAutoAttribute(isAuto);
      if (isAuto) {
        state.setHasDirAutoAttribute(true);
        collector.addElementStyleProperties(textDirection == LTR
                                                ? leftToRightDeclaration()
                                                : rightToLeftDeclaration());
      }
    }
  }

  matchAuthorRules(*state.element(), collector);

  if (state.element()->isStyledElement()) {
    // For Shadow DOM V1, inline style is already collected in
    // matchScopedRules().
    if (document().shadowCascadeOrder() !=
            ShadowCascadeOrder::ShadowCascadeV1 &&
        state.element()->inlineStyle()) {
      // Inline style is immutable as long as there is no CSSOM wrapper.
      bool isInlineStyleCacheable =
          !state.element()->inlineStyle()->isMutable();
      collector.addElementStyleProperties(state.element()->inlineStyle(),
                                          isInlineStyleCacheable);
    }

    // Now check SMIL animation override style.
    if (includeSMILProperties && state.element()->isSVGElement())
      collector.addElementStyleProperties(
          toSVGElement(state.element())->animatedSMILStyleProperties(),
          false /* isCacheable */);
  }

  collector.finishAddingAuthorRulesForTreeScope();
}

void StyleResolver::collectTreeBoundaryCrossingRules(
    const Element& element,
    ElementRuleCollector& collector) {
  if (m_treeBoundaryCrossingScopes.isEmpty())
    return;

  // When comparing rules declared in outer treescopes, outer's rules win.
  CascadeOrder outerCascadeOrder = m_treeBoundaryCrossingScopes.size() * 2;
  // When comparing rules declared in inner treescopes, inner's rules win.
  CascadeOrder innerCascadeOrder = m_treeBoundaryCrossingScopes.size();

  for (const auto& scopingNode : m_treeBoundaryCrossingScopes) {
    // Skip rule collection for element when tree boundary crossing rules of
    // scopingNode's scope can never apply to it.
    bool isInnerTreeScope = element.containingTreeScope().isInclusiveAncestorOf(
        scopingNode->containingTreeScope());
    if (!shouldCheckScope(element, *scopingNode, isInnerTreeScope))
      continue;

    CascadeOrder cascadeOrder =
        isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder;
    scopingNode->treeScope()
        .scopedStyleResolver()
        ->collectMatchingTreeBoundaryCrossingRules(collector, cascadeOrder);

    ++innerCascadeOrder;
    --outerCascadeOrder;
  }
}

PassRefPtr<ComputedStyle> StyleResolver::styleForDocument(Document& document) {
  const LocalFrame* frame = document.frame();

  RefPtr<ComputedStyle> documentStyle = ComputedStyle::create();
  documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder
                                                           : LogicalOrder);
  documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor()
                                                       : 1);
  FontDescription documentFontDescription = documentStyle->getFontDescription();
  documentFontDescription.setLocale(
      LayoutLocale::get(document.contentLanguage()));
  documentStyle->setFontDescription(documentFontDescription);
  documentStyle->setZIndex(0);
  documentStyle->setIsStackingContext(true);
  documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE
                                                       : READ_ONLY);
  // These are designed to match the user-agent stylesheet values for the
  // document element so that the common case doesn't need to create a new
  // ComputedStyle in Document::inheritHtmlAndBodyElementStyles.
  documentStyle->setDisplay(EDisplay::Block);
  documentStyle->setPosition(AbsolutePosition);

  document.setupFontBuilder(*documentStyle);

  return documentStyle.release();
}

void StyleResolver::adjustComputedStyle(StyleResolverState& state,
                                        Element* element) {
  StyleAdjuster::adjustComputedStyle(state.mutableStyleRef(),
                                     *state.parentStyle(), element);
}

// Start loading resources referenced by this style.
void StyleResolver::loadPendingResources(StyleResolverState& state) {
  state.elementStyleResources().loadPendingResources(state.style());
}

PassRefPtr<ComputedStyle> StyleResolver::styleForElement(
    Element* element,
    const ComputedStyle* defaultParent,
    StyleSharingBehavior sharingBehavior,
    RuleMatchingBehavior matchingBehavior) {
  DCHECK(document().frame());
  ASSERT(document().settings());
  ASSERT(!hasPendingAuthorStyleSheets());
  ASSERT(!m_needCollectFeatures);

  // Once an element has a layoutObject, we don't try to destroy it, since
  // otherwise the layoutObject will vanish if a style recalc happens during
  // loading.
  if (sharingBehavior == AllowStyleSharing && !document().isRenderingReady() &&
      !element->layoutObject()) {
    if (!s_styleNotYetAvailable) {
      s_styleNotYetAvailable = ComputedStyle::create().leakRef();
      s_styleNotYetAvailable->setDisplay(EDisplay::None);
      s_styleNotYetAvailable->font().update(
          document().styleEngine().fontSelector());
    }

    document().setHasNodesWithPlaceholderStyle();
    return s_styleNotYetAvailable;
  }

  document().styleEngine().incStyleForElementCount();
  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), elementsStyled, 1);

  SelectorFilterParentScope::ensureParentStackIsPushed();

  ElementResolveContext elementContext(*element);

  if (RuntimeEnabledFeatures::styleSharingEnabled() &&
      sharingBehavior == AllowStyleSharing &&
      (defaultParent || elementContext.parentStyle())) {
    SharedStyleFinder styleFinder(elementContext, m_features,
                                  m_siblingRuleSet.get(),
                                  m_uncommonAttributeRuleSet.get(), *this);
    if (RefPtr<ComputedStyle> sharedStyle = styleFinder.findSharedStyle())
      return sharedStyle.release();
  }

  StyleResolverState state(document(), elementContext, defaultParent);

  ElementAnimations* elementAnimations = element->elementAnimations();
  const ComputedStyle* baseComputedStyle =
      elementAnimations ? elementAnimations->baseComputedStyle() : nullptr;

  if (baseComputedStyle) {
    state.setStyle(ComputedStyle::clone(*baseComputedStyle));
    if (!state.parentStyle())
      state.setParentStyle(initialStyleForElement());
  } else {
    if (state.parentStyle()) {
      RefPtr<ComputedStyle> style = ComputedStyle::create();
      style->inheritFrom(*state.parentStyle(),
                         isAtShadowBoundary(element)
                             ? ComputedStyleBase::AtShadowBoundary
                             : ComputedStyleBase::NotAtShadowBoundary);
      state.setStyle(style.release());
    } else {
      state.setStyle(initialStyleForElement());
      state.setParentStyle(ComputedStyle::clone(*state.style()));
    }
  }

  // contenteditable attribute (implemented by -webkit-user-modify) should
  // be propagated from shadow host to distributed node.
  if (state.distributedToInsertionPoint()) {
    if (Element* parent = element->parentElement()) {
      if (ComputedStyle* styleOfShadowHost = parent->mutableComputedStyle())
        state.style()->setUserModify(styleOfShadowHost->userModify());
    }
  }

  if (element->isLink()) {
    state.style()->setIsLink(true);
    EInsideLink linkState = state.elementLinkState();
    if (linkState != NotInsideLink) {
      bool forceVisited = InspectorInstrumentation::forcePseudoState(
          element, CSSSelector::PseudoVisited);
      if (forceVisited)
        linkState = InsideVisitedLink;
    }
    state.style()->setInsideLink(linkState);
  }

  if (!baseComputedStyle) {
    bool needsCollection = false;
    CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(
        *element, needsCollection);
    if (needsCollection)
      collectFeatures();

    ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                   state.style());

    matchAllRules(state, collector,
                  matchingBehavior != MatchAllRulesExcludingSMIL);

    // TODO(dominicc): Remove this counter when Issue 590014 is fixed.
    if (element->hasTagName(HTMLNames::summaryTag)) {
      MatchedPropertiesRange properties =
          collector.matchedResult().authorRules();
      for (auto it = properties.begin(); it != properties.end(); ++it) {
        const CSSValue* value =
            it->properties->getPropertyCSSValue(CSSPropertyDisplay);
        if (value && value->isIdentifierValue() &&
            toCSSIdentifierValue(*value).getValueID() == CSSValueBlock)
          UseCounter::count(
              element->document(),
              UseCounter::SummaryElementWithDisplayBlockAuthorRule);
      }
    }

    if (element->computedStyle() &&
        element->computedStyle()->textAutosizingMultiplier() !=
            state.style()->textAutosizingMultiplier()) {
      // Preserve the text autosizing multiplier on style recalc. Autosizer will
      // update it during layout if needed.
      // NOTE: this must occur before applyMatchedProperties for correct
      // computation of font-relative lengths.
      state.style()->setTextAutosizingMultiplier(
          element->computedStyle()->textAutosizingMultiplier());
      state.style()->setUnique();
    }

    if (state.hasDirAutoAttribute())
      state.style()->setSelfOrAncestorHasDirAutoAttribute(true);

    applyMatchedProperties(state, collector.matchedResult());
    applyCallbackSelectors(state);

    // Cache our original display.
    state.style()->setOriginalDisplay(state.style()->display());

    adjustComputedStyle(state, element);

    if (elementAnimations)
      elementAnimations->updateBaseComputedStyle(state.style());
  } else {
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), baseStylesUsed, 1);
  }

  // FIXME: The CSSWG wants to specify that the effects of animations are
  // applied before important rules, but this currently happens here as we
  // require adjustment to have happened before deciding which properties to
  // transition.
  if (applyAnimatedProperties(state, element)) {
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), stylesAnimated, 1);
    adjustComputedStyle(state, element);
  }

  if (isHTMLBodyElement(*element))
    document().textLinkColors().setTextColor(state.style()->color());

  setAnimationUpdateIfNeeded(state, *element);

  if (state.style()->hasViewportUnits())
    document().setHasViewportUnits();

  if (state.style()->hasRemUnits())
    document().styleEngine().setUsesRemUnit(true);

  // Now return the style.
  return state.takeStyle();
}

// TODO(alancutter): Create compositor keyframe values directly instead of
// intermediate AnimatableValues.
PassRefPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(
    Element& element,
    const ComputedStyle& baseStyle,
    const ComputedStyle* parentStyle,
    CSSPropertyID property,
    const CSSValue* value) {
  // TODO(alancutter): Avoid creating a StyleResolverState just to apply a
  // single value on a ComputedStyle.
  StyleResolverState state(element.document(), &element, parentStyle);
  state.setStyle(ComputedStyle::clone(baseStyle));
  if (value) {
    StyleBuilder::applyProperty(property, state, *value);
    state.fontBuilder().createFont(
        state.document().styleEngine().fontSelector(), state.mutableStyleRef());
  }
  return CSSAnimatableValueFactory::create(property, *state.style());
}

PseudoElement* StyleResolver::createPseudoElement(Element* parent,
                                                  PseudoId pseudoId) {
  if (pseudoId == PseudoIdFirstLetter)
    return FirstLetterPseudoElement::create(parent);
  return PseudoElement::create(parent, pseudoId);
}

PseudoElement* StyleResolver::createPseudoElementIfNeeded(Element& parent,
                                                          PseudoId pseudoId) {
  LayoutObject* parentLayoutObject = parent.layoutObject();
  if (!parentLayoutObject)
    return nullptr;

  // The first letter pseudo element has to look up the tree and see if any
  // of the ancestors are first letter.
  if (pseudoId < FirstInternalPseudoId && pseudoId != PseudoIdFirstLetter &&
      !parentLayoutObject->style()->hasPseudoStyle(pseudoId))
    return nullptr;

  if (pseudoId == PseudoIdBackdrop && !parent.isInTopLayer())
    return nullptr;

  if (pseudoId == PseudoIdFirstLetter &&
      (parent.isSVGElement() ||
       !FirstLetterPseudoElement::firstLetterTextLayoutObject(parent)))
    return nullptr;

  if (!canHaveGeneratedChildren(*parentLayoutObject))
    return nullptr;

  ComputedStyle* parentStyle = parentLayoutObject->mutableStyle();
  if (ComputedStyle* cachedStyle =
          parentStyle->getCachedPseudoStyle(pseudoId)) {
    if (!pseudoElementLayoutObjectIsNeeded(cachedStyle))
      return nullptr;
    return createPseudoElement(&parent, pseudoId);
  }

  StyleResolverState state(document(), &parent, parentStyle);
  if (!pseudoStyleForElementInternal(parent, pseudoId, parentStyle, state))
    return nullptr;
  RefPtr<ComputedStyle> style = state.takeStyle();
  ASSERT(style);
  parentStyle->addCachedPseudoStyle(style);

  if (!pseudoElementLayoutObjectIsNeeded(style.get()))
    return nullptr;

  PseudoElement* pseudo = createPseudoElement(&parent, pseudoId);

  setAnimationUpdateIfNeeded(state, *pseudo);
  if (ElementAnimations* elementAnimations = pseudo->elementAnimations())
    elementAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo);
  return pseudo;
}

bool StyleResolver::pseudoStyleForElementInternal(
    Element& element,
    const PseudoStyleRequest& pseudoStyleRequest,
    const ComputedStyle* parentStyle,
    StyleResolverState& state) {
  ASSERT(document().frame());
  ASSERT(document().settings());
  ASSERT(pseudoStyleRequest.pseudoId != PseudoIdFirstLineInherited);
  ASSERT(state.parentStyle());

  SelectorFilterParentScope::ensureParentStackIsPushed();

  Element* pseudoElement = element.pseudoElement(pseudoStyleRequest.pseudoId);

  ElementAnimations* elementAnimations =
      pseudoElement ? pseudoElement->elementAnimations() : nullptr;
  const ComputedStyle* baseComputedStyle =
      elementAnimations ? elementAnimations->baseComputedStyle() : nullptr;

  if (baseComputedStyle) {
    state.setStyle(ComputedStyle::clone(*baseComputedStyle));
  } else if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
    RefPtr<ComputedStyle> style = ComputedStyle::create();
    style->inheritFrom(*state.parentStyle());
    state.setStyle(style.release());
  } else {
    state.setStyle(initialStyleForElement());
    state.setParentStyle(ComputedStyle::clone(*state.style()));
  }

  state.style()->setStyleType(pseudoStyleRequest.pseudoId);

  // Since we don't use pseudo-elements in any of our quirk/print
  // user agent rules, don't waste time walking those rules.

  if (!baseComputedStyle) {
    // Check UA, user and author rules.
    ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                   state.style());
    collector.setPseudoStyleRequest(pseudoStyleRequest);

    matchUARules(collector);
    matchAuthorRules(*state.element(), collector);
    collector.finishAddingAuthorRulesForTreeScope();

    if (!collector.matchedResult().hasMatchedProperties())
      return false;

    applyMatchedProperties(state, collector.matchedResult());
    applyCallbackSelectors(state);

    // Cache our original display.
    state.style()->setOriginalDisplay(state.style()->display());

    // FIXME: Passing 0 as the Element* introduces a lot of complexity
    // in the adjustComputedStyle code.
    adjustComputedStyle(state, 0);

    if (elementAnimations)
      elementAnimations->updateBaseComputedStyle(state.style());
  }

  // FIXME: The CSSWG wants to specify that the effects of animations are
  // applied before important rules, but this currently happens here as we
  // require adjustment to have happened before deciding which properties to
  // transition.
  if (applyAnimatedProperties(state, pseudoElement))
    adjustComputedStyle(state, 0);

  document().styleEngine().incStyleForElementCount();
  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), pseudoElementsStyled,
                                1);

  if (state.style()->hasViewportUnits())
    document().setHasViewportUnits();

  return true;
}

PassRefPtr<ComputedStyle> StyleResolver::pseudoStyleForElement(
    Element* element,
    const PseudoStyleRequest& pseudoStyleRequest,
    const ComputedStyle* parentStyle) {
  ASSERT(parentStyle);
  if (!element)
    return nullptr;

  StyleResolverState state(document(), element, parentStyle);
  if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle,
                                     state)) {
    if (pseudoStyleRequest.type == PseudoStyleRequest::ForRenderer)
      return nullptr;
    return state.takeStyle();
  }

  if (PseudoElement* pseudoElement =
          element->pseudoElement(pseudoStyleRequest.pseudoId))
    setAnimationUpdateIfNeeded(state, *pseudoElement);

  // Now return the style.
  return state.takeStyle();
}

PassRefPtr<ComputedStyle> StyleResolver::styleForPage(int pageIndex) {
  ASSERT(!hasPendingAuthorStyleSheets());
  // m_rootElementStyle will be set to the document style.
  StyleResolverState state(document(), document().documentElement());

  RefPtr<ComputedStyle> style = ComputedStyle::create();
  const ComputedStyle* rootElementStyle = state.rootElementStyle()
                                              ? state.rootElementStyle()
                                              : document().computedStyle();
  ASSERT(rootElementStyle);
  style->inheritFrom(*rootElementStyle);
  state.setStyle(style.release());

  PageRuleCollector collector(rootElementStyle, pageIndex);

  collector.matchPageRules(
      CSSDefaultStyleSheets::instance().defaultPrintStyle());

  if (ScopedStyleResolver* scopedResolver = document().scopedStyleResolver())
    scopedResolver->matchPageRules(collector);

  bool inheritedOnly = false;

  const MatchResult& result = collector.matchedResult();
  applyMatchedProperties<HighPropertyPriority>(state, result.allRules(), false,
                                               inheritedOnly);

  // If our font got dirtied, go ahead and update it now.
  updateFont(state);

  applyMatchedProperties<LowPropertyPriority>(state, result.allRules(), false,
                                              inheritedOnly);

  loadPendingResources(state);

  // Now return the style.
  return state.takeStyle();
}

PassRefPtr<ComputedStyle> StyleResolver::initialStyleForElement() {
  RefPtr<ComputedStyle> style = ComputedStyle::create();
  FontBuilder fontBuilder(document());
  fontBuilder.setInitial(style->effectiveZoom());
  fontBuilder.createFont(document().styleEngine().fontSelector(), *style);
  return style.release();
}

PassRefPtr<ComputedStyle> StyleResolver::styleForText(Text* textNode) {
  ASSERT(textNode);

  Node* parentNode = LayoutTreeBuilderTraversal::parent(*textNode);
  if (!parentNode || !parentNode->computedStyle())
    return initialStyleForElement();
  return parentNode->mutableComputedStyle();
}

void StyleResolver::updateFont(StyleResolverState& state) {
  state.fontBuilder().createFont(document().styleEngine().fontSelector(),
                                 state.mutableStyleRef());
  state.setConversionFontSizes(CSSToLengthConversionData::FontSizes(
      state.style(), state.rootElementStyle()));
  state.setConversionZoom(state.style()->effectiveZoom());
}

StyleRuleList* StyleResolver::styleRulesForElement(Element* element,
                                                   unsigned rulesToInclude) {
  ASSERT(element);
  StyleResolverState state(document(), element);
  ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                 state.style());
  collector.setMode(SelectorChecker::CollectingStyleRules);
  collectPseudoRulesForElement(*element, collector, PseudoIdNone,
                               rulesToInclude);
  return collector.matchedStyleRuleList();
}

CSSRuleList* StyleResolver::pseudoCSSRulesForElement(Element* element,
                                                     PseudoId pseudoId,
                                                     unsigned rulesToInclude) {
  ASSERT(element);
  StyleResolverState state(document(), element);
  ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                 state.style());
  collector.setMode(SelectorChecker::CollectingCSSRules);
  collectPseudoRulesForElement(*element, collector, pseudoId, rulesToInclude);
  return collector.matchedCSSRuleList();
}

CSSRuleList* StyleResolver::cssRulesForElement(Element* element,
                                               unsigned rulesToInclude) {
  return pseudoCSSRulesForElement(element, PseudoIdNone, rulesToInclude);
}

void StyleResolver::collectPseudoRulesForElement(
    const Element& element,
    ElementRuleCollector& collector,
    PseudoId pseudoId,
    unsigned rulesToInclude) {
  collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));

  if (rulesToInclude & UAAndUserCSSRules)
    matchUARules(collector);

  if (rulesToInclude & AuthorCSSRules) {
    collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
    collector.setIncludeEmptyRules(rulesToInclude & EmptyCSSRules);
    matchAuthorRules(element, collector);
  }
}

bool StyleResolver::applyAnimatedProperties(StyleResolverState& state,
                                            const Element* animatingElement) {
  Element* element = state.element();
  ASSERT(element);

  // The animating element may be this element, or its pseudo element. It is
  // null when calculating the style for a potential pseudo element that has
  // yet to be created.
  ASSERT(animatingElement == element || !animatingElement ||
         animatingElement->parentOrShadowHostElement() == element);

  if (!(animatingElement && animatingElement->hasAnimations()) &&
      !state.style()->transitions() && !state.style()->animations())
    return false;

  CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(),
                                 state.parentStyle(), state.animationUpdate(),
                                 this);
  if (state.animationUpdate().isEmpty())
    return false;

  CSSAnimations::snapshotCompositorKeyframes(
      *element, state.animationUpdate(), *state.style(), state.parentStyle());

  if (state.style()->insideLink() != NotInsideLink) {
    ASSERT(state.applyPropertyToRegularStyle());
    state.setApplyPropertyToVisitedLinkStyle(true);
  }

  const ActiveInterpolationsMap& activeInterpolationsMapForAnimations =
      state.animationUpdate().activeInterpolationsForAnimations();
  const ActiveInterpolationsMap& activeInterpolationsMapForTransitions =
      state.animationUpdate().activeInterpolationsForTransitions();
  // TODO(crbug.com/644148): Apply animations on custom properties.
  applyAnimatedProperties<HighPropertyPriority>(
      state, activeInterpolationsMapForAnimations);
  applyAnimatedProperties<HighPropertyPriority>(
      state, activeInterpolationsMapForTransitions);

  updateFont(state);

  applyAnimatedProperties<LowPropertyPriority>(
      state, activeInterpolationsMapForAnimations);
  applyAnimatedProperties<LowPropertyPriority>(
      state, activeInterpolationsMapForTransitions);

  // Start loading resources used by animations.
  loadPendingResources(state);

  ASSERT(!state.fontBuilder().fontDirty());

  state.setApplyPropertyToVisitedLinkStyle(false);

  return true;
}

StyleRuleKeyframes* StyleResolver::findKeyframesRule(
    const Element* element,
    const AtomicString& animationName) {
  HeapVector<Member<ScopedStyleResolver>, 8> resolvers;
  collectScopedResolversForHostedShadowTrees(*element, resolvers);
  if (ScopedStyleResolver* scopedResolver =
          element->treeScope().scopedStyleResolver())
    resolvers.append(scopedResolver);

  for (auto& resolver : resolvers) {
    if (StyleRuleKeyframes* keyframesRule =
            resolver->keyframeStylesForAnimation(animationName.impl()))
      return keyframesRule;
  }

  for (auto& resolver : resolvers)
    resolver->setHasUnresolvedKeyframesRule();
  return nullptr;
}

template <CSSPropertyPriority priority>
void StyleResolver::applyAnimatedProperties(
    StyleResolverState& state,
    const ActiveInterpolationsMap& activeInterpolationsMap) {
  // TODO(alancutter): Don't apply presentation attribute animations here,
  // they should instead apply in
  // SVGElement::collectStyleForPresentationAttribute().
  for (const auto& entry : activeInterpolationsMap) {
    CSSPropertyID property = entry.key.isCSSProperty()
                                 ? entry.key.cssProperty()
                                 : entry.key.presentationAttribute();
    if (!CSSPropertyPriorityData<priority>::propertyHasPriority(property))
      continue;
    const Interpolation& interpolation = *entry.value.first();
    if (interpolation.isInvalidatableInterpolation()) {
      InterpolationEnvironment environment(state);
      InvalidatableInterpolation::applyStack(entry.value, environment);
    } else {
      // TODO(alancutter): Remove this old code path once animations have
      // completely migrated to InterpolationTypes.
      toStyleInterpolation(interpolation).apply(state);
    }
  }
}

static inline bool isValidCueStyleProperty(CSSPropertyID id) {
  switch (id) {
    case CSSPropertyBackground:
    case CSSPropertyBackgroundAttachment:
    case CSSPropertyBackgroundClip:
    case CSSPropertyBackgroundColor:
    case CSSPropertyBackgroundImage:
    case CSSPropertyBackgroundOrigin:
    case CSSPropertyBackgroundPosition:
    case CSSPropertyBackgroundPositionX:
    case CSSPropertyBackgroundPositionY:
    case CSSPropertyBackgroundRepeat:
    case CSSPropertyBackgroundRepeatX:
    case CSSPropertyBackgroundRepeatY:
    case CSSPropertyBackgroundSize:
    case CSSPropertyColor:
    case CSSPropertyFont:
    case CSSPropertyFontFamily:
    case CSSPropertyFontSize:
    case CSSPropertyFontStretch:
    case CSSPropertyFontStyle:
    case CSSPropertyFontVariant:
    case CSSPropertyFontWeight:
    case CSSPropertyLineHeight:
    case CSSPropertyOpacity:
    case CSSPropertyOutline:
    case CSSPropertyOutlineColor:
    case CSSPropertyOutlineOffset:
    case CSSPropertyOutlineStyle:
    case CSSPropertyOutlineWidth:
    case CSSPropertyVisibility:
    case CSSPropertyWhiteSpace:
    // FIXME: 'text-decoration' shorthand to be handled when available.
    // See https://chromiumcodereview.appspot.com/19516002 for details.
    case CSSPropertyTextDecoration:
    case CSSPropertyTextShadow:
    case CSSPropertyBorderStyle:
      return true;
    case CSSPropertyTextDecorationLine:
    case CSSPropertyTextDecorationStyle:
    case CSSPropertyTextDecorationColor:
    case CSSPropertyTextDecorationSkip:
      return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
    default:
      break;
  }
  return false;
}

static inline bool isValidFirstLetterStyleProperty(CSSPropertyID id) {
  switch (id) {
    // Valid ::first-letter properties listed in spec:
    // http://www.w3.org/TR/css3-selectors/#application-in-css
    case CSSPropertyBackgroundAttachment:
    case CSSPropertyBackgroundBlendMode:
    case CSSPropertyBackgroundClip:
    case CSSPropertyBackgroundColor:
    case CSSPropertyBackgroundImage:
    case CSSPropertyBackgroundOrigin:
    case CSSPropertyBackgroundPosition:
    case CSSPropertyBackgroundPositionX:
    case CSSPropertyBackgroundPositionY:
    case CSSPropertyBackgroundRepeat:
    case CSSPropertyBackgroundRepeatX:
    case CSSPropertyBackgroundRepeatY:
    case CSSPropertyBackgroundSize:
    case CSSPropertyBorderBottomColor:
    case CSSPropertyBorderBottomLeftRadius:
    case CSSPropertyBorderBottomRightRadius:
    case CSSPropertyBorderBottomStyle:
    case CSSPropertyBorderBottomWidth:
    case CSSPropertyBorderImageOutset:
    case CSSPropertyBorderImageRepeat:
    case CSSPropertyBorderImageSlice:
    case CSSPropertyBorderImageSource:
    case CSSPropertyBorderImageWidth:
    case CSSPropertyBorderLeftColor:
    case CSSPropertyBorderLeftStyle:
    case CSSPropertyBorderLeftWidth:
    case CSSPropertyBorderRightColor:
    case CSSPropertyBorderRightStyle:
    case CSSPropertyBorderRightWidth:
    case CSSPropertyBorderTopColor:
    case CSSPropertyBorderTopLeftRadius:
    case CSSPropertyBorderTopRightRadius:
    case CSSPropertyBorderTopStyle:
    case CSSPropertyBorderTopWidth:
    case CSSPropertyColor:
    case CSSPropertyFloat:
    case CSSPropertyFont:
    case CSSPropertyFontFamily:
    case CSSPropertyFontKerning:
    case CSSPropertyFontSize:
    case CSSPropertyFontStretch:
    case CSSPropertyFontStyle:
    case CSSPropertyFontVariant:
    case CSSPropertyFontVariantCaps:
    case CSSPropertyFontVariantLigatures:
    case CSSPropertyFontVariantNumeric:
    case CSSPropertyFontWeight:
    case CSSPropertyLetterSpacing:
    case CSSPropertyLineHeight:
    case CSSPropertyMarginBottom:
    case CSSPropertyMarginLeft:
    case CSSPropertyMarginRight:
    case CSSPropertyMarginTop:
    case CSSPropertyPaddingBottom:
    case CSSPropertyPaddingLeft:
    case CSSPropertyPaddingRight:
    case CSSPropertyPaddingTop:
    case CSSPropertyTextTransform:
    case CSSPropertyVerticalAlign:
    case CSSPropertyWebkitBackgroundClip:
    case CSSPropertyWebkitBackgroundOrigin:
    case CSSPropertyWebkitBorderAfter:
    case CSSPropertyWebkitBorderAfterColor:
    case CSSPropertyWebkitBorderAfterStyle:
    case CSSPropertyWebkitBorderAfterWidth:
    case CSSPropertyWebkitBorderBefore:
    case CSSPropertyWebkitBorderBeforeColor:
    case CSSPropertyWebkitBorderBeforeStyle:
    case CSSPropertyWebkitBorderBeforeWidth:
    case CSSPropertyWebkitBorderEnd:
    case CSSPropertyWebkitBorderEndColor:
    case CSSPropertyWebkitBorderEndStyle:
    case CSSPropertyWebkitBorderEndWidth:
    case CSSPropertyWebkitBorderHorizontalSpacing:
    case CSSPropertyWebkitBorderImage:
    case CSSPropertyWebkitBorderStart:
    case CSSPropertyWebkitBorderStartColor:
    case CSSPropertyWebkitBorderStartStyle:
    case CSSPropertyWebkitBorderStartWidth:
    case CSSPropertyWebkitBorderVerticalSpacing:
    case CSSPropertyWebkitFontSmoothing:
    case CSSPropertyWebkitMarginAfter:
    case CSSPropertyWebkitMarginAfterCollapse:
    case CSSPropertyWebkitMarginBefore:
    case CSSPropertyWebkitMarginBeforeCollapse:
    case CSSPropertyWebkitMarginBottomCollapse:
    case CSSPropertyWebkitMarginCollapse:
    case CSSPropertyWebkitMarginEnd:
    case CSSPropertyWebkitMarginStart:
    case CSSPropertyWebkitMarginTopCollapse:
    case CSSPropertyWordSpacing:
      return true;
    case CSSPropertyTextDecoration:
      ASSERT(!RuntimeEnabledFeatures::css3TextDecorationsEnabled());
      return true;
    case CSSPropertyTextDecorationColor:
    case CSSPropertyTextDecorationLine:
    case CSSPropertyTextDecorationStyle:
    case CSSPropertyTextDecorationSkip:
      ASSERT(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
      return true;

    // text-shadow added in text decoration spec:
    // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property
    case CSSPropertyTextShadow:
    // box-shadox added in CSS3 backgrounds spec:
    // http://www.w3.org/TR/css3-background/#placement
    case CSSPropertyBoxShadow:
    // Properties that we currently support outside of spec.
    case CSSPropertyVisibility:
      return true;

    default:
      return false;
  }
}

static bool shouldIgnoreTextTrackAuthorStyle(const Document& document) {
  Settings* settings = document.settings();
  if (!settings)
    return false;
  // Ignore author specified settings for text tracks when any of the user
  // settings are present.
  if (!settings->textTrackBackgroundColor().isEmpty() ||
      !settings->textTrackFontFamily().isEmpty() ||
      !settings->textTrackFontStyle().isEmpty() ||
      !settings->textTrackFontVariant().isEmpty() ||
      !settings->textTrackTextColor().isEmpty() ||
      !settings->textTrackTextShadow().isEmpty() ||
      !settings->textTrackTextSize().isEmpty())
    return true;
  return false;
}

static inline bool isPropertyInWhitelist(
    PropertyWhitelistType propertyWhitelistType,
    CSSPropertyID property,
    const Document& document) {
  if (propertyWhitelistType == PropertyWhitelistNone)
    return true;  // Early bail for the by far most common case.

  if (propertyWhitelistType == PropertyWhitelistFirstLetter)
    return isValidFirstLetterStyleProperty(property);

  if (propertyWhitelistType == PropertyWhitelistCue)
    return isValidCueStyleProperty(property) &&
           !shouldIgnoreTextTrackAuthorStyle(document);

  ASSERT_NOT_REACHED();
  return true;
}

// This method expands the 'all' shorthand property to longhand properties
// and applies the expanded longhand properties.
template <CSSPropertyPriority priority>
void StyleResolver::applyAllProperty(
    StyleResolverState& state,
    const CSSValue& allValue,
    bool inheritedOnly,
    PropertyWhitelistType propertyWhitelistType) {
  // The 'all' property doesn't apply to variables:
  // https://drafts.csswg.org/css-variables/#defining-variables
  if (priority == ResolveVariables)
    return;

  unsigned startCSSProperty = CSSPropertyPriorityData<priority>::first();
  unsigned endCSSProperty = CSSPropertyPriorityData<priority>::last();

  for (unsigned i = startCSSProperty; i <= endCSSProperty; ++i) {
    CSSPropertyID propertyId = static_cast<CSSPropertyID>(i);

    // StyleBuilder does not allow any expanded shorthands.
    if (isShorthandProperty(propertyId))
      continue;

    // all shorthand spec says:
    // The all property is a shorthand that resets all CSS properties
    // except direction and unicode-bidi.
    // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand
    // We skip applyProperty when a given property is unicode-bidi or
    // direction.
    if (!CSSProperty::isAffectedByAllProperty(propertyId))
      continue;

    if (!isPropertyInWhitelist(propertyWhitelistType, propertyId, document()))
      continue;

    // When hitting matched properties' cache, only inherited properties will be
    // applied.
    if (inheritedOnly && !CSSPropertyMetadata::isInheritedProperty(propertyId))
      continue;

    StyleBuilder::applyProperty(propertyId, state, allValue);
  }
}

template <CSSPropertyPriority priority>
void StyleResolver::applyPropertiesForApplyAtRule(
    StyleResolverState& state,
    const CSSValue& value,
    bool isImportant,
    PropertyWhitelistType propertyWhitelistType) {
  state.style()->setHasVariableReferenceFromNonInheritedProperty();
  if (!state.style()->inheritedVariables())
    return;
  const String& name = toCSSCustomIdentValue(value).value();
  const StylePropertySet* propertySet =
      state.customPropertySetForApplyAtRule(name);
  bool inheritedOnly = false;
  if (propertySet)
    applyProperties<priority>(state, propertySet, isImportant, inheritedOnly,
                              propertyWhitelistType);
}

template <CSSPropertyPriority priority>
void StyleResolver::applyProperties(
    StyleResolverState& state,
    const StylePropertySet* properties,
    bool isImportant,
    bool inheritedOnly,
    PropertyWhitelistType propertyWhitelistType) {
  unsigned propertyCount = properties->propertyCount();
  for (unsigned i = 0; i < propertyCount; ++i) {
    StylePropertySet::PropertyReference current = properties->propertyAt(i);
    CSSPropertyID property = current.id();

    if (property == CSSPropertyApplyAtRule) {
      DCHECK(!inheritedOnly);
      applyPropertiesForApplyAtRule<priority>(
          state, current.value(), isImportant, propertyWhitelistType);
      continue;
    }

    if (isImportant != current.isImportant())
      continue;

    if (property == CSSPropertyAll) {
      applyAllProperty<priority>(state, current.value(), inheritedOnly,
                                 propertyWhitelistType);
      continue;
    }

    if (!isPropertyInWhitelist(propertyWhitelistType, property, document()))
      continue;

    if (inheritedOnly && !current.isInherited()) {
      // If the property value is explicitly inherited, we need to apply further
      // non-inherited properties as they might override the value inherited
      // here. For this reason we don't allow declarations with explicitly
      // inherited properties to be cached.
      DCHECK(!current.value().isInheritedValue());
      continue;
    }

    if (!CSSPropertyPriorityData<priority>::propertyHasPriority(property))
      continue;

    StyleBuilder::applyProperty(current.id(), state, current.value());
  }
}

template <CSSPropertyPriority priority>
void StyleResolver::applyMatchedProperties(StyleResolverState& state,
                                           const MatchedPropertiesRange& range,
                                           bool isImportant,
                                           bool inheritedOnly) {
  if (range.isEmpty())
    return;

  if (state.style()->insideLink() != NotInsideLink) {
    for (const auto& matchedProperties : range) {
      unsigned linkMatchType = matchedProperties.m_types.linkMatchType;
      // FIXME: It would be nicer to pass these as arguments but that requires
      // changes in many places.
      state.setApplyPropertyToRegularStyle(linkMatchType &
                                           CSSSelector::MatchLink);
      state.setApplyPropertyToVisitedLinkStyle(linkMatchType &
                                               CSSSelector::MatchVisited);

      applyProperties<priority>(state, matchedProperties.properties.get(),
                                isImportant, inheritedOnly,
                                static_cast<PropertyWhitelistType>(
                                    matchedProperties.m_types.whitelistType));
    }
    state.setApplyPropertyToRegularStyle(true);
    state.setApplyPropertyToVisitedLinkStyle(false);
    return;
  }
  for (const auto& matchedProperties : range)
    applyProperties<priority>(state, matchedProperties.properties.get(),
                              isImportant, inheritedOnly,
                              static_cast<PropertyWhitelistType>(
                                  matchedProperties.m_types.whitelistType));
}

static unsigned computeMatchedPropertiesHash(
    const MatchedProperties* properties,
    unsigned size) {
  return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
}

void StyleResolver::invalidateMatchedPropertiesCache() {
  m_matchedPropertiesCache.clear();
}

void StyleResolver::notifyResizeForViewportUnits() {
  m_viewportStyleResolver->collectViewportRules();
  m_matchedPropertiesCache.clearViewportDependent();
}

void StyleResolver::applyMatchedProperties(StyleResolverState& state,
                                           const MatchResult& matchResult) {
  const Element* element = state.element();
  ASSERT(element);

  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), matchedPropertyApply,
                                1);

  unsigned cacheHash =
      RuntimeEnabledFeatures::styleMatchedPropertiesCacheEnabled() &&
              matchResult.isCacheable()
          ? computeMatchedPropertiesHash(matchResult.matchedProperties().data(),
                                         matchResult.matchedProperties().size())
          : 0;
  bool applyInheritedOnly = false;
  const CachedMatchedProperties* cachedMatchedProperties =
      cacheHash
          ? m_matchedPropertiesCache.find(cacheHash, state,
                                          matchResult.matchedProperties())
          : nullptr;

  if (cachedMatchedProperties && MatchedPropertiesCache::isCacheable(state)) {
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(),
                                  matchedPropertyCacheHit, 1);
    // We can build up the style by copying non-inherited properties from an
    // earlier style object built using the same exact style declarations. We
    // then only need to apply the inherited properties, if any, as their values
    // can depend on the element context. This is fast and saves memory by
    // reusing the style data structures.
    state.style()->copyNonInheritedFromCached(
        *cachedMatchedProperties->computedStyle);
    if (state.parentStyle()->inheritedDataShared(
            *cachedMatchedProperties->parentComputedStyle) &&
        !isAtShadowBoundary(element) &&
        (!state.distributedToInsertionPoint() ||
         state.style()->userModify() == READ_ONLY)) {
      INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(),
                                    matchedPropertyCacheInheritedHit, 1);

      EInsideLink linkStatus = state.style()->insideLink();
      // If the cache item parent style has identical inherited properties to
      // the current parent style then the resulting style will be identical
      // too. We copy the inherited properties over from the cache and are done.
      state.style()->inheritFrom(*cachedMatchedProperties->computedStyle);

      // Unfortunately the link status is treated like an inherited property. We
      // need to explicitly restore it.
      state.style()->setInsideLink(linkStatus);

      updateFont(state);

      return;
    }
    applyInheritedOnly = true;
  }

  // TODO(leviw): We need the proper bit for tracking whether we need to do this
  // work.
  applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                           false, applyInheritedOnly);
  applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                           true, applyInheritedOnly);
  // TODO(leviw): stop recalculating every time
  CSSVariableResolver::resolveVariableDefinitions(state);

  if (RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) {
    if (cacheCustomPropertiesForApplyAtRules(state,
                                             matchResult.authorRules())) {
      applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                               false, applyInheritedOnly);
      applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                               true, applyInheritedOnly);
      CSSVariableResolver::resolveVariableDefinitions(state);
    }
  }

  // Now we have all of the matched rules in the appropriate order. Walk the
  // rules and apply high-priority properties first, i.e., those properties that
  // other properties depend on.  The order is (1) high-priority not important,
  // (2) high-priority important, (3) normal not important and (4) normal
  // important.
  applyMatchedProperties<HighPropertyPriority>(state, matchResult.allRules(),
                                               false, applyInheritedOnly);
  for (auto range : ImportantAuthorRanges(matchResult))
    applyMatchedProperties<HighPropertyPriority>(state, range, true,
                                                 applyInheritedOnly);
  applyMatchedProperties<HighPropertyPriority>(state, matchResult.uaRules(),
                                               true, applyInheritedOnly);

  if (UNLIKELY(isSVGForeignObjectElement(element))) {
    // LayoutSVGRoot handles zooming for the whole SVG subtree, so foreignObject
    // content should not be scaled again.
    //
    // FIXME: The following hijacks the zoom property for foreignObject so that
    // children of foreignObject get the correct font-size in case of zooming.
    // 'zoom' has HighPropertyPriority, along with other font-related properties
    // used as input to the FontBuilder, so resetting it here may cause the
    // FontBuilder to recompute the font used as inheritable font for
    // foreignObject content. If we want to support zoom on foreignObject we'll
    // need to find another way of handling the SVG zoom model.
    state.setEffectiveZoom(ComputedStyle::initialZoom());
  }

  if (cachedMatchedProperties &&
      cachedMatchedProperties->computedStyle->effectiveZoom() !=
          state.style()->effectiveZoom()) {
    state.fontBuilder().didChangeEffectiveZoom();
    applyInheritedOnly = false;
  }

  // If our font got dirtied, go ahead and update it now.
  updateFont(state);

  // Many properties depend on the font. If it changes we just apply all
  // properties.
  if (cachedMatchedProperties &&
      cachedMatchedProperties->computedStyle->getFontDescription() !=
          state.style()->getFontDescription())
    applyInheritedOnly = false;

  // Registered custom properties are computed after high priority properties.
  CSSVariableResolver::computeRegisteredVariables(state);

  // Now do the normal priority UA properties.
  applyMatchedProperties<LowPropertyPriority>(state, matchResult.uaRules(),
                                              false, applyInheritedOnly);

  // Cache the UA properties to pass them to LayoutTheme in adjustComputedStyle.
  state.cacheUserAgentBorderAndBackground();

  // Now do the author and user normal priority properties and all the
  // !important properties.
  applyMatchedProperties<LowPropertyPriority>(state, matchResult.authorRules(),
                                              false, applyInheritedOnly);
  for (auto range : ImportantAuthorRanges(matchResult))
    applyMatchedProperties<LowPropertyPriority>(state, range, true,
                                                applyInheritedOnly);
  applyMatchedProperties<LowPropertyPriority>(state, matchResult.uaRules(),
                                              true, applyInheritedOnly);

  if (state.style()->hasAppearance() && !applyInheritedOnly) {
    // Check whether the final border and background differs from the cached UA
    // ones.  When there is a partial match in the MatchedPropertiesCache, these
    // flags will already be set correctly and the value stored in
    // cacheUserAgentBorderAndBackground is incorrect, so doing this check again
    // would give the wrong answer.
    state.style()->setHasAuthorBackground(hasAuthorBackground(state));
    state.style()->setHasAuthorBorder(hasAuthorBorder(state));
  }

  loadPendingResources(state);

  if (!cachedMatchedProperties && cacheHash &&
      MatchedPropertiesCache::isCacheable(state)) {
    ASSERT(RuntimeEnabledFeatures::styleMatchedPropertiesCacheEnabled());
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(),
                                  matchedPropertyCacheAdded, 1);
    m_matchedPropertiesCache.add(*state.style(), *state.parentStyle(),
                                 cacheHash, matchResult.matchedProperties());
  }

  ASSERT(!state.fontBuilder().fontDirty());
}

bool StyleResolver::hasAuthorBackground(const StyleResolverState& state) {
  const CachedUAStyle* cachedUAStyle = state.cachedUAStyle();
  if (!cachedUAStyle)
    return false;

  FillLayer oldFill = cachedUAStyle->backgroundLayers;
  FillLayer newFill = state.style()->backgroundLayers();
  // Exclude background-repeat from comparison by resetting it.
  oldFill.setRepeatX(NoRepeatFill);
  oldFill.setRepeatY(NoRepeatFill);
  newFill.setRepeatX(NoRepeatFill);
  newFill.setRepeatY(NoRepeatFill);

  return (oldFill != newFill ||
          cachedUAStyle->backgroundColor != state.style()->backgroundColor());
}

bool StyleResolver::hasAuthorBorder(const StyleResolverState& state) {
  const CachedUAStyle* cachedUAStyle = state.cachedUAStyle();
  return cachedUAStyle && (cachedUAStyle->border != state.style()->border());
}

void StyleResolver::applyCallbackSelectors(StyleResolverState& state) {
  if (!m_watchedSelectorsRules)
    return;

  ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                 state.style());
  collector.setMode(SelectorChecker::CollectingStyleRules);
  collector.setIncludeEmptyRules(true);

  MatchRequest matchRequest(m_watchedSelectorsRules.get());
  collector.collectMatchingRules(matchRequest);
  collector.sortAndTransferMatchedRules();

  StyleRuleList* rules = collector.matchedStyleRuleList();
  if (!rules)
    return;
  for (size_t i = 0; i < rules->size(); i++)
    state.style()->addCallbackSelector(
        rules->at(i)->selectorList().selectorsText());
}

void StyleResolver::computeFont(ComputedStyle* style,
                                const StylePropertySet& propertySet) {
  CSSPropertyID properties[] = {
      CSSPropertyFontSize,   CSSPropertyFontFamily,      CSSPropertyFontStretch,
      CSSPropertyFontStyle,  CSSPropertyFontVariantCaps, CSSPropertyFontWeight,
      CSSPropertyLineHeight,
  };

  // TODO(timloh): This is weird, the style is being used as its own parent
  StyleResolverState state(document(), nullptr, style);
  state.setStyle(style);

  for (CSSPropertyID property : properties) {
    if (property == CSSPropertyLineHeight)
      updateFont(state);
    StyleBuilder::applyProperty(property, state,
                                *propertySet.getPropertyCSSValue(property));
  }
}

void StyleResolver::addViewportDependentMediaQueries(
    const MediaQueryResultList& list) {
  for (size_t i = 0; i < list.size(); ++i)
    m_viewportDependentMediaQueryResults.append(list[i]);
}

void StyleResolver::addDeviceDependentMediaQueries(
    const MediaQueryResultList& list) {
  for (size_t i = 0; i < list.size(); ++i)
    m_deviceDependentMediaQueryResults.append(list[i]);
}

bool StyleResolver::mediaQueryAffectedByViewportChange() const {
  for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) {
    if (m_medium->eval(m_viewportDependentMediaQueryResults[i]->expression()) !=
        m_viewportDependentMediaQueryResults[i]->result())
      return true;
  }
  return false;
}

bool StyleResolver::mediaQueryAffectedByDeviceChange() const {
  for (unsigned i = 0; i < m_deviceDependentMediaQueryResults.size(); ++i) {
    if (m_medium->eval(m_deviceDependentMediaQueryResults[i]->expression()) !=
        m_deviceDependentMediaQueryResults[i]->result())
      return true;
  }
  return false;
}

DEFINE_TRACE(StyleResolver) {
  visitor->trace(m_matchedPropertiesCache);
  visitor->trace(m_medium);
  visitor->trace(m_viewportDependentMediaQueryResults);
  visitor->trace(m_deviceDependentMediaQueryResults);
  visitor->trace(m_selectorFilter);
  visitor->trace(m_viewportStyleResolver);
  visitor->trace(m_features);
  visitor->trace(m_siblingRuleSet);
  visitor->trace(m_uncommonAttributeRuleSet);
  visitor->trace(m_watchedSelectorsRules);
  visitor->trace(m_treeBoundaryCrossingScopes);
  visitor->trace(m_styleSharingLists);
  visitor->trace(m_pendingStyleSheets);
  visitor->trace(m_document);
}

}  // namespace blink
