Title: [125817] trunk
Revision
125817
Author
[email protected]
Date
2012-08-16 15:44:07 -0700 (Thu, 16 Aug 2012)

Log Message

Refactor CSPDirective to support non-sourcelist types.
https://bugs.webkit.org/show_bug.cgi?id=94252

Patch by Mike West <[email protected]> on 2012-08-16
Reviewed by Adam Barth.

Source/WebCore:

The 'CSPDirective' was built to support source list Content Security
Policy directives like 'script-src' or 'object-src'. It doesn't support
new directive types like 'script-nonce' or 'plugin-types'. That
functionality has been implemented by hanging state off of
CSPDirectiveList, which isn't a great solution.

This patch pulls the source list functionality out of CSPDirective and
into SourceListDirective, and likewise pulls the nonce and media list
functionality into NonceDirective and MediaListDirective.

No new tests have been added; this refactoring should be externally
transparent, and the current CSP tests should continue to pass.

* page/ContentSecurityPolicy.cpp:
(WebCore::CSPDirective::CSPDirective):
(CSPDirective):
(WebCore::CSPDirective::text):
(WebCore::CSPDirective::policy):
    CSPDirective is now a parent class for NonceDirective,
    MediaListDirective, and SourceListDirective. It stores a pointer
    to the ContentSecurityPolicy object in order to facilitate logging,
    which now needs to happen at this level, rather than higher up in
    CSPDirectiveList.
(WebCore):
(NonceDirective):
(WebCore::NonceDirective::NonceDirective):
(WebCore::NonceDirective::allows):
(WebCore::NonceDirective::parse):
    Pull the nonce parsing code and state out of CSPDirectiveList
    and into this new class.
(MediaListDirective):
(WebCore::MediaListDirective::MediaListDirective):
(WebCore::MediaListDirective::allows):
(WebCore::MediaListDirective::parse):
    Pull the media list parsing code and state out of CSPDirectiveList
    and into this new class.
(SourceListDirective):
(WebCore::SourceListDirective::SourceListDirective):
(WebCore::SourceListDirective::allows):
    Pull the source list functionality out of CSPDirective
    and into this new class.
(CSPDirectiveList):
(WebCore::CSPDirectiveList::checkEval):
(WebCore::CSPDirectiveList::checkInline):
(WebCore::CSPDirectiveList::checkNonce):
(WebCore::CSPDirectiveList::checkSource):
(WebCore::CSPDirectiveList::checkMediaType):
(WebCore::CSPDirectiveList::operativeDirective):
(WebCore::CSPDirectiveList::checkEvalAndReportViolation):
(WebCore::CSPDirectiveList::checkNonceAndReportViolation):
(WebCore::CSPDirectiveList::checkMediaTypeAndReportViolation):
(WebCore::CSPDirectiveList::checkInlineAndReportViolation):
(WebCore::CSPDirectiveList::checkSourceAndReportViolation):
(WebCore::CSPDirectiveList::allowJavaScriptURLs):
(WebCore::CSPDirectiveList::allowInlineEventHandlers):
(WebCore::CSPDirectiveList::allowScriptNonce):
(WebCore::CSPDirectiveList::allowPluginType):
(WebCore::CSPDirectiveList::setCSPDirective):
(WebCore::CSPDirectiveList::addDirective):
    Use the new classes rather than CSPDirective (or no directive
    at all, in the case of nonces and plugin types).

LayoutTests:

* http/tests/security/contentSecurityPolicy/1.1/scriptnonce-invalidnonce-expected.txt:
    This test was buggy. Now it writes out the full directive text as it
    ought to.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (125816 => 125817)


