diff -r 000000000000 -r 1918ee327afb src/network/access/qnetworkaccessbackend.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/network/access/qnetworkaccessbackend.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnetworkaccessbackend_p.h" +#include "qnetworkaccessmanager_p.h" +#include "qnetworkrequest.h" +#include "qnetworkreply.h" +#include "qnetworkreply_p.h" +#include "QtCore/qhash.h" +#include "QtCore/qmutex.h" + +#include "qnetworkaccesscachebackend_p.h" +#include "qabstractnetworkcache.h" + +#include "private/qnoncontiguousbytedevice_p.h" + +QT_BEGIN_NAMESPACE + +static bool factoryDataShutdown = false; +class QNetworkAccessBackendFactoryData: public QList +{ +public: + QNetworkAccessBackendFactoryData() : mutex(QMutex::Recursive) { } + ~QNetworkAccessBackendFactoryData() + { + QMutexLocker locker(&mutex); // why do we need to lock? + factoryDataShutdown = true; + } + + QMutex mutex; +}; +Q_GLOBAL_STATIC(QNetworkAccessBackendFactoryData, factoryData) + +QNetworkAccessBackendFactory::QNetworkAccessBackendFactory() +{ + QMutexLocker locker(&factoryData()->mutex); + factoryData()->prepend(this); +} + +QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory() +{ + if (!factoryDataShutdown) { + QMutexLocker locker(&factoryData()->mutex); + factoryData()->removeAll(this); + } +} + +QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op, + const QNetworkRequest &request) +{ + QNetworkRequest::CacheLoadControl mode = + static_cast( + request.attribute(QNetworkRequest::CacheLoadControlAttribute, + QNetworkRequest::PreferNetwork).toInt()); + if (mode == QNetworkRequest::AlwaysCache + && (op == QNetworkAccessManager::GetOperation + || op == QNetworkAccessManager::HeadOperation)) { + QNetworkAccessBackend *backend = new QNetworkAccessCacheBackend; + backend->manager = this; + return backend; + } + + if (!factoryDataShutdown) { + QMutexLocker locker(&factoryData()->mutex); + QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(), + end = factoryData()->constEnd(); + while (it != end) { + QNetworkAccessBackend *backend = (*it)->create(op, request); + if (backend) { + backend->manager = this; + return backend; // found a factory that handled our request + } + ++it; + } + } + return 0; +} + +QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice() +{ + QNonContiguousByteDevice* device = 0; + + if (reply->outgoingDataBuffer) + device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer); + else + device = QNonContiguousByteDeviceFactory::create(reply->outgoingData); + + bool bufferDisallowed = + reply->request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, + QVariant(false)) == QVariant(true); + if (bufferDisallowed) + device->disableReset(); + + // make sure we delete this later + device->setParent(this); + + connect(device, SIGNAL(readProgress(qint64,qint64)), this, SLOT(emitReplyUploadProgress(qint64,qint64))); + + return device; +} + +// need to have this function since the reply is a private member variable +// and the special backends need to access this. +void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal) +{ + reply->emitUploadProgress(bytesSent, bytesTotal); +} + +QNetworkAccessBackend::QNetworkAccessBackend() + : manager(0) + , reply(0) +{ +} + +QNetworkAccessBackend::~QNetworkAccessBackend() +{ +} + +void QNetworkAccessBackend::downstreamReadyWrite() +{ + // do nothing +} + +void QNetworkAccessBackend::copyFinished(QIODevice *) +{ + // do nothing +} + +void QNetworkAccessBackend::ignoreSslErrors() +{ + // do nothing +} + +void QNetworkAccessBackend::ignoreSslErrors(const QList &errors) +{ + Q_UNUSED(errors); + // do nothing +} + +void QNetworkAccessBackend::fetchSslConfiguration(QSslConfiguration &) const +{ + // do nothing +} + +void QNetworkAccessBackend::setSslConfiguration(const QSslConfiguration &) +{ + // do nothing +} + +QNetworkCacheMetaData QNetworkAccessBackend::fetchCacheMetaData(const QNetworkCacheMetaData &) const +{ + return QNetworkCacheMetaData(); +} + +QNetworkAccessManager::Operation QNetworkAccessBackend::operation() const +{ + return reply->operation; +} + +QNetworkRequest QNetworkAccessBackend::request() const +{ + return reply->request; +} + +#ifndef QT_NO_NETWORKPROXY +QList QNetworkAccessBackend::proxyList() const +{ + return reply->proxyList; +} +#endif + +QAbstractNetworkCache *QNetworkAccessBackend::networkCache() const +{ + if (!manager) + return 0; + return manager->networkCache; +} + +void QNetworkAccessBackend::setCachingEnabled(bool enable) +{ + reply->setCachingEnabled(enable); +} + +bool QNetworkAccessBackend::isCachingEnabled() const +{ + return reply->isCachingEnabled(); +} + +qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const +{ + return reply->nextDownstreamBlockSize(); +} + +void QNetworkAccessBackend::writeDownstreamData(QByteDataBuffer &list) +{ + reply->appendDownstreamData(list); +} + +void QNetworkAccessBackend::writeDownstreamData(QIODevice *data) +{ + reply->appendDownstreamData(data); +} + +QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const +{ + return reply->q_func()->header(header); +} + +void QNetworkAccessBackend::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value) +{ + reply->setCookedHeader(header, value); +} + +bool QNetworkAccessBackend::hasRawHeader(const QByteArray &headerName) const +{ + return reply->q_func()->hasRawHeader(headerName); +} + +QByteArray QNetworkAccessBackend::rawHeader(const QByteArray &headerName) const +{ + return reply->q_func()->rawHeader(headerName); +} + +QList QNetworkAccessBackend::rawHeaderList() const +{ + return reply->q_func()->rawHeaderList(); +} + +void QNetworkAccessBackend::setRawHeader(const QByteArray &headerName, const QByteArray &headerValue) +{ + reply->setRawHeader(headerName, headerValue); +} + +QVariant QNetworkAccessBackend::attribute(QNetworkRequest::Attribute code) const +{ + return reply->q_func()->attribute(code); +} + +void QNetworkAccessBackend::setAttribute(QNetworkRequest::Attribute code, const QVariant &value) +{ + if (value.isValid()) + reply->attributes.insert(code, value); + else + reply->attributes.remove(code); +} +QUrl QNetworkAccessBackend::url() const +{ + return reply->url; +} + +void QNetworkAccessBackend::setUrl(const QUrl &url) +{ + reply->url = url; +} + +void QNetworkAccessBackend::finished() +{ + reply->finished(); +} + +void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QString &errorString) +{ + reply->error(code, errorString); +} + +#ifndef QT_NO_NETWORKPROXY +void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy, + QAuthenticator *authenticator) +{ + manager->proxyAuthenticationRequired(this, proxy, authenticator); +} +#endif + +void QNetworkAccessBackend::authenticationRequired(QAuthenticator *authenticator) +{ + manager->authenticationRequired(this, authenticator); +} + +void QNetworkAccessBackend::metaDataChanged() +{ + reply->metaDataChanged(); +} + +void QNetworkAccessBackend::redirectionRequested(const QUrl &target) +{ + reply->redirectionRequested(target); +} + +void QNetworkAccessBackend::sslErrors(const QList &errors) +{ +#ifndef QT_NO_OPENSSL + reply->sslErrors(errors); +#else + Q_UNUSED(errors); +#endif +} + +QT_END_NAMESPACE