summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2018-01-11 05:56:18 +0300
committerLiang Qi <liang.qi@qt.io>2018-01-11 10:25:26 +0000
commit79143ccfc158ec4fffc49eee600d600edb342b16 (patch)
tree0e078499d8fe3e8627e3612537e61f2dd1029625
parentcb895f50d5c08976c0f5ecbb82e6bd19d9ea090d (diff)
Import WebKit commit a8b574fb3cd509a2d3f2a1568ad0a66d1bf0f6e8
Change-Id: I66add69e6d08b74111ec8e7e4401e4d813501206 Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
-rw-r--r--Source/WebCore/CMakeLists.txt1
-rw-r--r--Source/WebCore/PlatformQt.cmake2
-rw-r--r--Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA1.cpp2
-rw-r--r--Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA224.cpp2
-rw-r--r--Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA256.cpp2
-rw-r--r--Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA384.cpp2
-rw-r--r--Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA512.cpp2
-rw-r--r--Source/WebCore/dom/InlineStyleSheetOwner.cpp6
-rw-r--r--Source/WebCore/dom/ScriptElement.cpp12
-rw-r--r--Source/WebCore/dom/StyledElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLLinkElement.cpp8
-rw-r--r--Source/WebCore/html/HTMLScriptElement.idl2
-rw-r--r--Source/WebCore/html/HTMLStyleElement.idl2
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicy.cpp101
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicy.h22
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp94
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h10
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicyHash.h69
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp110
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicySourceList.h20
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp10
-rw-r--r--Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h4
-rw-r--r--Source/WebCore/platform/crypto/CryptoDigest.h (renamed from Source/WebCore/crypto/CryptoDigest.h)15
-rw-r--r--Source/WebCore/platform/crypto/qt/CryptoDigestQt.cpp93
-rw-r--r--Source/WebKit/PlatformQt.cmake2
-rw-r--r--Source/WebKit2/PlatformQt.cmake12
-rw-r--r--Source/WebKit2/Shared/qt/ProcessExecutablePathQt.cpp7
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp1
-rw-r--r--Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp6
-rw-r--r--Source/cmake/OptionsQt.cmake55
-rw-r--r--Source/cmake/WebKitMacros.cmake2
-rw-r--r--Tools/qmake/projects/run_cmake.pro5
32 files changed, 595 insertions, 88 deletions
diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt
index 02f9d3bf3..e9fc4e54e 100644
--- a/Source/WebCore/CMakeLists.txt
+++ b/Source/WebCore/CMakeLists.txt
@@ -68,6 +68,7 @@ set(WebCore_INCLUDE_DIRECTORIES
"${WEBCORE_DIR}/platform"
"${WEBCORE_DIR}/platform/animation"
"${WEBCORE_DIR}/platform/audio"
+ "${WEBCORE_DIR}/platform/crypto"
"${WEBCORE_DIR}/platform/graphics"
"${WEBCORE_DIR}/platform/graphics/cpu/arm"
"${WEBCORE_DIR}/platform/graphics/cpu/arm/filters"
diff --git a/Source/WebCore/PlatformQt.cmake b/Source/WebCore/PlatformQt.cmake
index d237a83a6..49c76a8de 100644
--- a/Source/WebCore/PlatformQt.cmake
+++ b/Source/WebCore/PlatformQt.cmake
@@ -73,6 +73,8 @@ list(APPEND WebCore_SOURCES
platform/audio/qt/AudioBusQt.cpp
+ platform/crypto/qt/CryptoDigestQt.cpp
+
platform/graphics/ImageSource.cpp
platform/graphics/PlatformDisplay.cpp
platform/graphics/WOFFFileFormat.cpp
diff --git a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA1.cpp b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA1.cpp
index bc94aa3de..54dcd03fb 100644
--- a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA1.cpp
+++ b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA1.cpp
@@ -54,7 +54,7 @@ CryptoAlgorithmIdentifier CryptoAlgorithmSHA1::identifier() const
void CryptoAlgorithmSHA1::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback, ExceptionCode&)
{
- std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_1);
+ std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoDigest::Algorithm::SHA_1);
if (!digest) {
failureCallback();
return;
diff --git a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA224.cpp b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA224.cpp
index 62cc5a8c2..3878227d9 100644
--- a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA224.cpp
+++ b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA224.cpp
@@ -54,7 +54,7 @@ CryptoAlgorithmIdentifier CryptoAlgorithmSHA224::identifier() const
void CryptoAlgorithmSHA224::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback, ExceptionCode&)
{
- std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_224);
+ std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoDigest::Algorithm::SHA_224);
if (!digest) {
failureCallback();
return;
diff --git a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA256.cpp b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA256.cpp
index 27fe8aa0a..0acaf0905 100644
--- a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA256.cpp
+++ b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA256.cpp
@@ -54,7 +54,7 @@ CryptoAlgorithmIdentifier CryptoAlgorithmSHA256::identifier() const
void CryptoAlgorithmSHA256::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback, ExceptionCode&)
{
- std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_256);
+ std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoDigest::Algorithm::SHA_256);
if (!digest) {
failureCallback();
return;
diff --git a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA384.cpp b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA384.cpp
index 6eba234f3..b1bfbe157 100644
--- a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA384.cpp
+++ b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA384.cpp
@@ -54,7 +54,7 @@ CryptoAlgorithmIdentifier CryptoAlgorithmSHA384::identifier() const
void CryptoAlgorithmSHA384::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback, ExceptionCode&)
{
- std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_384);
+ std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoDigest::Algorithm::SHA_384);
if (!digest) {
failureCallback();
return;
diff --git a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA512.cpp b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA512.cpp
index 87d62d445..7ddf1d4d2 100644
--- a/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA512.cpp
+++ b/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA512.cpp
@@ -54,7 +54,7 @@ CryptoAlgorithmIdentifier CryptoAlgorithmSHA512::identifier() const
void CryptoAlgorithmSHA512::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback, ExceptionCode&)
{
- std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_512);
+ std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoDigest::Algorithm::SHA_512);
if (!digest) {
failureCallback();
return;
diff --git a/Source/WebCore/dom/InlineStyleSheetOwner.cpp b/Source/WebCore/dom/InlineStyleSheetOwner.cpp
index 83574842c..a487f6041 100644
--- a/Source/WebCore/dom/InlineStyleSheetOwner.cpp
+++ b/Source/WebCore/dom/InlineStyleSheetOwner.cpp
@@ -137,7 +137,11 @@ void InlineStyleSheetOwner::createSheet(Element& element, const String& text)
if (!isValidCSSContentType(element, m_contentType))
return;
- if (!document.contentSecurityPolicy()->allowInlineStyle(document.url(), m_startTextPosition.m_line, element.isInUserAgentShadowTree()))
+
+ ASSERT(document.contentSecurityPolicy());
+ const ContentSecurityPolicy& contentSecurityPolicy = *document.contentSecurityPolicy();
+ bool hasKnownNonce = contentSecurityPolicy.allowStyleWithNonce(element.fastGetAttribute(HTMLNames::nonceAttr), element.isInUserAgentShadowTree());
+ if (!contentSecurityPolicy.allowInlineStyle(document.url(), m_startTextPosition.m_line, text, hasKnownNonce))
return;
RefPtr<MediaQuerySet> mediaQueries;
diff --git a/Source/WebCore/dom/ScriptElement.cpp b/Source/WebCore/dom/ScriptElement.cpp
index 521028195..f9c70e326 100644
--- a/Source/WebCore/dom/ScriptElement.cpp
+++ b/Source/WebCore/dom/ScriptElement.cpp
@@ -258,8 +258,9 @@ bool ScriptElement::requestScript(const String& sourceUrl)
ASSERT(!m_cachedScript);
if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) {
+ bool hasKnownNonce = m_element.document().contentSecurityPolicy()->allowScriptWithNonce(m_element.fastGetAttribute(HTMLNames::nonceAttr), m_element.isInUserAgentShadowTree());
ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
- options.setContentSecurityPolicyImposition(m_element.isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
+ options.setContentSecurityPolicyImposition(hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
CachedResourceRequest request(ResourceRequest(m_element.document().completeURL(sourceUrl)), options);
@@ -293,8 +294,13 @@ void ScriptElement::executeScript(const ScriptSourceCode& sourceCode)
if (sourceCode.isEmpty())
return;
- if (!m_isExternalScript && !m_element.document().contentSecurityPolicy()->allowInlineScript(m_element.document().url(), m_startLineNumber, m_element.isInUserAgentShadowTree()))
- return;
+ if (!m_isExternalScript) {
+ ASSERT(m_element.document().contentSecurityPolicy());
+ const ContentSecurityPolicy& contentSecurityPolicy = *m_element.document().contentSecurityPolicy();
+ bool hasKnownNonce = contentSecurityPolicy.allowScriptWithNonce(m_element.fastGetAttribute(HTMLNames::nonceAttr), m_element.isInUserAgentShadowTree());
+ if (!contentSecurityPolicy.allowInlineScript(m_element.document().url(), m_startLineNumber, sourceCode.source().toStringWithoutCopying(), hasKnownNonce))
+ return;
+ }
#if ENABLE(NOSNIFF)
if (m_isExternalScript && m_cachedScript && !m_cachedScript->mimeTypeAllowedByNosniff()) {
diff --git a/Source/WebCore/dom/StyledElement.cpp b/Source/WebCore/dom/StyledElement.cpp
index e5d06633d..e7c328a44 100644
--- a/Source/WebCore/dom/StyledElement.cpp
+++ b/Source/WebCore/dom/StyledElement.cpp
@@ -202,7 +202,7 @@ void StyledElement::styleAttributeChanged(const AtomicString& newStyleString, At
if (PropertySetCSSStyleDeclaration* cssomWrapper = inlineStyleCSSOMWrapper())
cssomWrapper->clearParentElement();
ensureUniqueElementData().m_inlineStyle = nullptr;
- } else if (reason == ModifiedByCloning || document().contentSecurityPolicy()->allowInlineStyle(document().url(), startLineNumber, isInUserAgentShadowTree()))
+ } else if (reason == ModifiedByCloning || document().contentSecurityPolicy()->allowInlineStyle(document().url(), startLineNumber, String(), isInUserAgentShadowTree()))
setInlineStyleFromString(newStyleString);
elementData()->setStyleAttributeIsDirty(false);
diff --git a/Source/WebCore/html/HTMLLinkElement.cpp b/Source/WebCore/html/HTMLLinkElement.cpp
index 49c15ce12..4a73e530d 100644
--- a/Source/WebCore/html/HTMLLinkElement.cpp
+++ b/Source/WebCore/html/HTMLLinkElement.cpp
@@ -32,6 +32,7 @@
#include "CachedResource.h"
#include "CachedResourceLoader.h"
#include "CachedResourceRequest.h"
+#include "ContentSecurityPolicy.h"
#include "Document.h"
#include "Event.h"
#include "EventSender.h"
@@ -245,6 +246,13 @@ void HTMLLinkElement::process()
priority = ResourceLoadPriority::VeryLow;
CachedResourceRequest request(ResourceRequest(document().completeURL(url)), charset, priority);
request.setInitiator(this);
+
+ if (document().contentSecurityPolicy()->allowStyleWithNonce(fastGetAttribute(HTMLNames::nonceAttr))) {
+ ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
+ options.setContentSecurityPolicyImposition(ContentSecurityPolicyImposition::SkipPolicyCheck);
+ request.setOptions(options);
+ }
+
m_cachedSheet = document().cachedResourceLoader().requestCSSStyleSheet(request);
if (m_cachedSheet)
diff --git a/Source/WebCore/html/HTMLScriptElement.idl b/Source/WebCore/html/HTMLScriptElement.idl
index 1365d12bf..ff0b30aac 100644
--- a/Source/WebCore/html/HTMLScriptElement.idl
+++ b/Source/WebCore/html/HTMLScriptElement.idl
@@ -27,5 +27,5 @@ interface HTMLScriptElement : HTMLElement {
[Reflect, URL] attribute DOMString src;
[Reflect] attribute DOMString type;
[Reflect] attribute DOMString crossOrigin;
- [Reflect, Conditional=CSP_NEXT] attribute DOMString nonce;
+ [Reflect] attribute DOMString nonce;
};
diff --git a/Source/WebCore/html/HTMLStyleElement.idl b/Source/WebCore/html/HTMLStyleElement.idl
index 7abf3839f..fd3f7c0d3 100644
--- a/Source/WebCore/html/HTMLStyleElement.idl
+++ b/Source/WebCore/html/HTMLStyleElement.idl
@@ -25,5 +25,7 @@ interface HTMLStyleElement : HTMLElement {
// DOM Level 2 Style
readonly attribute StyleSheet sheet;
+
+ [Reflect] attribute DOMString nonce;
};
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
index 19bf207fa..9e726d5fe 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
+++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp
@@ -29,14 +29,17 @@
#include "ContentSecurityPolicyDirective.h"
#include "ContentSecurityPolicyDirectiveList.h"
+#include "ContentSecurityPolicyHash.h"
#include "ContentSecurityPolicySource.h"
#include "ContentSecurityPolicySourceList.h"
+#include "CryptoDigest.h"
#include "DOMStringList.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "FormData.h"
#include "FormDataList.h"
#include "Frame.h"
+#include "HTMLParserIdioms.h"
#include "InspectorInstrumentation.h"
#include "JSMainThreadExecState.h"
#include "ParsingUtilities.h"
@@ -45,6 +48,7 @@
#include "SchemeRegistry.h"
#include "SecurityOrigin.h"
#include "SecurityPolicyViolationEvent.h"
+#include "TextEncoding.h"
#include <inspector/InspectorValues.h>
#include <inspector/ScriptCallStack.h>
#include <inspector/ScriptCallStackFactory.h>
@@ -193,6 +197,48 @@ bool isAllowedByAllWithContext(const CSPDirectiveListVector& policies, const Str
return true;
}
+template<bool (ContentSecurityPolicyDirectiveList::*allowed)(const String& nonce) const>
+static bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const String& nonce)
+{
+ for (auto& policy : policies) {
+ if (!(policy.get()->*allowed)(nonce))
+ return false;
+ }
+ return true;
+}
+
+static CryptoDigest::Algorithm toCryptoDigestAlgorithm(ContentSecurityPolicyHashAlgorithm algorithm)
+{
+ switch (algorithm) {
+ case ContentSecurityPolicyHashAlgorithm::SHA_256:
+ return CryptoDigest::Algorithm::SHA_256;
+ case ContentSecurityPolicyHashAlgorithm::SHA_384:
+ return CryptoDigest::Algorithm::SHA_384;
+ case ContentSecurityPolicyHashAlgorithm::SHA_512:
+ return CryptoDigest::Algorithm::SHA_512;
+ }
+ ASSERT_NOT_REACHED();
+ return CryptoDigest::Algorithm::SHA_512;
+}
+
+template<bool (ContentSecurityPolicyDirectiveList::*allowed)(const ContentSecurityPolicyHash&) const>
+bool isAllowedByAllWithHashFromContent(const CSPDirectiveListVector& policies, const String& content, const TextEncoding& encoding, OptionSet<ContentSecurityPolicyHashAlgorithm> algorithms)
+{
+ // FIXME: Compute the digest with respect to the raw bytes received from the page.
+ // See <https://bugs.webkit.org/show_bug.cgi?id=155184>.
+ CString contentCString = encoding.encode(content, EntitiesForUnencodables);
+ for (auto algorithm : algorithms) {
+ auto cryptoDigest = CryptoDigest::create(toCryptoDigestAlgorithm(algorithm));
+ cryptoDigest->addBytes(contentCString.data(), contentCString.length());
+ Vector<uint8_t> digest = cryptoDigest->computeHash();
+ for (auto& policy : policies) {
+ if ((policy.get()->*allowed)(std::make_pair(algorithm, digest)))
+ return true;
+ }
+ }
+ return false;
+}
+
template<bool (ContentSecurityPolicyDirectiveList::*allowFromURL)(const URL&, ContentSecurityPolicy::ReportingStatus) const>
bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus)
{
@@ -216,14 +262,61 @@ bool ContentSecurityPolicy::allowInlineEventHandlers(const String& contextURL, c
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
+// FIXME: We should compute the document encoding once and cache it instead of computing it on each invocation.
+const TextEncoding& ContentSecurityPolicy::documentEncoding() const
{
- return overrideContentSecurityPolicy || isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowInlineScript>(m_policies, contextURL, contextLine, reportingStatus);
+ if (!is<Document>(m_scriptExecutionContext))
+ return UTF8Encoding();
+ Document& document = downcast<Document>(*m_scriptExecutionContext);
+ if (TextResourceDecoder* decoder = document.decoder())
+ return decoder->encoding();
+ return UTF8Encoding();
}
-bool ContentSecurityPolicy::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+bool ContentSecurityPolicy::allowScriptWithNonce(const String& nonce, bool overrideContentSecurityPolicy) const
{
- return overrideContentSecurityPolicy || m_overrideInlineStyleAllowed || isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus);
+ if (overrideContentSecurityPolicy)
+ return true;
+ String strippedNonce = stripLeadingAndTrailingHTMLSpaces(nonce);
+ if (strippedNonce.isEmpty())
+ return false;
+ if (isAllowedByAllWithNonce<&ContentSecurityPolicyDirectiveList::allowScriptWithNonce>(m_policies, strippedNonce))
+ return true;
+ return false;
+}
+
+bool ContentSecurityPolicy::allowStyleWithNonce(const String& nonce, bool overrideContentSecurityPolicy) const
+{
+ if (overrideContentSecurityPolicy)
+ return true;
+ String strippedNonce = stripLeadingAndTrailingHTMLSpaces(nonce);
+ if (strippedNonce.isEmpty())
+ return false;
+ if (isAllowedByAllWithNonce<&ContentSecurityPolicyDirectiveList::allowStyleWithNonce>(m_policies, strippedNonce))
+ return true;
+ return false;
+}
+
+bool ContentSecurityPolicy::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, const String& scriptContent, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+ if (overrideContentSecurityPolicy)
+ return true;
+ if (!m_hashAlgorithmsForInlineScripts.isEmpty() && !scriptContent.isEmpty()
+ && isAllowedByAllWithHashFromContent<&ContentSecurityPolicyDirectiveList::allowInlineScriptWithHash>(m_policies, scriptContent, documentEncoding(), m_hashAlgorithmsForInlineScripts))
+ return true;
+ return isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowInlineScript>(m_policies, contextURL, contextLine, reportingStatus);
+}
+
+bool ContentSecurityPolicy::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, const String& styleContent, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+ if (overrideContentSecurityPolicy)
+ return true;
+ if (m_overrideInlineStyleAllowed)
+ return true;
+ if (!m_hashAlgorithmsForInlineStylesheets.isEmpty() && !styleContent.isEmpty()
+ && isAllowedByAllWithHashFromContent<&ContentSecurityPolicyDirectiveList::allowInlineStyleWithHash>(m_policies, styleContent, documentEncoding(), m_hashAlgorithmsForInlineStylesheets))
+ return true;
+ return isAllowedByAllWithContext<&ContentSecurityPolicyDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus);
}
bool ContentSecurityPolicy::allowEval(JSC::ExecState* state, bool overrideContentSecurityPolicy, ContentSecurityPolicy::ReportingStatus reportingStatus) const
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.h b/Source/WebCore/page/csp/ContentSecurityPolicy.h
index 14c60f5c4..dcc05a173 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicy.h
+++ b/Source/WebCore/page/csp/ContentSecurityPolicy.h
@@ -29,6 +29,7 @@
#include "ContentSecurityPolicyResponseHeaders.h"
#include "ScriptState.h"
+#include <wtf/OptionSet.h>
#include <wtf/Vector.h>
#include <wtf/text/TextPosition.h>
@@ -43,8 +44,11 @@ class ContentSecurityPolicySource;
class DOMStringList;
class ScriptExecutionContext;
class SecurityOrigin;
+class TextEncoding;
class URL;
+enum class ContentSecurityPolicyHashAlgorithm;
+
typedef Vector<std::unique_ptr<ContentSecurityPolicyDirectiveList>> CSPDirectiveListVector;
typedef int SandboxFlags;
@@ -82,8 +86,10 @@ public:
};
bool allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
- bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
- bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
+ bool allowScriptWithNonce(const String& nonce, bool overrideContentSecurityPolicy = false) const;
+ bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, const String& scriptContent, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
+ bool allowStyleWithNonce(const String& nonce, bool overrideContentSecurityPolicy = false) const;
+ bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, const String& styleContent, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
bool allowEval(JSC::ExecState* = nullptr, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
bool allowPluginType(const String& type, const String& typeAttribute, const URL&, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
bool allowScriptFromSource(const URL&, bool overrideContentSecurityPolicy = false, ContentSecurityPolicy::ReportingStatus = ContentSecurityPolicy::ReportingStatus::SendReport) const;
@@ -134,6 +140,14 @@ public:
void reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const URL& blockedURL, const Vector<String>& reportURIs, const String& header, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), JSC::ExecState* = nullptr) const;
void reportBlockedScriptExecutionToInspector(const String& directiveText) const;
void enforceSandboxFlags(SandboxFlags sandboxFlags) { m_sandboxFlags |= sandboxFlags; }
+ void addHashAlgorithmsForInlineScripts(OptionSet<ContentSecurityPolicyHashAlgorithm> hashAlgorithmsForInlineScripts)
+ {
+ m_hashAlgorithmsForInlineScripts |= hashAlgorithmsForInlineScripts;
+ }
+ void addHashAlgorithmsForInlineStylesheets(OptionSet<ContentSecurityPolicyHashAlgorithm> hashAlgorithmsForInlineStylesheets)
+ {
+ m_hashAlgorithmsForInlineStylesheets |= hashAlgorithmsForInlineStylesheets;
+ }
// Used by ContentSecurityPolicySource
bool protocolMatchesSelf(const URL&) const;
@@ -145,6 +159,8 @@ private:
void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicy::PolicyFrom);
+ const TextEncoding& documentEncoding() const;
+
ScriptExecutionContext* m_scriptExecutionContext { nullptr };
std::unique_ptr<ContentSecurityPolicySource> m_selfSource;
String m_selfSourceProtocol;
@@ -152,6 +168,8 @@ private:
String m_lastPolicyEvalDisabledErrorMessage;
SandboxFlags m_sandboxFlags;
bool m_overrideInlineStyleAllowed { false };
+ OptionSet<ContentSecurityPolicyHashAlgorithm> m_hashAlgorithmsForInlineScripts;
+ OptionSet<ContentSecurityPolicyHashAlgorithm> m_hashAlgorithmsForInlineStylesheets;
};
}
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp b/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp
index 01cfa5134..47f5da456 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp
+++ b/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp
@@ -105,6 +105,40 @@ static bool isNotASCIISpace(UChar c)
return !isASCIISpace(c);
}
+static inline bool checkEval(ContentSecurityPolicySourceListDirective* directive)
+{
+ return !directive || directive->allowEval();
+}
+
+static inline bool checkInline(ContentSecurityPolicySourceListDirective* directive)
+{
+ return !directive || directive->allowInline();
+}
+
+static inline bool checkSource(ContentSecurityPolicySourceListDirective* directive, const URL& url)
+{
+ return !directive || directive->allows(url);
+}
+
+static inline bool checkHash(ContentSecurityPolicySourceListDirective* directive, const ContentSecurityPolicyHash& hash)
+{
+ return !directive || directive->allows(hash);
+}
+
+static inline bool checkNonce(ContentSecurityPolicySourceListDirective* directive, const String& nonce)
+{
+ return !directive || directive->allows(nonce);
+}
+
+static inline bool checkMediaType(ContentSecurityPolicyMediaListDirective* directive, const String& type, const String& typeAttribute)
+{
+ if (!directive)
+ return true;
+ if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
+ return false;
+ return directive->allows(type);
+}
+
ContentSecurityPolicyDirectiveList::ContentSecurityPolicyDirectiveList(ContentSecurityPolicy& policy, ContentSecurityPolicyHeaderType type)
: m_policy(policy)
, m_headerType(type)
@@ -120,7 +154,7 @@ std::unique_ptr<ContentSecurityPolicyDirectiveList> ContentSecurityPolicyDirecti
auto directives = std::make_unique<ContentSecurityPolicyDirectiveList>(policy, type);
directives->parse(header, from);
- if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
+ if (!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);
}
@@ -137,30 +171,6 @@ void ContentSecurityPolicyDirectiveList::reportViolation(const String& directive
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();
@@ -278,6 +288,16 @@ bool ContentSecurityPolicyDirectiveList::allowInlineScript(const String& context
return m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get()));
}
+bool ContentSecurityPolicyDirectiveList::allowInlineScriptWithHash(const ContentSecurityPolicyHash& hash) const
+{
+ return checkHash(operativeDirective(m_scriptSrc.get()), hash);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowScriptWithNonce(const String& nonce) const
+{
+ return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
+}
+
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: "));
@@ -286,6 +306,16 @@ bool ContentSecurityPolicyDirectiveList::allowInlineStyle(const String& contextU
return m_reportOnly || checkInline(operativeDirective(m_styleSrc.get()));
}
+bool ContentSecurityPolicyDirectiveList::allowInlineStyleWithHash(const ContentSecurityPolicyHash& hash) const
+{
+ return checkHash(operativeDirective(m_styleSrc.get()), hash);
+}
+
+bool ContentSecurityPolicyDirectiveList::allowStyleWithNonce(const String& nonce) const
+{
+ return checkNonce(operativeDirective(m_styleSrc.get()), nonce);
+}
+
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: "));
@@ -579,18 +609,22 @@ void ContentSecurityPolicyDirectiveList::addDirective(const String& name, const
{
ASSERT(!name.isEmpty());
- if (equalLettersIgnoringASCIICase(name, defaultSrc))
+ if (equalLettersIgnoringASCIICase(name, defaultSrc)) {
setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_defaultSrc);
- else if (equalLettersIgnoringASCIICase(name, scriptSrc))
+ m_policy.addHashAlgorithmsForInlineScripts(m_defaultSrc->hashAlgorithmsUsed());
+ m_policy.addHashAlgorithmsForInlineStylesheets(m_defaultSrc->hashAlgorithmsUsed());
+ } else if (equalLettersIgnoringASCIICase(name, scriptSrc)) {
setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_scriptSrc);
- else if (equalLettersIgnoringASCIICase(name, objectSrc))
+ m_policy.addHashAlgorithmsForInlineScripts(m_scriptSrc->hashAlgorithmsUsed());
+ } else if (equalLettersIgnoringASCIICase(name, styleSrc)) {
+ setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_styleSrc);
+ m_policy.addHashAlgorithmsForInlineStylesheets(m_styleSrc->hashAlgorithmsUsed());
+ } 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))
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h b/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h
index 2a98b2d09..997c2a5a6 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h
+++ b/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h
@@ -28,6 +28,7 @@
#define ContentSecurityPolicyDirectiveList_h
#include "ContentSecurityPolicy.h"
+#include "ContentSecurityPolicyHash.h"
#include "ContentSecurityPolicyMediaListDirective.h"
#include "ContentSecurityPolicySourceListDirective.h"
#include "URL.h"
@@ -50,7 +51,11 @@ public:
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 allowInlineScriptWithHash(const ContentSecurityPolicyHash&) const;
+ bool allowScriptWithNonce(const String& nonce) const;
bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
+ bool allowInlineStyleWithHash(const ContentSecurityPolicyHash&) const;
+ bool allowStyleWithNonce(const String& nonce) const;
bool allowEval(JSC::ExecState*, ContentSecurityPolicy::ReportingStatus) const;
bool allowPluginType(const String& type, const String& typeAttribute, const URL&, ContentSecurityPolicy::ReportingStatus) const;
@@ -87,11 +92,6 @@ private:
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;
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyHash.h b/Source/WebCore/page/csp/ContentSecurityPolicyHash.h
new file mode 100644
index 000000000..12a94f261
--- /dev/null
+++ b/Source/WebCore/page/csp/ContentSecurityPolicyHash.h
@@ -0,0 +1,69 @@
+/*
+ * 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 APPLE INC. AND ITS CONTRIBUTORS ``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 ITS 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 ContentSecurityPolicyHash_h
+#define ContentSecurityPolicyHash_h
+
+#include <wtf/HashTraits.h>
+#include <wtf/Hasher.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// Keep this synchronized with the constant maximumContentSecurityPolicyDigestLength below.
+enum class ContentSecurityPolicyHashAlgorithm {
+ SHA_256 = 1 << 0,
+ SHA_384 = 1 << 1,
+ SHA_512 = 1 << 2,
+};
+
+const size_t maximumContentSecurityPolicyDigestLength = 64; // bytes to hold SHA-512 digest
+
+typedef Vector<uint8_t> ContentSecurityPolicyDigest;
+typedef std::pair<ContentSecurityPolicyHashAlgorithm, ContentSecurityPolicyDigest> ContentSecurityPolicyHash;
+
+}
+
+namespace WTF {
+
+template<> struct DefaultHash<WebCore::ContentSecurityPolicyHashAlgorithm> { typedef IntHash<WebCore::ContentSecurityPolicyHashAlgorithm> Hash; };
+template<> struct HashTraits<WebCore::ContentSecurityPolicyHashAlgorithm> : StrongEnumHashTraits<WebCore::ContentSecurityPolicyHashAlgorithm> { };
+template<> struct DefaultHash<WebCore::ContentSecurityPolicyDigest> {
+ struct Hash {
+ static unsigned hash(const WebCore::ContentSecurityPolicyDigest& digest)
+ {
+ return StringHasher::computeHashAndMaskTop8Bits(digest.data(), digest.size());
+ }
+ static bool equal(const WebCore::ContentSecurityPolicyDigest& a, const WebCore::ContentSecurityPolicyDigest& b)
+ {
+ return a == b;
+ }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+};
+
+}
+
+#endif // ContentSecurityPolicyHash_h
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp b/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp
index 408b40e2b..8044ae8bf 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp
+++ b/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp
@@ -33,6 +33,8 @@
#include "SecurityOrigin.h"
#include "URL.h"
#include <wtf/ASCIICType.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/Base64.h>
namespace WebCore {
@@ -125,6 +127,16 @@ bool ContentSecurityPolicySourceList::matches(const URL& url)
return false;
}
+bool ContentSecurityPolicySourceList::matches(const ContentSecurityPolicyHash& hash) const
+{
+ return m_hashes.contains(hash);
+}
+
+bool ContentSecurityPolicySourceList::matches(const String& nonce) const
+{
+ return m_nonces.contains(nonce);
+}
+
// source-list = *WSP [ source *( 1*WSP source ) *WSP ]
// / *WSP "'none'" *WSP
//
@@ -145,6 +157,12 @@ void ContentSecurityPolicySourceList::parse(const UChar* begin, const UChar* end
bool hostHasWildcard = false;
bool portHasWildcard = false;
+ if (parseNonceSource(beginSource, position))
+ continue;
+
+ if (parseHashSource(beginSource, position))
+ continue;
+
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
@@ -385,4 +403,96 @@ bool ContentSecurityPolicySourceList::parsePort(const UChar* begin, const UChar*
return ok;
}
+static bool isBase64Character(UChar c)
+{
+ return isASCIIAlphanumeric(c) || c == '+' || c == '/' || c == '-' || c == '_';
+}
+
+// Match Blink's behavior of allowing an equal sign to appear anywhere in the value of the nonce
+// even though this does not match the behavior of Content Security Policy Level 3 spec.,
+// <https://w3c.github.io/webappsec-csp/> (29 February 2016).
+static bool isNonceCharacter(UChar c)
+{
+ return isBase64Character(c) || c == '=';
+}
+
+// nonce-source = "'nonce-" nonce-value "'"
+// nonce-value = base64-value
+bool ContentSecurityPolicySourceList::parseNonceSource(const UChar* begin, const UChar* end)
+{
+ static NeverDestroyed<String> noncePrefix("'nonce-", String::ConstructFromLiteral);
+ if (!StringView(begin, end - begin).startsWithIgnoringASCIICase(noncePrefix.get()))
+ return false;
+ const UChar* position = begin + noncePrefix.get().length();
+ const UChar* beginNonceValue = position;
+ skipWhile<UChar, isNonceCharacter>(position, end);
+ if (position >= end || position == beginNonceValue || *position != '\'')
+ return false;
+ m_nonces.add(String(beginNonceValue, position - beginNonceValue));
+ return true;
+}
+
+static bool parseHashAlgorithmAdvancingPosition(const UChar*& position, size_t length, ContentSecurityPolicyHashAlgorithm& algorithm)
+{
+ static struct {
+ NeverDestroyed<String> label;
+ ContentSecurityPolicyHashAlgorithm algorithm;
+ } labelToHashAlgorithmTable[] {
+ { ASCIILiteral("sha256"), ContentSecurityPolicyHashAlgorithm::SHA_256 },
+ { ASCIILiteral("sha384"), ContentSecurityPolicyHashAlgorithm::SHA_384 },
+ { ASCIILiteral("sha512"), ContentSecurityPolicyHashAlgorithm::SHA_512 },
+ };
+
+ StringView stringView(position, length);
+ for (auto& entry : labelToHashAlgorithmTable) {
+ String& label = entry.label.get();
+ if (!stringView.startsWithIgnoringASCIICase(label))
+ continue;
+ position += label.length();
+ algorithm = entry.algorithm;
+ return true;
+ }
+ return false;
+}
+
+// hash-source = "'" hash-algorithm "-" base64-value "'"
+// hash-algorithm = "sha256" / "sha384" / "sha512"
+// base64-value = 1*( ALPHA / DIGIT / "+" / "/" / "-" / "_" )*2( "=" )
+bool ContentSecurityPolicySourceList::parseHashSource(const UChar* begin, const UChar* end)
+{
+ if (begin == end)
+ return false;
+
+ const UChar* position = begin;
+ if (!skipExactly<UChar>(position, end, '\''))
+ return false;
+
+ ContentSecurityPolicyHashAlgorithm algorithm;
+ if (!parseHashAlgorithmAdvancingPosition(position, end - position, algorithm))
+ return false;
+
+ if (!skipExactly<UChar>(position, end, '-'))
+ return false;
+
+ const UChar* beginHashValue = position;
+ skipWhile<UChar, isBase64Character>(position, end);
+ skipExactly<UChar>(position, end, '=');
+ skipExactly<UChar>(position, end, '=');
+ if (position >= end || position == beginHashValue || *position != '\'')
+ return false;
+ Vector<uint8_t> digest;
+ StringView hashValue(beginHashValue, position - beginHashValue); // base64url or base64 encoded
+ // FIXME: Normalize Base64URL to Base64 instead of decoding twice. See <https://bugs.webkit.org/show_bug.cgi?id=155186>.
+ if (!base64Decode(hashValue.toStringWithoutCopying(), digest, Base64ValidatePadding)) {
+ if (!base64URLDecode(hashValue.toStringWithoutCopying(), digest))
+ return false;
+ }
+ if (digest.size() > maximumContentSecurityPolicyDigestLength)
+ return false;
+
+ m_hashes.add(std::make_pair(algorithm, digest));
+ m_hashAlgorithmsUsed |= algorithm;
+ return true;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h b/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h
index fdb9b7e09..811b6cec1 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h
+++ b/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h
@@ -27,8 +27,11 @@
#ifndef ContentSecurityPolicySourceList_h
#define ContentSecurityPolicySourceList_h
+#include "ContentSecurityPolicyHash.h"
#include "ContentSecurityPolicySource.h"
-#include <wtf/Vector.h>
+#include <wtf/HashSet.h>
+#include <wtf/OptionSet.h>
+#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -41,8 +44,14 @@ public:
ContentSecurityPolicySourceList(const ContentSecurityPolicy&, const String& directiveName);
void parse(const String&);
+
bool matches(const URL&);
- bool allowInline() const { return m_allowInline; }
+ bool matches(const ContentSecurityPolicyHash&) const;
+ bool matches(const String& nonce) const;
+
+ OptionSet<ContentSecurityPolicyHashAlgorithm> hashAlgorithmsUsed() const { return m_hashAlgorithmsUsed; }
+
+ bool allowInline() const { return m_allowInline && m_hashes.isEmpty() && m_nonces.isEmpty(); }
bool allowEval() const { return m_allowEval; }
bool allowSelf() const { return m_allowSelf; }
@@ -55,10 +64,17 @@ private:
bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard);
bool parsePath(const UChar* begin, const UChar* end, String& path);
+ bool parseNonceSource(const UChar* begin, const UChar* end);
+
bool isProtocolAllowedByStar(const URL&) const;
+ bool parseHashSource(const UChar* begin, const UChar* end);
+
const ContentSecurityPolicy& m_policy;
Vector<ContentSecurityPolicySource> m_list;
+ HashSet<String> m_nonces;
+ HashSet<ContentSecurityPolicyHash> m_hashes;
+ OptionSet<ContentSecurityPolicyHashAlgorithm> m_hashAlgorithmsUsed;
String m_directiveName;
bool m_allowSelf { false };
bool m_allowStar { false };
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp b/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp
index 89133d4eb..4c4f11c42 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp
+++ b/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.cpp
@@ -47,4 +47,14 @@ bool ContentSecurityPolicySourceListDirective::allows(const URL& url)
return m_sourceList.matches(url);
}
+bool ContentSecurityPolicySourceListDirective::allows(const String& nonce) const
+{
+ return m_sourceList.matches(nonce);
+}
+
+bool ContentSecurityPolicySourceListDirective::allows(const ContentSecurityPolicyHash& hash) const
+{
+ return m_sourceList.matches(hash);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h b/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h
index 9d4e2114c..ac650052d 100644
--- a/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h
+++ b/Source/WebCore/page/csp/ContentSecurityPolicySourceListDirective.h
@@ -39,9 +39,13 @@ public:
ContentSecurityPolicySourceListDirective(const String& name, const String& value, const ContentSecurityPolicy&);
bool allows(const URL&);
+ bool allows(const ContentSecurityPolicyHash&) const;
+ bool allows(const String& nonce) const;
bool allowInline() const { return m_sourceList.allowInline(); }
bool allowEval() const { return m_sourceList.allowEval(); }
+ OptionSet<ContentSecurityPolicyHashAlgorithm> hashAlgorithmsUsed() const { return m_sourceList.hashAlgorithmsUsed(); }
+
private:
ContentSecurityPolicySourceList m_sourceList;
};
diff --git a/Source/WebCore/crypto/CryptoDigest.h b/Source/WebCore/platform/crypto/CryptoDigest.h
index 353b13e82..31f075aa3 100644
--- a/Source/WebCore/crypto/CryptoDigest.h
+++ b/Source/WebCore/platform/crypto/CryptoDigest.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 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
@@ -26,12 +26,9 @@
#ifndef CryptoDigest_h
#define CryptoDigest_h
-#include "CryptoAlgorithmIdentifier.h"
#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
-#if ENABLE(SUBTLE_CRYPTO)
-
namespace WebCore {
struct CryptoDigestContext;
@@ -39,7 +36,14 @@ struct CryptoDigestContext;
class CryptoDigest {
WTF_MAKE_NONCOPYABLE(CryptoDigest);
public:
- static std::unique_ptr<CryptoDigest> create(CryptoAlgorithmIdentifier);
+ enum class Algorithm {
+ SHA_1,
+ SHA_224,
+ SHA_256,
+ SHA_384,
+ SHA_512,
+ };
+ static std::unique_ptr<CryptoDigest> create(Algorithm);
~CryptoDigest();
void addBytes(const void* input, size_t length);
@@ -53,5 +57,4 @@ private:
} // namespace WebCore
-#endif // ENABLE(SUBTLE_CRYPTO)
#endif // CryptoDigest_h
diff --git a/Source/WebCore/platform/crypto/qt/CryptoDigestQt.cpp b/Source/WebCore/platform/crypto/qt/CryptoDigestQt.cpp
new file mode 100644
index 000000000..1dcb8bf72
--- /dev/null
+++ b/Source/WebCore/platform/crypto/qt/CryptoDigestQt.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 Konstantin Tokavev <annulen@yandex.ru>
+ *
+ * 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 APPLE INC. AND ITS CONTRIBUTORS ``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 ITS 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 "CryptoDigest.h"
+
+#include <QCryptographicHash>
+#include <QDebug>
+
+namespace WebCore {
+
+static QCryptographicHash::Algorithm toQtAlgorithm(CryptoDigest::Algorithm algorithm)
+{
+ switch (algorithm) {
+ case CryptoDigest::Algorithm::SHA_1:
+ return QCryptographicHash::Sha1;
+
+ case CryptoDigest::Algorithm::SHA_224:
+ return QCryptographicHash::Sha224;
+
+ case CryptoDigest::Algorithm::SHA_256:
+ return QCryptographicHash::Sha256;
+
+ case CryptoDigest::Algorithm::SHA_384:
+ return QCryptographicHash::Sha384;
+
+ case CryptoDigest::Algorithm::SHA_512:
+ return QCryptographicHash::Sha512;
+ }
+
+ ASSERT_NOT_REACHED();
+ return QCryptographicHash::Algorithm();
+}
+
+struct CryptoDigestContext {
+ CryptoDigestContext(QCryptographicHash::Algorithm algorithm)
+ : hash(algorithm)
+ {
+ }
+ QCryptographicHash hash;
+};
+
+CryptoDigest::CryptoDigest()
+{
+}
+
+CryptoDigest::~CryptoDigest()
+{
+}
+
+std::unique_ptr<CryptoDigest> CryptoDigest::create(CryptoDigest::Algorithm algorithm)
+{
+ std::unique_ptr<CryptoDigest> digest(new CryptoDigest);
+ digest->m_context.reset(new CryptoDigestContext(toQtAlgorithm(algorithm)));
+ return digest;
+}
+
+void CryptoDigest::addBytes(const void* input, size_t length)
+{
+ m_context->hash.addData(static_cast<const char*>(input), length);
+}
+
+Vector<uint8_t> CryptoDigest::computeHash()
+{
+ QByteArray digest = m_context->hash.result();
+ Vector<uint8_t> result(digest.size());
+ memcpy(result.data(), digest.constData(), digest.size());
+ return result;
+}
+
+} // namespace WebCore
diff --git a/Source/WebKit/PlatformQt.cmake b/Source/WebKit/PlatformQt.cmake
index 909efc00d..3792def6f 100644
--- a/Source/WebKit/PlatformQt.cmake
+++ b/Source/WebKit/PlatformQt.cmake
@@ -418,7 +418,7 @@ install(
COMPONENT Data
)
-file(GLOB WebKit_PRIVATE_HEADERS qt/Api/*_p.h ../WebKit2/UIProcess/API/qt/*_p.h)
+file(GLOB WebKit_PRIVATE_HEADERS qt/Api/*_p.h)
install(
FILES
${WebKit_PRIVATE_HEADERS}
diff --git a/Source/WebKit2/PlatformQt.cmake b/Source/WebKit2/PlatformQt.cmake
index 6bd0627f0..5883096eb 100644
--- a/Source/WebKit2/PlatformQt.cmake
+++ b/Source/WebKit2/PlatformQt.cmake
@@ -1,7 +1,7 @@
set(WebKit2_WebProcess_OUTPUT_NAME QtWebProcess)
set(WebKit2_NetworkProcess_OUTPUT_NAME QtWebNetworkProcess)
set(WebKit2_PluginProcess_OUTPUT_NAME QtWebPluginProcess)
-set(WebKit2_DatabaseProcess_OUTPUT_NAME QtWebDatabaseProcess)
+set(WebKit2_DatabaseProcess_OUTPUT_NAME QtWebStorageProcess)
file(MAKE_DIRECTORY ${DERIVED_SOURCES_WEBKIT2_DIR})
@@ -259,6 +259,7 @@ if (ENABLE_NETSCAPE_PLUGIN_API)
endif ()
list(APPEND WebKit2_SYSTEM_INCLUDE_DIRECTORIES
+ ${GLIB_INCLUDE_DIRS}
${GSTREAMER_INCLUDE_DIRS}
${Qt5Quick_INCLUDE_DIRS}
${Qt5Quick_PRIVATE_INCLUDE_DIRS}
@@ -328,3 +329,12 @@ WEBKIT_CREATE_FORWARDING_HEADERS(QtWebKit/private DIRECTORIES UIProcess/API/qt)
if (ENABLE_API_TESTS)
add_subdirectory(UIProcess/API/qt/tests)
endif ()
+
+file(GLOB WebKit2_PRIVATE_HEADERS UIProcess/API/qt/*_p.h)
+install(
+ FILES
+ ${WebKit2_PRIVATE_HEADERS}
+ DESTINATION
+ ${KDE_INSTALL_INCLUDEDIR}/QtWebKit/${PROJECT_VERSION}/QtWebKit/private
+ COMPONENT Data
+)
diff --git a/Source/WebKit2/Shared/qt/ProcessExecutablePathQt.cpp b/Source/WebKit2/Shared/qt/ProcessExecutablePathQt.cpp
index c5f809d34..ae14ef13e 100644
--- a/Source/WebKit2/Shared/qt/ProcessExecutablePathQt.cpp
+++ b/Source/WebKit2/Shared/qt/ProcessExecutablePathQt.cpp
@@ -65,4 +65,11 @@ String executablePathOfNetworkProcess()
return executablePath(QStringLiteral("QtWebNetworkProcess"));
}
+#if ENABLE(DATABASE_PROCESS)
+String executablePathOfDatabaseProcess()
+{
+ return executablePath(QStringLiteral("QtWebStorageProcess"));
+}
+#endif
+
} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
index 3b84c6dba..b894d7338 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
@@ -407,6 +407,7 @@ void QQuickWebViewPrivate::initialize(WKPageConfigurationRef configurationRef)
preferences.setMediaSourceEnabled(false);
preferences.setWebGLEnabled(true);
preferences.setForceCompositingMode(true);
+ preferences.setAllowFileAccessFromFileURLs(true);
webPageProxy->setURLSchemeHandlerForScheme(QrcSchemeHandler::create(), ASCIILiteral("qrc"));
diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp
index 53913fa56..51a3ffbba 100644
--- a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp
+++ b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp
@@ -123,6 +123,12 @@ void ProcessLauncher::launchProcess()
QByteArray pluginProcessPrefix = qgetenv("QT_WEBKIT2_PP_CMD_PREFIX");
commandLine = commandLine.arg(QLatin1String(pluginProcessPrefix.constData())).arg(QString(executablePathOfPluginProcess()));
#endif
+#if ENABLE(DATABASE_PROCESS)
+ } else if (m_launchOptions.processType == ProcessType::Database) {
+ commandLine = QLatin1String("%1 \"%2\" %3 %4");
+ QByteArray processPrefix = qgetenv("QT_WEBKIT2_DP_CMD_PREFIX");
+ commandLine = commandLine.arg(QLatin1String(processPrefix.constData())).arg(QString(executablePathOfDatabaseProcess()));
+#endif
} else {
qDebug() << "Unsupported process type" << (int)m_launchOptions.processType;
ASSERT_NOT_REACHED();
diff --git a/Source/cmake/OptionsQt.cmake b/Source/cmake/OptionsQt.cmake
index 9ca197f72..559b2ab8b 100644
--- a/Source/cmake/OptionsQt.cmake
+++ b/Source/cmake/OptionsQt.cmake
@@ -480,10 +480,11 @@ else ()
endif ()
endif ()
-find_package(Fontconfig)
-
-if (FONTCONFIG_FOUND)
- SET_AND_EXPOSE_TO_BUILD(HAVE_FONTCONFIG 1)
+if (ENABLE_TEST_SUPPORT)
+ find_package(Fontconfig)
+ if (FONTCONFIG_FOUND)
+ SET_AND_EXPOSE_TO_BUILD(HAVE_FONTCONFIG 1)
+ endif ()
endif ()
find_package(WebP)
@@ -521,6 +522,33 @@ if (ENABLE_DEVICE_ORIENTATION)
SET_AND_EXPOSE_TO_BUILD(HAVE_QTSENSORS 1)
endif ()
+if (ENABLE_OPENGL)
+ # Note: Gui module is already found
+ # Warning: quotes are sinificant here!
+ if (NOT DEFINED Qt5Gui_OPENGL_IMPLEMENTATION OR "${Qt5Gui_OPENGL_IMPLEMENTATION}" STREQUAL "")
+ message(FATAL_ERROR "Qt with OpenGL support is required for ENABLE_OPENGL")
+ endif ()
+
+ SET_AND_EXPOSE_TO_BUILD(USE_TEXTURE_MAPPER_GL TRUE)
+ SET_AND_EXPOSE_TO_BUILD(ENABLE_GRAPHICS_CONTEXT_3D TRUE)
+
+ if (WIN32)
+ include(CheckCXXSymbolExists)
+ set(CMAKE_REQUIRED_INCLUDES ${Qt5Gui_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_FLAGS ${Qt5Gui_EXECUTABLE_COMPILE_FLAGS})
+ check_cxx_symbol_exists(QT_OPENGL_DYNAMIC qopenglcontext.h HAVE_QT_OPENGL_DYNAMIC)
+ if (HAVE_QT_OPENGL_DYNAMIC)
+ set(Qt5Gui_OPENGL_IMPLEMENTATION DynamicGL)
+ endif ()
+ unset(CMAKE_REQUIRED_INCLUDES)
+ unset(CMAKE_REQUIRED_FLAGS)
+ endif ()
+
+ message(STATUS "Qt OpenGL implementation: ${Qt5Gui_OPENGL_IMPLEMENTATION}")
+ message(STATUS "Qt OpenGL libraries: ${Qt5Gui_OPENGL_LIBRARIES}")
+ message(STATUS "Qt EGL libraries: ${Qt5Gui_EGL_LIBRARIES}")
+endif ()
+
if (ENABLE_PRINT_SUPPORT)
list(APPEND QT_REQUIRED_COMPONENTS PrintSupport)
SET_AND_EXPOSE_TO_BUILD(HAVE_QTPRINTSUPPORT 1)
@@ -665,25 +693,6 @@ if (ENABLE_X11_TARGET)
endif ()
endif ()
-if (ENABLE_OPENGL)
- SET_AND_EXPOSE_TO_BUILD(USE_TEXTURE_MAPPER_GL TRUE)
- SET_AND_EXPOSE_TO_BUILD(ENABLE_GRAPHICS_CONTEXT_3D TRUE)
-
- if (WIN32)
- include(CheckCXXSymbolExists)
- set(CMAKE_REQUIRED_INCLUDES ${Qt5Gui_INCLUDE_DIRS})
- set(CMAKE_REQUIRED_FLAGS ${Qt5Gui_EXECUTABLE_COMPILE_FLAGS})
- check_cxx_symbol_exists(QT_OPENGL_DYNAMIC qopenglcontext.h HAVE_QT_OPENGL_DYNAMIC)
- if (HAVE_QT_OPENGL_DYNAMIC)
- set(Qt5Gui_OPENGL_IMPLEMENTATION DynamicGL)
- endif ()
- unset(CMAKE_REQUIRED_INCLUDES)
- unset(CMAKE_REQUIRED_FLAGS)
- endif ()
-
- message("Qt OpenGL implementation: ${Qt5Gui_OPENGL_IMPLEMENTATION}")
-endif ()
-
if (NOT ENABLE_VIDEO)
set(USE_MEDIA_FOUNDATION OFF)
set(USE_QT_MULTIMEDIA OFF)
diff --git a/Source/cmake/WebKitMacros.cmake b/Source/cmake/WebKitMacros.cmake
index a34e85463..07e31432a 100644
--- a/Source/cmake/WebKitMacros.cmake
+++ b/Source/cmake/WebKitMacros.cmake
@@ -265,6 +265,8 @@ macro(WEBKIT_FRAMEWORK _target)
${${_target}_HEADERS}
${${_target}_SOURCES}
${${_target}_DERIVED_SOURCES}
+ ${${_target}_PRIVATE_HEADERS}
+ ${${_target}_PUBLIC_HEADERS}
)
target_link_libraries(${_target} ${${_target}_LIBRARIES})
set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS "BUILDING_${_target}")
diff --git a/Tools/qmake/projects/run_cmake.pro b/Tools/qmake/projects/run_cmake.pro
index fadfda059..f63fcd658 100644
--- a/Tools/qmake/projects/run_cmake.pro
+++ b/Tools/qmake/projects/run_cmake.pro
@@ -25,11 +25,10 @@ build_pass|!debug_and_release {
USE_LIBHYPHEN=OFF
!isEmpty(_QMAKE_SUPER_CACHE_) {
- CMAKE_PREFIX_PATH=\"$$ROOT_QT_BUILD_DIR/qtbase;$$ROOT_QT_BUILD_DIR/qtlocation;$$ROOT_QT_BUILD_DIR/qtsensors;$$ROOT_QT_BUILD_DIR/qtdeclarative;$$ROOT_QT_BUILD_DIR/qtwebchannel\"
+ CMAKE_CONFIG += CMAKE_PREFIX_PATH=\"$$ROOT_QT_BUILD_DIR/qtbase;$$ROOT_QT_BUILD_DIR/qtlocation;$$ROOT_QT_BUILD_DIR/qtsensors;$$ROOT_QT_BUILD_DIR/qtdeclarative;$$ROOT_QT_BUILD_DIR/qtwebchannel\"
} else {
- CMAKE_PREFIX_PATH=\"$$[QT_INSTALL_PREFIX]\"
+ CMAKE_CONFIG += Qt5_DIR=\"$$[QT_INSTALL_LIBS]/cmake/Qt5\"
}
- CMAKE_CONFIG += CMAKE_PREFIX_PATH=$$CMAKE_PREFIX_PATH
static: CMAKE_CONFIG += USE_THIN_ARCHIVES=OFF