--- trunk/LayoutTests/ChangeLog	2012-08-16 22:42:03 UTC (rev 125816)
+++ trunk/LayoutTests/ChangeLog	2012-08-16 22:44:07 UTC (rev 125817)
@@ -1,3 +1,14 @@
+2012-08-16  Mike West  <[email protected]>
+
+        Refactor CSPDirective to support non-sourcelist types.
+        https://bugs.webkit.org/show_bug.cgi?id=94252
+
+        Reviewed by Adam Barth.
+
+        * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-invalidnonce-expected.txt:
+            This test was buggy. Now it writes out the full directive text as it
+            ought to.
+
 2012-08-16  Kiran Muppala  <[email protected]>
 
         Update test expectations for fast/overflow/line-clamp-and-columns.html on mac

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/scriptnonce-invalidnonce-expected.txt (125816 => 125817)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/scriptnonce-invalidnonce-expected.txt	2012-08-16 22:42:03 UTC (rev 125816)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/scriptnonce-invalidnonce-expected.txt	2012-08-16 22:44:07 UTC (rev 125817)
@@ -12,7 +12,7 @@
 
 CONSOLE MESSAGE: Ignoring invalid Content Security Policy script nonce: 'nonces have no spaces'.
 
-CONSOLE MESSAGE: line 7: Refused to load 'http://127.0.0.1:8000/security/contentSecurityPolicy/resources/script.js' because it violates the following Content Security Policy directive: "script-nonce ".
+CONSOLE MESSAGE: line 7: Refused to load 'http://127.0.0.1:8000/security/contentSecurityPolicy/resources/script.js' because it violates the following Content Security Policy directive: "script-nonce nonces have no spaces".
 
 None of these scripts should execute, as all the nonces are invalid.
 

Modified: trunk/Source/WebCore/ChangeLog (125816 => 125817)


--- trunk/Source/WebCore/ChangeLog	2012-08-16 22:42:03 UTC (rev 125816)
+++ trunk/Source/WebCore/ChangeLog	2012-08-16 22:44:07 UTC (rev 125817)
@@ -1,3 +1,72 @@
+2012-08-16  Mike West  <[email protected]>
+
+        Refactor CSPDirective to support non-sourcelist types.
+        https://bugs.webkit.org/show_bug.cgi?id=94252
+
+        Reviewed by Adam Barth.
+
+        The 'CSPDirective' was built to support source list Content Security
+        Policy directives like 'script-src' or 'object-src'. It doesn't support
+        new directive types like 'script-nonce' or 'plugin-types'. That
+        functionality has been implemented by hanging state off of
+        CSPDirectiveList, which isn't a great solution.
+
+        This patch pulls the source list functionality out of CSPDirective and
+        into SourceListDirective, and likewise pulls the nonce and media list
+        functionality into NonceDirective and MediaListDirective.
+
+        No new tests have been added; this refactoring should be externally
+        transparent, and the current CSP tests should continue to pass.
+
+        * page/ContentSecurityPolicy.cpp:
+        (WebCore::CSPDirective::CSPDirective):
+        (CSPDirective):
+        (WebCore::CSPDirective::text):
+        (WebCore::CSPDirective::policy):
+            CSPDirective is now a parent class for NonceDirective,
+            MediaListDirective, and SourceListDirective. It stores a pointer
+            to the ContentSecurityPolicy object in order to facilitate logging,
+            which now needs to happen at this level, rather than higher up in
+            CSPDirectiveList.
+        (WebCore):
+        (NonceDirective):
+        (WebCore::NonceDirective::NonceDirective):
+        (WebCore::NonceDirective::allows):
+        (WebCore::NonceDirective::parse):
+            Pull the nonce parsing code and state out of CSPDirectiveList
+            and into this new class.
+        (MediaListDirective):
+        (WebCore::MediaListDirective::MediaListDirective):
+        (WebCore::MediaListDirective::allows):
+        (WebCore::MediaListDirective::parse):
+            Pull the media list parsing code and state out of CSPDirectiveList
+            and into this new class.
+        (SourceListDirective):
+        (WebCore::SourceListDirective::SourceListDirective):
+        (WebCore::SourceListDirective::allows):
+            Pull the source list functionality out of CSPDirective
+            and into this new class.
+        (CSPDirectiveList):
+        (WebCore::CSPDirectiveList::checkEval):
+        (WebCore::CSPDirectiveList::checkInline):
+        (WebCore::CSPDirectiveList::checkNonce):
+        (WebCore::CSPDirectiveList::checkSource):
+        (WebCore::CSPDirectiveList::checkMediaType):
+        (WebCore::CSPDirectiveList::operativeDirective):
+        (WebCore::CSPDirectiveList::checkEvalAndReportViolation):
+        (WebCore::CSPDirectiveList::checkNonceAndReportViolation):
+        (WebCore::CSPDirectiveList::checkMediaTypeAndReportViolation):
+        (WebCore::CSPDirectiveList::checkInlineAndReportViolation):
+        (WebCore::CSPDirectiveList::checkSourceAndReportViolation):
+        (WebCore::CSPDirectiveList::allowJavaScriptURLs):
+        (WebCore::CSPDirectiveList::allowInlineEventHandlers):
+        (WebCore::CSPDirectiveList::allowScriptNonce):
+        (WebCore::CSPDirectiveList::allowPluginType):
+        (WebCore::CSPDirectiveList::setCSPDirective):
+        (WebCore::CSPDirectiveList::addDirective):
+            Use the new classes rather than CSPDirective (or no directive
+            at all, in the case of nonces and plugin types).
+
 2012-08-16  Adam Barth  <[email protected]>
 
         Null checks of m_frame->document()->domWindow() aren't needed

