void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cachedStyleSheet, const SecurityOrigin* securityOrigin) { // 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; bool hasValidMIMEType = false; String sheetText = cachedStyleSheet->sheetText(enforceMIMEType, &hasValidMIMEType); CSSParser p(parserContext()); p.parseSheet(this, sheetText, 0); // If we're loading a stylesheet cross-origin, and the MIME type is not standard, require the CSS // 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()) { bool isCrossOriginCSS = !securityOrigin || !securityOrigin->canRequest(baseURL()); if (isCrossOriginCSS) { clearRules(); return; } } if (m_parserContext.needsSiteSpecificQuirks && isStrictParserMode(m_parserContext.mode)) { // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>. 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("/KHTMLFixes.css") && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText) && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) clearRules(); }
void ProcessingInstruction::setCSSStyleSheet( const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* sheet) { if (!isConnected()) { DCHECK(!m_sheet); return; } DCHECK(m_isCSS); CSSParserContext parserContext(document(), nullptr, baseURL, charset); StyleSheetContents* newSheet = StyleSheetContents::create(href, parserContext); CSSStyleSheet* cssSheet = CSSStyleSheet::create(newSheet, *this); cssSheet->setDisabled(m_alternate); cssSheet->setTitle(m_title); if (!m_alternate && !m_title.isEmpty()) document().styleEngine().setPreferredStylesheetSetNameIfNotSet( m_title, StyleEngine::DontUpdateActiveSheets); cssSheet->setMediaQueries(MediaQuerySet::create(m_media)); m_sheet = cssSheet; // We don't need the cross-origin security check here because we are // getting the sheet text in "strict" mode. This enforces a valid CSS MIME // type. parseStyleSheet(sheet->sheetText()); }
unsigned CSSGroupingRule::insertRule(const String& ruleString, unsigned index, ExceptionState& exceptionState) { ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); if (index > m_groupRule->childRules().size()) { exceptionState.throwDOMException(IndexSizeError, "the index " + String::number(index) + " must be less than or equal to the length of the rule list."); return 0; } CSSStyleSheet* styleSheet = parentStyleSheet(); CSSParserContext context(parserContext(), UseCounter::getFrom(styleSheet)); BisonCSSParser parser(context); RefPtrWillBeRawPtr<StyleRuleBase> newRule = parser.parseRule(styleSheet ? styleSheet->contents() : 0, ruleString); if (!newRule) { exceptionState.throwDOMException(SyntaxError, "the rule '" + ruleString + "' is invalid and cannot be parsed."); return 0; } if (newRule->isImportRule()) { // FIXME: an HierarchyRequestError should also be thrown for a @charset or a nested // @media rule. They are currently not getting parsed, resulting in a SyntaxError // to get raised above. exceptionState.throwDOMException(HierarchyRequestError, "'@import' rules cannot be inserted inside a group rule."); return 0; } CSSStyleSheet::RuleMutationScope mutationScope(this); m_groupRule->wrapperInsertRule(index, newRule); m_childRuleCSSOMWrappers.insert(index, RefPtrWillBeMember<CSSRule>(nullptr)); return index; }
bool StyleSheetContents::parseStringAtPosition(const String& sheetText, const TextPosition& startPosition, bool createdByParser) { CSSParserContext context(parserContext(), UseCounter::getFrom(this)); CSSParser::parseSheet(context, this, sheetText, startPosition, 0, createdByParser); return true; }
void StyleSheetContents::parseAuthorStyleSheet(const CSSStyleSheetResource* cachedStyleSheet, const SecurityOrigin* securityOrigin) { TRACE_EVENT0("webkit", "StyleSheetContents::parseAuthorStyleSheet"); bool quirksMode = isQuirksModeBehavior(m_parserContext.mode()); bool enforceMIMEType = !quirksMode; bool hasValidMIMEType = false; String sheetText = cachedStyleSheet->sheetText(enforceMIMEType, &hasValidMIMEType); CSSParserContext context(parserContext(), UseCounter::getFrom(this)); BisonCSSParser p(context); p.parseSheet(this, sheetText, TextPosition::minimumPosition(), 0, true); // If we're loading a stylesheet cross-origin, and the MIME type is not standard, require the CSS // 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()) { bool isCrossOriginCSS = !securityOrigin || !securityOrigin->canRequest(baseURL()); if (isCrossOriginCSS) { clearRules(); return; } } }
void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cachedStyleSheet) { bool hasValidMIMEType = true; String sheetText = cachedStyleSheet->sheetText(&hasValidMIMEType); if (!hasValidMIMEType) { ASSERT(sheetText.isNull()); if (auto* document = singleOwnerDocument()) { if (auto* page = document->page()) page->console().addMessage(MessageSource::Security, MessageLevel::Error, "Did not parse stylesheet at '" + cachedStyleSheet->url().stringCenterEllipsizedToLength() + "' because its MIME type was invalid."); } return; } CSSParser p(parserContext()); p.parseSheet(this, sheetText, TextPosition(), nullptr, true); if (m_parserContext.needsSiteSpecificQuirks && isStrictParserMode(m_parserContext.mode)) { // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>. DEPRECATED_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("/KHTMLFixes.css") && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText) && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) clearRules(); }
unsigned CSSGroupingRule::insertRule(const String& ruleString, unsigned index, ExceptionState& exceptionState) { ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); if (index > m_groupRule->childRules().size()) { exceptionState.throwDOMException(IndexSizeError, "the index " + String::number(index) + " must be less than or equal to the length of the rule list."); return 0; } CSSStyleSheet* styleSheet = parentStyleSheet(); CSSParserContext context(parserContext(), UseCounter::getFrom(styleSheet)); BisonCSSParser parser(context); RefPtrWillBeRawPtr<StyleRuleBase> newRule = parser.parseRule(styleSheet ? styleSheet->contents() : 0, ruleString); if (!newRule) { exceptionState.throwDOMException(SyntaxError, "the rule '" + ruleString + "' is invalid and cannot be parsed."); return 0; } CSSStyleSheet::RuleMutationScope mutationScope(this); m_groupRule->wrapperInsertRule(index, newRule); m_childRuleCSSOMWrappers.insert(index, RefPtrWillBeMember<CSSRule>(nullptr)); return index; }
ExceptionOr<unsigned> CSSGroupingRule::insertRule(const String& ruleString, unsigned index) { ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); if (index > m_groupRule->childRules().size()) { // INDEX_SIZE_ERR: Raised if the specified index is not a valid insertion point. return Exception { INDEX_SIZE_ERR }; } CSSParser parser(parserContext()); CSSStyleSheet* styleSheet = parentStyleSheet(); RefPtr<StyleRuleBase> newRule = parser.parseRule(styleSheet ? &styleSheet->contents() : nullptr, ruleString); if (!newRule) { // SYNTAX_ERR: Raised if the specified rule has a syntax error and is unparsable. return Exception { SYNTAX_ERR }; } if (newRule->isImportRule()) { // FIXME: an HIERARCHY_REQUEST_ERR should also be thrown for a @charset or a nested // @media rule. They are currently not getting parsed, resulting in a SYNTAX_ERR // to get raised above. // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified // index, e.g., if an @import rule is inserted after a standard rule set or other // at-rule. return Exception { HIERARCHY_REQUEST_ERR }; } CSSStyleSheet::RuleMutationScope mutationScope(this); m_groupRule->wrapperInsertRule(index, newRule.releaseNonNull()); m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>()); return index; }
CSSStyleSheet* CSSStyleSheet::createInline(Node& ownerNode, const KURL& baseURL, const TextPosition& startPosition, const String& encoding) { CSSParserContext parserContext(ownerNode.document(), nullptr, baseURL, encoding); StyleSheetContents* sheet = StyleSheetContents::create(baseURL.getString(), parserContext); return new CSSStyleSheet(sheet, ownerNode, true, startPosition); }
void CSSPageRule::setSelectorText(const String& selectorText) { CSSParserContext context(parserContext(), nullptr); CSSSelectorList selectorList = CSSParser::parsePageSelector(context, parentStyleSheet() ? parentStyleSheet()->contents() : nullptr, selectorText); if (!selectorList.isValid()) return; CSSStyleSheet::RuleMutationScope mutationScope(this); m_pageRule->wrapperAdoptSelectorList(std::move(selectorList)); }
void CSSPageRule::setSelectorText(const String& selectorText) { CSSParser parser(parserContext()); CSSSelectorList selectorList; parser.parseSelector(selectorText, selectorList); if (!selectorList.first()) return; CSSStyleSheet::RuleMutationScope mutationScope(this); String oldSelectorText = this->selectorText(); m_pageRule->wrapperAdoptSelectorList(selectorList); }
void CSSStyleRule::setSelectorText(const String& selectorText) { CSSParserContext context(parserContext(), 0); CSSSelectorList selectorList = CSSParser::parseSelector(context, parentStyleSheet() ? parentStyleSheet()->contents() : nullptr, selectorText); if (!selectorList.isValid()) return; CSSStyleSheet::RuleMutationScope mutationScope(this); m_styleRule->wrapperAdoptSelectorList(std::move(selectorList)); if (hasCachedSelectorText()) { selectorTextCache().remove(this); setHasCachedSelectorText(false); } }
void CSSKeyframesRule::insertRule(const String& ruleText) { ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size()); CSSStyleSheet* styleSheet = parentStyleSheet(); BisonCSSParser parser(parserContext(), UseCounter::getFrom(styleSheet)); RefPtr<StyleKeyframe> keyframe = parser.parseKeyframeRule(styleSheet ? styleSheet->contents() : 0, ruleText); if (!keyframe) return; CSSStyleSheet::RuleMutationScope mutationScope(this); m_keyframesRule->wrapperAppendKeyframe(keyframe); m_childRuleCSSOMWrappers.grow(length()); }
void CSSStyleRule::setSelectorText(const String& selectorText) { CSSParser p(parserContext()); CSSSelectorList selectorList; p.parseSelector(selectorText, selectorList); if (!selectorList.isValid()) return; CSSStyleSheet::RuleMutationScope mutationScope(this); m_styleRule->wrapperAdoptSelectorList(selectorList); if (hasCachedSelectorText()) { selectorTextCache().remove(this); setHasCachedSelectorText(false); } }
void CSSStyleRule::setSelectorText(const String& selectorText) { CSSParser p(parserContext()); CSSSelectorList selectorList; p.parseSelector(selectorText, selectorList); if (!selectorList.isValid()) return; // NOTE: The selector list has to fit into RuleData. <http://webkit.org/b/118369> if (selectorList.componentCount() > RuleData::maximumSelectorComponentCount) return; CSSStyleSheet::RuleMutationScope mutationScope(this); m_styleRule->wrapperAdoptSelectorList(selectorList); if (hasCachedSelectorText()) { selectorTextCache().remove(this); setHasCachedSelectorText(false); } }
unsigned CSSMediaRule::insertRule(const String& ruleString, unsigned index, ExceptionCode& ec) { ASSERT(m_childRuleCSSOMWrappers.size() == m_mediaRule->childRules().size()); if (index > m_mediaRule->childRules().size()) { // INDEX_SIZE_ERR: Raised if the specified index is not a valid insertion point. ec = INDEX_SIZE_ERR; return 0; } CSSParser parser(parserContext()); CSSStyleSheet* styleSheet = parentStyleSheet(); RefPtr<StyleRuleBase> newRule = parser.parseRule(styleSheet ? styleSheet->internal() : 0, ruleString); if (!newRule) { // SYNTAX_ERR: Raised if the specified rule has a syntax error and is unparsable. ec = SYNTAX_ERR; return 0; } if (newRule->isImportRule()) { // FIXME: an HIERARCHY_REQUEST_ERR should also be thrown for a @charset or a nested // @media rule. They are currently not getting parsed, resulting in a SYNTAX_ERR // to get raised above. // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified // index, e.g., if an @import rule is inserted after a standard rule set or other // at-rule. ec = HIERARCHY_REQUEST_ERR; return 0; } m_mediaRule->wrapperInsertRule(index, newRule); m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>()); if (CSSStyleSheet* styleSheet = parentStyleSheet()) styleSheet->styleSheetChanged(); return index; }
void ProcessingInstruction::setCSSStyleSheet(const String& href, const URL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet) { if (!inDocument()) { ASSERT(!m_sheet); return; } ASSERT(m_isCSS); CSSParserContext parserContext(document(), baseURL, charset); auto cssSheet = CSSStyleSheet::create(StyleSheetContents::create(href, parserContext), *this); cssSheet.get().setDisabled(m_alternate); cssSheet.get().setTitle(m_title); cssSheet.get().setMediaQueries(MediaQuerySet::create(m_media)); m_sheet = WTFMove(cssSheet); // We don't need the cross-origin security check here because we are // getting the sheet text in "strict" mode. This enforces a valid CSS MIME // type. parseStyleSheet(sheet->sheetText()); }
void StyleSheetContents::parseAuthorStyleSheet( const CSSStyleSheetResource* cachedStyleSheet, const SecurityOrigin* securityOrigin) { TRACE_EVENT1("blink,devtools.timeline", "ParseAuthorStyleSheet", "data", InspectorParseAuthorStyleSheetEvent::data(cachedStyleSheet)); SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Style.AuthorStyleSheet.ParseTime"); bool isSameOriginRequest = securityOrigin && securityOrigin->canRequest(baseURL()); // When the response was fetched via the Service Worker, the original URL may // not be same as the base URL. // TODO(horo): When we will use the original URL as the base URL, we can // remove this check. crbug.com/553535 if (cachedStyleSheet->response().wasFetchedViaServiceWorker()) { const KURL originalURL( cachedStyleSheet->response().originalURLViaServiceWorker()); // |originalURL| is empty when the response is created in the SW. if (!originalURL.isEmpty() && !securityOrigin->canRequest(originalURL)) isSameOriginRequest = false; } CSSStyleSheetResource::MIMETypeCheck mimeTypeCheck = isQuirksModeBehavior(m_parserContext.mode()) && isSameOriginRequest ? CSSStyleSheetResource::MIMETypeCheck::Lax : CSSStyleSheetResource::MIMETypeCheck::Strict; String sheetText = cachedStyleSheet->sheetText(mimeTypeCheck); const ResourceResponse& response = cachedStyleSheet->response(); m_sourceMapURL = response.httpHeaderField(HTTPNames::SourceMap); if (m_sourceMapURL.isEmpty()) { // Try to get deprecated header. m_sourceMapURL = response.httpHeaderField(HTTPNames::X_SourceMap); } CSSParserContext context(parserContext(), UseCounter::getFrom(this)); CSSParser::parseSheet(context, this, sheetText, RuntimeEnabledFeatures::lazyParseCSSEnabled()); }
bool Template::TryParseInternal(std::string& source, ParserError& error) { // Tokenize the source TokenList tokens; if (!Lexer::TryAnalyze(source, tokens, error)) return false; // Construct a parsing context ParserContext parserContext(tokens, this->_strainer, error); // Start building the AST if (!this->_root.TryParse(parserContext)) return false; // Yay! return true; }
void ProcessingInstruction::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* sheet) { if (!inDocument()) { ASSERT(!m_sheet); return; } ASSERT(m_isCSS); CSSParserContext parserContext(document(), 0, baseURL, charset); RefPtrWillBeRawPtr<StyleSheetContents> newSheet = StyleSheetContents::create(href, parserContext); RefPtrWillBeRawPtr<CSSStyleSheet> cssSheet = CSSStyleSheet::create(newSheet, this); cssSheet->setDisabled(m_alternate); cssSheet->setTitle(m_title); cssSheet->setMediaQueries(MediaQuerySet::create(m_media)); m_sheet = cssSheet.release(); // We don't need the cross-origin security check here because we are // getting the sheet text in "strict" mode. This enforces a valid CSS MIME // type. parseStyleSheet(sheet->sheetText()); }
PassRefPtr<CSSStyleSheet> CSSStyleSheet::createInline(Node* ownerNode, const KURL& baseURL, const String& encoding) { CSSParserContext parserContext(ownerNode->document(), baseURL, encoding); RefPtr<StyleSheetContents> sheet = StyleSheetContents::create(baseURL.string(), parserContext); return adoptRef(new CSSStyleSheet(sheet.release(), ownerNode, true)); }
Ref<CSSStyleSheet> CSSStyleSheet::createInline(Node& ownerNode, const URL& baseURL, const TextPosition& startPosition, const String& encoding) { CSSParserContext parserContext(ownerNode.document(), baseURL, encoding); return adoptRef(*new CSSStyleSheet(StyleSheetContents::create(baseURL.string(), parserContext), &ownerNode, startPosition, true)); }
void StyleSheetContents::requestImportedStyleSheets(CSSStyleSheet* rootSheet) { ASSERT(!rootSheet->parentStyleSheet()); for (unsigned i = 0; i < m_importRules.size(); ++i) m_importRules[i]->requestStyleSheet(rootSheet, parserContext()); }
PassRefPtrWillBeRawPtr<CSSStyleSheet> CSSStyleSheet::createInline(Node* ownerNode, const KURL& baseURL, const TextPosition& startPosition, const String& encoding) { CSSParserContext parserContext(ownerNode->document(), 0, baseURL, encoding); RefPtrWillBeRawPtr<StyleSheetContents> sheet = StyleSheetContents::create(baseURL.string(), parserContext); return adoptRefWillBeNoop(new CSSStyleSheet(sheet.release(), ownerNode, true, startPosition)); }
PassRefPtr<CSSStyleSheet> CSSStyleSheet::create(Node* ownerNode, const KURL& baseURL) { CSSParserContext parserContext(ownerNode->document(), 0, baseURL); RefPtr<StyleSheetContents> sheet = StyleSheetContents::create(&ownerNode->document(), parserContext); return adoptRef(new CSSStyleSheet(sheet.release(), ownerNode)); }
void StyleSheetContents::parseStringAtPosition( const String& sheetText, const TextPosition& startPosition) { CSSParserContext context(parserContext(), UseCounter::getFrom(this)); CSSParser::parseSheet(context, this, sheetText); }