Chromium Code Reviews| Index: third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| index 86a6de795f9fbe57a540ea225dbbf16344474856..058402eeb43072087080f609b40fbd6f1881c566 100644 |
| --- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| +++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| @@ -311,6 +311,48 @@ void ContentSecurityPolicy::didReceiveHeader( |
| applyPolicySideEffectsToExecutionContext(); |
| } |
| +bool ContentSecurityPolicy::checkAllowBlanketEnforcement( |
|
amalika
2016/10/11 19:06:46
This is the most important function.
After I ran
|
| + const ResourceResponse& response, |
| + const KURL& parentUrl) { |
| + if (response.url().isEmpty() || response.url().protocolIsAbout() || |
| + response.url().protocolIsAbout() || response.url().protocolIs("blob") || |
| + response.url().protocolIs("filesystem")) { |
| + return true; |
| + } |
| + |
| + if (parentUrl.protocol() == response.url().protocol() && |
| + parentUrl.host() == response.url().host() && |
| + parentUrl.port() == response.url().port()) { |
| + return true; |
| + } |
| + |
| + HTTPHeaderMap::const_iterator it = |
| + response.httpHeaderFields().find(HTTPNames::Allow_CSP_From); |
| + |
| + String header = |
| + it != response.httpHeaderFields().end() ? it->value : nullAtom; |
| + |
| + if (header.isEmpty() || !header.containsOnlyASCII()) |
| + return false; |
| + |
| + Vector<String> headers; |
| + header.split(',', headers); |
| + for (size_t i = 0; i < headers.size(); i++) { |
| + String currentHeader = headers[i].stripWhiteSpace(); |
| + if (equalIgnoringCase(currentHeader, "*")) { |
| + return true; |
| + } |
| + const KURL allowed(ParsedURLString, currentHeader); |
| + if (allowed.isValid() && parentUrl.protocol() == allowed.protocol() && |
| + parentUrl.host() == allowed.host() && |
| + parentUrl.port() == allowed.port()) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| +} |
| + |
| void ContentSecurityPolicy::addPolicyFromHeaderValue( |
| const String& header, |
| ContentSecurityPolicyHeaderType type, |
| @@ -357,1146 +399,1176 @@ void ContentSecurityPolicy::addPolicyFromHeaderValue( |
| skipExactly<UChar>(position, end, ','); |
| begin = position; |
| } |
| -} |
| - |
| -void ContentSecurityPolicy::reportAccumulatedHeaders( |
| - FrameLoaderClient* client) const { |
| - // Notify the embedder about headers that have accumulated before the |
| - // navigation got committed. See comments in |
| - // addAndReportPolicyFromHeaderValue for more details and context. |
| - DCHECK(client); |
| - for (const auto& policy : m_policies) { |
| - client->didAddContentSecurityPolicy(policy->header(), policy->headerType(), |
| - policy->headerSource()); |
| } |
| -} |
| -void ContentSecurityPolicy::addAndReportPolicyFromHeaderValue( |
| - const String& header, |
| - ContentSecurityPolicyHeaderType type, |
| - ContentSecurityPolicyHeaderSource source) { |
| - // Notify about the new header, so that it can be reported back to the |
| - // browser process. This is needed in order to: |
| - // 1) replicate CSP directives (i.e. frame-src) to OOPIFs (only for now / |
| - // short-term). |
| - // 2) enforce CSP in the browser process (not yet / long-term - see |
| - // https://crbug.com/376522). |
| - if (document() && document()->frame()) |
| - document()->frame()->client()->didAddContentSecurityPolicy(header, type, |
| - source); |
| - |
| - addPolicyFromHeaderValue(header, type, source); |
| -} |
| + void ContentSecurityPolicy::reportAccumulatedHeaders( |
| + FrameLoaderClient* client) const { |
| + // Notify the embedder about headers that have accumulated before the |
| + // navigation got committed. See comments in |
| + // addAndReportPolicyFromHeaderValue for more details and context. |
| + DCHECK(client); |
| + for (const auto& policy : m_policies) { |
| + client->didAddContentSecurityPolicy( |
| + policy->header(), policy->headerType(), policy->headerSource()); |
| + } |
| + } |
| -void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) { |
| - m_overrideInlineStyleAllowed = value; |
| -} |
| + void ContentSecurityPolicy::addAndReportPolicyFromHeaderValue( |
| + const String& header, |
| + ContentSecurityPolicyHeaderType type, |
| + ContentSecurityPolicyHeaderSource source) { |
| + // Notify about the new header, so that it can be reported back to the |
| + // browser process. This is needed in order to: |
| + // 1) replicate CSP directives (i.e. frame-src) to OOPIFs (only for now / |
| + // short-term). |
| + // 2) enforce CSP in the browser process (not yet / long-term - see |
| + // https://crbug.com/376522). |
| + if (document() && document()->frame()) { |
| + document()->frame()->client()->didAddContentSecurityPolicy(header, type, |
| + source); |
| + } |
| -void ContentSecurityPolicy::setOverrideURLForSelf(const KURL& url) { |
| - // Create a temporary CSPSource so that 'self' expressions can be resolved |
| - // before we bind to an execution context (for 'frame-ancestor' resolution, |
| - // for example). This CSPSource will be overwritten when we bind this object |
| - // to an execution context. |
| - RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url); |
| - m_selfProtocol = origin->protocol(); |
| - m_selfSource = |
| - new CSPSource(this, m_selfProtocol, origin->host(), origin->port(), |
| - String(), CSPSource::NoWildcard, CSPSource::NoWildcard); |
| -} |
| + addPolicyFromHeaderValue(header, type, source); |
| + } |
| -std::unique_ptr<Vector<CSPHeaderAndType>> ContentSecurityPolicy::headers() |
| - const { |
| - std::unique_ptr<Vector<CSPHeaderAndType>> headers = |
| - wrapUnique(new Vector<CSPHeaderAndType>); |
| - for (const auto& policy : m_policies) { |
| - CSPHeaderAndType headerAndType(policy->header(), policy->headerType()); |
| - headers->append(headerAndType); |
| + void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) { |
| + m_overrideInlineStyleAllowed = value; |
| } |
| - return headers; |
| -} |
| -template <bool (CSPDirectiveList::*allowed)( |
| - ContentSecurityPolicy::ReportingStatus) const> |
| -bool isAllowedByAll(const CSPDirectiveListVector& policies, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= (policy.get()->*allowed)(reportingStatus); |
| - return isAllowed; |
| -} |
| + void ContentSecurityPolicy::setOverrideURLForSelf(const KURL& url) { |
| + // Create a temporary CSPSource so that 'self' expressions can be resolved |
| + // before we bind to an execution context (for 'frame-ancestor' resolution, |
| + // for example). This CSPSource will be overwritten when we bind this object |
| + // to an execution context. |
| + RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url); |
| + m_selfProtocol = origin->protocol(); |
| + m_selfSource = |
| + new CSPSource(this, m_selfProtocol, origin->host(), origin->port(), |
| + String(), CSPSource::NoWildcard, CSPSource::NoWildcard); |
| + } |
| -template <bool (CSPDirectiveList::*allowed)( |
| - ScriptState* scriptState, |
| - ContentSecurityPolicy::ReportingStatus, |
| - ContentSecurityPolicy::ExceptionStatus) const> |
| -bool isAllowedByAllWithStateAndExceptionStatus( |
| - const CSPDirectiveListVector& policies, |
| - ScriptState* scriptState, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus, |
| - ContentSecurityPolicy::ExceptionStatus exceptionStatus) { |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= |
| - (policy.get()->*allowed)(scriptState, reportingStatus, exceptionStatus); |
| - return isAllowed; |
| -} |
| + std::unique_ptr<Vector<CSPHeaderAndType>> ContentSecurityPolicy::headers() |
| + const { |
| + std::unique_ptr<Vector<CSPHeaderAndType>> headers = |
| + wrapUnique(new Vector<CSPHeaderAndType>); |
| + for (const auto& policy : m_policies) { |
| + CSPHeaderAndType headerAndType(policy->header(), policy->headerType()); |
| + headers->append(headerAndType); |
| + } |
| + return headers; |
| + } |
| -template <bool (CSPDirectiveList::*allowed)( |
| - const String&, |
| - const WTF::OrdinalNumber&, |
| - ContentSecurityPolicy::ReportingStatus) const> |
| -bool isAllowedByAllWithContext( |
| - const CSPDirectiveListVector& policies, |
| - const String& contextURL, |
| - const WTF::OrdinalNumber& contextLine, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= |
| - (policy.get()->*allowed)(contextURL, contextLine, reportingStatus); |
| - return isAllowed; |
| -} |
| + template <bool (CSPDirectiveList::*allowed)( |
| + ContentSecurityPolicy::ReportingStatus) const> |
| + bool isAllowedByAll(const CSPDirectiveListVector& policies, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) |
| + isAllowed &= (policy.get()->*allowed)(reportingStatus); |
| + return isAllowed; |
| + } |
| -template < |
| - bool (CSPDirectiveList::*allowed)(const String&, |
| - const String&, |
| - const WTF::OrdinalNumber&, |
| - ContentSecurityPolicy::ReportingStatus, |
| - const String& content) const> |
| -bool isAllowedByAllWithContextAndContent( |
| - const CSPDirectiveListVector& policies, |
| - const String& contextURL, |
| - const String& nonce, |
| - const WTF::OrdinalNumber& contextLine, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus, |
| - const String& content) { |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= (policy.get()->*allowed)(contextURL, nonce, contextLine, |
| - reportingStatus, content); |
| - return isAllowed; |
| -} |
| + template <bool (CSPDirectiveList::*allowed)( |
| + ScriptState* scriptState, |
| + ContentSecurityPolicy::ReportingStatus, |
| + ContentSecurityPolicy::ExceptionStatus) const> |
| + bool isAllowedByAllWithStateAndExceptionStatus( |
| + const CSPDirectiveListVector& policies, |
| + ScriptState* scriptState, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus, |
| + ContentSecurityPolicy::ExceptionStatus exceptionStatus) { |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) { |
| + isAllowed &= (policy.get()->*allowed)(scriptState, reportingStatus, |
| + exceptionStatus); |
| + } |
| + return isAllowed; |
| + } |
| -template < |
| - bool (CSPDirectiveList::*allowed)(const String&, |
| - const String&, |
| - ParserDisposition, |
| - const WTF::OrdinalNumber&, |
| - ContentSecurityPolicy::ReportingStatus, |
| - const String& content) const> |
| -bool isAllowedByAllWithContextAndContentAndParser( |
| - const CSPDirectiveListVector& policies, |
| - const String& contextURL, |
| - const String& nonce, |
| - ParserDisposition parserDisposition, |
| - const WTF::OrdinalNumber& contextLine, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus, |
| - const String& content) { |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) { |
| - isAllowed &= |
| - (policy.get()->*allowed)(contextURL, nonce, parserDisposition, |
| - contextLine, reportingStatus, content); |
| - } |
| - return isAllowed; |
| -} |
| + template <bool (CSPDirectiveList::*allowed)( |
| + const String&, |
| + const WTF::OrdinalNumber&, |
| + ContentSecurityPolicy::ReportingStatus) const> |
| + bool isAllowedByAllWithContext( |
| + const CSPDirectiveListVector& policies, |
| + const String& contextURL, |
| + const WTF::OrdinalNumber& contextLine, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) { |
| + isAllowed &= |
| + (policy.get()->*allowed)(contextURL, contextLine, reportingStatus); |
| + } |
| + return isAllowed; |
| + } |
| -template <bool (CSPDirectiveList::*allowed)(const CSPHashValue&, |
| - ContentSecurityPolicy::InlineType) |
| - const> |
| -bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, |
| - const CSPHashValue& hashValue, |
| - ContentSecurityPolicy::InlineType type) { |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= (policy.get()->*allowed)(hashValue, type); |
| - return isAllowed; |
| -} |
| + template < |
| + bool (CSPDirectiveList::*allowed)(const String&, |
| + const String&, |
| + const WTF::OrdinalNumber&, |
| + ContentSecurityPolicy::ReportingStatus, |
| + const String& content) const> |
| + bool isAllowedByAllWithContextAndContent( |
| + const CSPDirectiveListVector& policies, |
| + const String& contextURL, |
| + const String& nonce, |
| + const WTF::OrdinalNumber& contextLine, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus, |
| + const String& content) { |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) { |
| + isAllowed &= (policy.get()->*allowed)(contextURL, nonce, contextLine, |
| + reportingStatus, content); |
| + } |
| + return isAllowed; |
| + } |
| -template <bool (CSPDirectiveList::*allowFromURL)( |
| - const KURL&, |
| - RedirectStatus, |
| - ContentSecurityPolicy::ReportingStatus) const> |
| -bool isAllowedByAllWithURL( |
| - const CSPDirectiveListVector& policies, |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| - if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) |
| - return true; |
| + template < |
| + bool (CSPDirectiveList::*allowed)(const String&, |
| + const String&, |
| + ParserDisposition, |
| + const WTF::OrdinalNumber&, |
| + ContentSecurityPolicy::ReportingStatus, |
| + const String& content) const> |
| + bool isAllowedByAllWithContextAndContentAndParser( |
| + const CSPDirectiveListVector& policies, |
| + const String& contextURL, |
| + const String& nonce, |
| + ParserDisposition parserDisposition, |
| + const WTF::OrdinalNumber& contextLine, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus, |
| + const String& content) { |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) { |
| + isAllowed &= |
| + (policy.get()->*allowed)(contextURL, nonce, parserDisposition, |
| + contextLine, reportingStatus, content); |
| + } |
| + return isAllowed; |
| + } |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= |
| - (policy.get()->*allowFromURL)(url, redirectStatus, reportingStatus); |
| - return isAllowed; |
| -} |
| + template <bool (CSPDirectiveList::*allowed)(const CSPHashValue&, |
| + ContentSecurityPolicy::InlineType) |
| + const> |
| + bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, |
| + const CSPHashValue& hashValue, |
| + ContentSecurityPolicy::InlineType type) { |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) |
| + isAllowed &= (policy.get()->*allowed)(hashValue, type); |
| + return isAllowed; |
| + } |
| -template <bool (CSPDirectiveList::*allowFromURLWithNonce)( |
| - const KURL&, |
| - const String& nonce, |
| - RedirectStatus, |
| - ContentSecurityPolicy::ReportingStatus) const> |
| -bool isAllowedByAllWithURLWithNonce( |
| - const CSPDirectiveListVector& policies, |
| - const KURL& url, |
| - const String& nonce, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| - if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) |
| - return true; |
| + template <bool (CSPDirectiveList::*allowFromURL)( |
| + const KURL&, |
| + RedirectStatus, |
| + ContentSecurityPolicy::ReportingStatus) const> |
| + bool isAllowedByAllWithURL( |
| + const CSPDirectiveListVector& policies, |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| + if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) |
| + return true; |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= (policy.get()->*allowFromURLWithNonce)( |
| - url, nonce, redirectStatus, reportingStatus); |
| - return isAllowed; |
| -} |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) { |
| + isAllowed &= |
| + (policy.get()->*allowFromURL)(url, redirectStatus, reportingStatus); |
| + } |
| + return isAllowed; |
| + } |
| -template <bool (CSPDirectiveList::*allowFromURLWithNonceAndParser)( |
| - const KURL&, |
| - const String& nonce, |
| - ParserDisposition parserDisposition, |
| - RedirectStatus, |
| - ContentSecurityPolicy::ReportingStatus) const> |
| -bool isAllowedByAllWithURLNonceAndParser( |
| - const CSPDirectiveListVector& policies, |
| - const KURL& url, |
| - const String& nonce, |
| - ParserDisposition parserDisposition, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| - if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) |
| - return true; |
| + template <bool (CSPDirectiveList::*allowFromURLWithNonce)( |
| + const KURL&, |
| + const String& nonce, |
| + RedirectStatus, |
| + ContentSecurityPolicy::ReportingStatus) const> |
| + bool isAllowedByAllWithURLWithNonce( |
| + const CSPDirectiveListVector& policies, |
| + const KURL& url, |
| + const String& nonce, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| + if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) |
| + return true; |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) { |
| - isAllowed &= (policy.get()->*allowFromURLWithNonceAndParser)( |
| - url, nonce, parserDisposition, redirectStatus, reportingStatus); |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) { |
| + isAllowed &= (policy.get()->*allowFromURLWithNonce)( |
| + url, nonce, redirectStatus, reportingStatus); |
| + } |
| + return isAllowed; |
| } |
| - return isAllowed; |
| -} |
| -template <bool (CSPDirectiveList::*allowed)( |
| - LocalFrame*, |
| - const KURL&, |
| - ContentSecurityPolicy::ReportingStatus) const> |
| -bool isAllowedByAllWithFrame( |
| - const CSPDirectiveListVector& policies, |
| - LocalFrame* frame, |
| - const KURL& url, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| - bool isAllowed = true; |
| - for (const auto& policy : policies) |
| - isAllowed &= (policy.get()->*allowed)(frame, url, reportingStatus); |
| - return isAllowed; |
| -} |
| - |
| -template <bool (CSPDirectiveList::*allowed)(const CSPHashValue&, |
| - ContentSecurityPolicy::InlineType) |
| - const> |
| -bool checkDigest(const String& source, |
| - ContentSecurityPolicy::InlineType type, |
| - uint8_t hashAlgorithmsUsed, |
| - const CSPDirectiveListVector& policies) { |
| - // Any additions or subtractions from this struct should also modify the |
| - // respective entries in the kSupportedPrefixes array in |
| - // CSPSourceList::parseHash(). |
| - static const struct { |
| - ContentSecurityPolicyHashAlgorithm cspHashAlgorithm; |
| - HashAlgorithm algorithm; |
| - } kAlgorithmMap[] = { |
| - {ContentSecurityPolicyHashAlgorithmSha1, HashAlgorithmSha1}, |
| - {ContentSecurityPolicyHashAlgorithmSha256, HashAlgorithmSha256}, |
| - {ContentSecurityPolicyHashAlgorithmSha384, HashAlgorithmSha384}, |
| - {ContentSecurityPolicyHashAlgorithmSha512, HashAlgorithmSha512}}; |
| - |
| - // Only bother normalizing the source/computing digests if there are any |
| - // checks to be done. |
| - if (hashAlgorithmsUsed == ContentSecurityPolicyHashAlgorithmNone) |
| - return false; |
| + template <bool (CSPDirectiveList::*allowFromURLWithNonceAndParser)( |
| + const KURL&, |
| + const String& nonce, |
| + ParserDisposition parserDisposition, |
| + RedirectStatus, |
| + ContentSecurityPolicy::ReportingStatus) const> |
| + bool isAllowedByAllWithURLNonceAndParser( |
| + const CSPDirectiveListVector& policies, |
| + const KURL& url, |
| + const String& nonce, |
| + ParserDisposition parserDisposition, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| + if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) |
| + return true; |
| - StringUTF8Adaptor utf8Source(source); |
| - |
| - for (const auto& algorithmMap : kAlgorithmMap) { |
| - DigestValue digest; |
| - if (algorithmMap.cspHashAlgorithm & hashAlgorithmsUsed) { |
| - bool digestSuccess = |
| - computeDigest(algorithmMap.algorithm, utf8Source.data(), |
| - utf8Source.length(), digest); |
| - if (digestSuccess && |
| - isAllowedByAllWithHash<allowed>( |
| - policies, CSPHashValue(algorithmMap.cspHashAlgorithm, digest), |
| - type)) |
| - return true; |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) { |
| + isAllowed &= (policy.get()->*allowFromURLWithNonceAndParser)( |
| + url, nonce, parserDisposition, redirectStatus, reportingStatus); |
| } |
| + return isAllowed; |
| } |
| - return false; |
| -} |
| - |
| -bool ContentSecurityPolicy::allowJavaScriptURLs( |
| - const String& contextURL, |
| - const WTF::OrdinalNumber& contextLine, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithContext<&CSPDirectiveList::allowJavaScriptURLs>( |
| - m_policies, contextURL, contextLine, reportingStatus); |
| -} |
| + template <bool (CSPDirectiveList::*allowed)( |
| + LocalFrame*, |
| + const KURL&, |
| + ContentSecurityPolicy::ReportingStatus) const> |
| + bool isAllowedByAllWithFrame( |
| + const CSPDirectiveListVector& policies, |
| + LocalFrame* frame, |
| + const KURL& url, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) { |
| + bool isAllowed = true; |
| + for (const auto& policy : policies) |
| + isAllowed &= (policy.get()->*allowed)(frame, url, reportingStatus); |
| + return isAllowed; |
| + } |
| -bool ContentSecurityPolicy::allowInlineEventHandler( |
| - const String& source, |
| - const String& contextURL, |
| - const WTF::OrdinalNumber& contextLine, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - // Inline event handlers may be whitelisted by hash, if |
| - // 'unsafe-hash-attributes' is present in a policy. Check against the digest |
| - // of the |source| first before proceeding on to checking whether inline |
| - // script is allowed. |
| - if (checkDigest<&CSPDirectiveList::allowScriptHash>( |
| - source, InlineType::Attribute, m_scriptHashAlgorithmsUsed, |
| - m_policies)) |
| - return true; |
| - return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineEventHandlers>( |
| - m_policies, contextURL, contextLine, reportingStatus); |
| -} |
| + template <bool (CSPDirectiveList::*allowed)(const CSPHashValue&, |
| + ContentSecurityPolicy::InlineType) |
| + const> |
| + bool checkDigest(const String& source, |
| + ContentSecurityPolicy::InlineType type, |
| + uint8_t hashAlgorithmsUsed, |
| + const CSPDirectiveListVector& policies) { |
| + // Any additions or subtractions from this struct should also modify the |
| + // respective entries in the kSupportedPrefixes array in |
| + // CSPSourceList::parseHash(). |
| + static const struct { |
| + ContentSecurityPolicyHashAlgorithm cspHashAlgorithm; |
| + HashAlgorithm algorithm; |
| + } kAlgorithmMap[] = { |
| + {ContentSecurityPolicyHashAlgorithmSha1, HashAlgorithmSha1}, |
| + {ContentSecurityPolicyHashAlgorithmSha256, HashAlgorithmSha256}, |
| + {ContentSecurityPolicyHashAlgorithmSha384, HashAlgorithmSha384}, |
| + {ContentSecurityPolicyHashAlgorithmSha512, HashAlgorithmSha512}}; |
| + |
| + // Only bother normalizing the source/computing digests if there are any |
| + // checks to be done. |
| + if (hashAlgorithmsUsed == ContentSecurityPolicyHashAlgorithmNone) |
| + return false; |
| -bool ContentSecurityPolicy::allowInlineScript( |
| - const String& contextURL, |
| - const String& nonce, |
| - ParserDisposition parserDisposition, |
| - const WTF::OrdinalNumber& contextLine, |
| - const String& scriptContent, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithContextAndContentAndParser< |
| - &CSPDirectiveList::allowInlineScript>(m_policies, contextURL, nonce, |
| - parserDisposition, contextLine, |
| - reportingStatus, scriptContent); |
| -} |
| + StringUTF8Adaptor utf8Source(source); |
| + |
| + for (const auto& algorithmMap : kAlgorithmMap) { |
| + DigestValue digest; |
| + if (algorithmMap.cspHashAlgorithm & hashAlgorithmsUsed) { |
| + bool digestSuccess = |
| + computeDigest(algorithmMap.algorithm, utf8Source.data(), |
| + utf8Source.length(), digest); |
| + if (digestSuccess && |
| + isAllowedByAllWithHash<allowed>( |
| + policies, CSPHashValue(algorithmMap.cspHashAlgorithm, digest), |
| + type)) |
| + return true; |
| + } |
| + } |
| -bool ContentSecurityPolicy::allowInlineStyle( |
| - const String& contextURL, |
| - const String& nonce, |
| - const WTF::OrdinalNumber& contextLine, |
| - const String& styleContent, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - if (m_overrideInlineStyleAllowed) |
| - return true; |
| - return isAllowedByAllWithContextAndContent< |
| - &CSPDirectiveList::allowInlineStyle>(m_policies, contextURL, nonce, |
| - contextLine, reportingStatus, |
| - styleContent); |
| -} |
| + return false; |
| + } |
| -bool ContentSecurityPolicy::allowEval( |
| - ScriptState* scriptState, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus, |
| - ContentSecurityPolicy::ExceptionStatus exceptionStatus) const { |
| - return isAllowedByAllWithStateAndExceptionStatus< |
| - &CSPDirectiveList::allowEval>(m_policies, scriptState, reportingStatus, |
| - exceptionStatus); |
| -} |
| + bool ContentSecurityPolicy::allowJavaScriptURLs( |
| + const String& contextURL, |
| + const WTF::OrdinalNumber& contextLine, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithContext<&CSPDirectiveList::allowJavaScriptURLs>( |
| + m_policies, contextURL, contextLine, reportingStatus); |
| + } |
| -String ContentSecurityPolicy::evalDisabledErrorMessage() const { |
| - for (const auto& policy : m_policies) { |
| - if (!policy->allowEval(0, SuppressReport)) |
| - return policy->evalDisabledErrorMessage(); |
| + bool ContentSecurityPolicy::allowInlineEventHandler( |
| + const String& source, |
| + const String& contextURL, |
| + const WTF::OrdinalNumber& contextLine, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + // Inline event handlers may be whitelisted by hash, if |
| + // 'unsafe-hash-attributes' is present in a policy. Check against the digest |
| + // of the |source| first before proceeding on to checking whether inline |
| + // script is allowed. |
| + if (checkDigest<&CSPDirectiveList::allowScriptHash>( |
| + source, InlineType::Attribute, m_scriptHashAlgorithmsUsed, |
| + m_policies)) |
| + return true; |
| + return isAllowedByAllWithContext< |
| + &CSPDirectiveList::allowInlineEventHandlers>( |
| + m_policies, contextURL, contextLine, reportingStatus); |
| } |
| - return String(); |
| -} |
| -bool ContentSecurityPolicy::allowPluginType( |
| - const String& type, |
| - const String& typeAttribute, |
| - const KURL& url, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - for (const auto& policy : m_policies) { |
| - if (!policy->allowPluginType(type, typeAttribute, url, reportingStatus)) |
| - return false; |
| + bool ContentSecurityPolicy::allowInlineScript( |
| + const String& contextURL, |
| + const String& nonce, |
| + ParserDisposition parserDisposition, |
| + const WTF::OrdinalNumber& contextLine, |
| + const String& scriptContent, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithContextAndContentAndParser< |
| + &CSPDirectiveList::allowInlineScript>(m_policies, contextURL, nonce, |
| + parserDisposition, contextLine, |
| + reportingStatus, scriptContent); |
| } |
| - return true; |
| -} |
| -bool ContentSecurityPolicy::allowPluginTypeForDocument( |
| - const Document& document, |
| - const String& type, |
| - const String& typeAttribute, |
| - const KURL& url, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - if (document.contentSecurityPolicy() && |
| - !document.contentSecurityPolicy()->allowPluginType(type, typeAttribute, |
| - url)) |
| - return false; |
| + bool ContentSecurityPolicy::allowInlineStyle( |
| + const String& contextURL, |
| + const String& nonce, |
| + const WTF::OrdinalNumber& contextLine, |
| + const String& styleContent, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + if (m_overrideInlineStyleAllowed) |
| + return true; |
| + return isAllowedByAllWithContextAndContent< |
| + &CSPDirectiveList::allowInlineStyle>(m_policies, contextURL, nonce, |
| + contextLine, reportingStatus, |
| + styleContent); |
| + } |
| - // CSP says that a plugin document in a nested browsing context should |
| - // inherit the plugin-types of its parent. |
| - // |
| - // FIXME: The plugin-types directive should be pushed down into the |
| - // current document instead of reaching up to the parent for it here. |
| - LocalFrame* frame = document.frame(); |
| - if (frame && frame->tree().parent() && document.isPluginDocument()) { |
| - ContentSecurityPolicy* parentCSP = |
| - frame->tree().parent()->securityContext()->contentSecurityPolicy(); |
| - if (parentCSP && !parentCSP->allowPluginType(type, typeAttribute, url)) |
| - return false; |
| + bool ContentSecurityPolicy::allowEval( |
| + ScriptState* scriptState, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus, |
| + ContentSecurityPolicy::ExceptionStatus exceptionStatus) const { |
| + return isAllowedByAllWithStateAndExceptionStatus< |
| + &CSPDirectiveList::allowEval>(m_policies, scriptState, reportingStatus, |
| + exceptionStatus); |
| } |
| - return true; |
| -} |
| + String ContentSecurityPolicy::evalDisabledErrorMessage() const { |
| + for (const auto& policy : m_policies) { |
| + if (!policy->allowEval(0, SuppressReport)) |
| + return policy->evalDisabledErrorMessage(); |
| + } |
| + return String(); |
| + } |
| -bool ContentSecurityPolicy::allowScriptFromSource( |
| - const KURL& url, |
| - const String& nonce, |
| - ParserDisposition parserDisposition, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURLNonceAndParser< |
| - &CSPDirectiveList::allowScriptFromSource>( |
| - m_policies, url, nonce, parserDisposition, redirectStatus, |
| - reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowPluginType( |
| + const String& type, |
| + const String& typeAttribute, |
| + const KURL& url, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + for (const auto& policy : m_policies) { |
| + if (!policy->allowPluginType(type, typeAttribute, url, reportingStatus)) |
| + return false; |
| + } |
| + return true; |
| + } |
| -bool ContentSecurityPolicy::allowScriptWithHash(const String& source, |
| - InlineType type) const { |
| - return checkDigest<&CSPDirectiveList::allowScriptHash>( |
| - source, type, m_scriptHashAlgorithmsUsed, m_policies); |
| -} |
| + bool ContentSecurityPolicy::allowPluginTypeForDocument( |
| + const Document& document, |
| + const String& type, |
| + const String& typeAttribute, |
| + const KURL& url, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + if (document.contentSecurityPolicy() && |
| + !document.contentSecurityPolicy()->allowPluginType(type, typeAttribute, |
| + url)) |
| + return false; |
| -bool ContentSecurityPolicy::allowStyleWithHash(const String& source, |
| - InlineType type) const { |
| - return checkDigest<&CSPDirectiveList::allowStyleHash>( |
| - source, type, m_styleHashAlgorithmsUsed, m_policies); |
| -} |
| + // CSP says that a plugin document in a nested browsing context should |
| + // inherit the plugin-types of its parent. |
| + // |
| + // FIXME: The plugin-types directive should be pushed down into the |
| + // current document instead of reaching up to the parent for it here. |
| + LocalFrame* frame = document.frame(); |
| + if (frame && frame->tree().parent() && document.isPluginDocument()) { |
| + ContentSecurityPolicy* parentCSP = |
| + frame->tree().parent()->securityContext()->contentSecurityPolicy(); |
| + if (parentCSP && !parentCSP->allowPluginType(type, typeAttribute, url)) |
| + return false; |
| + } |
| -bool ContentSecurityPolicy::allowRequestWithoutIntegrity( |
| - WebURLRequest::RequestContext context, |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - for (const auto& policy : m_policies) { |
| - if (!policy->allowRequestWithoutIntegrity(context, url, redirectStatus, |
| - reportingStatus)) |
| - return false; |
| + return true; |
| } |
| - return true; |
| -} |
| - |
| -bool ContentSecurityPolicy::allowRequest( |
| - WebURLRequest::RequestContext context, |
| - const KURL& url, |
| - const String& nonce, |
| - const IntegrityMetadataSet& integrityMetadata, |
| - ParserDisposition parserDisposition, |
| - RedirectStatus redirectStatus, |
| - ReportingStatus reportingStatus) const { |
| - if (integrityMetadata.isEmpty() && |
| - !allowRequestWithoutIntegrity(context, url, redirectStatus, |
| - reportingStatus)) |
| - return false; |
| - switch (context) { |
| - case WebURLRequest::RequestContextAudio: |
| - case WebURLRequest::RequestContextTrack: |
| - case WebURLRequest::RequestContextVideo: |
| - return allowMediaFromSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextBeacon: |
| - case WebURLRequest::RequestContextEventSource: |
| - case WebURLRequest::RequestContextFetch: |
| - case WebURLRequest::RequestContextXMLHttpRequest: |
| - return allowConnectToSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextEmbed: |
| - case WebURLRequest::RequestContextObject: |
| - return allowObjectFromSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextFavicon: |
| - case WebURLRequest::RequestContextImage: |
| - case WebURLRequest::RequestContextImageSet: |
| - return allowImageFromSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextFont: |
| - return allowFontFromSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextForm: |
| - return allowFormAction(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextFrame: |
| - case WebURLRequest::RequestContextIframe: |
| - return allowChildFrameFromSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextImport: |
| - case WebURLRequest::RequestContextScript: |
| - return allowScriptFromSource(url, nonce, parserDisposition, |
| - redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextXSLT: |
| - return allowScriptFromSource(url, nonce, parserDisposition, |
| - redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextManifest: |
| - return allowManifestFromSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextServiceWorker: |
| - case WebURLRequest::RequestContextSharedWorker: |
| - case WebURLRequest::RequestContextWorker: |
| - return allowWorkerContextFromSource(url, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextStyle: |
| - return allowStyleFromSource(url, nonce, redirectStatus, reportingStatus); |
| - case WebURLRequest::RequestContextCSPReport: |
| - case WebURLRequest::RequestContextDownload: |
| - case WebURLRequest::RequestContextHyperlink: |
| - case WebURLRequest::RequestContextInternal: |
| - case WebURLRequest::RequestContextLocation: |
| - case WebURLRequest::RequestContextPing: |
| - case WebURLRequest::RequestContextPlugin: |
| - case WebURLRequest::RequestContextPrefetch: |
| - case WebURLRequest::RequestContextSubresource: |
| - case WebURLRequest::RequestContextUnspecified: |
| - return true; |
| + bool ContentSecurityPolicy::allowScriptFromSource( |
| + const KURL& url, |
| + const String& nonce, |
| + ParserDisposition parserDisposition, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURLNonceAndParser< |
| + &CSPDirectiveList::allowScriptFromSource>( |
| + m_policies, url, nonce, parserDisposition, redirectStatus, |
| + reportingStatus); |
| } |
| - ASSERT_NOT_REACHED(); |
| - return true; |
| -} |
| -void ContentSecurityPolicy::usesScriptHashAlgorithms(uint8_t algorithms) { |
| - m_scriptHashAlgorithmsUsed |= algorithms; |
| -} |
| + bool ContentSecurityPolicy::allowScriptWithHash(const String& source, |
| + InlineType type) const { |
| + return checkDigest<&CSPDirectiveList::allowScriptHash>( |
| + source, type, m_scriptHashAlgorithmsUsed, m_policies); |
| + } |
| -void ContentSecurityPolicy::usesStyleHashAlgorithms(uint8_t algorithms) { |
| - m_styleHashAlgorithmsUsed |= algorithms; |
| -} |
| + bool ContentSecurityPolicy::allowStyleWithHash(const String& source, |
| + InlineType type) const { |
| + return checkDigest<&CSPDirectiveList::allowStyleHash>( |
| + source, type, m_styleHashAlgorithmsUsed, m_policies); |
| + } |
| -bool ContentSecurityPolicy::allowObjectFromSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowRequestWithoutIntegrity( |
| + WebURLRequest::RequestContext context, |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + for (const auto& policy : m_policies) { |
| + if (!policy->allowRequestWithoutIntegrity(context, url, redirectStatus, |
| + reportingStatus)) |
| + return false; |
| + } |
| + return true; |
| + } |
| -bool ContentSecurityPolicy::allowChildFrameFromSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowRequest( |
| + WebURLRequest::RequestContext context, |
| + const KURL& url, |
| + const String& nonce, |
| + const IntegrityMetadataSet& integrityMetadata, |
| + ParserDisposition parserDisposition, |
| + RedirectStatus redirectStatus, |
| + ReportingStatus reportingStatus) const { |
| + if (integrityMetadata.isEmpty() && |
| + !allowRequestWithoutIntegrity(context, url, redirectStatus, |
| + reportingStatus)) |
| + return false; |
| -bool ContentSecurityPolicy::allowImageFromSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| - url.protocol(), SchemeRegistry::PolicyAreaImage)) |
| + switch (context) { |
| + case WebURLRequest::RequestContextAudio: |
| + case WebURLRequest::RequestContextTrack: |
| + case WebURLRequest::RequestContextVideo: |
| + return allowMediaFromSource(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextBeacon: |
| + case WebURLRequest::RequestContextEventSource: |
| + case WebURLRequest::RequestContextFetch: |
| + case WebURLRequest::RequestContextXMLHttpRequest: |
| + return allowConnectToSource(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextEmbed: |
| + case WebURLRequest::RequestContextObject: |
| + return allowObjectFromSource(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextFavicon: |
| + case WebURLRequest::RequestContextImage: |
| + case WebURLRequest::RequestContextImageSet: |
| + return allowImageFromSource(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextFont: |
| + return allowFontFromSource(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextForm: |
| + return allowFormAction(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextFrame: |
| + case WebURLRequest::RequestContextIframe: |
| + return allowChildFrameFromSource(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextImport: |
| + case WebURLRequest::RequestContextScript: |
| + return allowScriptFromSource(url, nonce, parserDisposition, |
| + redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextXSLT: |
| + return allowScriptFromSource(url, nonce, parserDisposition, |
| + redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextManifest: |
| + return allowManifestFromSource(url, redirectStatus, reportingStatus); |
| + case WebURLRequest::RequestContextServiceWorker: |
| + case WebURLRequest::RequestContextSharedWorker: |
| + case WebURLRequest::RequestContextWorker: |
| + return allowWorkerContextFromSource(url, redirectStatus, |
| + reportingStatus); |
| + case WebURLRequest::RequestContextStyle: |
| + return allowStyleFromSource(url, nonce, redirectStatus, |
| + reportingStatus); |
| + case WebURLRequest::RequestContextCSPReport: |
| + case WebURLRequest::RequestContextDownload: |
| + case WebURLRequest::RequestContextHyperlink: |
| + case WebURLRequest::RequestContextInternal: |
| + case WebURLRequest::RequestContextLocation: |
| + case WebURLRequest::RequestContextPing: |
| + case WebURLRequest::RequestContextPlugin: |
| + case WebURLRequest::RequestContextPrefetch: |
| + case WebURLRequest::RequestContextSubresource: |
| + case WebURLRequest::RequestContextUnspecified: |
| + return true; |
| + } |
| + NOTREACHED(); |
| return true; |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowImageFromSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + } |
| -bool ContentSecurityPolicy::allowStyleFromSource( |
| - const KURL& url, |
| - const String& nonce, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| - url.protocol(), SchemeRegistry::PolicyAreaStyle)) |
| - return true; |
| - return isAllowedByAllWithURLWithNonce< |
| - &CSPDirectiveList::allowStyleFromSource>(m_policies, url, nonce, |
| - redirectStatus, reportingStatus); |
| -} |
| + void ContentSecurityPolicy::usesScriptHashAlgorithms(uint8_t algorithms) { |
| + m_scriptHashAlgorithmsUsed |= algorithms; |
| + } |
| -bool ContentSecurityPolicy::allowFontFromSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowFontFromSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + void ContentSecurityPolicy::usesStyleHashAlgorithms(uint8_t algorithms) { |
| + m_styleHashAlgorithmsUsed |= algorithms; |
| + } |
| -bool ContentSecurityPolicy::allowMediaFromSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowMediaFromSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowObjectFromSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| + } |
| -bool ContentSecurityPolicy::allowConnectToSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowConnectToSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowChildFrameFromSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| + } |
| -bool ContentSecurityPolicy::allowFormAction( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowFormAction>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowImageFromSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| + url.protocol(), SchemeRegistry::PolicyAreaImage)) |
| + return true; |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowImageFromSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| + } |
| -bool ContentSecurityPolicy::allowBaseURI( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowStyleFromSource( |
| + const KURL& url, |
| + const String& nonce, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| + url.protocol(), SchemeRegistry::PolicyAreaStyle)) |
| + return true; |
| + return isAllowedByAllWithURLWithNonce< |
| + &CSPDirectiveList::allowStyleFromSource>( |
| + m_policies, url, nonce, redirectStatus, reportingStatus); |
| + } |
| -bool ContentSecurityPolicy::allowWorkerContextFromSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure the |
| - // impact of this backwards-incompatible change. |
| - if (Document* document = this->document()) { |
| - UseCounter::count(*document, UseCounter::WorkerSubjectToCSP); |
| - if (isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>( |
| - m_policies, url, redirectStatus, SuppressReport) && |
| - !isAllowedByAllWithURLNonceAndParser< |
| - &CSPDirectiveList::allowScriptFromSource>( |
| - m_policies, url, AtomicString(), NotParserInserted, redirectStatus, |
| - SuppressReport)) { |
| - UseCounter::count(*document, |
| - UseCounter::WorkerAllowedByChildBlockedByScript); |
| - } |
| + bool ContentSecurityPolicy::allowFontFromSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowFontFromSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| } |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowMediaFromSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowMediaFromSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| + } |
| -bool ContentSecurityPolicy::allowManifestFromSource( |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithURL<&CSPDirectiveList::allowManifestFromSource>( |
| - m_policies, url, redirectStatus, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowConnectToSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowConnectToSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| + } |
| -bool ContentSecurityPolicy::allowAncestors( |
| - LocalFrame* frame, |
| - const KURL& url, |
| - ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| - return isAllowedByAllWithFrame<&CSPDirectiveList::allowAncestors>( |
| - m_policies, frame, url, reportingStatus); |
| -} |
| + bool ContentSecurityPolicy::allowFormAction( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowFormAction>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| + } |
| -bool ContentSecurityPolicy::isFrameAncestorsEnforced() const { |
| - for (const auto& policy : m_policies) { |
| - if (policy->isFrameAncestorsEnforced()) |
| - return true; |
| + bool ContentSecurityPolicy::allowBaseURI( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| } |
| - return false; |
| -} |
| -bool ContentSecurityPolicy::isActive() const { |
| - return !m_policies.isEmpty(); |
| -} |
| + bool ContentSecurityPolicy::allowWorkerContextFromSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure |
| + // the |
| + // impact of this backwards-incompatible change. |
| + if (Document* document = this->document()) { |
| + UseCounter::count(*document, UseCounter::WorkerSubjectToCSP); |
| + if (isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>( |
| + m_policies, url, redirectStatus, SuppressReport) && |
| + !isAllowedByAllWithURLNonceAndParser< |
| + &CSPDirectiveList::allowScriptFromSource>( |
| + m_policies, url, AtomicString(), NotParserInserted, |
| + redirectStatus, SuppressReport)) { |
| + UseCounter::count(*document, |
| + UseCounter::WorkerAllowedByChildBlockedByScript); |
| + } |
| + } |
| -ReflectedXSSDisposition ContentSecurityPolicy::getReflectedXSSDisposition() |
| - const { |
| - ReflectedXSSDisposition disposition = ReflectedXSSUnset; |
| - for (const auto& policy : m_policies) { |
| - if (policy->getReflectedXSSDisposition() > disposition) |
| - disposition = std::max(disposition, policy->getReflectedXSSDisposition()); |
| + return isAllowedByAllWithURL< |
| + &CSPDirectiveList::allowChildContextFromSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| } |
| - return disposition; |
| -} |
| -bool ContentSecurityPolicy::didSetReferrerPolicy() const { |
| - for (const auto& policy : m_policies) { |
| - if (policy->didSetReferrerPolicy()) |
| - return true; |
| + bool ContentSecurityPolicy::allowManifestFromSource( |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithURL<&CSPDirectiveList::allowManifestFromSource>( |
| + m_policies, url, redirectStatus, reportingStatus); |
| } |
| - return false; |
| -} |
| -const KURL ContentSecurityPolicy::url() const { |
| - return m_executionContext->contextURL(); |
| -} |
| + bool ContentSecurityPolicy::allowAncestors( |
| + LocalFrame* frame, |
| + const KURL& url, |
| + ContentSecurityPolicy::ReportingStatus reportingStatus) const { |
| + return isAllowedByAllWithFrame<&CSPDirectiveList::allowAncestors>( |
| + m_policies, frame, url, reportingStatus); |
| + } |
| -KURL ContentSecurityPolicy::completeURL(const String& url) const { |
| - return m_executionContext->contextCompleteURL(url); |
| -} |
| + bool ContentSecurityPolicy::isFrameAncestorsEnforced() const { |
| + for (const auto& policy : m_policies) { |
| + if (policy->isFrameAncestorsEnforced()) |
| + return true; |
| + } |
| + return false; |
| + } |
| -void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) { |
| - m_sandboxMask |= mask; |
| -} |
| + bool ContentSecurityPolicy::isActive() const { |
| + return !m_policies.isEmpty(); |
| + } |
| -void ContentSecurityPolicy::treatAsPublicAddress() { |
| - if (!RuntimeEnabledFeatures::corsRFC1918Enabled()) |
| - return; |
| - m_treatAsPublicAddress = true; |
| -} |
| + ReflectedXSSDisposition ContentSecurityPolicy::getReflectedXSSDisposition() |
| + const { |
| + ReflectedXSSDisposition disposition = ReflectedXSSUnset; |
| + for (const auto& policy : m_policies) { |
| + if (policy->getReflectedXSSDisposition() > disposition) { |
| + disposition = |
| + std::max(disposition, policy->getReflectedXSSDisposition()); |
| + } |
| + } |
| + return disposition; |
| + } |
| -void ContentSecurityPolicy::enforceStrictMixedContentChecking() { |
| - m_insecureRequestPolicy |= kBlockAllMixedContent; |
| -} |
| + bool ContentSecurityPolicy::didSetReferrerPolicy() const { |
| + for (const auto& policy : m_policies) { |
| + if (policy->didSetReferrerPolicy()) |
| + return true; |
| + } |
| + return false; |
| + } |
| -void ContentSecurityPolicy::upgradeInsecureRequests() { |
| - m_insecureRequestPolicy |= kUpgradeInsecureRequests; |
| -} |
| + const KURL ContentSecurityPolicy::url() const { |
| + return m_executionContext->contextURL(); |
| + } |
| -static String stripURLForUseInReport(Document* document, |
| - const KURL& url, |
| - RedirectStatus redirectStatus, |
| - const String& effectiveDirective) { |
| - if (!url.isValid()) |
| - return String(); |
| - if (!url.isHierarchical() || url.protocolIs("file")) |
| - return url.protocol(); |
| - |
| - // Until we're more careful about the way we deal with navigations in frames |
| - // (and, by extension, in plugin documents), strip cross-origin 'frame-src' |
| - // and 'object-src' violations down to an origin. https://crbug.com/633306 |
| - bool canSafelyExposeURL = |
| - document->getSecurityOrigin()->canRequest(url) || |
| - (redirectStatus == RedirectStatus::NoRedirect && |
| - !equalIgnoringCase(effectiveDirective, |
| - ContentSecurityPolicy::FrameSrc) && |
| - !equalIgnoringCase(effectiveDirective, |
| - ContentSecurityPolicy::ObjectSrc)); |
| - |
| - if (canSafelyExposeURL) { |
| - // 'KURL::strippedForUseAsReferrer()' dumps 'String()' for non-webby URLs. |
| - // It's better for developers if we return the origin of those URLs rather |
| - // than nothing. |
| - if (url.protocolIsInHTTPFamily()) |
| - return url.strippedForUseAsReferrer(); |
| - } |
| - return SecurityOrigin::create(url)->toString(); |
| -} |
| + KURL ContentSecurityPolicy::completeURL(const String& url) const { |
| + return m_executionContext->contextCompleteURL(url); |
| + } |
| -static void gatherSecurityPolicyViolationEventData( |
| - SecurityPolicyViolationEventInit& init, |
| - Document* document, |
| - const String& directiveText, |
| - const String& effectiveDirective, |
| - const KURL& blockedURL, |
| - const String& header, |
| - RedirectStatus redirectStatus, |
| - ContentSecurityPolicy::ViolationType violationType, |
| - int contextLine) { |
| - if (equalIgnoringCase(effectiveDirective, |
| - ContentSecurityPolicy::FrameAncestors)) { |
| - // If this load was blocked via 'frame-ancestors', then the URL of |
| - // |document| has not yet been initialized. In this case, we'll set both |
| - // 'documentURI' and 'blockedURI' to the blocked document's URL. |
| - init.setDocumentURI(blockedURL.getString()); |
| - init.setBlockedURI(blockedURL.getString()); |
| - } else { |
| - init.setDocumentURI(document->url().getString()); |
| - switch (violationType) { |
| - case ContentSecurityPolicy::InlineViolation: |
| - init.setBlockedURI("inline"); |
| - break; |
| - case ContentSecurityPolicy::EvalViolation: |
| - init.setBlockedURI("eval"); |
| - break; |
| - case ContentSecurityPolicy::URLViolation: |
| - init.setBlockedURI(stripURLForUseInReport( |
| - document, blockedURL, redirectStatus, effectiveDirective)); |
| - break; |
| - } |
| + void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) { |
| + m_sandboxMask |= mask; |
| } |
| - init.setReferrer(document->referrer()); |
| - init.setViolatedDirective(directiveText); |
| - init.setEffectiveDirective(effectiveDirective); |
| - init.setOriginalPolicy(header); |
| - init.setSourceFile(String()); |
| - init.setLineNumber(contextLine); |
| - init.setColumnNumber(0); |
| - init.setStatusCode(0); |
| - |
| - if (!SecurityOrigin::isSecure(document->url()) && document->loader()) |
| - init.setStatusCode(document->loader()->response().httpStatusCode()); |
| - |
| - std::unique_ptr<SourceLocation> location = SourceLocation::capture(document); |
| - if (location->lineNumber()) { |
| - KURL source = KURL(ParsedURLString, location->url()); |
| - init.setSourceFile(stripURLForUseInReport(document, source, redirectStatus, |
| - effectiveDirective)); |
| - init.setLineNumber(location->lineNumber()); |
| - init.setColumnNumber(location->columnNumber()); |
| + |
| + void ContentSecurityPolicy::treatAsPublicAddress() { |
| + if (!RuntimeEnabledFeatures::corsRFC1918Enabled()) |
| + return; |
| + m_treatAsPublicAddress = true; |
| } |
| -} |
| -void ContentSecurityPolicy::reportViolation( |
| - const String& directiveText, |
| - const String& effectiveDirective, |
| - const String& consoleMessage, |
| - const KURL& blockedURL, |
| - const Vector<String>& reportEndpoints, |
| - const String& header, |
| - ViolationType violationType, |
| - LocalFrame* contextFrame, |
| - RedirectStatus redirectStatus, |
| - int contextLine) { |
| - ASSERT(violationType == URLViolation || blockedURL.isEmpty()); |
| - |
| - // TODO(lukasza): Support sending reports from OOPIFs - |
| - // https://crbug.com/611232 (or move CSP child-src and frame-src checks to the |
| - // browser process - see https://crbug.com/376522). |
| - if (!m_executionContext && !contextFrame) { |
| - DCHECK(equalIgnoringCase(effectiveDirective, |
| - ContentSecurityPolicy::ChildSrc) || |
| - equalIgnoringCase(effectiveDirective, |
| - ContentSecurityPolicy::FrameSrc) || |
| - equalIgnoringCase(effectiveDirective, |
| - ContentSecurityPolicy::PluginTypes)); |
| - return; |
| + void ContentSecurityPolicy::enforceStrictMixedContentChecking() { |
| + m_insecureRequestPolicy |= kBlockAllMixedContent; |
| } |
| - ASSERT((m_executionContext && !contextFrame) || |
| - (equalIgnoringCase(effectiveDirective, |
| - ContentSecurityPolicy::FrameAncestors) && |
| - contextFrame)); |
| + void ContentSecurityPolicy::upgradeInsecureRequests() { |
| + m_insecureRequestPolicy |= kUpgradeInsecureRequests; |
| + } |
| - // FIXME: Support sending reports from worker. |
| - Document* document = |
| - contextFrame ? contextFrame->document() : this->document(); |
| - if (!document) |
| - return; |
| + static String stripURLForUseInReport(Document* document, |
| + const KURL& url, |
| + RedirectStatus redirectStatus, |
| + const String& effectiveDirective) { |
| + if (!url.isValid()) |
| + return String(); |
| + if (!url.isHierarchical() || url.protocolIs("file")) |
| + return url.protocol(); |
| + |
| + // Until we're more careful about the way we deal with navigations in frames |
| + // (and, by extension, in plugin documents), strip cross-origin 'frame-src' |
| + // and 'object-src' violations down to an origin. https://crbug.com/633306 |
| + bool canSafelyExposeURL = |
| + document->getSecurityOrigin()->canRequest(url) || |
| + (redirectStatus == RedirectStatus::NoRedirect && |
| + !equalIgnoringCase(effectiveDirective, |
| + ContentSecurityPolicy::FrameSrc) && |
| + !equalIgnoringCase(effectiveDirective, |
| + ContentSecurityPolicy::ObjectSrc)); |
| + |
| + if (canSafelyExposeURL) { |
| + // 'KURL::strippedForUseAsReferrer()' dumps 'String()' for non-webby URLs. |
| + // It's better for developers if we return the origin of those URLs rather |
| + // than nothing. |
| + if (url.protocolIsInHTTPFamily()) |
| + return url.strippedForUseAsReferrer(); |
| + } |
| + return SecurityOrigin::create(url)->toString(); |
| + } |
| - SecurityPolicyViolationEventInit violationData; |
| - gatherSecurityPolicyViolationEventData( |
| - violationData, document, directiveText, effectiveDirective, blockedURL, |
| - header, redirectStatus, violationType, contextLine); |
| - |
| - // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded |
| - // resources should be allowed regardless. We apparently do, however, so |
| - // we should at least stop spamming reporting endpoints. See |
| - // https://crbug.com/524356 for detail. |
| - if (!violationData.sourceFile().isEmpty() && |
| - SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| - KURL(ParsedURLString, violationData.sourceFile()).protocol())) |
| - return; |
| + static void gatherSecurityPolicyViolationEventData( |
| + SecurityPolicyViolationEventInit& init, |
| + Document* document, |
| + const String& directiveText, |
| + const String& effectiveDirective, |
| + const KURL& blockedURL, |
| + const String& header, |
| + RedirectStatus redirectStatus, |
| + ContentSecurityPolicy::ViolationType violationType, |
| + int contextLine) { |
| + if (equalIgnoringCase(effectiveDirective, |
| + ContentSecurityPolicy::FrameAncestors)) { |
| + // If this load was blocked via 'frame-ancestors', then the URL of |
| + // |document| has not yet been initialized. In this case, we'll set both |
| + // 'documentURI' and 'blockedURI' to the blocked document's URL. |
| + init.setDocumentURI(blockedURL.getString()); |
| + init.setBlockedURI(blockedURL.getString()); |
| + } else { |
| + init.setDocumentURI(document->url().getString()); |
| + switch (violationType) { |
| + case ContentSecurityPolicy::InlineViolation: |
| + init.setBlockedURI("inline"); |
| + break; |
| + case ContentSecurityPolicy::EvalViolation: |
| + init.setBlockedURI("eval"); |
| + break; |
| + case ContentSecurityPolicy::URLViolation: |
| + init.setBlockedURI(stripURLForUseInReport( |
| + document, blockedURL, redirectStatus, effectiveDirective)); |
| + break; |
| + } |
| + } |
| + init.setReferrer(document->referrer()); |
| + init.setViolatedDirective(directiveText); |
| + init.setEffectiveDirective(effectiveDirective); |
| + init.setOriginalPolicy(header); |
| + init.setSourceFile(String()); |
| + init.setLineNumber(contextLine); |
| + init.setColumnNumber(0); |
| + init.setStatusCode(0); |
| + |
| + if (!SecurityOrigin::isSecure(document->url()) && document->loader()) |
| + init.setStatusCode(document->loader()->response().httpStatusCode()); |
| + |
| + std::unique_ptr<SourceLocation> location = |
| + SourceLocation::capture(document); |
| + if (location->lineNumber()) { |
| + KURL source = KURL(ParsedURLString, location->url()); |
| + init.setSourceFile(stripURLForUseInReport( |
| + document, source, redirectStatus, effectiveDirective)); |
| + init.setLineNumber(location->lineNumber()); |
| + init.setColumnNumber(location->columnNumber()); |
| + } |
| + } |
| - // We need to be careful here when deciding what information to send to the |
| - // report-uri. Currently, we send only the current document's URL and the |
| - // directive that was violated. The document's URL is safe to send because |
| - // it's the document itself that's requesting that it be sent. You could |
| - // make an argument that we shouldn't send HTTPS document URLs to HTTP |
| - // report-uris (for the same reasons that we supress the Referer in that |
| - // case), but the Referer is sent implicitly whereas this request is only |
| - // sent explicitly. As for which directive was violated, that's pretty |
| - // harmless information. |
| - |
| - std::unique_ptr<JSONObject> cspReport = JSONObject::create(); |
| - cspReport->setString("document-uri", violationData.documentURI()); |
| - cspReport->setString("referrer", violationData.referrer()); |
| - cspReport->setString("violated-directive", violationData.violatedDirective()); |
| - cspReport->setString("effective-directive", |
| - violationData.effectiveDirective()); |
| - cspReport->setString("original-policy", violationData.originalPolicy()); |
| - cspReport->setString("blocked-uri", violationData.blockedURI()); |
| - if (violationData.lineNumber()) |
| - cspReport->setInteger("line-number", violationData.lineNumber()); |
| - if (violationData.columnNumber()) |
| - cspReport->setInteger("column-number", violationData.columnNumber()); |
| - if (!violationData.sourceFile().isEmpty()) |
| - cspReport->setString("source-file", violationData.sourceFile()); |
| - cspReport->setInteger("status-code", violationData.statusCode()); |
| - |
| - std::unique_ptr<JSONObject> reportObject = JSONObject::create(); |
| - reportObject->setObject("csp-report", std::move(cspReport)); |
| - String stringifiedReport = reportObject->toJSONString(); |
| - |
| - if (!shouldSendViolationReport(stringifiedReport)) |
| - return; |
| - didSendViolationReport(stringifiedReport); |
| + void ContentSecurityPolicy::reportViolation( |
| + const String& directiveText, |
| + const String& effectiveDirective, |
| + const String& consoleMessage, |
| + const KURL& blockedURL, |
| + const Vector<String>& reportEndpoints, |
| + const String& header, |
| + ViolationType violationType, |
| + LocalFrame* contextFrame, |
| + RedirectStatus redirectStatus, |
| + int contextLine) { |
| + DCHECK(violationType == URLViolation || blockedURL.isEmpty()); |
| + |
| + // TODO(lukasza): Support sending reports from OOPIFs - |
| + // https://crbug.com/611232 (or move CSP child-src and frame-src checks to |
| + // the |
| + // browser process - see https://crbug.com/376522). |
| + if (!m_executionContext && !contextFrame) { |
| + DCHECK(equalIgnoringCase(effectiveDirective, |
| + ContentSecurityPolicy::ChildSrc) || |
| + equalIgnoringCase(effectiveDirective, |
| + ContentSecurityPolicy::FrameSrc) || |
| + equalIgnoringCase(effectiveDirective, |
| + ContentSecurityPolicy::PluginTypes)); |
| + return; |
| + } |
| - RefPtr<EncodedFormData> report = |
| - EncodedFormData::create(stringifiedReport.utf8()); |
| + DCHECK((m_executionContext && !contextFrame) || |
| + (equalIgnoringCase(effectiveDirective, |
| + ContentSecurityPolicy::FrameAncestors) && |
| + contextFrame)); |
| + |
| + // FIXME: Support sending reports from worker. |
| + Document* document = |
| + contextFrame ? contextFrame->document() : this->document(); |
| + if (!document) |
| + return; |
| + |
| + SecurityPolicyViolationEventInit violationData; |
| + gatherSecurityPolicyViolationEventData( |
| + violationData, document, directiveText, effectiveDirective, blockedURL, |
| + header, redirectStatus, violationType, contextLine); |
| + |
| + // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded |
| + // resources should be allowed regardless. We apparently do, however, so |
| + // we should at least stop spamming reporting endpoints. See |
| + // https://crbug.com/524356 for detail. |
| + if (!violationData.sourceFile().isEmpty() && |
| + SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| + KURL(ParsedURLString, violationData.sourceFile()).protocol())) |
| + return; |
| + |
| + // We need to be careful here when deciding what information to send to the |
| + // report-uri. Currently, we send only the current document's URL and the |
| + // directive that was violated. The document's URL is safe to send because |
| + // it's the document itself that's requesting that it be sent. You could |
| + // make an argument that we shouldn't send HTTPS document URLs to HTTP |
| + // report-uris (for the same reasons that we supress the Referer in that |
| + // case), but the Referer is sent implicitly whereas this request is only |
| + // sent explicitly. As for which directive was violated, that's pretty |
| + // harmless information. |
| + |
| + std::unique_ptr<JSONObject> cspReport = JSONObject::create(); |
| + cspReport->setString("document-uri", violationData.documentURI()); |
| + cspReport->setString("referrer", violationData.referrer()); |
| + cspReport->setString("violated-directive", |
| + violationData.violatedDirective()); |
| + cspReport->setString("effective-directive", |
| + violationData.effectiveDirective()); |
| + cspReport->setString("original-policy", violationData.originalPolicy()); |
| + cspReport->setString("blocked-uri", violationData.blockedURI()); |
| + if (violationData.lineNumber()) |
| + cspReport->setInteger("line-number", violationData.lineNumber()); |
| + if (violationData.columnNumber()) |
| + cspReport->setInteger("column-number", violationData.columnNumber()); |
| + if (!violationData.sourceFile().isEmpty()) |
| + cspReport->setString("source-file", violationData.sourceFile()); |
| + cspReport->setInteger("status-code", violationData.statusCode()); |
| + |
| + std::unique_ptr<JSONObject> reportObject = JSONObject::create(); |
| + reportObject->setObject("csp-report", std::move(cspReport)); |
| + String stringifiedReport = reportObject->toJSONString(); |
| + |
| + if (!shouldSendViolationReport(stringifiedReport)) |
| + return; |
| + didSendViolationReport(stringifiedReport); |
| + |
| + RefPtr<EncodedFormData> report = |
| + EncodedFormData::create(stringifiedReport.utf8()); |
| + |
| + LocalFrame* frame = document->frame(); |
| + if (!frame) |
| + return; |
| + frame->localDOMWindow()->enqueueDocumentEvent( |
| + SecurityPolicyViolationEvent::create( |
| + EventTypeNames::securitypolicyviolation, violationData)); |
| + |
| + for (const String& endpoint : reportEndpoints) { |
| + // If we have a context frame we're dealing with 'frame-ancestors' and we |
| + // don't have our own execution context. Use the frame's document to |
| + // complete the endpoint URL, overriding its URL with the blocked |
| + // document's |
| + // URL. |
| + DCHECK(!contextFrame || !m_executionContext); |
| + DCHECK(!contextFrame || |
| + equalIgnoringCase(effectiveDirective, FrameAncestors)); |
| + KURL url = |
| + contextFrame |
| + ? frame->document()->completeURLWithOverride(endpoint, blockedURL) |
| + : completeURL(endpoint); |
| + PingLoader::sendViolationReport( |
| + frame, url, report, PingLoader::ContentSecurityPolicyViolationReport); |
| + } |
| + } |
| - LocalFrame* frame = document->frame(); |
| - if (!frame) |
| - return; |
| - frame->localDOMWindow()->enqueueDocumentEvent( |
| - SecurityPolicyViolationEvent::create( |
| - EventTypeNames::securitypolicyviolation, violationData)); |
| - |
| - for (const String& endpoint : reportEndpoints) { |
| - // If we have a context frame we're dealing with 'frame-ancestors' and we |
| - // don't have our own execution context. Use the frame's document to |
| - // complete the endpoint URL, overriding its URL with the blocked document's |
| - // URL. |
| - DCHECK(!contextFrame || !m_executionContext); |
| - DCHECK(!contextFrame || |
| - equalIgnoringCase(effectiveDirective, FrameAncestors)); |
| - KURL url = |
| - contextFrame |
| - ? frame->document()->completeURLWithOverride(endpoint, blockedURL) |
| - : completeURL(endpoint); |
| - PingLoader::sendViolationReport( |
| - frame, url, report, PingLoader::ContentSecurityPolicyViolationReport); |
| + void ContentSecurityPolicy::reportMixedContent( |
| + const KURL& mixedURL, |
| + RedirectStatus redirectStatus) { |
| + for (const auto& policy : m_policies) |
| + policy->reportMixedContent(mixedURL, redirectStatus); |
| } |
| -} |
| -void ContentSecurityPolicy::reportMixedContent(const KURL& mixedURL, |
| - RedirectStatus redirectStatus) { |
| - for (const auto& policy : m_policies) |
| - policy->reportMixedContent(mixedURL, redirectStatus); |
| -} |
| + void ContentSecurityPolicy::reportInvalidReferrer( |
| + const String& invalidValue) { |
| + logToConsole( |
| + "The 'referrer' Content Security Policy directive has the invalid " |
| + "value " |
| + "\"" + |
| + invalidValue + |
| + "\". Valid values are \"no-referrer\", \"no-referrer-when-downgrade\", " |
| + "\"origin\", \"origin-when-cross-origin\", and \"unsafe-url\"."); |
| + } |
| -void ContentSecurityPolicy::reportInvalidReferrer(const String& invalidValue) { |
| - logToConsole( |
| - "The 'referrer' Content Security Policy directive has the invalid value " |
| - "\"" + |
| - invalidValue + |
| - "\". Valid values are \"no-referrer\", \"no-referrer-when-downgrade\", " |
| - "\"origin\", \"origin-when-cross-origin\", and \"unsafe-url\"."); |
| -} |
| + void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) { |
| + logToConsole( |
| + "The report-only Content Security Policy '" + header + |
| + "' was delivered via a <meta> element, which is disallowed. The " |
| + "policy has been ignored."); |
| + } |
| -void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) { |
| - logToConsole("The report-only Content Security Policy '" + header + |
| - "' was delivered via a <meta> element, which is disallowed. The " |
| - "policy has been ignored."); |
| -} |
| + void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) { |
| + logToConsole("The Content Security Policy '" + header + |
| + "' was delivered via a <meta> element outside the document's " |
| + "<head>, which is disallowed. The policy has been ignored."); |
| + } |
| -void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) { |
| - logToConsole("The Content Security Policy '" + header + |
| - "' was delivered via a <meta> element outside the document's " |
| - "<head>, which is disallowed. The policy has been ignored."); |
| -} |
| + void ContentSecurityPolicy::reportValueForEmptyDirective( |
| + const String& name, |
| + const String& value) { |
| + logToConsole("The Content Security Policy directive '" + name + |
| + "' should be empty, but was delivered with a value of '" + |
| + value + |
| + "'. The directive has been applied, and the value ignored."); |
| + } |
| -void ContentSecurityPolicy::reportValueForEmptyDirective(const String& name, |
| - const String& value) { |
| - logToConsole("The Content Security Policy directive '" + name + |
| - "' should be empty, but was delivered with a value of '" + |
| - value + |
| - "'. The directive has been applied, and the value ignored."); |
| -} |
| + void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) { |
| + logToConsole("The Content Security Policy directive '" + name + |
| + "' is ignored when delivered in a report-only policy."); |
| + } |
| -void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) { |
| - logToConsole("The Content Security Policy directive '" + name + |
| - "' is ignored when delivered in a report-only policy."); |
| -} |
| + void ContentSecurityPolicy::reportInvalidDirectiveInMeta( |
| + const String& directive) { |
| + logToConsole( |
| + "Content Security Policies delivered via a <meta> element may not " |
| + "contain the " + |
| + directive + " directive."); |
| + } |
| -void ContentSecurityPolicy::reportInvalidDirectiveInMeta( |
| - const String& directive) { |
| - logToConsole( |
| - "Content Security Policies delivered via a <meta> element may not " |
| - "contain the " + |
| - directive + " directive."); |
| -} |
| + void ContentSecurityPolicy::reportUnsupportedDirective(const String& name) { |
| + DEFINE_STATIC_LOCAL(String, allow, ("allow")); |
| + DEFINE_STATIC_LOCAL(String, options, ("options")); |
| + DEFINE_STATIC_LOCAL(String, policyURI, ("policy-uri")); |
| + DEFINE_STATIC_LOCAL(String, allowMessage, |
| + ("The 'allow' directive has been replaced with " |
| + "'default-src'. Please use " |
| + "that directive instead, as 'allow' has no effect.")); |
| + DEFINE_STATIC_LOCAL( |
| + String, optionsMessage, |
| + ("The 'options' directive has been replaced with 'unsafe-inline' and " |
| + "'unsafe-eval' source expressions for the 'script-src' and " |
| + "'style-src' " |
| + "directives. Please use those directives instead, as 'options' has no " |
| + "effect.")); |
| + DEFINE_STATIC_LOCAL(String, policyURIMessage, |
| + ("The 'policy-uri' directive has been removed from the " |
| + "specification. Please specify a complete policy via " |
| + "the Content-Security-Policy header.")); |
| + |
| + String message = |
| + "Unrecognized Content-Security-Policy directive '" + name + "'.\n"; |
| + MessageLevel level = ErrorMessageLevel; |
| + if (equalIgnoringCase(name, allow)) { |
| + message = allowMessage; |
| + } else if (equalIgnoringCase(name, options)) { |
| + message = optionsMessage; |
| + } else if (equalIgnoringCase(name, policyURI)) { |
| + message = policyURIMessage; |
| + } else if (isDirectiveName(name)) { |
| + message = "The Content-Security-Policy directive '" + name + |
| + "' is implemented behind a flag which is currently disabled.\n"; |
| + level = InfoMessageLevel; |
| + } |
| -void ContentSecurityPolicy::reportUnsupportedDirective(const String& name) { |
| - DEFINE_STATIC_LOCAL(String, allow, ("allow")); |
| - DEFINE_STATIC_LOCAL(String, options, ("options")); |
| - DEFINE_STATIC_LOCAL(String, policyURI, ("policy-uri")); |
| - DEFINE_STATIC_LOCAL( |
| - String, allowMessage, |
| - ("The 'allow' directive has been replaced with 'default-src'. Please use " |
| - "that directive instead, as 'allow' has no effect.")); |
| - DEFINE_STATIC_LOCAL( |
| - String, optionsMessage, |
| - ("The 'options' directive has been replaced with 'unsafe-inline' and " |
| - "'unsafe-eval' source expressions for the 'script-src' and 'style-src' " |
| - "directives. Please use those directives instead, as 'options' has no " |
| - "effect.")); |
| - DEFINE_STATIC_LOCAL(String, policyURIMessage, |
| - ("The 'policy-uri' directive has been removed from the " |
| - "specification. Please specify a complete policy via " |
| - "the Content-Security-Policy header.")); |
| - |
| - String message = |
| - "Unrecognized Content-Security-Policy directive '" + name + "'.\n"; |
| - MessageLevel level = ErrorMessageLevel; |
| - if (equalIgnoringCase(name, allow)) { |
| - message = allowMessage; |
| - } else if (equalIgnoringCase(name, options)) { |
| - message = optionsMessage; |
| - } else if (equalIgnoringCase(name, policyURI)) { |
| - message = policyURIMessage; |
| - } else if (isDirectiveName(name)) { |
| - message = "The Content-Security-Policy directive '" + name + |
| - "' is implemented behind a flag which is currently disabled.\n"; |
| - level = InfoMessageLevel; |
| - } |
| - |
| - logToConsole(message, level); |
| -} |
| + logToConsole(message, level); |
| + } |
| -void ContentSecurityPolicy::reportDirectiveAsSourceExpression( |
| - const String& directiveName, |
| - const String& sourceExpression) { |
| - String message = "The Content Security Policy directive '" + directiveName + |
| - "' contains '" + sourceExpression + |
| - "' as a source expression. Did you mean '" + directiveName + |
| - " ...; " + sourceExpression + "...' (note the semicolon)?"; |
| - logToConsole(message); |
| -} |
| + void ContentSecurityPolicy::reportDirectiveAsSourceExpression( |
| + const String& directiveName, |
| + const String& sourceExpression) { |
| + String message = "The Content Security Policy directive '" + directiveName + |
| + "' contains '" + sourceExpression + |
| + "' as a source expression. Did you mean '" + |
| + directiveName + " ...; " + sourceExpression + |
| + "...' (note the semicolon)?"; |
| + logToConsole(message); |
| + } |
| -void ContentSecurityPolicy::reportDuplicateDirective(const String& name) { |
| - String message = |
| - "Ignoring duplicate Content-Security-Policy directive '" + name + "'.\n"; |
| - logToConsole(message); |
| -} |
| + void ContentSecurityPolicy::reportDuplicateDirective(const String& name) { |
| + String message = "Ignoring duplicate Content-Security-Policy directive '" + |
| + name + "'.\n"; |
| + logToConsole(message); |
| + } |
| -void ContentSecurityPolicy::reportInvalidPluginTypes(const String& pluginType) { |
| - String message; |
| - if (pluginType.isNull()) |
| - message = |
| - "'plugin-types' Content Security Policy directive is empty; all " |
| - "plugins will be blocked.\n"; |
| - else if (pluginType == "'none'") |
| - message = |
| - "Invalid plugin type in 'plugin-types' Content Security Policy " |
| - "directive: '" + |
| - pluginType + |
| - "'. Did you mean to set the object-src directive to 'none'?\n"; |
| - else |
| - message = |
| - "Invalid plugin type in 'plugin-types' Content Security Policy " |
| - "directive: '" + |
| - pluginType + "'.\n"; |
| - logToConsole(message); |
| -} |
| + void ContentSecurityPolicy::reportInvalidPluginTypes( |
| + const String& pluginType) { |
| + String message; |
| + if (pluginType.isNull()) { |
| + message = |
| + "'plugin-types' Content Security Policy directive is empty; all " |
| + "plugins will be blocked.\n"; |
| + } else if (pluginType == "'none'") { |
| + message = |
| + "Invalid plugin type in 'plugin-types' Content Security Policy " |
| + "directive: '" + |
| + pluginType + |
| + "'. Did you mean to set the object-src directive to 'none'?\n"; |
| + } else { |
| + message = |
| + "Invalid plugin type in 'plugin-types' Content Security Policy " |
| + "directive: '" + |
| + pluginType + "'.\n"; |
| + } |
| + logToConsole(message); |
| + } |
| -void ContentSecurityPolicy::reportInvalidSandboxFlags( |
| - const String& invalidFlags) { |
| - logToConsole( |
| - "Error while parsing the 'sandbox' Content Security Policy directive: " + |
| - invalidFlags); |
| -} |
| + void ContentSecurityPolicy::reportInvalidSandboxFlags( |
| + const String& invalidFlags) { |
| + logToConsole( |
| + "Error while parsing the 'sandbox' Content Security Policy " |
| + "directive: " + |
| + invalidFlags); |
| + } |
| -void ContentSecurityPolicy::reportInvalidReflectedXSS( |
| - const String& invalidValue) { |
| - logToConsole( |
| - "The 'reflected-xss' Content Security Policy directive has the invalid " |
| - "value \"" + |
| - invalidValue + |
| - "\". Valid values are \"allow\", \"filter\", and \"block\"."); |
| -} |
| + void ContentSecurityPolicy::reportInvalidReflectedXSS( |
| + const String& invalidValue) { |
| + logToConsole( |
| + "The 'reflected-xss' Content Security Policy directive has the invalid " |
| + "value \"" + |
| + invalidValue + |
| + "\". Valid values are \"allow\", \"filter\", and \"block\"."); |
| + } |
| -void ContentSecurityPolicy::reportInvalidRequireSRIForTokens( |
| - const String& invalidTokens) { |
| - logToConsole( |
| - "Error while parsing the 'require-sri-for' Content Security Policy " |
| - "directive: " + |
| - invalidTokens); |
| -} |
| + void ContentSecurityPolicy::reportInvalidRequireSRIForTokens( |
| + const String& invalidTokens) { |
| + logToConsole( |
| + "Error while parsing the 'require-sri-for' Content Security Policy " |
| + "directive: " + |
| + invalidTokens); |
| + } |
| -void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter( |
| - const String& directiveName, |
| - const String& value) { |
| - String message = "The value for Content Security Policy directive '" + |
| - directiveName + "' contains an invalid character: '" + |
| - value + |
| - "'. Non-whitespace characters outside ASCII 0x21-0x7E must " |
| - "be percent-encoded, as described in RFC 3986, section 2.1: " |
| - "http://tools.ietf.org/html/rfc3986#section-2.1."; |
| - logToConsole(message); |
| -} |
| + void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter( |
| + const String& directiveName, |
| + const String& value) { |
| + String message = |
| + "The value for Content Security Policy directive '" + directiveName + |
| + "' contains an invalid character: '" + value + |
| + "'. Non-whitespace characters outside ASCII 0x21-0x7E must " |
| + "be percent-encoded, as described in RFC 3986, section 2.1: " |
| + "http://tools.ietf.org/html/rfc3986#section-2.1."; |
| + logToConsole(message); |
| + } |
| -void ContentSecurityPolicy::reportInvalidPathCharacter( |
| - const String& directiveName, |
| - const String& value, |
| - const char invalidChar) { |
| - ASSERT(invalidChar == '#' || invalidChar == '?'); |
| - |
| - String ignoring = |
| - "The fragment identifier, including the '#', will be ignored."; |
| - if (invalidChar == '?') |
| - ignoring = "The query component, including the '?', will be ignored."; |
| - String message = "The source list for Content Security Policy directive '" + |
| - directiveName + |
| - "' contains a source with an invalid path: '" + value + |
| - "'. " + ignoring; |
| - logToConsole(message); |
| -} |
| + void ContentSecurityPolicy::reportInvalidPathCharacter( |
| + const String& directiveName, |
| + const String& value, |
| + const char invalidChar) { |
| + DCHECK(invalidChar == '#' || invalidChar == '?'); |
| + |
| + String ignoring = |
| + "The fragment identifier, including the '#', will be ignored."; |
| + if (invalidChar == '?') |
| + ignoring = "The query component, including the '?', will be ignored."; |
| + String message = "The source list for Content Security Policy directive '" + |
| + directiveName + |
| + "' contains a source with an invalid path: '" + value + |
| + "'. " + ignoring; |
| + logToConsole(message); |
| + } |
| -void ContentSecurityPolicy::reportInvalidSourceExpression( |
| - const String& directiveName, |
| - const String& source) { |
| - String message = "The source list for Content Security Policy directive '" + |
| - directiveName + "' contains an invalid source: '" + source + |
| - "'. It will be ignored."; |
| - if (equalIgnoringCase(source, "'none'")) |
| - message = message + |
| - " Note that 'none' has no effect unless it is the only " |
| - "expression in the source list."; |
| - logToConsole(message); |
| -} |
| + void ContentSecurityPolicy::reportInvalidSourceExpression( |
| + const String& directiveName, |
| + const String& source) { |
| + String message = "The source list for Content Security Policy directive '" + |
| + directiveName + "' contains an invalid source: '" + |
| + source + "'. It will be ignored."; |
| + if (equalIgnoringCase(source, "'none'")) { |
| + message = message + |
| + " Note that 'none' has no effect unless it is the only " |
| + "expression in the source list."; |
| + } |
| + logToConsole(message); |
| + } |
| -void ContentSecurityPolicy::reportMissingReportURI(const String& policy) { |
| - logToConsole("The Content Security Policy '" + policy + |
| - "' was delivered in report-only mode, but does not specify a " |
| - "'report-uri'; the policy will have no effect. Please either " |
| - "add a 'report-uri' directive, or deliver the policy via the " |
| - "'Content-Security-Policy' header."); |
| -} |
| + void ContentSecurityPolicy::reportMissingReportURI(const String& policy) { |
| + logToConsole("The Content Security Policy '" + policy + |
| + "' was delivered in report-only mode, but does not specify a " |
| + "'report-uri'; the policy will have no effect. Please either " |
| + "add a 'report-uri' directive, or deliver the policy via the " |
| + "'Content-Security-Policy' header."); |
| + } |
| -void ContentSecurityPolicy::logToConsole(const String& message, |
| - MessageLevel level) { |
| - logToConsole(ConsoleMessage::create(SecurityMessageSource, level, message)); |
| -} |
| + void ContentSecurityPolicy::logToConsole(const String& message, |
| + MessageLevel level) { |
| + logToConsole(ConsoleMessage::create(SecurityMessageSource, level, message)); |
| + } |
| -void ContentSecurityPolicy::logToConsole(ConsoleMessage* consoleMessage, |
| - LocalFrame* frame) { |
| - if (frame) |
| - frame->document()->addConsoleMessage(consoleMessage); |
| - else if (m_executionContext) |
| - m_executionContext->addConsoleMessage(consoleMessage); |
| - else |
| - m_consoleMessages.append(consoleMessage); |
| -} |
| + void ContentSecurityPolicy::logToConsole(ConsoleMessage* consoleMessage, |
| + LocalFrame* frame) { |
| + if (frame) |
| + frame->document()->addConsoleMessage(consoleMessage); |
| + else if (m_executionContext) |
| + m_executionContext->addConsoleMessage(consoleMessage); |
| + else |
| + m_consoleMessages.append(consoleMessage); |
| + } |
| -void ContentSecurityPolicy::reportBlockedScriptExecutionToInspector( |
| - const String& directiveText) const { |
| - InspectorInstrumentation::scriptExecutionBlockedByCSP(m_executionContext, |
| - directiveText); |
| -} |
| + void ContentSecurityPolicy::reportBlockedScriptExecutionToInspector( |
| + const String& directiveText) const { |
| + InspectorInstrumentation::scriptExecutionBlockedByCSP(m_executionContext, |
| + directiveText); |
| + } |
| -bool ContentSecurityPolicy::experimentalFeaturesEnabled() const { |
| - return RuntimeEnabledFeatures:: |
| - experimentalContentSecurityPolicyFeaturesEnabled(); |
| -} |
| + bool ContentSecurityPolicy::experimentalFeaturesEnabled() const { |
| + return RuntimeEnabledFeatures:: |
| + experimentalContentSecurityPolicyFeaturesEnabled(); |
| + } |
| -bool ContentSecurityPolicy::shouldSendCSPHeader(Resource::Type type) const { |
| - for (const auto& policy : m_policies) { |
| - if (policy->shouldSendCSPHeader(type)) |
| - return true; |
| + bool ContentSecurityPolicy::shouldSendCSPHeader(Resource::Type type) const { |
| + for (const auto& policy : m_policies) { |
| + if (policy->shouldSendCSPHeader(type)) |
| + return true; |
| + } |
| + return false; |
| } |
| - return false; |
| -} |
| -bool ContentSecurityPolicy::urlMatchesSelf(const KURL& url) const { |
| - return m_selfSource->matches(url, RedirectStatus::NoRedirect); |
| -} |
| + bool ContentSecurityPolicy::urlMatchesSelf(const KURL& url) const { |
| + return m_selfSource->matches(url, RedirectStatus::NoRedirect); |
| + } |
| -bool ContentSecurityPolicy::protocolMatchesSelf(const KURL& url) const { |
| - if (equalIgnoringCase("http", m_selfProtocol)) |
| - return url.protocolIsInHTTPFamily(); |
| - return equalIgnoringCase(url.protocol(), m_selfProtocol); |
| -} |
| + bool ContentSecurityPolicy::protocolMatchesSelf(const KURL& url) const { |
| + if (equalIgnoringCase("http", m_selfProtocol)) |
| + return url.protocolIsInHTTPFamily(); |
| + return equalIgnoringCase(url.protocol(), m_selfProtocol); |
| + } |
| -bool ContentSecurityPolicy::selfMatchesInnerURL() const { |
| - // Due to backwards-compatibility concerns, we allow 'self' to match blob and |
| - // filesystem URLs if we're in a context that bypasses Content Security Policy |
| - // in the main world. |
| - // |
| - // TODO(mkwst): Revisit this once embedders have an opportunity to update |
| - // their extension models. |
| - return m_executionContext && |
| - SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| - m_executionContext->getSecurityOrigin()->protocol()); |
| -} |
| + bool ContentSecurityPolicy::selfMatchesInnerURL() const { |
| + // Due to backwards-compatibility concerns, we allow 'self' to match blob |
| + // and |
| + // filesystem URLs if we're in a context that bypasses Content Security |
| + // Policy |
| + // in the main world. |
| + // |
| + // TODO(mkwst): Revisit this once embedders have an opportunity to update |
| + // their extension models. |
| + return m_executionContext && |
| + SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
| + m_executionContext->getSecurityOrigin()->protocol()); |
| + } |
| -bool ContentSecurityPolicy::shouldBypassMainWorld( |
| - const ExecutionContext* context) { |
| - if (context && context->isDocument()) { |
| - const Document* document = toDocument(context); |
| - if (document->frame()) |
| - return document->frame()->script().shouldBypassMainWorldCSP(); |
| + bool ContentSecurityPolicy::shouldBypassMainWorld( |
| + const ExecutionContext* context) { |
| + if (context && context->isDocument()) { |
| + const Document* document = toDocument(context); |
| + if (document->frame()) |
| + return document->frame()->script().shouldBypassMainWorldCSP(); |
| + } |
| + return false; |
| } |
| - return false; |
| -} |
| -bool ContentSecurityPolicy::shouldSendViolationReport( |
| - const String& report) const { |
| - // Collisions have no security impact, so we can save space by storing only |
| - // the string's hash rather than the whole report. |
| - return !m_violationReportsSent.contains(report.impl()->hash()); |
| -} |
| + bool ContentSecurityPolicy::shouldSendViolationReport( |
| + const String& report) const { |
| + // Collisions have no security impact, so we can save space by storing only |
| + // the string's hash rather than the whole report. |
| + return !m_violationReportsSent.contains(report.impl()->hash()); |
| + } |
| -void ContentSecurityPolicy::didSendViolationReport(const String& report) { |
| - m_violationReportsSent.add(report.impl()->hash()); |
| -} |
| + void ContentSecurityPolicy::didSendViolationReport(const String& report) { |
| + m_violationReportsSent.add(report.impl()->hash()); |
| + } |
| } // namespace blink |