diff options
Diffstat (limited to 'Source/WebCore/css/StyleSheetContents.cpp')
-rw-r--r-- | Source/WebCore/css/StyleSheetContents.cpp | 155 |
1 files changed, 81 insertions, 74 deletions
diff --git a/Source/WebCore/css/StyleSheetContents.cpp b/Source/WebCore/css/StyleSheetContents.cpp index cc3cec52a..ba00e2b21 100644 --- a/Source/WebCore/css/StyleSheetContents.cpp +++ b/Source/WebCore/css/StyleSheetContents.cpp @@ -26,12 +26,12 @@ #include "CSSStyleSheet.h" #include "CachedCSSStyleSheet.h" #include "Document.h" -#include "MemoryInstrumentation.h" #include "Node.h" #include "SecurityOrigin.h" #include "StylePropertySet.h" #include "StyleRule.h" #include "StyleRuleImport.h" +#include "WebCoreMemoryInstrumentation.h" #include <wtf/Deque.h> namespace WebCore { @@ -54,11 +54,9 @@ unsigned StyleSheetContents::estimatedSizeInBytes() const return size; } -StyleSheetContents::StyleSheetContents(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext& context) - : m_ownerRule(ownerRule) - , m_originalURL(originalURL) +StyleSheetContents::StyleSheetContents(const String& originalURL, const CSSParserContext& context) + : m_originalURL(originalURL) , m_loadCompleted(false) - , m_isUserStyleSheet(ownerRule && ownerRule->parentStyleSheet() && ownerRule->parentStyleSheet()->isUserStyleSheet()) , m_hasSyntacticallyValidCSSHeader(true) , m_didLoadErrorOccur(false) , m_usesRemUnits(false) @@ -70,7 +68,6 @@ StyleSheetContents::StyleSheetContents(StyleRuleImport* ownerRule, const String& StyleSheetContents::StyleSheetContents(const StyleSheetContents& o) : RefCounted<StyleSheetContents>() - , m_ownerRule(0) , m_originalURL(o.m_originalURL) , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule) , m_importRules(o.m_importRules.size()) @@ -104,9 +101,6 @@ bool StyleSheetContents::isCacheable() const // FIXME: Support copying import rules. if (!m_importRules.isEmpty()) return false; - // FIXME: Support cached stylesheets in import rules. - if (m_ownerRule) - return false; // This would require dealing with multiple clients for load callbacks. if (!m_loadCompleted) return false; @@ -129,8 +123,6 @@ void StyleSheetContents::parserAppendRule(PassRefPtr<StyleRuleBase> rule) // Parser enforces that @import rules come before anything else except @charset. ASSERT(m_childRules.isEmpty()); m_importRules.append(static_cast<StyleRuleImport*>(rule.get())); - m_importRules.last()->setParentStyleSheet(this); - m_importRules.last()->requestStyleSheet(); return; } m_childRules.append(rule); @@ -169,10 +161,6 @@ void StyleSheetContents::clearCharsetRule() void StyleSheetContents::clearRules() { - for (unsigned i = 0; i < m_importRules.size(); ++i) { - ASSERT(m_importRules.at(i)->parentStyleSheet() == this); - m_importRules[i]->clearParentStyleSheet(); - } m_importRules.clear(); m_childRules.clear(); clearCharsetRule(); @@ -207,9 +195,6 @@ bool StyleSheetContents::wrapperInsertRule(PassRefPtr<StyleRuleBase> rule, unsig if (!rule->isImportRule()) return false; m_importRules.insert(childVectorIndex, static_cast<StyleRuleImport*>(rule.get())); - m_importRules[childVectorIndex]->setParentStyleSheet(this); - m_importRules[childVectorIndex]->requestStyleSheet(); - // FIXME: Stylesheet doesn't actually change meaningfully before the imported sheets are loaded. return true; } // Inserting @import rule after a non-import rule is not allowed. @@ -235,7 +220,6 @@ void StyleSheetContents::wrapperDeleteRule(unsigned index) --childVectorIndex; } if (childVectorIndex < m_importRules.size()) { - m_importRules[childVectorIndex]->clearParentStyleSheet(); m_importRules.remove(childVectorIndex); return; } @@ -266,8 +250,22 @@ const AtomicString& StyleSheetContents::determineNamespace(const AtomicString& p return it->second; } -void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cachedStyleSheet, const SecurityOrigin* securityOrigin) +void StyleSheetContents::requestImportedStyleSheets(CSSStyleSheet* rootSheet) { + ASSERT(!rootSheet->parentStyleSheet()); + for (unsigned i = 0; i < m_importRules.size(); ++i) + m_importRules[i]->requestStyleSheet(rootSheet, parserContext()); +} + +void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cachedStyleSheet, CSSStyleSheet* rootSheet) +{ + if (cachedStyleSheet->errorOccurred()) { + m_didLoadErrorOccur = true; + return; + } + Document* ownerDocument = rootSheet->ownerDocument(); + if (!ownerDocument) + return; // Check to see if we should enforce the MIME type of the CSS resource in strict mode. // Running in iWeb 2 is one example of where we don't want to - <rdar://problem/6099748> bool enforceMIMEType = isStrictParserMode(m_parserContext.mode) && m_parserContext.enforcesCSSMIMETypeInNoQuirksMode; @@ -281,6 +279,7 @@ void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cached // to at least start with a syntactically valid CSS rule. // This prevents an attacker playing games by injecting CSS strings into HTML, XML, JSON, etc. etc. if (!hasValidMIMEType && !hasSyntacticallyValidCSSHeader()) { + const SecurityOrigin* securityOrigin = ownerDocument->securityOrigin(); bool isCrossOriginCSS = !securityOrigin || !securityOrigin->canRequest(baseURL()); if (isCrossOriginCSS) { clearRules(); @@ -289,14 +288,17 @@ void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cached } if (m_parserContext.needsSiteSpecificQuirks && isStrictParserMode(m_parserContext.mode)) { // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>. - DEFINE_STATIC_LOCAL(const String, slashKHTMLFixesDotCss, ("/KHTMLFixes.css")); - DEFINE_STATIC_LOCAL(const String, mediaWikiKHTMLFixesStyleSheet, ("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n")); + DEFINE_STATIC_LOCAL(const String, mediaWikiKHTMLFixesStyleSheet, (ASCIILiteral("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n"))); // There are two variants of KHTMLFixes.css. One is equal to mediaWikiKHTMLFixesStyleSheet, // while the other lacks the second trailing newline. - if (baseURL().string().endsWith(slashKHTMLFixesDotCss) && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText) - && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) + if (baseURL().string().endsWith("/KHTMLFixes.css") && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText) + && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) { clearRules(); + return; + } } + + requestImportedStyleSheets(rootSheet); } bool StyleSheetContents::parseString(const String& sheetText) @@ -309,6 +311,10 @@ bool StyleSheetContents::parseStringAtLine(const String& sheetText, int startLin CSSParser p(parserContext()); p.parseSheet(this, sheetText, startLineNumber); + if (!m_clients.isEmpty()) { + ASSERT(m_clients.size() == 1); + requestImportedStyleSheets(m_clients[0]); + } return true; } @@ -321,64 +327,70 @@ bool StyleSheetContents::isLoading() const return false; } -void StyleSheetContents::checkLoaded() +bool StyleSheetContents::checkImportedSheetLoadCompleted() { - if (isLoading()) - return; + for (unsigned i = 0; i < m_importRules.size(); ++i) { + StyleRuleImport* importRule = m_importRules[i].get(); + if (importRule->isLoading()) + return false; + if (importRule->styleSheet() && !importRule->styleSheet()->checkImportedSheetLoadCompleted()) + return false; + if (importRule->hadLoadError()) + m_didLoadErrorOccur = true; + } + m_loadCompleted = true; + return true; +} - // Avoid |this| being deleted by scripts that run via - // ScriptableDocumentParser::executeScriptsWaitingForStylesheets(). - // See <rdar://problem/6622300>. - RefPtr<StyleSheetContents> protector(this); - StyleSheetContents* parentSheet = parentStyleSheet(); - if (parentSheet) { - parentSheet->checkLoaded(); - m_loadCompleted = true; +void StyleSheetContents::checkLoadCompleted() +{ + if (m_clients.isEmpty()) return; - } - RefPtr<Node> ownerNode = singleOwnerNode(); - if (!ownerNode) { - m_loadCompleted = true; + if (!checkImportedSheetLoadCompleted()) return; - } + + RefPtr<StyleSheetContents> protect(this); + + ASSERT(hasOneClient()); + ASSERT(!m_clients[0]->parentStyleSheet()); + RefPtr<Node> ownerNode = m_clients[0]->ownerNode(); + if (!ownerNode) + return; + m_loadCompleted = ownerNode->sheetLoaded(); if (m_loadCompleted) ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoadErrorOccur); } -void StyleSheetContents::notifyLoadedSheet(const CachedCSSStyleSheet* sheet) -{ - ASSERT(sheet); - m_didLoadErrorOccur |= sheet->errorOccurred(); -} - -void StyleSheetContents::startLoadingDynamicSheet() -{ - if (Node* owner = singleOwnerNode()) - owner->startLoadingDynamicSheet(); -} - -StyleSheetContents* StyleSheetContents::rootStyleSheet() const +bool StyleSheetContents::getAncestors(const StyleRuleImport* importRule, Vector<const StyleSheetContents*>& result) const { - const StyleSheetContents* root = this; - while (root->parentStyleSheet()) - root = root->parentStyleSheet(); - return const_cast<StyleSheetContents*>(root); + result.append(this); + for (unsigned i = 0; i < m_importRules.size(); ++i) { + if (m_importRules[i] == importRule) + return true; + } + for (unsigned i = 0; i < m_importRules.size(); ++i) { + if (m_importRules[i]->styleSheet() && m_importRules[i]->styleSheet()->getAncestors(importRule, result)) + return true; + } + result.removeLast(); + return false; } -Node* StyleSheetContents::singleOwnerNode() const +bool StyleSheetContents::hasImportCycle(const StyleRuleImport* importRule, const KURL& importURL, const KURL& documentBaseURL) const { - StyleSheetContents* root = rootStyleSheet(); - if (root->m_clients.isEmpty()) - return 0; - ASSERT(root->m_clients.size() == 1); - return root->m_clients[0]->ownerNode(); -} + Vector<const StyleSheetContents*> ancestors; + getAncestors(importRule, ancestors); -Document* StyleSheetContents::singleOwnerDocument() const -{ - Node* ownerNode = singleOwnerNode(); - return ownerNode ? ownerNode->document() : 0; + KURL parentBaseURL = documentBaseURL; + for (unsigned i = 0; i < ancestors.size(); ++i) { + if (equalIgnoringFragmentIdentifier(importURL, ancestors[i]->baseURL())) + return true; + if (equalIgnoringFragmentIdentifier(importURL, KURL(parentBaseURL, ancestors[i]->originalURL()))) + return true; + parentBaseURL = ancestors[i]->baseURL(); + } + return false; } KURL StyleSheetContents::completeURL(const String& url) const @@ -451,11 +463,6 @@ bool StyleSheetContents::hasFailedOrCanceledSubresources() const return childRulesHaveFailedOrCanceledSubresources(m_childRules); } -StyleSheetContents* StyleSheetContents::parentStyleSheet() const -{ - return m_ownerRule ? m_ownerRule->parentStyleSheet() : 0; -} - void StyleSheetContents::registerClient(CSSStyleSheet* sheet) { ASSERT(!m_clients.contains(sheet)); @@ -485,7 +492,7 @@ void StyleSheetContents::removedFromMemoryCache() void StyleSheetContents::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { - MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS); + MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); info.addInstrumentedMember(m_originalURL); info.addInstrumentedMember(m_encodingFromCharsetRule); info.addVector(m_importRules); |