CSP: Extract helper classes into their own files
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Feb 2016 01:21:18 +0000 (01:21 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Feb 2016 01:21:18 +0000 (01:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=154040
<rdar://problem/24571189>

Reviewed by Brent Fulgham.

No functionality was changed. So, no new tests.

* CMakeLists.txt: Add files ContentSecurityPolicy{DirectiveList, MediaListDirective, Source, SourceList, SourceListDirective}.cpp.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* page/csp/ContentSecurityPolicy.cpp: Clean up #includes. Include header ParsingUtilities.h so that we can remove our own
variants of skip{Exactly, Until, While}(). Update code as necessary for class renames.
(WebCore::skipExactly): Deleted; instead use the analogous function in ParsingUtilities.h.
(WebCore::skipUntil): Deleted; instead use the analogous function in ParsingUtilities.h.
(WebCore::skipWhile): Deleted; instead use the analogous function in ParsingUtilities.h.
(WebCore::isSourceListNone): Moved to file ContentSecurityPolicySourceList.cpp.
(WebCore::CSPSource): Deleted; moved implementation to files ContentSecurityPolicySource.{cpp, h}.
(WebCore::CSPSourceList): Deleted; moved implementation to files ContentSecurityPolicySourceList.{cpp, h}.
(WebCore::CSPDirective): Deleted; moved implementation to file ContentSecurityPolicyDirective.h.
(WebCore::MediaListDirective): Deleted; moved implementation to files ContentSecurityPolicyMediaListDirective.{cpp, h}.
(WebCore::SourceListDirective): Deleted; moved implementation to files ContentSecurityPolicySourceListDirective.{cpp, h}.
(WebCore::CSPDirectiveList): Deleted; moved implementation to files ContentSecurityPolicyDirectiveList.{cpp, h}.
* page/csp/ContentSecurityPolicy.h:
* page/csp/ContentSecurityPolicyDirective.h: Added.
* page/csp/ContentSecurityPolicyDirectiveList.cpp: Added; removed use of ternary operator where it made the code less readable.
Updated code to make use of the functions defined in ParsingUtilities.h.
(WebCore::isExperimentalDirectiveName): Moved from file ContentSecurityPolicy.cpp.
(WebCore::isCSPDirectiveName): Ditto.
(WebCore::isDirectiveNameCharacter): Ditto.
(WebCore::isDirectiveValueCharacter): Ditto.
(WebCore::isNotASCIISpace): Ditto.
* page/csp/ContentSecurityPolicyDirectiveList.h: Added.
* page/csp/ContentSecurityPolicyMediaListDirective.cpp: Added. Updated code to make use of the functions defined in ParsingUtilities.h.
(WebCore::isMediaTypeCharacter): Moved from file ContentSecurityPolicy.cpp.
(WebCore::isNotASCIISpace): Ditto.
* page/csp/ContentSecurityPolicyMediaListDirective.h: Added.
* page/csp/ContentSecurityPolicySource.cpp: Added.
* page/csp/ContentSecurityPolicySource.h: Added.
* page/csp/ContentSecurityPolicySourceList.cpp: Added. Updated code to make use of the functions defined in ParsingUtilities.h.
(WebCore::isSourceCharacter): Moved from file ContentSecurityPolicy.cpp.
(WebCore::isHostCharacter): Ditto.
(WebCore::isPathComponentCharacter): Ditto.
(WebCore::isSchemeContinuationCharacter): Ditto.
(WebCore::isNotColonOrSlash): Ditto.
(WebCore::isSourceListNone): Ditto.
* page/csp/ContentSecurityPolicySourceList.h: Added.
* page/csp/ContentSecurityPolicySourceListDirective.cpp: Added.
* page/csp/ContentSecurityPolicySourceListDirective.h: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@196350 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/page/csp/ContentSecurityPolicy.cpp
Source/WebCore/page/csp/ContentSecurityPolicy.h
Source/WebCore/page/csp/ContentSecurityPolicyDirective.h [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.cpp [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.h [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicySource.cpp [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicySource.h [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicySourceList.h [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h [new file with mode: 0644]

index 9593727..868825f 100644 (file)
@@ -2073,7 +2073,12 @@ set(WebCore_SOURCES
     page/animation/KeyframeAnimation.cpp
 
     page/csp/ContentSecurityPolicy.cpp
+    page/csp/ContentSecurityPolicyDirectiveList.cpp
+    page/csp/ContentSecurityPolicyMediaListDirective.cpp
     page/csp/ContentSecurityPolicyResponseHeaders.cpp
+    page/csp/ContentSecurityPolicySource.cpp
+    page/csp/ContentSecurityPolicySourceList.cpp
+    page/csp/ContentSecurityPolicySourceListDirective.cpp
 
     page/scrolling/AxisScrollSnapOffsets.cpp
     page/scrolling/ScrollLatchingState.cpp
index a61e588..5e394c9 100644 (file)
@@ -1,3 +1,54 @@
+2016-02-09  Daniel Bates  <dabates@apple.com>
+
+        CSP: Extract helper classes into their own files
+        https://bugs.webkit.org/show_bug.cgi?id=154040
+        <rdar://problem/24571189>
+
+        Reviewed by Brent Fulgham.
+
+        No functionality was changed. So, no new tests.
+
+        * CMakeLists.txt: Add files ContentSecurityPolicy{DirectiveList, MediaListDirective, Source, SourceList, SourceListDirective}.cpp.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * page/csp/ContentSecurityPolicy.cpp: Clean up #includes. Include header ParsingUtilities.h so that we can remove our own
+        variants of skip{Exactly, Until, While}(). Update code as necessary for class renames.
+        (WebCore::skipExactly): Deleted; instead use the analogous function in ParsingUtilities.h.
+        (WebCore::skipUntil): Deleted; instead use the analogous function in ParsingUtilities.h.
+        (WebCore::skipWhile): Deleted; instead use the analogous function in ParsingUtilities.h.
+        (WebCore::isSourceListNone): Moved to file ContentSecurityPolicySourceList.cpp.
+        (WebCore::CSPSource): Deleted; moved implementation to files ContentSecurityPolicySource.{cpp, h}.
+        (WebCore::CSPSourceList): Deleted; moved implementation to files ContentSecurityPolicySourceList.{cpp, h}.
+        (WebCore::CSPDirective): Deleted; moved implementation to file ContentSecurityPolicyDirective.h.
+        (WebCore::MediaListDirective): Deleted; moved implementation to files ContentSecurityPolicyMediaListDirective.{cpp, h}.
+        (WebCore::SourceListDirective): Deleted; moved implementation to files ContentSecurityPolicySourceListDirective.{cpp, h}.
+        (WebCore::CSPDirectiveList): Deleted; moved implementation to files ContentSecurityPolicyDirectiveList.{cpp, h}.
+        * page/csp/ContentSecurityPolicy.h:
+        * page/csp/ContentSecurityPolicyDirective.h: Added.
+        * page/csp/ContentSecurityPolicyDirectiveList.cpp: Added; removed use of ternary operator where it made the code less readable.
+        Updated code to make use of the functions defined in ParsingUtilities.h.
+        (WebCore::isExperimentalDirectiveName): Moved from file ContentSecurityPolicy.cpp.
+        (WebCore::isCSPDirectiveName): Ditto.
+        (WebCore::isDirectiveNameCharacter): Ditto.
+        (WebCore::isDirectiveValueCharacter): Ditto.
+        (WebCore::isNotASCIISpace): Ditto.
+        * page/csp/ContentSecurityPolicyDirectiveList.h: Added.
+        * page/csp/ContentSecurityPolicyMediaListDirective.cpp: Added. Updated code to make use of the functions defined in ParsingUtilities.h.
+        (WebCore::isMediaTypeCharacter): Moved from file ContentSecurityPolicy.cpp.
+        (WebCore::isNotASCIISpace): Ditto.
+        * page/csp/ContentSecurityPolicyMediaListDirective.h: Added.
+        * page/csp/ContentSecurityPolicySource.cpp: Added.
+        * page/csp/ContentSecurityPolicySource.h: Added.
+        * page/csp/ContentSecurityPolicySourceList.cpp: Added. Updated code to make use of the functions defined in ParsingUtilities.h.
+        (WebCore::isSourceCharacter): Moved from file ContentSecurityPolicy.cpp.
+        (WebCore::isHostCharacter): Ditto.
+        (WebCore::isPathComponentCharacter): Ditto.
+        (WebCore::isSchemeContinuationCharacter): Ditto.
+        (WebCore::isNotColonOrSlash): Ditto.
+        (WebCore::isSourceListNone): Ditto.
+        * page/csp/ContentSecurityPolicySourceList.h: Added.
+        * page/csp/ContentSecurityPolicySourceListDirective.cpp: Added.
+        * page/csp/ContentSecurityPolicySourceListDirective.h: Added.
+
 2016-02-09  Brady Eidson  <beidson@apple.com>
 
         Modern IDB: TransactionOperation objects leak.
index d39dcec..27ca1da 100644 (file)
                CE12525B1A1C018200864480 /* CFNetworkSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CE12525A1A1C018200864480 /* CFNetworkSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE6DADF91C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6DADF71C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp */; };
                CE6DADFA1C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6DADF81C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h */; };
+               CE799F971C6A46BC0097B518 /* ContentSecurityPolicySourceList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE799F951C6A46BC0097B518 /* ContentSecurityPolicySourceList.cpp */; };
+               CE799F981C6A46BC0097B518 /* ContentSecurityPolicySourceList.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799F961C6A46BC0097B518 /* ContentSecurityPolicySourceList.h */; };
+               CE799F9B1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE799F991C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.cpp */; };
+               CE799F9C1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799F9A1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.h */; };
+               CE799F9F1C6A4C160097B518 /* ContentSecurityPolicySource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE799F9D1C6A4C160097B518 /* ContentSecurityPolicySource.cpp */; };
+               CE799FA01C6A4C160097B518 /* ContentSecurityPolicySource.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799F9E1C6A4C160097B518 /* ContentSecurityPolicySource.h */; };
+               CE799FA41C6A503A0097B518 /* ContentSecurityPolicyDirective.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799FA21C6A503A0097B518 /* ContentSecurityPolicyDirective.h */; };
+               CE799FA71C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE799FA51C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.cpp */; };
+               CE799FA81C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799FA61C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.h */; };
+               CE799FAB1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE799FA91C6A50660097B518 /* ContentSecurityPolicySourceListDirective.cpp */; };
+               CE799FAC1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799FAA1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.h */; };
                CE7B2DB31586ABAD0098B3FA /* AlternativeTextUIController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE7B2DB41586ABAD0098B3FA /* AlternativeTextUIController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */; };
                CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE6D89294C7AACE0AD89B3DD /* MathMLMencloseElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathMLMencloseElement.h; sourceTree = "<group>"; };
                CE6DADF71C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyResponseHeaders.cpp; path = csp/ContentSecurityPolicyResponseHeaders.cpp; sourceTree = "<group>"; };
                CE6DADF81C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyResponseHeaders.h; path = csp/ContentSecurityPolicyResponseHeaders.h; sourceTree = "<group>"; };
+               CE799F951C6A46BC0097B518 /* ContentSecurityPolicySourceList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicySourceList.cpp; path = csp/ContentSecurityPolicySourceList.cpp; sourceTree = "<group>"; };
+               CE799F961C6A46BC0097B518 /* ContentSecurityPolicySourceList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicySourceList.h; path = csp/ContentSecurityPolicySourceList.h; sourceTree = "<group>"; };
+               CE799F991C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyDirectiveList.cpp; path = csp/ContentSecurityPolicyDirectiveList.cpp; sourceTree = "<group>"; };
+               CE799F9A1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyDirectiveList.h; path = csp/ContentSecurityPolicyDirectiveList.h; sourceTree = "<group>"; };
+               CE799F9D1C6A4C160097B518 /* ContentSecurityPolicySource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicySource.cpp; path = csp/ContentSecurityPolicySource.cpp; sourceTree = "<group>"; };
+               CE799F9E1C6A4C160097B518 /* ContentSecurityPolicySource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicySource.h; path = csp/ContentSecurityPolicySource.h; sourceTree = "<group>"; };
+               CE799FA21C6A503A0097B518 /* ContentSecurityPolicyDirective.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyDirective.h; path = csp/ContentSecurityPolicyDirective.h; sourceTree = "<group>"; };
+               CE799FA51C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyMediaListDirective.cpp; path = csp/ContentSecurityPolicyMediaListDirective.cpp; sourceTree = "<group>"; };
+               CE799FA61C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyMediaListDirective.h; path = csp/ContentSecurityPolicyMediaListDirective.h; sourceTree = "<group>"; };
+               CE799FA91C6A50660097B518 /* ContentSecurityPolicySourceListDirective.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicySourceListDirective.cpp; path = csp/ContentSecurityPolicySourceListDirective.cpp; sourceTree = "<group>"; };
+               CE799FAA1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicySourceListDirective.h; path = csp/ContentSecurityPolicySourceListDirective.h; sourceTree = "<group>"; };
                CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlternativeTextUIController.h; sourceTree = "<group>"; };
                CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AlternativeTextUIController.mm; sourceTree = "<group>"; };
                CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextAlternativeWithRange.h; sourceTree = "<group>"; };
                                97C471DA12F925BD0086354B /* ContentSecurityPolicy.h */,
                                CE6DADF71C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp */,
                                CE6DADF81C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h */,
