diff options
author | Steve Block <steveblock@google.com> | 2011-05-25 19:08:45 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-06-08 13:51:31 +0100 |
commit | 2bde8e466a4451c7319e3a072d118917957d6554 (patch) | |
tree | 28f4a1b869a513e565c7760d0e6a06e7cf1fe95a /Source/WebCore/platform/network/qt | |
parent | 6939c99b71d9372d14a0c74a772108052e8c48c8 (diff) | |
download | external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.zip external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.gz external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.bz2 |
Merge WebKit at r82507: Initial merge by git
Change-Id: I60ce9d780725b58b45e54165733a8ffee23b683e
Diffstat (limited to 'Source/WebCore/platform/network/qt')
7 files changed, 337 insertions, 296 deletions
diff --git a/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h b/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h index 892a3fb..4fcd19c 100644 --- a/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h +++ b/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h @@ -32,7 +32,7 @@ namespace WebCore { class DnsPrefetchHelper : public QObject { Q_OBJECT public: - DnsPrefetchHelper() : QObject(), currentLookups(0) {}; + DnsPrefetchHelper() : QObject(), currentLookups(0) { } public slots: void lookup(QString hostname) @@ -42,26 +42,8 @@ namespace WebCore { if (currentLookups >= 10) return; // do not launch more than 10 lookups at the same time -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 3) currentLookups++; QHostInfo::lookupHost(hostname, this, SLOT(lookedUp(QHostInfo))); -#else - // This code is only needed for Qt versions that do not have - // the small Qt DNS cache yet. - - QTime* entryTime = lookupCache.object(hostname); - if (entryTime && entryTime->elapsed() > 300*1000) { - // delete knowledge about lookup if it is already 300 seconds old - lookupCache.remove(hostname); - } else if (!entryTime) { - // not in cache yet, can look it up - QTime *tmpTime = new QTime(); - *tmpTime = QTime::currentTime(); - lookupCache.insert(hostname, tmpTime); - currentLookups++; - QHostInfo::lookupHost(hostname, this, SLOT(lookedUp(QHostInfo))); - } -#endif } void lookedUp(const QHostInfo&) @@ -74,9 +56,6 @@ namespace WebCore { } protected: -#if QT_VERSION < QT_VERSION_CHECK(4, 6, 3) - QCache<QString, QTime> lookupCache; // 100 entries -#endif int currentLookups; }; diff --git a/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h b/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h index 766dc90..4b8252c 100644 --- a/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h +++ b/Source/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h @@ -22,15 +22,9 @@ #include <QObject> -#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) -namespace QtMobility { -class QNetworkConfigurationManager; -} -#else QT_BEGIN_NAMESPACE class QNetworkConfigurationManager; QT_END_NAMESPACE -#endif namespace WebCore { @@ -46,11 +40,7 @@ public slots: void networkAccessPermissionChanged(bool); public: -#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) - QtMobility::QNetworkConfigurationManager* m_configurationManager; -#else QNetworkConfigurationManager* m_configurationManager; -#endif bool m_online; bool m_networkAccessAllowed; NetworkStateNotifier* m_notifier; diff --git a/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp index f3e7023..ced52eb 100644 --- a/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp +++ b/Source/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp @@ -25,10 +25,6 @@ #include "NetworkStateNotifierPrivate.h" #include "qnetworkconfigmanager.h" -#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) -using namespace QtMobility; -#endif - namespace WebCore { NetworkStateNotifierPrivate::NetworkStateNotifierPrivate(NetworkStateNotifier* notifier) diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index 61fe96c..6e63145 100644 --- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -41,21 +41,11 @@ #include <QDebug> #include <QCoreApplication> -// What type of connection should be used for the signals of the -// QNetworkReply? This depends on if Qt has a bugfix for this or not. -// It is fixed in Qt 4.6.3. See https://bugs.webkit.org/show_bug.cgi?id=32113 -// and https://bugs.webkit.org/show_bug.cgi?id=36755 -#if QT_VERSION > QT_VERSION_CHECK(4, 6, 2) -#define SIGNAL_CONN Qt::DirectConnection -#else -#define SIGNAL_CONN Qt::QueuedConnection -#endif - // In Qt 4.8, the attribute for sending a request synchronously will be made public, // for now, use this hackish solution for setting the internal attribute. const QNetworkRequest::Attribute gSynchronousNetworkRequestAttribute = static_cast<QNetworkRequest::Attribute>(QNetworkRequest::HttpPipeliningWasUsedAttribute + 7); -static const int gMaxRecursionLimit = 10; +static const int gMaxRedirections = 10; namespace WebCore { @@ -159,6 +149,86 @@ bool FormDataIODevice::isSequential() const return true; } +QNetworkReplyWrapper::QNetworkReplyWrapper(QNetworkReply* reply, QObject* parent) + : QObject(parent) + , m_reply(reply) +{ + Q_ASSERT(m_reply); + + connect(m_reply, SIGNAL(metaDataChanged()), this, SLOT(receiveMetaData())); + connect(m_reply, SIGNAL(readyRead()), this, SLOT(receiveMetaData())); + connect(m_reply, SIGNAL(finished()), this, SLOT(receiveMetaData())); +} + +QNetworkReplyWrapper::~QNetworkReplyWrapper() +{ + if (m_reply) + m_reply->deleteLater(); +} + +QNetworkReply* QNetworkReplyWrapper::release() +{ + if (!m_reply) + return 0; + + resetConnections(); + QNetworkReply* reply = m_reply; + m_reply = 0; + reply->setParent(0); + return reply; +} + +void QNetworkReplyWrapper::resetConnections() +{ + if (m_reply) + m_reply->disconnect(this); + QCoreApplication::removePostedEvents(this, QEvent::MetaCall); +} + +void QNetworkReplyWrapper::receiveMetaData() +{ + // This slot is only used to receive the first signal from the QNetworkReply object. + resetConnections(); + + m_redirectionTargetUrl = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (m_redirectionTargetUrl.isValid()) { + emit metaDataChanged(); + emit finished(); + return; + } + + WTF::String contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString(); + m_encoding = extractCharsetFromMediaType(contentType); + m_advertisedMimeType = extractMIMETypeFromMediaType(contentType); + + bool hasData = m_reply->bytesAvailable(); + bool isFinished = m_reply->isFinished(); + + if (!isFinished) { + // If not finished, connect to the slots that will be used from this point on. + connect(m_reply, SIGNAL(readyRead()), this, SIGNAL(readyRead())); + connect(m_reply, SIGNAL(finished()), this, SLOT(didReceiveFinished())); + } + + emit metaDataChanged(); + + if (hasData) + emit readyRead(); + + if (isFinished) { + emit finished(); + return; + } + +} + +void QNetworkReplyWrapper::didReceiveFinished() +{ + // Disconnecting will make sure that nothing will happen after emitting the finished signal. + resetConnections(); + emit finished(); +} + String QNetworkReplyHandler::httpMethod() const { switch (m_method) { @@ -172,30 +242,24 @@ String QNetworkReplyHandler::httpMethod() const return "PUT"; case QNetworkAccessManager::DeleteOperation: return "DELETE"; -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) case QNetworkAccessManager::CustomOperation: return m_resourceHandle->firstRequest().httpMethod(); -#endif default: ASSERT_NOT_REACHED(); return "GET"; } } -QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode loadMode) +QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadType loadType, bool deferred) : QObject(0) - , m_reply(0) + , m_replyWrapper(0) , m_resourceHandle(handle) - , m_redirected(false) - , m_responseSent(false) - , m_responseContainsData(false) - , m_loadMode(loadMode) - , m_shouldStart(true) - , m_shouldFinish(false) - , m_shouldSendResponse(false) - , m_shouldForwardData(false) - , m_redirectionTries(gMaxRecursionLimit) + , m_loadType(loadType) + , m_deferred(deferred) + , m_redirectionTries(gMaxRedirections) { + resetState(); + const ResourceRequest &r = m_resourceHandle->firstRequest(); if (r.httpMethod() == "GET") @@ -208,13 +272,8 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load m_method = QNetworkAccessManager::PutOperation; else if (r.httpMethod() == "DELETE") m_method = QNetworkAccessManager::DeleteOperation; -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) else m_method = QNetworkAccessManager::CustomOperation; -#else - else - m_method = QNetworkAccessManager::UnknownOperation; -#endif QObject* originatingObject = 0; if (m_resourceHandle->getInternal()->m_context) @@ -222,40 +281,58 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load m_request = r.toNetworkRequest(originatingObject); - if (m_loadMode == LoadSynchronously) - m_request.setAttribute(gSynchronousNetworkRequestAttribute, true); - - if (m_loadMode == LoadNormal || m_loadMode == LoadSynchronously) + if (!m_deferred) start(); +} + +void QNetworkReplyHandler::resetState() +{ + m_redirected = false; + m_responseSent = false; + m_responseContainsData = false; + m_hasStarted = false; + m_callFinishOnResume = false; + m_callSendResponseIfNeededOnResume = false; + m_callForwardDataOnResume = false; + + if (m_replyWrapper) { + m_replyWrapper->deleteLater(); + m_replyWrapper = 0; + } +} - if (m_loadMode == LoadSynchronously) - m_loadMode = LoadNormal; +void QNetworkReplyHandler::setLoadingDeferred(bool deferred) +{ + m_deferred = deferred; + + if (!deferred) + resumeDeferredLoad(); } -void QNetworkReplyHandler::setLoadMode(LoadMode mode) +void QNetworkReplyHandler::resumeDeferredLoad() { - // https://bugs.webkit.org/show_bug.cgi?id=26556 - // We cannot call sendQueuedItems() from here, because the signal that - // caused us to get into deferred mode, might not be processed yet. - switch (mode) { - case LoadNormal: - m_loadMode = LoadResuming; - emit processQueuedItems(); - break; - case LoadDeferred: - m_loadMode = LoadDeferred; - break; - case LoadResuming: - Q_ASSERT(0); // should never happen - break; - }; + if (!m_hasStarted) { + ASSERT(!m_callSendResponseIfNeededOnResume); + ASSERT(!m_callForwardDataOnResume); + ASSERT(!m_callFinishOnResume); + start(); + return; + } + + if (m_callSendResponseIfNeededOnResume) + sendResponseIfNeeded(); + + if (m_callForwardDataOnResume) + forwardData(); + + if (m_callFinishOnResume) + finish(); } void QNetworkReplyHandler::abort() { m_resourceHandle = 0; - if (m_reply) { - QNetworkReply* reply = release(); + if (QNetworkReply* reply = release()) { reply->abort(); reply->deleteLater(); } @@ -264,20 +341,16 @@ void QNetworkReplyHandler::abort() QNetworkReply* QNetworkReplyHandler::release() { - QNetworkReply* reply = m_reply; - if (m_reply) { - disconnect(m_reply, 0, this, 0); - // We have queued connections to the QNetworkReply. Make sure any - // posted meta call events that were the result of a signal emission - // don't reach the slots in our instance. - QCoreApplication::removePostedEvents(this, QEvent::MetaCall); - m_reply->setParent(0); - m_reply = 0; - } + if (!m_replyWrapper) + return 0; + + QNetworkReply* reply = m_replyWrapper->release(); + m_replyWrapper->deleteLater(); + m_replyWrapper = 0; return reply; } -static bool ignoreHttpError(QNetworkReply* reply, bool receivedData) +static bool shouldIgnoreHttpError(QNetworkReply* reply, bool receivedData) { int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -292,66 +365,73 @@ static bool ignoreHttpError(QNetworkReply* reply, bool receivedData) void QNetworkReplyHandler::finish() { - m_shouldFinish = (m_loadMode != LoadNormal); - if (m_shouldFinish) + ASSERT(m_hasStarted); + + m_callFinishOnResume = m_deferred; + if (m_deferred) return; - if (!m_reply) + if (!m_replyWrapper || !m_replyWrapper->reply()) return; + sendResponseIfNeeded(); - if (!m_resourceHandle) + if (wasAborted()) return; + ResourceHandleClient* client = m_resourceHandle->client(); if (!client) { - m_reply->deleteLater(); - m_reply = 0; + m_replyWrapper->deleteLater(); + m_replyWrapper = 0; return; } - if (!m_redirected) { - if (!m_reply->error() || ignoreHttpError(m_reply, m_responseContainsData)) - client->didFinishLoading(m_resourceHandle, 0); - else { - QUrl url = m_reply->url(); - int httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - if (httpStatusCode) { - ResourceError error("HTTP", httpStatusCode, url.toString(), m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); - client->didFail(m_resourceHandle, error); - } else { - ResourceError error("QtNetwork", m_reply->error(), url.toString(), m_reply->errorString()); - client->didFail(m_resourceHandle, error); - } - } - if (m_reply) { - m_reply->deleteLater(); - m_reply = 0; - } - } else { - if (m_reply) { - m_reply->deleteLater(); - m_reply = 0; - } + if (m_redirected) { resetState(); start(); + return; + } + + if (!m_replyWrapper->reply()->error() || shouldIgnoreHttpError(m_replyWrapper->reply(), m_responseContainsData)) + client->didFinishLoading(m_resourceHandle, 0); + else { + QUrl url = m_replyWrapper->reply()->url(); + int httpStatusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + if (httpStatusCode) { + ResourceError error("HTTP", httpStatusCode, url.toString(), m_replyWrapper->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); + client->didFail(m_resourceHandle, error); + } else { + ResourceError error("QtNetwork", m_replyWrapper->reply()->error(), url.toString(), m_replyWrapper->reply()->errorString()); + client->didFail(m_resourceHandle, error); + } + } + + if (m_replyWrapper) { + m_replyWrapper->deleteLater(); + m_replyWrapper = 0; } } void QNetworkReplyHandler::sendResponseIfNeeded() { - m_shouldSendResponse = (m_loadMode != LoadNormal); - if (m_shouldSendResponse) + ASSERT(m_hasStarted); + + m_callSendResponseIfNeededOnResume = m_deferred; + if (m_deferred) return; - if (!m_reply) + if (!m_replyWrapper || !m_replyWrapper->reply()) return; - if (m_reply->error() && !ignoreHttpError(m_reply, m_responseContainsData)) + if (m_replyWrapper->reply()->error() && !shouldIgnoreHttpError(m_replyWrapper->reply(), m_responseContainsData)) return; - if (m_responseSent || !m_resourceHandle) + if (wasAborted()) + return; + + if (m_responseSent) return; m_responseSent = true; @@ -359,18 +439,18 @@ void QNetworkReplyHandler::sendResponseIfNeeded() if (!client) return; - WTF::String contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString(); + WTF::String contentType = m_replyWrapper->reply()->header(QNetworkRequest::ContentTypeHeader).toString(); WTF::String encoding = extractCharsetFromMediaType(contentType); WTF::String mimeType = extractMIMETypeFromMediaType(contentType); if (mimeType.isEmpty()) { // let's try to guess from the extension - mimeType = MIMETypeRegistry::getMIMETypeForPath(m_reply->url().path()); + mimeType = MIMETypeRegistry::getMIMETypeForPath(m_replyWrapper->reply()->url().path()); } - KURL url(m_reply->url()); + KURL url(m_replyWrapper->reply()->url()); ResourceResponse response(url, mimeType.lower(), - m_reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), + m_replyWrapper->reply()->header(QNetworkRequest::ContentLengthHeader).toLongLong(), encoding, String()); if (url.isLocalFile()) { @@ -379,10 +459,10 @@ void QNetworkReplyHandler::sendResponseIfNeeded() } // The status code is equal to 0 for protocols not in the HTTP family. - int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + int statusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (url.protocolInHTTPFamily()) { - String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromAscii(m_reply->rawHeader("Content-Disposition"))); + String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromLatin1(m_replyWrapper->reply()->rawHeader("Content-Disposition"))); if (!suggestedFilename.isEmpty()) response.setSuggestedFilename(suggestedFilename); @@ -390,70 +470,79 @@ void QNetworkReplyHandler::sendResponseIfNeeded() response.setSuggestedFilename(url.lastPathComponent()); response.setHTTPStatusCode(statusCode); - response.setHTTPStatusText(m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData()); + response.setHTTPStatusText(m_replyWrapper->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData()); // Add remaining headers. -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - foreach (const QNetworkReply::RawHeaderPair& pair, m_reply->rawHeaderPairs()) - response.setHTTPHeaderField(QString::fromAscii(pair.first), QString::fromAscii(pair.second)); -#else - foreach (const QByteArray& headerName, m_reply->rawHeaderList()) - response.setHTTPHeaderField(QString::fromAscii(headerName), QString::fromAscii(m_reply->rawHeader(headerName))); -#endif + foreach (const QNetworkReply::RawHeaderPair& pair, m_replyWrapper->reply()->rawHeaderPairs()) + response.setHTTPHeaderField(QString::fromLatin1(pair.first), QString::fromLatin1(pair.second)); } - QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + QUrl redirection = m_replyWrapper->reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (redirection.isValid()) { - QUrl newUrl = m_reply->url().resolved(redirection); + redirect(response, redirection); + return; + } - m_redirectionTries--; - if (m_redirectionTries == 0) { // 10 or more redirections to the same url is considered infinite recursion - ResourceError error(newUrl.host(), 400 /*bad request*/, - newUrl.toString(), - QCoreApplication::translate("QWebPage", "Redirection limit reached")); - client->didFail(m_resourceHandle, error); - return; - } - m_redirected = true; + client->didReceiveResponse(m_resourceHandle, response); +} +void QNetworkReplyHandler::redirect(ResourceResponse& response, const QUrl& redirection) +{ + QUrl newUrl = m_replyWrapper->reply()->url().resolved(redirection); - // Status Code 301 (Moved Permanently), 302 (Moved Temporarily), 303 (See Other): - // - If original request is POST convert to GET and redirect automatically - // Status Code 307 (Temporary Redirect) and all other redirect status codes: - // - Use the HTTP method from the previous request - if ((statusCode >= 301 && statusCode <= 303) && m_resourceHandle->firstRequest().httpMethod() == "POST") - m_method = QNetworkAccessManager::GetOperation; + ResourceHandleClient* client = m_resourceHandle->client(); + ASSERT(client); + + int statusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - ResourceRequest newRequest = m_resourceHandle->firstRequest(); - newRequest.setHTTPMethod(httpMethod()); - newRequest.setURL(newUrl); + m_redirectionTries--; + if (!m_redirectionTries) { + ResourceError error(newUrl.host(), 400 /*bad request*/, + newUrl.toString(), + QCoreApplication::translate("QWebPage", "Redirection limit reached")); + client->didFail(m_resourceHandle, error); + return; + } + m_redirected = true; - // Should not set Referer after a redirect from a secure resource to non-secure one. - if (!newRequest.url().protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https")) - newRequest.clearHTTPReferrer(); + // Status Code 301 (Moved Permanently), 302 (Moved Temporarily), 303 (See Other): + // - If original request is POST convert to GET and redirect automatically + // Status Code 307 (Temporary Redirect) and all other redirect status codes: + // - Use the HTTP method from the previous request + if ((statusCode >= 301 && statusCode <= 303) && m_resourceHandle->firstRequest().httpMethod() == "POST") + m_method = QNetworkAccessManager::GetOperation; - client->willSendRequest(m_resourceHandle, newRequest, response); - if (!m_resourceHandle) // network error did cancel the request - return; + ResourceRequest newRequest = m_resourceHandle->firstRequest(); + newRequest.setHTTPMethod(httpMethod()); + newRequest.setURL(newUrl); - QObject* originatingObject = 0; - if (m_resourceHandle->getInternal()->m_context) - originatingObject = m_resourceHandle->getInternal()->m_context->originatingObject(); + // Should not set Referer after a redirect from a secure resource to non-secure one. + if (!newRequest.url().protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https")) + newRequest.clearHTTPReferrer(); - m_request = newRequest.toNetworkRequest(originatingObject); + client->willSendRequest(m_resourceHandle, newRequest, response); + if (wasAborted()) // Network error cancelled the request. return; - } - client->didReceiveResponse(m_resourceHandle, response); + QObject* originatingObject = 0; + if (m_resourceHandle->getInternal()->m_context) + originatingObject = m_resourceHandle->getInternal()->m_context->originatingObject(); + + m_request = newRequest.toNetworkRequest(originatingObject); } void QNetworkReplyHandler::forwardData() { - m_shouldForwardData = (m_loadMode != LoadNormal); - if (m_shouldForwardData) + ASSERT(m_hasStarted); + + m_callForwardDataOnResume = m_deferred; + if (m_deferred) return; - if (m_reply->bytesAvailable()) + if (!m_replyWrapper || !m_replyWrapper->reply()) + return; + + if (m_replyWrapper->reply()->bytesAvailable()) m_responseContainsData = true; sendResponseIfNeeded(); @@ -462,22 +551,25 @@ void QNetworkReplyHandler::forwardData() if (m_redirected) return; - if (!m_resourceHandle) + if (wasAborted()) return; - QByteArray data = m_reply->read(m_reply->bytesAvailable()); + QByteArray data = m_replyWrapper->reply()->read(m_replyWrapper->reply()->bytesAvailable()); ResourceHandleClient* client = m_resourceHandle->client(); if (!client) return; + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793 + // -1 means we do not provide any data about transfer size to inspector so it would use + // Content-Length headers or content size to show transfer size. if (!data.isEmpty()) - client->didReceiveData(m_resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/); + client->didReceiveData(m_resourceHandle, data.constData(), data.length(), -1); } void QNetworkReplyHandler::uploadProgress(qint64 bytesSent, qint64 bytesTotal) { - if (!m_resourceHandle) + if (wasAborted()) return; ResourceHandleClient* client = m_resourceHandle->client(); @@ -487,9 +579,10 @@ void QNetworkReplyHandler::uploadProgress(qint64 bytesSent, qint64 bytesTotal) client->didSendData(m_resourceHandle, bytesSent, bytesTotal); } -void QNetworkReplyHandler::start() +QNetworkReply* QNetworkReplyHandler::sendNetworkRequest() { - m_shouldStart = false; + if (m_loadType == SynchronousLoad) + m_request.setAttribute(gSynchronousNetworkRequestAttribute, true); ResourceHandleInternal* d = m_resourceHandle->getInternal(); @@ -498,7 +591,7 @@ void QNetworkReplyHandler::start() manager = d->m_context->networkAccessManager(); if (!manager) - return; + return 0; const QUrl url = m_request.url(); const QString scheme = url.scheme(); @@ -511,108 +604,61 @@ void QNetworkReplyHandler::start() switch (m_method) { case QNetworkAccessManager::GetOperation: - m_reply = manager->get(m_request); - break; + return manager->get(m_request); case QNetworkAccessManager::PostOperation: { - FormDataIODevice* postDevice = new FormDataIODevice(d->m_firstRequest.httpBody()); + FormDataIODevice* postDevice = new FormDataIODevice(d->m_firstRequest.httpBody()); // We may be uploading files so prevent QNR from buffering data m_request.setHeader(QNetworkRequest::ContentLengthHeader, postDevice->getFormDataSize()); m_request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, QVariant(true)); - m_reply = manager->post(m_request, postDevice); - postDevice->setParent(m_reply); - break; + QNetworkReply* result = manager->post(m_request, postDevice); + postDevice->setParent(result); + return result; } case QNetworkAccessManager::HeadOperation: - m_reply = manager->head(m_request); - break; + return manager->head(m_request); case QNetworkAccessManager::PutOperation: { - FormDataIODevice* putDevice = new FormDataIODevice(d->m_firstRequest.httpBody()); + FormDataIODevice* putDevice = new FormDataIODevice(d->m_firstRequest.httpBody()); // We may be uploading files so prevent QNR from buffering data m_request.setHeader(QNetworkRequest::ContentLengthHeader, putDevice->getFormDataSize()); m_request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, QVariant(true)); - m_reply = manager->put(m_request, putDevice); - putDevice->setParent(m_reply); - break; + QNetworkReply* result = manager->put(m_request, putDevice); + putDevice->setParent(result); + return result; } case QNetworkAccessManager::DeleteOperation: { - m_reply = manager->deleteResource(m_request); - break; + return manager->deleteResource(m_request); } -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) case QNetworkAccessManager::CustomOperation: - m_reply = manager->sendCustomRequest(m_request, m_resourceHandle->firstRequest().httpMethod().latin1().data()); - break; -#endif - case QNetworkAccessManager::UnknownOperation: { - m_reply = 0; - ResourceHandleClient* client = m_resourceHandle->client(); - if (client) { - ResourceError error(url.host(), 400 /*bad request*/, - url.toString(), - QCoreApplication::translate("QWebPage", "Bad HTTP request")); - client->didFail(m_resourceHandle, error); - } - return; - } - } - - m_reply->setParent(this); - - if (m_loadMode == LoadSynchronously && m_reply->isFinished()) { - // If supported, a synchronous request will be finished at this point, no need to hook up the signals. - return; - } - - connect(m_reply, SIGNAL(finished()), - this, SLOT(finish()), SIGNAL_CONN); - - // For http(s) we know that the headers are complete upon metaDataChanged() emission, so we - // can send the response as early as possible - if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) - connect(m_reply, SIGNAL(metaDataChanged()), - this, SLOT(sendResponseIfNeeded()), SIGNAL_CONN); - - connect(m_reply, SIGNAL(readyRead()), - this, SLOT(forwardData()), SIGNAL_CONN); - - if (m_resourceHandle->firstRequest().reportUploadProgress()) { - connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)), - this, SLOT(uploadProgress(qint64, qint64)), SIGNAL_CONN); + return manager->sendCustomRequest(m_request, m_resourceHandle->firstRequest().httpMethod().latin1().data()); + case QNetworkAccessManager::UnknownOperation: + ASSERT_NOT_REACHED(); + return 0; } - - // Make this a direct function call once we require 4.6.1+. - connect(this, SIGNAL(processQueuedItems()), - this, SLOT(sendQueuedItems()), SIGNAL_CONN); + return 0; } -void QNetworkReplyHandler::resetState() +void QNetworkReplyHandler::start() { - m_redirected = false; - m_responseSent = false; - m_responseContainsData = false; - m_shouldStart = true; - m_shouldFinish = false; - m_shouldSendResponse = false; - m_shouldForwardData = false; -} + ASSERT(!m_hasStarted); + m_hasStarted = true; -void QNetworkReplyHandler::sendQueuedItems() -{ - if (m_loadMode != LoadResuming) + QNetworkReply* reply = sendNetworkRequest(); + if (!reply) return; - m_loadMode = LoadNormal; - if (m_shouldStart) - start(); + m_replyWrapper = new QNetworkReplyWrapper(reply, this); - if (m_shouldSendResponse) - sendResponseIfNeeded(); + if (m_loadType == SynchronousLoad && m_replyWrapper->reply()->isFinished()) { + // If supported, a synchronous request will be finished at this point, no need to hook up the signals. + return; + } - if (m_shouldForwardData) - forwardData(); + connect(m_replyWrapper, SIGNAL(finished()), this, SLOT(finish())); + connect(m_replyWrapper, SIGNAL(metaDataChanged()), this, SLOT(sendResponseIfNeeded())); + connect(m_replyWrapper, SIGNAL(readyRead()), this, SLOT(forwardData())); - if (m_shouldFinish) - finish(); + if (m_resourceHandle->firstRequest().reportUploadProgress()) + connect(m_replyWrapper->reply(), SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64))); } } diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h index 8c9bd08..61694d6 100644 --- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h +++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h @@ -34,56 +34,90 @@ QT_END_NAMESPACE namespace WebCore { class ResourceHandle; +class ResourceResponse; + +class QNetworkReplyWrapper : public QObject { + Q_OBJECT +public: + QNetworkReplyWrapper(QNetworkReply*, QObject* parent = 0); + ~QNetworkReplyWrapper(); + + QNetworkReply* reply() const { return m_reply; } + QNetworkReply* release(); + + QUrl redirectionTargetUrl() const { return m_redirectionTargetUrl; } + QString encoding() const { return m_encoding; } + QString advertisedMimeType() const { return m_advertisedMimeType; } + +Q_SIGNALS: + void finished(); + void metaDataChanged(); + void readyRead(); + void uploadProgress(qint64 bytesSent, qint64 bytesTotal); + +private Q_SLOTS: + void receiveMetaData(); + void didReceiveFinished(); + +private: + void resetConnections(); + + QNetworkReply* m_reply; + QUrl m_redirectionTargetUrl; + + QString m_encoding; + QString m_advertisedMimeType; +}; class QNetworkReplyHandler : public QObject { Q_OBJECT public: - enum LoadMode { - LoadNormal, - LoadDeferred, - LoadResuming, - LoadSynchronously + enum LoadType { + AsynchronousLoad, + SynchronousLoad }; - QNetworkReplyHandler(ResourceHandle *handle, LoadMode); - void setLoadMode(LoadMode); + QNetworkReplyHandler(ResourceHandle*, LoadType, bool deferred = false); + void setLoadingDeferred(bool); - QNetworkReply* reply() const { return m_reply; } + QNetworkReply* reply() const { return m_replyWrapper ? m_replyWrapper->reply() : 0; } void abort(); QNetworkReply* release(); -signals: - void processQueuedItems(); - public slots: void finish(); void sendResponseIfNeeded(); void forwardData(); - void sendQueuedItems(); void uploadProgress(qint64 bytesSent, qint64 bytesTotal); private: void start(); void resetState(); String httpMethod() const; + void resumeDeferredLoad(); + void redirect(ResourceResponse&, const QUrl&); + bool wasAborted() const { return !m_resourceHandle; } + QNetworkReply* sendNetworkRequest(); - QNetworkReply* m_reply; + QNetworkReplyWrapper* m_replyWrapper; ResourceHandle* m_resourceHandle; bool m_redirected; bool m_responseSent; bool m_responseContainsData; - LoadMode m_loadMode; + LoadType m_loadType; QNetworkAccessManager::Operation m_method; QNetworkRequest m_request; + bool m_deferred; + // defer state holding - bool m_shouldStart; - bool m_shouldFinish; - bool m_shouldSendResponse; - bool m_shouldForwardData; + bool m_hasStarted; + bool m_callFinishOnResume; + bool m_callSendResponseIfNeededOnResume; + bool m_callForwardDataOnResume; int m_redirectionTries; }; diff --git a/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp b/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp index cd17660..a6da432 100644 --- a/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp +++ b/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp @@ -42,9 +42,6 @@ #include "ResourceHandleInternal.h" #include "SharedBuffer.h" -// FIXME: WebCore including these headers from WebKit is a massive layering violation. -#include "qwebframe_p.h" - #include <QAbstractNetworkCache> #include <QCoreApplication> #include <QUrl> @@ -140,7 +137,7 @@ bool ResourceHandle::start(NetworkingContext* context) getInternal()->m_context = context; ResourceHandleInternal *d = getInternal(); - d->m_job = new QNetworkReplyHandler(this, QNetworkReplyHandler::LoadMode(d->m_defersLoading)); + d->m_job = new QNetworkReplyHandler(this, QNetworkReplyHandler::AsynchronousLoad, d->m_defersLoading); return true; } @@ -207,7 +204,7 @@ void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const d->m_firstRequest.setURL(urlWithCredentials); } d->m_context = context; - d->m_job = new QNetworkReplyHandler(handle.get(), QNetworkReplyHandler::LoadSynchronously); + d->m_job = new QNetworkReplyHandler(handle.get(), QNetworkReplyHandler::SynchronousLoad); QNetworkReply* reply = d->m_job->reply(); // When using synchronous calls, we are finished when reaching this point. @@ -225,8 +222,9 @@ void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const void ResourceHandle::platformSetDefersLoading(bool defers) { - if (d->m_job) - d->m_job->setLoadMode(QNetworkReplyHandler::LoadMode(defers)); + if (!d->m_job) + return; + d->m_job->setLoadingDeferred(defers); } } // namespace WebCore diff --git a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp index 7e162ed..498c90a 100644 --- a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp +++ b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp @@ -83,13 +83,11 @@ QNetworkRequest ResourceRequest::toNetworkRequest(QObject* originatingFrame) con break; } -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) if (!allowCookies()) { request.setAttribute(QNetworkRequest::CookieLoadControlAttribute, QNetworkRequest::Manual); request.setAttribute(QNetworkRequest::CookieSaveControlAttribute, QNetworkRequest::Manual); request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual); } -#endif return request; } |