ContentSecurityPolicy.h [plain text]
#pragma once
#include "ContentSecurityPolicyResponseHeaders.h"
#include "SecurityOrigin.h"
#include "SecurityOriginHash.h"
#include <wtf/HashSet.h>
#include <wtf/OptionSet.h>
#include <wtf/Vector.h>
#include <wtf/text/TextPosition.h>
namespace JSC {
class ExecState;
}
namespace WTF {
class OrdinalNumber;
}
namespace WebCore {
class ContentSecurityPolicyDirective;
class ContentSecurityPolicyDirectiveList;
class ContentSecurityPolicySource;
class DOMStringList;
class Frame;
class JSDOMWindowShell;
class ResourceRequest;
class ScriptExecutionContext;
class SecurityOrigin;
class TextEncoding;
class URL;
enum class ContentSecurityPolicyHashAlgorithm;
typedef Vector<std::unique_ptr<ContentSecurityPolicyDirectiveList>> CSPDirectiveListVector;
typedef int SandboxFlags;
class ContentSecurityPolicy {
WTF_MAKE_FAST_ALLOCATED;
public:
explicit ContentSecurityPolicy(ScriptExecutionContext&);
explicit ContentSecurityPolicy(const SecurityOrigin&, const Frame* = nullptr);
~ContentSecurityPolicy();
void copyStateFrom(const ContentSecurityPolicy*);
void didCreateWindowShell(JSDOMWindowShell&) const;
enum class PolicyFrom {
HTTPEquivMeta,
HTTPHeader,
Inherited,
};
ContentSecurityPolicyResponseHeaders responseHeaders() const;
enum ReportParsingErrors { No, Yes };
void didReceiveHeaders(const ContentSecurityPolicyResponseHeaders&, ReportParsingErrors = ReportParsingErrors::Yes);
void processHTTPEquiv(const String& content, ContentSecurityPolicyHeaderType type) { didReceiveHeader(content, type, ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta); }
bool allowScriptWithNonce(const String& nonce, bool overrideContentSecurityPolicy = false) const;
bool allowStyleWithNonce(const String& nonce, bool overrideContentSecurityPolicy = false) const;
bool allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy = false) const;
bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy = false) const;
bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, const String& scriptContent, bool overrideContentSecurityPolicy = false) const;
bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, const String& styleContent, bool overrideContentSecurityPolicy = false) const;
bool allowEval(JSC::ExecState*, bool overrideContentSecurityPolicy = false) const;
bool allowPluginType(const String& type, const String& typeAttribute, const URL&, bool overrideContentSecurityPolicy = false) const;
bool allowFrameAncestors(const Frame&, const URL&, bool overrideContentSecurityPolicy = false) const;
enum class RedirectResponseReceived { No, Yes };
bool allowScriptFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowChildFrameFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowChildContextFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowImageFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowStyleFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowFontFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowMediaFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowConnectToSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowFormAction(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowObjectFromSource(const URL&, bool overrideContentSecurityPolicy = false, RedirectResponseReceived = RedirectResponseReceived::No) const;
bool allowBaseURI(const URL&, bool overrideContentSecurityPolicy = false) const;
void setOverrideAllowInlineStyle(bool);
void gatherReportURIs(DOMStringList&) const;
bool experimentalFeaturesEnabled() const;
void reportInvalidPluginTypes(const String&) const;
void reportDirectiveAsSourceExpression(const String& directiveName, const String& sourceExpression) const;
void reportInvalidPathCharacter(const String& directiveName, const String& value, const char) const;
void reportInvalidSourceExpression(const String& directiveName, const String& source) const;
bool urlMatchesSelf(const URL&) const;
bool allowContentSecurityPolicySourceStarToMatchAnyProtocol() const;
void reportDuplicateDirective(const String&) const;
void reportInvalidDirectiveValueCharacter(const String& directiveName, const String& value) const;
void reportInvalidSandboxFlags(const String&) const;
void reportInvalidDirectiveInReportOnlyMode(const String&) const;
void reportInvalidDirectiveInHTTPEquivMeta(const String&) const;
void reportMissingReportURI(const String&) const;
void reportUnsupportedDirective(const String&) const;
void enforceSandboxFlags(SandboxFlags sandboxFlags) { m_sandboxFlags |= sandboxFlags; }
void addHashAlgorithmsForInlineScripts(OptionSet<ContentSecurityPolicyHashAlgorithm> hashAlgorithmsForInlineScripts)
{
m_hashAlgorithmsForInlineScripts |= hashAlgorithmsForInlineScripts;
}
void addHashAlgorithmsForInlineStylesheets(OptionSet<ContentSecurityPolicyHashAlgorithm> hashAlgorithmsForInlineStylesheets)
{
m_hashAlgorithmsForInlineStylesheets |= hashAlgorithmsForInlineStylesheets;
}
bool protocolMatchesSelf(const URL&) const;
void setUpgradeInsecureRequests(bool);
bool upgradeInsecureRequests() const { return m_upgradeInsecureRequests; }
enum class InsecureRequestType { Load, FormSubmission, Navigation };
void upgradeInsecureRequestIfNeeded(ResourceRequest&, InsecureRequestType);
void upgradeInsecureRequestIfNeeded(URL&, InsecureRequestType);
HashSet<RefPtr<SecurityOrigin>>&& takeNavigationRequestsToUpgrade();
void inheritInsecureNavigationRequestsToUpgradeFromOpener(const ContentSecurityPolicy&);
void setInsecureNavigationRequestsToUpgrade(HashSet<RefPtr<SecurityOrigin>>&&);
private:
void logToConsole(const String& message, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), JSC::ExecState* = nullptr) const;
void updateSourceSelf(const SecurityOrigin&);
void applyPolicyToScriptExecutionContext();
void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicy::PolicyFrom);
const TextEncoding& documentEncoding() const;
template<typename Predicate, typename... Args> const ContentSecurityPolicyDirective* violatedDirectiveInAnyPolicy(Predicate&&, Args&&...) const WARN_UNUSED_RETURN;
template<typename Predicate> bool foundHashOfContentInAllPolicies(Predicate&&, const String& content, OptionSet<ContentSecurityPolicyHashAlgorithm>) const WARN_UNUSED_RETURN;
void reportViolation(const String& violatedDirective, const ContentSecurityPolicyDirective& effectiveViolatedDirective, const URL& blockedURL, const String& consoleMessage, JSC::ExecState*) const;
void reportViolation(const String& violatedDirective, const ContentSecurityPolicyDirective& effectiveViolatedDirective, const URL& blockedURL, const String& consoleMessage, const String& sourceURL, const TextPosition& sourcePosition, JSC::ExecState* = nullptr) const;
void reportBlockedScriptExecutionToInspector(const String& directiveText) const;
ScriptExecutionContext* m_scriptExecutionContext { nullptr };
const Frame* m_frame { nullptr };
std::unique_ptr<ContentSecurityPolicySource> m_selfSource;
String m_selfSourceProtocol;
CSPDirectiveListVector m_policies;
String m_lastPolicyEvalDisabledErrorMessage;
SandboxFlags m_sandboxFlags;
bool m_overrideInlineStyleAllowed { false };
bool m_isReportingEnabled { true };
bool m_upgradeInsecureRequests { false };
OptionSet<ContentSecurityPolicyHashAlgorithm> m_hashAlgorithmsForInlineScripts;
OptionSet<ContentSecurityPolicyHashAlgorithm> m_hashAlgorithmsForInlineStylesheets;
HashSet<RefPtr<SecurityOrigin>> m_insecureNavigationRequestsToUpgrade;
};
template<typename Predicate, typename... Args>
inline const ContentSecurityPolicyDirective* ContentSecurityPolicy::violatedDirectiveInAnyPolicy(Predicate&& predicate, Args&&... args) const
{
for (auto& policy : m_policies) {
if (const ContentSecurityPolicyDirective* violatedDirective = (policy.get()->*predicate)(std::forward<Args>(args)...))
return violatedDirective;
}
return nullptr;
}
}