+                               CE799FA21C6A503A0097B518 /* ContentSecurityPolicyDirective.h */,
+                               CE799F991C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.cpp */,
+                               CE799F9A1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.h */,
+                               CE799FA51C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.cpp */,
+                               CE799FA61C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.h */,
+                               CE799F9D1C6A4C160097B518 /* ContentSecurityPolicySource.cpp */,
+                               CE799F9E1C6A4C160097B518 /* ContentSecurityPolicySource.h */,
+                               CE799F951C6A46BC0097B518 /* ContentSecurityPolicySourceList.cpp */,
+                               CE799F961C6A46BC0097B518 /* ContentSecurityPolicySourceList.h */,
+                               CE799FA91C6A50660097B518 /* ContentSecurityPolicySourceListDirective.cpp */,
+                               CE799FAA1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.h */,
                        );
                        name = csp;
                        sourceTree = "<group>";
                                5CDFA6C81AA4F2DA00EA8746 /* ContentExtensionActions.h in Headers */,
                                7C93F34E1AA6BF0700A98BAB /* ContentExtensionCompiler.h in Headers */,
                                7CFDC57D1AC1D80500E24A57 /* ContentExtensionError.h in Headers */,
-                               CE6DADFA1C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h in Headers */,
                                26F0C8981A2E724B002794F8 /* ContentExtensionParser.h in Headers */,
                                26F0C89C1A2EC110002794F8 /* ContentExtensionRule.h in Headers */,
                                26F0C8A01A2EC3BE002794F8 /* ContentExtensionsBackend.h in Headers */,
                                A149786F1ABAF33800CEF7E4 /* ContentFilter.h in Headers */,
                                A14090FD1AA51E480091191A /* ContentFilterUnblockHandler.h in Headers */,
                                97C471DC12F925BD0086354B /* ContentSecurityPolicy.h in Headers */,
+                               CE799FA41C6A503A0097B518 /* ContentSecurityPolicyDirective.h in Headers */,
+                               CE799F9C1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.h in Headers */,
+                               CE799FA81C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.h in Headers */,
+                               CE6DADFA1C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h in Headers */,
+                               CE799FA01C6A4C160097B518 /* ContentSecurityPolicySource.h in Headers */,
+                               CE799F981C6A46BC0097B518 /* ContentSecurityPolicySourceList.h in Headers */,
+                               CE799FAC1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.h in Headers */,
                                41D015CA0F4B5C71004A662F /* ContentType.h in Headers */,
                                97627B8E14FB3CEE002CDCA1 /* ContextDestructionObserver.h in Headers */,
                                93B6A0E60B0BCA5C00F5027A /* ContextMenu.h in Headers */,
                                A149786E1ABAF33800CEF7E4 /* ContentFilter.cpp in Sources */,
                                A14090FB1AA51E1D0091191A /* ContentFilterUnblockHandlerCocoa.mm in Sources */,
                                97C471DB12F925BD0086354B /* ContentSecurityPolicy.cpp in Sources */,
+                               CE799F9B1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.cpp in Sources */,
+                               CE799FA71C6A50570097B518 /* ContentSecurityPolicyMediaListDirective.cpp in Sources */,
+                               CE6DADF91C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp in Sources */,
+                               CE799F9F1C6A4C160097B518 /* ContentSecurityPolicySource.cpp in Sources */,
+                               CE799F971C6A46BC0097B518 /* ContentSecurityPolicySourceList.cpp in Sources */,
+                               CE799FAB1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.cpp in Sources */,
                                41D015CB0F4B5C71004A662F /* ContentType.cpp in Sources */,
                                97627B8D14FB3CEE002CDCA1 /* ContextDestructionObserver.cpp in Sources */,
                                1AB40EE21BF427DB00BA81BE /* ContextMenu.cpp in Sources */,
                                7C48A6D0191C9D6500026674 /* WebKitNamespace.cpp in Sources */,
                                A5DEBDA316FB908700836FE0 /* WebKitPlaybackTargetAvailabilityEvent.cpp in Sources */,
                                31C0FF240E4CEB6E007D6FE5 /* WebKitTransitionEvent.cpp in Sources */,
-                               CE6DADF91C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp in Sources */,
                                0FCF332E0F2B9A25004B6795 /* WebLayer.mm in Sources */,
                                0709D78E1AE55554004E42F8 /* WebMediaSessionManager.cpp in Sources */,
                                0709D7921AE5557E004E42F8 /* WebMediaSessionManagerMac.cpp in Sources */,
index 48ec135..4f159df 100644 (file)
 #include "config.h"
 #include "ContentSecurityPolicy.h"
 
+#include "ContentSecurityPolicyDirective.h"
+#include "ContentSecurityPolicyDirectiveList.h"
+#include "ContentSecurityPolicySource.h"
+#include "ContentSecurityPolicySourceList.h"
 #include "DOMStringList.h"
 #include "Document.h"
 #include "FormData.h"
 #include "Frame.h"
 #include "InspectorInstrumentation.h"
 #include "JSMainThreadExecState.h"
+#include "ParsingUtilities.h"
 #include "PingLoader.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SchemeRegistry.h"
-#include "ScriptController.h"
 #include "SecurityOrigin.h"
 #include "SecurityPolicyViolationEvent.h"
 #include <inspector/InspectorValues.h>
 #include <inspector/ScriptCallStack.h>
 #include <inspector/ScriptCallStackFactory.h>
