blob: 9e8b71d4c673970a39ca4861bb7e752b3c417e05 [file] [log] [blame]
antti@apple.comd8eeff62015-09-23 15:04:16 +00001/*
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)
antti@apple.com215ce402016-10-07 16:55:11 +00006 * Copyright (C) 2004-2009, 2011-2012, 2015-2016 Apple Inc. All rights reserved.
antti@apple.comd8eeff62015-09-23 15:04:16 +00007 * 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"
antti@apple.com215ce402016-10-07 16:55:11 +000029#include "StyleScope.h"
antti@apple.comd8eeff62015-09-23 15:04:16 +000030
31#include "CSSStyleSheet.h"
32#include "Element.h"
antti@apple.comf2400ed2016-09-26 23:51:17 +000033#include "ElementChildIterator.h"
antti@apple.comd8eeff62015-09-23 15:04:16 +000034#include "ExtensionStyleSheets.h"
35#include "HTMLIFrameElement.h"
36#include "HTMLLinkElement.h"
antti@apple.com33415542016-12-05 22:42:28 +000037#include "HTMLSlotElement.h"
antti@apple.comd8eeff62015-09-23 15:04:16 +000038#include "HTMLStyleElement.h"
39#include "InspectorInstrumentation.h"
antti@apple.comd8eeff62015-09-23 15:04:16 +000040#include "ProcessingInstruction.h"
antti@apple.comd8eeff62015-09-23 15:04:16 +000041#include "SVGStyleElement.h"
42#include "Settings.h"
antti@apple.comd14e08d2015-09-25 22:06:09 +000043#include "ShadowRoot.h"
antti@apple.comd8eeff62015-09-23 15:04:16 +000044#include "StyleInvalidationAnalysis.h"
45#include "StyleResolver.h"
46#include "StyleSheetContents.h"
47#include "StyleSheetList.h"
48#include "UserContentController.h"
49#include "UserContentURLPattern.h"
50#include "UserStyleSheet.h"
51
52namespace WebCore {
53
54using namespace ContentExtensions;
55using namespace HTMLNames;
56
antti@apple.com215ce402016-10-07 16:55:11 +000057namespace Style {
58
59Scope::Scope(Document& document)
antti@apple.comd14e08d2015-09-25 22:06:09 +000060 : m_document(document)
antti@apple.com215ce402016-10-07 16:55:11 +000061 , m_pendingUpdateTimer(*this, &Scope::pendingUpdateTimerFired)
antti@apple.comd14e08d2015-09-25 22:06:09 +000062{
63}
64
antti@apple.com215ce402016-10-07 16:55:11 +000065Scope::Scope(ShadowRoot& shadowRoot)
antti@apple.comd14e08d2015-09-25 22:06:09 +000066 : m_document(shadowRoot.documentScope())
67 , m_shadowRoot(&shadowRoot)
antti@apple.com215ce402016-10-07 16:55:11 +000068 , m_pendingUpdateTimer(*this, &Scope::pendingUpdateTimerFired)
antti@apple.comd8eeff62015-09-23 15:04:16 +000069{
70}
71
antti@apple.com4f9ac5b2016-10-21 13:36:45 +000072Scope::~Scope()
73{
74}
75
antti@apple.comb4a1f8c2016-10-13 09:22:38 +000076bool Scope::shouldUseSharedUserAgentShadowTreeStyleResolver() const
77{
78 if (!m_shadowRoot)
79 return false;
cdumez@apple.comdc3b6ad2016-10-27 20:23:06 +000080 if (m_shadowRoot->mode() != ShadowRootMode::UserAgent)
antti@apple.comb4a1f8c2016-10-13 09:22:38 +000081 return false;
82 // If we have stylesheets in the user agent shadow tree use per-scope resolver.
83 if (!m_styleSheetCandidateNodes.isEmpty())
84 return false;
85 return true;
86}
87
antti@apple.comd00354e22016-10-08 08:42:03 +000088StyleResolver& Scope::resolver()
antti@apple.comdff10722016-10-06 20:53:08 +000089{
antti@apple.comb4a1f8c2016-10-13 09:22:38 +000090 if (shouldUseSharedUserAgentShadowTreeStyleResolver())
antti@apple.comd00354e22016-10-08 08:42:03 +000091 return m_document.userAgentShadowTreeStyleResolver();
antti@apple.comdff10722016-10-06 20:53:08 +000092
antti@apple.comd00354e22016-10-08 08:42:03 +000093 if (!m_resolver) {
94 m_resolver = std::make_unique<StyleResolver>(m_document);
95 m_resolver->appendAuthorStyleSheets(m_activeStyleSheets);
96 }
antti@apple.com217d3d22016-11-22 20:13:38 +000097 ASSERT(!m_shadowRoot || &m_document == &m_shadowRoot->document());
98 ASSERT(&m_resolver->document() == &m_document);
antti@apple.comd00354e22016-10-08 08:42:03 +000099 return *m_resolver;
antti@apple.comdff10722016-10-06 20:53:08 +0000100}
101
antti@apple.comd00354e22016-10-08 08:42:03 +0000102StyleResolver* Scope::resolverIfExists()
antti@apple.comdff10722016-10-06 20:53:08 +0000103{
antti@apple.comb4a1f8c2016-10-13 09:22:38 +0000104 if (shouldUseSharedUserAgentShadowTreeStyleResolver())
antti@apple.comd00354e22016-10-08 08:42:03 +0000105 return &m_document.userAgentShadowTreeStyleResolver();
antti@apple.comdff10722016-10-06 20:53:08 +0000106
antti@apple.comd00354e22016-10-08 08:42:03 +0000107 return m_resolver.get();
108}
109
110void Scope::clearResolver()
111{
112 m_resolver = nullptr;
113
114 if (!m_shadowRoot)
115 m_document.didClearStyleResolver();
antti@apple.comdff10722016-10-06 20:53:08 +0000116}
117
antti@apple.com215ce402016-10-07 16:55:11 +0000118Scope& Scope::forNode(Node& node)
antti@apple.comdff10722016-10-06 20:53:08 +0000119{
cdumez@apple.com85cc2622017-02-02 21:29:15 +0000120 ASSERT(node.isConnected());
antti@apple.comdff10722016-10-06 20:53:08 +0000121 auto* shadowRoot = node.containingShadowRoot();
122 if (shadowRoot)
antti@apple.com215ce402016-10-07 16:55:11 +0000123 return shadowRoot->styleScope();
124 return node.document().styleScope();
antti@apple.comdff10722016-10-06 20:53:08 +0000125}
126
antti@apple.com33415542016-12-05 22:42:28 +0000127Scope* Scope::forOrdinal(Element& element, ScopeOrdinal ordinal)
128{
129 switch (ordinal) {
130 case ScopeOrdinal::Element:
131 return &forNode(element);
132 case ScopeOrdinal::ContainingHost: {
133 auto* containingShadowRoot = element.containingShadowRoot();
134 if (!containingShadowRoot)
135 return nullptr;
136 return &forNode(*containingShadowRoot->host());
137 }
138 case ScopeOrdinal::Shadow: {
139 auto* shadowRoot = element.shadowRoot();
140 if (!shadowRoot)
141 return nullptr;
142 return &shadowRoot->styleScope();
143 }
144 default: {
145 ASSERT(ordinal >= ScopeOrdinal::FirstSlot);
146 auto slotIndex = ScopeOrdinal::FirstSlot;
147 for (auto* slot = element.assignedSlot(); slot; slot = slot->assignedSlot(), ++slotIndex) {
148 if (slotIndex == ordinal)
149 return &forNode(*slot);
150 }
151 return nullptr;
152 }
153 }
154}
155
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000156void Scope::setPreferredStylesheetSetName(const String& name)
157{
158 if (m_preferredStylesheetSetName == name)
159 return;
160 m_preferredStylesheetSetName = name;
161 didChangeActiveStyleSheetCandidates();
162}
163
164void Scope::setSelectedStylesheetSetName(const String& name)
165{
166 if (m_selectedStylesheetSetName == name)
167 return;
168 m_selectedStylesheetSetName = name;
169 didChangeActiveStyleSheetCandidates();
170}
171
antti@apple.comd8eeff62015-09-23 15:04:16 +0000172// This method is called whenever a top-level stylesheet has finished loading.
antti@apple.com215ce402016-10-07 16:55:11 +0000173void Scope::removePendingSheet(RemovePendingSheetNotificationType notification)
antti@apple.comd8eeff62015-09-23 15:04:16 +0000174{
175 // Make sure we knew this sheet was pending, and that our count isn't out of sync.
176 ASSERT(m_pendingStyleSheetCount > 0);
177
178 m_pendingStyleSheetCount--;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000179 if (m_pendingStyleSheetCount)
180 return;
181
182 if (notification == RemovePendingSheetNotifyLater) {
183 m_document.setNeedsNotifyRemoveAllPendingStylesheet();
184 return;
185 }
antti@apple.comd14e08d2015-09-25 22:06:09 +0000186
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000187 didChangeActiveStyleSheetCandidates();
antti@apple.comd14e08d2015-09-25 22:06:09 +0000188
antti@apple.com8ed5a402016-10-10 08:19:03 +0000189 if (!m_shadowRoot)
190 m_document.didRemoveAllPendingStylesheet();
antti@apple.comd8eeff62015-09-23 15:04:16 +0000191}
192
antti@apple.com215ce402016-10-07 16:55:11 +0000193void Scope::addStyleSheetCandidateNode(Node& node, bool createdByParser)
antti@apple.comd8eeff62015-09-23 15:04:16 +0000194{
cdumez@apple.com85cc2622017-02-02 21:29:15 +0000195 if (!node.isConnected())
antti@apple.comd8eeff62015-09-23 15:04:16 +0000196 return;
197
198 // Until the <body> exists, we have no choice but to compare document positions,
199 // since styles outside of the body and head continue to be shunted into the head
200 // (and thus can shift to end up before dynamically added DOM content that is also
201 // outside the body).
202 if ((createdByParser && m_document.bodyOrFrameset()) || m_styleSheetCandidateNodes.isEmpty()) {
203 m_styleSheetCandidateNodes.add(&node);
204 return;
205 }
206
207 // Determine an appropriate insertion point.
208 auto begin = m_styleSheetCandidateNodes.begin();
209 auto end = m_styleSheetCandidateNodes.end();
210 auto it = end;
211 Node* followingNode = nullptr;
212 do {
213 --it;
214 Node* n = *it;
cdumez@apple.com18a0d9d2016-07-22 16:01:48 +0000215 unsigned short position = n->compareDocumentPosition(node);
antti@apple.comd8eeff62015-09-23 15:04:16 +0000216 if (position == Node::DOCUMENT_POSITION_FOLLOWING) {
217 m_styleSheetCandidateNodes.insertBefore(followingNode, &node);
218 return;
219 }
220 followingNode = n;
221 } while (it != begin);
222
223 m_styleSheetCandidateNodes.insertBefore(followingNode, &node);
224}
225
antti@apple.com215ce402016-10-07 16:55:11 +0000226void Scope::removeStyleSheetCandidateNode(Node& node)
antti@apple.comd8eeff62015-09-23 15:04:16 +0000227{
antti@apple.comdff10722016-10-06 20:53:08 +0000228 if (m_styleSheetCandidateNodes.remove(&node))
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000229 didChangeActiveStyleSheetCandidates();
antti@apple.comd8eeff62015-09-23 15:04:16 +0000230}
231
antti@apple.com215ce402016-10-07 16:55:11 +0000232void Scope::collectActiveStyleSheets(Vector<RefPtr<StyleSheet>>& sheets)
antti@apple.comd8eeff62015-09-23 15:04:16 +0000233{
234 if (m_document.settings() && !m_document.settings()->authorAndUserStylesEnabled())
235 return;
236
237 for (auto& node : m_styleSheetCandidateNodes) {
238 StyleSheet* sheet = nullptr;
239 if (is<ProcessingInstruction>(*node)) {
240 // Processing instruction (XML documents only).
241 // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
242 ProcessingInstruction& pi = downcast<ProcessingInstruction>(*node);
243 sheet = pi.sheet();
244#if ENABLE(XSLT)
245 // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
246 if (pi.isXSL() && !m_document.transformSourceDocument()) {
247 // Don't apply XSL transforms until loading is finished.
248 if (!m_document.parsing())
249 m_document.applyXSLTransform(&pi);
250 return;
251 }
252#endif
253 } else if (is<HTMLLinkElement>(*node) || is<HTMLStyleElement>(*node) || is<SVGStyleElement>(*node)) {
254 Element& element = downcast<Element>(*node);
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000255 AtomicString title = element.attributeWithoutSynchronization(titleAttr);
antti@apple.comd8eeff62015-09-23 15:04:16 +0000256 bool enabledViaScript = false;
257 if (is<HTMLLinkElement>(element)) {
258 // <LINK> element
259 HTMLLinkElement& linkElement = downcast<HTMLLinkElement>(element);
260 if (linkElement.isDisabled())
261 continue;
262 enabledViaScript = linkElement.isEnabledViaScript();
263 if (linkElement.styleSheetIsLoading()) {
264 // it is loading but we should still decide which style sheet set to use
265 if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSetName.isEmpty()) {
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000266 if (!linkElement.attributeWithoutSynchronization(relAttr).contains("alternate")) {
antti@apple.comd8eeff62015-09-23 15:04:16 +0000267 m_preferredStylesheetSetName = title;
268 m_selectedStylesheetSetName = title;
269 }
270 }
271 continue;
272 }
273 if (!linkElement.sheet())
274 title = nullAtom;
275 }
276 // Get the current preferred styleset. This is the
277 // set of sheets that will be enabled.
278 if (is<SVGStyleElement>(element))
279 sheet = downcast<SVGStyleElement>(element).sheet();
280 else if (is<HTMLLinkElement>(element))
281 sheet = downcast<HTMLLinkElement>(element).sheet();
282 else
283 sheet = downcast<HTMLStyleElement>(element).sheet();
284 // Check to see if this sheet belongs to a styleset
285 // (thus making it PREFERRED or ALTERNATE rather than
286 // PERSISTENT).
rniwa@webkit.orge999a052016-07-16 15:21:55 +0000287 auto& rel = element.attributeWithoutSynchronization(relAttr);
antti@apple.comd8eeff62015-09-23 15:04:16 +0000288 if (!enabledViaScript && !title.isEmpty()) {
289 // Yes, we have a title.
290 if (m_preferredStylesheetSetName.isEmpty()) {
291 // No preferred set has been established. If
292 // we are NOT an alternate sheet, then establish
293 // us as the preferred set. Otherwise, just ignore
294 // this sheet.
295 if (is<HTMLStyleElement>(element) || !rel.contains("alternate"))
296 m_preferredStylesheetSetName = m_selectedStylesheetSetName = title;
297 }
298 if (title != m_preferredStylesheetSetName)
299 sheet = nullptr;
300 }
301
302 if (rel.contains("alternate") && title.isEmpty())
303 sheet = nullptr;
304 }
305 if (sheet)
306 sheets.append(sheet);
307 }
308}
309
antti@apple.com215ce402016-10-07 16:55:11 +0000310Scope::StyleResolverUpdateType Scope::analyzeStyleSheetChange(const Vector<RefPtr<CSSStyleSheet>>& newStylesheets, bool& requiresFullStyleRecalc)
antti@apple.comd8eeff62015-09-23 15:04:16 +0000311{
antti@apple.comd8eeff62015-09-23 15:04:16 +0000312 requiresFullStyleRecalc = true;
313
antti@apple.comd8eeff62015-09-23 15:04:16 +0000314 unsigned newStylesheetCount = newStylesheets.size();
antti@apple.comd8eeff62015-09-23 15:04:16 +0000315
antti@apple.comd00354e22016-10-08 08:42:03 +0000316 if (!resolverIfExists())
antti@apple.com0ffd7132015-09-30 15:39:15 +0000317 return Reconstruct;
318
antti@apple.comd00354e22016-10-08 08:42:03 +0000319 auto& styleResolver = *resolverIfExists();
antti@apple.comd8eeff62015-09-23 15:04:16 +0000320
321 // Find out which stylesheets are new.
322 unsigned oldStylesheetCount = m_activeStyleSheets.size();
323 if (newStylesheetCount < oldStylesheetCount)
antti@apple.com0ffd7132015-09-30 15:39:15 +0000324 return Reconstruct;
325
antti@apple.comd8eeff62015-09-23 15:04:16 +0000326 Vector<StyleSheetContents*> addedSheets;
327 unsigned newIndex = 0;
328 for (unsigned oldIndex = 0; oldIndex < oldStylesheetCount; ++oldIndex) {
329 if (newIndex >= newStylesheetCount)
antti@apple.com0ffd7132015-09-30 15:39:15 +0000330 return Reconstruct;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000331 while (m_activeStyleSheets[oldIndex] != newStylesheets[newIndex]) {
332 addedSheets.append(&newStylesheets[newIndex]->contents());
333 ++newIndex;
334 if (newIndex == newStylesheetCount)
antti@apple.com0ffd7132015-09-30 15:39:15 +0000335 return Reconstruct;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000336 }
337 ++newIndex;
338 }
339 bool hasInsertions = !addedSheets.isEmpty();
340 while (newIndex < newStylesheetCount) {
341 addedSheets.append(&newStylesheets[newIndex]->contents());
342 ++newIndex;
343 }
344 // If all new sheets were added at the end of the list we can just add them to existing StyleResolver.
345 // If there were insertions we need to re-add all the stylesheets so rules are ordered correctly.
antti@apple.com0ffd7132015-09-30 15:39:15 +0000346 auto styleResolverUpdateType = hasInsertions ? Reset : Additive;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000347
348 // If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs.
349 if (!m_document.bodyOrFrameset() || m_document.hasNodesWithPlaceholderStyle())
antti@apple.com0ffd7132015-09-30 15:39:15 +0000350 return styleResolverUpdateType;
351
antti@apple.comd8eeff62015-09-23 15:04:16 +0000352 StyleInvalidationAnalysis invalidationAnalysis(addedSheets, styleResolver.mediaQueryEvaluator());
353 if (invalidationAnalysis.dirtiesAllStyle())
antti@apple.com0ffd7132015-09-30 15:39:15 +0000354 return styleResolverUpdateType;
antti@apple.com8ed5a402016-10-10 08:19:03 +0000355
356 if (m_shadowRoot)
357 invalidationAnalysis.invalidateStyle(*m_shadowRoot);
358 else
359 invalidationAnalysis.invalidateStyle(m_document);
360
antti@apple.comd8eeff62015-09-23 15:04:16 +0000361 requiresFullStyleRecalc = false;
antti@apple.com0ffd7132015-09-30 15:39:15 +0000362
363 return styleResolverUpdateType;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000364}
365
366static void filterEnabledNonemptyCSSStyleSheets(Vector<RefPtr<CSSStyleSheet>>& result, const Vector<RefPtr<StyleSheet>>& sheets)
367{
hs85.jeong@samsung.com22102292015-10-30 17:04:07 +0000368 for (auto& sheet : sheets) {
369 if (!is<CSSStyleSheet>(*sheet))
antti@apple.comd8eeff62015-09-23 15:04:16 +0000370 continue;
hs85.jeong@samsung.com22102292015-10-30 17:04:07 +0000371 CSSStyleSheet& styleSheet = downcast<CSSStyleSheet>(*sheet);
antti@apple.com60d1da22016-09-20 20:05:31 +0000372 if (styleSheet.isLoading())
373 continue;
hs85.jeong@samsung.com22102292015-10-30 17:04:07 +0000374 if (styleSheet.disabled())
antti@apple.comd8eeff62015-09-23 15:04:16 +0000375 continue;
hs85.jeong@samsung.com22102292015-10-30 17:04:07 +0000376 if (!styleSheet.length())
antti@apple.comd8eeff62015-09-23 15:04:16 +0000377 continue;
hs85.jeong@samsung.com22102292015-10-30 17:04:07 +0000378 result.append(&styleSheet);
antti@apple.comd8eeff62015-09-23 15:04:16 +0000379 }
380}
381
antti@apple.com215ce402016-10-07 16:55:11 +0000382void Scope::updateActiveStyleSheets(UpdateType updateType)
antti@apple.comd8eeff62015-09-23 15:04:16 +0000383{
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000384 ASSERT(!m_pendingUpdate);
385
386 if (!m_document.hasLivingRenderTree())
387 return;
antti@apple.com6a4f5902016-09-25 13:32:24 +0000388
antti@apple.com27d2b34b2016-07-13 19:17:46 +0000389 if (m_document.inStyleRecalc() || m_document.inRenderTreeUpdate()) {
390 // Protect against deleting style resolver in the middle of a style resolution.
antti@apple.com6a4f5902016-09-25 13:32:24 +0000391 // Crash stacks indicate we can get here when a resource load fails synchronously (for example due to content blocking).
antti@apple.com27d2b34b2016-07-13 19:17:46 +0000392 // FIXME: These kind of cases should be eliminated and this path replaced by an assert.
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000393 m_pendingUpdate = UpdateType::ContentsOrInterpretation;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000394 m_document.scheduleForcedStyleRecalc();
antti@apple.com6a4f5902016-09-25 13:32:24 +0000395 return;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000396 }
antti@apple.com6a4f5902016-09-25 13:32:24 +0000397
antti@apple.com6a4f5902016-09-25 13:32:24 +0000398 // Don't bother updating, since we haven't loaded all our style info yet
399 // and haven't calculated the style resolver for the first time.
400 if (!m_shadowRoot && !m_didUpdateActiveStyleSheets && m_pendingStyleSheetCount) {
antti@apple.comd00354e22016-10-08 08:42:03 +0000401 clearResolver();
antti@apple.com6a4f5902016-09-25 13:32:24 +0000402 return;
403 }
404
405 m_didUpdateActiveStyleSheets = true;
antti@apple.comd8eeff62015-09-23 15:04:16 +0000406
407 Vector<RefPtr<StyleSheet>> activeStyleSheets;
408 collectActiveStyleSheets(activeStyleSheets);
409
410 Vector<RefPtr<CSSStyleSheet>> activeCSSStyleSheets;
411 activeCSSStyleSheets.appendVector(m_document.extensionStyleSheets().injectedAuthorStyleSheets());
412 activeCSSStyleSheets.appendVector(m_document.extensionStyleSheets().authorStyleSheetsForTesting());
413 filterEnabledNonemptyCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
414
antti@apple.com6a4f5902016-09-25 13:32:24 +0000415 bool requiresFullStyleRecalc = true;
416 StyleResolverUpdateType styleResolverUpdateType = Reconstruct;
417 if (updateType == UpdateType::ActiveSet)
418 styleResolverUpdateType = analyzeStyleSheetChange(activeCSSStyleSheets, requiresFullStyleRecalc);
antti@apple.comd8eeff62015-09-23 15:04:16 +0000419
antti@apple.com0ffd7132015-09-30 15:39:15 +0000420 updateStyleResolver(activeCSSStyleSheets, styleResolverUpdateType);
antti@apple.comd8eeff62015-09-23 15:04:16 +0000421
422 m_weakCopyOfActiveStyleSheetListForFastLookup = nullptr;
423 m_activeStyleSheets.swap(activeCSSStyleSheets);
424 m_styleSheetsForStyleSheetList.swap(activeStyleSheets);
425
426 InspectorInstrumentation::activeStyleSheetsUpdated(m_document);
427
428 for (const auto& sheet : m_activeStyleSheets) {
antti@apple.comd8eeff62015-09-23 15:04:16 +0000429 if (sheet->contents().usesStyleBasedEditability())
430 m_usesStyleBasedEditability = true;
431 }
antti@apple.comd8eeff62015-09-23 15:04:16 +0000432
antti@apple.comdd7fe9f2016-11-11 21:59:33 +0000433 // FIXME: Move this code somewhere else.
antti@apple.com6a4f5902016-09-25 13:32:24 +0000434 if (requiresFullStyleRecalc) {
antti@apple.comf2400ed2016-09-26 23:51:17 +0000435 if (m_shadowRoot) {
436 for (auto& shadowChild : childrenOfType<Element>(*m_shadowRoot))
antti@apple.com1c455832016-10-18 12:28:55 +0000437 shadowChild.invalidateStyleForSubtree();
antti@apple.comdd7fe9f2016-11-11 21:59:33 +0000438 if (m_shadowRoot->host()) {
439 if (!resolver().ruleSets().authorStyle().hostPseudoClassRules().isEmpty())
440 m_shadowRoot->host()->invalidateStyle();
441 if (!resolver().ruleSets().authorStyle().slottedPseudoElementRules().isEmpty()) {
442 for (auto& shadowChild : childrenOfType<Element>(*m_shadowRoot->host()))
443 shadowChild.invalidateStyle();
444 }
445 }
antti@apple.comf2400ed2016-09-26 23:51:17 +0000446 } else
antti@apple.com6a4f5902016-09-25 13:32:24 +0000447 m_document.scheduleForcedStyleRecalc();
448 }
antti@apple.comd8eeff62015-09-23 15:04:16 +0000449}
450
antti@apple.com215ce402016-10-07 16:55:11 +0000451void Scope::updateStyleResolver(Vector<RefPtr<CSSStyleSheet>>& activeStyleSheets, StyleResolverUpdateType updateType)
antti@apple.com0ffd7132015-09-30 15:39:15 +0000452{
453 if (updateType == Reconstruct) {
antti@apple.comd00354e22016-10-08 08:42:03 +0000454 clearResolver();
antti@apple.com0ffd7132015-09-30 15:39:15 +0000455 return;
456 }
antti@apple.comd00354e22016-10-08 08:42:03 +0000457 auto& styleResolver = resolver();
antti@apple.com0ffd7132015-09-30 15:39:15 +0000458
459 if (updateType == Reset) {
460 styleResolver.ruleSets().resetAuthorStyle();
461 styleResolver.appendAuthorStyleSheets(activeStyleSheets);
462 } else {
463 ASSERT(updateType == Additive);
464 unsigned firstNewIndex = m_activeStyleSheets.size();
465 Vector<RefPtr<CSSStyleSheet>> newStyleSheets;
466 newStyleSheets.appendRange(activeStyleSheets.begin() + firstNewIndex, activeStyleSheets.end());
467 styleResolver.appendAuthorStyleSheets(newStyleSheets);
468 }
antti@apple.com0ffd7132015-09-30 15:39:15 +0000469}
470
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000471const Vector<RefPtr<CSSStyleSheet>> Scope::activeStyleSheetsForInspector()
antti@apple.comd8eeff62015-09-23 15:04:16 +0000472{
473 Vector<RefPtr<CSSStyleSheet>> result;
474
475 result.appendVector(m_document.extensionStyleSheets().injectedAuthorStyleSheets());
476 result.appendVector(m_document.extensionStyleSheets().authorStyleSheetsForTesting());
477
478 for (auto& styleSheet : m_styleSheetsForStyleSheetList) {
479 if (!is<CSSStyleSheet>(*styleSheet))
480 continue;
481
482 CSSStyleSheet& sheet = downcast<CSSStyleSheet>(*styleSheet);
483 if (sheet.disabled())
484 continue;
485
486 result.append(&sheet);
487 }
488
489 return result;
490}
491
antti@apple.com215ce402016-10-07 16:55:11 +0000492bool Scope::activeStyleSheetsContains(const CSSStyleSheet* sheet) const
antti@apple.comd8eeff62015-09-23 15:04:16 +0000493{
494 if (!m_weakCopyOfActiveStyleSheetListForFastLookup) {
495 m_weakCopyOfActiveStyleSheetListForFastLookup = std::make_unique<HashSet<const CSSStyleSheet*>>();
hs85.jeong@samsung.com22102292015-10-30 17:04:07 +0000496 for (auto& activeStyleSheet : m_activeStyleSheets)
497 m_weakCopyOfActiveStyleSheetListForFastLookup->add(activeStyleSheet.get());
antti@apple.comd8eeff62015-09-23 15:04:16 +0000498 }
499 return m_weakCopyOfActiveStyleSheetListForFastLookup->contains(sheet);
500}
501
antti@apple.com96c4e702016-10-22 21:27:53 +0000502void Scope::flushPendingSelfUpdate()
antti@apple.com0b6bc502016-09-24 12:28:48 +0000503{
antti@apple.com96c4e702016-10-22 21:27:53 +0000504 ASSERT(m_pendingUpdate);
505
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000506 auto updateType = *m_pendingUpdate;
antti@apple.com6a4f5902016-09-25 13:32:24 +0000507
508 clearPendingUpdate();
antti@apple.com6a4f5902016-09-25 13:32:24 +0000509 updateActiveStyleSheets(updateType);
antti@apple.com0b6bc502016-09-24 12:28:48 +0000510}
511
antti@apple.com96c4e702016-10-22 21:27:53 +0000512void Scope::flushPendingDescendantUpdates()
513{
514 ASSERT(m_hasDescendantWithPendingUpdate);
515 ASSERT(!m_shadowRoot);
516 for (auto* descendantShadowRoot : m_document.inDocumentShadowRoots())
517 descendantShadowRoot->styleScope().flushPendingUpdate();
518 m_hasDescendantWithPendingUpdate = false;
519}
520
antti@apple.com215ce402016-10-07 16:55:11 +0000521void Scope::clearPendingUpdate()
antti@apple.com0b6bc502016-09-24 12:28:48 +0000522{
antti@apple.com6a4f5902016-09-25 13:32:24 +0000523 m_pendingUpdateTimer.stop();
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000524 m_pendingUpdate = { };
antti@apple.com0b6bc502016-09-24 12:28:48 +0000525}
526
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000527void Scope::scheduleUpdate(UpdateType update)
antti@apple.com0b6bc502016-09-24 12:28:48 +0000528{
antti@apple.com96c4e702016-10-22 21:27:53 +0000529 if (!m_pendingUpdate || *m_pendingUpdate < update) {
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000530 m_pendingUpdate = update;
antti@apple.com96c4e702016-10-22 21:27:53 +0000531 if (m_shadowRoot)
532 m_document.styleScope().m_hasDescendantWithPendingUpdate = true;
533 }
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000534
antti@apple.com6a4f5902016-09-25 13:32:24 +0000535 if (m_pendingUpdateTimer.isActive())
antti@apple.com0b6bc502016-09-24 12:28:48 +0000536 return;
antti@apple.com6a4f5902016-09-25 13:32:24 +0000537 m_pendingUpdateTimer.startOneShot(0);
antti@apple.com0b6bc502016-09-24 12:28:48 +0000538}
539
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000540void Scope::didChangeActiveStyleSheetCandidates()
antti@apple.com0b6bc502016-09-24 12:28:48 +0000541{
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000542 scheduleUpdate(UpdateType::ActiveSet);
antti@apple.com6a4f5902016-09-25 13:32:24 +0000543}
544
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000545void Scope::didChangeStyleSheetContents()
antti@apple.com6a4f5902016-09-25 13:32:24 +0000546{
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000547 scheduleUpdate(UpdateType::ContentsOrInterpretation);
548}
549
550void Scope::didChangeStyleSheetEnvironment()
551{
552 if (!m_shadowRoot) {
553 for (auto* descendantShadowRoot : m_document.inDocumentShadowRoots()) {
554 // Stylesheets is author shadow roots are are potentially affected.
cdumez@apple.comdc3b6ad2016-10-27 20:23:06 +0000555 if (descendantShadowRoot->mode() != ShadowRootMode::UserAgent)
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000556 descendantShadowRoot->styleScope().scheduleUpdate(UpdateType::ContentsOrInterpretation);
557 }
558 }
559 scheduleUpdate(UpdateType::ContentsOrInterpretation);
antti@apple.com6a4f5902016-09-25 13:32:24 +0000560}
561
antti@apple.com215ce402016-10-07 16:55:11 +0000562void Scope::pendingUpdateTimerFired()
antti@apple.com6a4f5902016-09-25 13:32:24 +0000563{
564 flushPendingUpdate();
antti@apple.com0b6bc502016-09-24 12:28:48 +0000565}
566
antti@apple.com4f9ac5b2016-10-21 13:36:45 +0000567const Vector<RefPtr<StyleSheet>>& Scope::styleSheetsForStyleSheetList()
568{
569 // FIXME: StyleSheetList content should be updated separately from style resolver updates.
570 flushPendingUpdate();
571 return m_styleSheetsForStyleSheetList;
572}
573
antti@apple.comd8eeff62015-09-23 15:04:16 +0000574}
antti@apple.com215ce402016-10-07 16:55:11 +0000575}