Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / frame / ContentSecurityPolicy.cpp
index 253c8d0..5414ba7 100644 (file)
@@ -310,7 +310,7 @@ public:
 
     bool matches(const KURL&);
     bool allowInline() const { return m_allowInline; }
-    bool allowEval() const { return m_allowEval; }
+    bool allowScriptEval() const { return m_allowScriptEval; }
     bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_nonces.contains(nonce); }
     bool allowHash(const SourceHashValue& hashValue) const { return m_hashes.contains(hashValue); }
     uint8_t hashAlgorithmsUsed() const { return m_hashAlgorithmsUsed; }
@@ -338,7 +338,7 @@ private:
     String m_directiveName;
     bool m_allowStar;
     bool m_allowInline;
-    bool m_allowEval;
+    bool m_allowScriptEval;
     HashSet<String> m_nonces;
     HashSet<SourceHashValue> m_hashes;
     uint8_t m_hashAlgorithmsUsed;
@@ -349,7 +349,7 @@ CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct
     , m_directiveName(directiveName)
     , m_allowStar(false)
     , m_allowInline(false)
-    , m_allowEval(false)
+    , m_allowScriptEval(false)
     , m_hashAlgorithmsUsed(0)
 {
 }
@@ -730,7 +730,7 @@ void CSPSourceList::addSourceUnsafeInline()
 
 void CSPSourceList::addSourceUnsafeEval()
 {
-    m_allowEval = true;
+    m_allowScriptEval = true;
 }
 
 void CSPSourceList::addSourceNonce(const String& nonce)
@@ -858,7 +858,7 @@ public:
     }
 
     bool allowInline() const { return m_sourceList.allowInline(); }
-    bool allowEval() const { return m_sourceList.allowEval(); }
+    bool allowScriptEval() const { return m_sourceList.allowScriptEval(); }
     bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce(nonce.stripWhiteSpace()); }
     bool allowHash(const SourceHashValue& hashValue) const { return m_sourceList.allowHash(hashValue); }
     bool isHashOrNoncePresent() const { return m_sourceList.isHashOrNoncePresent(); }
@@ -884,7 +884,8 @@ public:
     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(ScriptState*, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowScriptEval(ScriptState*, ContentSecurityPolicy::ReportingStatus) const;
+    bool allowStyleEval(ScriptState*, ContentSecurityPolicy::ReportingStatus) const;
     bool allowPluginType(const String& type, const String& typeAttribute, const KURL&, ContentSecurityPolicy::ReportingStatus) const;
 
     bool allowScriptFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const;
@@ -905,6 +906,7 @@ public:
     bool allowStyleHash(const SourceHashValue&) const;
 
     const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
+    const String& styleEvalDisabledErrorMessage() const { return m_styleEvalDisabledErrorMessage; }
     ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflectedXSSDisposition; }
     ReferrerPolicy referrerPolicy() const { return m_referrerPolicy; }
     bool didSetReferrerPolicy() const { return m_didSetReferrerPolicy; }
@@ -940,6 +942,7 @@ private:
     bool checkAncestors(SourceListDirective*, Frame*) const;
 
     void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisabledErrorMessage = errorMessage; }
+    void setStyleEvalDisabledErrorMessage(const String& errorMessage) { m_styleEvalDisabledErrorMessage = errorMessage; }
 
     bool checkEvalAndReportViolation(SourceListDirective*, const String& consoleMessage, ScriptState*) const;
     bool checkInlineAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
@@ -981,6 +984,7 @@ private:
     Vector<KURL> m_reportURIs;
 
     String m_evalDisabledErrorMessage;
+    String m_styleEvalDisabledErrorMessage;
 };
 
 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurityPolicy::HeaderType type, ContentSecurityPolicy::HeaderSource source)
@@ -1001,10 +1005,10 @@ PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* pol
     OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy, type, source));
     directives->parse(begin, end);
 