-#include <wtf/HashSet.h>
-#include <wtf/NeverDestroyed.h>
 #include <wtf/text/TextPosition.h>
 
 using namespace Inspector;
 
 namespace WebCore {
 
-// Normally WebKit uses "static" for internal linkage, but using "static" for
-// these functions causes a compile error because these functions are used as
-// template parameters.
-namespace {
-
-bool isDirectiveNameCharacter(UChar c)
-{
-    return isASCIIAlphanumeric(c) || c == '-';
-}
-
-bool isDirectiveValueCharacter(UChar c)
-{
-    return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR
-}
-
-bool isSourceCharacter(UChar c)
-{
-    return !isASCIISpace(c);
-}
-
-bool isPathComponentCharacter(UChar c)
-{
-    return c != '?' && c != '#';
-}
-
-bool isHostCharacter(UChar c)
-{
-    return isASCIIAlphanumeric(c) || c == '-';
-}
-
-bool isSchemeContinuationCharacter(UChar c)
-{
-    return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.';
-}
-
-bool isNotASCIISpace(UChar c)
-{
-    return !isASCIISpace(c);
-}
-
-bool isNotColonOrSlash(UChar c)
-{
-    return c != ':' && c != '/';
-}
-
-bool isMediaTypeCharacter(UChar c)
-{
-    return !isASCIISpace(c) && c != '/';
-}
-
-// CSP 1.0 Directives
-static const char connectSrc[] = "connect-src";
-static const char defaultSrc[] = "default-src";
-static const char fontSrc[] = "font-src";
-static const char frameSrc[] = "frame-src";
-static const char imgSrc[] = "img-src";
-static const char mediaSrc[] = "media-src";
-static const char objectSrc[] = "object-src";
-static const char reportURI[] = "report-uri";
-static const char sandbox[] = "sandbox";
-static const char scriptSrc[] = "script-src";
-static const char styleSrc[] = "style-src";
-
-// CSP 1.1 Directives
-static const char baseURI[] = "base-uri";
-static const char formAction[] = "form-action";
-static const char pluginTypes[] = "plugin-types";
-#if ENABLE(CSP_NEXT)
-static const char reflectedXSS[] = "reflected-xss";
-#endif
-
-#if ENABLE(CSP_NEXT)
-
-static inline bool isExperimentalDirectiveName(const String& name)
-{
-    return equalLettersIgnoringASCIICase(name, baseURI)
-        || equalLettersIgnoringASCIICase(name, formAction)
-        || equalLettersIgnoringASCIICase(name, pluginTypes)
-        || equalLettersIgnoringASCIICase(name, reflectedXSS);
-}
-
-#else
-
-static inline bool isExperimentalDirectiveName(const String&)
-{
-    return false;
-}
-
-#endif
-
-bool isDirectiveName(const String& name)
-{
-    return equalLettersIgnoringASCIICase(name, connectSrc)
-        || equalLettersIgnoringASCIICase(name, defaultSrc)
-        || equalLettersIgnoringASCIICase(name, fontSrc)
-        || equalLettersIgnoringASCIICase(name, frameSrc)
-        || equalLettersIgnoringASCIICase(name, imgSrc)
-        || equalLettersIgnoringASCIICase(name, mediaSrc)
-        || equalLettersIgnoringASCIICase(name, objectSrc)
-        || equalLettersIgnoringASCIICase(name, reportURI)
-        || equalLettersIgnoringASCIICase(name, sandbox)
-        || equalLettersIgnoringASCIICase(name, scriptSrc)
-        || equalLettersIgnoringASCIICase(name, styleSrc)
-        || isExperimentalDirectiveName(name);
-}
-
-} // namespace
-
-static bool skipExactly(const UChar*& position, const UChar* end, UChar delimiter)
-{
-    if (position < end && *position == delimiter) {
-        ++position;
-        return true;
-    }
-    return false;
-}
-
-template<bool characterPredicate(UChar)>
-static bool skipExactly(const UChar*& position, const UChar* end)
-{
-    if (position < end && characterPredicate(*position)) {
-        ++position;
-        return true;
-    }
-    return false;
-}
-
-static void skipUntil(const UChar*& position, const UChar* end, UChar delimiter)
-{
-    while (position < end && *position != delimiter)
-        ++position;
-}
-
-template<bool characterPredicate(UChar)>
-static void skipWhile(const UChar*& position, const UChar* end)
-{
-    while (position < end && characterPredicate(*position))
-        ++position;
-}
-
-static bool isSourceListNone(const String& value)
-{
-    auto characters = StringView(value).upconvertedCharacters();
-    const UChar* begin = characters;
-    const UChar* end = characters + value.length();
-    skipWhile<isASCIISpace>(begin, end);
-
-    const UChar* position = begin;
-    skipWhile<isSourceCharacter>(position, end);
-    if (!equalLettersIgnoringASCIICase(begin, position - begin, "'none'"))
-        return false;
-
-    skipWhile<isASCIISpace>(position, end);
-    if (position != end)
-        return false;
-
-    return true;
-}
-
-class CSPSource {
-public:
-    CSPSource(const ContentSecurityPolicy& policy, const String& scheme, const String& host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard)
-        : m_policy(policy)
-        , m_scheme(scheme)
-        , m_host(host)
-        , m_port(port)
-        , m_path(path)
-        , m_hostHasWildcard(hostHasWildcard)
-        , m_portHasWildcard(portHasWildcard)
-    {
-    }
-
-    bool matches(const URL& url) const
-    {
-        if (!schemeMatches(url))
-            return false;
-        if (isSchemeOnly())
-            return true;
-        return hostMatches(url) && portMatches(url) && pathMatches(url);
-    }
-
-private:
-    bool schemeMatches(const URL& url) const
-    {
-        if (m_scheme.isEmpty())
-            return m_policy.protocolMatchesSelf(url);
-        return equalIgnoringASCIICase(url.protocol(), m_scheme);
-    }
-
-    bool hostMatches(const URL& url) const
-    {
-        const String& host = url.host();
-        if (equalIgnoringASCIICase(host, m_host))
-            return true;
-        return m_hostHasWildcard && host.endsWith("." + m_host, false);
-
-    }
-
-    bool pathMatches(const URL& url) const
-    {
-        if (m_path.isEmpty())
-            return true;
-
-        String path = decodeURLEscapeSequences(url.path());
-
-        if (m_path.endsWith("/"))
-            return path.startsWith(m_path, false);
-
-        return path == m_path;
-    }
-
-    bool portMatches(const URL& url) const
-    {
-        if (m_portHasWildcard)
-            return true;
-
-        int port = url.port();
-
-        if (port == m_port)
-            return true;
-
-        if (!port)
-            return isDefaultPortForProtocol(m_port, url.protocol());
-
-        if (!m_port)
-            return isDefaultPortForProtocol(port, url.protocol());
-
-        return false;
-    }
-
-    bool isSchemeOnly() const { return m_host.isEmpty(); }
-
-    const ContentSecurityPolicy& m_policy;
-    String m_scheme;
-    String m_host;
-    int m_port;
-    String m_path;
-
-    bool m_hostHasWildcard;
-    bool m_portHasWildcard;
-};
-
-class CSPSourceList {
-public:
-    CSPSourceList(const ContentSecurityPolicy&, const String& directiveName);
-
-    void parse(const String&);
-    bool matches(const URL&);
-    bool allowInline() const { return m_allowInline; }
-    bool allowEval() const { return m_allowEval; }
-    bool allowSelf() const { return m_allowSelf; }
-
-private:
-    void parse(const UChar* begin, const UChar* end);
-
-    bool parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard);
-    bool parseScheme(const UChar* begin, const UChar* end, String& scheme);
-    bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard);
-    bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard);
-    bool parsePath(const UChar* begin, const UChar* end, String& path);
-
-    const ContentSecurityPolicy& m_policy;
-    Vector<CSPSource> m_list;
-    String m_directiveName;
-    bool m_allowSelf { false };
-    bool m_allowStar { false };
-    bool m_allowInline { false };
-    bool m_allowEval { false };
-};
-
-CSPSourceList::CSPSourceList(const ContentSecurityPolicy& policy, const String& directiveName)
-    : m_policy(policy)
-    , m_directiveName(directiveName)
-{
-}
-
-void CSPSourceList::parse(const String& value)
-{
-    // We represent 'none' as an empty m_list.
-    if (isSourceListNone(value))
-        return;
-    auto characters = StringView(value).upconvertedCharacters();
-    parse(characters, characters + value.length());
-}
-
-bool CSPSourceList::matches(const URL& url)
-{
-    if (m_allowStar)
-        return true;
-
-    URL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin::extractInnerURL(url) : url;
-
-    if (m_allowSelf && m_policy.urlMatchesSelf(effectiveURL))
-        return true;
-
-    for (auto& entry : m_list) {
-        if (entry.matches(effectiveURL))
-            return true;
-    }
-
-    return false;
-}
-
-// source-list       = *WSP [ source *( 1*WSP source ) *WSP ]
-//                   / *WSP "'none'" *WSP
-//
-void CSPSourceList::parse(const UChar* begin, const UChar* end)
-{
-    const UChar* position = begin;
-
-    while (position < end) {
-        skipWhile<isASCIISpace>(position, end);
-        if (position == end)
-            return;
-
-        const UChar* beginSource = position;
-        skipWhile<isSourceCharacter>(position, end);
-
-        String scheme, host, path;
-        int port = 0;
-        bool hostHasWildcard = false;
-        bool portHasWildcard = false;
-
-        if (parseSource(beginSource, position, scheme, host, port, path, hostHasWildcard, portHasWildcard)) {
-            // Wildcard hosts and keyword sources ('self', 'unsafe-inline',
-            // etc.) aren't stored in m_list, but as attributes on the source
-            // list itself.
-            if (scheme.isEmpty() && host.isEmpty())
-                continue;
-            if (isDirectiveName(host))
-                m_policy.reportDirectiveAsSourceExpression(m_directiveName, host);
-            m_list.append(CSPSource(m_policy, scheme, host, port, path, hostHasWildcard, portHasWildcard));
-        } else
-            m_policy.reportInvalidSourceExpression(m_directiveName, String(beginSource, position - beginSource));
-
-        ASSERT(position == end || isASCIISpace(*position));
-     }
-}
-
-// source            = scheme ":"
-//                   / ( [ scheme "://" ] host [ port ] [ path ] )
-//                   / "'self'"
-//
-bool CSPSourceList::parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard)
-{
-    if (begin == end)
-        return false;
-
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'none'"))
-        return false;
-
-    if (end - begin == 1 && *begin == '*') {
-        m_allowStar = true;
-        return true;
-    }
-
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'self'")) {
-        m_allowSelf = true;
-        return true;
-    }
-
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'unsafe-inline'")) {
-        m_allowInline = true;
-        return true;
-    }
-
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'unsafe-eval'")) {
-        m_allowEval = true;
-        return true;
-    }
-
-    const UChar* position = begin;
-    const UChar* beginHost = begin;
-    const UChar* beginPath = end;
-    const UChar* beginPort = nullptr;
-
-    skipWhile<isNotColonOrSlash>(position, end);
-
-    if (position == end) {
-        // host
-        //     ^
-        return parseHost(beginHost, position, host, hostHasWildcard);
-    }
-
-    if (position < end && *position == '/') {
-        // host/path || host/ || /
-        //     ^            ^    ^
-        if (!parseHost(beginHost, position, host, hostHasWildcard)
-            || !parsePath(position, end, path)
-            || position != end)
-            return false;
-        return true;
-    }
-
-    if (position < end && *position == ':') {
-        if (end - position == 1) {
-            // scheme:
-            //       ^
-            return parseScheme(begin, position, scheme);
-        }
-
-        if (position[1] == '/') {
-            // scheme://host || scheme://
-            //       ^                ^
-            if (!parseScheme(begin, position, scheme)
-                || !skipExactly(position, end, ':')
-                || !skipExactly(position, end, '/')
-                || !skipExactly(position, end, '/'))
-                return false;
-            if (position == end)
-                return true;
-            beginHost = position;
-            skipWhile<isNotColonOrSlash>(position, end);
-        }
-
-        if (position < end && *position == ':') {
-            // host:port || scheme://host:port
-            //     ^                     ^
-            beginPort = position;
-            skipUntil(position, end, '/');
-        }
-    }
-
-    if (position < end && *position == '/') {
-        // scheme://host/path || scheme://host:port/path
-        //              ^                          ^
-        if (position == beginHost)
-            return false;
-
-        beginPath = position;
-    }
-
-    if (!parseHost(beginHost, beginPort ? beginPort : beginPath, host, hostHasWildcard))
-        return false;
-
-    if (beginPort) {
-        if (!parsePort(beginPort, beginPath, port, portHasWildcard))
-            return false;
-    } else {
-        port = 0;
-    }
-
-    if (beginPath != end) {
-        if (!parsePath(beginPath, end, path))
-            return false;
-    }
-
-    return true;
-}
-
-//                     ; <scheme> production from RFC 3986
-// scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
-//
-bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& scheme)
-{
-    ASSERT(begin <= end);
-    ASSERT(scheme.isEmpty());
-
-    if (begin == end)
-        return false;
-
-    const UChar* position = begin;
-
-    if (!skipExactly<isASCIIAlpha>(position, end))
-        return false;
-
-    skipWhile<isSchemeContinuationCharacter>(position, end);
-
-    if (position != end)
-        return false;
-
-    scheme = String(begin, end - begin);
-    return true;
-}
-
-// host              = [ "*." ] 1*host-char *( "." 1*host-char )
-//                   / "*"
-// host-char         = ALPHA / DIGIT / "-"
-//
-bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard)
-{
-    ASSERT(begin <= end);
-    ASSERT(host.isEmpty());
-    ASSERT(!hostHasWildcard);
-
-    if (begin == end)
-        return false;
-
-    const UChar* position = begin;
-
-    if (skipExactly(position, end, '*')) {
-        hostHasWildcard = true;
-
-        if (position == end)
-            return true;
-
-        if (!skipExactly(position, end, '.'))
-            return false;
-    }
-
-    const UChar* hostBegin = position;
-
-    while (position < end) {
-        if (!skipExactly<isHostCharacter>(position, end))
-            return false;
-
-        skipWhile<isHostCharacter>(position, end);
-
-        if (position < end && !skipExactly(position, end, '.'))
-            return false;
-    }
-
-    ASSERT(position == end);
-    host = String(hostBegin, end - hostBegin);
-    return true;
-}
-
-bool CSPSourceList::parsePath(const UChar* begin, const UChar* end, String& path)
-{
-    ASSERT(begin <= end);
-    ASSERT(path.isEmpty());
-
-    const UChar* position = begin;
-    skipWhile<isPathComponentCharacter>(position, end);
-    // path/to/file.js?query=string || path/to/file.js#anchor
-    //                ^                               ^
-    if (position < end)
-        m_policy.reportInvalidPathCharacter(m_directiveName, String(begin, end - begin), *position);
-
-    path = decodeURLEscapeSequences(String(begin, position - begin));
-
-    ASSERT(position <= end);
-    ASSERT(position == end || (*position == '#' || *position == '?'));
-    return true;
-}
-
-// port              = ":" ( 1*DIGIT / "*" )
-//
-bool CSPSourceList::parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard)
-{
-    ASSERT(begin <= end);
-    ASSERT(!port);
-    ASSERT(!portHasWildcard);
-
-    if (!skipExactly(begin, end, ':'))
-        ASSERT_NOT_REACHED();
-
-    if (begin == end)
-        return false;
-
-    if (end - begin == 1 && *begin == '*') {
-        port = 0;
-        portHasWildcard = true;
-        return true;
-    }
-
-    const UChar* position = begin;
-    skipWhile<isASCIIDigit>(position, end);
-
-    if (position != end)
-        return false;
-
-    bool ok;
-    port = charactersToIntStrict(begin, end - begin, &ok);
-    return ok;
-}
-
-class CSPDirective {
-public:
-    CSPDirective(const String& name, const String& value, const ContentSecurityPolicy& policy)
-        : m_name(name)
-        , m_text(name + ' ' + value)
-        , m_policy(policy)
-    {
-    }
-
-    const String& text() const { return m_text; }
-
-protected:
-    const ContentSecurityPolicy& policy() const { return m_policy; }
-
-private:
-    String m_name;
-    String m_text;
-    const ContentSecurityPolicy& m_policy;
-};
-
-class MediaListDirective : public CSPDirective {
-public:
-    MediaListDirective(const String& name, const String& value, const ContentSecurityPolicy& policy)
-        : CSPDirective(name, value, policy)
-    {
-        parse(value);
-    }
-
-    bool allows(const String& type)
-    {
-        return m_pluginTypes.contains(type);
-    }
-
-private:
-    void parse(const String& value)
-    {
-        auto characters = StringView(value).upconvertedCharacters();
-        const UChar* begin = characters;
-        const UChar* position = begin;
-        const UChar* end = begin + value.length();
-
-        // 'plugin-types ____;' OR 'plugin-types;'
-        if (value.isEmpty()) {
-            policy().reportInvalidPluginTypes(value);
-            return;
-        }
-
-        while (position < end) {
-            // _____ OR _____mime1/mime1
-            // ^        ^
-            skipWhile<isASCIISpace>(position, end);
-            if (position == end)
-                return;
-
-            // mime1/mime1 mime2/mime2
-            // ^
-            begin = position;
-            if (!skipExactly<isMediaTypeCharacter>(position, end)) {
-                skipWhile<isNotASCIISpace>(position, end);
-                policy().reportInvalidPluginTypes(String(begin, position - begin));
-                continue;
-            }
-            skipWhile<isMediaTypeCharacter>(position, end);
-
-            // mime1/mime1 mime2/mime2
-            //      ^
-            if (!skipExactly(position, end, '/')) {
-                skipWhile<isNotASCIISpace>(position, end);
-                policy().reportInvalidPluginTypes(String(begin, position - begin));
-                continue;
-            }
-
-            // mime1/mime1 mime2/mime2
-            //       ^
-            if (!skipExactly<isMediaTypeCharacter>(position, end)) {
-                skipWhile<isNotASCIISpace>(position, end);
-                policy().reportInvalidPluginTypes(String(begin, position - begin));
-                continue;
-            }
-            skipWhile<isMediaTypeCharacter>(position, end);
-
-            // mime1/mime1 mime2/mime2 OR mime1/mime1  OR mime1/mime1/error
-            //            ^                          ^               ^
-            if (position < end && isNotASCIISpace(*position)) {
-                skipWhile<isNotASCIISpace>(position, end);
-                policy().reportInvalidPluginTypes(String(begin, position - begin));
-                continue;
-            }
-            m_pluginTypes.add(String(begin, position - begin));
-
-            ASSERT(position == end || isASCIISpace(*position));
-        }
-    }
-
-    HashSet<String> m_pluginTypes;
-};
-
-class SourceListDirective : public CSPDirective {
-public:
-    SourceListDirective(const String& name, const String& value, const ContentSecurityPolicy& policy)
-        : CSPDirective(name, value, policy)
-        , m_sourceList(policy, name)
-    {
-        m_sourceList.parse(value);
-    }
-
-    bool allows(const URL& url)
-    {
-        // FIXME: We should investigate returning false for an empty URL.
-        if (url.isEmpty())
-            return m_sourceList.allowSelf();
-        return m_sourceList.matches(url);
-    }
-
-    bool allowInline() const { return m_sourceList.allowInline(); }
-    bool allowEval() const { return m_sourceList.allowEval(); }
-
-private:
-    CSPSourceList m_sourceList;
-};
-
-class CSPDirectiveList {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    static std::unique_ptr<CSPDirectiveList> create(ContentSecurityPolicy&, const String&, ContentSecurityPolicyHeaderType);
-    CSPDirectiveList(ContentSecurityPolicy&, ContentSecurityPolicyHeaderType);
-
-    const String& header() const { return m_header; }
-    ContentSecurityPolicyHeaderType headerType() const { return m_headerType; }
-
-    bool allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowEval(JSC::ExecState*, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowPluginType(const String& type, const String& typeAttribute, const URL&, ContentSecurityPolicy::ReportingStatus) const;
-
-    bool allowScriptFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowObjectFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowChildFrameFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowImageFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowStyleFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowFontFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowMediaFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowConnectToSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowFormAction(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-    bool allowBaseURI(const URL&, ContentSecurityPolicy::ReportingStatus) const;
-
-    const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
-    ContentSecurityPolicy::ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflectedXSSDisposition; }
-    bool isReportOnly() const { return m_reportOnly; }
-    const Vector<String>& reportURIs() const { return m_reportURIs; }
-
-private:
-    void parse(const String&);
-
-    bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value);
-    void parseReportURI(const String& name, const String& value);
-    void parsePluginTypes(const String& name, const String& value);
-    void parseReflectedXSS(const String& name, const String& value);
-    void addDirective(const String& name, const String& value);
-    void applySandboxPolicy(const String& name, const String& sandboxPolicy);
-
-    template <class CSPDirectiveType>
-    void setCSPDirective(const String& name, const String& value, std::unique_ptr<CSPDirectiveType>&);
-
-    SourceListDirective* operativeDirective(SourceListDirective*) const;
-    void reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const URL& blockedURL = URL(), const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), JSC::ExecState* = nullptr) const;
-
-    bool checkEval(SourceListDirective*) const;
-    bool checkInline(SourceListDirective*) const;
-    bool checkSource(SourceListDirective*, const URL&) const;
-    bool checkMediaType(MediaListDirective*, const String& type, const String& typeAttribute) const;
-
-    void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisabledErrorMessage = errorMessage; }
-
-    bool checkEvalAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), JSC::ExecState* = nullptr) const;
-    bool checkInlineAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
-
-    bool checkSourceAndReportViolation(SourceListDirective*, const URL&, const String& effectiveDirective) const;
-    bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& type, const String& typeAttribute, const String& consoleMessage) const;
-
-    bool denyIfEnforcingPolicy() const { return m_reportOnly; }
-
-    // FIXME: Make this a const reference once we teach applySandboxPolicy() to store its policy as opposed to applying it directly onto ContentSecurityPolicy.
-    ContentSecurityPolicy& m_policy;
-
-    String m_header;
-    ContentSecurityPolicyHeaderType m_headerType;
-
-    bool m_reportOnly;
-    bool m_haveSandboxPolicy;
-    ContentSecurityPolicy::ReflectedXSSDisposition m_reflectedXSSDisposition;
-
-    std::unique_ptr<MediaListDirective> m_pluginTypes;
-    std::unique_ptr<SourceListDirective> m_baseURI;
-    std::unique_ptr<SourceListDirective> m_connectSrc;
-    std::unique_ptr<SourceListDirective> m_defaultSrc;
-    std::unique_ptr<SourceListDirective> m_fontSrc;
-    std::unique_ptr<SourceListDirective> m_formAction;
-    std::unique_ptr<SourceListDirective> m_frameSrc;
-    std::unique_ptr<SourceListDirective> m_imgSrc;
-    std::unique_ptr<SourceListDirective> m_mediaSrc;
-    std::unique_ptr<SourceListDirective> m_objectSrc;
-    std::unique_ptr<SourceListDirective> m_scriptSrc;
-    std::unique_ptr<SourceListDirective> m_styleSrc;
-
-    Vector<String> m_reportURIs;
-
-    String m_evalDisabledErrorMessage;
-};
-
-CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy& policy, ContentSecurityPolicyHeaderType type)
-    : m_policy(policy)
-    , m_headerType(type)
-    , m_reportOnly(false)
-    , m_haveSandboxPolicy(false)
-    , m_reflectedXSSDisposition(ContentSecurityPolicy::ReflectedXSSUnset)
-{
-    m_reportOnly = (type == ContentSecurityPolicyHeaderType::Report || type == ContentSecurityPolicyHeaderType::PrefixedReport);
-}
-
-std::unique_ptr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy& policy, const String& header, ContentSecurityPolicyHeaderType type)
-{
-    auto directives = std::make_unique<CSPDirectiveList>(policy, type);
-    directives->parse(header);
-
-    if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
-        String message = makeString("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");
-        directives->setEvalDisabledErrorMessage(message);
-    }
-
-    if (directives->isReportOnly() && directives->reportURIs().isEmpty())
-        policy.reportMissingReportURI(header);
-
-    return directives;
-}
-
-void CSPDirectiveList::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const URL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine, JSC::ExecState* state) const
-{
-    String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
-    m_policy.reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header, contextURL, contextLine, state);
-}
-
-bool CSPDirectiveList::checkEval(SourceListDirective* directive) const
-{
-    return !directive || directive->allowEval();
-}
-
-bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
-{
-    return !directive || directive->allowInline();
-}
-
-bool CSPDirectiveList::checkSource(SourceListDirective* directive, const URL& url) const
-{
-    return !directive || directive->allows(url);
-}
-
-bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const
-{
-    if (!directive)
-        return true;
-    if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
-        return false;
-    return directive->allows(type);
-}
-
-SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive) const
-{
-    return directive ? directive : m_defaultSrc.get();
-}
-
-bool CSPDirectiveList::checkEvalAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, JSC::ExecState* state) const
-{
-    if (checkEval(directive))
-        return true;
-
-    String suffix = String();
-    if (directive == m_defaultSrc.get())
-        suffix = " Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.";
-
-    reportViolation(directive->text(), scriptSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", URL(), contextURL, contextLine, state);
-    if (!m_reportOnly) {
-        m_policy.reportBlockedScriptExecutionToInspector(directive->text());
-        return false;
-    }
-    return true;
-}
-
-bool CSPDirectiveList::checkMediaTypeAndReportViolation(MediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const
-{
-    if (checkMediaType(directive, type, typeAttribute))
-        return true;
-
-    String message = makeString(consoleMessage, '\'', directive->text(), "\'.");
-    if (typeAttribute.isEmpty())
-        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]\" ...>').";
-
-    reportViolation(directive->text(), pluginTypes, message + "\n", URL());
-    return denyIfEnforcingPolicy();
-}
-
-bool CSPDirectiveList::checkInlineAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const
-{
-    if (checkInline(directive))
-        return true;
-
-    String suffix = String();
-    if (directive == m_defaultSrc.get())
-        suffix = makeString(" Note that '", (isScript ? "script" : "style"), "-src' was not explicitly set, so 'default-src' is used as a fallback.");
-
-    reportViolation(directive->text(), isScript ? scriptSrc : styleSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", URL(), contextURL, contextLine);
-
-    if (!m_reportOnly) {
-        if (isScript)
-            m_policy.reportBlockedScriptExecutionToInspector(directive->text());
-        return false;
-    }
-    return true;
-}
-
-bool CSPDirectiveList::checkSourceAndReportViolation(SourceListDirective* directive, const URL& url, const String& effectiveDirective) const
-{
-    if (checkSource(directive, url))
-        return true;
-
-    const char* prefix;
-    if (baseURI == effectiveDirective)
-        prefix = "Refused to set the document's base URI to '";
-    else if (connectSrc == effectiveDirective)
-        prefix = "Refused to connect to '";
-    else if (fontSrc == effectiveDirective)
-        prefix = "Refused to load the font '";
-    else if (formAction == effectiveDirective)
-        prefix = "Refused to send form data to '";
-    else if (frameSrc == effectiveDirective)
-        prefix = "Refused to load frame '";
-    else if (imgSrc == effectiveDirective)
-        prefix = "Refused to load the image '";
-    else if (mediaSrc == effectiveDirective)
-        prefix = "Refused to load media from '";
-    else if (objectSrc == effectiveDirective)
-        prefix = "Refused to load plugin data from '";
-    else if (scriptSrc == effectiveDirective)
-        prefix = "Refused to load the script '";
-    else if (styleSrc == effectiveDirective)
-        prefix = "Refused to load the stylesheet '";
-    else
-        prefix = "";
-
-    String suffix;
-    if (directive == m_defaultSrc.get())
-        suffix = " Note that '" + effectiveDirective + "' was not explicitly set, so 'default-src' is used as a fallback.";
-
-    reportViolation(directive->text(), effectiveDirective, makeString(prefix, url.stringCenterEllipsizedToLength(), "' because it violates the following Content Security Policy directive: \"", directive->text(), "\".", suffix, '\n'), url);
-    return denyIfEnforcingPolicy();
-}
-
-bool CSPDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: "));
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true)
-        : (m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get())));
-}
-
-bool CSPDirectiveList::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to execute inline event handler because it violates the following Content Security Policy directive: "));
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true)
-        : (m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get())));
-}
-
-bool CSPDirectiveList::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to execute inline script because it violates the following Content Security Policy directive: "));
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true) :
-        (m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get())));
-}
-
-bool CSPDirectiveList::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to apply inline style because it violates the following Content Security Policy directive: "));
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkInlineAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, contextURL, contextLine, false) :
-        (m_reportOnly || checkInline(operativeDirective(m_styleSrc.get())));
-}
-
-bool CSPDirectiveList::allowEval(JSC::ExecState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to evaluate script because it violates the following Content Security Policy directive: "));
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, String(), WTF::OrdinalNumber::beforeFirst(), state) :
-        (m_reportOnly || checkEval(operativeDirective(m_scriptSrc.get())));
-}
-
-bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.stringCenterEllipsizedToLength() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ") :
-        (m_reportOnly || checkMediaType(m_pluginTypes.get(), type, typeAttribute));
-}
-
-bool CSPDirectiveList::allowScriptFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_scriptSrc.get()), url, scriptSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_scriptSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowObjectFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    if (url.isBlankURL())
-        return true;
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_objectSrc.get()), url, objectSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_objectSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowChildFrameFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    if (url.isBlankURL())
-        return true;
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_frameSrc.get()), url, frameSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_frameSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowImageFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_imgSrc.get()), url, imgSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_imgSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowStyleFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_styleSrc.get()), url, styleSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_styleSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowFontFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_fontSrc.get()), url, fontSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_fontSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowMediaFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_mediaSrc.get()), url, mediaSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_mediaSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowConnectToSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(operativeDirective(m_connectSrc.get()), url, connectSrc) :
-        (m_reportOnly || checkSource(operativeDirective(m_connectSrc.get()), url));
-}
-
-bool CSPDirectiveList::allowFormAction(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(m_formAction.get(), url, formAction) :
-        (m_reportOnly || checkSource(m_formAction.get(), url));
-}
-
-bool CSPDirectiveList::allowBaseURI(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
-{
-    return reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport ?
-        checkSourceAndReportViolation(m_baseURI.get(), url, baseURI) :
-        (m_reportOnly || checkSource(m_baseURI.get(), url));
-}
-
-// policy            = directive-list
-// directive-list    = [ directive *( ";" [ directive ] ) ]
-//
-void CSPDirectiveList::parse(const String& policy)
-{
-    m_header = policy;
-    if (policy.isEmpty())
-        return;
-
-    auto characters = StringView(policy).upconvertedCharacters();
-    const UChar* position = characters;
-    const UChar* end = position + policy.length();
-
-    while (position < end) {
-        const UChar* directiveBegin = position;
-        skipUntil(position, end, ';');
-
-        String name, value;
-        if (parseDirective(directiveBegin, position, name, value)) {
-            ASSERT(!name.isEmpty());
-            addDirective(name, value);
-        }
-
-        ASSERT(position == end || *position == ';');
-        skipExactly(position, end, ';');
-    }
-}
-
-// directive         = *WSP [ directive-name [ WSP directive-value ] ]
-// directive-name    = 1*( ALPHA / DIGIT / "-" )
-// directive-value   = *( WSP / <VCHAR except ";"> )
-//
-bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value)
-{
-    ASSERT(name.isEmpty());
-    ASSERT(value.isEmpty());
-
-    const UChar* position = begin;
-    skipWhile<isASCIISpace>(position, end);
-
-    // Empty directive (e.g. ";;;"). Exit early.
-    if (position == end)
-        return false;
-
-    const UChar* nameBegin = position;
-    skipWhile<isDirectiveNameCharacter>(position, end);
-
-    // The directive-name must be non-empty.
-    if (nameBegin == position) {
-        skipWhile<isNotASCIISpace>(position, end);
-        m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin));
-        return false;
-    }
-
-    name = String(nameBegin, position - nameBegin);
-
-    if (position == end)
-        return true;
-
-    if (!skipExactly<isASCIISpace>(position, end)) {
-        skipWhile<isNotASCIISpace>(position, end);
-        m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin));
-        return false;
-    }
-
-    skipWhile<isASCIISpace>(position, end);
-
-    const UChar* valueBegin = position;
-    skipWhile<isDirectiveValueCharacter>(position, end);
-
-    if (position != end) {
-        m_policy.reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin));
-        return false;
-    }
-
-    // The directive-value may be empty.
-    if (valueBegin == position)
-        return true;
-
-    value = String(valueBegin, position - valueBegin);
-    return true;
-}
-
-void CSPDirectiveList::parseReportURI(const String& name, const String& value)
-{
-    if (!m_reportURIs.isEmpty()) {
-        m_policy.reportDuplicateDirective(name);
-        return;
-    }
-
-    auto characters = StringView(value).upconvertedCharacters();
-    const UChar* position = characters;
-    const UChar* end = position + value.length();
-
-    while (position < end) {
-        skipWhile<isASCIISpace>(position, end);
-
-        const UChar* urlBegin = position;
-        skipWhile<isNotASCIISpace>(position, end);
-
-        if (urlBegin < position)
-            m_reportURIs.append(value.substring(urlBegin - characters, position - urlBegin));
-    }
-}
-
-
-template<class CSPDirectiveType>
-void CSPDirectiveList::setCSPDirective(const String& name, const String& value, std::unique_ptr<CSPDirectiveType>& directive)
-{
-    if (directive) {
-        m_policy.reportDuplicateDirective(name);
-        return;
-    }
-    directive = std::make_unique<CSPDirectiveType>(name, value, m_policy);
-}
-
-void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy)
-{
-    if (m_haveSandboxPolicy) {
-        m_policy.reportDuplicateDirective(name);
-        return;
-    }
-    m_haveSandboxPolicy = true;
-    String invalidTokens;
-    m_policy.enforceSandboxFlags(SecurityContext::parseSandboxPolicy(sandboxPolicy, invalidTokens));
-    if (!invalidTokens.isNull())
-        m_policy.reportInvalidSandboxFlags(invalidTokens);
-}
-
-void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value)
-{
-    if (m_reflectedXSSDisposition != ContentSecurityPolicy::ReflectedXSSUnset) {
-        m_policy.reportDuplicateDirective(name);
-        m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
-        return;
-    }
-
-    if (value.isEmpty()) {
-        m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
-        m_policy.reportInvalidReflectedXSS(value);
-        return;
-    }
-
-    auto characters = StringView(value).upconvertedCharacters();
-    const UChar* position = characters;
-    const UChar* end = position + value.length();
-
-    skipWhile<isASCIISpace>(position, end);
-    const UChar* begin = position;
-    skipWhile<isNotASCIISpace>(position, end);
-
-    // value1
-    //       ^
-    if (equalLettersIgnoringASCIICase(begin, position - begin, "allow"))
-        m_reflectedXSSDisposition = ContentSecurityPolicy::AllowReflectedXSS;
-    else if (equalLettersIgnoringASCIICase(begin, position - begin, "filter"))
-        m_reflectedXSSDisposition = ContentSecurityPolicy::FilterReflectedXSS;
-    else if (equalLettersIgnoringASCIICase(begin, position - begin, "block"))
-        m_reflectedXSSDisposition = ContentSecurityPolicy::BlockReflectedXSS;
-    else {
-        m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
-        m_policy.reportInvalidReflectedXSS(value);
-        return;
-    }
-
-    skipWhile<isASCIISpace>(position, end);
-    if (position == end && m_reflectedXSSDisposition != ContentSecurityPolicy::ReflectedXSSUnset)
-        return;
-
-    // value1 value2
-    //        ^
-    m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
-    m_policy.reportInvalidReflectedXSS(value);
-}
-
-void CSPDirectiveList::addDirective(const String& name, const String& value)
-{
-    ASSERT(!name.isEmpty());
-
-    if (equalLettersIgnoringASCIICase(name, defaultSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_defaultSrc);
-    else if (equalLettersIgnoringASCIICase(name, scriptSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_scriptSrc);
-    else if (equalLettersIgnoringASCIICase(name, objectSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_objectSrc);
-    else if (equalLettersIgnoringASCIICase(name, frameSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_frameSrc);
-    else if (equalLettersIgnoringASCIICase(name, imgSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_imgSrc);
-    else if (equalLettersIgnoringASCIICase(name, styleSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_styleSrc);
-    else if (equalLettersIgnoringASCIICase(name, fontSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_fontSrc);
-    else if (equalLettersIgnoringASCIICase(name, mediaSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_mediaSrc);
-    else if (equalLettersIgnoringASCIICase(name, connectSrc))
-        setCSPDirective<SourceListDirective>(name, value, m_connectSrc);
-    else if (equalLettersIgnoringASCIICase(name, sandbox))
-        applySandboxPolicy(name, value);
-    else if (equalLettersIgnoringASCIICase(name, reportURI))
-        parseReportURI(name, value);
-#if ENABLE(CSP_NEXT)
-    else if (m_policy.experimentalFeaturesEnabled()) {
-        if (equalLettersIgnoringASCIICase(name, baseURI))
-            setCSPDirective<SourceListDirective>(name, value, m_baseURI);
-        else if (equalLettersIgnoringASCIICase(name, formAction))
-            setCSPDirective<SourceListDirective>(name, value, m_formAction);
-        else if (equalLettersIgnoringASCIICase(name, pluginTypes))
-            setCSPDirective<MediaListDirective>(name, value, m_pluginTypes);
-        else if (equalLettersIgnoringASCIICase(name, reflectedXSS))
-            parseReflectedXSS(name, value);
-        else
-            m_policy.reportUnsupportedDirective(name);
-    }
-#endif
-    else
-        m_policy.reportUnsupportedDirective(name);
-}
-
 ContentSecurityPolicy::ContentSecurityPolicy(ScriptExecutionContext& scriptExecutionContext)
     : m_scriptExecutionContext(&scriptExecutionContext)
     , m_sandboxFlags(SandboxNone)
@@ -1324,14 +60,14 @@ ContentSecurityPolicy::ContentSecurityPolicy(ScriptExecutionContext& scriptExecu
     ASSERT(scriptExecutionContext.securityOrigin());
     auto& securityOrigin = *scriptExecutionContext.securityOrigin();
     m_selfSourceProtocol = securityOrigin.protocol();
-    m_selfSource = std::make_unique<CSPSource>(*this, m_selfSourceProtocol, securityOrigin.host(), securityOrigin.port(), emptyString(), false, false);
+    m_selfSource = std::make_unique<ContentSecurityPolicySource>(*this, m_selfSourceProtocol, securityOrigin.host(), securityOrigin.port(), emptyString(), false, false);
 }
 
 ContentSecurityPolicy::ContentSecurityPolicy(const SecurityOrigin& securityOrigin)
     : m_sandboxFlags(SandboxNone)
 {
     m_selfSourceProtocol = securityOrigin.protocol();
-    m_selfSource = std::make_unique<CSPSource>(*this, m_selfSourceProtocol, securityOrigin.host(), securityOrigin.port(), emptyString(), false, false);
+    m_selfSource = std::make_unique<ContentSecurityPolicySource>(*this, m_selfSourceProtocol, securityOrigin.host(), securityOrigin.port(), emptyString(), false, false);
 }
 
 ContentSecurityPolicy::~ContentSecurityPolicy()
@@ -1370,11 +106,11 @@ void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecuri
     const UChar* position = begin;
     const UChar* end = begin + header.length();
     while (position < end) {
-        skipUntil(position, end, ',');
+        skipUntil<UChar>(position, end, ',');
 
         // header1,header2 OR header1
         //        ^                  ^
-        std::unique_ptr<CSPDirectiveList> policy = CSPDirectiveList::create(*this, String(begin, position - begin), type);
+        std::unique_ptr<ContentSecurityPolicyDirectiveList> policy = ContentSecurityPolicyDirectiveList::create(*this, String(begin, position - begin), type);
         if (!policy->allowEval(0, ContentSecurityPolicy::ReportingStatus::SuppressReport))
             m_lastPolicyEvalDisabledErrorMessage = policy->evalDisabledErrorMessage();
 
@@ -1382,7 +118,7 @@ void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecuri
 
         // Skip the comma, and begin the next header from the current position.
         ASSERT(position == end || *position == ',');
-        skipExactly(position, end, ',');
+        skipExactly<UChar>(position, end, ',');
         begin = position;
     }
 
@@ -1418,7 +154,7 @@ bool ContentSecurityPolicy::protocolMatchesSelf(const URL& url) const
     return equalIgnoringASCIICase(url.protocol(), m_selfSourceProtocol);
 }
 
-template<bool (CSPDirectiveList::*allowed)(ContentSecurityPolicy::ReportingStatus) const>
+template<bool (ContentSecurityPolicyDirectiveList::*allowed)(ContentSecurityPolicy::ReportingStatus) const>
 bool isAllowedByAll(const CSPDirectiveListVector& policies, ContentSecurityPolicy::ReportingStatus reportingStatus)
 {
     for (auto& policy : policies) {
@@ -1428,7 +164,7 @@ bool isAllowedByAll(const CSPDirectiveListVector& policies, ContentSecurityPolic
     return true;
 }
 
-template<bool (CSPDirectiveList::*allowed)(JSC::ExecState* state, ContentSecurityPolicy::ReportingStatus) const>
+template<bool (ContentSecurityPolicyDirectiveList::*allowed)(JSC::ExecState* state, ContentSecurityPolicy::ReportingStatus) const>
 bool isAllowedByAllWithState(const CSPDirectiveListVector& policies, JSC::ExecState* state, ContentSecurityPolicy::ReportingStatus reportingStatus)
 {
     for (auto& policy : policies) {
@@ -1438,7 +174,7 @@ bool isAllowedByAllWithState(const CSPDirectiveListVector& policies, JSC::ExecSt
     return true;
 }
 
-template<bool (CSPDirectiveList::*allowed)(const String&, const WTF::OrdinalNumber&, ContentSecurityPolicy::ReportingStatus) const>
+template<bool (ContentSecurityPolicyDirectiveList::*allowed)(const String&, const WTF::OrdinalNumber&, ContentSecurityPolicy::ReportingStatus) const>
 bool isAllowedByAllWithContext(const CSPDirectiveListVector& policies, const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus)
 {
     for (auto& policy : policies) {
@@ -1448,7 +184,7 @@ bool isAllowedByAllWithContext(const CSPDirectiveListVector& policies, const Str
     return true;
 }
 
-template<bool (CSPDirectiveList::*allowFromURL)(const URL&, ContentSecurityPolicy::ReportingStatus) const>
+template<bool (ContentSecurityPolicyDirectiveList::*allowFromURL)(const URL&, ContentSecurityPolicy::ReportingStatus) const>
 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus)
 {
     if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol()))
@@ -1463,27 +199,27 @@ bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const URL& ur
 
 bool ContentSecurityPolicy::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithContext<&CSPDirectiveList::allowJavaScriptURLs>(m_policies, contextURL, contextLine, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowJavaScriptURLs>(m_policies, contextURL, contextLine, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithContext<&CSPDirectiveList::allowInlineEventHandlers>(m_policies, contextURL, contextLine, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowInlineEventHandlers>(m_policies, contextURL, contextLine, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithContext<&CSPDirectiveList::allowInlineScript>(m_policies, contextURL, contextLine, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowInlineScript>(m_policies, contextURL, contextLine, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || m_overrideInlineStyleAllowed || isAllowedByAllWithContext<&CSPDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus);
+    return overrideContentSecurityPolicy || m_overrideInlineStyleAllowed || isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowEval(JSC::ExecState* state, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithState<&CSPDirectiveList::allowEval>(m_policies, state, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithState<&ContentSecurityPolicyDirectiveList::allowEval>(m_policies, state, reportingStatus);
 }
 
 String ContentSecurityPolicy::evalDisabledErrorMessage() const
@@ -1508,52 +244,52 @@ bool ContentSecurityPolicy::allowPluginType(const String& type, const String& ty
 
 bool ContentSecurityPolicy::allowScriptFromSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowScriptFromSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowObjectFromSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowObjectFromSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowChildFrameFromSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowChildFrameFromSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowImageFromSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowImageFromSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowImageFromSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowStyleFromSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowStyleFromSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowStyleFromSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowFontFromSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowFontFromSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowFontFromSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowMediaFromSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowMediaFromSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowMediaFromSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowConnectToSource(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowConnectToSource>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowConnectToSource>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowFormAction(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowFormAction>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowFormAction>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::allowBaseURI(const URL& url, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>(m_policies, url, reportingStatus);
+    return overrideContentSecurityPolicy || isAllowedByAllWithURL<&ContentSecurityPolicyDirectiveList::allowBaseURI>(m_policies, url, reportingStatus);
 }
 
 bool ContentSecurityPolicy::isActive() const
index 9817a49..6373a02 100644 (file)
@@ -38,14 +38,14 @@ class OrdinalNumber;
 
 namespace WebCore {
 
-class CSPDirectiveList;
-class CSPSource;
+class ContentSecurityPolicyDirectiveList;
+class ContentSecurityPolicySource;
 class DOMStringList;
 class ScriptExecutionContext;
 class SecurityOrigin;
 class URL;
 
-typedef Vector<std::unique_ptr<CSPDirectiveList>> CSPDirectiveListVector;
+typedef Vector<std::unique_ptr<ContentSecurityPolicyDirectiveList>> CSPDirectiveListVector;
 typedef int SandboxFlags;
 
 class ContentSecurityPolicy {
@@ -107,16 +107,16 @@ public:
     // FIXME: We should make the various directives serve only as state stores for the parsed policy and remove these functions.
     // This class should traverse the directives, validating the policy, and applying it to the script execution context.
 
-    // Used by MediaListDirective
+    // Used by ContentSecurityPolicyMediaListDirective
     void reportInvalidPluginTypes(const String&) const;
 
-    // Used by CSPSourceList
+    // Used by ContentSecurityPolicySourceList
     void reportDirectiveAsSourceExpression(const String& directiveName, const String& sourceExpression) const;
     void reportInvalidPathCharacter(const String& directiveName, const String& value, const char) const;
     void reportInvalidSourceExpression(const String& directiveName, const String& source) const;
     bool urlMatchesSelf(const URL&) const;
 
-    // Used by CSPDirectiveList
+    // Used by ContentSecurityPolicyDirectiveList
     void reportDuplicateDirective(const String&) const;
     void reportInvalidDirectiveValueCharacter(const String& directiveName, const String& value) const;
     void reportInvalidSandboxFlags(const String&) const;
@@ -127,7 +127,7 @@ public:
     void reportBlockedScriptExecutionToInspector(const String& directiveText) const;
     void enforceSandboxFlags(SandboxFlags sandboxFlags) { m_sandboxFlags |= sandboxFlags; }
 
-    // Used by CSPSource
+    // Used by ContentSecurityPolicySource
     bool protocolMatchesSelf(const URL&) const;
 
 private:
@@ -135,7 +135,7 @@ private:
     void applyPolicyToScriptExecutionContext();
 
     ScriptExecutionContext* m_scriptExecutionContext { nullptr };
-    std::unique_ptr<CSPSource> m_selfSource;
+    std::unique_ptr<ContentSecurityPolicySource> m_selfSource;
     String m_selfSourceProtocol;
     CSPDirectiveListVector m_policies;
     String m_lastPolicyEvalDisabledErrorMessage;
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyDirective.h b/Source/WebCore/page/csp/ContentSecurityPolicyDirective.h
new file mode 100644 (file)
index 0000000..44aa13f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ContentSecurityPolicyDirective_h
+#define ContentSecurityPolicyDirective_h
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class ContentSecurityPolicy;
+
+class ContentSecurityPolicyDirective {
+public:
+    ContentSecurityPolicyDirective(const String& name, const String& value, const ContentSecurityPolicy& policy)
+        : m_name(name)
+        , m_text(name + ' ' + value)
+        , m_policy(policy)
+    {
+    }
+
+    const String& text() const { return m_text; }
+
+protected:
+    const ContentSecurityPolicy& policy() const { return m_policy; }
+
+private:
+    String m_name;
+    String m_text;
+    const ContentSecurityPolicy& m_policy;
+};
+
+} // namespace WebCore
+
+#endif /* ContentSecurityPolicyDirective_h */
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp b/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp
new file mode 100644 (file)
index 0000000..32c4a20
--- /dev/null
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContentSecurityPolicyDirectiveList.h"
+
+#include "ParsingUtilities.h"
+#include "SecurityContext.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+// CSP 1.0 Directives
+static const char connectSrc[] = "connect-src";
+static const char defaultSrc[] = "default-src";
+static const char fontSrc[] = "font-src";
+static const char frameSrc[] = "frame-src";
+static const char imgSrc[] = "img-src";
+static const char mediaSrc[] = "media-src";
+static const char objectSrc[] = "object-src";
+static const char reportURI[] = "report-uri";
+static const char sandbox[] = "sandbox";
+static const char scriptSrc[] = "script-src";
+static const char styleSrc[] = "style-src";
+
+// CSP 1.1 Directives
+static const char baseURI[] = "base-uri";
+static const char formAction[] = "form-action";
+static const char pluginTypes[] = "plugin-types";
+#if ENABLE(CSP_NEXT)
+static const char reflectedXSS[] = "reflected-xss";
+#endif
+
+#if ENABLE(CSP_NEXT)
+
+static inline bool isExperimentalDirectiveName(const String& name)
+{
+    return equalLettersIgnoringASCIICase(name, baseURI)
+        || equalLettersIgnoringASCIICase(name, formAction)
+        || equalLettersIgnoringASCIICase(name, pluginTypes)
+        || equalLettersIgnoringASCIICase(name, reflectedXSS);
+}
+
+#else
+
+static inline bool isExperimentalDirectiveName(const String&)
+{
+    return false;
+}
+
+#endif
+
+bool isCSPDirectiveName(const String& name)
+{
+    return equalLettersIgnoringASCIICase(name, connectSrc)
+        || equalLettersIgnoringASCIICase(name, defaultSrc)
+        || equalLettersIgnoringASCIICase(name, fontSrc)
+        || equalLettersIgnoringASCIICase(name, frameSrc)
+        || equalLettersIgnoringASCIICase(name, imgSrc)
+        || equalLettersIgnoringASCIICase(name, mediaSrc)
+        || equalLettersIgnoringASCIICase(name, objectSrc)
+        || equalLettersIgnoringASCIICase(name, reportURI)
+        || equalLettersIgnoringASCIICase(name, sandbox)
+        || equalLettersIgnoringASCIICase(name, scriptSrc)
+        || equalLettersIgnoringASCIICase(name, styleSrc)
+        || isExperimentalDirectiveName(name);
+}
+
+static bool isDirectiveNameCharacter(UChar c)
+{
+    return isASCIIAlphanumeric(c) || c == '-';
+}
+
+static bool isDirectiveValueCharacter(UChar c)
+{
+    return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR
+}
+
+static bool isNotASCIISpace(UChar c)
+{
+    return !isASCIISpace(c);
+}
+
+ContentSecurityPolicyDirectiveList::ContentSecurityPolicyDirectiveList(ContentSecurityPolicy& policy, ContentSecurityPolicyHeaderType type)
+    : m_policy(policy)
+    , m_headerType(type)
+    , m_reportOnly(false)
+    , m_haveSandboxPolicy(false)
+    , m_reflectedXSSDisposition(ContentSecurityPolicy::ReflectedXSSUnset)
+{
+    m_reportOnly = (type == ContentSecurityPolicyHeaderType::Report || type == ContentSecurityPolicyHeaderType::PrefixedReport);
+}
+
+std::unique_ptr<ContentSecurityPolicyDirectiveList> ContentSecurityPolicyDirectiveList::create(ContentSecurityPolicy& policy, const String& header, ContentSecurityPolicyHeaderType type)
+{
+    auto directives = std::make_unique<ContentSecurityPolicyDirectiveList>(policy, type);
+    directives->parse(header);
+
+    if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
+        String message = makeString("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");
+        directives->setEvalDisabledErrorMessage(message);
+    }
+
+    if (directives->isReportOnly() && directives->reportURIs().isEmpty())
+        policy.reportMissingReportURI(header);
+
+    return directives;
+}
+
+void ContentSecurityPolicyDirectiveList::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const URL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine, JSC::ExecState* state) const
+{
+    String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
+    m_policy.reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header, contextURL, contextLine, state);
+}
+
+bool ContentSecurityPolicyDirectiveList::checkEval(ContentSecurityPolicySourceListDirective* directive) const
+{
+    return !directive || directive->allowEval();
+}
+
+bool ContentSecurityPolicyDirectiveList::checkInline(ContentSecurityPolicySourceListDirective* directive) const
+{
+    return !directive || directive->allowInline();
+}
+
+bool ContentSecurityPolicyDirectiveList::checkSource(ContentSecurityPolicySourceListDirective* directive, const URL& url) const
+{
+    return !directive || directive->allows(url);
+}
+
+bool ContentSecurityPolicyDirectiveList::checkMediaType(ContentSecurityPolicyMediaListDirective* directive, const String& type, const String& typeAttribute) const
+{
+    if (!directive)
+        return true;
+    if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
+        return false;
+    return directive->allows(type);
+}
+
+ContentSecurityPolicySourceListDirective* ContentSecurityPolicyDirectiveList::operativeDirective(ContentSecurityPolicySourceListDirective* directive) const
+{
+    return directive ? directive : m_defaultSrc.get();
+}
+
+bool ContentSecurityPolicyDirectiveList::checkEvalAndReportViolation(ContentSecurityPolicySourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, JSC::ExecState* state) const
+{
+    if (checkEval(directive))
+        return true;
+
+    String suffix = String();
+    if (directive == m_defaultSrc.get())
+        suffix = " Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.";
+
+    reportViolation(directive->text(), scriptSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", URL(), contextURL, contextLine, state);
+    if (!m_reportOnly) {
+        m_policy.reportBlockedScriptExecutionToInspector(directive->text());
+        return false;
+    }
+    return true;
+}
+
+bool ContentSecurityPolicyDirectiveList::checkMediaTypeAndReportViolation(ContentSecurityPolicyMediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const
+{
+    if (checkMediaType(directive, type, typeAttribute))
+        return true;
+
+    String message = makeString(consoleMessage, '\'', directive->text(), "\'.");
+    if (typeAttribute.isEmpty())
+        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]\" ...>').";
+
+    reportViolation(directive->text(), pluginTypes, message + "\n", URL());
+    return denyIfEnforcingPolicy();
+}
+
+bool ContentSecurityPolicyDirectiveList::checkInlineAndReportViolation(ContentSecurityPolicySourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const
+{
+    if (checkInline(directive))
+        return true;
+
+    String suffix = String();
+    if (directive == m_defaultSrc.get())
+        suffix = makeString(" Note that '", (isScript ? "script" : "style"), "-src' was not explicitly set, so 'default-src' is used as a fallback.");
+
+    reportViolation(directive->text(), isScript ? scriptSrc : styleSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", URL(), contextURL, contextLine);
+
+    if (!m_reportOnly) {
+        if (isScript)
+            m_policy.reportBlockedScriptExecutionToInspector(directive->text());
+        return false;
+    }
+    return true;
+}
+
+bool ContentSecurityPolicyDirectiveList::checkSourceAndReportViolation(ContentSecurityPolicySourceListDirective* directive, const URL& url, const String& effectiveDirective) const
+{
+    if (checkSource(directive, url))
+        return true;
+
+    const char* prefix;
+    if (baseURI == effectiveDirective)
+        prefix = "Refused to set the document's base URI to '";
+    else if (connectSrc == effectiveDirective)
+        prefix = "Refused to connect to '";
+    else if (fontSrc == effectiveDirective)
+        prefix = "Refused to load the font '";
+    else if (formAction == effectiveDirective)
+        prefix = "Refused to send form data to '";
+    else if (frameSrc == effectiveDirective)
+        prefix = "Refused to load frame '";
+    else if (imgSrc == effectiveDirective)
+        prefix = "Refused to load the image '";
+    else if (mediaSrc == effectiveDirective)
+        prefix = "Refused to load media from '";
+    else if (objectSrc == effectiveDirective)
+        prefix = "Refused to load plugin data from '";
+    else if (scriptSrc == effectiveDirective)
+        prefix = "Refused to load the script '";
+    else if (styleSrc == effectiveDirective)
+        prefix = "Refused to load the stylesheet '";
+    else
+        prefix = "";
+
+    String suffix;
+    if (directive == m_defaultSrc.get())
+        suffix = " Note that '" + effectiveDirective + "' was not explicitly set, so 'default-src' is used as a fallback.";
+
+    reportViolation(directive->text(), effectiveDirective, makeString(prefix, url.stringCenterEllipsizedToLength(), "' because it violates the following Content Security Policy directive: \"", directive->text(), "\".", suffix, '\n'), url);
+    return denyIfEnforcingPolicy();
+}
+
+bool ContentSecurityPolicyDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: "));
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true);
+    return m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get()));
+}
+
+bool ContentSecurityPolicyDirectiveList::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to execute inline event handler because it violates the following Content Security Policy directive: "));
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true);
+    return m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get()));
+}
+
+bool ContentSecurityPolicyDirectiveList::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to execute inline script because it violates the following Content Security Policy directive: "));
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true);
+    return m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get()));
+}
+
+bool ContentSecurityPolicyDirectiveList::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to apply inline style because it violates the following Content Security Policy directive: "));
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkInlineAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, contextURL, contextLine, false);
+    return m_reportOnly || checkInline(operativeDirective(m_styleSrc.get()));
+}
+
+bool ContentSecurityPolicyDirectiveList::allowEval(JSC::ExecState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Refused to evaluate script because it violates the following Content Security Policy directive: "));
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, String(), WTF::OrdinalNumber::beforeFirst(), state);
+    return m_reportOnly || checkEval(operativeDirective(m_scriptSrc.get()));
+}
+
+bool ContentSecurityPolicyDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.stringCenterEllipsizedToLength() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ");
+    return m_reportOnly || checkMediaType(m_pluginTypes.get(), type, typeAttribute);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowScriptFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_scriptSrc.get()), url, scriptSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_scriptSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowObjectFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (url.isBlankURL())
+        return true;
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_objectSrc.get()), url, objectSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_objectSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowChildFrameFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (url.isBlankURL())
+        return true;
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_frameSrc.get()), url, frameSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_frameSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowImageFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_imgSrc.get()), url, imgSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_imgSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowStyleFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_styleSrc.get()), url, styleSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_styleSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowFontFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_fontSrc.get()), url, fontSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_fontSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowMediaFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_mediaSrc.get()), url, mediaSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_mediaSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowConnectToSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(operativeDirective(m_connectSrc.get()), url, connectSrc);
+    return m_reportOnly || checkSource(operativeDirective(m_connectSrc.get()), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowFormAction(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(m_formAction.get(), url, formAction);
+    return m_reportOnly || checkSource(m_formAction.get(), url);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowBaseURI(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport)
+        return checkSourceAndReportViolation(m_baseURI.get(), url, baseURI);
+    return m_reportOnly || checkSource(m_baseURI.get(), url);
+}
+
+// policy            = directive-list
+// directive-list    = [ directive *( ";" [ directive ] ) ]
+//
+void ContentSecurityPolicyDirectiveList::parse(const String& policy)
+{
+    m_header = policy;
+    if (policy.isEmpty())
+        return;
+
+    auto characters = StringView(policy).upconvertedCharacters();
+    const UChar* position = characters;
+    const UChar* end = position + policy.length();
+
+    while (position < end) {
+        const UChar* directiveBegin = position;
+        skipUntil<UChar>(position, end, ';');
+
+        String name, value;
+        if (parseDirective(directiveBegin, position, name, value)) {
+            ASSERT(!name.isEmpty());
+            addDirective(name, value);
+        }
+
+        ASSERT(position == end || *position == ';');
+        skipExactly<UChar>(position, end, ';');
+    }
+}
+
+// directive         = *WSP [ directive-name [ WSP directive-value ] ]
+// directive-name    = 1*( ALPHA / DIGIT / "-" )
+// directive-value   = *( WSP / <VCHAR except ";"> )
+//
+bool ContentSecurityPolicyDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value)
+{
+    ASSERT(name.isEmpty());
+    ASSERT(value.isEmpty());
+
+    const UChar* position = begin;
+    skipWhile<UChar, isASCIISpace>(position, end);
+
+    // Empty directive (e.g. ";;;"). Exit early.
+    if (position == end)
+        return false;
+
+    const UChar* nameBegin = position;
+    skipWhile<UChar, isDirectiveNameCharacter>(position, end);
+
+    // The directive-name must be non-empty.
+    if (nameBegin == position) {
+        skipWhile<UChar, isNotASCIISpace>(position, end);
+        m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin));
+        return false;
+    }
+
+    name = String(nameBegin, position - nameBegin);
+
+    if (position == end)
+        return true;
+
+    if (!skipExactly<UChar, isASCIISpace>(position, end)) {
+        skipWhile<UChar, isNotASCIISpace>(position, end);
+        m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin));
+        return false;
+    }
+
+    skipWhile<UChar, isASCIISpace>(position, end);
+
+    const UChar* valueBegin = position;
+    skipWhile<UChar, isDirectiveValueCharacter>(position, end);
+
+    if (position != end) {
+        m_policy.reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin));
+        return false;
+    }
+
+    // The directive-value may be empty.
+    if (valueBegin == position)
+        return true;
+
+    value = String(valueBegin, position - valueBegin);
+    return true;
+}
+
+void ContentSecurityPolicyDirectiveList::parseReportURI(const String& name, const String& value)
+{
+    if (!m_reportURIs.isEmpty()) {
+        m_policy.reportDuplicateDirective(name);
+        return;
+    }
+
+    auto characters = StringView(value).upconvertedCharacters();
+    const UChar* position = characters;
+    const UChar* end = position + value.length();
+
+    while (position < end) {
+        skipWhile<UChar, isASCIISpace>(position, end);
+
+        const UChar* urlBegin = position;
+        skipWhile<UChar, isNotASCIISpace>(position, end);
+
+        if (urlBegin < position)
+            m_reportURIs.append(value.substring(urlBegin - characters, position - urlBegin));
+    }
+}
+
+
+template<class CSPDirectiveType>
+void ContentSecurityPolicyDirectiveList::setCSPDirective(const String& name, const String& value, std::unique_ptr<CSPDirectiveType>& directive)
+{
+    if (directive) {
+        m_policy.reportDuplicateDirective(name);
+        return;
+    }
+    directive = std::make_unique<CSPDirectiveType>(name, value, m_policy);
+}
+
+void ContentSecurityPolicyDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy)
+{
+    if (m_haveSandboxPolicy) {
+        m_policy.reportDuplicateDirective(name);
+        return;
+    }
+    m_haveSandboxPolicy = true;
+    String invalidTokens;
+    m_policy.enforceSandboxFlags(SecurityContext::parseSandboxPolicy(sandboxPolicy, invalidTokens));
+    if (!invalidTokens.isNull())
+        m_policy.reportInvalidSandboxFlags(invalidTokens);
+}
+
+void ContentSecurityPolicyDirectiveList::parseReflectedXSS(const String& name, const String& value)
+{
+    if (m_reflectedXSSDisposition != ContentSecurityPolicy::ReflectedXSSUnset) {
+        m_policy.reportDuplicateDirective(name);
+        m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
+        return;
+    }
+
+    if (value.isEmpty()) {
+        m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
+        m_policy.reportInvalidReflectedXSS(value);
+        return;
+    }
+
+    auto characters = StringView(value).upconvertedCharacters();
+    const UChar* position = characters;
+    const UChar* end = position + value.length();
+
+    skipWhile<UChar, isASCIISpace>(position, end);
+    const UChar* begin = position;
+    skipWhile<UChar, isNotASCIISpace>(position, end);
+
+    // value1
+    //       ^
+    if (equalLettersIgnoringASCIICase(begin, position - begin, "allow"))
+        m_reflectedXSSDisposition = ContentSecurityPolicy::AllowReflectedXSS;
+    else if (equalLettersIgnoringASCIICase(begin, position - begin, "filter"))
+        m_reflectedXSSDisposition = ContentSecurityPolicy::FilterReflectedXSS;
+    else if (equalLettersIgnoringASCIICase(begin, position - begin, "block"))
+        m_reflectedXSSDisposition = ContentSecurityPolicy::BlockReflectedXSS;
+    else {
+        m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
+        m_policy.reportInvalidReflectedXSS(value);
+        return;
+    }
+
+    skipWhile<UChar, isASCIISpace>(position, end);
+    if (position == end && m_reflectedXSSDisposition != ContentSecurityPolicy::ReflectedXSSUnset)
+        return;
+
+    // value1 value2
+    //        ^
+    m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid;
+    m_policy.reportInvalidReflectedXSS(value);
+}
+
+void ContentSecurityPolicyDirectiveList::addDirective(const String& name, const String& value)
+{
+    ASSERT(!name.isEmpty());
+
+    if (equalLettersIgnoringASCIICase(name, defaultSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_defaultSrc);
+    else if (equalLettersIgnoringASCIICase(name, scriptSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_scriptSrc);
+    else if (equalLettersIgnoringASCIICase(name, objectSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_objectSrc);
+    else if (equalLettersIgnoringASCIICase(name, frameSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_frameSrc);
+    else if (equalLettersIgnoringASCIICase(name, imgSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_imgSrc);
+    else if (equalLettersIgnoringASCIICase(name, styleSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_styleSrc);
+    else if (equalLettersIgnoringASCIICase(name, fontSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_fontSrc);
+    else if (equalLettersIgnoringASCIICase(name, mediaSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_mediaSrc);
+    else if (equalLettersIgnoringASCIICase(name, connectSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_connectSrc);
+    else if (equalLettersIgnoringASCIICase(name, sandbox))
+        applySandboxPolicy(name, value);
+    else if (equalLettersIgnoringASCIICase(name, reportURI))
+        parseReportURI(name, value);
+#if ENABLE(CSP_NEXT)
+    else if (m_policy.experimentalFeaturesEnabled()) {
+        if (equalLettersIgnoringASCIICase(name, baseURI))
+            setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_baseURI);
+        else if (equalLettersIgnoringASCIICase(name, formAction))
+            setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_formAction);
+        else if (equalLettersIgnoringASCIICase(name, pluginTypes))
+            setCSPDirective<ContentSecurityPolicyMediaListDirective>(name, value, m_pluginTypes);
+        else if (equalLettersIgnoringASCIICase(name, reflectedXSS))
+            parseReflectedXSS(name, value);
+        else
+            m_policy.reportUnsupportedDirective(name);
+    }
+#endif
+    else
+        m_policy.reportUnsupportedDirective(name);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h b/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h
new file mode 100644 (file)
index 0000000..25b2028
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ContentSecurityPolicyDirectiveList_h
+#define ContentSecurityPolicyDirectiveList_h
+
+#include "ContentSecurityPolicy.h"
+#include "ContentSecurityPolicyMediaListDirective.h"
+#include "ContentSecurityPolicySourceListDirective.h"
+#include "URL.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+bool isCSPDirectiveName(const String&);
+
+class ContentSecurityPolicyDirectiveList {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(ContentSecurityPolicyDirectiveList)
+public:
+    static std::unique_ptr<ContentSecurityPolicyDirectiveList> create(ContentSecurityPolicy&, const String&, ContentSecurityPolicyHeaderType);
+    ContentSecurityPolicyDirectiveList(ContentSecurityPolicy&, ContentSecurityPolicyHeaderType);
+
+    const String& header() const { return m_header; }
+    ContentSecurityPolicyHeaderType headerType() const { return m_headerType; }
+
+    bool allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowEval(JSC::ExecState*, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowPluginType(const String& type, const String& typeAttribute, const URL&, ContentSecurityPolicy::ReportingStatus) const;
+
+    bool allowScriptFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowObjectFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowChildFrameFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowImageFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowStyleFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowFontFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowMediaFromSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowConnectToSource(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowFormAction(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowBaseURI(const URL&, ContentSecurityPolicy::ReportingStatus) const;
+
+    const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
+    ContentSecurityPolicy::ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflectedXSSDisposition; }
+    bool isReportOnly() const { return m_reportOnly; }
+    const Vector<String>& reportURIs() const { return m_reportURIs; }
+
+private:
+    void parse(const String&);
+
+    bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value);
+    void parseReportURI(const String& name, const String& value);
+    void parsePluginTypes(const String& name, const String& value);
+    void parseReflectedXSS(const String& name, const String& value);
+    void addDirective(const String& name, const String& value);
+    void applySandboxPolicy(const String& name, const String& sandboxPolicy);
+
+    template <class CSPDirectiveType>
+    void setCSPDirective(const String& name, const String& value, std::unique_ptr<CSPDirectiveType>&);
+
+    ContentSecurityPolicySourceListDirective* operativeDirective(ContentSecurityPolicySourceListDirective*) const;
+    void reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const URL& blockedURL = URL(), const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), JSC::ExecState* = nullptr) const;
+
+    bool checkEval(ContentSecurityPolicySourceListDirective*) const;
+    bool checkInline(ContentSecurityPolicySourceListDirective*) const;
+    bool checkSource(ContentSecurityPolicySourceListDirective*, const URL&) const;
+    bool checkMediaType(ContentSecurityPolicyMediaListDirective*, const String& type, const String& typeAttribute) const;
+
+    void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisabledErrorMessage = errorMessage; }
+
+    bool checkEvalAndReportViolation(ContentSecurityPolicySourceListDirective*, const String& consoleMessage, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), JSC::ExecState* = nullptr) const;
+    bool checkInlineAndReportViolation(ContentSecurityPolicySourceListDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
+
+    bool checkSourceAndReportViolation(ContentSecurityPolicySourceListDirective*, const URL&, const String& effectiveDirective) const;
+    bool checkMediaTypeAndReportViolation(ContentSecurityPolicyMediaListDirective*, const String& type, const String& typeAttribute, const String& consoleMessage) const;
+
+    bool denyIfEnforcingPolicy() const { return m_reportOnly; }
+
+    // FIXME: Make this a const reference once we teach applySandboxPolicy() to store its policy as opposed to applying it directly onto ContentSecurityPolicy.
+    ContentSecurityPolicy& m_policy;
+
+    String m_header;
+    ContentSecurityPolicyHeaderType m_headerType;
+
+    bool m_reportOnly;
+    bool m_haveSandboxPolicy;
+    ContentSecurityPolicy::ReflectedXSSDisposition m_reflectedXSSDisposition;
+
+    std::unique_ptr<ContentSecurityPolicyMediaListDirective> m_pluginTypes;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_baseURI;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_connectSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_defaultSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_fontSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_formAction;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_frameSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_imgSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_mediaSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_objectSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_scriptSrc;
+    std::unique_ptr<ContentSecurityPolicySourceListDirective> m_styleSrc;
+    
+    Vector<String> m_reportURIs;
+    
+    String m_evalDisabledErrorMessage;
+};
+
+} // namespace WebCore
+
+#endif /* ContentSecurityPolicyDirectiveList_h */
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.cpp b/Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.cpp
new file mode 100644 (file)
index 0000000..2af3935
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContentSecurityPolicyMediaListDirective.h"
+
+#include "ContentSecurityPolicy.h"
+#include "ParsingUtilities.h"
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+static bool isMediaTypeCharacter(UChar c)
+{
+    return !isASCIISpace(c) && c != '/';
+}
+
+static bool isNotASCIISpace(UChar c)
+{
+    return !isASCIISpace(c);
+}
+
+ContentSecurityPolicyMediaListDirective::ContentSecurityPolicyMediaListDirective(const String& name, const String& value, const ContentSecurityPolicy& policy)
+    : ContentSecurityPolicyDirective(name, value, policy)
+{
+    parse(value);
+}
+
+bool ContentSecurityPolicyMediaListDirective::allows(const String& type) const
+{
+    return m_pluginTypes.contains(type);
+}
+
+void ContentSecurityPolicyMediaListDirective::parse(const String& value)
+{
+    auto characters = StringView(value).upconvertedCharacters();
+    const UChar* begin = characters;
+    const UChar* position = begin;
+    const UChar* end = begin + value.length();
+
+    // 'plugin-types ____;' OR 'plugin-types;'
+    if (value.isEmpty()) {
+        policy().reportInvalidPluginTypes(value);
+        return;
+    }
+
+    while (position < end) {
+        // _____ OR _____mime1/mime1
+        // ^        ^
+        skipWhile<UChar, isASCIISpace>(position, end);
+        if (position == end)
+            return;
+
+        // mime1/mime1 mime2/mime2
+        // ^
+        begin = position;
+        if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) {
+            skipWhile<UChar, isNotASCIISpace>(position, end);
+            policy().reportInvalidPluginTypes(String(begin, position - begin));
+            continue;
+        }
+        skipWhile<UChar, isMediaTypeCharacter>(position, end);
+
+        // mime1/mime1 mime2/mime2
+        //      ^
+        if (!skipExactly<UChar>(position, end, '/')) {
+            skipWhile<UChar, isNotASCIISpace>(position, end);
+            policy().reportInvalidPluginTypes(String(begin, position - begin));
+            continue;
+        }
+
+        // mime1/mime1 mime2/mime2
+        //       ^
+        if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) {
+            skipWhile<UChar, isNotASCIISpace>(position, end);
+            policy().reportInvalidPluginTypes(String(begin, position - begin));
+            continue;
+        }
+        skipWhile<UChar, isMediaTypeCharacter>(position, end);
+
+        // mime1/mime1 mime2/mime2 OR mime1/mime1  OR mime1/mime1/error
+        //            ^                          ^               ^
+        if (position < end && isNotASCIISpace(*position)) {
+            skipWhile<UChar, isNotASCIISpace>(position, end);
+            policy().reportInvalidPluginTypes(String(begin, position - begin));
+            continue;
+        }
+        m_pluginTypes.add(String(begin, position - begin));
+
+        ASSERT(position == end || isASCIISpace(*position));
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.h b/Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.h
new file mode 100644 (file)
index 0000000..f1a057e
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ContentSecurityPolicyMediaListDirective_h
+#define ContentSecurityPolicyMediaListDirective_h
+
+#include "ContentSecurityPolicyDirective.h"
+#include <wtf/HashSet.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class ContentSecurityPolicy;
+
+class ContentSecurityPolicyMediaListDirective : public ContentSecurityPolicyDirective {
+public:
+    ContentSecurityPolicyMediaListDirective(const String& name, const String& value, const ContentSecurityPolicy&);
+
+    bool allows(const String& type) const;
+
+private:
+    void parse(const String&);
+
+    HashSet<String> m_pluginTypes;
+};
+
+} // namespace WebCore
+
+#endif /* ContentSecurityPolicyMediaListDirective_h */
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySource.cpp b/Source/WebCore/page/csp/ContentSecurityPolicySource.cpp
new file mode 100644 (file)
index 0000000..87b9ea9
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContentSecurityPolicySource.h"
+
+#include "ContentSecurityPolicy.h"
+#include "URL.h"
+
+namespace WebCore {
+
+ContentSecurityPolicySource::ContentSecurityPolicySource(const ContentSecurityPolicy& policy, const String& scheme, const String& host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard)
+    : m_policy(policy)
+    , m_scheme(scheme)
+    , m_host(host)
+    , m_port(port)
+    , m_path(path)
+    , m_hostHasWildcard(hostHasWildcard)
+    , m_portHasWildcard(portHasWildcard)
+{
+}
+
+bool ContentSecurityPolicySource::matches(const URL& url) const
+{
+    if (!schemeMatches(url))
+        return false;
+    if (isSchemeOnly())
+        return true;
+    return hostMatches(url) && portMatches(url) && pathMatches(url);
+}
+
+bool ContentSecurityPolicySource::schemeMatches(const URL& url) const
+{
+    if (m_scheme.isEmpty())
+        return m_policy.protocolMatchesSelf(url);
+    return equalIgnoringASCIICase(url.protocol(), m_scheme);
+}
+
+bool ContentSecurityPolicySource::hostMatches(const URL& url) const
+{
+    const String& host = url.host();
+    if (equalIgnoringASCIICase(host, m_host))
+        return true;
+    return m_hostHasWildcard && host.endsWith("." + m_host, false);
+
+}
+
+bool ContentSecurityPolicySource::pathMatches(const URL& url) const
+{
+    if (m_path.isEmpty())
+        return true;
+
+    String path = decodeURLEscapeSequences(url.path());
+
+    if (m_path.endsWith("/"))
+        return path.startsWith(m_path, false);
+
+    return path == m_path;
+}
+
+bool ContentSecurityPolicySource::portMatches(const URL& url) const
+{
+    if (m_portHasWildcard)
+        return true;
+
+    int port = url.port();
+
+    if (port == m_port)
+        return true;
+
+    if (!port)
+        return isDefaultPortForProtocol(m_port, url.protocol());
+
+    if (!m_port)
+        return isDefaultPortForProtocol(port, url.protocol());
+
+    return false;
+}
+
+bool ContentSecurityPolicySource::isSchemeOnly() const
+{
+    return m_host.isEmpty();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySource.h b/Source/WebCore/page/csp/ContentSecurityPolicySource.h
new file mode 100644 (file)
index 0000000..5c779d5
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ContentSecurityPolicySource_h
+#define ContentSecurityPolicySource_h
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class ContentSecurityPolicy;
+class URL;
+
+class ContentSecurityPolicySource {
+public:
+    ContentSecurityPolicySource(const ContentSecurityPolicy&, const String& scheme, const String& host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard);
+
+    bool matches(const URL&) const;
+
+private:
+    bool schemeMatches(const URL&) const;
+    bool hostMatches(const URL&) const;
+    bool pathMatches(const URL&) const;
+    bool portMatches(const URL&) const;
+    bool isSchemeOnly() const;
+
+    const ContentSecurityPolicy& m_policy;
+    String m_scheme;
+    String m_host;
+    int m_port;
+    String m_path;
+
+    bool m_hostHasWildcard;
+    bool m_portHasWildcard;
+};
+
+} // namespace WebCore
+
+#endif /* ContentSecurityPolicySource_h */
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp b/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp
new file mode 100644 (file)
index 0000000..54c4d14
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContentSecurityPolicySourceList.h"
+
+#include "ContentSecurityPolicy.h"
+#include "ContentSecurityPolicyDirectiveList.h"
+#include "ParsingUtilities.h"
+#include "SecurityOrigin.h"
+#include "URL.h"
+#include <wtf/ASCIICType.h>
+
+namespace WebCore {
+
+static bool isSourceCharacter(UChar c)
+{
+    return !isASCIISpace(c);
+}
+
+static bool isHostCharacter(UChar c)
+{
+    return isASCIIAlphanumeric(c) || c == '-';
+}
+
+static bool isPathComponentCharacter(UChar c)
+{
+    return c != '?' && c != '#';
+}
+
+static bool isSchemeContinuationCharacter(UChar c)
+{
+    return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.';
+}
+
+static bool isNotColonOrSlash(UChar c)
+{
+    return c != ':' && c != '/';
+}
+
+static bool isSourceListNone(const String& value)
+{
+    auto characters = StringView(value).upconvertedCharacters();
+    const UChar* begin = characters;
+    const UChar* end = characters + value.length();
+    skipWhile<UChar, isASCIISpace>(begin, end);
+
+    const UChar* position = begin;
+    skipWhile<UChar, isSourceCharacter>(position, end);
+    if (!equalLettersIgnoringASCIICase(begin, position - begin, "'none'"))
+        return false;
+
+    skipWhile<UChar, isASCIISpace>(position, end);
+    if (position != end)
+        return false;
+    
+    return true;
+}
+
+ContentSecurityPolicySourceList::ContentSecurityPolicySourceList(const ContentSecurityPolicy& policy, const String& directiveName)
+    : m_policy(policy)
+    , m_directiveName(directiveName)
+{
+}
+
+void ContentSecurityPolicySourceList::parse(const String& value)
+{
+    // We represent 'none' as an empty m_list.
+    if (isSourceListNone(value))
+        return;
+    auto characters = StringView(value).upconvertedCharacters();
+    parse(characters, characters + value.length());
+}
+
+bool ContentSecurityPolicySourceList::matches(const URL& url)
+{
+    if (m_allowStar)
+        return true;
+
+    URL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin::extractInnerURL(url) : url;
+
+    if (m_allowSelf && m_policy.urlMatchesSelf(effectiveURL))
+        return true;
+
+    for (auto& entry : m_list) {
+        if (entry.matches(effectiveURL))
+            return true;
+    }
+
+    return false;
+}
+
+// source-list       = *WSP [ source *( 1*WSP source ) *WSP ]
+//                   / *WSP "'none'" *WSP
+//
+void ContentSecurityPolicySourceList::parse(const UChar* begin, const UChar* end)
+{
+    const UChar* position = begin;
+
+    while (position < end) {
+        skipWhile<UChar, isASCIISpace>(position, end);
+        if (position == end)
+            return;
+
+        const UChar* beginSource = position;
+        skipWhile<UChar, isSourceCharacter>(position, end);
+
+        String scheme, host, path;
+        int port = 0;
+        bool hostHasWildcard = false;
+        bool portHasWildcard = false;
+
+        if (parseSource(beginSource, position, scheme, host, port, path, hostHasWildcard, portHasWildcard)) {
+            // Wildcard hosts and keyword sources ('self', 'unsafe-inline',
+            // etc.) aren't stored in m_list, but as attributes on the source
+            // list itself.
+            if (scheme.isEmpty() && host.isEmpty())
+                continue;
+            if (isCSPDirectiveName(host))
+                m_policy.reportDirectiveAsSourceExpression(m_directiveName, host);
+            m_list.append(ContentSecurityPolicySource(m_policy, scheme, host, port, path, hostHasWildcard, portHasWildcard));
+        } else
+            m_policy.reportInvalidSourceExpression(m_directiveName, String(beginSource, position - beginSource));
+
+        ASSERT(position == end || isASCIISpace(*position));
+    }
+}
+
+// source            = scheme ":"
+//                   / ( [ scheme "://" ] host [ port ] [ path ] )
+//                   / "'self'"
+//
+bool ContentSecurityPolicySourceList::parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard)
+{
+    if (begin == end)
+        return false;
+
+    if (equalLettersIgnoringASCIICase(begin, end - begin, "'none'"))
+        return false;
+
+    if (end - begin == 1 && *begin == '*') {
+        m_allowStar = true;
+        return true;
+    }
+
+    if (equalLettersIgnoringASCIICase(begin, end - begin, "'self'")) {
+        m_allowSelf = true;
+        return true;
+    }
+
+    if (equalLettersIgnoringASCIICase(begin, end - begin, "'unsafe-inline'")) {
+        m_allowInline = true;
+        return true;
+    }
+
+    if (equalLettersIgnoringASCIICase(begin, end - begin, "'unsafe-eval'")) {
+        m_allowEval = true;
+        return true;
+    }
+
+    const UChar* position = begin;
+    const UChar* beginHost = begin;
+    const UChar* beginPath = end;
+    const UChar* beginPort = nullptr;
+
+    skipWhile<UChar, isNotColonOrSlash>(position, end);
+
+    if (position == end) {
+        // host
+        //     ^
+        return parseHost(beginHost, position, host, hostHasWildcard);
+    }
+
+    if (position < end && *position == '/') {
+        // host/path || host/ || /
+        //     ^            ^    ^
+        if (!parseHost(beginHost, position, host, hostHasWildcard)
+            || !parsePath(position, end, path)
+            || position != end)
+            return false;
+        return true;
+    }
+
+    if (position < end && *position == ':') {
+        if (end - position == 1) {
+            // scheme:
+            //       ^
+            return parseScheme(begin, position, scheme);
+        }
+
+        if (position[1] == '/') {
+            // scheme://host || scheme://
+            //       ^                ^
+            if (!parseScheme(begin, position, scheme)
+                || !skipExactly<UChar>(position, end, ':')
+                || !skipExactly<UChar>(position, end, '/')
+                || !skipExactly<UChar>(position, end, '/'))
+                return false;
+            if (position == end)
+                return true;
+            beginHost = position;
+            skipWhile<UChar, isNotColonOrSlash>(position, end);
+        }
+
+        if (position < end && *position == ':') {
+            // host:port || scheme://host:port
+            //     ^                     ^
+            beginPort = position;
+            skipUntil<UChar>(position, end, '/');
+        }
+    }
+
+    if (position < end && *position == '/') {
+        // scheme://host/path || scheme://host:port/path
+        //              ^                          ^
+        if (position == beginHost)
+            return false;
+
+        beginPath = position;
+    }
+
+    if (!parseHost(beginHost, beginPort ? beginPort : beginPath, host, hostHasWildcard))
+        return false;
+
+    if (!beginPort)
+        port = 0;
+    else {
+        if (!parsePort(beginPort, beginPath, port, portHasWildcard))
+            return false;
+    }
+
+    if (beginPath != end) {
+        if (!parsePath(beginPath, end, path))
+            return false;
+    }
+
+    return true;
+}
+
+//                     ; <scheme> production from RFC 3986
+// scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+//
+bool ContentSecurityPolicySourceList::parseScheme(const UChar* begin, const UChar* end, String& scheme)
+{
+    ASSERT(begin <= end);
+    ASSERT(scheme.isEmpty());
+
+    if (begin == end)
+        return false;
+
+    const UChar* position = begin;
+
+    if (!skipExactly<UChar, isASCIIAlpha>(position, end))
+        return false;
+
+    skipWhile<UChar, isSchemeContinuationCharacter>(position, end);
+
+    if (position != end)
+        return false;
+
+    scheme = String(begin, end - begin);
+    return true;
+}
+
+// host              = [ "*." ] 1*host-char *( "." 1*host-char )
+//                   / "*"
+// host-char         = ALPHA / DIGIT / "-"
+//
+bool ContentSecurityPolicySourceList::parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard)
+{
+    ASSERT(begin <= end);
+    ASSERT(host.isEmpty());
+    ASSERT(!hostHasWildcard);
+
+    if (begin == end)
+        return false;
+
+    const UChar* position = begin;
+
+    if (skipExactly<UChar>(position, end, '*')) {
+        hostHasWildcard = true;
+
+        if (position == end)
+            return true;
+
+        if (!skipExactly<UChar>(position, end, '.'))
+            return false;
+    }
+
+    const UChar* hostBegin = position;
+
+    while (position < end) {
+        if (!skipExactly<UChar, isHostCharacter>(position, end))
+            return false;
+
+        skipWhile<UChar, isHostCharacter>(position, end);
+
+        if (position < end && !skipExactly<UChar>(position, end, '.'))
+            return false;
+    }
+
+    ASSERT(position == end);
+    host = String(hostBegin, end - hostBegin);
+    return true;
+}
+
+bool ContentSecurityPolicySourceList::parsePath(const UChar* begin, const UChar* end, String& path)
+{
+    ASSERT(begin <= end);
+    ASSERT(path.isEmpty());
+    
+    const UChar* position = begin;
+    skipWhile<UChar, isPathComponentCharacter>(position, end);
+    // path/to/file.js?query=string || path/to/file.js#anchor
+    //                ^                               ^
+    if (position < end)
+        m_policy.reportInvalidPathCharacter(m_directiveName, String(begin, end - begin), *position);
+    
+    path = decodeURLEscapeSequences(String(begin, position - begin));
+    
+    ASSERT(position <= end);
+    ASSERT(position == end || (*position == '#' || *position == '?'));
+    return true;
+}
+
+// port              = ":" ( 1*DIGIT / "*" )
+//
+bool ContentSecurityPolicySourceList::parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard)
+{
+    ASSERT(begin <= end);
+    ASSERT(!port);
+    ASSERT(!portHasWildcard);
+    
+    if (!skipExactly<UChar>(begin, end, ':'))
+        ASSERT_NOT_REACHED();
+    
+    if (begin == end)
+        return false;
+    
+    if (end - begin == 1 && *begin == '*') {
+        port = 0;
+        portHasWildcard = true;
+        return true;
+    }
+    
+    const UChar* position = begin;
+    skipWhile<UChar, isASCIIDigit>(position, end);
+    
+    if (position != end)
+        return false;
+    
+    bool ok;
+    port = charactersToIntStrict(begin, end - begin, &ok);
+    return ok;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h b/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h
new file mode 100644 (file)
index 0000000..0646a9f
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ContentSecurityPolicySourceList_h
+#define ContentSecurityPolicySourceList_h
+
+#include "ContentSecurityPolicySource.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class ContentSecurityPolicy;
+class URL;
+
+class ContentSecurityPolicySourceList {
+public:
+    ContentSecurityPolicySourceList(const ContentSecurityPolicy&, const String& directiveName);
+
+    void parse(const String&);
+    bool matches(const URL&);
+    bool allowInline() const { return m_allowInline; }
+    bool allowEval() const { return m_allowEval; }
+    bool allowSelf() const { return m_allowSelf; }
+
+private:
+    void parse(const UChar* begin, const UChar* end);
+
+    bool parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard);
+    bool parseScheme(const UChar* begin, const UChar* end, String& scheme);
+    bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard);
+    bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard);
+    bool parsePath(const UChar* begin, const UChar* end, String& path);
+
+    const ContentSecurityPolicy& m_policy;
+    Vector<ContentSecurityPolicySource> m_list;
+    String m_directiveName;
+    bool m_allowSelf { false };
+    bool m_allowStar { false };
+    bool m_allowInline { false };
+    bool m_allowEval { false };
+};
+
+} // namespace WebCore
+
+#endif /* ContentSecurityPolicySourceList_h */
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp b/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp
new file mode 100644 (file)
index 0000000..89133d4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContentSecurityPolicySourceListDirective.h"
+
+#include "ContentSecurityPolicy.h"
+#include "URL.h"
+
+namespace WebCore {
+
+ContentSecurityPolicySourceListDirective::ContentSecurityPolicySourceListDirective(const String& name, const String& value, const ContentSecurityPolicy& policy)
+    : ContentSecurityPolicyDirective(name, value, policy)
+    , m_sourceList(policy, name)
+{
+    m_sourceList.parse(value);
+}
+
+bool ContentSecurityPolicySourceListDirective::allows(const URL& url)
+{
+    // FIXME: We should investigate returning false for an empty URL.
+    if (url.isEmpty())
+        return m_sourceList.allowSelf();
+    return m_sourceList.matches(url);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h b/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h
new file mode 100644 (file)
index 0000000..9d4e211
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Google, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ContentSecurityPolicySourceListDirective_h
+#define ContentSecurityPolicySourceListDirective_h
+
+#include "ContentSecurityPolicyDirective.h"
+#include "ContentSecurityPolicySourceList.h"
+
+namespace WebCore {
+
+class ContentSecurityPolicy;
+
+class ContentSecurityPolicySourceListDirective : public ContentSecurityPolicyDirective {
+public:
+    ContentSecurityPolicySourceListDirective(const String& name, const String& value, const ContentSecurityPolicy&);
+
+    bool allows(const URL&);
+    bool allowInline() const { return m_sourceList.allowInline(); }
+    bool allowEval() const { return m_sourceList.allowEval(); }
+
+private:
+    ContentSecurityPolicySourceList m_sourceList;
+};
+
+} // namespace WebCore
+
+#endif /* ContentSecurityPolicySourceListDirective_h */