Modified: trunk/Source/WebCore/page/ContentSecurityPolicy.cpp (125816 => 125817)


--- trunk/Source/WebCore/page/ContentSecurityPolicy.cpp	2012-08-16 22:42:03 UTC (rev 125816)
+++ trunk/Source/WebCore/page/ContentSecurityPolicy.cpp	2012-08-16 22:44:07 UTC (rev 125817)
@@ -536,27 +536,162 @@
 class CSPDirective {
 public:
     CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy)
-        : m_sourceList(policy, name)
+        : m_name(name)
         , m_text(name + ' ' + value)
-        , m_selfURL(policy->url())
+        , 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;
+    ContentSecurityPolicy* m_policy;
+};
+
+class NonceDirective : public CSPDirective {
+public:
+    NonceDirective(const String& name, const String& value, ContentSecurityPolicy* policy)
+        : CSPDirective(name, value, policy)
+    {
+        parse(value);
+    }
+
+    bool allows(const String& nonce) const
+    {
+        return (!m_scriptNonce.isEmpty() && nonce.stripWhiteSpace() == m_scriptNonce);
+    }
+
+private:
+    void parse(const String& value)
+    {
+        String nonce;
+        const UChar* position = value.characters();
+        const UChar* end = position + value.length();
+
+        skipWhile<isASCIISpace>(position, end);
+        const UChar* nonceBegin = position;
+        if (position == end) {
+            policy()->reportInvalidNonce(String());
+            m_scriptNonce = "";
+            return;
+        }
+        skipWhile<isNonceCharacter>(position, end);
+        if (nonceBegin < position)
+            nonce = String(nonceBegin, position - nonceBegin);
+
+        // Trim off trailing whitespace: If we're not at the end of the string, log
+        // an error.
+        skipWhile<isASCIISpace>(position, end);
+        if (position < end) {
+            policy()->reportInvalidNonce(value);
+            m_scriptNonce = "";
+        } else
+            m_scriptNonce = nonce;
+    }
+
+    String m_scriptNonce;
+};
+
+class MediaListDirective : public CSPDirective {
+public:
+    MediaListDirective(const String& name, const String& value, ContentSecurityPolicy* policy)
+        : CSPDirective(name, value, policy)
+    {
+        parse(value);
+    }
+
+    bool allows(const String& type)
+    {
+        return m_pluginTypes.contains(type);
+    }
+
+private:
+    void parse(const String& value)
+    {
+        const UChar* begin = value.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, ContentSecurityPolicy* policy)
+        : CSPDirective(name, value, policy)
+        , m_sourceList(policy, name)
+    {
         m_sourceList.parse(value);
     }
 
     bool allows(const KURL& url)
     {
-        return m_sourceList.matches(url.isEmpty() ? m_selfURL : url);
+        return m_sourceList.matches(url.isEmpty() ? policy()->url() : url);
     }
 
     bool allowInline() const { return m_sourceList.allowInline(); }
     bool allowEval() const { return m_sourceList.allowEval(); }
 
-    const String& text() { return m_text; }
-
 private:
     CSPSourceList m_sourceList;
-    String m_text;
-    KURL m_selfURL;
 };
 
 class CSPDirectiveList {
@@ -598,22 +733,23 @@
     void addDirective(const String& name, const String& value);
     void applySandboxPolicy(const String& name, const String& sandboxPolicy);
 
-    void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirective>&);
+    template <class CSPDirectiveType>
+    void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>&);
 
