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

Side by Side Diff: Source/core/css/invalidation/StyleSheetInvalidationAnalysis.cpp

Issue 1313443003: Fix crash when removing stylesheets from shadow tree. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Addressed review issues and added test. Created 5 years, 4 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 14 matching lines...) Expand all
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/css/invalidation/StyleSheetInvalidationAnalysis.h" 27 #include "core/css/invalidation/StyleSheetInvalidationAnalysis.h"
28 28
29 #include "core/css/CSSSelectorList.h" 29 #include "core/css/CSSSelectorList.h"
30 #include "core/css/StyleRuleImport.h" 30 #include "core/css/StyleRuleImport.h"
31 #include "core/css/StyleSheetContents.h" 31 #include "core/css/StyleSheetContents.h"
32 #include "core/dom/ContainerNode.h" 32 #include "core/dom/ContainerNode.h"
33 #include "core/dom/Document.h" 33 #include "core/dom/Document.h"
34 #include "core/dom/ElementTraversal.h" 34 #include "core/dom/ElementTraversal.h"
35 #include "core/dom/TreeScope.h"
35 #include "core/dom/shadow/ShadowRoot.h" 36 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/html/HTMLStyleElement.h" 37 #include "core/html/HTMLStyleElement.h"
37 38
38 namespace blink { 39 namespace blink {
39 40
40 StyleSheetInvalidationAnalysis::StyleSheetInvalidationAnalysis(const WillBeHeapV ector<RawPtrWillBeMember<StyleSheetContents>>& sheets) 41 StyleSheetInvalidationAnalysis::StyleSheetInvalidationAnalysis(const TreeScope& treeScope, const WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents>>& sheet s)
41 : m_dirtiesAllStyle(false) 42 : m_treeScope(treeScope)
42 { 43 {
43 for (unsigned i = 0; i < sheets.size() && !m_dirtiesAllStyle; ++i) 44 for (unsigned i = 0; i < sheets.size() && !m_dirtiesAllStyle; ++i)
44 analyzeStyleSheet(sheets[i]); 45 analyzeStyleSheet(sheets[i]);
45 } 46 }
46 47
47 static bool determineSelectorScopes(const CSSSelectorList& selectorList, HashSet <StringImpl*>& idScopes, HashSet<StringImpl*>& classScopes) 48 static bool determineSelectorScopes(const CSSSelectorList& selectorList, HashSet <StringImpl*>& idScopes, HashSet<StringImpl*>& classScopes)
48 { 49 {
49 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) { 50 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
50 const CSSSelector* scopeSelector = 0; 51 const CSSSelector* scopeSelector = 0;
51 // This picks the widest scope, not the narrowest, to minimize the numbe r of found scopes. 52 // This picks the widest scope, not the narrowest, to minimize the numbe r of found scopes.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 const StyleRule* styleRule = toStyleRule(rule); 86 const StyleRule* styleRule = toStyleRule(rule);
86 const CSSSelectorList& selectorList = styleRule->selectorList(); 87 const CSSSelectorList& selectorList = styleRule->selectorList();
87 for (size_t selectorIndex = 0; selectorIndex != kNotFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex)) { 88 for (size_t selectorIndex = 0; selectorIndex != kNotFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex)) {
88 if (selectorList.hasShadowDistributedAt(selectorIndex)) 89 if (selectorList.hasShadowDistributedAt(selectorIndex))
89 return true; 90 return true;
90 } 91 }
91 } 92 }
92 return false; 93 return false;
93 } 94 }
94 95
95 static Node* determineScopingNodeForStyleInShadow(HTMLStyleElement* ownerElement , StyleSheetContents* styleSheetContents)
96 {
97 ASSERT(ownerElement && ownerElement->isInShadowTree());
98
99 if (hasDistributedRule(styleSheetContents)) {
100 ContainerNode* scope = ownerElement;
101 do {
102 scope = scope->containingShadowRoot()->shadowHost();
103 } while (scope->isInShadowTree());
104 return scope;
105 }
106
107 return ownerElement->containingShadowRoot()->shadowHost();
108 }
109
110 static bool ruleAdditionMightRequireDocumentStyleRecalc(StyleRuleBase* rule) 96 static bool ruleAdditionMightRequireDocumentStyleRecalc(StyleRuleBase* rule)
111 { 97 {
112 // This funciton is conservative. We only return false when we know that 98 // This funciton is conservative. We only return false when we know that
113 // the added @rule can't require style recalcs. 99 // the added @rule can't require style recalcs.
114 switch (rule->type()) { 100 switch (rule->type()) {
115 case StyleRule::Import: // Whatever we import should do its own analysis, we don't need to invalidate the document here! 101 case StyleRule::Import: // Whatever we import should do its own analysis, we don't need to invalidate the document here!
116 case StyleRule::Page: // Page rules apply only during printing, we force a f ull-recalc before printing. 102 case StyleRule::Page: // Page rules apply only during printing, we force a f ull-recalc before printing.
117 return false; 103 return false;
118 104
119 case StyleRule::Media: // If the media rule doesn't apply, we could avoid re calc. 105 case StyleRule::Media: // If the media rule doesn't apply, we could avoid re calc.
(...skipping 25 matching lines...) Expand all
145 // See if all rules on the sheet are scoped to some specific ids or classes. 131 // See if all rules on the sheet are scoped to some specific ids or classes.
146 // Then test if we actually have any of those in the tree at the moment. 132 // Then test if we actually have any of those in the tree at the moment.
147 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport>>& importRules = s tyleSheetContents->importRules(); 133 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport>>& importRules = s tyleSheetContents->importRules();
148 for (unsigned i = 0; i < importRules.size(); ++i) { 134 for (unsigned i = 0; i < importRules.size(); ++i) {
149 if (!importRules[i]->styleSheet()) 135 if (!importRules[i]->styleSheet())
150 continue; 136 continue;
151 analyzeStyleSheet(importRules[i]->styleSheet()); 137 analyzeStyleSheet(importRules[i]->styleSheet());
152 if (m_dirtiesAllStyle) 138 if (m_dirtiesAllStyle)
153 return; 139 return;
154 } 140 }
155 if (styleSheetContents->hasSingleOwnerNode()) { 141
156 Node* ownerNode = styleSheetContents->singleOwnerNode(); 142 if (m_treeScope.rootNode().isShadowRoot()) {
157 if (isHTMLStyleElement(ownerNode) && toHTMLStyleElement(*ownerNode).isIn ShadowTree()) { 143 if (hasDistributedRule(styleSheetContents))
158 m_scopingNodes.append(determineScopingNodeForStyleInShadow(toHTMLSty leElement(ownerNode), styleSheetContents)); 144 m_hasDistributedRules = true;
159 return; 145 return;
160 }
161 } 146 }
162 147
163 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase>>& rules = styleShee tContents->childRules(); 148 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase>>& rules = styleShee tContents->childRules();
164 for (unsigned i = 0; i < rules.size(); i++) { 149 for (unsigned i = 0; i < rules.size(); i++) {
165 StyleRuleBase* rule = rules[i].get(); 150 StyleRuleBase* rule = rules[i].get();
166 if (!rule->isStyleRule()) { 151 if (!rule->isStyleRule()) {
167 if (ruleAdditionMightRequireDocumentStyleRecalc(rule)) { 152 if (ruleAdditionMightRequireDocumentStyleRecalc(rule)) {
168 m_dirtiesAllStyle = true; 153 m_dirtiesAllStyle = true;
169 return; 154 return;
170 } 155 }
(...skipping 14 matching lines...) Expand all
185 if (classScopes.isEmpty() || !element->hasClass()) 170 if (classScopes.isEmpty() || !element->hasClass())
186 return false; 171 return false;
187 const SpaceSplitString& classNames = element->classNames(); 172 const SpaceSplitString& classNames = element->classNames();
188 for (unsigned i = 0; i < classNames.size(); ++i) { 173 for (unsigned i = 0; i < classNames.size(); ++i) {
189 if (classScopes.contains(classNames[i].impl())) 174 if (classScopes.contains(classNames[i].impl()))
190 return true; 175 return true;
191 } 176 }
192 return false; 177 return false;
193 } 178 }
194 179
195 void StyleSheetInvalidationAnalysis::invalidateStyle(Document& document) 180 static ContainerNode* outermostShadowHost(const ShadowRoot& root)
181 {
182 ContainerNode* host = root.host();
183 while (host->isInShadowTree())
184 host = host->containingShadowRoot()->host();
185 return host;
186 }
187
188 void StyleSheetInvalidationAnalysis::invalidateStyle()
196 { 189 {
197 ASSERT(!m_dirtiesAllStyle); 190 ASSERT(!m_dirtiesAllStyle);
198 191
199 if (!m_scopingNodes.isEmpty()) { 192 if (m_treeScope.rootNode().isShadowRoot()) {
200 for (unsigned i = 0; i < m_scopingNodes.size(); ++i) 193 ContainerNode* invalidationRoot = &m_treeScope.rootNode();
201 m_scopingNodes.at(i)->setNeedsStyleRecalc(SubtreeStyleChange, StyleC hangeReasonForTracing::create(StyleChangeReason::StyleSheetChange)); 194 if (m_hasDistributedRules)
195 invalidationRoot = outermostShadowHost(*toShadowRoot(invalidationRoo t));
196 invalidationRoot->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeRea sonForTracing::create(StyleChangeReason::StyleSheetChange));
197 return;
202 } 198 }
203 199
204 if (m_idScopes.isEmpty() && m_classScopes.isEmpty()) 200 if (m_idScopes.isEmpty() && m_classScopes.isEmpty())
205 return; 201 return;
206 Element* element = ElementTraversal::firstWithin(document); 202 Element* element = ElementTraversal::firstWithin(m_treeScope.document());
207 while (element) { 203 while (element) {
208 if (elementMatchesSelectorScopes(element, m_idScopes, m_classScopes)) { 204 if (elementMatchesSelectorScopes(element, m_idScopes, m_classScopes)) {
209 element->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonFo rTracing::create(StyleChangeReason::StyleSheetChange)); 205 element->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonFo rTracing::create(StyleChangeReason::StyleSheetChange));
210 // The whole subtree is now invalidated, we can skip to the next sib ling. 206 // The whole subtree is now invalidated, we can skip to the next sib ling.
211 element = ElementTraversal::nextSkippingChildren(*element); 207 element = ElementTraversal::nextSkippingChildren(*element);
212 continue; 208 continue;
213 } 209 }
214 element = ElementTraversal::next(*element); 210 element = ElementTraversal::next(*element);
215 } 211 }
216 } 212 }
217 213
218 } 214 }
OLDNEW
« no previous file with comments | « Source/core/css/invalidation/StyleSheetInvalidationAnalysis.h ('k') | Source/core/dom/TreeScopeStyleSheetCollection.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698