-    if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
-        String message = "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_scriptSrc.get())->text() + "\".\n";
-        directives->setEvalDisabledErrorMessage(message);
-    }
+    if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get())))
+        directives->setEvalDisabledErrorMessage("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");
+    if (!directives->checkEval(directives->operativeDirective(directives->m_styleSrc.get())))
+        directives->setStyleEvalDisabledErrorMessage("Refused to evaluate a string as CSS because 'unsafe-eval' is not an allowed source of style in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_styleSrc.get())->text() + "\".\n");
 
     if (directives->isReportOnly() && directives->reportURIs().isEmpty())
         policy->reportMissingReportURI(String(begin, end - begin));
@@ -1035,7 +1039,7 @@ void CSPDirectiveList::reportViolationWithState(const String& directiveText, con
 
 bool CSPDirectiveList::checkEval(SourceListDirective* directive) const
 {
-    return !directive || directive->allowEval();
+    return !directive || directive->allowScriptEval();
 }
 
 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
@@ -1223,7 +1227,7 @@ bool CSPDirectiveList::allowInlineStyle(const String& contextURL, const WTF::Ord
         checkInline(operativeDirective(m_styleSrc.get()));
 }
 
-bool CSPDirectiveList::allowEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+bool CSPDirectiveList::allowScriptEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
     DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "));
 
@@ -1232,6 +1236,15 @@ bool CSPDirectiveList::allowEval(ScriptState* state, ContentSecurityPolicy::Repo
         checkEval(operativeDirective(m_scriptSrc.get()));
 }
 
+bool CSPDirectiveList::allowStyleEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate a string as CSS because 'unsafe-eval' is not an allowed source of style in the following Content Security Policy directive: "));
+
+    return reportingStatus == ContentSecurityPolicy::SendReport ?
+        checkEvalAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, state) :
+        checkEval(operativeDirective(m_styleSrc.get()));
+}
+
 bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
     return reportingStatus == ContentSecurityPolicy::SendReport ?
@@ -1670,15 +1683,6 @@ void ContentSecurityPolicy::didReceiveHeaders(const ContentSecurityPolicyRespons
         didReceiveHeader(headers.contentSecurityPolicy(), ContentSecurityPolicy::Enforce, ContentSecurityPolicy::HeaderSourceHTTP);
     if (!headers.contentSecurityPolicyReportOnly().isEmpty())
         didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecurityPolicy::Report, ContentSecurityPolicy::HeaderSourceHTTP);
-
-    // FIXME: Remove this reporting (and the 'xWebKitCSP*' methods) after the next release branch.
-    if (m_client->isDocument()) {
-        Document* document = static_cast<Document*>(m_client);
-        if (!headers.xWebKitCSP().isEmpty())
-            UseCounter::countDeprecation(*document, UseCounter::PrefixedContentSecurityPolicy);
-        if (!headers.xWebKitCSPReportOnly().isEmpty())
-            UseCounter::countDeprecation(*document, UseCounter::PrefixedContentSecurityPolicyReportOnly);
-    }
 }
 
 void ContentSecurityPolicy::didReceiveHeader(const String& header, HeaderType type, HeaderSource source)
