1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@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 #include "config.h"
28 #include "core/css/resolver/ScopedStyleResolver.h"
29
30 #include "HTMLNames.h"
31 #include "core/css/CSSStyleSheet.h"
32 #include "core/css/PageRuleCollector.h"
33 #include "core/css/RuleFeature.h"
34 #include "core/css/StyleRule.h"
35 #include "core/css/StyleSheetContents.h"
36 #include "core/css/resolver/StyleResolver.h" // For MatchRequest.
37 #include "core/css/resolver/ViewportStyleResolver.h"
38 #include "core/dom/Document.h"
39 #include "core/dom/shadow/ElementShadow.h"
40 #include "core/dom/shadow/ShadowRoot.h"
41 #include "core/html/HTMLStyleElement.h"
42
43 namespace WebCore {
44
scopingNodeFor(Document & document,const CSSStyleSheet * sheet)45 ContainerNode* ScopedStyleResolver::scopingNodeFor(Document& document, const CSSStyleSheet* sheet)
46 {
47 ASSERT(sheet);
48
49 Document* sheetDocument = sheet->ownerDocument();
50 if (!sheetDocument)
51 return 0;
52 Node* ownerNode = sheet->ownerNode();
53 if (!ownerNode || !isHTMLStyleElement(ownerNode))
54 return &document;
55
56 HTMLStyleElement* styleElement = toHTMLStyleElement(ownerNode);
57 if (!styleElement->scoped()) {
58 if (styleElement->isInShadowTree())
59 return styleElement->containingShadowRoot();
60 return &document;
61 }
62
63 ContainerNode* parent = styleElement->parentNode();
64 if (!parent)
65 return 0;
66
67 return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
68 }
69
addRulesFromSheet(StyleSheetContents * sheet,const MediaQueryEvaluator & medium,StyleResolver * resolver)70 void ScopedStyleResolver::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver)
71 {
72 m_authorStyleSheets.append(sheet);
73
74 AddRuleFlags addRuleFlags = resolver->document().securityOrigin()->canRequest(sheet->baseURL()) ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState;
75 const RuleSet& ruleSet = sheet->ensureRuleSet(medium, addRuleFlags);
76 resolver->addMediaQueryResults(ruleSet.viewportDependentMediaQueryResults());
77 resolver->processScopedRules(ruleSet, sheet->baseURL(), &m_scopingNode);
78 }
79
collectFeaturesTo(RuleFeatureSet & features)80 void ScopedStyleResolver::collectFeaturesTo(RuleFeatureSet& features)
81 {
82 for (size_t i = 0; i < m_authorStyleSheets.size(); ++i)
83 features.add(m_authorStyleSheets[i]->ruleSet().features());
84 }
85
resetAuthorStyle()86 void ScopedStyleResolver::resetAuthorStyle()
87 {
88 m_authorStyleSheets.clear();
89 m_keyframesRuleMap.clear();
90 }
91
checkRegionStyle(Element * regionElement)92 bool ScopedStyleResolver::checkRegionStyle(Element* regionElement)
93 {
94 for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) {
95 const RuleSet& ruleSet = m_authorStyleSheets[i]->ruleSet();
96 for (unsigned i = 0; i < ruleSet.m_regionSelectorsAndRuleSets.size(); ++i) {
97 ASSERT(ruleSet.m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
98 if (checkRegionSelector(ruleSet.m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
99 return true;
100 }
101 }
102 return false;
103 }
104
keyframeStylesForAnimation(const StringImpl * animationName)105 const StyleRuleKeyframes* ScopedStyleResolver::keyframeStylesForAnimation(const StringImpl* animationName)
106 {
107 if (m_keyframesRuleMap.isEmpty())
108 return 0;
109
110 KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(animationName);
111 if (it == m_keyframesRuleMap.end())
112 return 0;
113
114 return it->value.get();
115 }
116
addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)117 void ScopedStyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
118 {
119 AtomicString s(rule->name());
120 if (rule->isVendorPrefixed()) {
121 KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(rule->name().impl());
122 if (it == m_keyframesRuleMap.end())
123 m_keyframesRuleMap.set(s.impl(), rule);
124 else if (it->value->isVendorPrefixed())
125 m_keyframesRuleMap.set(s.impl(), rule);
126 } else {
127 m_keyframesRuleMap.set(s.impl(), rule);
128 }
129 }
130
collectMatchingAuthorRules(ElementRuleCollector & collector,bool includeEmptyRules,bool applyAuthorStyles,CascadeScope cascadeScope,CascadeOrder cascadeOrder)131 void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, bool applyAuthorStyles, CascadeScope cascadeScope, CascadeOrder cascadeOrder)
132 {
133 const ContainerNode* scopingNode = &m_scopingNode;
134 unsigned behaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary;
135
136 if (!applyAuthorStyles)
137 behaviorAtBoundary |= SelectorChecker::ScopeContainsLastMatchedElement;
138
139 if (m_scopingNode.isShadowRoot()) {
140 scopingNode = toShadowRoot(m_scopingNode).host();
141 behaviorAtBoundary |= SelectorChecker::ScopeIsShadowHost;
142 }
143
144 RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
145 for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) {
146 MatchRequest matchRequest(&m_authorStyleSheets[i]->ruleSet(), includeEmptyRules, scopingNode, applyAuthorStyles, i);
147 collector.collectMatchingRules(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder);
148 collector.collectMatchingRulesForRegion(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder);
149 }
150 }
151
matchPageRules(PageRuleCollector & collector)152 void ScopedStyleResolver::matchPageRules(PageRuleCollector& collector)
153 {
154 // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
155 ASSERT(m_scopingNode.isDocumentNode());
156 for (size_t i = 0; i < m_authorStyleSheets.size(); ++i)
157 collector.matchPageRules(&m_authorStyleSheets[i]->ruleSet());
158 }
159
collectViewportRulesTo(StyleResolver * resolver) const160 void ScopedStyleResolver::collectViewportRulesTo(StyleResolver* resolver) const
161 {
162 if (!m_scopingNode.isDocumentNode())
163 return;
164 for (size_t i = 0; i < m_authorStyleSheets.size(); ++i)
165 resolver->viewportStyleResolver()->collectViewportRules(&m_authorStyleSheets[i]->ruleSet(), ViewportStyleResolver::AuthorOrigin);
166 }
167
168 } // namespace WebCore
169