-    CSPDirective* operativeDirective(CSPDirective*) const;
+    SourceListDirective* operativeDirective(SourceListDirective*) const;
     void reportViolation(const String& directiveText, const String& consoleMessage, const KURL& blockedURL = KURL(), const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), PassRefPtr<ScriptCallStack> = 0) const;
 
-    bool checkEval(CSPDirective*) const;
-    bool checkInline(CSPDirective*) const;
-    bool checkNonce(const String&) const;
-    bool checkSource(CSPDirective*, const KURL&) const;
-    bool checkPluginType(const String& type, const String& typeAttribute) const;
+    bool checkEval(SourceListDirective*) const;
+    bool checkInline(SourceListDirective*) const;
+    bool checkNonce(NonceDirective*, const String&) const;
+    bool checkSource(SourceListDirective*, const KURL&) const;
+    bool checkMediaType(MediaListDirective*, const String& type, const String& typeAttribute) const;
 
-    bool checkEvalAndReportViolation(CSPDirective*, const String& consoleMessage, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), PassRefPtr<ScriptCallStack> = 0) const;
-    bool checkInlineAndReportViolation(CSPDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const;
-    bool checkNonceAndReportViolation(const String& nonce, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const;
-    bool checkSourceAndReportViolation(CSPDirective*, const KURL&, const String& type) const;
-    bool checkPluginTypeAndReportViolation(const String& type, const String& typeAttribute, const String& consoleMessage) const;
+    bool checkEvalAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), PassRefPtr<ScriptCallStack> = 0) const;
+    bool checkInlineAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const;
+    bool checkNonceAndReportViolation(NonceDirective*, const String& nonce, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const;
+    bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& type) const;
+    bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& type, const String& typeAttribute, const String& consoleMessage) const;
 
     bool denyIfEnforcingPolicy() const { return m_reportOnly; }
 
@@ -623,21 +759,20 @@
     bool m_reportOnly;
     bool m_haveSandboxPolicy;
 
-    OwnPtr<CSPDirective> m_defaultSrc;
-    OwnPtr<CSPDirective> m_scriptSrc;
-    OwnPtr<CSPDirective> m_objectSrc;
-    OwnPtr<CSPDirective> m_frameSrc;
-    OwnPtr<CSPDirective> m_imgSrc;
-    OwnPtr<CSPDirective> m_styleSrc;
-    OwnPtr<CSPDirective> m_fontSrc;
-    OwnPtr<CSPDirective> m_mediaSrc;
-    OwnPtr<CSPDirective> m_connectSrc;
-    OwnPtr<CSPDirective> m_formAction;
+    OwnPtr<MediaListDirective> m_pluginTypes;
+    OwnPtr<NonceDirective> m_scriptNonce;
+    OwnPtr<SourceListDirective> m_connectSrc;
+    OwnPtr<SourceListDirective> m_defaultSrc;
+    OwnPtr<SourceListDirective> m_fontSrc;
+    OwnPtr<SourceListDirective> m_formAction;
+    OwnPtr<SourceListDirective> m_frameSrc;
+    OwnPtr<SourceListDirective> m_imgSrc;
+    OwnPtr<SourceListDirective> m_mediaSrc;
+    OwnPtr<SourceListDirective> m_objectSrc;
+    OwnPtr<SourceListDirective> m_scriptSrc;
+    OwnPtr<SourceListDirective> m_styleSrc;
 
     Vector<KURL> m_reportURIs;
