CSSParserContext.cpp   [plain text]


/*
 * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "CSSParserContext.h"

#include "Document.h"
#include "DocumentLoader.h"
#include "Page.h"
#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
#include <wtf/NeverDestroyed.h>

namespace WebCore {

const CSSParserContext& strictCSSParserContext()
{
    static NeverDestroyed<CSSParserContext> strictContext(HTMLStandardMode);
    return strictContext;
}

CSSParserContext::CSSParserContext(CSSParserMode mode, const URL& baseURL)
    : baseURL(baseURL)
    , mode(mode)
{
}

CSSParserContext::CSSParserContext(const Document& document, const URL& sheetBaseURL, const String& charset)
    : baseURL(sheetBaseURL.isNull() ? document.baseURL() : sheetBaseURL)
    , charset(charset)
    , mode(document.inQuirksMode() ? HTMLQuirksMode : HTMLStandardMode)
    , isHTMLDocument(document.isHTMLDocument())
    , hasDocumentSecurityOrigin(sheetBaseURL.isNull() || document.securityOrigin().canRequest(baseURL))
{
    enforcesCSSMIMETypeInNoQuirksMode = document.settings().enforceCSSMIMETypeInNoQuirksMode();
    useLegacyBackgroundSizeShorthandBehavior = document.settings().useLegacyBackgroundSizeShorthandBehavior();
#if ENABLE(TEXT_AUTOSIZING)
    textAutosizingEnabled = document.settings().textAutosizingEnabled();
#endif
#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
    legacyOverflowScrollingTouchEnabled = document.settings().legacyOverflowScrollingTouchEnabled();
    // The legacy -webkit-overflow-scrolling: touch behavior may have been disabled through the website policy,
    // in that case we want to disable the legacy behavior regardless of what the setting says.
    if (auto* loader = document.loader()) {
        if (loader->legacyOverflowScrollingTouchPolicy() == LegacyOverflowScrollingTouchPolicy::Disable)
            legacyOverflowScrollingTouchEnabled = false;
    }
#endif
    springTimingFunctionEnabled = document.settings().springTimingFunctionEnabled();
    constantPropertiesEnabled = document.settings().constantPropertiesEnabled();
    colorFilterEnabled = document.settings().colorFilterEnabled();
#if ENABLE(ATTACHMENT_ELEMENT)
    attachmentEnabled = RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled();
#endif
    deferredCSSParserEnabled = document.settings().deferredCSSParserEnabled();
    useSystemAppearance = document.page() ? document.page()->useSystemAppearance() : false;
}

bool operator==(const CSSParserContext& a, const CSSParserContext& b)
{
    return a.baseURL == b.baseURL
        && a.charset == b.charset
        && a.mode == b.mode
        && a.isHTMLDocument == b.isHTMLDocument
#if ENABLE(TEXT_AUTOSIZING)
        && a.textAutosizingEnabled == b.textAutosizingEnabled
#endif
#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
        && a.legacyOverflowScrollingTouchEnabled == b.legacyOverflowScrollingTouchEnabled
#endif
        && a.enforcesCSSMIMETypeInNoQuirksMode == b.enforcesCSSMIMETypeInNoQuirksMode
        && a.useLegacyBackgroundSizeShorthandBehavior == b.useLegacyBackgroundSizeShorthandBehavior
        && a.springTimingFunctionEnabled == b.springTimingFunctionEnabled
        && a.constantPropertiesEnabled == b.constantPropertiesEnabled
        && a.colorFilterEnabled == b.colorFilterEnabled
#if ENABLE(ATTACHMENT_ELEMENT)
        && a.attachmentEnabled == b.attachmentEnabled
#endif
        && a.deferredCSSParserEnabled == b.deferredCSSParserEnabled
        && a.hasDocumentSecurityOrigin == b.hasDocumentSecurityOrigin
        && a.useSystemAppearance == b.useSystemAppearance;
}

URL CSSParserContext::completeURL(const String& url) const
{
    auto completedURL = [&] {
        if (url.isNull())
            return URL();
        if (charset.isEmpty())
            return URL(baseURL, url);
        TextEncoding encoding(charset);
        auto& encodingForURLParsing = encoding.encodingForFormSubmissionOrURLParsing();
        return URL(baseURL, url, encodingForURLParsing == UTF8Encoding() ? nullptr : &encodingForURLParsing);
    }();

    if (mode == WebVTTMode && !completedURL.protocolIsData())
        return URL();

    return completedURL;
}

}