1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/frame/csp/CSPDirectiveList.h"
8 #include "core/frame/LocalFrame.h"
9 #include "platform/ParsingUtilities.h"
10 #include "platform/weborigin/KURL.h"
11 #include "wtf/text/WTFString.h"
15 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source)
18 , m_headerSource(source)
20 , m_haveSandboxPolicy(false)
21 , m_reflectedXSSDisposition(ReflectedXSSUnset)
22 , m_didSetReferrerPolicy(false)
23 , m_referrerPolicy(ReferrerPolicyDefault)
25 m_reportOnly = type == ContentSecurityPolicyHeaderTypeReport;
28 PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* policy, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source)
30 OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy, type, source));
31 directives->parse(begin, end);
33 if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
34 String message = "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_scriptSrc.get())->text() + "\".\n";
35 directives->setEvalDisabledErrorMessage(message);
38 if (directives->isReportOnly() && directives->reportURIs().isEmpty())
39 policy->reportMissingReportURI(String(begin, end - begin));
41 return directives.release();
44 void CSPDirectiveList::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL) const
46 String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
47 m_policy->client()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message);
48 m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header);
51 void CSPDirectiveList::reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const
53 String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
54 m_policy->client()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message, contextURL, contextLine.oneBasedInt());
55 m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header);
58 void CSPDirectiveList::reportViolationWithState(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptState* state) const
60 String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
61 m_policy->client()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message, state);
62 m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header);
65 bool CSPDirectiveList::checkEval(SourceListDirective* directive) const
67 return !directive || directive->allowEval();
70 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
72 return !directive || (directive->allowInline() && !directive->isHashOrNoncePresent());
75 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const
77 return !directive || directive->allowNonce(nonce);
80 bool CSPDirectiveList::checkHash(SourceListDirective* directive, const CSPHashValue& hashValue) const
82 return !directive || directive->allowHash(hashValue);
85 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& url) const
87 return !directive || directive->allows(url);
90 bool CSPDirectiveList::checkAncestors(SourceListDirective* directive, LocalFrame* frame) const
92 if (!frame || !directive)
95 for (LocalFrame* current = frame->tree().parent(); current; current = current->tree().parent()) {
96 if (!directive->allows(current->document()->url()))
102 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const
106 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
108 return directive->allows(type);
111 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive) const
113 return directive ? directive : m_defaultSrc.get();
116 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive, SourceListDirective* override) const
118 return directive ? directive : override;
121 bool CSPDirectiveList::checkEvalAndReportViolation(SourceListDirective* directive, const String& consoleMessage, ScriptState* state) const
123 if (checkEval(directive))
126 String suffix = String();
127 if (directive == m_defaultSrc)
128 suffix = " Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.";
130 reportViolationWithState(directive->text(), ContentSecurityPolicy::ScriptSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), state);
132 m_policy->reportBlockedScriptExecutionToInspector(directive->text());
138 bool CSPDirectiveList::checkMediaTypeAndReportViolation(MediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const
140 if (checkMediaType(directive, type, typeAttribute))
143 String message = consoleMessage + "\'" + directive->text() + "\'.";
144 if (typeAttribute.isEmpty())
145 message = message + " When enforcing the 'plugin-types' directive, the plugin's media type must be explicitly declared with a 'type' attribute on the containing element (e.g. '<object type=\"[TYPE GOES HERE]\" ...>').";
147 reportViolation(directive->text(), ContentSecurityPolicy::PluginTypes, message + "\n", KURL());
148 return denyIfEnforcingPolicy();
151 bool CSPDirectiveList::checkInlineAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const
153 if (checkInline(directive))
156 String suffix = String();
157 if (directive->allowInline() && directive->isHashOrNoncePresent()) {
158 // If inline is allowed, but a hash or nonce is present, we ignore 'unsafe-inline'. Throw a reasonable error.
159 suffix = " Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.";
161 suffix = " Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.";
162 if (directive == m_defaultSrc)
163 suffix = suffix + " Note also that '" + String(isScript ? "script" : "style") + "-src' was not explicitly set, so 'default-src' is used as a fallback.";
166 reportViolationWithLocation(directive->text(), isScript ? ContentSecurityPolicy::ScriptSrc : ContentSecurityPolicy::StyleSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), contextURL, contextLine);
170 m_policy->reportBlockedScriptExecutionToInspector(directive->text());
176 bool CSPDirectiveList::checkSourceAndReportViolation(SourceListDirective* directive, const KURL& url, const String& effectiveDirective) const
178 if (checkSource(directive, url))
182 if (ContentSecurityPolicy::BaseURI == effectiveDirective)
183 prefix = "Refused to set the document's base URI to '";
184 else if (ContentSecurityPolicy::ChildSrc == effectiveDirective)
185 prefix = "Refused to create a child context containing '";
186 else if (ContentSecurityPolicy::ConnectSrc == effectiveDirective)
187 prefix = "Refused to connect to '";
188 else if (ContentSecurityPolicy::FontSrc == effectiveDirective)
189 prefix = "Refused to load the font '";
190 else if (ContentSecurityPolicy::FormAction == effectiveDirective)
191 prefix = "Refused to send form data to '";
192 else if (ContentSecurityPolicy::FrameSrc == effectiveDirective)
193 prefix = "Refused to frame '";
194 else if (ContentSecurityPolicy::ImgSrc == effectiveDirective)
195 prefix = "Refused to load the image '";
196 else if (ContentSecurityPolicy::MediaSrc == effectiveDirective)
197 prefix = "Refused to load media from '";
198 else if (ContentSecurityPolicy::ObjectSrc == effectiveDirective)
199 prefix = "Refused to load plugin data from '";
200 else if (ContentSecurityPolicy::ScriptSrc == effectiveDirective)
201 prefix = "Refused to load the script '";
202 else if (ContentSecurityPolicy::StyleSrc == effectiveDirective)
203 prefix = "Refused to load the stylesheet '";
205 String suffix = String();
206 if (directive == m_defaultSrc)
207 suffix = " Note that '" + effectiveDirective + "' was not explicitly set, so 'default-src' is used as a fallback.";
209 reportViolation(directive->text(), effectiveDirective, prefix + url.elidedString() + "' because it violates the following Content Security Policy directive: \"" + directive->text() + "\"." + suffix + "\n", url);
210 return denyIfEnforcingPolicy();
213 bool CSPDirectiveList::checkAncestorsAndReportViolation(SourceListDirective* directive, LocalFrame* frame) const
215 if (checkAncestors(directive, frame))
218 reportViolation(directive->text(), "frame-ancestors", "Refused to display '" + frame->document()->url().elidedString() + " in a frame because an ancestor violates the following Content Security Policy directive: \"" + directive->text() + "\".", frame->document()->url());
219 return denyIfEnforcingPolicy();
222 bool CSPDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
224 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: "));
225 if (reportingStatus == ContentSecurityPolicy::SendReport)
226 return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true);
228 return checkInline(operativeDirective(m_scriptSrc.get()));
231 bool CSPDirectiveList::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
233 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline event handler because it violates the following Content Security Policy directive: "));
234 if (reportingStatus == ContentSecurityPolicy::SendReport)
235 return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true);
236 return checkInline(operativeDirective(m_scriptSrc.get()));
239 bool CSPDirectiveList::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
241 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline script because it violates the following Content Security Policy directive: "));
242 return reportingStatus == ContentSecurityPolicy::SendReport ?
243 checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true) :
244 checkInline(operativeDirective(m_scriptSrc.get()));
247 bool CSPDirectiveList::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
249 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to apply inline style because it violates the following Content Security Policy directive: "));
250 return reportingStatus == ContentSecurityPolicy::SendReport ?
251 checkInlineAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, contextURL, contextLine, false) :
252 checkInline(operativeDirective(m_styleSrc.get()));
255 bool CSPDirectiveList::allowEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
257 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "));
259 return reportingStatus == ContentSecurityPolicy::SendReport ?
260 checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, state) :
261 checkEval(operativeDirective(m_scriptSrc.get()));
264 bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
266 return reportingStatus == ContentSecurityPolicy::SendReport ?
267 checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.elidedString() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ") :
268 checkMediaType(m_pluginTypes.get(), type, typeAttribute);
271 bool CSPDirectiveList::allowScriptFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
273 return reportingStatus == ContentSecurityPolicy::SendReport ?
274 checkSourceAndReportViolation(operativeDirective(m_scriptSrc.get()), url, ContentSecurityPolicy::ScriptSrc) :
275 checkSource(operativeDirective(m_scriptSrc.get()), url);
278 bool CSPDirectiveList::allowObjectFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
280 if (url.isBlankURL())
282 return reportingStatus == ContentSecurityPolicy::SendReport ?
283 checkSourceAndReportViolation(operativeDirective(m_objectSrc.get()), url, ContentSecurityPolicy::ObjectSrc) :
284 checkSource(operativeDirective(m_objectSrc.get()), url);
287 bool CSPDirectiveList::allowChildFrameFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
289 if (url.isBlankURL())
292 // 'frame-src' is the only directive which overrides something other than the default sources.
293 // It overrides 'child-src', which overrides the default sources. So, we do this nested set
294 // of calls to 'operativeDirective()' to grab 'frame-src' if it exists, 'child-src' if it
295 // doesn't, and 'defaut-src' if neither are available.
297 // All of this only applies, of course, if we're in CSP 1.1. In CSP 1.0, 'frame-src'
298 // overrides 'default-src' directly.
299 SourceListDirective* whichDirective = m_policy->experimentalFeaturesEnabled() ?
300 operativeDirective(m_frameSrc.get(), operativeDirective(m_childSrc.get())) :
301 operativeDirective(m_frameSrc.get());
303 return reportingStatus == ContentSecurityPolicy::SendReport ?
304 checkSourceAndReportViolation(whichDirective, url, ContentSecurityPolicy::FrameSrc) :
305 checkSource(whichDirective, url);
308 bool CSPDirectiveList::allowImageFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
310 return reportingStatus == ContentSecurityPolicy::SendReport ?
311 checkSourceAndReportViolation(operativeDirective(m_imgSrc.get()), url, ContentSecurityPolicy::ImgSrc) :
312 checkSource(operativeDirective(m_imgSrc.get()), url);
315 bool CSPDirectiveList::allowStyleFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
317 return reportingStatus == ContentSecurityPolicy::SendReport ?
318 checkSourceAndReportViolation(operativeDirective(m_styleSrc.get()), url, ContentSecurityPolicy::StyleSrc) :
319 checkSource(operativeDirective(m_styleSrc.get()), url);
322 bool CSPDirectiveList::allowFontFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
324 return reportingStatus == ContentSecurityPolicy::SendReport ?
325 checkSourceAndReportViolation(operativeDirective(m_fontSrc.get()), url, ContentSecurityPolicy::FontSrc) :
326 checkSource(operativeDirective(m_fontSrc.get()), url);
329 bool CSPDirectiveList::allowMediaFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
331 return reportingStatus == ContentSecurityPolicy::SendReport ?
332 checkSourceAndReportViolation(operativeDirective(m_mediaSrc.get()), url, ContentSecurityPolicy::MediaSrc) :
333 checkSource(operativeDirective(m_mediaSrc.get()), url);
336 bool CSPDirectiveList::allowConnectToSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
338 return reportingStatus == ContentSecurityPolicy::SendReport ?
339 checkSourceAndReportViolation(operativeDirective(m_connectSrc.get()), url, ContentSecurityPolicy::ConnectSrc) :
340 checkSource(operativeDirective(m_connectSrc.get()), url);
343 bool CSPDirectiveList::allowFormAction(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
345 return reportingStatus == ContentSecurityPolicy::SendReport ?
346 checkSourceAndReportViolation(m_formAction.get(), url, ContentSecurityPolicy::FormAction) :
347 checkSource(m_formAction.get(), url);
350 bool CSPDirectiveList::allowBaseURI(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
352 return reportingStatus == ContentSecurityPolicy::SendReport ?
353 checkSourceAndReportViolation(m_baseURI.get(), url, ContentSecurityPolicy::BaseURI) :
354 checkSource(m_baseURI.get(), url);
357 bool CSPDirectiveList::allowAncestors(LocalFrame* frame, ContentSecurityPolicy::ReportingStatus reportingStatus) const
359 return reportingStatus == ContentSecurityPolicy::SendReport ?
360 checkAncestorsAndReportViolation(m_frameAncestors.get(), frame) :
361 checkAncestors(m_frameAncestors.get(), frame);
364 bool CSPDirectiveList::allowChildContextFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
366 return reportingStatus == ContentSecurityPolicy::SendReport ?
367 checkSourceAndReportViolation(operativeDirective(m_childSrc.get()), url, ContentSecurityPolicy::ChildSrc) :
368 checkSource(operativeDirective(m_childSrc.get()), url);
371 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const
373 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
376 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const
378 return checkNonce(operativeDirective(m_styleSrc.get()), nonce);
381 bool CSPDirectiveList::allowScriptHash(const CSPHashValue& hashValue) const
383 return checkHash(operativeDirective(m_scriptSrc.get()), hashValue);
386 bool CSPDirectiveList::allowStyleHash(const CSPHashValue& hashValue) const
388 return checkHash(operativeDirective(m_styleSrc.get()), hashValue);
391 // policy = directive-list
392 // directive-list = [ directive *( ";" [ directive ] ) ]
394 void CSPDirectiveList::parse(const UChar* begin, const UChar* end)
396 m_header = String(begin, end - begin);
401 const UChar* position = begin;
402 while (position < end) {
403 const UChar* directiveBegin = position;
404 skipUntil<UChar>(position, end, ';');
407 if (parseDirective(directiveBegin, position, name, value)) {
408 ASSERT(!name.isEmpty());
409 addDirective(name, value);
412 ASSERT(position == end || *position == ';');
413 skipExactly<UChar>(position, end, ';');
417 // directive = *WSP [ directive-name [ WSP directive-value ] ]
418 // directive-name = 1*( ALPHA / DIGIT / "-" )
419 // directive-value = *( WSP / <VCHAR except ";"> )
421 bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value)
423 ASSERT(name.isEmpty());
424 ASSERT(value.isEmpty());
426 const UChar* position = begin;
427 skipWhile<UChar, isASCIISpace>(position, end);
429 // Empty directive (e.g. ";;;"). Exit early.
433 const UChar* nameBegin = position;
434 skipWhile<UChar, isCSPDirectiveNameCharacter>(position, end);
436 // The directive-name must be non-empty.
437 if (nameBegin == position) {
438 skipWhile<UChar, isNotASCIISpace>(position, end);
439 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin));
443 name = String(nameBegin, position - nameBegin);
448 if (!skipExactly<UChar, isASCIISpace>(position, end)) {
449 skipWhile<UChar, isNotASCIISpace>(position, end);
450 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin));
454 skipWhile<UChar, isASCIISpace>(position, end);
456 const UChar* valueBegin = position;
457 skipWhile<UChar, isCSPDirectiveValueCharacter>(position, end);
459 if (position != end) {
460 m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin));
464 // The directive-value may be empty.
465 if (valueBegin == position)
468 value = String(valueBegin, position - valueBegin);
472 void CSPDirectiveList::parseReportURI(const String& name, const String& value)
474 if (!m_reportURIs.isEmpty()) {
475 m_policy->reportDuplicateDirective(name);
479 Vector<UChar> characters;
480 value.appendTo(characters);
482 const UChar* position = characters.data();
483 const UChar* end = position + characters.size();
485 while (position < end) {
486 skipWhile<UChar, isASCIISpace>(position, end);
488 const UChar* urlBegin = position;
489 skipWhile<UChar, isNotASCIISpace>(position, end);
491 if (urlBegin < position) {
492 String url = String(urlBegin, position - urlBegin);
493 m_reportURIs.append(m_policy->completeURL(url));
499 template<class CSPDirectiveType>
500 void CSPDirectiveList::setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>& directive)
503 m_policy->reportDuplicateDirective(name);
506 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy));
509 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy)
512 m_policy->reportInvalidInReportOnly(name);
515 if (m_haveSandboxPolicy) {
516 m_policy->reportDuplicateDirective(name);
519 m_haveSandboxPolicy = true;
520 String invalidTokens;
521 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidTokens));
522 if (!invalidTokens.isNull())
523 m_policy->reportInvalidSandboxFlags(invalidTokens);
526 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value)
528 if (m_reflectedXSSDisposition != ReflectedXSSUnset) {
529 m_policy->reportDuplicateDirective(name);
530 m_reflectedXSSDisposition = ReflectedXSSInvalid;
534 if (value.isEmpty()) {
535 m_reflectedXSSDisposition = ReflectedXSSInvalid;
536 m_policy->reportInvalidReflectedXSS(value);
540 Vector<UChar> characters;
541 value.appendTo(characters);
543 const UChar* position = characters.data();
544 const UChar* end = position + characters.size();
546 skipWhile<UChar, isASCIISpace>(position, end);
547 const UChar* begin = position;
548 skipWhile<UChar, isNotASCIISpace>(position, end);
552 if (equalIgnoringCase("allow", begin, position - begin)) {
553 m_reflectedXSSDisposition = AllowReflectedXSS;
554 } else if (equalIgnoringCase("filter", begin, position - begin)) {
555 m_reflectedXSSDisposition = FilterReflectedXSS;
556 } else if (equalIgnoringCase("block", begin, position - begin)) {
557 m_reflectedXSSDisposition = BlockReflectedXSS;
559 m_reflectedXSSDisposition = ReflectedXSSInvalid;
560 m_policy->reportInvalidReflectedXSS(value);
564 skipWhile<UChar, isASCIISpace>(position, end);
565 if (position == end && m_reflectedXSSDisposition != ReflectedXSSUnset)
570 m_reflectedXSSDisposition = ReflectedXSSInvalid;
571 m_policy->reportInvalidReflectedXSS(value);
574 void CSPDirectiveList::parseReferrer(const String& name, const String& value)
576 if (m_didSetReferrerPolicy) {
577 m_policy->reportDuplicateDirective(name);
578 m_referrerPolicy = ReferrerPolicyNever;
582 m_didSetReferrerPolicy = true;
584 if (value.isEmpty()) {
585 m_policy->reportInvalidReferrer(value);
586 m_referrerPolicy = ReferrerPolicyNever;
590 Vector<UChar> characters;
591 value.appendTo(characters);
593 const UChar* position = characters.data();
594 const UChar* end = position + characters.size();
596 skipWhile<UChar, isASCIISpace>(position, end);
597 const UChar* begin = position;
598 skipWhile<UChar, isNotASCIISpace>(position, end);
602 if (equalIgnoringCase("always", begin, position - begin)) {
603 m_referrerPolicy = ReferrerPolicyAlways;
604 } else if (equalIgnoringCase("default", begin, position - begin)) {
605 m_referrerPolicy = ReferrerPolicyDefault;
606 } else if (equalIgnoringCase("never", begin, position - begin)) {
607 m_referrerPolicy = ReferrerPolicyNever;
608 } else if (equalIgnoringCase("origin", begin, position - begin)) {
609 m_referrerPolicy = ReferrerPolicyOrigin;
611 m_referrerPolicy = ReferrerPolicyNever;
612 m_policy->reportInvalidReferrer(value);
616 skipWhile<UChar, isASCIISpace>(position, end);
622 m_referrerPolicy = ReferrerPolicyNever;
623 m_policy->reportInvalidReferrer(value);
627 void CSPDirectiveList::addDirective(const String& name, const String& value)
629 ASSERT(!name.isEmpty());
631 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) {
632 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc);
633 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) {
634 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc);
635 m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed());
636 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ObjectSrc)) {
637 setCSPDirective<SourceListDirective>(name, value, m_objectSrc);
638 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FrameSrc)) {
639 setCSPDirective<SourceListDirective>(name, value, m_frameSrc);
640 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ImgSrc)) {
641 setCSPDirective<SourceListDirective>(name, value, m_imgSrc);
642 } else if (equalIgnoringCase(name, ContentSecurityPolicy::StyleSrc)) {
643 setCSPDirective<SourceListDirective>(name, value, m_styleSrc);
644 m_policy->usesStyleHashAlgorithms(m_styleSrc->hashAlgorithmsUsed());
645 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FontSrc)) {
646 setCSPDirective<SourceListDirective>(name, value, m_fontSrc);
647 } else if (equalIgnoringCase(name, ContentSecurityPolicy::MediaSrc)) {
648 setCSPDirective<SourceListDirective>(name, value, m_mediaSrc);
649 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ConnectSrc)) {
650 setCSPDirective<SourceListDirective>(name, value, m_connectSrc);
651 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Sandbox)) {
652 applySandboxPolicy(name, value);
653 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReportURI)) {
654 parseReportURI(name, value);
655 } else if (m_policy->experimentalFeaturesEnabled()) {
656 if (equalIgnoringCase(name, ContentSecurityPolicy::BaseURI))
657 setCSPDirective<SourceListDirective>(name, value, m_baseURI);
658 else if (equalIgnoringCase(name, ContentSecurityPolicy::ChildSrc))
659 setCSPDirective<SourceListDirective>(name, value, m_childSrc);
660 else if (equalIgnoringCase(name, ContentSecurityPolicy::FormAction))
661 setCSPDirective<SourceListDirective>(name, value, m_formAction);
662 else if (equalIgnoringCase(name, ContentSecurityPolicy::FrameAncestors))
663 setCSPDirective<SourceListDirective>(name, value, m_frameAncestors);
664 else if (equalIgnoringCase(name, ContentSecurityPolicy::PluginTypes))
665 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes);
666 else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS))
667 parseReflectedXSS(name, value);
668 else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer))
669 parseReferrer(name, value);
671 m_policy->reportUnsupportedDirective(name);
673 m_policy->reportUnsupportedDirective(name);
678 } // namespace WebCore