-    HashSet<String> m_pluginTypes;
-    String m_pluginTypesDirective;
-    String m_scriptNonce;
 };
 
 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy)
@@ -671,43 +806,41 @@
     m_policy->reportViolation(directiveText, message, blockedURL, m_reportURIs, m_header, contextURL, contextLine, callStack);
 }
 
-bool CSPDirectiveList::checkEval(CSPDirective* directive) const
+bool CSPDirectiveList::checkEval(SourceListDirective* directive) const
 {
     return !directive || directive->allowEval();
 }
 
-bool CSPDirectiveList::checkInline(CSPDirective* directive) const
+bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
 {
     return !directive || directive->allowInline();
 }
 
-bool CSPDirectiveList::checkNonce(const String& nonce) const
+bool CSPDirectiveList::checkNonce(NonceDirective* directive, const String& nonce) const
 {
-    return (m_scriptNonce.isNull()
-            || (!m_scriptNonce.isEmpty()
-                && nonce.stripWhiteSpace() == m_scriptNonce));
+    return !directive || directive->allows(nonce);
 }
 
-bool CSPDirectiveList::checkSource(CSPDirective* directive, const KURL& url) const
+bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& url) const
 {
     return !directive || directive->allows(url);
 }
 
-bool CSPDirectiveList::checkPluginType(const String& type, const String& typeAttribute) const
+bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const
 {
-    if (m_pluginTypesDirective.isNull())
+    if (!directive)
         return true;
     if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
         return false;
-    return m_pluginTypes.contains(type);
+    return directive->allows(type);
 }
 
-CSPDirective* CSPDirectiveList::operativeDirective(CSPDirective* directive) const
+SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive) const
 {
     return directive ? directive : m_defaultSrc.get();
 }
 
-bool CSPDirectiveList::checkEvalAndReportViolation(CSPDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, PassRefPtr<ScriptCallStack> callStack) const
+bool CSPDirectiveList::checkEvalAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, PassRefPtr<ScriptCallStack> callStack) const
 {
     if (checkEval(directive))
         return true;
@@ -715,24 +848,24 @@
     return denyIfEnforcingPolicy();
 }
 
-bool CSPDirectiveList::checkNonceAndReportViolation(const String& nonce, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const
+bool CSPDirectiveList::checkNonceAndReportViolation(NonceDirective* directive, const String& nonce, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const
 {
-    if (checkNonce(nonce))
+    if (checkNonce(directive, nonce))
         return true;
-    reportViolation(m_scriptNonce, consoleMessage + "\"script-nonce " + m_scriptNonce + "\".\n", KURL(), contextURL, contextLine);
+    reportViolation(directive->text(), consoleMessage + "\"" + directive->text() + "\".\n", KURL(), contextURL, contextLine);
     return denyIfEnforcingPolicy();
 }
 
-bool CSPDirectiveList::checkPluginTypeAndReportViolation(const String& type, const String& typeAttribute, const String& consoleMessage) const
+bool CSPDirectiveList::checkMediaTypeAndReportViolation(MediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const
 {
-    if (checkPluginType(type, typeAttribute))
+    if (checkMediaType(directive, type, typeAttribute))
         return true;
 
-    reportViolation(m_pluginTypesDirective, consoleMessage + "'plugin-types " + m_pluginTypesDirective + "'.\n", KURL());
+    reportViolation(directive->text(), consoleMessage + "\'" + directive->text() + "\'.\n", KURL());
     return denyIfEnforcingPolicy();
 }
 
-bool CSPDirectiveList::checkInlineAndReportViolation(CSPDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const
+bool CSPDirectiveList::checkInlineAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const
 {
     if (checkInline(directive))
         return true;
@@ -740,7 +873,7 @@
     return denyIfEnforcingPolicy();
 }
 
-bool CSPDirectiveList::checkSourceAndReportViolation(CSPDirective* directive, const KURL& url, const String& type) const
+bool CSPDirectiveList::checkSourceAndReportViolation(SourceListDirective* directive, const KURL& url, const String& type) const
 {
     if (checkSource(directive, url))
         return true;
@@ -760,10 +893,10 @@
     DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute _javascript_ URL because it violates the following Content Security Policy directive: "));
     if (reportingStatus == ContentSecurityPolicy::SendReport) {
         return (checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine)
-                && checkNonceAndReportViolation(String(), consoleMessage, contextURL, contextLine));
+                && checkNonceAndReportViolation(m_scriptNonce.get(), String(), consoleMessage, contextURL, contextLine));
     } else {
         return (checkInline(operativeDirective(m_scriptSrc.get()))
-                && checkNonce(String()));
+                && checkNonce(m_scriptNonce.get(), String()));
     }
 }
 
@@ -772,10 +905,10 @@
     DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline event handler because it violates the following Content Security Policy directive: "));
     if (reportingStatus == ContentSecurityPolicy::SendReport) {
         return (checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine)
-                && checkNonceAndReportViolation(String(), consoleMessage, contextURL, contextLine));
+                && checkNonceAndReportViolation(m_scriptNonce.get(), String(), consoleMessage, contextURL, contextLine));
     } else {
         return (checkInline(operativeDirective(m_scriptSrc.get()))
-                && checkNonce(String()));
+                && checkNonce(m_scriptNonce.get(), String()));
     }
 }
 