@@ -1688,9 +1692,8 @@ void ContentSecurityPolicy::didReceiveHeader(const String& header, HeaderType ty
 
 void ContentSecurityPolicy::addPolicyFromHeaderValue(const String& header, HeaderType type, HeaderSource source)
 {
-    Document* document = 0;
-    if (m_client->isDocument()) {
-        document = static_cast<Document*>(m_client);
+    Document* document = this->document();
+    if (document) {
         UseCounter::count(*document, getUseCounterType(type));
 
         // CSP 1.1 defines report-only in a <meta> element as invalid. Measure for now, disable in experimental mode.
@@ -1722,7 +1725,7 @@ void ContentSecurityPolicy::addPolicyFromHeaderValue(const String& header, Heade
         OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin, position, type, source);
 
         // We disable 'eval()' even in the case of report-only policies, and rely on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread callback to determine whether the call should execute or not.
-        if (!policy->allowEval(0, SuppressReport))
+        if (!policy->allowScriptEval(0, SuppressReport))
             m_client->disableEval(policy->evalDisabledErrorMessage());
 
         m_policies.append(policy.release());
@@ -1847,20 +1850,39 @@ bool ContentSecurityPolicy::allowInlineStyle(const String& contextURL, const WTF
     return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus);
 }
 
-bool ContentSecurityPolicy::allowEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+bool ContentSecurityPolicy::allowScriptEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    return isAllowedByAllWithState<&CSPDirectiveList::allowScriptEval>(m_policies, state, reportingStatus);
+}
+
+bool ContentSecurityPolicy::allowStyleEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
-    return isAllowedByAllWithState<&CSPDirectiveList::allowEval>(m_policies, state, reportingStatus);
+    if (!experimentalFeaturesEnabled()) {
+        if (Document* document = this->document())
+            UseCounter::count(*document, UseCounter::UnsafeEvalBlocksCSSOM);
+        return true;
+    }
+    return isAllowedByAllWithState<&CSPDirectiveList::allowStyleEval>(m_policies, state, reportingStatus);
 }
 
 String ContentSecurityPolicy::evalDisabledErrorMessage() const
 {
     for (size_t i = 0; i < m_policies.size(); ++i) {
-        if (!m_policies[i]->allowEval(0, SuppressReport))
+        if (!m_policies[i]->allowScriptEval(0, SuppressReport))
             return m_policies[i]->evalDisabledErrorMessage();
     }
     return String();
 }
 
+String ContentSecurityPolicy::styleEvalDisabledErrorMessage() const
+{
+    for (size_t i = 0; i < m_policies.size(); ++i) {
+        if (!m_policies[i]->allowStyleEval(0, SuppressReport))
+            return m_policies[i]->styleEvalDisabledErrorMessage();
+    }
+    return String();
+}
+
 bool ContentSecurityPolicy::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
 {
     for (size_t i = 0; i < m_policies.size(); ++i) {
@@ -1983,6 +2005,21 @@ bool ContentSecurityPolicy::allowChildContextFromSource(const KURL& url, Content
     return isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, reportingStatus);
 }
 
+bool ContentSecurityPolicy::allowWorkerContextFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+    // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure the impact of this backwards-incompatible change.
+    if (m_client->isDocument()) {
+        Document* document = static_cast<Document*>(m_client);
+        UseCounter::count(*document, UseCounter::WorkerSubjectToCSP);
+        if (isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, SuppressReport) && !isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, SuppressReport))
+            UseCounter::count(*document, UseCounter::WorkerAllowedByChildBlockedByScript);
+    }
+
+    return experimentalFeaturesEnabled() ?
+        isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, reportingStatus) :
+        isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, reportingStatus);
+}
+
 bool ContentSecurityPolicy::isActive() const
 {
     return !m_policies.isEmpty();
@@ -2039,8 +2076,8 @@ KURL ContentSecurityPolicy::completeURL(const String& url) const
 
 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const
 {
-    if (m_client->isDocument())
-        static_cast<Document*>(m_client)->enforceSandboxFlags(mask);
+    if (Document* document = this->document())
+        document->enforceSandboxFlags(mask);
 }
 
 static String stripURLForUseInReport(Document* document, const KURL& url)
@@ -2088,7 +2125,7 @@ void ContentSecurityPolicy::reportViolation(const String& directiveText, const S
     if (!m_client->isDocument())
         return;
 
-    Document* document = static_cast<Document*>(m_client);
+    Document* document = this->document();
     Frame* frame = document->frame();
     if (!frame)
         return;
@@ -2152,6 +2189,11 @@ void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) const
     logToConsole("The report-only Content Security Policy '" + header + "' was delivered via a <meta> element, which is disallowed. The policy has been ignored.");
 }
 
+void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) const
+{
+    logToConsole("The Content Security Policy '" + header + "' was delivered via a <meta> element outside the document's <head>, which is disallowed. The policy has been ignored.");
+}
+
 void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) const
 {
     logToConsole("The Content Security Policy directive '" + name + "' is ignored when delivered in a report-only policy.");