summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/network
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/network')
-rw-r--r--Source/WebCore/platform/network/qt/BlobUrlConversion.cpp98
-rw-r--r--Source/WebCore/platform/network/qt/BlobUrlConversion.h29
-rw-r--r--Source/WebCore/platform/network/qt/CookieJarQt.cpp32
-rw-r--r--Source/WebCore/platform/network/qt/DNSQt.cpp7
-rw-r--r--Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp5
-rw-r--r--Source/WebCore/platform/network/qt/ResourceRequestQt.cpp82
6 files changed, 184 insertions, 69 deletions
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();