@@ -807,15 +940,15 @@
 {
     DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute script because it violates the following Content Security Policy directive: "));
     if (url.isEmpty())
-        return checkNonceAndReportViolation(nonce, consoleMessage, contextURL, contextLine);
-    return checkNonceAndReportViolation(nonce, "Refused to load '" + url.string() + "' because it violates the following Content Security Policy directive: ", contextURL, contextLine);
+        return checkNonceAndReportViolation(m_scriptNonce.get(), nonce, consoleMessage, contextURL, contextLine);
+    return checkNonceAndReportViolation(m_scriptNonce.get(), nonce, "Refused to load '" + url.string() + "' because it violates the following Content Security Policy directive: ", contextURL, contextLine);
 }
 
 bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
     return reportingStatus == ContentSecurityPolicy::SendReport ?
-        checkPluginTypeAndReportViolation(type, typeAttribute, "Refused to load '" + url.string() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ") :
-        checkPluginType(type, typeAttribute);
+        checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.string() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ") :
+        checkMediaType(m_pluginTypes.get(), type, typeAttribute);
 }
 
 bool CSPDirectiveList::allowScriptFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
@@ -1001,111 +1134,15 @@
     }
 }
 
-void CSPDirectiveList::parseScriptNonce(const String& name, const String& value)
-{
-    if (!m_scriptNonce.isNull()) {
-        m_policy->reportDuplicateDirective(name);
-        return;
-    }
 
-    String nonce;
-    const UChar* position = value.characters();
-    const UChar* end = position + value.length();
-
-    skipWhile<isASCIISpace>(position, end);
-    const UChar* nonceBegin = position;
-    if (position == end) {
-        m_policy->reportInvalidNonce(String());
-        m_scriptNonce = "";
-        return;
-    }
-    skipWhile<isNonceCharacter>(position, end);
-    if (nonceBegin < position)
-        nonce = String(nonceBegin, position - nonceBegin);
-
-    // Trim off trailing whitespace: If we're not at the end of the string, log
-    // an error.
-    skipWhile<isASCIISpace>(position, end);
-    if (position < end) {
-        m_policy->reportInvalidNonce(value);
-        m_scriptNonce = "";
-    } else
-        m_scriptNonce = nonce;
-}
-
-void CSPDirectiveList::parsePluginTypes(const String& name, const String& value)
+template<class CSPDirectiveType>
+void CSPDirectiveList::setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>& directive)
 {
-    if (!m_pluginTypesDirective.isNull()) {
-        m_policy->reportDuplicateDirective(name);
-        return;
-    }
-
-    const UChar* begin = value.characters();
-    const UChar* position = begin;
-    const UChar* end = begin + value.length();
-    m_pluginTypesDirective = value;
-
-    // 'plugin-types ____;' OR 'plugin-types;'
-    if (value.isEmpty()) {
-        m_policy->reportInvalidPluginTypes(value);
-        m_pluginTypesDirective = "";
-        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);
-            m_policy->reportInvalidPluginTypes(String(begin, position - begin));
-            continue;
-        }
-        skipWhile<isMediaTypeCharacter>(position, end);
-
-        // mime1/mime1 mime2/mime2
-        //      ^
-        if (!skipExactly(position, end, '/')) {
-            skipWhile<isNotASCIISpace>(position, end);
-            m_policy->reportInvalidPluginTypes(String(begin, position - begin));
-            continue;
-        }
-
-        // mime1/mime1 mime2/mime2
-        //       ^
-        if (!skipExactly<isMediaTypeCharacter>(position, end)) {
-            skipWhile<isNotASCIISpace>(position, end);
-            m_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);
-            m_policy->reportInvalidPluginTypes(String(begin, position - begin));
-            continue;
-        }
-        m_pluginTypes.add(String(begin, position - begin));
-
-        ASSERT(position == end || isASCIISpace(*position));
-    }
-}
-
-void CSPDirectiveList::setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirective>& directive)
-{
     if (directive) {
         m_policy->reportDuplicateDirective(name);
         return;
     }
-    directive = adoptPtr(new CSPDirective(name, value, m_policy));
+    directive = adoptPtr(new CSPDirectiveType(name, value, m_policy));
 }
 
 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy)
