1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 4 * Copyright (C) 2012 Google Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #ifndef ScopedStyleResolver_h 28 #define ScopedStyleResolver_h 29 30 #include "core/css/CSSKeyframesRule.h" 31 #include "core/css/ElementRuleCollector.h" 32 #include "core/css/RuleSet.h" 33 #include "core/dom/ContainerNode.h" 34 #include "core/dom/Element.h" 35 #include "wtf/Forward.h" 36 #include "wtf/HashMap.h" 37 #include "wtf/OwnPtr.h" 38 #include "wtf/PassOwnPtr.h" 39 #include "wtf/Vector.h" 40 41 namespace WebCore { 42 43 class ElementRuleCollector; 44 class MediaQueryEvaluator; 45 class PageRuleCollector; 46 class ShadowRoot; 47 class StyleSheetContents; 48 49 // This class selects a RenderStyle for a given element based on a collection of stylesheets. 50 class ScopedStyleResolver { 51 WTF_MAKE_NONCOPYABLE(ScopedStyleResolver); WTF_MAKE_FAST_ALLOCATED; 52 public: 53 static PassOwnPtr<ScopedStyleResolver> create(const ContainerNode* scopingNode) { return adoptPtr(new ScopedStyleResolver(scopingNode)); } 54 55 static const ContainerNode* scopingNodeFor(const CSSStyleSheet*); 56 57 const ContainerNode* scopingNode() const { return m_scopingNode; } 58 const TreeScope* treeScope() const { return m_scopingNode->treeScope(); } 59 void prepareEmptyRuleSet() { m_authorStyle = RuleSet::create(); } 60 void setParent(ScopedStyleResolver* newParent) { m_parent = newParent; } 61 ScopedStyleResolver* parent() { return m_parent; } 62 63 bool hasOnlyEmptyRuleSets() const { return !m_authorStyle->ruleCount() && m_atHostRules.isEmpty(); } 64 65 public: 66 bool checkRegionStyle(Element*); 67 const StyleRuleKeyframes* keyframeStylesForAnimation(const StringImpl* animationName); 68 void addKeyframeStyle(PassRefPtr<StyleRuleKeyframes>); 69 70 void matchHostRules(ElementRuleCollector&, bool includeEmptyRules); 71 void matchAuthorRules(ElementRuleCollector&, bool includeEmptyRules, bool applyAuthorStyles); 72 void collectMatchingAuthorRules(ElementRuleCollector&, bool includeEmptyRules, bool applyAuthorStyles, CascadeScope, CascadeOrder = ignoreCascadeOrder); 73 void matchPageRules(PageRuleCollector&); 74 void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, StyleResolver*); 75 void addHostRule(StyleRuleHost*, bool hasDocumentSecurityOrigin, const ContainerNode* scopingNode); 76 void collectFeaturesTo(RuleFeatureSet&); 77 void resetAuthorStyle(); 78 void resetAtHostRules(const ShadowRoot*); 79 void collectViewportRulesTo(StyleResolver*) const; 80 81 private: 82 ScopedStyleResolver() : m_scopingNode(0), m_parent(0) { } 83 ScopedStyleResolver(const ContainerNode* scopingNode) : m_scopingNode(scopingNode), m_parent(0) { } 84 85 RuleSet* ensureAtHostRuleSetFor(const ShadowRoot*); 86 RuleSet* atHostRuleSetFor(const ShadowRoot*) const; 87 88 const ContainerNode* m_scopingNode; 89 ScopedStyleResolver* m_parent; 90 91 OwnPtr<RuleSet> m_authorStyle; 92 HashMap<const ShadowRoot*, OwnPtr<RuleSet> > m_atHostRules; 93 94 typedef HashMap<const StringImpl*, RefPtr<StyleRuleKeyframes> > KeyframesRuleMap; 95 KeyframesRuleMap m_keyframesRuleMap; 96 }; 97 98 class ScopedStyleTree { 99 WTF_MAKE_NONCOPYABLE(ScopedStyleTree); WTF_MAKE_FAST_ALLOCATED; 100 public: 101 ScopedStyleTree() : m_scopedResolverForDocument(0), m_buildInDocumentOrder(true) { } 102 103 ScopedStyleResolver* ensureScopedStyleResolver(const ContainerNode* scopingNode); 104 ScopedStyleResolver* scopedStyleResolverFor(const ContainerNode* scopingNode); 105 ScopedStyleResolver* addScopedStyleResolver(const ContainerNode* scopingNode, bool& isNewEntry); 106 void clear(); 107 108 // for fast-path. 109 bool hasOnlyScopedResolverForDocument() const { return m_scopedResolverForDocument && m_authorStyles.size() == 1; } 110 ScopedStyleResolver* scopedStyleResolverForDocument() { return m_scopedResolverForDocument; } 111 112 void resolveScopedStyles(const Element*, Vector<ScopedStyleResolver*, 8>&); 113 void collectScopedResolversForHostedShadowTrees(const Element*, Vector<ScopedStyleResolver*, 8>&); 114 void resolveScopedKeyframesRules(const Element*, Vector<ScopedStyleResolver*, 8>&); 115 ScopedStyleResolver* scopedResolverFor(const Element*); 116 117 void remove(const ContainerNode* scopingNode); 118 119 void pushStyleCache(const ContainerNode* scopingNode, const ContainerNode* parent); 120 void popStyleCache(const ContainerNode* scopingNode); 121 122 void collectFeaturesTo(RuleFeatureSet& features); 123 void setBuildInDocumentOrder(bool enabled) { m_buildInDocumentOrder = enabled; } 124 bool buildInDocumentOrder() const { return m_buildInDocumentOrder; } 125 126 private: 127 void setupScopedStylesTree(ScopedStyleResolver* target); 128 129 bool cacheIsValid(const ContainerNode* parent) const { return parent && parent == m_cache.nodeForScopedStyles; } 130 void resolveStyleCache(const ContainerNode* scopingNode); 131 ScopedStyleResolver* enclosingScopedStyleResolverFor(const ContainerNode* scopingNode); 132 133 void reparentNodes(const ScopedStyleResolver* oldParent, ScopedStyleResolver* newParent); 134 135 private: 136 HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> > m_authorStyles; 137 ScopedStyleResolver* m_scopedResolverForDocument; 138 bool m_buildInDocumentOrder; 139 140 struct ScopedStyleCache { 141 ScopedStyleResolver* scopedResolver; 142 const ContainerNode* nodeForScopedStyles; 143 144 void clear() 145 { 146 scopedResolver = 0; 147 nodeForScopedStyles = 0; 148 } 149 }; 150 ScopedStyleCache m_cache; 151 }; 152 153 inline ScopedStyleResolver* ScopedStyleTree::scopedResolverFor(const Element* element) 154 { 155 if (!cacheIsValid(element)) 156 resolveStyleCache(element); 157 158 return m_cache.scopedResolver; 159 } 160 161 } // namespace WebCore 162 163 #endif // ScopedStyleResolver_h 164