• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
7  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8  * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
9  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
10  * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27 
28 #include "config.h"
29 #include "core/dom/StyleEngine.h"
30 
31 #include "HTMLNames.h"
32 #include "SVGNames.h"
33 #include "core/css/CSSFontSelector.h"
34 #include "core/css/CSSStyleSheet.h"
35 #include "core/css/StyleInvalidationAnalysis.h"
36 #include "core/css/StyleSheetContents.h"
37 #include "core/dom/Element.h"
38 #include "core/dom/ProcessingInstruction.h"
39 #include "core/dom/ShadowTreeStyleSheetCollection.h"
40 #include "core/dom/shadow/ShadowRoot.h"
41 #include "core/html/HTMLIFrameElement.h"
42 #include "core/html/HTMLImport.h"
43 #include "core/html/HTMLLinkElement.h"
44 #include "core/html/HTMLStyleElement.h"
45 #include "core/inspector/InspectorInstrumentation.h"
46 #include "core/page/Page.h"
47 #include "core/page/PageGroup.h"
48 #include "core/frame/Settings.h"
49 #include "core/svg/SVGStyleElement.h"
50 #include "platform/URLPatternMatcher.h"
51 
52 namespace WebCore {
53 
54 using namespace HTMLNames;
55 
StyleEngine(Document & document)56 StyleEngine::StyleEngine(Document& document)
57     : m_document(document)
58     , m_isMaster(HTMLImport::isMaster(&document))
59     , m_pendingStylesheets(0)
60     , m_injectedStyleSheetCacheValid(false)
61     , m_needsUpdateActiveStylesheetsOnStyleRecalc(false)
62     , m_documentStyleSheetCollection(document)
63     , m_documentScopeDirty(true)
64     , m_usesSiblingRules(false)
65     , m_usesSiblingRulesOverride(false)
66     , m_usesFirstLineRules(false)
67     , m_usesFirstLetterRules(false)
68     , m_usesRemUnits(false)
69     , m_maxDirectAdjacentSelectors(0)
70     , m_ignorePendingStylesheets(false)
71     , m_didCalculateResolver(false)
72     , m_lastResolverAccessCount(0)
73     , m_resolverThrowawayTimer(this, &StyleEngine::resolverThrowawayTimerFired)
74     // We don't need to create CSSFontSelector for imported document or
75     // HTMLTemplateElement's document, because those documents have no frame.
76     , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : 0)
77 {
78 }
79 
~StyleEngine()80 StyleEngine::~StyleEngine()
81 {
82     for (unsigned i = 0; i < m_injectedAuthorStyleSheets.size(); ++i)
83         m_injectedAuthorStyleSheets[i]->clearOwnerNode();
84     for (unsigned i = 0; i < m_authorStyleSheets.size(); ++i)
85         m_authorStyleSheets[i]->clearOwnerNode();
86 
87     if (m_fontSelector) {
88         m_fontSelector->clearDocument();
89         if (m_resolver)
90             m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
91     }
92 }
93 
master()94 inline Document* StyleEngine::master()
95 {
96     if (isMaster())
97         return &m_document;
98     HTMLImport* import = m_document.import();
99     if (!import) // Document::import() can return null while executing its destructor.
100         return 0;
101     return import->master();
102 }
103 
insertTreeScopeInDocumentOrder(TreeScopeSet & treeScopes,TreeScope * treeScope)104 void StyleEngine::insertTreeScopeInDocumentOrder(TreeScopeSet& treeScopes, TreeScope* treeScope)
105 {
106     if (treeScopes.isEmpty()) {
107         treeScopes.add(treeScope);
108         return;
109     }
110     if (treeScopes.contains(treeScope))
111         return;
112 
113     TreeScopeSet::iterator begin = treeScopes.begin();
114     TreeScopeSet::iterator end = treeScopes.end();
115     TreeScopeSet::iterator it = end;
116     TreeScope* followingTreeScope = 0;
117     do {
118         --it;
119         TreeScope* n = *it;
120         unsigned short position = n->comparePosition(*treeScope);
121         if (position & Node::DOCUMENT_POSITION_FOLLOWING) {
122             treeScopes.insertBefore(followingTreeScope, treeScope);
123             return;
124         }
125         followingTreeScope = n;
126     } while (it != begin);
127 
128     treeScopes.insertBefore(followingTreeScope, treeScope);
129 }
130 
ensureStyleSheetCollectionFor(TreeScope & treeScope)131 StyleSheetCollection* StyleEngine::ensureStyleSheetCollectionFor(TreeScope& treeScope)
132 {
133     if (treeScope == m_document)
134         return &m_documentStyleSheetCollection;
135 
136     HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::AddResult result = m_styleSheetCollectionMap.add(&treeScope, nullptr);
137     if (result.isNewEntry)
138         result.iterator->value = adoptPtr(new ShadowTreeStyleSheetCollection(toShadowRoot(treeScope)));
139     return result.iterator->value.get();
140 }
141 
styleSheetCollectionFor(TreeScope & treeScope)142 StyleSheetCollection* StyleEngine::styleSheetCollectionFor(TreeScope& treeScope)
143 {
144     if (treeScope == m_document)
145         return &m_documentStyleSheetCollection;
146 
147     HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::iterator it = m_styleSheetCollectionMap.find(&treeScope);
148     if (it == m_styleSheetCollectionMap.end())
149         return 0;
150     return it->value.get();
151 }
152 
styleSheetsForStyleSheetList(TreeScope & treeScope)153 const Vector<RefPtr<StyleSheet> >& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope)
154 {
155     if (treeScope == m_document)
156         return m_documentStyleSheetCollection.styleSheetsForStyleSheetList();
157 
158     return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetList();
159 }
160 
activeAuthorStyleSheets() const161 const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::activeAuthorStyleSheets() const
162 {
163     return m_documentStyleSheetCollection.activeAuthorStyleSheets();
164 }
165 
getActiveAuthorStyleSheets(Vector<const Vector<RefPtr<CSSStyleSheet>> * > & activeAuthorStyleSheets) const166 void StyleEngine::getActiveAuthorStyleSheets(Vector<const Vector<RefPtr<CSSStyleSheet> >*>& activeAuthorStyleSheets) const
167 {
168     activeAuthorStyleSheets.append(&m_documentStyleSheetCollection.activeAuthorStyleSheets());
169 
170     HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values begin = m_styleSheetCollectionMap.values().begin();
171     HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values end = m_styleSheetCollectionMap.values().end();
172     HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values it = begin;
173     for (; it != end; ++it) {
174         const StyleSheetCollection* collection = it->get();
175         activeAuthorStyleSheets.append(&collection->activeAuthorStyleSheets());
176     }
177 }
178 
combineCSSFeatureFlags(const RuleFeatureSet & features)179 void StyleEngine::combineCSSFeatureFlags(const RuleFeatureSet& features)
180 {
181     // Delay resetting the flags until after next style recalc since unapplying the style may not work without these set (this is true at least with before/after).
182     m_usesSiblingRules = m_usesSiblingRules || features.usesSiblingRules();
183     m_usesFirstLineRules = m_usesFirstLineRules || features.usesFirstLineRules();
184     m_maxDirectAdjacentSelectors = max(m_maxDirectAdjacentSelectors, features.maxDirectAdjacentSelectors());
185 }
186 
resetCSSFeatureFlags(const RuleFeatureSet & features)187 void StyleEngine::resetCSSFeatureFlags(const RuleFeatureSet& features)
188 {
189     m_usesSiblingRules = features.usesSiblingRules();
190     m_usesFirstLineRules = features.usesFirstLineRules();
191     m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors();
192 }
193 
injectedAuthorStyleSheets() const194 const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::injectedAuthorStyleSheets() const
195 {
196     updateInjectedStyleSheetCache();
197     return m_injectedAuthorStyleSheets;
198 }
199 
updateInjectedStyleSheetCache() const200 void StyleEngine::updateInjectedStyleSheetCache() const
201 {
202     if (m_injectedStyleSheetCacheValid)
203         return;
204     m_injectedStyleSheetCacheValid = true;
205     m_injectedAuthorStyleSheets.clear();
206 
207     Page* owningPage = m_document.page();
208     if (!owningPage)
209         return;
210 
211     const PageGroup& pageGroup = owningPage->group();
212     const InjectedStyleSheetVector& sheets = pageGroup.injectedStyleSheets();
213     for (unsigned i = 0; i < sheets.size(); ++i) {
214         const InjectedStyleSheet* sheet = sheets[i].get();
215         if (sheet->injectedFrames() == InjectStyleInTopFrameOnly && m_document.ownerElement())
216             continue;
217         if (!URLPatternMatcher::matchesPatterns(m_document.url(), sheet->whitelist()))
218             continue;
219         RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(&m_document), KURL());
220         m_injectedAuthorStyleSheets.append(groupSheet);
221         groupSheet->contents()->parseString(sheet->source());
222     }
223 }
224 
invalidateInjectedStyleSheetCache()225 void StyleEngine::invalidateInjectedStyleSheetCache()
226 {
227     m_injectedStyleSheetCacheValid = false;
228     markDocumentDirty();
229     // FIXME: updateInjectedStyleSheetCache is called inside StyleSheetCollection::updateActiveStyleSheets
230     // and batch updates lots of sheets so we can't call addedStyleSheet() or removedStyleSheet().
231     m_document.styleResolverChanged(RecalcStyleDeferred);
232 }
233 
addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet)234 void StyleEngine::addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet)
235 {
236     m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, &m_document));
237     m_document.addedStyleSheet(m_authorStyleSheets.last().get(), RecalcStyleImmediately);
238     markDocumentDirty();
239 }
240 
addPendingSheet()241 void StyleEngine::addPendingSheet()
242 {
243     master()->styleEngine()->notifyPendingStyleSheetAdded();
244 }
245 
246 // This method is called whenever a top-level stylesheet has finished loading.
removePendingSheet(Node * styleSheetCandidateNode,RemovePendingSheetNotificationType notification)247 void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, RemovePendingSheetNotificationType notification)
248 {
249     TreeScope* treeScope = isHTMLStyleElement(styleSheetCandidateNode) ? &styleSheetCandidateNode->treeScope() : &m_document;
250     markTreeScopeDirty(*treeScope);
251     master()->styleEngine()->notifyPendingStyleSheetRemoved(notification);
252 }
253 
notifyPendingStyleSheetAdded()254 void StyleEngine::notifyPendingStyleSheetAdded()
255 {
256     ASSERT(isMaster());
257     m_pendingStylesheets++;
258 }
259 
notifyPendingStyleSheetRemoved(RemovePendingSheetNotificationType notification)260 void StyleEngine::notifyPendingStyleSheetRemoved(RemovePendingSheetNotificationType notification)
261 {
262     ASSERT(isMaster());
263     // Make sure we knew this sheet was pending, and that our count isn't out of sync.
264     ASSERT(m_pendingStylesheets > 0);
265 
266     m_pendingStylesheets--;
267     if (m_pendingStylesheets)
268         return;
269 
270     if (notification == RemovePendingSheetNotifyLater) {
271         m_document.setNeedsNotifyRemoveAllPendingStylesheet();
272         return;
273     }
274 
275     // FIXME: We can't call addedStyleSheet or removedStyleSheet here because we don't know
276     // what's new. We should track that to tell the style system what changed.
277     m_document.didRemoveAllPendingStylesheet();
278 }
279 
modifiedStyleSheet(StyleSheet * sheet)280 void StyleEngine::modifiedStyleSheet(StyleSheet* sheet)
281 {
282     if (!sheet)
283         return;
284 
285     Node* node = sheet->ownerNode();
286     if (!node || !node->inDocument())
287         return;
288 
289     TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document;
290     ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
291 
292     markTreeScopeDirty(treeScope);
293 }
294 
addStyleSheetCandidateNode(Node * node,bool createdByParser)295 void StyleEngine::addStyleSheetCandidateNode(Node* node, bool createdByParser)
296 {
297     if (!node->inDocument())
298         return;
299 
300     TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document;
301     ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
302 
303     StyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope);
304     ASSERT(collection);
305     collection->addStyleSheetCandidateNode(node, createdByParser);
306 
307     markTreeScopeDirty(treeScope);
308     if (treeScope != m_document)
309         insertTreeScopeInDocumentOrder(m_activeTreeScopes, &treeScope);
310 }
311 
removeStyleSheetCandidateNode(Node * node,ContainerNode * scopingNode)312 void StyleEngine::removeStyleSheetCandidateNode(Node* node, ContainerNode* scopingNode)
313 {
314     TreeScope& treeScope = scopingNode ? scopingNode->treeScope() : m_document;
315     ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
316 
317     StyleSheetCollection* collection = styleSheetCollectionFor(treeScope);
318     ASSERT(collection);
319     collection->removeStyleSheetCandidateNode(node, scopingNode);
320 
321     markTreeScopeDirty(treeScope);
322     m_activeTreeScopes.remove(&treeScope);
323 }
324 
modifiedStyleSheetCandidateNode(Node * node)325 void StyleEngine::modifiedStyleSheetCandidateNode(Node* node)
326 {
327     if (!node->inDocument())
328         return;
329 
330     TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document;
331     ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
332     markTreeScopeDirty(treeScope);
333 }
334 
shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode)335 bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode)
336 {
337     return !m_dirtyTreeScopes.isEmpty() || updateMode == FullStyleUpdate;
338 }
339 
clearMediaQueryRuleSetOnTreeScopeStyleSheets(TreeScopeSet treeScopes)340 void StyleEngine::clearMediaQueryRuleSetOnTreeScopeStyleSheets(TreeScopeSet treeScopes)
341 {
342     for (TreeScopeSet::iterator it = treeScopes.begin(); it != treeScopes.end(); ++it) {
343         TreeScope& treeScope = **it;
344         ASSERT(treeScope != m_document);
345         ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(treeScope));
346         ASSERT(collection);
347         collection->clearMediaQueryRuleSetStyleSheets();
348     }
349 }
350 
clearMediaQueryRuleSetStyleSheets()351 void StyleEngine::clearMediaQueryRuleSetStyleSheets()
352 {
353     m_documentStyleSheetCollection.clearMediaQueryRuleSetStyleSheets();
354     clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_activeTreeScopes);
355     clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_dirtyTreeScopes);
356 }
357 
collectDocumentActiveStyleSheets(StyleSheetCollectionBase & collection)358 void StyleEngine::collectDocumentActiveStyleSheets(StyleSheetCollectionBase& collection)
359 {
360     ASSERT(isMaster());
361 
362     if (HTMLImport* rootImport = m_document.import()) {
363         for (HTMLImport* import = traverseFirstPostOrder(rootImport); import; import = traverseNextPostOrder(import)) {
364             Document* document = import->document();
365             if (!document)
366                 continue;
367             StyleEngine* engine = document->styleEngine();
368             DocumentStyleSheetCollection::CollectFor collectFor = document == &m_document ?
369                 DocumentStyleSheetCollection::CollectForList : DocumentStyleSheetCollection::DontCollectForList;
370             engine->m_documentStyleSheetCollection.collectStyleSheets(engine, collection, collectFor);
371         }
372     } else {
373         m_documentStyleSheetCollection.collectStyleSheets(this, collection, DocumentStyleSheetCollection::CollectForList);
374     }
375 }
376 
updateActiveStyleSheets(StyleResolverUpdateMode updateMode)377 bool StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode)
378 {
379     ASSERT(isMaster());
380 
381     if (m_document.inStyleRecalc()) {
382         // SVG <use> element may manage to invalidate style selector in the middle of a style recalc.
383         // https://bugs.webkit.org/show_bug.cgi?id=54344
384         // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc).
385         m_needsUpdateActiveStylesheetsOnStyleRecalc = true;
386         return false;
387 
388     }
389     if (!m_document.isActive())
390         return false;
391 
392     bool requiresFullStyleRecalc = false;
393     if (m_documentScopeDirty || updateMode == FullStyleUpdate)
394         requiresFullStyleRecalc = m_documentStyleSheetCollection.updateActiveStyleSheets(this, updateMode);
395 
396     if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) {
397         TreeScopeSet treeScopes = updateMode == FullStyleUpdate ? m_activeTreeScopes : m_dirtyTreeScopes;
398         HashSet<TreeScope*> treeScopesRemoved;
399 
400         for (TreeScopeSet::iterator it = treeScopes.begin(); it != treeScopes.end(); ++it) {
401             TreeScope* treeScope = *it;
402             ASSERT(treeScope != m_document);
403             ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(*treeScope));
404             ASSERT(collection);
405             collection->updateActiveStyleSheets(this, updateMode);
406             if (!collection->hasStyleSheetCandidateNodes())
407                 treeScopesRemoved.add(treeScope);
408         }
409         if (!treeScopesRemoved.isEmpty())
410             for (HashSet<TreeScope*>::iterator it = treeScopesRemoved.begin(); it != treeScopesRemoved.end(); ++it)
411                 m_activeTreeScopes.remove(*it);
412     }
413     m_needsUpdateActiveStylesheetsOnStyleRecalc = false;
414     activeStyleSheetsUpdatedForInspector();
415     m_usesRemUnits = m_documentStyleSheetCollection.usesRemUnits();
416 
417     if (m_documentScopeDirty || updateMode == FullStyleUpdate)
418         m_document.notifySeamlessChildDocumentsOfStylesheetUpdate();
419 
420     m_dirtyTreeScopes.clear();
421     m_documentScopeDirty = false;
422 
423     return requiresFullStyleRecalc;
424 }
425 
activeStyleSheetsUpdatedForInspector()426 void StyleEngine::activeStyleSheetsUpdatedForInspector()
427 {
428     if (m_activeTreeScopes.isEmpty()) {
429         InspectorInstrumentation::activeStyleSheetsUpdated(&m_document, m_documentStyleSheetCollection.styleSheetsForStyleSheetList());
430         return;
431     }
432     Vector<RefPtr<StyleSheet> > activeStyleSheets;
433 
434     activeStyleSheets.append(m_documentStyleSheetCollection.styleSheetsForStyleSheetList());
435 
436     TreeScopeSet::iterator begin = m_activeTreeScopes.begin();
437     TreeScopeSet::iterator end = m_activeTreeScopes.end();
438     for (TreeScopeSet::iterator it = begin; it != end; ++it) {
439         if (StyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it))
440             activeStyleSheets.append(collection->styleSheetsForStyleSheetList());
441     }
442 
443     // FIXME: Inspector needs a vector which has all active stylesheets.
444     // However, creating such a large vector might cause performance regression.
445     // Need to implement some smarter solution.
446     InspectorInstrumentation::activeStyleSheetsUpdated(&m_document, activeStyleSheets);
447 }
448 
didRemoveShadowRoot(ShadowRoot * shadowRoot)449 void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot)
450 {
451     m_styleSheetCollectionMap.remove(shadowRoot);
452 }
453 
appendActiveAuthorStyleSheets()454 void StyleEngine::appendActiveAuthorStyleSheets()
455 {
456     ASSERT(isMaster());
457 
458     m_resolver->setBuildScopedStyleTreeInDocumentOrder(true);
459     m_resolver->appendAuthorStyleSheets(0, m_documentStyleSheetCollection.activeAuthorStyleSheets());
460 
461     TreeScopeSet::iterator begin = m_activeTreeScopes.begin();
462     TreeScopeSet::iterator end = m_activeTreeScopes.end();
463     for (TreeScopeSet::iterator it = begin; it != end; ++it) {
464         if (StyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it)) {
465             m_resolver->setBuildScopedStyleTreeInDocumentOrder(!collection->scopingNodesForStyleScoped());
466             m_resolver->appendAuthorStyleSheets(0, collection->activeAuthorStyleSheets());
467         }
468     }
469     m_resolver->finishAppendAuthorStyleSheets();
470     m_resolver->setBuildScopedStyleTreeInDocumentOrder(false);
471 }
472 
createResolver()473 void StyleEngine::createResolver()
474 {
475     // It is a programming error to attempt to resolve style on a Document
476     // which is not in a frame. Code which hits this should have checked
477     // Document::isActive() before calling into code which could get here.
478 
479     ASSERT(m_document.frame());
480     ASSERT(m_fontSelector);
481 
482     m_resolver = adoptPtr(new StyleResolver(m_document));
483     appendActiveAuthorStyleSheets();
484     m_fontSelector->registerForInvalidationCallbacks(m_resolver.get());
485     combineCSSFeatureFlags(m_resolver->ensureRuleFeatureSet());
486 }
487 
clearResolver()488 void StyleEngine::clearResolver()
489 {
490     ASSERT(!m_document.inStyleRecalc());
491     ASSERT(isMaster() || !m_resolver);
492     ASSERT(m_fontSelector || !m_resolver);
493     if (m_resolver)
494         m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
495     m_resolver.clear();
496 }
497 
clearMasterResolver()498 void StyleEngine::clearMasterResolver()
499 {
500     if (Document* master = this->master())
501         master->styleEngine()->clearResolver();
502 }
503 
resolverAccessCount() const504 unsigned StyleEngine::resolverAccessCount() const
505 {
506     return m_resolver ? m_resolver->accessCount() : 0;
507 }
508 
resolverThrowawayTimerFired(Timer<StyleEngine> *)509 void StyleEngine::resolverThrowawayTimerFired(Timer<StyleEngine>*)
510 {
511     if (resolverAccessCount() == m_lastResolverAccessCount)
512         clearResolver();
513     m_lastResolverAccessCount = resolverAccessCount();
514 }
515 
didAttach()516 void StyleEngine::didAttach()
517 {
518     m_resolverThrowawayTimer.startRepeating(60);
519 }
520 
didDetach()521 void StyleEngine::didDetach()
522 {
523     m_resolverThrowawayTimer.stop();
524     clearResolver();
525 }
526 
shouldClearResolver() const527 bool StyleEngine::shouldClearResolver() const
528 {
529     return !m_didCalculateResolver && !haveStylesheetsLoaded();
530 }
531 
resolverChanged(RecalcStyleTime time,StyleResolverUpdateMode mode)532 StyleResolverChange StyleEngine::resolverChanged(RecalcStyleTime time, StyleResolverUpdateMode mode)
533 {
534     StyleResolverChange change;
535 
536     if (!isMaster()) {
537         if (Document* master = this->master())
538             master->styleResolverChanged(time, mode);
539         return change;
540     }
541 
542     // Don't bother updating, since we haven't loaded all our style info yet
543     // and haven't calculated the style selector for the first time.
544     if (!m_document.isActive() || shouldClearResolver()) {
545         clearResolver();
546         return change;
547     }
548 
549     m_didCalculateResolver = true;
550     if (m_document.didLayoutWithPendingStylesheets() && !hasPendingSheets())
551         change.setNeedsRepaint();
552 
553     if (updateActiveStyleSheets(mode))
554         change.setNeedsStyleRecalc();
555 
556     return change;
557 }
558 
resetFontSelector()559 void StyleEngine::resetFontSelector()
560 {
561     if (!m_fontSelector)
562         return;
563 
564     m_fontSelector->clearDocument();
565     if (m_resolver) {
566         m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
567         m_resolver->invalidateMatchedPropertiesCache();
568     }
569 
570     // If the document has been already detached, we don't need to recreate
571     // CSSFontSelector.
572     if (m_document.isActive()) {
573         m_fontSelector = CSSFontSelector::create(&m_document);
574         if (m_resolver)
575             m_fontSelector->registerForInvalidationCallbacks(m_resolver.get());
576     } else {
577         m_fontSelector = 0;
578     }
579 }
580 
markTreeScopeDirty(TreeScope & scope)581 void StyleEngine::markTreeScopeDirty(TreeScope& scope)
582 {
583     if (scope == m_document) {
584         markDocumentDirty();
585         return;
586     }
587 
588     m_dirtyTreeScopes.add(&scope);
589 }
590 
markDocumentDirty()591 void StyleEngine::markDocumentDirty()
592 {
593     m_documentScopeDirty = true;
594     if (!HTMLImport::isMaster(&m_document))
595         m_document.import()->master()->styleEngine()->markDocumentDirty();
596 }
597 
598 }
599