• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
11  * Copyright (C) 2012 Google Inc. All rights reserved.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public License
24  * along with this library; see the file COPYING.LIB.  If not, write to
25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28 
29 #include "config.h"
30 #include "core/css/resolver/StyleResolver.h"
31 
32 #include "core/CSSPropertyNames.h"
33 #include "core/HTMLNames.h"
34 #include "core/StylePropertyShorthand.h"
35 #include "core/animation/ActiveAnimations.h"
36 #include "core/animation/AnimatableValue.h"
37 #include "core/animation/Animation.h"
38 #include "core/animation/AnimationTimeline.h"
39 #include "core/animation/css/CSSAnimatableValueFactory.h"
40 #include "core/animation/css/CSSAnimations.h"
41 #include "core/animation/interpolation/StyleInterpolation.h"
42 #include "core/css/CSSCalculationValue.h"
43 #include "core/css/CSSDefaultStyleSheets.h"
44 #include "core/css/CSSFontSelector.h"
45 #include "core/css/CSSKeyframeRule.h"
46 #include "core/css/CSSKeyframesRule.h"
47 #include "core/css/CSSReflectValue.h"
48 #include "core/css/CSSRuleList.h"
49 #include "core/css/CSSSelector.h"
50 #include "core/css/CSSStyleRule.h"
51 #include "core/css/CSSValueList.h"
52 #include "core/css/CSSValuePool.h"
53 #include "core/css/ElementRuleCollector.h"
54 #include "core/css/FontFace.h"
55 #include "core/css/MediaQueryEvaluator.h"
56 #include "core/css/PageRuleCollector.h"
57 #include "core/css/StylePropertySet.h"
58 #include "core/css/StyleRuleImport.h"
59 #include "core/css/StyleSheetContents.h"
60 #include "core/css/parser/BisonCSSParser.h"
61 #include "core/css/resolver/AnimatedStyleBuilder.h"
62 #include "core/css/resolver/MatchResult.h"
63 #include "core/css/resolver/MediaQueryResult.h"
64 #include "core/css/resolver/SharedStyleFinder.h"
65 #include "core/css/resolver/StyleAdjuster.h"
66 #include "core/css/resolver/StyleResolverParentScope.h"
67 #include "core/css/resolver/StyleResolverState.h"
68 #include "core/css/resolver/StyleResolverStats.h"
69 #include "core/css/resolver/ViewportStyleResolver.h"
70 #include "core/dom/CSSSelectorWatch.h"
71 #include "core/dom/NodeRenderStyle.h"
72 #include "core/dom/StyleEngine.h"
73 #include "core/dom/Text.h"
74 #include "core/dom/shadow/ElementShadow.h"
75 #include "core/dom/shadow/ShadowRoot.h"
76 #include "core/frame/FrameView.h"
77 #include "core/frame/LocalFrame.h"
78 #include "core/html/HTMLIFrameElement.h"
79 #include "core/inspector/InspectorInstrumentation.h"
80 #include "core/rendering/RenderView.h"
81 #include "core/rendering/style/KeyframeList.h"
82 #include "core/svg/SVGDocumentExtensions.h"
83 #include "core/svg/SVGElement.h"
84 #include "core/svg/SVGFontFaceElement.h"
85 #include "platform/RuntimeEnabledFeatures.h"
86 #include "wtf/StdLibExtras.h"
87 
88 namespace {
89 
90 using namespace WebCore;
91 
setAnimationUpdateIfNeeded(StyleResolverState & state,Element & element)92 void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element)
93 {
94     // If any changes to CSS Animations were detected, stash the update away for application after the
95     // render object is updated if we're in the appropriate scope.
96     if (state.animationUpdate())
97         element.ensureActiveAnimations().cssAnimations().setPendingUpdate(state.takeAnimationUpdate());
98 }
99 
100 } // namespace
101 
102 namespace WebCore {
103 
104 using namespace HTMLNames;
105 
106 RenderStyle* StyleResolver::s_styleNotYetAvailable;
107 
leftToRightDeclaration()108 static StylePropertySet* leftToRightDeclaration()
109 {
110     DEFINE_STATIC_REF(MutableStylePropertySet, leftToRightDecl, (MutableStylePropertySet::create()));
111     if (leftToRightDecl->isEmpty())
112         leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
113     return leftToRightDecl;
114 }
115 
rightToLeftDeclaration()116 static StylePropertySet* rightToLeftDeclaration()
117 {
118     DEFINE_STATIC_REF(MutableStylePropertySet, rightToLeftDecl, (MutableStylePropertySet::create()));
119     if (rightToLeftDecl->isEmpty())
120         rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
121     return rightToLeftDecl;
122 }
123 
addFontFaceRule(Document * document,CSSFontSelector * cssFontSelector,const StyleRuleFontFace * fontFaceRule)124 static void addFontFaceRule(Document* document, CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule)
125 {
126     RefPtrWillBeRawPtr<FontFace> fontFace = FontFace::create(document, fontFaceRule);
127     if (fontFace)
128         cssFontSelector->fontFaceCache()->add(cssFontSelector, fontFaceRule, fontFace);
129 }
130 
StyleResolver(Document & document)131 StyleResolver::StyleResolver(Document& document)
132     : m_document(document)
133     , m_viewportStyleResolver(ViewportStyleResolver::create(&document))
134     , m_needCollectFeatures(false)
135     , m_styleResourceLoader(document.fetcher())
136     , m_styleSharingDepth(0)
137     , m_styleResolverStatsSequence(0)
138     , m_accessCount(0)
139 {
140     FrameView* view = document.view();
141     if (view)
142         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), &view->frame()));
143     else
144         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
145 
146     m_styleTree.clear();
147 
148     initWatchedSelectorRules(CSSSelectorWatch::from(document).watchedCallbackSelectors());
149 
150 #if ENABLE(SVG_FONTS)
151     if (document.svgExtensions()) {
152         const WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >& svgFontFaceElements = document.svgExtensions()->svgFontFaceElements();
153         WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator end = svgFontFaceElements.end();
154         for (WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
155             addFontFaceRule(&document, document.styleEngine()->fontSelector(), (*it)->fontFaceRule());
156     }
157 #endif
158 }
159 
initWatchedSelectorRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRule>> & watchedSelectors)160 void StyleResolver::initWatchedSelectorRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRule> >& watchedSelectors)
161 {
162     if (!watchedSelectors.size())
163         return;
164     m_watchedSelectorsRules = RuleSet::create();
165     for (unsigned i = 0; i < watchedSelectors.size(); ++i)
166         m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(), RuleHasNoSpecialState);
167 }
168 
lazyAppendAuthorStyleSheets(unsigned firstNew,const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet>> & styleSheets)169 void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
170 {
171     unsigned size = styleSheets.size();
172     for (unsigned i = firstNew; i < size; ++i)
173         m_pendingStyleSheets.add(styleSheets[i].get());
174 }
175 
removePendingAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet>> & styleSheets)176 void StyleResolver::removePendingAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
177 {
178     for (unsigned i = 0; i < styleSheets.size(); ++i)
179         m_pendingStyleSheets.remove(styleSheets[i].get());
180 }
181 
appendCSSStyleSheet(CSSStyleSheet * cssSheet)182 void StyleResolver::appendCSSStyleSheet(CSSStyleSheet* cssSheet)
183 {
184     ASSERT(cssSheet);
185     ASSERT(!cssSheet->disabled());
186     if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults))
187         return;
188 
189     ContainerNode* scopingNode = ScopedStyleResolver::scopingNodeFor(document(), cssSheet);
190     if (!scopingNode)
191         return;
192 
193     ScopedStyleResolver* resolver = ensureScopedStyleResolver(scopingNode);
194     ASSERT(resolver);
195     resolver->addRulesFromSheet(cssSheet, *m_medium, this);
196 }
197 
appendPendingAuthorStyleSheets()198 void StyleResolver::appendPendingAuthorStyleSheets()
199 {
200     setBuildScopedStyleTreeInDocumentOrder(false);
201     for (WillBeHeapListHashSet<RawPtrWillBeMember<CSSStyleSheet>, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it)
202         appendCSSStyleSheet(*it);
203 
204     m_pendingStyleSheets.clear();
205     finishAppendAuthorStyleSheets();
206 }
207 
appendAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet>> & styleSheets)208 void StyleResolver::appendAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
209 {
210     // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
211     // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
212     unsigned size = styleSheets.size();
213     for (unsigned i = 0; i < size; ++i)
214         appendCSSStyleSheet(styleSheets[i].get());
215 }
216 
finishAppendAuthorStyleSheets()217 void StyleResolver::finishAppendAuthorStyleSheets()
218 {
219     collectFeatures();
220 
221     if (document().renderView() && document().renderView()->style())
222         document().renderView()->style()->font().update(document().styleEngine()->fontSelector());
223 
224     collectViewportRules();
225 
226     document().styleEngine()->resetCSSFeatureFlags(m_features);
227 }
228 
resetRuleFeatures()229 void StyleResolver::resetRuleFeatures()
230 {
231     // Need to recreate RuleFeatureSet.
232     m_features.clear();
233     m_siblingRuleSet.clear();
234     m_uncommonAttributeRuleSet.clear();
235     m_needCollectFeatures = true;
236 }
237 
processScopedRules(const RuleSet & authorRules,CSSStyleSheet * parentStyleSheet,ContainerNode & scope)238 void StyleResolver::processScopedRules(const RuleSet& authorRules, CSSStyleSheet* parentStyleSheet, ContainerNode& scope)
239 {
240     const WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> > keyframesRules = authorRules.keyframesRules();
241     for (unsigned i = 0; i < keyframesRules.size(); ++i)
242         ensureScopedStyleResolver(&scope)->addKeyframeStyle(keyframesRules[i]);
243 
244     m_treeBoundaryCrossingRules.addTreeBoundaryCrossingRules(authorRules, scope, parentStyleSheet);
245 
246     // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
247     if (scope.isDocumentNode()) {
248         const WillBeHeapVector<RawPtrWillBeMember<StyleRuleFontFace> > fontFaceRules = authorRules.fontFaceRules();
249         for (unsigned i = 0; i < fontFaceRules.size(); ++i)
250             addFontFaceRule(&m_document, document().styleEngine()->fontSelector(), fontFaceRules[i]);
251         if (fontFaceRules.size())
252             invalidateMatchedPropertiesCache();
253     }
254 }
255 
resetAuthorStyle(const ContainerNode * scopingNode)256 void StyleResolver::resetAuthorStyle(const ContainerNode* scopingNode)
257 {
258     ScopedStyleResolver* resolver = scopingNode ? m_styleTree.lookupScopedStyleResolverFor(scopingNode) : m_styleTree.scopedStyleResolverForDocument();
259     if (!resolver)
260         return;
261 
262     m_treeBoundaryCrossingRules.reset(scopingNode);
263 
264     resolver->resetAuthorStyle();
265     resetRuleFeatures();
266     if (!scopingNode)
267         return;
268 
269     m_styleTree.remove(scopingNode);
270 }
271 
makeRuleSet(const WillBeHeapVector<RuleFeature> & rules)272 static PassOwnPtrWillBeRawPtr<RuleSet> makeRuleSet(const WillBeHeapVector<RuleFeature>& rules)
273 {
274     size_t size = rules.size();
275     if (!size)
276         return nullptr;
277     OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create();
278     for (size_t i = 0; i < size; ++i)
279         ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState);
280     return ruleSet.release();
281 }
282 
collectFeatures()283 void StyleResolver::collectFeatures()
284 {
285     m_features.clear();
286     // Collect all ids and rules using sibling selectors (:first-child and similar)
287     // in the current set of stylesheets. Style sharing code uses this information to reject
288     // sharing candidates.
289     CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
290     if (defaultStyleSheets.defaultStyle())
291         m_features.add(defaultStyleSheets.defaultStyle()->features());
292 
293     if (document().isViewSource())
294         m_features.add(defaultStyleSheets.defaultViewSourceStyle()->features());
295 
296     if (document().isTransitionDocument())
297         m_features.add(defaultStyleSheets.defaultTransitionStyle()->features());
298 
299     if (m_watchedSelectorsRules)
300         m_features.add(m_watchedSelectorsRules->features());
301 
302     m_treeBoundaryCrossingRules.collectFeaturesTo(m_features);
303 
304     m_styleTree.collectFeaturesTo(m_features);
305 
306     m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
307     m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
308     m_needCollectFeatures = false;
309 }
310 
hasRulesForId(const AtomicString & id) const311 bool StyleResolver::hasRulesForId(const AtomicString& id) const
312 {
313     return m_features.hasSelectorForId(id);
314 }
315 
addToStyleSharingList(Element & element)316 void StyleResolver::addToStyleSharingList(Element& element)
317 {
318     // Never add elements to the style sharing list if we're not in a recalcStyle,
319     // otherwise we could leave stale pointers in there.
320     if (!document().inStyleRecalc())
321         return;
322     INCREMENT_STYLE_STATS_COUNTER(*this, sharedStyleCandidates);
323     StyleSharingList& list = styleSharingList();
324     if (list.size() >= styleSharingListSize)
325         list.remove(--list.end());
326     list.prepend(&element);
327 }
328 
styleSharingList()329 StyleSharingList& StyleResolver::styleSharingList()
330 {
331     m_styleSharingLists.resize(styleSharingMaxDepth);
332 
333     // We never put things at depth 0 into the list since that's only the <html> element
334     // and it has no siblings or cousins to share with.
335     unsigned depth = std::max(std::min(m_styleSharingDepth, styleSharingMaxDepth), 1u) - 1u;
336     ASSERT(depth >= 0);
337 
338     if (!m_styleSharingLists[depth])
339         m_styleSharingLists[depth] = adoptPtr(new StyleSharingList);
340     return *m_styleSharingLists[depth];
341 }
342 
clearStyleSharingList()343 void StyleResolver::clearStyleSharingList()
344 {
345     m_styleSharingLists.resize(0);
346 }
347 
pushParentElement(Element & parent)348 void StyleResolver::pushParentElement(Element& parent)
349 {
350     const ContainerNode* parentsParent = parent.parentOrShadowHostElement();
351 
352     // We are not always invoked consistently. For example, script execution can cause us to enter
353     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
354     // Reset the stack in this case, or if we see a new root element.
355     // Otherwise just push the new parent.
356     if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
357         m_selectorFilter.setupParentStack(parent);
358     else
359         m_selectorFilter.pushParent(parent);
360 
361     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
362     m_styleTree.pushStyleCache(parent, parent.parentOrShadowHostNode());
363 }
364 
popParentElement(Element & parent)365 void StyleResolver::popParentElement(Element& parent)
366 {
367     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
368     // Pause maintaining the stack in this case.
369     if (m_selectorFilter.parentStackIsConsistent(&parent))
370         m_selectorFilter.popParent();
371 
372     m_styleTree.popStyleCache(parent);
373 }
374 
pushParentShadowRoot(const ShadowRoot & shadowRoot)375 void StyleResolver::pushParentShadowRoot(const ShadowRoot& shadowRoot)
376 {
377     ASSERT(shadowRoot.host());
378     m_styleTree.pushStyleCache(shadowRoot, shadowRoot.host());
379 }
380 
popParentShadowRoot(const ShadowRoot & shadowRoot)381 void StyleResolver::popParentShadowRoot(const ShadowRoot& shadowRoot)
382 {
383     ASSERT(shadowRoot.host());
384     m_styleTree.popStyleCache(shadowRoot);
385 }
386 
~StyleResolver()387 StyleResolver::~StyleResolver()
388 {
389 }
390 
applyAuthorStylesOf(const Element * element)391 static inline bool applyAuthorStylesOf(const Element* element)
392 {
393     return element->treeScope().applyAuthorStyles();
394 }
395 
matchAuthorRulesForShadowHost(Element * element,ElementRuleCollector & collector,bool includeEmptyRules,Vector<ScopedStyleResolver *,8> & resolvers,Vector<ScopedStyleResolver *,8> & resolversInShadowTree)396 void StyleResolver::matchAuthorRulesForShadowHost(Element* element, ElementRuleCollector& collector, bool includeEmptyRules, Vector<ScopedStyleResolver*, 8>& resolvers, Vector<ScopedStyleResolver*, 8>& resolversInShadowTree)
397 {
398     collector.clearMatchedRules();
399     collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
400 
401     CascadeScope cascadeScope = 0;
402     CascadeOrder cascadeOrder = 0;
403     bool applyAuthorStyles = applyAuthorStylesOf(element);
404 
405     for (int j = resolversInShadowTree.size() - 1; j >= 0; --j)
406         resolversInShadowTree.at(j)->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope, cascadeOrder++);
407 
408     if (resolvers.isEmpty() || resolvers.first()->treeScope() != element->treeScope())
409         ++cascadeScope;
410     cascadeOrder += resolvers.size();
411     for (unsigned i = 0; i < resolvers.size(); ++i)
412         resolvers.at(i)->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, --cascadeOrder);
413 
414     m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
415     collector.sortAndTransferMatchedRules();
416 }
417 
matchAuthorRules(Element * element,ElementRuleCollector & collector,bool includeEmptyRules)418 void StyleResolver::matchAuthorRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
419 {
420     collector.clearMatchedRules();
421     collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
422 
423     bool applyAuthorStyles = applyAuthorStylesOf(element);
424     if (m_styleTree.hasOnlyScopedResolverForDocument()) {
425         m_styleTree.scopedStyleResolverForDocument()->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, ignoreCascadeScope);
426         m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
427         collector.sortAndTransferMatchedRules();
428         return;
429     }
430 
431     Vector<ScopedStyleResolver*, 8> resolvers;
432     m_styleTree.resolveScopedStyles(element, resolvers);
433 
434     Vector<ScopedStyleResolver*, 8> resolversInShadowTree;
435     m_styleTree.collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree);
436     if (!resolversInShadowTree.isEmpty()) {
437         matchAuthorRulesForShadowHost(element, collector, includeEmptyRules, resolvers, resolversInShadowTree);
438         return;
439     }
440 
441     if (resolvers.isEmpty())
442         return;
443 
444     CascadeScope cascadeScope = 0;
445     CascadeOrder cascadeOrder = resolvers.size();
446     for (unsigned i = 0; i < resolvers.size(); ++i, --cascadeOrder) {
447         ScopedStyleResolver* resolver = resolvers.at(i);
448         // FIXME: Need to clarify how to treat style scoped.
449         resolver->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->scopingNode().isShadowRoot() ? 0 : cascadeOrder);
450     }
451 
452     m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
453     collector.sortAndTransferMatchedRules();
454 }
455 
matchWatchSelectorRules(ElementRuleCollector & collector)456 void StyleResolver::matchWatchSelectorRules(ElementRuleCollector& collector)
457 {
458     if (!m_watchedSelectorsRules)
459         return;
460 
461     collector.clearMatchedRules();
462     collector.matchedResult().ranges.lastUserRule = collector.matchedResult().matchedProperties.size() - 1;
463 
464     MatchRequest matchRequest(m_watchedSelectorsRules.get());
465     RuleRange ruleRange = collector.matchedResult().ranges.userRuleRange();
466     collector.collectMatchingRules(matchRequest, ruleRange);
467 
468     collector.sortAndTransferMatchedRules();
469 }
470 
matchUARules(ElementRuleCollector & collector)471 void StyleResolver::matchUARules(ElementRuleCollector& collector)
472 {
473     collector.setMatchingUARules(true);
474 
475     CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
476     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
477         ? defaultStyleSheets.defaultPrintStyle() : defaultStyleSheets.defaultStyle();
478     matchUARules(collector, userAgentStyleSheet);
479 
480     // In quirks mode, we match rules from the quirks user agent sheet.
481     if (document().inQuirksMode())
482         matchUARules(collector, defaultStyleSheets.defaultQuirksStyle());
483 
484     // 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.
485     if (document().isViewSource())
486         matchUARules(collector, defaultStyleSheets.defaultViewSourceStyle());
487 
488     if (document().isTransitionDocument())
489         matchUARules(collector, defaultStyleSheets.defaultTransitionStyle());
490 
491     collector.setMatchingUARules(false);
492 
493     matchWatchSelectorRules(collector);
494 }
495 
matchUARules(ElementRuleCollector & collector,RuleSet * rules)496 void StyleResolver::matchUARules(ElementRuleCollector& collector, RuleSet* rules)
497 {
498     collector.clearMatchedRules();
499     collector.matchedResult().ranges.lastUARule = collector.matchedResult().matchedProperties.size() - 1;
500 
501     RuleRange ruleRange = collector.matchedResult().ranges.UARuleRange();
502     collector.collectMatchingRules(MatchRequest(rules), ruleRange);
503 
504     collector.sortAndTransferMatchedRules();
505 }
506 
matchAllRules(StyleResolverState & state,ElementRuleCollector & collector,bool includeSMILProperties)507 void StyleResolver::matchAllRules(StyleResolverState& state, ElementRuleCollector& collector, bool includeSMILProperties)
508 {
509     matchUARules(collector);
510 
511     // Now check author rules, beginning first with presentational attributes mapped from HTML.
512     if (state.element()->isStyledElement()) {
513         collector.addElementStyleProperties(state.element()->presentationAttributeStyle());
514 
515         // Now we check additional mapped declarations.
516         // Tables and table cells share an additional mapped rule that must be applied
517         // after all attributes, since their mapped style depends on the values of multiple attributes.
518         collector.addElementStyleProperties(state.element()->additionalPresentationAttributeStyle());
519 
520         if (state.element()->isHTMLElement()) {
521             bool isAuto;
522             TextDirection textDirection = toHTMLElement(state.element())->directionalityIfhasDirAutoAttribute(isAuto);
523             if (isAuto)
524                 collector.matchedResult().addMatchedProperties(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
525         }
526     }
527 
528     matchAuthorRules(state.element(), collector, false);
529 
530     if (state.element()->isStyledElement()) {
531         if (state.element()->inlineStyle()) {
532             // Inline style is immutable as long as there is no CSSOM wrapper.
533             bool isInlineStyleCacheable = !state.element()->inlineStyle()->isMutable();
534             collector.addElementStyleProperties(state.element()->inlineStyle(), isInlineStyleCacheable);
535         }
536 
537         // Now check SMIL animation override style.
538         if (includeSMILProperties && state.element()->isSVGElement())
539             collector.addElementStyleProperties(toSVGElement(state.element())->animatedSMILStyleProperties(), false /* isCacheable */);
540     }
541 }
542 
styleForDocument(Document & document)543 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document& document)
544 {
545     const LocalFrame* frame = document.frame();
546 
547     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
548     documentStyle->setDisplay(BLOCK);
549     documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder : LogicalOrder);
550     documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor() : 1);
551     documentStyle->setLocale(document.contentLanguage());
552     documentStyle->setZIndex(0);
553     documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE : READ_ONLY);
554 
555     document.setupFontBuilder(documentStyle.get());
556 
557     return documentStyle.release();
558 }
559 
560 // FIXME: This is duplicated with StyleAdjuster.cpp
561 // Perhaps this should move onto ElementResolveContext or even Element?
isAtShadowBoundary(const Element * element)562 static inline bool isAtShadowBoundary(const Element* element)
563 {
564     if (!element)
565         return false;
566     ContainerNode* parentNode = element->parentNode();
567     return parentNode && parentNode->isShadowRoot();
568 }
569 
resetDirectionAndWritingModeOnDocument(Document & document)570 static inline void resetDirectionAndWritingModeOnDocument(Document& document)
571 {
572     document.setDirectionSetOnDocumentElement(false);
573     document.setWritingModeSetOnDocumentElement(false);
574 }
575 
addContentAttrValuesToFeatures(const Vector<AtomicString> & contentAttrValues,RuleFeatureSet & features)576 static void addContentAttrValuesToFeatures(const Vector<AtomicString>& contentAttrValues, RuleFeatureSet& features)
577 {
578     for (size_t i = 0; i < contentAttrValues.size(); ++i)
579         features.addContentAttr(contentAttrValues[i]);
580 }
581 
adjustRenderStyle(StyleResolverState & state,Element * element)582 void StyleResolver::adjustRenderStyle(StyleResolverState& state, Element* element)
583 {
584     StyleAdjuster adjuster(m_document.inQuirksMode());
585     adjuster.adjustRenderStyle(state.style(), state.parentStyle(), element, state.cachedUAStyle());
586 }
587 
588 // Start loading resources referenced by this style.
loadPendingResources(StyleResolverState & state)589 void StyleResolver::loadPendingResources(StyleResolverState& state)
590 {
591     m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources());
592     document().styleEngine()->fontSelector()->fontLoader()->loadPendingFonts();
593 }
594 
styleForElement(Element * element,RenderStyle * defaultParent,StyleSharingBehavior sharingBehavior,RuleMatchingBehavior matchingBehavior)595 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent, StyleSharingBehavior sharingBehavior,
596     RuleMatchingBehavior matchingBehavior)
597 {
598     ASSERT(document().frame());
599     ASSERT(documentSettings());
600     ASSERT(!hasPendingAuthorStyleSheets());
601     ASSERT(!m_needCollectFeatures);
602 
603     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
604     // will vanish if a style recalc happens during loading.
605     if (sharingBehavior == AllowStyleSharing && !document().isRenderingReady() && !element->renderer()) {
606         if (!s_styleNotYetAvailable) {
607             s_styleNotYetAvailable = RenderStyle::create().leakRef();
608             s_styleNotYetAvailable->setDisplay(NONE);
609             s_styleNotYetAvailable->font().update(document().styleEngine()->fontSelector());
610         }
611 
612         document().setHasNodesWithPlaceholderStyle();
613         return s_styleNotYetAvailable;
614     }
615 
616     didAccess();
617 
618     StyleResolverParentScope::ensureParentStackIsPushed();
619 
620     if (element == document().documentElement())
621         resetDirectionAndWritingModeOnDocument(document());
622     StyleResolverState state(document(), element, defaultParent);
623 
624     if (sharingBehavior == AllowStyleSharing && state.parentStyle()) {
625         SharedStyleFinder styleFinder(state.elementContext(), m_features, m_siblingRuleSet.get(), m_uncommonAttributeRuleSet.get(), *this);
626         if (RefPtr<RenderStyle> sharedStyle = styleFinder.findSharedStyle())
627             return sharedStyle.release();
628     }
629 
630     if (state.parentStyle()) {
631         state.setStyle(RenderStyle::create());
632         state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
633     } else {
634         state.setStyle(defaultStyleForElement());
635         state.setParentStyle(RenderStyle::clone(state.style()));
636     }
637     // contenteditable attribute (implemented by -webkit-user-modify) should
638     // be propagated from shadow host to distributed node.
639     if (state.distributedToInsertionPoint()) {
640         if (Element* parent = element->parentElement()) {
641             if (RenderStyle* styleOfShadowHost = parent->renderStyle())
642                 state.style()->setUserModify(styleOfShadowHost->userModify());
643         }
644     }
645 
646     state.fontBuilder().initForStyleResolve(state.document(), state.style());
647 
648     if (element->isLink()) {
649         state.style()->setIsLink(true);
650         EInsideLink linkState = state.elementLinkState();
651         if (linkState != NotInsideLink) {
652             bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
653             if (forceVisited)
654                 linkState = InsideVisitedLink;
655         }
656         state.style()->setInsideLink(linkState);
657     }
658 
659     bool needsCollection = false;
660     CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(element, needsCollection);
661     if (needsCollection)
662         collectFeatures();
663 
664     {
665         ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
666 
667         matchAllRules(state, collector, matchingBehavior != MatchAllRulesExcludingSMIL);
668 
669         applyMatchedProperties(state, collector.matchedResult());
670 
671         addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
672     }
673 
674     // Cache our original display.
675     state.style()->setOriginalDisplay(state.style()->display());
676 
677     adjustRenderStyle(state, element);
678 
679     // FIXME: The CSSWG wants to specify that the effects of animations are applied before
680     // important rules, but this currently happens here as we require adjustment to have happened
681     // before deciding which properties to transition.
682     if (applyAnimatedProperties(state, element))
683         adjustRenderStyle(state, element);
684 
685     // FIXME: Shouldn't this be on RenderBody::styleDidChange?
686     if (isHTMLBodyElement(*element))
687         document().textLinkColors().setTextColor(state.style()->color());
688 
689     setAnimationUpdateIfNeeded(state, *element);
690 
691     if (state.style()->hasViewportUnits())
692         document().setHasViewportUnits();
693 
694     // Now return the style.
695     return state.takeStyle();
696 }
697 
styleForKeyframe(Element * element,const RenderStyle & elementStyle,RenderStyle * parentStyle,const StyleKeyframe * keyframe,const AtomicString & animationName)698 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element* element, const RenderStyle& elementStyle, RenderStyle* parentStyle, const StyleKeyframe* keyframe, const AtomicString& animationName)
699 {
700     ASSERT(document().frame());
701     ASSERT(documentSettings());
702     ASSERT(!hasPendingAuthorStyleSheets());
703 
704     if (element == document().documentElement())
705         resetDirectionAndWritingModeOnDocument(document());
706     StyleResolverState state(document(), element, parentStyle);
707 
708     MatchResult result;
709     result.addMatchedProperties(&keyframe->properties());
710 
711     ASSERT(!state.style());
712 
713     // Create the style
714     state.setStyle(RenderStyle::clone(&elementStyle));
715     state.setLineHeightValue(0);
716 
717     state.fontBuilder().initForStyleResolve(state.document(), state.style());
718 
719     // We don't need to bother with !important. Since there is only ever one
720     // decl, there's nothing to override. So just add the first properties.
721     // We also don't need to bother with animation properties since the only
722     // relevant one is animation-timing-function and we special-case that in
723     // CSSAnimations.cpp
724     bool inheritedOnly = false;
725     applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
726 
727     // If our font got dirtied, go ahead and update it now.
728     updateFont(state);
729 
730     // Line-height is set when we are sure we decided on the font-size
731     if (state.lineHeightValue())
732         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
733 
734     // Now do rest of the properties.
735     applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
736 
737     // If our font got dirtied by one of the non-essential font props,
738     // go ahead and update it a second time.
739     updateFont(state);
740 
741     loadPendingResources(state);
742 
743     didAccess();
744 
745     return state.takeStyle();
746 }
747 
748 // This function is used by the WebAnimations JavaScript API method animate().
749 // FIXME: Remove this when animate() switches away from resolution-dependent parsing.
createAnimatableValueSnapshot(Element & element,CSSPropertyID property,CSSValue & value)750 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(Element& element, CSSPropertyID property, CSSValue& value)
751 {
752     RefPtr<RenderStyle> style;
753     if (element.renderStyle())
754         style = RenderStyle::clone(element.renderStyle());
755     else
756         style = RenderStyle::create();
757     StyleResolverState state(element.document(), &element);
758     state.setStyle(style);
759     state.fontBuilder().initForStyleResolve(state.document(), state.style());
760     return createAnimatableValueSnapshot(state, property, value);
761 }
762 
createAnimatableValueSnapshot(StyleResolverState & state,CSSPropertyID property,CSSValue & value)763 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(StyleResolverState& state, CSSPropertyID property, CSSValue& value)
764 {
765     StyleBuilder::applyProperty(property, state, &value);
766     return CSSAnimatableValueFactory::create(property, *state.style());
767 }
768 
createPseudoElementIfNeeded(Element & parent,PseudoId pseudoId)769 PassRefPtrWillBeRawPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& parent, PseudoId pseudoId)
770 {
771     RenderObject* parentRenderer = parent.renderer();
772     if (!parentRenderer)
773         return nullptr;
774 
775     if (pseudoId < FIRST_INTERNAL_PSEUDOID && !parentRenderer->style()->hasPseudoStyle(pseudoId))
776         return nullptr;
777 
778     if (pseudoId == BACKDROP && !parent.isInTopLayer())
779         return nullptr;
780 
781     if (!parentRenderer->canHaveGeneratedChildren())
782         return nullptr;
783 
784     RenderStyle* parentStyle = parentRenderer->style();
785     if (RenderStyle* cachedStyle = parentStyle->getCachedPseudoStyle(pseudoId)) {
786         if (!pseudoElementRendererIsNeeded(cachedStyle))
787             return nullptr;
788         return PseudoElement::create(&parent, pseudoId);
789     }
790 
791     StyleResolverState state(document(), &parent, parentStyle);
792     if (!pseudoStyleForElementInternal(parent, pseudoId, parentStyle, state))
793         return nullptr;
794     RefPtr<RenderStyle> style = state.takeStyle();
795     ASSERT(style);
796     parentStyle->addCachedPseudoStyle(style);
797 
798     if (!pseudoElementRendererIsNeeded(style.get()))
799         return nullptr;
800 
801     RefPtrWillBeRawPtr<PseudoElement> pseudo = PseudoElement::create(&parent, pseudoId);
802 
803     setAnimationUpdateIfNeeded(state, *pseudo);
804     if (ActiveAnimations* activeAnimations = pseudo->activeAnimations())
805         activeAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo.get());
806     return pseudo.release();
807 }
808 
pseudoStyleForElementInternal(Element & element,const PseudoStyleRequest & pseudoStyleRequest,RenderStyle * parentStyle,StyleResolverState & state)809 bool StyleResolver::pseudoStyleForElementInternal(Element& element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, StyleResolverState& state)
810 {
811     ASSERT(document().frame());
812     ASSERT(documentSettings());
813     ASSERT(pseudoStyleRequest.pseudoId != FIRST_LINE_INHERITED);
814 
815     StyleResolverParentScope::ensureParentStackIsPushed();
816 
817     if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
818         state.setStyle(RenderStyle::create());
819         state.style()->inheritFrom(state.parentStyle());
820     } else {
821         state.setStyle(defaultStyleForElement());
822         state.setParentStyle(RenderStyle::clone(state.style()));
823     }
824 
825     state.fontBuilder().initForStyleResolve(state.document(), state.style());
826 
827     // Since we don't use pseudo-elements in any of our quirk/print
828     // user agent rules, don't waste time walking those rules.
829 
830     {
831         // Check UA, user and author rules.
832         ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
833         collector.setPseudoStyleRequest(pseudoStyleRequest);
834 
835         matchUARules(collector);
836         matchAuthorRules(state.element(), collector, false);
837 
838         if (collector.matchedResult().matchedProperties.isEmpty())
839             return false;
840 
841         state.style()->setStyleType(pseudoStyleRequest.pseudoId);
842 
843         applyMatchedProperties(state, collector.matchedResult());
844 
845         addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
846     }
847 
848     // Cache our original display.
849     state.style()->setOriginalDisplay(state.style()->display());
850 
851     // FIXME: Passing 0 as the Element* introduces a lot of complexity
852     // in the adjustRenderStyle code.
853     adjustRenderStyle(state, 0);
854 
855     // FIXME: The CSSWG wants to specify that the effects of animations are applied before
856     // important rules, but this currently happens here as we require adjustment to have happened
857     // before deciding which properties to transition.
858     if (applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId)))
859         adjustRenderStyle(state, 0);
860 
861     didAccess();
862 
863     if (state.style()->hasViewportUnits())
864         document().setHasViewportUnits();
865 
866     return true;
867 }
868 
pseudoStyleForElement(Element * element,const PseudoStyleRequest & pseudoStyleRequest,RenderStyle * parentStyle)869 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
870 {
871     ASSERT(parentStyle);
872     if (!element)
873         return nullptr;
874 
875     StyleResolverState state(document(), element, parentStyle);
876     if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle, state))
877         return nullptr;
878 
879     if (PseudoElement* pseudoElement = element->pseudoElement(pseudoStyleRequest.pseudoId))
880         setAnimationUpdateIfNeeded(state, *pseudoElement);
881 
882     // Now return the style.
883     return state.takeStyle();
884 }
885 
styleForPage(int pageIndex)886 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
887 {
888     ASSERT(!hasPendingAuthorStyleSheets());
889     resetDirectionAndWritingModeOnDocument(document());
890     StyleResolverState state(document(), document().documentElement()); // m_rootElementStyle will be set to the document style.
891 
892     state.setStyle(RenderStyle::create());
893     const RenderStyle* rootElementStyle = state.rootElementStyle() ? state.rootElementStyle() : document().renderStyle();
894     ASSERT(rootElementStyle);
895     state.style()->inheritFrom(rootElementStyle);
896 
897     state.fontBuilder().initForStyleResolve(state.document(), state.style());
898 
899     PageRuleCollector collector(rootElementStyle, pageIndex);
900 
901     collector.matchPageRules(CSSDefaultStyleSheets::instance().defaultPrintStyle());
902 
903     if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument())
904         scopedResolver->matchPageRules(collector);
905 
906     state.setLineHeightValue(0);
907     bool inheritedOnly = false;
908 
909     MatchResult& result = collector.matchedResult();
910     applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
911 
912     // If our font got dirtied, go ahead and update it now.
913     updateFont(state);
914 
915     // Line-height is set when we are sure we decided on the font-size.
916     if (state.lineHeightValue())
917         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
918 
919     applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
920 
921     addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
922 
923     loadPendingResources(state);
924 
925     didAccess();
926 
927     // Now return the style.
928     return state.takeStyle();
929 }
930 
collectViewportRules()931 void StyleResolver::collectViewportRules()
932 {
933     CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
934     viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultStyle(), ViewportStyleResolver::UserAgentOrigin);
935 
936     if (!InspectorInstrumentation::applyViewportStyleOverride(&document(), this))
937         viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultViewportStyle(), ViewportStyleResolver::UserAgentOrigin);
938 
939     if (document().isMobileDocument())
940         viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultXHTMLMobileProfileStyle(), ViewportStyleResolver::UserAgentOrigin);
941 
942     if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument())
943         scopedResolver->collectViewportRulesTo(this);
944 
945     viewportStyleResolver()->resolve();
946 }
947 
defaultStyleForElement()948 PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement()
949 {
950     StyleResolverState state(document(), 0);
951     state.setStyle(RenderStyle::create());
952     state.fontBuilder().initForStyleResolve(document(), state.style());
953     state.style()->setLineHeight(RenderStyle::initialLineHeight());
954     state.setLineHeightValue(0);
955     state.fontBuilder().setInitial(state.style()->effectiveZoom());
956     state.style()->font().update(document().styleEngine()->fontSelector());
957     return state.takeStyle();
958 }
959 
styleForText(Text * textNode)960 PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode)
961 {
962     ASSERT(textNode);
963 
964     NodeRenderingTraversal::ParentDetails parentDetails;
965     Node* parentNode = NodeRenderingTraversal::parent(textNode, &parentDetails);
966     if (!parentNode || !parentNode->renderStyle())
967         return defaultStyleForElement();
968     return parentNode->renderStyle();
969 }
970 
updateFont(StyleResolverState & state)971 void StyleResolver::updateFont(StyleResolverState& state)
972 {
973     state.fontBuilder().createFont(document().styleEngine()->fontSelector(), state.parentStyle(), state.style());
974     if (state.fontBuilder().fontSizeHasViewportUnits())
975         state.style()->setHasViewportUnits();
976 }
977 
styleRulesForElement(Element * element,unsigned rulesToInclude)978 PassRefPtrWillBeRawPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, unsigned rulesToInclude)
979 {
980     ASSERT(element);
981     StyleResolverState state(document(), element);
982     ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
983     collector.setMode(SelectorChecker::CollectingStyleRules);
984     collectPseudoRulesForElement(element, collector, NOPSEUDO, rulesToInclude);
985     return collector.matchedStyleRuleList();
986 }
987 
pseudoCSSRulesForElement(Element * element,PseudoId pseudoId,unsigned rulesToInclude)988 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::pseudoCSSRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude)
989 {
990     ASSERT(element);
991     StyleResolverState state(document(), element);
992     ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
993     collector.setMode(SelectorChecker::CollectingCSSRules);
994     collectPseudoRulesForElement(element, collector, pseudoId, rulesToInclude);
995     return collector.matchedCSSRuleList();
996 }
997 
cssRulesForElement(Element * element,unsigned rulesToInclude)998 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::cssRulesForElement(Element* element, unsigned rulesToInclude)
999 {
1000     return pseudoCSSRulesForElement(element, NOPSEUDO, rulesToInclude);
1001 }
1002 
collectPseudoRulesForElement(Element * element,ElementRuleCollector & collector,PseudoId pseudoId,unsigned rulesToInclude)1003 void StyleResolver::collectPseudoRulesForElement(Element* element, ElementRuleCollector& collector, PseudoId pseudoId, unsigned rulesToInclude)
1004 {
1005     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
1006 
1007     if (rulesToInclude & UAAndUserCSSRules)
1008         matchUARules(collector);
1009 
1010     if (rulesToInclude & AuthorCSSRules) {
1011         collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
1012         matchAuthorRules(element, collector, rulesToInclude & EmptyCSSRules);
1013     }
1014 }
1015 
1016 // -------------------------------------------------------------------------------------
1017 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1018 
applyAnimatedProperties(StyleResolverState & state,Element * animatingElement)1019 bool StyleResolver::applyAnimatedProperties(StyleResolverState& state, Element* animatingElement)
1020 {
1021     const Element* element = state.element();
1022     ASSERT(element);
1023 
1024     // The animating element may be this element, or its pseudo element. It is
1025     // null when calculating the style for a potential pseudo element that has
1026     // yet to be created.
1027     ASSERT(animatingElement == element || !animatingElement || animatingElement->parentOrShadowHostElement() == element);
1028 
1029     if (!(animatingElement && animatingElement->hasActiveAnimations())
1030         && !state.style()->transitions() && !state.style()->animations())
1031         return false;
1032 
1033     state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(), state.parentStyle(), this));
1034     if (!state.animationUpdate())
1035         return false;
1036 
1037     const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations = state.animationUpdate()->activeInterpolationsForAnimations();
1038     const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForTransitions = state.animationUpdate()->activeInterpolationsForTransitions();
1039     applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForAnimations);
1040     applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForTransitions);
1041 
1042     updateFont(state);
1043 
1044     applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForAnimations);
1045     applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForTransitions);
1046 
1047     // Start loading resources used by animations.
1048     loadPendingResources(state);
1049 
1050     ASSERT(!state.fontBuilder().fontDirty());
1051 
1052     return true;
1053 }
1054 
1055 template <StyleResolver::StyleApplicationPass pass>
applyAnimatedProperties(StyleResolverState & state,const WillBeHeapHashMap<CSSPropertyID,RefPtrWillBeMember<Interpolation>> & activeInterpolations)1056 void StyleResolver::applyAnimatedProperties(StyleResolverState& state, const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolations)
1057 {
1058     ASSERT(pass != AnimationProperties);
1059 
1060     for (WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >::const_iterator iter = activeInterpolations.begin(); iter != activeInterpolations.end(); ++iter) {
1061         CSSPropertyID property = iter->key;
1062         if (!isPropertyForPass<pass>(property))
1063             continue;
1064         const StyleInterpolation* interpolation = toStyleInterpolation(iter->value.get());
1065         interpolation->apply(state);
1066     }
1067 }
1068 
isValidCueStyleProperty(CSSPropertyID id)1069 static inline bool isValidCueStyleProperty(CSSPropertyID id)
1070 {
1071     switch (id) {
1072     case CSSPropertyBackground:
1073     case CSSPropertyBackgroundAttachment:
1074     case CSSPropertyBackgroundClip:
1075     case CSSPropertyBackgroundColor:
1076     case CSSPropertyBackgroundImage:
1077     case CSSPropertyBackgroundOrigin:
1078     case CSSPropertyBackgroundPosition:
1079     case CSSPropertyBackgroundPositionX:
1080     case CSSPropertyBackgroundPositionY:
1081     case CSSPropertyBackgroundRepeat:
1082     case CSSPropertyBackgroundRepeatX:
1083     case CSSPropertyBackgroundRepeatY:
1084     case CSSPropertyBackgroundSize:
1085     case CSSPropertyColor:
1086     case CSSPropertyFont:
1087     case CSSPropertyFontFamily:
1088     case CSSPropertyFontSize:
1089     case CSSPropertyFontStyle:
1090     case CSSPropertyFontVariant:
1091     case CSSPropertyFontWeight:
1092     case CSSPropertyLineHeight:
1093     case CSSPropertyOpacity:
1094     case CSSPropertyOutline:
1095     case CSSPropertyOutlineColor:
1096     case CSSPropertyOutlineOffset:
1097     case CSSPropertyOutlineStyle:
1098     case CSSPropertyOutlineWidth:
1099     case CSSPropertyVisibility:
1100     case CSSPropertyWhiteSpace:
1101     // FIXME: 'text-decoration' shorthand to be handled when available.
1102     // See https://chromiumcodereview.appspot.com/19516002 for details.
1103     case CSSPropertyTextDecoration:
1104     case CSSPropertyTextShadow:
1105     case CSSPropertyBorderStyle:
1106         return true;
1107     case CSSPropertyTextDecorationLine:
1108     case CSSPropertyTextDecorationStyle:
1109     case CSSPropertyTextDecorationColor:
1110         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
1111     default:
1112         break;
1113     }
1114     return false;
1115 }
1116 
isValidFirstLetterStyleProperty(CSSPropertyID id)1117 static inline bool isValidFirstLetterStyleProperty(CSSPropertyID id)
1118 {
1119     switch (id) {
1120     // Valid ::first-letter properties listed in spec:
1121     // http://www.w3.org/TR/css3-selectors/#application-in-css
1122     case CSSPropertyBackgroundAttachment:
1123     case CSSPropertyBackgroundBlendMode:
1124     case CSSPropertyBackgroundClip:
1125     case CSSPropertyBackgroundColor:
1126     case CSSPropertyBackgroundImage:
1127     case CSSPropertyBackgroundOrigin:
1128     case CSSPropertyBackgroundPosition:
1129     case CSSPropertyBackgroundPositionX:
1130     case CSSPropertyBackgroundPositionY:
1131     case CSSPropertyBackgroundRepeat:
1132     case CSSPropertyBackgroundRepeatX:
1133     case CSSPropertyBackgroundRepeatY:
1134     case CSSPropertyBackgroundSize:
1135     case CSSPropertyBorderBottomColor:
1136     case CSSPropertyBorderBottomLeftRadius:
1137     case CSSPropertyBorderBottomRightRadius:
1138     case CSSPropertyBorderBottomStyle:
1139     case CSSPropertyBorderBottomWidth:
1140     case CSSPropertyBorderImageOutset:
1141     case CSSPropertyBorderImageRepeat:
1142     case CSSPropertyBorderImageSlice:
1143     case CSSPropertyBorderImageSource:
1144     case CSSPropertyBorderImageWidth:
1145     case CSSPropertyBorderLeftColor:
1146     case CSSPropertyBorderLeftStyle:
1147     case CSSPropertyBorderLeftWidth:
1148     case CSSPropertyBorderRightColor:
1149     case CSSPropertyBorderRightStyle:
1150     case CSSPropertyBorderRightWidth:
1151     case CSSPropertyBorderTopColor:
1152     case CSSPropertyBorderTopLeftRadius:
1153     case CSSPropertyBorderTopRightRadius:
1154     case CSSPropertyBorderTopStyle:
1155     case CSSPropertyBorderTopWidth:
1156     case CSSPropertyColor:
1157     case CSSPropertyFloat:
1158     case CSSPropertyFont:
1159     case CSSPropertyFontFamily:
1160     case CSSPropertyFontKerning:
1161     case CSSPropertyFontSize:
1162     case CSSPropertyFontStretch:
1163     case CSSPropertyFontStyle:
1164     case CSSPropertyFontVariant:
1165     case CSSPropertyFontVariantLigatures:
1166     case CSSPropertyFontWeight:
1167     case CSSPropertyLetterSpacing:
1168     case CSSPropertyLineHeight:
1169     case CSSPropertyMarginBottom:
1170     case CSSPropertyMarginLeft:
1171     case CSSPropertyMarginRight:
1172     case CSSPropertyMarginTop:
1173     case CSSPropertyPaddingBottom:
1174     case CSSPropertyPaddingLeft:
1175     case CSSPropertyPaddingRight:
1176     case CSSPropertyPaddingTop:
1177     case CSSPropertyTextTransform:
1178     case CSSPropertyVerticalAlign:
1179     case CSSPropertyWebkitBackgroundClip:
1180     case CSSPropertyWebkitBackgroundComposite:
1181     case CSSPropertyWebkitBackgroundOrigin:
1182     case CSSPropertyWebkitBackgroundSize:
1183     case CSSPropertyWebkitBorderAfter:
1184     case CSSPropertyWebkitBorderAfterColor:
1185     case CSSPropertyWebkitBorderAfterStyle:
1186     case CSSPropertyWebkitBorderAfterWidth:
1187     case CSSPropertyWebkitBorderBefore:
1188     case CSSPropertyWebkitBorderBeforeColor:
1189     case CSSPropertyWebkitBorderBeforeStyle:
1190     case CSSPropertyWebkitBorderBeforeWidth:
1191     case CSSPropertyWebkitBorderEnd:
1192     case CSSPropertyWebkitBorderEndColor:
1193     case CSSPropertyWebkitBorderEndStyle:
1194     case CSSPropertyWebkitBorderEndWidth:
1195     case CSSPropertyWebkitBorderFit:
1196     case CSSPropertyWebkitBorderHorizontalSpacing:
1197     case CSSPropertyWebkitBorderImage:
1198     case CSSPropertyWebkitBorderRadius:
1199     case CSSPropertyWebkitBorderStart:
1200     case CSSPropertyWebkitBorderStartColor:
1201     case CSSPropertyWebkitBorderStartStyle:
1202     case CSSPropertyWebkitBorderStartWidth:
1203     case CSSPropertyWebkitBorderVerticalSpacing:
1204     case CSSPropertyWebkitFontSmoothing:
1205     case CSSPropertyWebkitMarginAfter:
1206     case CSSPropertyWebkitMarginAfterCollapse:
1207     case CSSPropertyWebkitMarginBefore:
1208     case CSSPropertyWebkitMarginBeforeCollapse:
1209     case CSSPropertyWebkitMarginBottomCollapse:
1210     case CSSPropertyWebkitMarginCollapse:
1211     case CSSPropertyWebkitMarginEnd:
1212     case CSSPropertyWebkitMarginStart:
1213     case CSSPropertyWebkitMarginTopCollapse:
1214     case CSSPropertyWordSpacing:
1215         return true;
1216     case CSSPropertyTextDecorationColor:
1217     case CSSPropertyTextDecorationLine:
1218     case CSSPropertyTextDecorationStyle:
1219         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
1220 
1221     // text-shadow added in text decoration spec:
1222     // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property
1223     case CSSPropertyTextShadow:
1224     // box-shadox added in CSS3 backgrounds spec:
1225     // http://www.w3.org/TR/css3-background/#placement
1226     case CSSPropertyBoxShadow:
1227     case CSSPropertyWebkitBoxShadow:
1228     // Properties that we currently support outside of spec.
1229     case CSSPropertyWebkitLineBoxContain:
1230     case CSSPropertyVisibility:
1231         return true;
1232 
1233     default:
1234         return false;
1235     }
1236 }
1237 
1238 // FIXME: Consider refactoring to create a new class which owns the following
1239 // first/last/range properties.
1240 // This method returns the first CSSPropertyId of properties which generate
1241 // animations. All animation properties are obtained by using
1242 // firstCSSPropertyId<AnimationProperties> and
1243 // lastCSSPropertyId<AnimationProperties>.
1244 // c.f. //src/third_party/WebKit/Source/core/css/CSSPropertyNames.in.
firstCSSPropertyId()1245 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::AnimationProperties>()
1246 {
1247     COMPILE_ASSERT(firstCSSProperty == CSSPropertyDisplay, CSS_first_animation_property_should_be_first_property);
1248     return CSSPropertyDisplay;
1249 }
1250 
1251 // This method returns the first CSSPropertyId of properties which generate
1252 // animations.
lastCSSPropertyId()1253 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::AnimationProperties>()
1254 {
1255     COMPILE_ASSERT(CSSPropertyTransitionTimingFunction == CSSPropertyColor - 1, CSS_transition_timing_is_last_animation_property);
1256     return CSSPropertyTransitionTimingFunction;
1257 }
1258 
1259 // This method returns the first CSSPropertyId of high priority properties.
1260 // Other properties can depend on high priority properties. For example,
1261 // border-color property with currentColor value depends on color property.
1262 // All high priority properties are obtained by using
1263 // firstCSSPropertyId<HighPriorityProperties> and
1264 // lastCSSPropertyId<HighPriorityProperties>.
firstCSSPropertyId()1265 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::HighPriorityProperties>()
1266 {
1267     COMPILE_ASSERT(CSSPropertyTransitionTimingFunction + 1 == CSSPropertyColor, CSS_color_is_first_high_priority_property);
1268     return CSSPropertyColor;
1269 }
1270 
1271 // This method returns the last CSSPropertyId of high priority properties.
lastCSSPropertyId()1272 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::HighPriorityProperties>()
1273 {
1274     COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyColor + 17, CSS_line_height_is_end_of_high_prioity_property_range);
1275     COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyLineHeight - 1, CSS_zoom_is_before_line_height);
1276     return CSSPropertyLineHeight;
1277 }
1278 
1279 // This method returns the first CSSPropertyId of remaining properties,
1280 // i.e. low priority properties. No properties depend on low priority
1281 // properties. So we don't need to resolve such properties quickly.
1282 // All low priority properties are obtained by using
1283 // firstCSSPropertyId<LowPriorityProperties> and
1284 // lastCSSPropertyId<LowPriorityProperties>.
firstCSSPropertyId()1285 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::LowPriorityProperties>()
1286 {
1287     COMPILE_ASSERT(CSSPropertyBackground == CSSPropertyLineHeight + 1, CSS_background_is_first_low_priority_property);
1288     return CSSPropertyBackground;
1289 }
1290 
1291 // This method returns the last CSSPropertyId of low priority properties.
lastCSSPropertyId()1292 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::LowPriorityProperties>()
1293 {
1294     return static_cast<CSSPropertyID>(lastCSSProperty);
1295 }
1296 
1297 template <StyleResolver::StyleApplicationPass pass>
isPropertyForPass(CSSPropertyID property)1298 bool StyleResolver::isPropertyForPass(CSSPropertyID property)
1299 {
1300     return firstCSSPropertyId<pass>() <= property && property <= lastCSSPropertyId<pass>();
1301 }
1302 
1303 // This method expands all shorthand property to longhand properties
1304 // considering StyleApplicationPass, and apply each expanded longhand property.
1305 // For example, if StyleApplicationPass is AnimationProperties, all shorthand
1306 // is expaneded to display, -webkit-animation, -webkit-animation-delay, ...,
1307 // transition-timing-function. So each property's value will be applied
1308 // according to all's value (initial, inherit or unset).
1309 template <StyleResolver::StyleApplicationPass pass>
applyAllProperty(StyleResolverState & state,CSSValue * allValue)1310 void StyleResolver::applyAllProperty(StyleResolverState& state, CSSValue* allValue)
1311 {
1312     bool isUnsetValue = !allValue->isInitialValue() && !allValue->isInheritedValue();
1313     unsigned startCSSProperty = firstCSSPropertyId<pass>();
1314     unsigned endCSSProperty = lastCSSPropertyId<pass>();
1315 
1316     for (unsigned i = startCSSProperty; i <= endCSSProperty; ++i) {
1317         CSSPropertyID propertyId = static_cast<CSSPropertyID>(i);
1318 
1319         // StyleBuilder does not allow any expanded shorthands.
1320         if (isExpandedShorthandForAll(propertyId))
1321             continue;
1322 
1323         // all shorthand spec says:
1324         // The all property is a shorthand that resets all CSS properties
1325         // except direction and unicode-bidi.
1326         // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand
1327         // We skip applyProperty when a given property is unicode-bidi or
1328         // direction.
1329         if (!CSSProperty::isAffectedByAllProperty(propertyId))
1330             continue;
1331 
1332         CSSValue* value;
1333         if (!isUnsetValue) {
1334             value = allValue;
1335         } else {
1336             if (CSSProperty::isInheritedProperty(propertyId))
1337                 value = cssValuePool().createInheritedValue().get();
1338             else
1339                 value = cssValuePool().createExplicitInitialValue().get();
1340         }
1341         StyleBuilder::applyProperty(propertyId, state, value);
1342     }
1343 }
1344 
1345 template <StyleResolver::StyleApplicationPass pass>
applyProperties(StyleResolverState & state,const StylePropertySet * properties,StyleRule * rule,bool isImportant,bool inheritedOnly,PropertyWhitelistType propertyWhitelistType)1346 void StyleResolver::applyProperties(StyleResolverState& state, const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
1347 {
1348     state.setCurrentRule(rule);
1349 
1350     unsigned propertyCount = properties->propertyCount();
1351     for (unsigned i = 0; i < propertyCount; ++i) {
1352         StylePropertySet::PropertyReference current = properties->propertyAt(i);
1353         if (isImportant != current.isImportant())
1354             continue;
1355 
1356         CSSPropertyID property = current.id();
1357         if (property == CSSPropertyAll) {
1358             applyAllProperty<pass>(state, current.value());
1359             continue;
1360         }
1361 
1362         if (inheritedOnly && !current.isInherited()) {
1363             // If the property value is explicitly inherited, we need to apply further non-inherited properties
1364             // as they might override the value inherited here. For this reason we don't allow declarations with
1365             // explicitly inherited properties to be cached.
1366             ASSERT(!current.value()->isInheritedValue());
1367             continue;
1368         }
1369 
1370         if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(property))
1371             continue;
1372         if (propertyWhitelistType == PropertyWhitelistFirstLetter && !isValidFirstLetterStyleProperty(property))
1373             continue;
1374         if (!isPropertyForPass<pass>(property))
1375             continue;
1376         if (pass == HighPriorityProperties && property == CSSPropertyLineHeight)
1377             state.setLineHeightValue(current.value());
1378         else
1379             StyleBuilder::applyProperty(current.id(), state, current.value());
1380     }
1381 }
1382 
1383 template <StyleResolver::StyleApplicationPass pass>
applyMatchedProperties(StyleResolverState & state,const MatchResult & matchResult,bool isImportant,int startIndex,int endIndex,bool inheritedOnly)1384 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
1385 {
1386     if (startIndex == -1)
1387         return;
1388 
1389     if (state.style()->insideLink() != NotInsideLink) {
1390         for (int i = startIndex; i <= endIndex; ++i) {
1391             const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1392             unsigned linkMatchType = matchedProperties.linkMatchType;
1393             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
1394             state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink);
1395             state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited);
1396 
1397             applyProperties<pass>(state, matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
1398         }
1399         state.setApplyPropertyToRegularStyle(true);
1400         state.setApplyPropertyToVisitedLinkStyle(false);
1401         return;
1402     }
1403     for (int i = startIndex; i <= endIndex; ++i) {
1404         const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1405         applyProperties<pass>(state, matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
1406     }
1407 }
1408 
computeMatchedPropertiesHash(const MatchedProperties * properties,unsigned size)1409 static unsigned computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
1410 {
1411     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
1412 }
1413 
invalidateMatchedPropertiesCache()1414 void StyleResolver::invalidateMatchedPropertiesCache()
1415 {
1416     m_matchedPropertiesCache.clear();
1417 }
1418 
notifyResizeForViewportUnits()1419 void StyleResolver::notifyResizeForViewportUnits()
1420 {
1421     collectViewportRules();
1422     m_matchedPropertiesCache.clearViewportDependent();
1423 }
1424 
applyMatchedProperties(StyleResolverState & state,const MatchResult & matchResult)1425 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult)
1426 {
1427     const Element* element = state.element();
1428     ASSERT(element);
1429 
1430     INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyApply);
1431 
1432     unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
1433     bool applyInheritedOnly = false;
1434     const CachedMatchedProperties* cachedMatchedProperties = 0;
1435 
1436     if (cacheHash && (cachedMatchedProperties = m_matchedPropertiesCache.find(cacheHash, state, matchResult))
1437         && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
1438         INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheHit);
1439         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
1440         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
1441         // element context. This is fast and saves memory by reusing the style data structures.
1442         state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get());
1443         if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && !isAtShadowBoundary(element)
1444             && (!state.distributedToInsertionPoint() || state.style()->userModify() == READ_ONLY)) {
1445             INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit);
1446 
1447             EInsideLink linkStatus = state.style()->insideLink();
1448             // If the cache item parent style has identical inherited properties to the current parent style then the
1449             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
1450             state.style()->inheritFrom(cachedMatchedProperties->renderStyle.get());
1451 
1452             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
1453             state.style()->setInsideLink(linkStatus);
1454             return;
1455         }
1456         applyInheritedOnly = true;
1457     }
1458 
1459     // Apply animation properties in order to apply animation results and trigger transitions below.
1460     applyMatchedProperties<AnimationProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1461     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1462     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1463     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1464 
1465     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
1466     // high-priority properties first, i.e., those properties that other properties depend on.
1467     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1468     // and (4) normal important.
1469     state.setLineHeightValue(0);
1470     applyMatchedProperties<HighPriorityProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1471     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1472     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1473     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1474 
1475     if (UNLIKELY(isSVGForeignObjectElement(element))) {
1476         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should not be scaled again.
1477         //
1478         // FIXME: The following hijacks the zoom property for foreignObject so that children of foreignObject get the
1479         // correct font-size in case of zooming. 'zoom' is part of HighPriorityProperties, along with other font-related
1480         // properties used as input to the FontBuilder, so resetting it here may cause the FontBuilder to recompute the
1481         // font used as inheritable font for foreignObject content. If we want to support zoom on foreignObject we'll
1482         // need to find another way of handling the SVG zoom model.
1483         state.setEffectiveZoom(RenderStyle::initialZoom());
1484     }
1485 
1486     if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) {
1487         state.fontBuilder().setFontDirty(true);
1488         applyInheritedOnly = false;
1489     }
1490 
1491     // If our font got dirtied, go ahead and update it now.
1492     updateFont(state);
1493 
1494     // Line-height is set when we are sure we decided on the font-size.
1495     if (state.lineHeightValue())
1496         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
1497 
1498     // Many properties depend on the font. If it changes we just apply all properties.
1499     if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->fontDescription() != state.style()->fontDescription())
1500         applyInheritedOnly = false;
1501 
1502     // Now do the normal priority UA properties.
1503     applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1504 
1505     // Cache the UA properties to pass them to RenderTheme in adjustRenderStyle.
1506     state.cacheUserAgentBorderAndBackground();
1507 
1508     // Now do the author and user normal priority properties and all the !important properties.
1509     applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1510     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1511     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1512     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1513 
1514     loadPendingResources(state);
1515 
1516     if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
1517         INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded);
1518         m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult);
1519     }
1520 
1521     ASSERT(!state.fontBuilder().fontDirty());
1522 }
1523 
CSSPropertyValue(CSSPropertyID id,const StylePropertySet & propertySet)1524 CSSPropertyValue::CSSPropertyValue(CSSPropertyID id, const StylePropertySet& propertySet)
1525     : property(id), value(propertySet.getPropertyCSSValue(id).get())
1526 { }
1527 
enableStats(StatsReportType reportType)1528 void StyleResolver::enableStats(StatsReportType reportType)
1529 {
1530     if (m_styleResolverStats)
1531         return;
1532     m_styleResolverStats = StyleResolverStats::create();
1533     m_styleResolverStatsTotals = StyleResolverStats::create();
1534     if (reportType == ReportSlowStats) {
1535         m_styleResolverStats->printMissedCandidateCount = true;
1536         m_styleResolverStatsTotals->printMissedCandidateCount = true;
1537     }
1538 }
1539 
disableStats()1540 void StyleResolver::disableStats()
1541 {
1542     m_styleResolverStatsSequence = 0;
1543     m_styleResolverStats.clear();
1544     m_styleResolverStatsTotals.clear();
1545 }
1546 
printStats()1547 void StyleResolver::printStats()
1548 {
1549     if (!m_styleResolverStats)
1550         return;
1551     fprintf(stderr, "=== Style Resolver Stats (resolve #%u) (%s) ===\n", ++m_styleResolverStatsSequence, m_document.url().string().utf8().data());
1552     fprintf(stderr, "%s\n", m_styleResolverStats->report().utf8().data());
1553     fprintf(stderr, "== Totals ==\n");
1554     fprintf(stderr, "%s\n", m_styleResolverStatsTotals->report().utf8().data());
1555 }
1556 
applyPropertiesToStyle(const CSSPropertyValue * properties,size_t count,RenderStyle * style)1557 void StyleResolver::applyPropertiesToStyle(const CSSPropertyValue* properties, size_t count, RenderStyle* style)
1558 {
1559     StyleResolverState state(document(), document().documentElement(), style);
1560     state.setStyle(style);
1561 
1562     state.fontBuilder().initForStyleResolve(document(), style);
1563 
1564     for (size_t i = 0; i < count; ++i) {
1565         if (properties[i].value) {
1566             // As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call,
1567             // which assumes the fontMetrics are available for the affected font, otherwise a crash occurs (see http://trac.webkit.org/changeset/96122).
1568             // The updateFont() call below updates the fontMetrics and ensure the proper setting of font-size and line-height.
1569             switch (properties[i].property) {
1570             case CSSPropertyFontSize:
1571             case CSSPropertyLineHeight:
1572                 updateFont(state);
1573                 break;
1574             default:
1575                 break;
1576             }
1577             StyleBuilder::applyProperty(properties[i].property, state, properties[i].value);
1578         }
1579     }
1580 }
1581 
addMediaQueryResults(const MediaQueryResultList & list)1582 void StyleResolver::addMediaQueryResults(const MediaQueryResultList& list)
1583 {
1584     for (size_t i = 0; i < list.size(); ++i)
1585         m_viewportDependentMediaQueryResults.append(list[i]);
1586 }
1587 
mediaQueryAffectedByViewportChange() const1588 bool StyleResolver::mediaQueryAffectedByViewportChange() const
1589 {
1590     for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) {
1591         if (m_medium->eval(m_viewportDependentMediaQueryResults[i]->expression()) != m_viewportDependentMediaQueryResults[i]->result())
1592             return true;
1593     }
1594     return false;
1595 }
1596 
trace(Visitor * visitor)1597 void StyleResolver::trace(Visitor* visitor)
1598 {
1599     visitor->trace(m_keyframesRuleMap);
1600     visitor->trace(m_viewportDependentMediaQueryResults);
1601     visitor->trace(m_viewportStyleResolver);
1602     visitor->trace(m_features);
1603     visitor->trace(m_siblingRuleSet);
1604     visitor->trace(m_uncommonAttributeRuleSet);
1605     visitor->trace(m_watchedSelectorsRules);
1606     visitor->trace(m_treeBoundaryCrossingRules);
1607     visitor->trace(m_pendingStyleSheets);
1608 }
1609 
1610 } // namespace WebCore
1611