summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/dom/StyleEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/dom/StyleEngine.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/dom/StyleEngine.cpp485
1 files changed, 294 insertions, 191 deletions
diff --git a/chromium/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/chromium/third_party/WebKit/Source/core/dom/StyleEngine.cpp
index 54ce1fe3368..901bed5922c 100644
--- a/chromium/third_party/WebKit/Source/core/dom/StyleEngine.cpp
+++ b/chromium/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -28,25 +28,23 @@
#include "config.h"
#include "core/dom/StyleEngine.h"
-#include "HTMLNames.h"
-#include "SVGNames.h"
+#include "core/HTMLNames.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/CSSStyleSheet.h"
-#include "core/css/StyleInvalidationAnalysis.h"
+#include "core/css/FontFaceCache.h"
#include "core/css/StyleSheetContents.h"
+#include "core/dom/DocumentStyleSheetCollector.h"
#include "core/dom/Element.h"
#include "core/dom/ProcessingInstruction.h"
#include "core/dom/ShadowTreeStyleSheetCollection.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/html/HTMLIFrameElement.h"
-#include "core/html/HTMLImport.h"
#include "core/html/HTMLLinkElement.h"
-#include "core/html/HTMLStyleElement.h"
+#include "core/html/imports/HTMLImportsController.h"
#include "core/inspector/InspectorInstrumentation.h"
+#include "core/page/InjectedStyleSheets.h"
#include "core/page/Page.h"
-#include "core/page/PageGroup.h"
#include "core/frame/Settings.h"
-#include "core/svg/SVGStyleElement.h"
#include "platform/URLPatternMatcher.h"
namespace WebCore {
@@ -54,12 +52,15 @@ namespace WebCore {
using namespace HTMLNames;
StyleEngine::StyleEngine(Document& document)
- : m_document(document)
- , m_isMaster(HTMLImport::isMaster(&document))
+ : m_document(&document)
+ , m_isMaster(!document.importsController() || document.importsController()->master() == &document)
, m_pendingStylesheets(0)
, m_injectedStyleSheetCacheValid(false)
- , m_needsUpdateActiveStylesheetsOnStyleRecalc(false)
+#if ENABLE(OILPAN)
+ , m_documentStyleSheetCollection(new DocumentStyleSheetCollection(document))
+#else
, m_documentStyleSheetCollection(document)
+#endif
, m_documentScopeDirty(true)
, m_usesSiblingRules(false)
, m_usesSiblingRulesOverride(false)
@@ -69,16 +70,25 @@ StyleEngine::StyleEngine(Document& document)
, m_maxDirectAdjacentSelectors(0)
, m_ignorePendingStylesheets(false)
, m_didCalculateResolver(false)
- , m_lastResolverAccessCount(0)
- , m_resolverThrowawayTimer(this, &StyleEngine::resolverThrowawayTimerFired)
// We don't need to create CSSFontSelector for imported document or
// HTMLTemplateElement's document, because those documents have no frame.
- , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : 0)
+ , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : nullptr)
+ , m_xslStyleSheet(nullptr)
{
+ if (m_fontSelector)
+ m_fontSelector->registerForInvalidationCallbacks(this);
}
StyleEngine::~StyleEngine()
{
+}
+
+#if !ENABLE(OILPAN)
+void StyleEngine::detachFromDocument()
+{
+ // Cleanup is performed eagerly when the StyleEngine is removed from the
+ // document. The StyleEngine is unreachable after this, since only the
+ // document has a reference to it.
for (unsigned i = 0; i < m_injectedAuthorStyleSheets.size(); ++i)
m_injectedAuthorStyleSheets[i]->clearOwnerNode();
for (unsigned i = 0; i < m_authorStyleSheets.size(); ++i)
@@ -86,16 +96,21 @@ StyleEngine::~StyleEngine()
if (m_fontSelector) {
m_fontSelector->clearDocument();
- if (m_resolver)
- m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
+ m_fontSelector->unregisterForInvalidationCallbacks(this);
}
+
+ // Decrement reference counts for things we could be keeping alive.
+ m_fontSelector.clear();
+ m_resolver.clear();
+ m_styleSheetCollectionMap.clear();
}
+#endif
inline Document* StyleEngine::master()
{
if (isMaster())
- return &m_document;
- HTMLImport* import = m_document.import();
+ return m_document;
+ HTMLImportsController* import = document().importsController();
if (!import) // Document::import() can return null while executing its destructor.
return 0;
return import->master();
@@ -128,52 +143,39 @@ void StyleEngine::insertTreeScopeInDocumentOrder(TreeScopeSet& treeScopes, TreeS
treeScopes.insertBefore(followingTreeScope, treeScope);
}
-StyleSheetCollection* StyleEngine::ensureStyleSheetCollectionFor(TreeScope& treeScope)
+TreeScopeStyleSheetCollection* StyleEngine::ensureStyleSheetCollectionFor(TreeScope& treeScope)
{
if (treeScope == m_document)
- return &m_documentStyleSheetCollection;
+ return documentStyleSheetCollection();
- HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::AddResult result = m_styleSheetCollectionMap.add(&treeScope, nullptr);
+ StyleSheetCollectionMap::AddResult result = m_styleSheetCollectionMap.add(&treeScope, nullptr);
if (result.isNewEntry)
- result.iterator->value = adoptPtr(new ShadowTreeStyleSheetCollection(toShadowRoot(treeScope)));
- return result.iterator->value.get();
+ result.storedValue->value = adoptPtrWillBeNoop(new ShadowTreeStyleSheetCollection(toShadowRoot(treeScope)));
+ return result.storedValue->value.get();
}
-StyleSheetCollection* StyleEngine::styleSheetCollectionFor(TreeScope& treeScope)
+TreeScopeStyleSheetCollection* StyleEngine::styleSheetCollectionFor(TreeScope& treeScope)
{
if (treeScope == m_document)
- return &m_documentStyleSheetCollection;
+ return documentStyleSheetCollection();
- HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::iterator it = m_styleSheetCollectionMap.find(&treeScope);
+ StyleSheetCollectionMap::iterator it = m_styleSheetCollectionMap.find(&treeScope);
if (it == m_styleSheetCollectionMap.end())
return 0;
return it->value.get();
}
-const Vector<RefPtr<StyleSheet> >& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope)
+const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope)
{
if (treeScope == m_document)
- return m_documentStyleSheetCollection.styleSheetsForStyleSheetList();
+ return documentStyleSheetCollection()->styleSheetsForStyleSheetList();
return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetList();
}
-const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::activeAuthorStyleSheets() const
-{
- return m_documentStyleSheetCollection.activeAuthorStyleSheets();
-}
-
-void StyleEngine::getActiveAuthorStyleSheets(Vector<const Vector<RefPtr<CSSStyleSheet> >*>& activeAuthorStyleSheets) const
+const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& StyleEngine::activeAuthorStyleSheets() const
{
- activeAuthorStyleSheets.append(&m_documentStyleSheetCollection.activeAuthorStyleSheets());
-
- HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values begin = m_styleSheetCollectionMap.values().begin();
- HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values end = m_styleSheetCollectionMap.values().end();
- HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values it = begin;
- for (; it != end; ++it) {
- const StyleSheetCollection* collection = it->get();
- activeAuthorStyleSheets.append(&collection->activeAuthorStyleSheets());
- }
+ return documentStyleSheetCollection()->activeAuthorStyleSheets();
}
void StyleEngine::combineCSSFeatureFlags(const RuleFeatureSet& features)
@@ -191,7 +193,7 @@ void StyleEngine::resetCSSFeatureFlags(const RuleFeatureSet& features)
m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors();
}
-const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::injectedAuthorStyleSheets() const
+const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& StyleEngine::injectedAuthorStyleSheets() const
{
updateInjectedStyleSheetCache();
return m_injectedAuthorStyleSheets;
@@ -204,21 +206,20 @@ void StyleEngine::updateInjectedStyleSheetCache() const
m_injectedStyleSheetCacheValid = true;
m_injectedAuthorStyleSheets.clear();
- Page* owningPage = m_document.page();
+ Page* owningPage = document().page();
if (!owningPage)
return;
- const PageGroup& pageGroup = owningPage->group();
- const InjectedStyleSheetVector& sheets = pageGroup.injectedStyleSheets();
- for (unsigned i = 0; i < sheets.size(); ++i) {
- const InjectedStyleSheet* sheet = sheets[i].get();
- if (sheet->injectedFrames() == InjectStyleInTopFrameOnly && m_document.ownerElement())
+ const InjectedStyleSheetEntryVector& entries = InjectedStyleSheets::instance().entries();
+ for (unsigned i = 0; i < entries.size(); ++i) {
+ const InjectedStyleSheetEntry* entry = entries[i].get();
+ if (entry->injectedFrames() == InjectStyleInTopFrameOnly && document().ownerElement())
continue;
- if (!URLPatternMatcher::matchesPatterns(m_document.url(), sheet->whitelist()))
+ if (!URLPatternMatcher::matchesPatterns(document().url(), entry->whitelist()))
continue;
- RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(&m_document), KURL());
+ RefPtrWillBeRawPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(m_document, KURL());
m_injectedAuthorStyleSheets.append(groupSheet);
- groupSheet->contents()->parseString(sheet->source());
+ groupSheet->contents()->parseString(entry->source());
}
}
@@ -228,38 +229,28 @@ void StyleEngine::invalidateInjectedStyleSheetCache()
markDocumentDirty();
// FIXME: updateInjectedStyleSheetCache is called inside StyleSheetCollection::updateActiveStyleSheets
// and batch updates lots of sheets so we can't call addedStyleSheet() or removedStyleSheet().
- m_document.styleResolverChanged(RecalcStyleDeferred);
+ document().styleResolverChanged();
}
-void StyleEngine::addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet)
+void StyleEngine::addAuthorSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> authorSheet)
{
- m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, &m_document));
- m_document.addedStyleSheet(m_authorStyleSheets.last().get(), RecalcStyleImmediately);
+ m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, m_document));
+ document().addedStyleSheet(m_authorStyleSheets.last().get());
markDocumentDirty();
}
void StyleEngine::addPendingSheet()
{
- master()->styleEngine()->notifyPendingStyleSheetAdded();
+ m_pendingStylesheets++;
}
// This method is called whenever a top-level stylesheet has finished loading.
-void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, RemovePendingSheetNotificationType notification)
+void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode)
{
- TreeScope* treeScope = isHTMLStyleElement(styleSheetCandidateNode) ? &styleSheetCandidateNode->treeScope() : &m_document;
+ ASSERT(styleSheetCandidateNode);
+ TreeScope* treeScope = isHTMLStyleElement(*styleSheetCandidateNode) ? &styleSheetCandidateNode->treeScope() : m_document.get();
markTreeScopeDirty(*treeScope);
- master()->styleEngine()->notifyPendingStyleSheetRemoved(notification);
-}
-
-void StyleEngine::notifyPendingStyleSheetAdded()
-{
- ASSERT(isMaster());
- m_pendingStylesheets++;
-}
-void StyleEngine::notifyPendingStyleSheetRemoved(RemovePendingSheetNotificationType notification)
-{
- ASSERT(isMaster());
// Make sure we knew this sheet was pending, and that our count isn't out of sync.
ASSERT(m_pendingStylesheets > 0);
@@ -267,14 +258,9 @@ void StyleEngine::notifyPendingStyleSheetRemoved(RemovePendingSheetNotificationT
if (m_pendingStylesheets)
return;
- if (notification == RemovePendingSheetNotifyLater) {
- m_document.setNeedsNotifyRemoveAllPendingStylesheet();
- return;
- }
-
// FIXME: We can't call addedStyleSheet or removedStyleSheet here because we don't know
// what's new. We should track that to tell the style system what changed.
- m_document.didRemoveAllPendingStylesheet();
+ document().didRemoveAllPendingStylesheet();
}
void StyleEngine::modifiedStyleSheet(StyleSheet* sheet)
@@ -286,7 +272,7 @@ void StyleEngine::modifiedStyleSheet(StyleSheet* sheet)
if (!node || !node->inDocument())
return;
- TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document;
+ TreeScope& treeScope = isHTMLStyleElement(*node) ? node->treeScope() : *m_document;
ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
markTreeScopeDirty(treeScope);
@@ -297,10 +283,10 @@ void StyleEngine::addStyleSheetCandidateNode(Node* node, bool createdByParser)
if (!node->inDocument())
return;
- TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document;
+ TreeScope& treeScope = isHTMLStyleElement(*node) ? node->treeScope() : *m_document;
ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
-
- StyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope);
+ ASSERT(!isXSLStyleSheet(*node));
+ TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope);
ASSERT(collection);
collection->addStyleSheetCandidateNode(node, createdByParser);
@@ -309,12 +295,17 @@ void StyleEngine::addStyleSheetCandidateNode(Node* node, bool createdByParser)
insertTreeScopeInDocumentOrder(m_activeTreeScopes, &treeScope);
}
-void StyleEngine::removeStyleSheetCandidateNode(Node* node, ContainerNode* scopingNode)
+void StyleEngine::removeStyleSheetCandidateNode(Node* node)
+{
+ removeStyleSheetCandidateNode(node, 0, *m_document);
+}
+
+void StyleEngine::removeStyleSheetCandidateNode(Node* node, ContainerNode* scopingNode, TreeScope& treeScope)
{
- TreeScope& treeScope = scopingNode ? scopingNode->treeScope() : m_document;
ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
+ ASSERT(!isXSLStyleSheet(*node));
- StyleSheetCollection* collection = styleSheetCollectionFor(treeScope);
+ TreeScopeStyleSheetCollection* collection = styleSheetCollectionFor(treeScope);
ASSERT(collection);
collection->removeStyleSheetCandidateNode(node, scopingNode);
@@ -322,17 +313,59 @@ void StyleEngine::removeStyleSheetCandidateNode(Node* node, ContainerNode* scopi
m_activeTreeScopes.remove(&treeScope);
}
+void StyleEngine::addXSLStyleSheet(ProcessingInstruction* node, bool createdByParser)
+{
+ if (!node->inDocument())
+ return;
+
+ ASSERT(isXSLStyleSheet(*node));
+ bool needToUpdate = false;
+ if (createdByParser || !m_xslStyleSheet) {
+ needToUpdate = !m_xslStyleSheet;
+ } else {
+ unsigned position = m_xslStyleSheet->compareDocumentPositionInternal(node, Node::TreatShadowTreesAsDisconnected);
+ needToUpdate = position & Node::DOCUMENT_POSITION_FOLLOWING;
+ }
+
+ if (!needToUpdate)
+ return;
+
+ markTreeScopeDirty(*m_document);
+ m_xslStyleSheet = node;
+}
+
+void StyleEngine::removeXSLStyleSheet(ProcessingInstruction* node)
+{
+ ASSERT(isXSLStyleSheet(*node));
+ if (m_xslStyleSheet != node)
+ return;
+
+ markTreeScopeDirty(*m_document);
+ m_xslStyleSheet = nullptr;
+}
+
void StyleEngine::modifiedStyleSheetCandidateNode(Node* node)
{
if (!node->inDocument())
return;
- TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document;
+ TreeScope& treeScope = isHTMLStyleElement(*node) ? node->treeScope() : *m_document;
ASSERT(isHTMLStyleElement(node) || treeScope == m_document);
markTreeScopeDirty(treeScope);
}
-bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode)
+void StyleEngine::enableExitTransitionStylesheets()
+{
+ TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(*m_document);
+ collection->enableExitTransitionStylesheets();
+}
+
+bool StyleEngine::shouldUpdateDocumentStyleSheetCollection(StyleResolverUpdateMode updateMode) const
+{
+ return m_documentScopeDirty || updateMode == FullStyleUpdate;
+}
+
+bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode) const
{
return !m_dirtyTreeScopes.isEmpty() || updateMode == FullStyleUpdate;
}
@@ -350,48 +383,30 @@ void StyleEngine::clearMediaQueryRuleSetOnTreeScopeStyleSheets(TreeScopeSet tree
void StyleEngine::clearMediaQueryRuleSetStyleSheets()
{
- m_documentStyleSheetCollection.clearMediaQueryRuleSetStyleSheets();
+ documentStyleSheetCollection()->clearMediaQueryRuleSetStyleSheets();
clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_activeTreeScopes);
clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_dirtyTreeScopes);
}
-void StyleEngine::collectDocumentActiveStyleSheets(StyleSheetCollectionBase& collection)
+void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentCollector)
{
- ASSERT(isMaster());
-
- if (HTMLImport* rootImport = m_document.import()) {
- for (HTMLImport* import = traverseFirstPostOrder(rootImport); import; import = traverseNextPostOrder(import)) {
- Document* document = import->document();
- if (!document)
- continue;
- StyleEngine* engine = document->styleEngine();
- DocumentStyleSheetCollection::CollectFor collectFor = document == &m_document ?
- DocumentStyleSheetCollection::CollectForList : DocumentStyleSheetCollection::DontCollectForList;
- engine->m_documentStyleSheetCollection.collectStyleSheets(engine, collection, collectFor);
- }
- } else {
- m_documentStyleSheetCollection.collectStyleSheets(this, collection, DocumentStyleSheetCollection::CollectForList);
- }
+ ASSERT(!isMaster());
+ WillBeHeapVector<RefPtrWillBeMember<StyleSheet> > sheetsForList;
+ ImportedDocumentStyleSheetCollector subcollector(parentCollector, sheetsForList);
+ documentStyleSheetCollection()->collectStyleSheets(this, subcollector);
+ documentStyleSheetCollection()->swapSheetsForSheetList(sheetsForList);
}
-bool StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode)
+void StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode)
{
ASSERT(isMaster());
+ ASSERT(!document().inStyleRecalc());
- if (m_document.inStyleRecalc()) {
- // SVG <use> element may manage to invalidate style selector in the middle of a style recalc.
- // https://bugs.webkit.org/show_bug.cgi?id=54344
- // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc).
- m_needsUpdateActiveStylesheetsOnStyleRecalc = true;
- return false;
-
- }
- if (!m_document.isActive())
- return false;
+ if (!document().isActive())
+ return;
- bool requiresFullStyleRecalc = false;
- if (m_documentScopeDirty || updateMode == FullStyleUpdate)
- requiresFullStyleRecalc = m_documentStyleSheetCollection.updateActiveStyleSheets(this, updateMode);
+ if (shouldUpdateDocumentStyleSheetCollection(updateMode))
+ documentStyleSheetCollection()->updateActiveStyleSheets(this, updateMode);
if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) {
TreeScopeSet treeScopes = updateMode == FullStyleUpdate ? m_activeTreeScopes : m_dirtyTreeScopes;
@@ -406,44 +421,36 @@ bool StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode)
if (!collection->hasStyleSheetCandidateNodes())
treeScopesRemoved.add(treeScope);
}
- if (!treeScopesRemoved.isEmpty())
- for (HashSet<TreeScope*>::iterator it = treeScopesRemoved.begin(); it != treeScopesRemoved.end(); ++it)
- m_activeTreeScopes.remove(*it);
+ m_activeTreeScopes.removeAll(treeScopesRemoved);
}
- m_needsUpdateActiveStylesheetsOnStyleRecalc = false;
- activeStyleSheetsUpdatedForInspector();
- m_usesRemUnits = m_documentStyleSheetCollection.usesRemUnits();
- if (m_documentScopeDirty || updateMode == FullStyleUpdate)
- m_document.notifySeamlessChildDocumentsOfStylesheetUpdate();
+ InspectorInstrumentation::activeStyleSheetsUpdated(m_document);
+ m_usesRemUnits = documentStyleSheetCollection()->usesRemUnits();
m_dirtyTreeScopes.clear();
m_documentScopeDirty = false;
-
- return requiresFullStyleRecalc;
}
-void StyleEngine::activeStyleSheetsUpdatedForInspector()
+const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > StyleEngine::activeStyleSheetsForInspector() const
{
- if (m_activeTreeScopes.isEmpty()) {
- InspectorInstrumentation::activeStyleSheetsUpdated(&m_document, m_documentStyleSheetCollection.styleSheetsForStyleSheetList());
- return;
- }
- Vector<RefPtr<StyleSheet> > activeStyleSheets;
+ if (m_activeTreeScopes.isEmpty())
+ return documentStyleSheetCollection()->activeAuthorStyleSheets();
- activeStyleSheets.append(m_documentStyleSheetCollection.styleSheetsForStyleSheetList());
+ WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > activeStyleSheets;
- TreeScopeSet::iterator begin = m_activeTreeScopes.begin();
- TreeScopeSet::iterator end = m_activeTreeScopes.end();
- for (TreeScopeSet::iterator it = begin; it != end; ++it) {
- if (StyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it))
- activeStyleSheets.append(collection->styleSheetsForStyleSheetList());
+ activeStyleSheets.appendVector(documentStyleSheetCollection()->activeAuthorStyleSheets());
+
+ TreeScopeSet::const_iterator begin = m_activeTreeScopes.begin();
+ TreeScopeSet::const_iterator end = m_activeTreeScopes.end();
+ for (TreeScopeSet::const_iterator it = begin; it != end; ++it) {
+ if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it))
+ activeStyleSheets.appendVector(collection->activeAuthorStyleSheets());
}
// FIXME: Inspector needs a vector which has all active stylesheets.
// However, creating such a large vector might cause performance regression.
// Need to implement some smarter solution.
- InspectorInstrumentation::activeStyleSheetsUpdated(&m_document, activeStyleSheets);
+ return activeStyleSheets;
}
void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot)
@@ -456,14 +463,14 @@ void StyleEngine::appendActiveAuthorStyleSheets()
ASSERT(isMaster());
m_resolver->setBuildScopedStyleTreeInDocumentOrder(true);
- m_resolver->appendAuthorStyleSheets(0, m_documentStyleSheetCollection.activeAuthorStyleSheets());
+ m_resolver->appendAuthorStyleSheets(documentStyleSheetCollection()->activeAuthorStyleSheets());
TreeScopeSet::iterator begin = m_activeTreeScopes.begin();
TreeScopeSet::iterator end = m_activeTreeScopes.end();
for (TreeScopeSet::iterator it = begin; it != end; ++it) {
- if (StyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it)) {
+ if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it)) {
m_resolver->setBuildScopedStyleTreeInDocumentOrder(!collection->scopingNodesForStyleScoped());
- m_resolver->appendAuthorStyleSheets(0, collection->activeAuthorStyleSheets());
+ m_resolver->appendAuthorStyleSheets(collection->activeAuthorStyleSheets());
}
}
m_resolver->finishAppendAuthorStyleSheets();
@@ -476,22 +483,19 @@ void StyleEngine::createResolver()
// which is not in a frame. Code which hits this should have checked
// Document::isActive() before calling into code which could get here.
- ASSERT(m_document.frame());
- ASSERT(m_fontSelector);
+ ASSERT(document().frame());
- m_resolver = adoptPtr(new StyleResolver(m_document));
+ m_resolver = adoptPtrWillBeNoop(new StyleResolver(*m_document));
appendActiveAuthorStyleSheets();
- m_fontSelector->registerForInvalidationCallbacks(m_resolver.get());
- combineCSSFeatureFlags(m_resolver->ensureRuleFeatureSet());
+ combineCSSFeatureFlags(m_resolver->ensureUpdatedRuleFeatureSet());
}
void StyleEngine::clearResolver()
{
- ASSERT(!m_document.inStyleRecalc());
+ ASSERT(!document().inStyleRecalc());
ASSERT(isMaster() || !m_resolver);
- ASSERT(m_fontSelector || !m_resolver);
if (m_resolver)
- m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
+ document().updateStyleInvalidationIfNeeded();
m_resolver.clear();
}
@@ -506,21 +510,8 @@ unsigned StyleEngine::resolverAccessCount() const
return m_resolver ? m_resolver->accessCount() : 0;
}
-void StyleEngine::resolverThrowawayTimerFired(Timer<StyleEngine>*)
-{
- if (resolverAccessCount() == m_lastResolverAccessCount)
- clearResolver();
- m_lastResolverAccessCount = resolverAccessCount();
-}
-
-void StyleEngine::didAttach()
-{
- m_resolverThrowawayTimer.startRepeating(60);
-}
-
void StyleEngine::didDetach()
{
- m_resolverThrowawayTimer.stop();
clearResolver();
}
@@ -529,53 +520,74 @@ bool StyleEngine::shouldClearResolver() const
return !m_didCalculateResolver && !haveStylesheetsLoaded();
}
-StyleResolverChange StyleEngine::resolverChanged(RecalcStyleTime time, StyleResolverUpdateMode mode)
+bool StyleEngine::shouldApplyXSLTransform() const
{
- StyleResolverChange change;
+ if (!RuntimeEnabledFeatures::xsltEnabled())
+ return false;
+ return m_xslStyleSheet && !m_document->transformSourceDocument();
+}
+void StyleEngine::resolverChanged(StyleResolverUpdateMode mode)
+{
if (!isMaster()) {
if (Document* master = this->master())
- master->styleResolverChanged(time, mode);
- return change;
+ master->styleResolverChanged(mode);
+ return;
}
// Don't bother updating, since we haven't loaded all our style info yet
// and haven't calculated the style selector for the first time.
- if (!m_document.isActive() || shouldClearResolver()) {
+ if (!document().isActive() || shouldClearResolver()) {
clearResolver();
- return change;
+ return;
}
- m_didCalculateResolver = true;
- if (m_document.didLayoutWithPendingStylesheets() && !hasPendingSheets())
- change.setNeedsRepaint();
+ if (shouldApplyXSLTransform()) {
+ // Processing instruction (XML documents only).
+ // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
+ // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
+ if (!m_document->parsing() && !m_xslStyleSheet->isLoading())
+ m_document->applyXSLTransform(m_xslStyleSheet.get());
+ return;
+ }
- if (updateActiveStyleSheets(mode))
- change.setNeedsStyleRecalc();
+ m_didCalculateResolver = true;
+ updateActiveStyleSheets(mode);
+}
- return change;
+void StyleEngine::clearFontCache()
+{
+ // We should not recreate FontSelector. Instead, clear fontFaceCache.
+ if (m_fontSelector)
+ m_fontSelector->fontFaceCache()->clear();
+ if (m_resolver)
+ m_resolver->invalidateMatchedPropertiesCache();
}
-void StyleEngine::resetFontSelector()
+void StyleEngine::updateGenericFontFamilySettings()
{
+ // FIXME: we should not update generic font family settings when
+ // document is inactive.
+ ASSERT(document().isActive());
+
if (!m_fontSelector)
return;
- m_fontSelector->clearDocument();
- if (m_resolver) {
- m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get());
+ m_fontSelector->updateGenericFontFamilySettings(*m_document);
+ if (m_resolver)
m_resolver->invalidateMatchedPropertiesCache();
- }
+}
- // If the document has been already detached, we don't need to recreate
- // CSSFontSelector.
- if (m_document.isActive()) {
- m_fontSelector = CSSFontSelector::create(&m_document);
- if (m_resolver)
- m_fontSelector->registerForInvalidationCallbacks(m_resolver.get());
- } else {
- m_fontSelector = 0;
- }
+void StyleEngine::removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >& fontFaceRules)
+{
+ if (!m_fontSelector)
+ return;
+
+ FontFaceCache* cache = m_fontSelector->fontFaceCache();
+ for (unsigned i = 0; i < fontFaceRules.size(); ++i)
+ cache->remove(fontFaceRules[i]);
+ if (m_resolver)
+ m_resolver->invalidateMatchedPropertiesCache();
}
void StyleEngine::markTreeScopeDirty(TreeScope& scope)
@@ -591,8 +603,99 @@ void StyleEngine::markTreeScopeDirty(TreeScope& scope)
void StyleEngine::markDocumentDirty()
{
m_documentScopeDirty = true;
- if (!HTMLImport::isMaster(&m_document))
- m_document.import()->master()->styleEngine()->markDocumentDirty();
+ if (document().importLoader())
+ document().importsController()->master()->styleEngine()->markDocumentDirty();
+}
+
+static bool isCacheableForStyleElement(const StyleSheetContents& contents)
+{
+ // FIXME: Support copying import rules.
+ if (!contents.importRules().isEmpty())
+ return false;
+ // Until import rules are supported in cached sheets it's not possible for loading to fail.
+ ASSERT(!contents.didLoadErrorOccur());
+ // It is not the original sheet anymore.
+ if (contents.isMutable())
+ return false;
+ if (!contents.hasSyntacticallyValidCSSHeader())
+ return false;
+ return true;
+}
+
+PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::createSheet(Element* e, const String& text, TextPosition startPosition, bool createdByParser)
+{
+ RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet = nullptr;
+
+ e->document().styleEngine()->addPendingSheet();
+
+ if (!e->document().inQuirksMode()) {
+ AtomicString textContent(text);
+
+ WillBeHeapHashMap<AtomicString, RawPtrWillBeMember<StyleSheetContents> >::AddResult result = m_textToSheetCache.add(textContent, nullptr);
+ if (result.isNewEntry || !result.storedValue->value) {
+ styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
+ if (result.isNewEntry && isCacheableForStyleElement(*styleSheet->contents())) {
+ result.storedValue->value = styleSheet->contents();
+ m_sheetToTextCache.add(styleSheet->contents(), textContent);
+ }
+ } else {
+ StyleSheetContents* contents = result.storedValue->value;
+ ASSERT(contents);
+ ASSERT(isCacheableForStyleElement(*contents));
+ ASSERT(contents->singleOwnerDocument() == e->document());
+ styleSheet = CSSStyleSheet::createInline(contents, e, startPosition);
+ }
+ } else {
+ // FIXME: currently we don't cache StyleSheetContents inQuirksMode.
+ styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
+ }
+
+ ASSERT(styleSheet);
+ styleSheet->setTitle(e->title());
+ return styleSheet;
+}
+
+PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::parseSheet(Element* e, const String& text, TextPosition startPosition, bool createdByParser)
+{
+ RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet = nullptr;
+ styleSheet = CSSStyleSheet::createInline(e, KURL(), startPosition, e->document().inputEncoding());
+ styleSheet->contents()->parseStringAtPosition(text, startPosition, createdByParser);
+ return styleSheet;
+}
+
+void StyleEngine::removeSheet(StyleSheetContents* contents)
+{
+ WillBeHeapHashMap<RawPtrWillBeMember<StyleSheetContents>, AtomicString>::iterator it = m_sheetToTextCache.find(contents);
+ if (it == m_sheetToTextCache.end())
+ return;
+
+ m_textToSheetCache.remove(it->value);
+ m_sheetToTextCache.remove(contents);
+}
+
+void StyleEngine::fontsNeedUpdate(CSSFontSelector*)
+{
+ if (!document().isActive())
+ return;
+
+ if (m_resolver)
+ m_resolver->invalidateMatchedPropertiesCache();
+ document().setNeedsStyleRecalc(SubtreeStyleChange);
+}
+
+void StyleEngine::trace(Visitor* visitor)
+{
+ visitor->trace(m_document);
+ visitor->trace(m_injectedAuthorStyleSheets);
+ visitor->trace(m_authorStyleSheets);
+ visitor->trace(m_documentStyleSheetCollection);
+ visitor->trace(m_styleSheetCollectionMap);
+ visitor->trace(m_resolver);
+ visitor->trace(m_fontSelector);
+ visitor->trace(m_textToSheetCache);
+ visitor->trace(m_sheetToTextCache);
+ visitor->trace(m_xslStyleSheet);
+ CSSFontSelectorClient::trace(visitor);
}
}