PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/core/dom/StyleEngine.cpp

https://repo.or.cz/blink.git
C++ | 735 lines | 550 code | 111 blank | 74 comment | 113 complexity | a6fe24d046b68b687a392548a433be11 MD5 | raw file
Possible License(s): BSD-3-Clause, Unlicense, AGPL-1.0, Apache-2.0
  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. #include "config.h"
  28. #include "core/dom/StyleEngine.h"
  29. #include "core/HTMLNames.h"
  30. #include "core/css/CSSFontSelector.h"
  31. #include "core/css/CSSStyleSheet.h"
  32. #include "core/css/FontFaceCache.h"
  33. #include "core/css/StyleSheetContents.h"
  34. #include "core/css/resolver/ScopedStyleResolver.h"
  35. #include "core/dom/DocumentStyleSheetCollector.h"
  36. #include "core/dom/Element.h"
  37. #include "core/dom/ProcessingInstruction.h"
  38. #include "core/dom/ShadowTreeStyleSheetCollection.h"
  39. #include "core/dom/shadow/ShadowRoot.h"
  40. #include "core/frame/Settings.h"
  41. #include "core/html/HTMLIFrameElement.h"
  42. #include "core/html/HTMLLinkElement.h"
  43. #include "core/html/imports/HTMLImportsController.h"
  44. #include "core/inspector/InspectorInstrumentation.h"
  45. #include "core/page/Page.h"
  46. #include "core/svg/SVGStyleElement.h"
  47. #include "platform/TraceEvent.h"
  48. namespace blink {
  49. using namespace HTMLNames;
  50. StyleEngine::StyleEngine(Document& document)
  51. : m_document(&document)
  52. , m_isMaster(!document.importsController() || document.importsController()->master() == &document)
  53. , m_pendingStylesheets(0)
  54. , m_documentStyleSheetCollection(DocumentStyleSheetCollection::create(document))
  55. , m_documentScopeDirty(true)
  56. , m_usesSiblingRules(false)
  57. , m_usesFirstLineRules(false)
  58. , m_usesWindowInactiveSelector(false)
  59. , m_usesRemUnits(false)
  60. , m_maxDirectAdjacentSelectors(0)
  61. , m_ignorePendingStylesheets(false)
  62. , m_didCalculateResolver(false)
  63. // We don't need to create CSSFontSelector for imported document or
  64. // HTMLTemplateElement's document, because those documents have no frame.
  65. , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : nullptr)
  66. {
  67. if (m_fontSelector)
  68. m_fontSelector->registerForInvalidationCallbacks(this);
  69. }
  70. StyleEngine::~StyleEngine()
  71. {
  72. }
  73. static bool isStyleElement(Node& node)
  74. {
  75. return isHTMLStyleElement(node) || isSVGStyleElement(node);
  76. }
  77. #if !ENABLE(OILPAN)
  78. void StyleEngine::detachFromDocument()
  79. {
  80. // Cleanup is performed eagerly when the StyleEngine is removed from the
  81. // document. The StyleEngine is unreachable after this, since only the
  82. // document has a reference to it.
  83. for (unsigned i = 0; i < m_authorStyleSheets.size(); ++i)
  84. m_authorStyleSheets[i]->clearOwnerNode();
  85. if (m_fontSelector) {
  86. m_fontSelector->clearDocument();
  87. m_fontSelector->unregisterForInvalidationCallbacks(this);
  88. }
  89. // Decrement reference counts for things we could be keeping alive.
  90. m_fontSelector.clear();
  91. m_resolver.clear();
  92. m_styleSheetCollectionMap.clear();
  93. m_activeTreeScopes.clear();
  94. }
  95. #endif
  96. inline Document* StyleEngine::master()
  97. {
  98. if (isMaster())
  99. return m_document;
  100. HTMLImportsController* import = document().importsController();
  101. if (!import) // Document::import() can return null while executing its destructor.
  102. return 0;
  103. return import->master();
  104. }
  105. TreeScopeStyleSheetCollection* StyleEngine::ensureStyleSheetCollectionFor(TreeScope& treeScope)
  106. {
  107. if (treeScope == m_document)
  108. return documentStyleSheetCollection();
  109. StyleSheetCollectionMap::AddResult result = m_styleSheetCollectionMap.add(&treeScope, nullptr);
  110. if (result.isNewEntry)
  111. result.storedValue->value = adoptPtrWillBeNoop(new ShadowTreeStyleSheetCollection(toShadowRoot(treeScope)));
  112. return result.storedValue->value.get();
  113. }
  114. TreeScopeStyleSheetCollection* StyleEngine::styleSheetCollectionFor(TreeScope& treeScope)
  115. {
  116. if (treeScope == m_document)
  117. return documentStyleSheetCollection();
  118. StyleSheetCollectionMap::iterator it = m_styleSheetCollectionMap.find(&treeScope);
  119. if (it == m_styleSheetCollectionMap.end())
  120. return 0;
  121. return it->value.get();
  122. }
  123. const WillBeHeapVector<RefPtrWillBeMember<StyleSheet>>& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope)
  124. {
  125. if (treeScope == m_document)
  126. return documentStyleSheetCollection()->styleSheetsForStyleSheetList();
  127. return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetList();
  128. }
  129. const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet>>& StyleEngine::activeAuthorStyleSheets() const
  130. {
  131. return documentStyleSheetCollection()->activeAuthorStyleSheets();
  132. }
  133. void StyleEngine::combineCSSFeatureFlags(const RuleFeatureSet& features)
  134. {
  135. // 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).
  136. m_usesSiblingRules = m_usesSiblingRules || features.usesSiblingRules();
  137. m_usesFirstLineRules = m_usesFirstLineRules || features.usesFirstLineRules();
  138. m_usesWindowInactiveSelector = m_usesWindowInactiveSelector || features.usesWindowInactiveSelector();
  139. m_maxDirectAdjacentSelectors = max(m_maxDirectAdjacentSelectors, features.maxDirectAdjacentSelectors());
  140. }
  141. void StyleEngine::resetCSSFeatureFlags(const RuleFeatureSet& features)
  142. {
  143. m_usesSiblingRules = features.usesSiblingRules();
  144. m_usesFirstLineRules = features.usesFirstLineRules();
  145. m_usesWindowInactiveSelector = features.usesWindowInactiveSelector();
  146. m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors();
  147. }
  148. void StyleEngine::addAuthorSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> authorSheet)
  149. {
  150. m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, m_document));
  151. document().addedStyleSheet(m_authorStyleSheets.last().get());
  152. markDocumentDirty();
  153. }
  154. void StyleEngine::addPendingSheet()
  155. {
  156. m_pendingStylesheets++;
  157. }
  158. // This method is called whenever a top-level stylesheet has finished loading.
  159. void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode)
  160. {
  161. ASSERT(styleSheetCandidateNode);
  162. TreeScope* treeScope = isStyleElement(*styleSheetCandidateNode) ? &styleSheetCandidateNode->treeScope() : m_document.get();
  163. if (styleSheetCandidateNode->inDocument())
  164. markTreeScopeDirty(*treeScope);
  165. // Make sure we knew this sheet was pending, and that our count isn't out of sync.
  166. ASSERT(m_pendingStylesheets > 0);
  167. m_pendingStylesheets--;
  168. if (m_pendingStylesheets)
  169. return;
  170. // FIXME: We can't call addedStyleSheet or removedStyleSheet here because we don't know
  171. // what's new. We should track that to tell the style system what changed.
  172. document().didRemoveAllPendingStylesheet();
  173. }
  174. void StyleEngine::modifiedStyleSheet(StyleSheet* sheet)
  175. {
  176. if (!sheet)
  177. return;
  178. Node* node = sheet->ownerNode();
  179. if (!node || !node->inDocument())
  180. return;
  181. TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document;
  182. ASSERT(isStyleElement(*node) || treeScope == m_document);
  183. markTreeScopeDirty(treeScope);
  184. }
  185. void StyleEngine::addStyleSheetCandidateNode(Node* node, bool createdByParser)
  186. {
  187. if (!node->inDocument() || document().isDetached())
  188. return;
  189. TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document;
  190. ASSERT(isStyleElement(*node) || treeScope == m_document);
  191. ASSERT(!isXSLStyleSheet(*node));
  192. TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope);
  193. ASSERT(collection);
  194. collection->addStyleSheetCandidateNode(node, createdByParser);
  195. markTreeScopeDirty(treeScope);
  196. if (treeScope != m_document)
  197. m_activeTreeScopes.add(&treeScope);
  198. }
  199. void StyleEngine::removeStyleSheetCandidateNode(Node* node)
  200. {
  201. removeStyleSheetCandidateNode(node, *m_document);
  202. }
  203. void StyleEngine::removeStyleSheetCandidateNode(Node* node, TreeScope& treeScope)
  204. {
  205. ASSERT(isStyleElement(*node) || treeScope == m_document);
  206. ASSERT(!isXSLStyleSheet(*node));
  207. TreeScopeStyleSheetCollection* collection = styleSheetCollectionFor(treeScope);
  208. // After detaching document, collection could be null. In the case,
  209. // we should not update anything. Instead, just return.
  210. if (!collection)
  211. return;
  212. collection->removeStyleSheetCandidateNode(node);
  213. markTreeScopeDirty(treeScope);
  214. }
  215. void StyleEngine::modifiedStyleSheetCandidateNode(Node* node)
  216. {
  217. if (!node->inDocument())
  218. return;
  219. TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document;
  220. ASSERT(isStyleElement(*node) || treeScope == m_document);
  221. markTreeScopeDirty(treeScope);
  222. }
  223. bool StyleEngine::shouldUpdateDocumentStyleSheetCollection(StyleResolverUpdateMode updateMode) const
  224. {
  225. return m_documentScopeDirty || updateMode == FullStyleUpdate;
  226. }
  227. bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode) const
  228. {
  229. return !m_dirtyTreeScopes.isEmpty() || updateMode == FullStyleUpdate;
  230. }
  231. void StyleEngine::clearMediaQueryRuleSetOnTreeScopeStyleSheets(UnorderedTreeScopeSet& treeScopes)
  232. {
  233. for (TreeScope* treeScope : treeScopes) {
  234. ASSERT(treeScope != m_document);
  235. ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(*treeScope));
  236. ASSERT(collection);
  237. collection->clearMediaQueryRuleSetStyleSheets();
  238. }
  239. }
  240. void StyleEngine::clearMediaQueryRuleSetStyleSheets()
  241. {
  242. documentStyleSheetCollection()->clearMediaQueryRuleSetStyleSheets();
  243. clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_activeTreeScopes);
  244. clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_dirtyTreeScopes);
  245. }
  246. void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentCollector)
  247. {
  248. ASSERT(!isMaster());
  249. WillBeHeapVector<RefPtrWillBeMember<StyleSheet>> sheetsForList;
  250. ImportedDocumentStyleSheetCollector subcollector(parentCollector, sheetsForList);
  251. documentStyleSheetCollection()->collectStyleSheets(*this, subcollector);
  252. documentStyleSheetCollection()->swapSheetsForSheetList(sheetsForList);
  253. }
  254. void StyleEngine::updateActiveStyleSheetsInShadow(StyleResolverUpdateMode updateMode, TreeScope* treeScope, UnorderedTreeScopeSet& treeScopesRemoved)
  255. {
  256. ASSERT(treeScope != m_document);
  257. ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(*treeScope));
  258. ASSERT(collection);
  259. collection->updateActiveStyleSheets(*this, updateMode);
  260. if (!collection->hasStyleSheetCandidateNodes()) {
  261. treeScopesRemoved.add(treeScope);
  262. // When removing TreeScope from ActiveTreeScopes,
  263. // its resolver should be destroyed by invoking resetAuthorStyle.
  264. ASSERT(!treeScope->scopedStyleResolver());
  265. }
  266. }
  267. void StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode)
  268. {
  269. ASSERT(isMaster());
  270. ASSERT(!document().inStyleRecalc());
  271. if (!document().isActive())
  272. return;
  273. if (shouldUpdateDocumentStyleSheetCollection(updateMode))
  274. documentStyleSheetCollection()->updateActiveStyleSheets(*this, updateMode);
  275. if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) {
  276. UnorderedTreeScopeSet treeScopesRemoved;
  277. if (updateMode == FullStyleUpdate) {
  278. for (TreeScope* treeScope : m_activeTreeScopes)
  279. updateActiveStyleSheetsInShadow(updateMode, treeScope, treeScopesRemoved);
  280. } else {
  281. for (TreeScope* treeScope : m_dirtyTreeScopes)
  282. updateActiveStyleSheetsInShadow(updateMode, treeScope, treeScopesRemoved);
  283. }
  284. for (TreeScope* treeScope : treeScopesRemoved)
  285. m_activeTreeScopes.remove(treeScope);
  286. }
  287. InspectorInstrumentation::activeStyleSheetsUpdated(m_document);
  288. m_dirtyTreeScopes.clear();
  289. m_documentScopeDirty = false;
  290. }
  291. const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet>> StyleEngine::activeStyleSheetsForInspector() const
  292. {
  293. if (m_activeTreeScopes.isEmpty())
  294. return documentStyleSheetCollection()->activeAuthorStyleSheets();
  295. WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet>> activeStyleSheets;
  296. activeStyleSheets.appendVector(documentStyleSheetCollection()->activeAuthorStyleSheets());
  297. for (TreeScope* treeScope : m_activeTreeScopes) {
  298. if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(treeScope))
  299. activeStyleSheets.appendVector(collection->activeAuthorStyleSheets());
  300. }
  301. // FIXME: Inspector needs a vector which has all active stylesheets.
  302. // However, creating such a large vector might cause performance regression.
  303. // Need to implement some smarter solution.
  304. return activeStyleSheets;
  305. }
  306. void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot)
  307. {
  308. m_styleSheetCollectionMap.remove(shadowRoot);
  309. m_activeTreeScopes.remove(shadowRoot);
  310. m_dirtyTreeScopes.remove(shadowRoot);
  311. }
  312. void StyleEngine::shadowRootRemovedFromDocument(ShadowRoot* shadowRoot)
  313. {
  314. if (StyleResolver* styleResolver = resolver()) {
  315. styleResolver->resetAuthorStyle(*shadowRoot);
  316. if (TreeScopeStyleSheetCollection* collection = styleSheetCollectionFor(*shadowRoot))
  317. styleResolver->removePendingAuthorStyleSheets(collection->activeAuthorStyleSheets());
  318. }
  319. m_styleSheetCollectionMap.remove(shadowRoot);
  320. m_activeTreeScopes.remove(shadowRoot);
  321. m_dirtyTreeScopes.remove(shadowRoot);
  322. }
  323. void StyleEngine::appendActiveAuthorStyleSheets()
  324. {
  325. ASSERT(isMaster());
  326. m_resolver->appendAuthorStyleSheets(documentStyleSheetCollection()->activeAuthorStyleSheets());
  327. for (TreeScope* treeScope : m_activeTreeScopes) {
  328. if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(treeScope))
  329. m_resolver->appendAuthorStyleSheets(collection->activeAuthorStyleSheets());
  330. }
  331. m_resolver->finishAppendAuthorStyleSheets();
  332. }
  333. void StyleEngine::createResolver()
  334. {
  335. TRACE_EVENT1("blink", "StyleEngine::createResolver", "frame", document().frame());
  336. // It is a programming error to attempt to resolve style on a Document
  337. // which is not in a frame. Code which hits this should have checked
  338. // Document::isActive() before calling into code which could get here.
  339. ASSERT(document().frame());
  340. m_resolver = adoptPtrWillBeNoop(new StyleResolver(*m_document));
  341. // A scoped style resolver for document will be created during
  342. // appendActiveAuthorStyleSheets if needed.
  343. appendActiveAuthorStyleSheets();
  344. combineCSSFeatureFlags(m_resolver->ensureUpdatedRuleFeatureSet());
  345. }
  346. void StyleEngine::clearResolver()
  347. {
  348. ASSERT(!document().inStyleRecalc());
  349. ASSERT(isMaster() || !m_resolver);
  350. document().clearScopedStyleResolver();
  351. // StyleEngine::shadowRootRemovedFromDocument removes not-in-document
  352. // treescopes from activeTreeScopes. StyleEngine::didRemoveShadowRoot
  353. // removes treescopes which are being destroyed from activeTreeScopes.
  354. // So we need to clearScopedStyleResolver for treescopes which have been
  355. // just removed from document. If document is destroyed before invoking
  356. // updateActiveStyleSheets, the treescope has a scopedStyleResolver which
  357. // has destroyed StyleSheetContents.
  358. for (TreeScope* treeScope : m_activeTreeScopes)
  359. treeScope->clearScopedStyleResolver();
  360. if (m_resolver) {
  361. TRACE_EVENT1("blink", "StyleEngine::clearResolver", "frame", document().frame());
  362. m_resolver.clear();
  363. }
  364. }
  365. void StyleEngine::clearMasterResolver()
  366. {
  367. if (Document* master = this->master())
  368. master->styleEngine().clearResolver();
  369. }
  370. unsigned StyleEngine::resolverAccessCount() const
  371. {
  372. return m_resolver ? m_resolver->accessCount() : 0;
  373. }
  374. void StyleEngine::didDetach()
  375. {
  376. clearResolver();
  377. }
  378. bool StyleEngine::shouldClearResolver() const
  379. {
  380. return !m_didCalculateResolver && !haveStylesheetsLoaded();
  381. }
  382. void StyleEngine::resolverChanged(StyleResolverUpdateMode mode)
  383. {
  384. if (!isMaster()) {
  385. if (Document* master = this->master())
  386. master->styleResolverChanged(mode);
  387. return;
  388. }
  389. // Don't bother updating, since we haven't loaded all our style info yet
  390. // and haven't calculated the style selector for the first time.
  391. if (!document().isActive() || shouldClearResolver()) {
  392. clearResolver();
  393. return;
  394. }
  395. m_didCalculateResolver = true;
  396. updateActiveStyleSheets(mode);
  397. }
  398. void StyleEngine::clearFontCache()
  399. {
  400. if (m_fontSelector)
  401. m_fontSelector->fontFaceCache()->clearCSSConnected();
  402. if (m_resolver)
  403. m_resolver->invalidateMatchedPropertiesCache();
  404. }
  405. void StyleEngine::updateGenericFontFamilySettings()
  406. {
  407. // FIXME: we should not update generic font family settings when
  408. // document is inactive.
  409. ASSERT(document().isActive());
  410. if (!m_fontSelector)
  411. return;
  412. m_fontSelector->updateGenericFontFamilySettings(*m_document);
  413. if (m_resolver)
  414. m_resolver->invalidateMatchedPropertiesCache();
  415. }
  416. void StyleEngine::removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace>>& fontFaceRules)
  417. {
  418. if (!m_fontSelector)
  419. return;
  420. FontFaceCache* cache = m_fontSelector->fontFaceCache();
  421. for (unsigned i = 0; i < fontFaceRules.size(); ++i)
  422. cache->remove(fontFaceRules[i]);
  423. if (m_resolver)
  424. m_resolver->invalidateMatchedPropertiesCache();
  425. }
  426. void StyleEngine::markTreeScopeDirty(TreeScope& scope)
  427. {
  428. if (scope == m_document) {
  429. markDocumentDirty();
  430. return;
  431. }
  432. ASSERT(m_styleSheetCollectionMap.contains(&scope));
  433. m_dirtyTreeScopes.add(&scope);
  434. }
  435. void StyleEngine::markDocumentDirty()
  436. {
  437. m_documentScopeDirty = true;
  438. if (document().importLoader())
  439. document().importsController()->master()->styleEngine().markDocumentDirty();
  440. }
  441. static bool isCacheableForStyleElement(const StyleSheetContents& contents)
  442. {
  443. // FIXME: Support copying import rules.
  444. if (!contents.importRules().isEmpty())
  445. return false;
  446. // Until import rules are supported in cached sheets it's not possible for loading to fail.
  447. ASSERT(!contents.didLoadErrorOccur());
  448. // It is not the original sheet anymore.
  449. if (contents.isMutable())
  450. return false;
  451. if (!contents.hasSyntacticallyValidCSSHeader())
  452. return false;
  453. return true;
  454. }
  455. PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::createSheet(Element* e, const String& text, TextPosition startPosition)
  456. {
  457. RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet = nullptr;
  458. e->document().styleEngine().addPendingSheet();
  459. AtomicString textContent(text);
  460. WillBeHeapHashMap<AtomicString, RawPtrWillBeMember<StyleSheetContents>>::AddResult result = m_textToSheetCache.add(textContent, nullptr);
  461. if (result.isNewEntry || !result.storedValue->value) {
  462. styleSheet = StyleEngine::parseSheet(e, text, startPosition);
  463. if (result.isNewEntry && isCacheableForStyleElement(*styleSheet->contents())) {
  464. result.storedValue->value = styleSheet->contents();
  465. m_sheetToTextCache.add(styleSheet->contents(), textContent);
  466. }
  467. } else {
  468. StyleSheetContents* contents = result.storedValue->value;
  469. ASSERT(contents);
  470. ASSERT(isCacheableForStyleElement(*contents));
  471. ASSERT(contents->singleOwnerDocument() == e->document());
  472. styleSheet = CSSStyleSheet::createInline(contents, e, startPosition);
  473. }
  474. ASSERT(styleSheet);
  475. styleSheet->setTitle(e->title());
  476. return styleSheet;
  477. }
  478. PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::parseSheet(Element* e, const String& text, TextPosition startPosition)
  479. {
  480. RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet = nullptr;
  481. styleSheet = CSSStyleSheet::createInline(e, KURL(), startPosition, e->document().characterSet());
  482. styleSheet->contents()->parseStringAtPosition(text, startPosition);
  483. return styleSheet;
  484. }
  485. void StyleEngine::removeSheet(StyleSheetContents* contents)
  486. {
  487. WillBeHeapHashMap<RawPtrWillBeMember<StyleSheetContents>, AtomicString>::iterator it = m_sheetToTextCache.find(contents);
  488. if (it == m_sheetToTextCache.end())
  489. return;
  490. m_textToSheetCache.remove(it->value);
  491. m_sheetToTextCache.remove(contents);
  492. }
  493. void StyleEngine::collectScopedStyleFeaturesTo(RuleFeatureSet& features) const
  494. {
  495. HashSet<const StyleSheetContents*> visitedSharedStyleSheetContents;
  496. if (document().scopedStyleResolver())
  497. document().scopedStyleResolver()->collectFeaturesTo(features, visitedSharedStyleSheetContents);
  498. for (TreeScope* treeScope : m_activeTreeScopes) {
  499. // When creating StyleResolver, dirty treescopes might not be processed.
  500. // So some active treescopes might not have a scoped style resolver.
  501. // In this case, we should skip collectFeatures for the treescopes without
  502. // scoped style resolvers. When invoking updateActiveStyleSheets,
  503. // the treescope's features will be processed.
  504. if (ScopedStyleResolver* resolver = treeScope->scopedStyleResolver())
  505. resolver->collectFeaturesTo(features, visitedSharedStyleSheetContents);
  506. }
  507. }
  508. void StyleEngine::fontsNeedUpdate(CSSFontSelector*)
  509. {
  510. if (!document().isActive())
  511. return;
  512. if (m_resolver)
  513. m_resolver->invalidateMatchedPropertiesCache();
  514. document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Fonts));
  515. }
  516. void StyleEngine::setFontSelector(PassRefPtrWillBeRawPtr<CSSFontSelector> fontSelector)
  517. {
  518. #if !ENABLE(OILPAN)
  519. if (m_fontSelector)
  520. m_fontSelector->unregisterForInvalidationCallbacks(this);
  521. #endif
  522. m_fontSelector = fontSelector;
  523. if (m_fontSelector)
  524. m_fontSelector->registerForInvalidationCallbacks(this);
  525. }
  526. void StyleEngine::platformColorsChanged()
  527. {
  528. if (m_resolver)
  529. m_resolver->invalidateMatchedPropertiesCache();
  530. document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::PlatformColorChange));
  531. }
  532. void StyleEngine::classChangedForElement(const SpaceSplitString& changedClasses, Element& element)
  533. {
  534. ASSERT(isMaster());
  535. InvalidationSetVector invalidationSets;
  536. unsigned changedSize = changedClasses.size();
  537. RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSet();
  538. for (unsigned i = 0; i < changedSize; ++i)
  539. ruleFeatureSet.collectInvalidationSetsForClass(invalidationSets, element, changedClasses[i]);
  540. scheduleInvalidationSetsForElement(invalidationSets, element);
  541. }
  542. void StyleEngine::classChangedForElement(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element& element)
  543. {
  544. ASSERT(isMaster());
  545. InvalidationSetVector invalidationSets;
  546. if (!oldClasses.size()) {
  547. classChangedForElement(newClasses, element);
  548. return;
  549. }
  550. // Class vectors tend to be very short. This is faster than using a hash table.
  551. BitVector remainingClassBits;
  552. remainingClassBits.ensureSize(oldClasses.size());
  553. RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSet();
  554. for (unsigned i = 0; i < newClasses.size(); ++i) {
  555. bool found = false;
  556. for (unsigned j = 0; j < oldClasses.size(); ++j) {
  557. if (newClasses[i] == oldClasses[j]) {
  558. // Mark each class that is still in the newClasses so we can skip doing
  559. // an n^2 search below when looking for removals. We can't break from
  560. // this loop early since a class can appear more than once.
  561. remainingClassBits.quickSet(j);
  562. found = true;
  563. }
  564. }
  565. // Class was added.
  566. if (!found)
  567. ruleFeatureSet.collectInvalidationSetsForClass(invalidationSets, element, newClasses[i]);
  568. }
  569. for (unsigned i = 0; i < oldClasses.size(); ++i) {
  570. if (remainingClassBits.quickGet(i))
  571. continue;
  572. // Class was removed.
  573. ruleFeatureSet.collectInvalidationSetsForClass(invalidationSets, element, oldClasses[i]);
  574. }
  575. scheduleInvalidationSetsForElement(invalidationSets, element);
  576. }
  577. void StyleEngine::attributeChangedForElement(const QualifiedName& attributeName, Element& element)
  578. {
  579. ASSERT(isMaster());
  580. InvalidationSetVector invalidationSets;
  581. ensureResolver().ensureUpdatedRuleFeatureSet().collectInvalidationSetsForAttribute(invalidationSets, element, attributeName);
  582. scheduleInvalidationSetsForElement(invalidationSets, element);
  583. }
  584. void StyleEngine::idChangedForElement(const AtomicString& oldId, const AtomicString& newId, Element& element)
  585. {
  586. ASSERT(isMaster());
  587. InvalidationSetVector invalidationSets;
  588. RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSet();
  589. if (!oldId.isEmpty())
  590. ruleFeatureSet.collectInvalidationSetsForId(invalidationSets, element, oldId);
  591. if (!newId.isEmpty())
  592. ruleFeatureSet.collectInvalidationSetsForId(invalidationSets, element, newId);
  593. scheduleInvalidationSetsForElement(invalidationSets, element);
  594. }
  595. void StyleEngine::pseudoStateChangedForElement(CSSSelector::PseudoType pseudoType, Element& element)
  596. {
  597. ASSERT(isMaster());
  598. InvalidationSetVector invalidationSets;
  599. ensureResolver().ensureUpdatedRuleFeatureSet().collectInvalidationSetsForPseudoClass(invalidationSets, element, pseudoType);
  600. scheduleInvalidationSetsForElement(invalidationSets, element);
  601. }
  602. void StyleEngine::scheduleInvalidationSetsForElement(const InvalidationSetVector& invalidationSets, Element& element)
  603. {
  604. for (auto invalidationSet : invalidationSets)
  605. m_styleInvalidator.scheduleInvalidation(invalidationSet, element);
  606. }
  607. DEFINE_TRACE(StyleEngine)
  608. {
  609. #if ENABLE(OILPAN)
  610. visitor->trace(m_document);
  611. visitor->trace(m_authorStyleSheets);
  612. visitor->trace(m_documentStyleSheetCollection);
  613. visitor->trace(m_styleSheetCollectionMap);
  614. visitor->trace(m_resolver);
  615. visitor->trace(m_styleInvalidator);
  616. visitor->trace(m_dirtyTreeScopes);
  617. visitor->trace(m_activeTreeScopes);
  618. visitor->trace(m_fontSelector);
  619. visitor->trace(m_textToSheetCache);
  620. visitor->trace(m_sheetToTextCache);
  621. #endif
  622. CSSFontSelectorClient::trace(visitor);
  623. }
  624. }