blob: f5455a880ed629f60d9d23d28126a44d59027a5a [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/loader/HttpEquiv.h"
#include "core/dom/Document.h"
#include "core/dom/ScriptableDocumentParser.h"
#include "core/dom/StyleEngine.h"
#include "core/fetch/ClientHintsPreferences.h"
#include "core/frame/UseCounter.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/loader/DocumentLoader.h"
#include "core/origin_trials/OriginTrialContext.h"
#include "platform/HTTPNames.h"
#include "platform/network/HTTPParsers.h"
#include "platform/weborigin/KURL.h"
namespace blink {
void HttpEquiv::process(Document& document,
const AtomicString& equiv,
const AtomicString& content,
bool inDocumentHeadElement) {
DCHECK(!equiv.isNull());
DCHECK(!content.isNull());
if (equalIgnoringCase(equiv, "default-style")) {
processHttpEquivDefaultStyle(document, content);
} else if (equalIgnoringCase(equiv, "refresh")) {
processHttpEquivRefresh(document, content);
} else if (equalIgnoringCase(equiv, "set-cookie")) {
processHttpEquivSetCookie(document, content);
} else if (equalIgnoringCase(equiv, "content-language")) {
document.setContentLanguage(content);
} else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) {
document.parseDNSPrefetchControlHeader(content);
} else if (equalIgnoringCase(equiv, "x-frame-options")) {
document.addConsoleMessage(ConsoleMessage::create(
SecurityMessageSource, ErrorMessageLevel,
"X-Frame-Options may only be set via an HTTP header sent along with a "
"document. It may not be set inside <meta>."));
} else if (equalIgnoringCase(equiv, "accept-ch")) {
processHttpEquivAcceptCH(document, content);
} else if (equalIgnoringCase(equiv, "content-security-policy") ||
equalIgnoringCase(equiv, "content-security-policy-report-only")) {
if (inDocumentHeadElement)
processHttpEquivContentSecurityPolicy(document, equiv, content);
else
document.contentSecurityPolicy()->reportMetaOutsideHead(content);
} else if (equalIgnoringCase(equiv, "suborigin")) {
document.addConsoleMessage(ConsoleMessage::create(
SecurityMessageSource, ErrorMessageLevel,
"Error with Suborigin header: Suborigin header with value '" + content +
"' was delivered via a <meta> element and not an HTTP header, "
"which is disallowed. The Suborigin has been ignored."));
} else if (equalIgnoringCase(equiv, HTTPNames::Origin_Trial)) {
if (inDocumentHeadElement)
OriginTrialContext::from(&document)->addToken(content);
}
}
void HttpEquiv::processHttpEquivContentSecurityPolicy(
Document& document,
const AtomicString& equiv,
const AtomicString& content) {
if (document.importLoader())
return;
if (equalIgnoringCase(equiv, "content-security-policy"))
document.contentSecurityPolicy()->didReceiveHeader(
content, ContentSecurityPolicyHeaderTypeEnforce,
ContentSecurityPolicyHeaderSourceMeta);
else if (equalIgnoringCase(equiv, "content-security-policy-report-only"))
document.contentSecurityPolicy()->didReceiveHeader(
content, ContentSecurityPolicyHeaderTypeReport,
ContentSecurityPolicyHeaderSourceMeta);
else
NOTREACHED();
}
void HttpEquiv::processHttpEquivAcceptCH(Document& document,
const AtomicString& content) {
if (!document.frame())
return;
UseCounter::count(document, UseCounter::ClientHintsMetaAcceptCH);
document.clientHintsPreferences().updateFromAcceptClientHintsHeader(
content, document.fetcher());
}
void HttpEquiv::processHttpEquivDefaultStyle(Document& document,
const AtomicString& content) {
document.styleEngine().setHttpDefaultStyle(content);
}
void HttpEquiv::processHttpEquivRefresh(Document& document,
const AtomicString& content) {
UseCounter::count(document, UseCounter::MetaRefresh);
if (!document.contentSecurityPolicy()->allowInlineScript(
KURL(), "", OrdinalNumber(), "",
ContentSecurityPolicy::SuppressReport))
UseCounter::count(document,
UseCounter::MetaRefreshWhenCSPBlocksInlineScript);
document.maybeHandleHttpRefresh(content, Document::HttpRefreshFromMetaTag);
}
void HttpEquiv::processHttpEquivSetCookie(Document& document,
const AtomicString& content) {
// FIXME: make setCookie work on XML documents too; e.g. in case of
// <html:meta.....>
if (!document.isHTMLDocument())
return;
UseCounter::count(document, UseCounter::MetaSetCookie);
if (!document.contentSecurityPolicy()->allowInlineScript(
KURL(), "", OrdinalNumber(), "",
ContentSecurityPolicy::SuppressReport))
UseCounter::count(document,
UseCounter::MetaSetCookieWhenCSPBlocksInlineScript);
// Exception (for sandboxed documents) ignored.
document.setCookie(content, IGNORE_EXCEPTION);
}
} // namespace blink