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();
    }
Beispiel #2
0
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();
    }
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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));
}
Beispiel #11
0
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);
    }
}
Beispiel #13
0
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);
    }
}
Beispiel #15
0
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);
    }
}
Beispiel #16
0
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());
}
Beispiel #18
0
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());
}
Beispiel #19
0
    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));
}
Beispiel #22
0
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));
}
Beispiel #25
0
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));
}
Beispiel #26
0
void StyleSheetContents::parseStringAtPosition(
    const String& sheetText,
    const TextPosition& startPosition) {
    CSSParserContext context(parserContext(), UseCounter::getFrom(this));
    CSSParser::parseSheet(context, this, sheetText);
}