@@ -1140,34 +1177,34 @@
     ASSERT(!name.isEmpty());
 
     if (equalIgnoringCase(name, defaultSrc))
-        setCSPDirective(name, value, m_defaultSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_defaultSrc);
     else if (equalIgnoringCase(name, scriptSrc))
-        setCSPDirective(name, value, m_scriptSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_scriptSrc);
     else if (equalIgnoringCase(name, objectSrc))
-        setCSPDirective(name, value, m_objectSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_objectSrc);
     else if (equalIgnoringCase(name, frameSrc))
-        setCSPDirective(name, value, m_frameSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_frameSrc);
     else if (equalIgnoringCase(name, imgSrc))
-        setCSPDirective(name, value, m_imgSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_imgSrc);
     else if (equalIgnoringCase(name, styleSrc))
-        setCSPDirective(name, value, m_styleSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_styleSrc);
     else if (equalIgnoringCase(name, fontSrc))
-        setCSPDirective(name, value, m_fontSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_fontSrc);
     else if (equalIgnoringCase(name, mediaSrc))
-        setCSPDirective(name, value, m_mediaSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_mediaSrc);
     else if (equalIgnoringCase(name, connectSrc))
-        setCSPDirective(name, value, m_connectSrc);
+        setCSPDirective<SourceListDirective>(name, value, m_connectSrc);
     else if (equalIgnoringCase(name, sandbox))
         applySandboxPolicy(name, value);
     else if (equalIgnoringCase(name, reportURI))
         parseReportURI(name, value);
 #if ENABLE(CSP_NEXT)
     else if (equalIgnoringCase(name, formAction))
-        setCSPDirective(name, value, m_formAction);
+        setCSPDirective<SourceListDirective>(name, value, m_formAction);
     else if (equalIgnoringCase(name, pluginTypes))
-        parsePluginTypes(name, value);
+        setCSPDirective<MediaListDirective>(name, value, m_pluginTypes);
     else if (equalIgnoringCase(name, scriptNonce))
-        parseScriptNonce(name, value);
+        setCSPDirective<NonceDirective>(name, value, m_scriptNonce);
 #endif
     else
         m_policy->reportUnrecognizedDirective(name);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to