diff options
| author | Liang Qi <liang.qi@qt.io> | 2018-01-13 21:26:34 +0100 |
|---|---|---|
| committer | Liang Qi <liang.qi@qt.io> | 2018-01-13 21:26:34 +0100 |
| commit | beaeeb99881184fd368c121fcbb1a31c78b794a3 (patch) | |
| tree | 0e078499d8fe3e8627e3612537e61f2dd1029625 /Source/WebCore | |
| parent | f7697030f444b5e16331c6d0a99712736b9ff026 (diff) | |
| parent | 79143ccfc158ec4fffc49eee600d600edb342b16 (diff) | |
| download | qtwebkit-beaeeb99881184fd368c121fcbb1a31c78b794a3.tar.gz | |
Merge remote-tracking branch 'origin/5.212' into dev
Change-Id: I9e64176fe95183acf5e093aa081b0a498795bdb2
Diffstat (limited to 'Source/WebCore')
63 files changed, 1118 insertions, 446 deletions
diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt index 7d0ad0433..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" @@ -3353,7 +3354,7 @@ if (ENABLE_USER_MESSAGE_HANDLERS) endif () if (USE_WOFF2) - list(APPEND WebCore_INCLUDE_DIRECTORIES "${THIRDPARTY_DIR}/woff2/src") + list(APPEND WebCore_INCLUDE_DIRECTORIES "${THIRDPARTY_DIR}/woff2/include") list(APPEND WebCore_LIBRARIES woff2) endif () @@ -3558,9 +3559,11 @@ if (WebCore_USER_AGENT_SCRIPTS) MAKE_JS_FILE_ARRAYS( ${DERIVED_SOURCES_WEBCORE_DIR}/UserAgentScriptsData.cpp ${DERIVED_SOURCES_WEBCORE_DIR}/UserAgentScripts.h + WebCore WebCore_USER_AGENT_SCRIPTS WebCore_USER_AGENT_SCRIPTS_DEPENDENCIES ) + list(APPEND WebCore_DERIVED_SOURCES ${DERIVED_SOURCES_WEBCORE_DIR}/UserAgentScriptsData.cpp) endif () # Generate plug-in resources diff --git a/Source/WebCore/PlatformQt.cmake b/Source/WebCore/PlatformQt.cmake index c5466b6c7..49c76a8de 100644 --- a/Source/WebCore/PlatformQt.cmake +++ b/Source/WebCore/PlatformQt.cmake @@ -2,6 +2,10 @@ include(platform/ImageDecoders.cmake) include(platform/Linux.cmake) include(platform/TextureMapper.cmake) +if (JPEG_DEFINITIONS) + add_definitions(${JPEG_DEFINITIONS}) +endif () + list(APPEND WebCore_INCLUDE_DIRECTORIES "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}" "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/inspector" @@ -69,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 @@ -110,6 +116,7 @@ list(APPEND WebCore_SOURCES platform/network/NetworkStorageSessionStub.cpp platform/network/MIMESniffing.cpp + platform/network/qt/BlobUrlConversion.cpp platform/network/qt/CookieJarQt.cpp platform/network/qt/CredentialStorageQt.cpp platform/network/qt/DNSQt.cpp @@ -162,19 +169,19 @@ list(APPEND WebCore_SOURCES platform/text/qt/TextBreakIteratorInternalICUQt.cpp ) -QTWEBKIT_GENERATE_MOC_FILES_CPP( +QTWEBKIT_GENERATE_MOC_FILES_CPP(WebCore platform/network/qt/DNSQt.cpp platform/qt/MainThreadSharedTimerQt.cpp ) -QTWEBKIT_GENERATE_MOC_FILES_H( +QTWEBKIT_GENERATE_MOC_FILES_H(WebCore platform/network/qt/CookieJarQt.h platform/network/qt/QNetworkReplyHandler.h platform/network/qt/QtMIMETypeSniffer.h ) -QTWEBKIT_GENERATE_MOC_FILE_H(platform/network/qt/NetworkStateNotifierPrivate.h platform/network/qt/NetworkStateNotifierQt.cpp) -QTWEBKIT_GENERATE_MOC_FILE_H(platform/network/qt/SocketStreamHandlePrivate.h platform/network/qt/SocketStreamHandleQt.cpp) +QTWEBKIT_GENERATE_MOC_FILE_H(WebCore platform/network/qt/NetworkStateNotifierPrivate.h platform/network/qt/NetworkStateNotifierQt.cpp) +QTWEBKIT_GENERATE_MOC_FILE_H(WebCore platform/network/qt/SocketStreamHandlePrivate.h platform/network/qt/SocketStreamHandleQt.cpp) if (COMPILER_IS_GCC_OR_CLANG) set_source_files_properties( @@ -182,6 +189,12 @@ if (COMPILER_IS_GCC_OR_CLANG) PROPERTIES COMPILE_FLAGS "-frtti -UQT_NO_DYNAMIC_CAST" ) + + set_source_files_properties( + platform/network/qt/BlobUrlConversion.cpp + PROPERTIES + COMPILE_FLAGS "-fexceptions -UQT_NO_EXCEPTIONS" + ) endif () if (ENABLE_DEVICE_ORIENTATION) @@ -197,7 +210,7 @@ if (ENABLE_GAMEPAD_DEPRECATED) list(APPEND WebCore_SOURCES platform/qt/GamepadsQt.cpp ) - QTWEBKIT_GENERATE_MOC_FILES_CPP(platform/qt/GamepadsQt.cpp) + QTWEBKIT_GENERATE_MOC_FILES_CPP(WebCore platform/qt/GamepadsQt.cpp) endif () if (ENABLE_GRAPHICS_CONTEXT_3D) @@ -221,7 +234,7 @@ if (ENABLE_NETSCAPE_PLUGIN_API) platform/win/WebCoreInstanceHandle.cpp ) list(APPEND WebCore_LIBRARIES - Shlwapi + shlwapi version ) elseif (PLUGIN_BACKEND_XLIB) @@ -374,7 +387,7 @@ if (USE_QT_MULTIMEDIA) list(APPEND WebCore_LIBRARIES ${Qt5Multimedia_LIBRARIES} ) - QTWEBKIT_GENERATE_MOC_FILES_H(platform/graphics/qt/MediaPlayerPrivateQt.h) + QTWEBKIT_GENERATE_MOC_FILES_H(WebCore platform/graphics/qt/MediaPlayerPrivateQt.h) endif () if (ENABLE_VIDEO) diff --git a/Source/WebCore/Scripts/make-js-file-arrays.py b/Source/WebCore/Scripts/make-js-file-arrays.py deleted file mode 100755 index 3116a11bb..000000000 --- a/Source/WebCore/Scripts/make-js-file-arrays.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2014 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. - -import io -import os -from optparse import OptionParser -from StringIO import StringIO -from jsmin import JavascriptMinify - - -def stringifyCodepoint(code): - if code < 128: - return '{0:d}'.format(code) - else: - return "'\\x{0:02x}'".format(code) - - -def chunk(list, chunkSize): - for i in xrange(0, len(list), chunkSize): - yield list[i:i + chunkSize] - - -def main(): - parser = OptionParser(usage="usage: %prog [--no-minify] header source [input [input...]]") - parser.add_option('--no-minify', action='store_true', help='Do not run the input files through jsmin') - (options, arguments) = parser.parse_args() - if len(arguments) < 3: - print 'Error: must provide at least 3 arguments' - parser.print_usage() - exit(-1) - - headerPath = arguments[0] - sourcePath = arguments[1] - inputPaths = arguments[2:] - - headerFile = open(headerPath, 'w') - print >> headerFile, 'namespace WebCore {' - - sourceFile = open(sourcePath, 'w') - print >> sourceFile, '#include "{0:s}"'.format(os.path.basename(headerPath)) - print >> sourceFile, 'namespace WebCore {' - - jsm = JavascriptMinify() - - for inputFileName in inputPaths: - inputStream = io.FileIO(inputFileName) - outputStream = StringIO() - - if not options.no_minify: - jsm.minify(inputStream, outputStream) - characters = outputStream.getvalue() - else: - characters = inputStream.read() - - size = len(characters) - variableName = os.path.splitext(os.path.basename(inputFileName))[0] - - print >> headerFile, 'extern const char {0:s}JavaScript[{1:d}];'.format(variableName, size) - print >> sourceFile, 'const char {0:s}JavaScript[{1:d}] = {{'.format(variableName, size) - - codepoints = map(ord, characters) - for codepointChunk in chunk(codepoints, 16): - print >> sourceFile, ' {0:s},'.format(','.join(map(stringifyCodepoint, codepointChunk))) - - print >> sourceFile, '};' - - print >> headerFile, '}' - print >> sourceFile, '}' - -if __name__ == '__main__': - main() diff --git a/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp index 3aed7052f..cb2119b10 100644 --- a/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp @@ -30,8 +30,7 @@ #include "HTMLCollection.h" #include "HTMLFormElement.h" #include "JSDOMWindowCustom.h" -#include "JSNodeList.h" -#include "StaticNodeList.h" +#include "JSRadioNodeList.h" using namespace JSC; @@ -48,8 +47,7 @@ bool JSHTMLFormElement::nameGetter(ExecState* exec, PropertyName propertyName, J return true; } - // FIXME: HTML5 specifies that this should be a RadioNodeList. - value = toJS(exec, globalObject(), StaticElementList::adopt(namedItems).get()); + value = toJS(exec, globalObject(), wrapped().radioNodeList(propertyNameToAtomicString(propertyName)).get()); return true; } diff --git a/Source/WebCore/bridge/qt/qt_class.cpp b/Source/WebCore/bridge/qt/qt_class.cpp index 5efebc0fd..1554f8d63 100644 --- a/Source/WebCore/bridge/qt/qt_class.cpp +++ b/Source/WebCore/bridge/qt/qt_class.cpp @@ -108,7 +108,7 @@ JSValue QtClass::fallbackObject(ExecState* exec, Instance* inst, PropertyName id return jsUndefined(); int flags = metaMethod.methodType() == QMetaMethod::Signal ? QtRuntimeMethod::MethodIsSignal : 0; - QtRuntimeMethod* method = new QtRuntimeMethod(context, static_cast<QtInstance*>(inst)->getObject(), normal, index, flags, qtinst); + QtRuntimeMethod* method = new QtRuntimeMethod(static_cast<QtInstance*>(inst)->getObject(), normal, index, flags, qtinst); qtinst->m_methods.insert(name, method); JSValue obj = toJS(method->jsObjectRef(context, &exception)); if (exception) diff --git a/Source/WebCore/bridge/qt/qt_runtime.cpp b/Source/WebCore/bridge/qt/qt_runtime.cpp index 84335e8ca..4859faee3 100644 --- a/Source/WebCore/bridge/qt/qt_runtime.cpp +++ b/Source/WebCore/bridge/qt/qt_runtime.cpp @@ -1230,7 +1230,7 @@ static JSClassRef prototypeForSignalsAndSlots() return cls; } -QtRuntimeMethod::QtRuntimeMethod(JSContextRef ctx, QObject* object, const QByteArray& identifier, int index, int flags, QtInstance* instance) +QtRuntimeMethod::QtRuntimeMethod(QObject* object, const QByteArray& identifier, int index, int flags, QtInstance* instance) : m_object(object) , m_identifier(identifier) , m_index(index) diff --git a/Source/WebCore/bridge/qt/qt_runtime.h b/Source/WebCore/bridge/qt/qt_runtime.h index 34a97244a..c9d675c3f 100644 --- a/Source/WebCore/bridge/qt/qt_runtime.h +++ b/Source/WebCore/bridge/qt/qt_runtime.h @@ -84,7 +84,7 @@ public: AllowPrivate = 2 }; - QtRuntimeMethod(JSContextRef, QObject*, const QByteArray& identifier, int signalIndex, int flags, QtInstance*); + QtRuntimeMethod(QObject*, const QByteArray& identifier, int signalIndex, int flags, QtInstance*); ~QtRuntimeMethod(); static JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 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/HTMLAnchorElement.cpp b/Source/WebCore/html/HTMLAnchorElement.cpp index bc100a870..75eb7a2a3 100644 --- a/Source/WebCore/html/HTMLAnchorElement.cpp +++ b/Source/WebCore/html/HTMLAnchorElement.cpp @@ -46,6 +46,7 @@ #include "SecurityOrigin.h" #include "SecurityPolicy.h" #include "Settings.h" +#include "URLUtils.h" #include <wtf/text/StringBuilder.h> namespace WebCore { @@ -76,15 +77,6 @@ HTMLAnchorElement::~HTMLAnchorElement() clearRootEditableElementForSelectionOnMouseDown(); } -// This function does not allow leading spaces before the port number. -static unsigned parsePortFromStringPosition(const String& value, unsigned portStart, unsigned& portEnd) -{ - portEnd = portStart; - while (isASCIIDigit(value[portEnd])) - ++portEnd; - return value.substring(portStart, portEnd - portStart).toUInt(); -} - bool HTMLAnchorElement::supportsFocus() const { if (hasEditableStyle()) 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/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp index ef9bb394e..82d35c1a8 100644 --- a/Source/WebCore/inspector/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp @@ -1446,7 +1446,7 @@ Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEv JSC::JSLockHolder lock(scriptListener->isolatedWorld().vm()); state = execStateFromNode(scriptListener->isolatedWorld(), &node->document()); handler = scriptListener->jsFunction(&node->document()); - if (handler) { + if (handler && state) { body = handler->toString(state)->value(state); if (auto function = JSC::jsDynamicCast<JSC::JSFunction*>(handler)) { if (!function->isHostOrBuiltinFunction()) { diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp index 35127c647..fb4a63e0b 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp @@ -823,10 +823,17 @@ CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalida logMemoryCacheResourceRequest(frame(), DiagnosticLoggingKeys::inMemoryCacheKey(), DiagnosticLoggingKeys::unusedReasonErrorKey()); return Reload; } - - // For resources that are not yet loaded we ignore the cache policy. - if (existingResource->isLoading()) + + if (existingResource->isLoading()) { + // Do not use cached main resources that are still loading because sharing + // loading CachedResources in this case causes issues with regards to cancellation. + // If one of the DocumentLoader clients decides to cancel the load, then the load + // would be cancelled for all other DocumentLoaders as well. + if (type == CachedResource::Type::MainResource) + return Reload; + // For cached subresources that are still loading we ignore the cache policy. return Use; + } auto revalidationDecision = existingResource->makeRevalidationDecision(cachePolicy(type)); logResourceRevalidationDecision(revalidationDecision, frame()); diff --git a/Source/WebCore/page/Performance.cpp b/Source/WebCore/page/Performance.cpp index ed39a1d15..1c491da5d 100644 --- a/Source/WebCore/page/Performance.cpp +++ b/Source/WebCore/page/Performance.cpp @@ -233,7 +233,7 @@ void Performance::webkitClearMeasures(const String& measureName) double Performance::now() const { double nowSeconds = monotonicallyIncreasingTime() - m_referenceTime; - const double resolutionSeconds = 0.000005; + const double resolutionSeconds = 0.0001; return 1000.0 * floor(nowSeconds / resolutionSeconds) * resolutionSeconds; } diff --git a/Source/WebCore/page/Settings.in b/Source/WebCore/page/Settings.in index 84a9f0cd0..74d9e0709 100644 --- a/Source/WebCore/page/Settings.in +++ b/Source/WebCore/page/Settings.in @@ -79,7 +79,6 @@ needsSiteSpecificQuirks initial=false domTimersThrottlingEnabled initial=true webArchiveDebugModeEnabled initial=false, conditional=WEB_ARCHIVE localFileContentSniffingEnabled initial=false -offlineStorageDatabaseEnabled initial=false offlineWebApplicationCacheEnabled initial=false enforceCSSMIMETypeInNoQuirksMode initial=true usesEncodingDetector initial=false @@ -91,6 +90,9 @@ acceleratedFiltersEnabled initial=false useLegacyTextAlignPositionedElementBehavior initial=false javaScriptRuntimeFlags type=JSC::RuntimeFlags +# PLATFORM(QT) only +offlineStorageDatabaseEnabled initial=true + # FIXME: This should really be disabled by default as it makes platforms that don't support the feature download files # they can't use by. Leaving enabled for now to not change existing behavior. downloadableBinaryFontsEnabled initial=true 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/page/qt/EventHandlerQt.cpp b/Source/WebCore/page/qt/EventHandlerQt.cpp index 240ea75eb..b717b1f54 100644 --- a/Source/WebCore/page/qt/EventHandlerQt.cpp +++ b/Source/WebCore/page/qt/EventHandlerQt.cpp @@ -49,6 +49,7 @@ #include "PlatformWheelEvent.h" #include "RenderWidget.h" #include "Scrollbar.h" +#include <QCoreApplication> namespace WebCore { @@ -123,7 +124,14 @@ bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& unsigned EventHandler::accessKeyModifiers() { #if OS(DARWIN) - return PlatformEvent::CtrlKey | PlatformEvent::AltKey; + // On macOS, the ControlModifier value corresponds + // to the Command keys on the keyboard, + // and the MetaModifier value corresponds to the Control keys. + // See http://doc.qt.io/qt-5/qt.html#KeyboardModifier-enum + if (UNLIKELY(QCoreApplication::testAttribute(Qt::AA_MacDontSwapCtrlAndMeta))) + return PlatformEvent::CtrlKey | PlatformEvent::AltKey; + else + return PlatformEvent::MetaKey | PlatformEvent::AltKey; #else return PlatformEvent::AltKey; #endif 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/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index d7f529cf8..8b821fa98 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -563,6 +563,7 @@ public: #if PLATFORM(QT) void pushTransparencyLayerInternal(const QRect&, qreal, QPixmap&); + void popTransparencyLayerInternal(); void takeOwnershipOfPlatformContext(); #endif diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp index c2323cf04..d8f4a5da7 100644 --- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp +++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp @@ -31,8 +31,8 @@ #include <wtf/ByteOrder.h> #if USE(WOFF2) -#include "woff2_common.h" -#include "woff2_dec.h" +#include <woff2/decode.h> +static const uint32_t kWoff2Signature = 0x774f4632; // "wOF2" #endif namespace WebCore { @@ -84,7 +84,7 @@ bool isWOFF(SharedBuffer& buffer) return false; #if USE(WOFF2) - return signature == woffSignature || signature == woff2::kWoff2Signature; + return signature == woffSignature || signature == kWoff2Signature; #else return signature == woffSignature; #endif @@ -140,7 +140,7 @@ bool convertWOFFToSfnt(SharedBuffer& woff, Vector<char>& sfnt) } #if USE(WOFF2) - if (signature == woff2::kWoff2Signature) { + if (signature == kWoff2Signature) { const uint8_t* woffData = reinterpret_cast_ptr<const uint8_t*>(woff.data()); const size_t woffSize = woff.size(); const size_t sfntSize = woff2::ComputeWOFF2FinalSize(woffData, woffSize); diff --git a/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp b/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp index c502a0c3b..8ae96b94c 100644 --- a/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp +++ b/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp @@ -29,7 +29,11 @@ #if ENABLE(GRAPHICS_CONTEXT_3D) #include "TemporaryOpenGLSetting.h" -#if USE(OPENGL_ES_2) +#if PLATFORM(QT) +#define FUNCTIONS m_functions +#include "OpenGLShimsQt.h" +#define glIsEnabled(...) m_functions->glIsEnabled(__VA_ARGS__) +#elif USE(OPENGL_ES_2) #include <GLES2/gl2.h> #include "OpenGLESShims.h" #elif PLATFORM(IOS) @@ -38,10 +42,6 @@ #include <OpenGL/gl.h> #elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) #include "OpenGLShims.h" -#elif PLATFORM(QT) -#define FUNCTIONS m_functions -#include "OpenGLShimsQt.h" -#define glIsEnabled(...) m_functions->glIsEnabled(__VA_ARGS__) #endif namespace WebCore { diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 260081946..1e041050e 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -358,7 +358,7 @@ void GraphicsContext::restorePlatformState() { if (!m_data->layers.isEmpty() && !m_data->layers.top()->alphaMask.isNull()) if (!--m_data->layers.top()->saveCounter) - endPlatformTransparencyLayer(); + popTransparencyLayerInternal(); m_data->p()->restore(); } @@ -1313,18 +1313,39 @@ void GraphicsContext::beginPlatformTransparencyLayer(float opacity) ++m_data->layerCount; } +void GraphicsContext::popTransparencyLayerInternal() +{ + TransparencyLayer* layer = m_data->layers.pop(); + ASSERT(!layer->alphaMask.isNull()); + ASSERT(layer->saveCounter == 0); + layer->painter.resetTransform(); + layer->painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + layer->painter.drawPixmap(QPoint(), layer->alphaMask); + layer->painter.end(); + + QPainter* p = m_data->p(); + p->save(); + p->resetTransform(); + p->setOpacity(layer->opacity); + p->drawPixmap(layer->offset, layer->pixmap); + p->restore(); + + delete layer; +} + void GraphicsContext::endPlatformTransparencyLayer() { if (paintingDisabled()) return; + while ( ! m_data->layers.top()->alphaMask.isNull() ){ + --m_data->layers.top()->saveCounter; + popTransparencyLayerInternal(); + if (m_data->layers.isEmpty()) + return; + } TransparencyLayer* layer = m_data->layers.pop(); - if (!layer->alphaMask.isNull()) { - layer->painter.resetTransform(); - layer->painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - layer->painter.drawPixmap(QPoint(), layer->alphaMask); - } else - --m_data->layerCount; // see the comment for layerCount + --m_data->layerCount; // see the comment for layerCount layer->painter.end(); QPainter* p = m_data->p(); diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 2295362aa..af798f761 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -34,7 +34,6 @@ #include "IntRect.h" #include "MIMETypeRegistry.h" #include "StillImageQt.h" -#include "TransparencyLayer.h" #include <runtime/JSCInlines.h> #include <runtime/TypedArrayInlines.h> #include <wtf/text/WTFString.h> diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp index 48130eba4..b8b605805 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp @@ -114,14 +114,70 @@ void TextureMapperImageBuffer::drawSolidColor(const FloatRect& rect, const Trans context->restore(); } -void TextureMapperImageBuffer::drawBorder(const Color&, float /* borderWidth */, const FloatRect&, const TransformationMatrix&) +void TextureMapperImageBuffer::drawBorder(const Color& color, float borderWidth , const FloatRect& rect, const TransformationMatrix& matrix) { - notImplemented(); +#if PLATFORM(QT) + GraphicsContext* context = currentContext(); + if (!context) + return; + + context->save(); + context->setCompositeOperation(isInMaskMode() ? CompositeDestinationIn : CompositeSourceOver); +#if ENABLE(3D_TRANSFORMS) + context->concat3DTransform(matrix); +#else + context->concatCTM(matrix.toAffineTransform()); +#endif + + QPainter& painter = *context->platformContext(); + painter.setBrush(Qt::NoBrush); + QPen newPen(color); + newPen.setWidthF(borderWidth); + painter.setPen(newPen); + painter.drawRect(rect); + + context->restore(); +#endif } -void TextureMapperImageBuffer::drawNumber(int /* number */, const Color&, const FloatPoint&, const TransformationMatrix&) +void TextureMapperImageBuffer::drawNumber(int number, const Color& color, const FloatPoint& targetPoint, const TransformationMatrix& matrix) { - notImplemented(); +#if PLATFORM(QT) + GraphicsContext* context = currentContext(); + if (!context) + return; + + context->save(); + context->setCompositeOperation(isInMaskMode() ? CompositeDestinationIn : CompositeSourceOver); +#if ENABLE(3D_TRANSFORMS) + context->concat3DTransform(matrix); +#else + context->concatCTM(matrix.toAffineTransform()); +#endif + + // Partially duplicates TextureMapperGL::drawNumber + int pointSize = 8; + QString counterString = QString::number(number); + + QFont font(QString::fromLatin1("Monospace"), pointSize, QFont::Bold); + font.setStyleHint(QFont::TypeWriter); + + QFontMetrics fontMetrics(font); + int width = fontMetrics.width(counterString) + 4; + int height = fontMetrics.height(); + + IntSize size(width, height); + IntRect sourceRect(IntPoint::zero(), size); + + QPainter& painter = *context->platformContext(); + painter.translate(targetPoint); + painter.fillRect(sourceRect, color); + painter.setFont(font); + painter.setPen(Qt::white); + painter.drawText(2, height * 0.85, counterString); + + context->restore(); +#endif } PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper&, const FilterOperations& filters) diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp index 0610c85b6..98f2ec964 100644 --- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp +++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp @@ -542,6 +542,16 @@ bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult) break; } + case MESessionStarted: { + auto weakPtr = m_weakPtrFactory.createWeakPtr(); + callOnMainThread([weakPtr] { + if (!weakPtr) + return; + weakPtr->onSessionStarted(); + }); + break; + } + case MEBufferingStarted: { auto weakPtr = m_weakPtrFactory.createWeakPtr(); callOnMainThread([weakPtr] { @@ -940,6 +950,11 @@ void MediaPlayerPrivateMediaFoundation::onBufferingStopped() updateReadyState(); } +void MediaPlayerPrivateMediaFoundation::onSessionStarted() +{ + updateReadyState(); +} + void MediaPlayerPrivateMediaFoundation::onSessionEnded() { m_networkState = MediaPlayer::Loaded; diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h index c3303cf7b..0fe07fa13 100644 --- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h +++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h @@ -152,6 +152,7 @@ private: void onTopologySet(); void onBufferingStarted(); void onBufferingStopped(); + void onSessionStarted(); void onSessionEnded(); LPCWSTR registerVideoWindowClass(); diff --git a/Source/WebCore/platform/network/qt/BlobUrlConversion.cpp b/Source/WebCore/platform/network/qt/BlobUrlConversion.cpp new file mode 100644 index 000000000..8f61eaeb9 --- /dev/null +++ b/Source/WebCore/platform/network/qt/BlobUrlConversion.cpp @@ -0,0 +1,98 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2017 Konstantin Tokarev <annulen@yandex.ru> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "BlobUrlConversion.h" + +#include "BlobData.h" +#include "BlobRegistryImpl.h" + +#include <QUrl> +#include <wtf/text/Base64.h> + +namespace WebCore { + +static bool appendBlobResolved(Vector<char>& out, const URL& url, QString* contentType = 0) +{ + RefPtr<BlobData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(url); + if (!blobData) + return false; + + if (contentType) + *contentType = blobData->contentType(); + + BlobDataItemList::const_iterator it = blobData->items().begin(); + const BlobDataItemList::const_iterator itend = blobData->items().end(); + for (; it != itend; ++it) { + const BlobDataItem& blobItem = *it; + if (blobItem.type() == BlobDataItem::Type::Data) { + if (!out.tryAppend(reinterpret_cast<const char*>(blobItem.data().data()->data()) + blobItem.offset(), blobItem.length())) + return false; + } else if (blobItem.type() == BlobDataItem::Type::File) { + // File types are not allowed here, so just ignore it. + RELEASE_ASSERT_WITH_MESSAGE(false, "File types are not allowed here"); + } else + ASSERT_NOT_REACHED(); + } + return true; +} + +static QUrl resolveBlobUrl(const URL& url) +{ + RefPtr<BlobData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(url); + if (!blobData) + return QUrl(); + + Vector<char> data; + QString contentType; + if (!appendBlobResolved(data, url, &contentType)) { + qWarning("Failed to convert blob data to base64: cannot allocate memory for continuous blob data"); + return QUrl(); + } + + // QByteArray::{from,to}Base64 are prone to integer overflow, this is the maximum size that can be safe + size_t maxBase64Size = std::numeric_limits<int>::max() / 3 - 1; + + Vector<char> base64; + WTF::base64Encode(data, base64, WTF::Base64URLPolicy); + if (base64.isEmpty() || base64.size() > maxBase64Size) { + qWarning("Failed to convert blob data to base64: data is too large"); + return QUrl(); + } + + QString dataUri(QStringLiteral("data:")); + dataUri.append(contentType); + dataUri.append(QStringLiteral(";base64,")); + dataUri.reserve(dataUri.size() + base64.size()); + dataUri.append(QLatin1String(base64.data(), base64.size())); + return QUrl(dataUri); +} + +QUrl convertBlobToDataUrl(const QUrl& url) +{ + QT_TRY { + return resolveBlobUrl(url); + } QT_CATCH(const std::bad_alloc &) { + qWarning("Failed to convert blob data to base64: not enough memory"); + } + return QUrl(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/network/qt/BlobUrlConversion.h b/Source/WebCore/platform/network/qt/BlobUrlConversion.h new file mode 100644 index 000000000..2dbd0a680 --- /dev/null +++ b/Source/WebCore/platform/network/qt/BlobUrlConversion.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2017 Konstantin Tokarev <annulen@yandex.ru> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace WebCore { + +QUrl convertBlobToDataUrl(const QUrl&); + +} diff --git a/Source/WebCore/platform/network/qt/CookieJarQt.cpp b/Source/WebCore/platform/network/qt/CookieJarQt.cpp index 3b08c06cd..d1cf87fdd 100644 --- a/Source/WebCore/platform/network/qt/CookieJarQt.cpp +++ b/Source/WebCore/platform/network/qt/CookieJarQt.cpp @@ -42,12 +42,21 @@ #include <QNetworkCookie> #include <QStringList> #include <QVariant> +#include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> namespace WebCore { static SharedCookieJarQt* s_sharedCookieJarQt = 0; +static void appendCookie(StringBuilder& builder, const QNetworkCookie& cookie) +{ + if (!builder.isEmpty()) + builder.append("; "); + QByteArray rawData = cookie.toRawForm(QNetworkCookie::NameAndValueOnly); + builder.append(rawData.constData(), rawData.length()); +} + void setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, const String& value) { QNetworkCookieJar* jar = session.context() ? session.context()->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared(); @@ -59,7 +68,8 @@ void setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstPar if (!thirdPartyCookiePolicyPermits(session.context(), urlForCookies, firstPartyUrl)) return; - QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QString(value).toLatin1()); + CString cookieString = value.latin1(); + QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QByteArray::fromRawData(cookieString.data(), cookieString.length())); QList<QNetworkCookie>::Iterator it = cookies.begin(); while (it != cookies.end()) { if (it->isHttpOnly()) @@ -86,14 +96,13 @@ String cookiesForDOM(const NetworkStorageSession& session, const URL& firstParty if (cookies.isEmpty()) return String(); - QStringList resultCookies; - foreach (const QNetworkCookie& networkCookie, cookies) { - if (networkCookie.isHttpOnly()) + StringBuilder builder; + for (const auto& cookie : cookies) { + if (cookie.isHttpOnly()) continue; - resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData())); + appendCookie(builder, cookie); } - - return resultCookies.join(QLatin1String("; ")); + return builder.toString(); } String cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const URL& /*firstParty*/, const URL& url) @@ -106,11 +115,10 @@ String cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const if (cookies.isEmpty()) return String(); - QStringList resultCookies; - foreach (QNetworkCookie networkCookie, cookies) - resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData())); - - return resultCookies.join(QLatin1String("; ")); + StringBuilder builder; + for (const auto& cookie : cookies) + appendCookie(builder, cookie); + return builder.toString(); } bool cookiesEnabled(const NetworkStorageSession& session, const URL& /*firstParty*/, const URL& /*url*/) diff --git a/Source/WebCore/platform/network/qt/DNSQt.cpp b/Source/WebCore/platform/network/qt/DNSQt.cpp index b12cbaa09..4559d17a0 100644 --- a/Source/WebCore/platform/network/qt/DNSQt.cpp +++ b/Source/WebCore/platform/network/qt/DNSQt.cpp @@ -24,6 +24,7 @@ #include <QHostInfo> #include <QObject> #include <QString> +#include <wtf/NeverDestroyed.h> #include <wtf/text/WTFString.h> namespace WebCore { @@ -34,7 +35,7 @@ public: DnsPrefetchHelper() : QObject() { } public Q_SLOTS: - void lookup(QString hostname) + void lookup(const String& hostname) { if (hostname.isEmpty()) { DNSResolveQueue::singleton().decrementRequestCount(); @@ -71,8 +72,8 @@ void DNSResolveQueue::updateIsUsingProxy() // This is called by the platform-independent DNSResolveQueue. void DNSResolveQueue::platformResolve(const String& hostname) { - static DnsPrefetchHelper dnsPrefetchHelper; - dnsPrefetchHelper.lookup(QString(hostname)); + static NeverDestroyed<DnsPrefetchHelper> dnsPrefetchHelper; + dnsPrefetchHelper.get().lookup(hostname); } } // namespace diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index cd096bfe7..1b60c5131 100644 --- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -647,7 +647,10 @@ void QNetworkReplyHandler::redirect(ResourceResponse& response, const QUrl& redi { ASSERT(!m_queue.deferSignals()); - QUrl newUrl = m_replyWrapper->reply()->url().resolved(redirection); + QUrl currentUrl = m_replyWrapper->reply()->url(); + QUrl newUrl = currentUrl.resolved(redirection); + if (currentUrl.hasFragment()) + newUrl.setFragment(currentUrl.fragment()); ResourceHandleClient* client = m_resourceHandle->client(); ASSERT(client); diff --git a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp index 655724a4c..c54a8115b 100644 --- a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp +++ b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp @@ -18,18 +18,27 @@ */ #include "config.h" -#include "NetworkingContext.h" #include "ResourceRequest.h" -#include "ThirdPartyCookiesQt.h" - -#include "BlobData.h" -#include "BlobRegistryImpl.h" -#include <qglobal.h> +#include "BlobUrlConversion.h" +#include "NetworkingContext.h" +#include "ThirdPartyCookiesQt.h" #include <QNetworkRequest> #include <QUrl> +// HTTP/2 is implemented since Qt 5.8, but QTBUG-64359 makes it unusable in browser +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 4) +#define USE_HTTP2 1 +#endif + +// HTTP2AllowedAttribute enforces HTTP/2 instead of negotiating, see QTBUG-61397 +#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) +#define HTTP2_IS_BUGGY_WITHOUT_HTTPS 1 +#else +#define HTTP2_IS_BUGGY_WITHOUT_HTTPS 0 +#endif + namespace WebCore { // The limit can be found in qhttpnetworkconnection.cpp. @@ -43,44 +52,11 @@ unsigned initializeMaximumHTTPConnectionCountPerHost() return 6 * (1 + 3 + 2); } -static void appendBlobResolved(QByteArray& data, const QUrl& url, QString* contentType = 0) +static QUrl toQUrl(const URL& url) { - RefPtr<BlobData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(url); - if (!blobData) - return; - - if (contentType) - *contentType = blobData->contentType(); - - BlobDataItemList::const_iterator it = blobData->items().begin(); - const BlobDataItemList::const_iterator itend = blobData->items().end(); - for (; it != itend; ++it) { - const BlobDataItem& blobItem = *it; - if (blobItem.type() == BlobDataItem::Type::Data) - data.append(reinterpret_cast<const char*>(blobItem.data().data()->data()) + static_cast<int>(blobItem.offset()), static_cast<int>(blobItem.length())); - else if (blobItem.type() == BlobDataItem::Type::File) { - // File types are not allowed here, so just ignore it. - RELEASE_ASSERT_WITH_MESSAGE(false, "File types are not allowed here"); - } else - ASSERT_NOT_REACHED(); - } -} - -static void resolveBlobUrl(const QUrl& url, QUrl& resolvedUrl) -{ - RefPtr<BlobData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(url); - if (!blobData) - return; - - QByteArray data; - QString contentType; - appendBlobResolved(data, url, &contentType); - - QString dataUri(QStringLiteral("data:")); - dataUri.append(contentType); - dataUri.append(QStringLiteral(";base64,")); - dataUri.append(QString::fromLatin1(data.toBase64())); - resolvedUrl = QUrl(dataUri); + if (url.protocolIsBlob()) + return convertBlobToDataUrl(url); + return url; } static inline QByteArray stringToByteArray(const String& string) @@ -93,19 +69,19 @@ static inline QByteArray stringToByteArray(const String& string) QNetworkRequest ResourceRequest::toNetworkRequest(NetworkingContext *context) const { QNetworkRequest request; - QUrl newurl = url(); - - if (newurl.scheme() == QLatin1String("blob")) - resolveBlobUrl(url(), newurl); - - request.setUrl(newurl); + const URL& originalUrl = url(); + request.setUrl(toQUrl(originalUrl)); request.setOriginatingObject(context ? context->originatingObject() : 0); -#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) - // HTTP2AllowedAttribute enforces HTTP/2 instead of negotiating, see QTBUG-61397 - if (newurl.scheme().toLower() == QLatin1String("https")) - request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); +#if USE(HTTP2) +#if HTTP2_IS_BUGGY_WITHOUT_HTTPS + if (originalUrl.protocolIs("https")) #endif + { + request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); + } +#endif // USE(HTTP2) + const HTTPHeaderMap &headers = httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = headers.begin(), end = headers.end(); diff --git a/Source/WebCore/platform/qt/EventLoopQt.cpp b/Source/WebCore/platform/qt/EventLoopQt.cpp index 39bb54c53..c0ca31ec5 100644 --- a/Source/WebCore/platform/qt/EventLoopQt.cpp +++ b/Source/WebCore/platform/qt/EventLoopQt.cpp @@ -26,7 +26,7 @@ namespace WebCore { void EventLoop::cycle() { - QCoreApplication::processEvents(); + QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); } } // namespace WebCore diff --git a/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp b/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp index a0e67e494..2e667e2da 100644 --- a/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp +++ b/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp @@ -808,6 +808,7 @@ static bool isVirtualKeyCodeRepresentingCharacter(int code) } } +template<bool unmodified> static String keyTextForKeyEvent(const QKeyEvent* event) { switch (event->key()) { @@ -820,6 +821,53 @@ static String keyTextForKeyEvent(const QKeyEvent* event) case Qt::Key_Enter: if (event->text().isNull()) return ASCIILiteral("\r"); + break; + +// Workaround for broken accesskey when QKeyEvent has modifier, see QTBUG-64891 +#define MAKE_TEXT_FOR_KEY(QtKey, Character) \ + case Qt::Key_##QtKey: \ + if (unmodified && event->text().isNull()) \ + return ASCIILiteral(#Character); \ + break; + + MAKE_TEXT_FOR_KEY(0, 0); + MAKE_TEXT_FOR_KEY(1, 1); + MAKE_TEXT_FOR_KEY(2, 2); + MAKE_TEXT_FOR_KEY(3, 3); + MAKE_TEXT_FOR_KEY(4, 4); + MAKE_TEXT_FOR_KEY(5, 5); + MAKE_TEXT_FOR_KEY(6, 6); + MAKE_TEXT_FOR_KEY(7, 7); + MAKE_TEXT_FOR_KEY(8, 8); + MAKE_TEXT_FOR_KEY(9, 9); + MAKE_TEXT_FOR_KEY(A, a); + MAKE_TEXT_FOR_KEY(B, b); + MAKE_TEXT_FOR_KEY(C, c); + MAKE_TEXT_FOR_KEY(D, d); + MAKE_TEXT_FOR_KEY(E, e); + MAKE_TEXT_FOR_KEY(F, f); + MAKE_TEXT_FOR_KEY(G, g); + MAKE_TEXT_FOR_KEY(H, h); + MAKE_TEXT_FOR_KEY(I, i); + MAKE_TEXT_FOR_KEY(J, j); + MAKE_TEXT_FOR_KEY(K, k); + MAKE_TEXT_FOR_KEY(L, l); + MAKE_TEXT_FOR_KEY(M, m); + MAKE_TEXT_FOR_KEY(N, n); + MAKE_TEXT_FOR_KEY(O, o); + MAKE_TEXT_FOR_KEY(P, p); + MAKE_TEXT_FOR_KEY(Q, q); + MAKE_TEXT_FOR_KEY(R, r); + MAKE_TEXT_FOR_KEY(S, s); + MAKE_TEXT_FOR_KEY(T, t); + MAKE_TEXT_FOR_KEY(U, u); + MAKE_TEXT_FOR_KEY(V, v); + MAKE_TEXT_FOR_KEY(W, w); + MAKE_TEXT_FOR_KEY(X, x); + MAKE_TEXT_FOR_KEY(Y, y); + MAKE_TEXT_FOR_KEY(Z, z); + +#undef MAKE_TEXT_FOR_KEY } return event->text(); } @@ -840,8 +888,8 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(QKeyEvent* event, bool useNativeVir m_modifiers |= MetaKey; m_useNativeVirtualKeyAsDOMKey = useNativeVirtualKeyAsDOMKey; - m_text = keyTextForKeyEvent(event); - m_unmodifiedText = m_text; // FIXME: not correct + m_text = keyTextForKeyEvent<false>(event); + m_unmodifiedText = keyTextForKeyEvent<true>(event); m_keyIdentifier = keyIdentifierForQtKeyCode(event->key()); m_autoRepeat = event->isAutoRepeat(); m_isKeypad = (state & Qt::KeypadModifier); diff --git a/Source/WebCore/platform/qt/UserAgentQt.cpp b/Source/WebCore/platform/qt/UserAgentQt.cpp index 4b8876220..fc5eab7a8 100644 --- a/Source/WebCore/platform/qt/UserAgentQt.cpp +++ b/Source/WebCore/platform/qt/UserAgentQt.cpp @@ -37,7 +37,7 @@ namespace WebCore { This implementation returns the following value: - "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Version/9.0 Safari/%WebKitVersion%" + "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Version/10.0 Safari/%WebKitVersion%" In this string the following values are replaced the first time the function is called: \list @@ -58,7 +58,7 @@ String UserAgentQt::standardUserAgent(const String &applicationNameForUserAgent, if (ua.isNull()) { - ua = QStringLiteral("Mozilla/5.0 (%1%2%3) AppleWebKit/%4 (KHTML, like Gecko) %99 Version/9.0 Safari/%5"); + ua = QStringLiteral("Mozilla/5.0 (%1%2%3) AppleWebKit/%4 (KHTML, like Gecko) %99 Version/10.0 Safari/%5"); // Platform. ua = ua.arg( diff --git a/Source/WebCore/platform/text/TextCodecUTF8.cpp b/Source/WebCore/platform/text/TextCodecUTF8.cpp index 6b32955c1..31f548662 100644 --- a/Source/WebCore/platform/text/TextCodecUTF8.cpp +++ b/Source/WebCore/platform/text/TextCodecUTF8.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2008, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2004-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,18 +31,10 @@ #include <wtf/text/StringBuffer.h> #include <wtf/unicode/CharacterNames.h> -using namespace WTF; -using namespace WTF::Unicode; - namespace WebCore { const int nonCharacter = -1; -std::unique_ptr<TextCodec> TextCodecUTF8::create(const TextEncoding&, const void*) -{ - return std::make_unique<TextCodecUTF8>(); -} - void TextCodecUTF8::registerEncodingNames(EncodingNameRegistrar registrar) { registrar("UTF-8", "UTF-8"); @@ -59,7 +51,9 @@ void TextCodecUTF8::registerEncodingNames(EncodingNameRegistrar registrar) void TextCodecUTF8::registerCodecs(TextCodecRegistrar registrar) { - registrar("UTF-8", create, 0); + registrar("UTF-8", [] (const TextEncoding&, const void*) -> std::unique_ptr<TextCodec> { + return std::make_unique<TextCodecUTF8>(); + }, nullptr); } static inline int nonASCIISequenceLength(uint8_t firstByte) @@ -73,11 +67,11 @@ static inline int nonASCIISequenceLength(uint8_t firstByte) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -85,55 +79,76 @@ static inline int nonASCIISequenceLength(uint8_t firstByte) return lengths[firstByte]; } -static inline int decodeNonASCIISequence(const uint8_t* sequence, unsigned length) +static inline int decodeNonASCIISequence(const uint8_t* sequence, int& length) { ASSERT(!isASCII(sequence[0])); if (length == 2) { + ASSERT(sequence[0] >= 0xC2); ASSERT(sequence[0] <= 0xDF); - if (sequence[0] < 0xC2) - return nonCharacter; - if (sequence[1] < 0x80 || sequence[1] > 0xBF) + if (sequence[1] < 0x80 || sequence[1] > 0xBF) { + length = 1; return nonCharacter; + } return ((sequence[0] << 6) + sequence[1]) - 0x00003080; } if (length == 3) { - ASSERT(sequence[0] >= 0xE0 && sequence[0] <= 0xEF); + ASSERT(sequence[0] >= 0xE0); + ASSERT(sequence[0] <= 0xEF); switch (sequence[0]) { case 0xE0: - if (sequence[1] < 0xA0 || sequence[1] > 0xBF) + if (sequence[1] < 0xA0 || sequence[1] > 0xBF) { + length = 1; return nonCharacter; + } break; case 0xED: - if (sequence[1] < 0x80 || sequence[1] > 0x9F) + if (sequence[1] < 0x80 || sequence[1] > 0x9F) { + length = 1; return nonCharacter; + } break; default: - if (sequence[1] < 0x80 || sequence[1] > 0xBF) + if (sequence[1] < 0x80 || sequence[1] > 0xBF) { + length = 1; return nonCharacter; + } } - if (sequence[2] < 0x80 || sequence[2] > 0xBF) + if (sequence[2] < 0x80 || sequence[2] > 0xBF) { + length = 2; return nonCharacter; + } return ((sequence[0] << 12) + (sequence[1] << 6) + sequence[2]) - 0x000E2080; } ASSERT(length == 4); - ASSERT(sequence[0] >= 0xF0 && sequence[0] <= 0xF4); + ASSERT(sequence[0] >= 0xF0); + ASSERT(sequence[0] <= 0xF4); switch (sequence[0]) { case 0xF0: - if (sequence[1] < 0x90 || sequence[1] > 0xBF) + if (sequence[1] < 0x90 || sequence[1] > 0xBF) { + length = 1; return nonCharacter; + } break; case 0xF4: - if (sequence[1] < 0x80 || sequence[1] > 0x8F) + if (sequence[1] < 0x80 || sequence[1] > 0x8F) { + length = 1; return nonCharacter; + } break; default: - if (sequence[1] < 0x80 || sequence[1] > 0xBF) + if (sequence[1] < 0x80 || sequence[1] > 0xBF) { + length = 1; return nonCharacter; + } } - if (sequence[2] < 0x80 || sequence[2] > 0xBF) + if (sequence[2] < 0x80 || sequence[2] > 0xBF) { + length = 2; return nonCharacter; - if (sequence[3] < 0x80 || sequence[3] > 0xBF) + } + if (sequence[3] < 0x80 || sequence[3] > 0xBF) { + length = 3; return nonCharacter; + } return ((sequence[0] << 18) + (sequence[1] << 12) + (sequence[2] << 6) + sequence[3]) - 0x03C82080; } @@ -156,18 +171,7 @@ void TextCodecUTF8::consumePartialSequenceByte() memmove(m_partialSequence, m_partialSequence + 1, m_partialSequenceSize); } -void TextCodecUTF8::handleError(UChar*& destination, bool stopOnError, bool& sawError) -{ - sawError = true; - if (stopOnError) - return; - // Each error generates a replacement character and consumes one byte. - *destination++ = replacementCharacter; - consumePartialSequenceByte(); -} - -template <> -bool TextCodecUTF8::handlePartialSequence<LChar>(LChar*& destination, const uint8_t*& source, const uint8_t* end, bool flush, bool, bool&) +bool TextCodecUTF8::handlePartialSequence(LChar*& destination, const uint8_t*& source, const uint8_t* end, bool flush) { ASSERT(m_partialSequenceSize); do { @@ -199,7 +203,7 @@ bool TextCodecUTF8::handlePartialSequence<LChar>(LChar*& destination, const uint m_partialSequenceSize = count; } int character = decodeNonASCIISequence(m_partialSequence, count); - if ((character == nonCharacter) || (character > 0xff)) + if (character == nonCharacter || character > 0xFF) return true; m_partialSequenceSize -= count; @@ -209,8 +213,7 @@ bool TextCodecUTF8::handlePartialSequence<LChar>(LChar*& destination, const uint return false; } -template <> -bool TextCodecUTF8::handlePartialSequence<UChar>(UChar*& destination, const uint8_t*& source, const uint8_t* end, bool flush, bool stopOnError, bool& sawError) +void TextCodecUTF8::handlePartialSequence(UChar*& destination, const uint8_t*& source, const uint8_t* end, bool flush, bool stopOnError, bool& sawError) { ASSERT(m_partialSequenceSize); do { @@ -221,9 +224,11 @@ bool TextCodecUTF8::handlePartialSequence<UChar>(UChar*& destination, const uint } int count = nonASCIISequenceLength(m_partialSequence[0]); if (!count) { - handleError(destination, stopOnError, sawError); + sawError = true; if (stopOnError) - return false; + return; + *destination++ = replacementCharacter; + consumePartialSequenceByte(); continue; } if (count > m_partialSequenceSize) { @@ -233,12 +238,15 @@ bool TextCodecUTF8::handlePartialSequence<UChar>(UChar*& destination, const uint // add it to the existing partial sequence. memcpy(m_partialSequence + m_partialSequenceSize, source, end - source); m_partialSequenceSize += end - source; - return false; + return; } // An incomplete partial sequence at the end is an error. - handleError(destination, stopOnError, sawError); + sawError = true; if (stopOnError) - return false; + return; + *destination++ = replacementCharacter; + m_partialSequenceSize = 0; + source = end; continue; } memcpy(m_partialSequence + m_partialSequenceSize, source, count - m_partialSequenceSize); @@ -247,17 +255,18 @@ bool TextCodecUTF8::handlePartialSequence<UChar>(UChar*& destination, const uint } int character = decodeNonASCIISequence(m_partialSequence, count); if (character == nonCharacter) { - handleError(destination, stopOnError, sawError); + sawError = true; if (stopOnError) - return false; + return; + *destination++ = replacementCharacter; + m_partialSequenceSize -= count; + memmove(m_partialSequence, m_partialSequence + count, m_partialSequenceSize); continue; } m_partialSequenceSize -= count; destination = appendCharacter(destination, character); } while (m_partialSequenceSize); - - return false; } String TextCodecUTF8::decode(const char* bytes, size_t length, bool flush, bool stopOnError, bool& sawError) @@ -269,7 +278,7 @@ String TextCodecUTF8::decode(const char* bytes, size_t length, bool flush, bool const uint8_t* source = reinterpret_cast<const uint8_t*>(bytes); const uint8_t* end = source + length; - const uint8_t* alignedEnd = alignToMachineWord(end); + const uint8_t* alignedEnd = WTF::alignToMachineWord(end); LChar* destination = buffer.characters(); do { @@ -279,7 +288,7 @@ String TextCodecUTF8::decode(const char* bytes, size_t length, bool flush, bool // in some compilers. LChar* destinationForHandlePartialSequence = destination; const uint8_t* sourceForHandlePartialSequence = source; - if (handlePartialSequence(destinationForHandlePartialSequence, sourceForHandlePartialSequence, end, flush, stopOnError, sawError)) { + if (handlePartialSequence(destinationForHandlePartialSequence, sourceForHandlePartialSequence, end, flush)) { source = sourceForHandlePartialSequence; goto upConvertTo16Bit; } @@ -292,14 +301,14 @@ String TextCodecUTF8::decode(const char* bytes, size_t length, bool flush, bool while (source < end) { if (isASCII(*source)) { // Fast path for ASCII. Most UTF-8 text will be ASCII. - if (isAlignedToMachineWord(source)) { + if (WTF::isAlignedToMachineWord(source)) { while (source < alignedEnd) { - MachineWord chunk = *reinterpret_cast_ptr<const MachineWord*>(source); - if (!isAllASCII<LChar>(chunk)) + auto chunk = *reinterpret_cast_ptr<const WTF::MachineWord*>(source); + if (!WTF::isAllASCII<LChar>(chunk)) break; copyASCIIMachineWord(destination, source); - source += sizeof(MachineWord); - destination += sizeof(MachineWord); + source += sizeof(WTF::MachineWord); + destination += sizeof(WTF::MachineWord); } if (source == end) break; @@ -328,10 +337,10 @@ String TextCodecUTF8::decode(const char* bytes, size_t length, bool flush, bool sawError = true; if (stopOnError) break; - + goto upConvertTo16Bit; } - if (character > 0xff) + if (character > 0xFF) goto upConvertTo16Bit; source += count; @@ -369,14 +378,14 @@ upConvertTo16Bit: while (source < end) { if (isASCII(*source)) { // Fast path for ASCII. Most UTF-8 text will be ASCII. - if (isAlignedToMachineWord(source)) { + if (WTF::isAlignedToMachineWord(source)) { while (source < alignedEnd) { - MachineWord chunk = *reinterpret_cast_ptr<const MachineWord*>(source); - if (!isAllASCII<LChar>(chunk)) + auto chunk = *reinterpret_cast_ptr<const WTF::MachineWord*>(source); + if (!WTF::isAllASCII<LChar>(chunk)) break; copyASCIIMachineWord(destination16, source); - source += sizeof(MachineWord); - destination16 += sizeof(MachineWord); + source += sizeof(WTF::MachineWord); + destination16 += sizeof(WTF::MachineWord); } if (source == end) break; @@ -405,9 +414,8 @@ upConvertTo16Bit: sawError = true; if (stopOnError) break; - // Each error generates a replacement character and consumes one byte. *destination16++ = replacementCharacter; - ++source; + source += count ? count : 1; continue; } source += count; @@ -427,17 +435,15 @@ CString TextCodecUTF8::encode(const UChar* characters, size_t length, Unencodabl // Non-BMP characters take two UTF-16 code units and can take up to 4 bytes (2x). if (length > std::numeric_limits<size_t>::max() / 3) CRASH(); - Vector<uint8_t> bytes(length * 3); - size_t i = 0; + Vector<char, 3000> bytes(length * 3); size_t bytesWritten = 0; - while (i < length) { + for (size_t i = 0; i < length; ) { UChar32 character; U16_NEXT(characters, i, length, character); U8_APPEND_UNSAFE(bytes.data(), bytesWritten, character); } - - return CString(reinterpret_cast<char*>(bytes.data()), bytesWritten); + return CString { bytes.data(), bytesWritten }; } } // namespace WebCore diff --git a/Source/WebCore/platform/text/TextCodecUTF8.h b/Source/WebCore/platform/text/TextCodecUTF8.h index 94305ce18..636a0cb8d 100644 --- a/Source/WebCore/platform/text/TextCodecUTF8.h +++ b/Source/WebCore/platform/text/TextCodecUTF8.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TextCodecUTF8_h -#define TextCodecUTF8_h +#pragma once #include "TextCodec.h" @@ -32,12 +31,6 @@ namespace WebCore { class TextCodecUTF8 : public TextCodec { public: - static std::unique_ptr<TextCodec> create(const TextEncoding&, const void*); - TextCodecUTF8() - : m_partialSequenceSize(0) - { - } - static void registerEncodingNames(EncodingNameRegistrar); static void registerCodecs(TextCodecRegistrar); @@ -45,16 +38,14 @@ private: virtual String decode(const char*, size_t length, bool flush, bool stopOnError, bool& sawError); virtual CString encode(const UChar*, size_t length, UnencodableHandling); - template <typename CharType> - bool handlePartialSequence(CharType*& destination, const uint8_t*& source, const uint8_t* end, bool flush, bool stopOnError, bool& sawError); - void handleError(UChar*& destination, bool stopOnError, bool& sawError); + bool handlePartialSequence(LChar*& destination, const uint8_t*& source, const uint8_t* end, bool flush); + void handlePartialSequence(UChar*& destination, const uint8_t*& source, const uint8_t* end, bool flush, bool stopOnError, bool& sawError); void consumePartialSequenceByte(); - int m_partialSequenceSize; + int m_partialSequenceSize { 0 }; uint8_t m_partialSequence[U8_MAX_LENGTH]; }; } // namespace WebCore -#endif // TextCodecUTF8_h diff --git a/Source/WebCore/platform/text/TextEncoding.h b/Source/WebCore/platform/text/TextEncoding.h index d9943024f..922fc3e21 100644 --- a/Source/WebCore/platform/text/TextEncoding.h +++ b/Source/WebCore/platform/text/TextEncoding.h @@ -31,68 +31,68 @@ namespace WebCore { - class TextEncoding { - public: - TextEncoding() : m_name(0) { } - TextEncoding(const char* name); - WEBCORE_EXPORT TextEncoding(const String& name); +class TextEncoding { +public: + TextEncoding() : m_name(0) { } + WEBCORE_EXPORT TextEncoding(const char* name); + WEBCORE_EXPORT TextEncoding(const String& name); - bool isValid() const { return m_name; } - const char* name() const { return m_name; } - const char* domName() const; // name exposed via DOM - bool usesVisualOrdering() const; - bool isJapanese() const; - - PassRefPtr<StringImpl> displayString(PassRefPtr<StringImpl> str) const - { - if (m_backslashAsCurrencySymbol == '\\' || !str) - return str; - return str->replace('\\', m_backslashAsCurrencySymbol); - } - template <typename CharacterType> - void displayBuffer(CharacterType* characters, unsigned len) const - { - if (m_backslashAsCurrencySymbol == '\\') - return; - for (unsigned i = 0; i < len; ++i) { - if (characters[i] == '\\') - characters[i] = m_backslashAsCurrencySymbol; - } + bool isValid() const { return m_name; } + const char* name() const { return m_name; } + const char* domName() const; // name exposed via DOM + bool usesVisualOrdering() const; + bool isJapanese() const; + + PassRefPtr<StringImpl> displayString(PassRefPtr<StringImpl> str) const + { + if (m_backslashAsCurrencySymbol == '\\' || !str) + return str; + return str->replace('\\', m_backslashAsCurrencySymbol); + } + template <typename CharacterType> + void displayBuffer(CharacterType* characters, unsigned len) const + { + if (m_backslashAsCurrencySymbol == '\\') + return; + for (unsigned i = 0; i < len; ++i) { + if (characters[i] == '\\') + characters[i] = m_backslashAsCurrencySymbol; } + } - const TextEncoding& closestByteBasedEquivalent() const; - const TextEncoding& encodingForFormSubmission() const; + const TextEncoding& closestByteBasedEquivalent() const; + const TextEncoding& encodingForFormSubmission() const; - String decode(const char* str, size_t length) const - { - bool ignored; - return decode(str, length, false, ignored); - } - WEBCORE_EXPORT String decode(const char*, size_t length, bool stopOnError, bool& sawError) const; - CString encode(StringView, UnencodableHandling) const; + String decode(const char* str, size_t length) const + { + bool ignored; + return decode(str, length, false, ignored); + } + WEBCORE_EXPORT String decode(const char*, size_t length, bool stopOnError, bool& sawError) const; + CString encode(StringView, UnencodableHandling) const; - UChar backslashAsCurrencySymbol() const; - bool isByteBasedEncoding() const { return !isNonByteBasedEncoding(); } + UChar backslashAsCurrencySymbol() const; + bool isByteBasedEncoding() const { return !isNonByteBasedEncoding(); } - private: - bool isNonByteBasedEncoding() const; - bool isUTF7Encoding() const; +private: + bool isNonByteBasedEncoding() const; + bool isUTF7Encoding() const; - const char* m_name; - UChar m_backslashAsCurrencySymbol; - }; + const char* m_name; + UChar m_backslashAsCurrencySymbol; +}; - inline bool operator==(const TextEncoding& a, const TextEncoding& b) { return a.name() == b.name(); } - inline bool operator!=(const TextEncoding& a, const TextEncoding& b) { return a.name() != b.name(); } +inline bool operator==(const TextEncoding& a, const TextEncoding& b) { return a.name() == b.name(); } +inline bool operator!=(const TextEncoding& a, const TextEncoding& b) { return a.name() != b.name(); } - const TextEncoding& ASCIIEncoding(); - const TextEncoding& Latin1Encoding(); - const TextEncoding& UTF16BigEndianEncoding(); - const TextEncoding& UTF16LittleEndianEncoding(); - const TextEncoding& UTF32BigEndianEncoding(); - const TextEncoding& UTF32LittleEndianEncoding(); - WEBCORE_EXPORT const TextEncoding& UTF8Encoding(); - WEBCORE_EXPORT const TextEncoding& WindowsLatin1Encoding(); +const TextEncoding& ASCIIEncoding(); +const TextEncoding& Latin1Encoding(); +const TextEncoding& UTF16BigEndianEncoding(); +const TextEncoding& UTF16LittleEndianEncoding(); +const TextEncoding& UTF32BigEndianEncoding(); +const TextEncoding& UTF32LittleEndianEncoding(); +WEBCORE_EXPORT const TextEncoding& UTF8Encoding(); +WEBCORE_EXPORT const TextEncoding& WindowsLatin1Encoding(); } // namespace WebCore diff --git a/Source/WebCore/platform/text/TextEncodingRegistry.h b/Source/WebCore/platform/text/TextEncodingRegistry.h index e882a9ab3..6623fb949 100644 --- a/Source/WebCore/platform/text/TextEncodingRegistry.h +++ b/Source/WebCore/platform/text/TextEncodingRegistry.h @@ -31,26 +31,26 @@ namespace WebCore { - class TextCodec; - class TextEncoding; +class TextCodec; +class TextEncoding; - // Use TextResourceDecoder::decode to decode resources, since it handles BOMs. - // Use TextEncoding::encode to encode, since it takes care of normalization. - std::unique_ptr<TextCodec> newTextCodec(const TextEncoding&); +// Use TextResourceDecoder::decode to decode resources, since it handles BOMs. +// Use TextEncoding::encode to encode, since it takes care of normalization. +WEBCORE_EXPORT std::unique_ptr<TextCodec> newTextCodec(const TextEncoding&); - // Only TextEncoding should use the following functions directly. - const char* atomicCanonicalTextEncodingName(const char* alias); - template <typename CharacterType> - const char* atomicCanonicalTextEncodingName(const CharacterType*, size_t); - const char* atomicCanonicalTextEncodingName(const String&); - bool noExtendedTextEncodingNameUsed(); - bool isJapaneseEncoding(const char* canonicalEncodingName); - bool shouldShowBackslashAsCurrencySymbolIn(const char* canonicalEncodingName); +// Only TextEncoding should use the following functions directly. +const char* atomicCanonicalTextEncodingName(const char* alias); +template <typename CharacterType> +const char* atomicCanonicalTextEncodingName(const CharacterType*, size_t); +const char* atomicCanonicalTextEncodingName(const String&); +bool noExtendedTextEncodingNameUsed(); +bool isJapaneseEncoding(const char* canonicalEncodingName); +bool shouldShowBackslashAsCurrencySymbolIn(const char* canonicalEncodingName); - WEBCORE_EXPORT String defaultTextEncodingNameForSystemLanguage(); +WEBCORE_EXPORT String defaultTextEncodingNameForSystemLanguage(); #ifndef NDEBUG - void dumpTextEncodingNameMap(); +void dumpTextEncodingNameMap(); #endif } diff --git a/Source/WebCore/rendering/line/BreakingContext.h b/Source/WebCore/rendering/line/BreakingContext.h index 799d2c063..fff452898 100644 --- a/Source/WebCore/rendering/line/BreakingContext.h +++ b/Source/WebCore/rendering/line/BreakingContext.h @@ -559,9 +559,9 @@ inline void BreakingContext::handleReplaced() m_ignoringSpaces = true; } if (downcast<RenderListMarker>(*m_current.renderer()).isInside()) - m_width.addUncommittedWidth(replacedLogicalWidth); + m_width.addUncommittedReplacedWidth(replacedLogicalWidth); } else - m_width.addUncommittedWidth(replacedLogicalWidth); + m_width.addUncommittedReplacedWidth(replacedLogicalWidth); if (is<RenderRubyRun>(*m_current.renderer())) { m_width.applyOverhang(downcast<RenderRubyRun>(m_current.renderer()), m_lastObject, m_nextObject); downcast<RenderRubyRun>(m_current.renderer())->updatePriorContextFromCachedBreakIterator(m_renderTextInfo.lineBreakIterator); @@ -748,7 +748,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool bool breakNBSP = m_autoWrap && m_currentStyle->nbspMode() == SPACE; // Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word, // which is only possible if the word is the first thing on the line. - bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.hasCommitted()) || m_currWS == PRE); + bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && (!m_width.committedWidth() && !m_width.hasCommittedReplaced())) || m_currWS == PRE); bool midWordBreak = false; bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap; bool keepAllWords = m_currentStyle->wordBreak() == KeepAllWordBreak; diff --git a/Source/WebCore/rendering/line/LineWidth.cpp b/Source/WebCore/rendering/line/LineWidth.cpp index 71e05cb23..b28406d63 100644 --- a/Source/WebCore/rendering/line/LineWidth.cpp +++ b/Source/WebCore/rendering/line/LineWidth.cpp @@ -128,6 +128,10 @@ void LineWidth::commit() { m_committedWidth += m_uncommittedWidth; m_uncommittedWidth = 0; + if (m_hasUncommittedReplaced) { + m_hasCommittedReplaced = true; + m_hasUncommittedReplaced = false; + } m_hasCommitted = true; } diff --git a/Source/WebCore/rendering/line/LineWidth.h b/Source/WebCore/rendering/line/LineWidth.h index 370b3a0f8..bcb274c8e 100644 --- a/Source/WebCore/rendering/line/LineWidth.h +++ b/Source/WebCore/rendering/line/LineWidth.h @@ -60,6 +60,7 @@ public: float logicalLeftOffset() const { return m_left; } bool hasCommitted() const { return m_hasCommitted; } + bool hasCommittedReplaced() const { return m_hasCommittedReplaced; } void updateAvailableWidth(LayoutUnit minimumHeight = 0); void shrinkAvailableWidthForNewFloatIfNeeded(const FloatingObject&); @@ -67,6 +68,11 @@ public: { m_uncommittedWidth += delta; } + void addUncommittedReplacedWidth(float delta) + { + addUncommittedWidth(delta); + m_hasUncommittedReplaced = true; + } void commit(); void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer); void fitBelowFloats(bool isFirstLine = false); @@ -92,6 +98,8 @@ private: float m_availableWidth { 0 }; bool m_isFirstLine { true }; bool m_hasCommitted { false }; + bool m_hasCommittedReplaced { false }; + bool m_hasUncommittedReplaced { false }; IndentTextOrNot m_shouldIndentText; }; diff --git a/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h index 6177281c3..f2b8f562c 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h @@ -35,7 +35,7 @@ class SVGAnimatedListPropertyTearOff : public SVGAnimatedProperty { public: typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType; typedef SVGPropertyTearOff<ListItemType> ListItemTearOff; - typedef Vector<RefPtr<ListItemTearOff>> ListWrapperCache; + typedef Vector<ListItemTearOff*> ListWrapperCache; typedef SVGListProperty<PropertyType> ListProperty; typedef SVGListPropertyTearOff<PropertyType> ListPropertyTearOff; typedef PropertyType ContentType; @@ -68,6 +68,11 @@ public: m_baseVal = nullptr; else if (&property == m_animVal) m_animVal = nullptr; + else { + size_t i = m_wrappers.find(&property); + if (i != notFound) + m_wrappers[i] = nullptr; + } } int findItem(SVGProperty* property) diff --git a/Source/WebCore/svg/properties/SVGListProperty.h b/Source/WebCore/svg/properties/SVGListProperty.h index 77788e102..cd6c44596 100644 --- a/Source/WebCore/svg/properties/SVGListProperty.h +++ b/Source/WebCore/svg/properties/SVGListProperty.h @@ -159,7 +159,7 @@ public: m_values->clear(); m_values->append(newItem->propertyReference()); - m_wrappers->append(newItem); + m_wrappers->append(newItem.get()); commitChange(); return newItem; @@ -200,7 +200,7 @@ public: // It is also associated with our animated property, so it can notify the SVG Element which holds the SVGAnimated*List // that it has been modified (and thus can call svgAttributeChanged(associatedAttributeName)). wrapper = ListItemTearOff::create(animatedList, UndefinedRole, m_values->at(index)); - m_wrappers->at(index) = wrapper; + m_wrappers->at(index) = wrapper.get(); } return wrapper.release(); @@ -257,7 +257,7 @@ public: m_values->insert(index, newItem->propertyReference()); // Store new wrapper at position 'index', change its underlying value, so mutations of newItem, directly affect the item in the list. - m_wrappers->insert(index, newItem); + m_wrappers->insert(index, newItem.get()); commitChange(); return newItem; @@ -335,7 +335,7 @@ public: // Update the value and the wrapper at the desired position 'index'. m_values->at(index) = newItem->propertyReference(); - m_wrappers->at(index) = newItem; + m_wrappers->at(index) = newItem.get(); commitChange(); return newItem; @@ -423,7 +423,7 @@ public: // Append the value and wrapper at the end of the list. m_values->append(newItem->propertyReference()); - m_wrappers->append(newItem); + m_wrappers->append(newItem.get()); commitChange(ListModificationAppend); return newItem; diff --git a/Source/WebCore/svg/properties/SVGListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGListPropertyTearOff.h index 94df5474d..86bef088f 100644 --- a/Source/WebCore/svg/properties/SVGListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGListPropertyTearOff.h @@ -68,7 +68,7 @@ public: ASSERT(m_values->size() == m_wrappers->size()); ASSERT_WITH_SECURITY_IMPLICATION(itemIndex < m_wrappers->size()); - RefPtr<ListItemTearOff>& item = m_wrappers->at(itemIndex); + RefPtr<ListItemTearOff> item = m_wrappers->at(itemIndex); item->detachWrapper(); m_wrappers->remove(itemIndex); m_values->remove(itemIndex); @@ -144,7 +144,7 @@ protected: unsigned size = m_wrappers->size(); ASSERT(size == m_values->size()); for (unsigned i = 0; i < size; ++i) { - ListItemTearOff* item = m_wrappers->at(i).get(); + ListItemTearOff* item = m_wrappers->at(i); if (!item) continue; item->setAnimatedProperty(m_animatedProperty.get()); diff --git a/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h index 066364876..f30c910a9 100644 --- a/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h @@ -62,7 +62,7 @@ public: detachListWrappers(0); RefPtr<SVGPropertyTearOff<SVGTransform>> wrapper = SVGPropertyTearOff<SVGTransform>::create(m_values->consolidate()); - m_wrappers->append(wrapper); + m_wrappers->append(wrapper.get()); ASSERT(m_values->size() == m_wrappers->size()); return wrapper; |
