Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: Source/core/css/ScopedStyleResolver.cpp

Issue 15072003: Move StyleResolver and related classes to core/css/resolver (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/css/ScopedStyleResolver.h ('k') | Source/core/css/StyleMedia.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 AN Y
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 AN Y
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 O N
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/ScopedStyleResolver.h"
29
30 #include "HTMLNames.h"
31 #include "core/css/CSSStyleRule.h"
32 #include "core/css/CSSStyleSheet.h"
33 #include "core/css/RuleFeature.h"
34 #include "core/css/RuleSet.h"
35 #include "core/dom/ContextFeatures.h"
36 #include "core/dom/ElementShadow.h"
37 #include "core/dom/ShadowRoot.h"
38 #include "core/dom/WebCoreMemoryInstrumentation.h"
39 #include "core/html/HTMLStyleElement.h"
40 #include "core/html/shadow/ContentDistributor.h"
41 #include <wtf/MemoryInstrumentationHashMap.h>
42 #include <wtf/MemoryInstrumentationHashSet.h>
43 #include <wtf/MemoryInstrumentationVector.h>
44
45 namespace WebCore {
46
47 ScopedStyleResolver::ScopedStyleResolver()
48 : m_stackParent(0)
49 , m_stackParentBoundsIndex(0)
50 {
51 }
52
53 ScopedStyleResolver::~ScopedStyleResolver()
54 {
55 }
56
57 const ContainerNode* ScopedStyleResolver::scopeFor(const CSSStyleSheet* sheet)
58 {
59 ASSERT(sheet);
60
61 Document* document = sheet->ownerDocument();
62 if (!document)
63 return 0;
64 Node* ownerNode = sheet->ownerNode();
65 if (!ownerNode || !ownerNode->isHTMLElement() || !ownerNode->hasTagName(HTML Names::styleTag))
66 return 0;
67
68 HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode);
69 if (!styleElement->scoped())
70 return styleElement->isInShadowTree() ? styleElement->containingShadowRo ot() : 0;
71
72 ContainerNode* parent = styleElement->parentNode();
73 if (!parent)
74 return 0;
75
76 return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
77 }
78
79 inline RuleSet* ScopedStyleResolver::ruleSetFor(const ContainerNode* scope) cons t
80 {
81 if (!scope->hasScopedHTMLStyleChild())
82 return 0;
83 ScopedRuleSetMap::const_iterator it = m_authorStyles.find(scope);
84 return it != m_authorStyles.end() ? it->value.get() : 0;
85 }
86
87 RuleSet* ScopedStyleResolver::ensureRuleSetFor(const ContainerNode* scope)
88 {
89 ScopedRuleSetMap::AddResult addResult = m_authorStyles.add(scope, nullptr);
90 if (addResult.isNewEntry)
91 addResult.iterator->value = RuleSet::create();
92 return addResult.iterator->value.get();
93 }
94
95 void ScopedStyleResolver::setupStack(const ContainerNode* parent)
96 {
97 // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere.
98 ASSERT(!m_authorStyles.isEmpty());
99
100 m_stack.shrink(0);
101 int authorStyleBoundsIndex = 0;
102 for (const ContainerNode* scope = parent; scope; scope = scope->parentOrShad owHostNode()) {
103 RuleSet* ruleSet = ruleSetFor(scope);
104 if (ruleSet)
105 m_stack.append(StackFrame(scope, authorStyleBoundsIndex, ruleSet));
106 if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
107 --authorStyleBoundsIndex;
108 }
109
110 m_stack.reverse();
111 m_stackParent = parent;
112 m_stackParentBoundsIndex = 0;
113 }
114
115 void ScopedStyleResolver::push(const ContainerNode* scope, const ContainerNode* scopeParent)
116 {
117 // Shortcut: Don't bother with the scoping element stack if <style scoped> i sn't used anywhere.
118 if (m_authorStyles.isEmpty()) {
119 ASSERT(!m_stackParent);
120 ASSERT(m_stack.isEmpty());
121 return;
122 }
123
124 // In some wacky cases during style resolve we may get invoked for random el ements.
125 // Recreate the whole scoping element stack in such cases.
126 if (!stackIsConsistent(scopeParent)) {
127 setupStack(scope);
128 return;
129 }
130
131 if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
132 ++m_stackParentBoundsIndex;
133 // Otherwise just push the parent onto the stack.
134 RuleSet* ruleSet = ruleSetFor(scope);
135 if (ruleSet)
136 m_stack.append(StackFrame(scope, m_stackParentBoundsIndex, ruleSet));
137 m_stackParent = scope;
138 }
139
140 void ScopedStyleResolver::pop(const ContainerNode* scope)
141 {
142 // Only bother to update the scoping element stack if it is consistent.
143 if (stackIsConsistent(scope)) {
144 if (!m_stack.isEmpty() && m_stack.last().m_scope == scope)
145 m_stack.removeLast();
146 if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
147 --m_stackParentBoundsIndex;
148 m_stackParent = scope->parentOrShadowHostNode();
149 }
150 }
151
152 void ScopedStyleResolver::collectFeaturesTo(RuleFeatureSet& features)
153 {
154 for (ScopedRuleSetMap::iterator it = m_authorStyles.begin(); it != m_authorS tyles.end(); ++it)
155 features.add(it->value->features());
156 for (ScopedRuleSetMap::iterator it = m_atHostRules.begin(); it != m_atHostRu les.end(); ++it)
157 features.add(it->value->features());
158 }
159
160 inline RuleSet* ScopedStyleResolver::ensureAtHostRuleSetFor(const ShadowRoot* sh adowRoot)
161 {
162 ScopedRuleSetMap::AddResult addResult = m_atHostRules.add(shadowRoot, nullpt r);
163 if (addResult.isNewEntry)
164 addResult.iterator->value = RuleSet::create();
165 return addResult.iterator->value.get();
166 }
167
168 inline RuleSet* ScopedStyleResolver::atHostRuleSetFor(const ShadowRoot* shadowRo ot) const
169 {
170 ScopedRuleSetMap::const_iterator it = m_atHostRules.find(shadowRoot);
171 return it != m_atHostRules.end() ? it->value.get() : 0;
172 }
173
174 void ScopedStyleResolver::addHostRule(StyleRuleHost* hostRule, bool hasDocumentS ecurityOrigin, const ContainerNode* scope)
175 {
176 if (!scope || !scope->isInShadowTree())
177 return;
178
179 ShadowRoot* shadowRoot = scope->containingShadowRoot();
180 if (!shadowRoot || !shadowRoot->host())
181 return;
182
183 RuleSet* rule = ensureAtHostRuleSetFor(shadowRoot);
184
185 const Vector<RefPtr<StyleRuleBase> >& childRules = hostRule->childRules();
186 AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecur ityOrigin : RuleHasNoSpecialState;
187 addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleCanUseFastCheckS elector);
188 for (unsigned i = 0; i < childRules.size(); ++i) {
189 StyleRuleBase* hostStylingRule = childRules[i].get();
190 if (hostStylingRule->isStyleRule())
191 rule->addStyleRule(static_cast<StyleRule*>(hostStylingRule), addRule Flags);
192 }
193 }
194
195 bool ScopedStyleResolver::styleSharingCandidateMatchesHostRules(const Element* e lement)
196 {
197 if (m_atHostRules.isEmpty())
198 return false;
199
200 ElementShadow* shadow = element->shadow();
201 if (!shadow)
202 return false;
203
204 // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
205 // add a new flag to ElementShadow and cache whether any@host @-rules are
206 // applied to the element or not. So we can avoid always traversing
207 // shadow roots.
208 for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shad owRoot = shadowRoot->olderShadowRoot()) {
209 if (atHostRuleSetFor(shadowRoot))
210 return true;
211
212 if (!ScopeContentDistribution::hasShadowElement(shadowRoot))
213 break;
214 }
215 return false;
216 }
217
218 void ScopedStyleResolver::matchHostRules(const Element* element, Vector<RuleSet* >& matchedRules)
219 {
220 if (m_atHostRules.isEmpty())
221 return;
222
223 ElementShadow* shadow = element->shadow();
224 if (!shadow)
225 return;
226
227 // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
228 // add a new flag to ElementShadow and cache whether any @host @-rules are
229 // applied to the element or not. So we can quickly exit this method
230 // by using the flag.
231 for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shad owRoot = shadowRoot->olderShadowRoot()) {
232 if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot))
233 matchedRules.append(ruleSet);
234 if (!ScopeContentDistribution::hasShadowElement(shadowRoot))
235 break;
236 }
237 }
238
239 void ScopedStyleResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
240 {
241 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
242 info.addMember(m_authorStyles, "authorStyles");
243 info.addMember(m_stack, "stack");
244 info.addMember(m_atHostRules, "atHostRules");
245 info.addMember(m_stackParent, "stackParent");
246 }
247
248 }
249
OLDNEW
« no previous file with comments | « Source/core/css/ScopedStyleResolver.h ('k') | Source/core/css/StyleMedia.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698