X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fnetwork%2Faccess%2Fqnetworkreplyimpl.cpp;h=d0393475deaa7553d490c69d01044290003f07f3;hb=46e40214cfd62c935a20cddc7e9ae6fb45ba1884;hp=78e246315c0faca3a1e5f5e9113bb7e9da6fa203;hpb=e219892b9dcb7fa94aaffefb8b8cbd9fdad6f2fa;p=profile%2Fivi%2Fqtbase.git diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 78e2463..d039347 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -1,34 +1,34 @@ /**************************************************************************** ** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ ** ** 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. +** 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 +** 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. -** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. ** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. ** ** ** @@ -42,6 +42,7 @@ #include "qnetworkreplyimpl_p.h" #include "qnetworkaccessbackend_p.h" #include "qnetworkcookie.h" +#include "qnetworkcookiejar.h" #include "qabstractnetworkcache.h" #include "QtCore/qcoreapplication.h" #include "QtCore/qdatetime.h" @@ -72,6 +73,8 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() void QNetworkReplyImplPrivate::_q_startOperation() { + Q_Q(QNetworkReplyImpl); + // ensure this function is only being called once if (state == Working || state == Finished) { qDebug("QNetworkReplyImpl::_q_startOperation was called more than once"); @@ -90,30 +93,61 @@ void QNetworkReplyImplPrivate::_q_startOperation() } #ifndef QT_NO_BEARERMANAGEMENT - if (!backend->start()) { // ### we should call that method even if bearer is not used + // Do not start background requests if they are not allowed by session policy + QSharedPointer session(manager->d_func()->getNetworkSession()); + QVariant isBackground = backend->request().attribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(false)); + if (isBackground.toBool() && session && session->usagePolicies().testFlag(QNetworkSession::NoBackgroundTrafficPolicy)) { + error(QNetworkReply::BackgroundRequestNotAllowedError, + QCoreApplication::translate("QNetworkReply", "Background request not allowed.")); + finished(); + return; + } +#endif + + if (!backend->start()) { +#ifndef QT_NO_BEARERMANAGEMENT // backend failed to start because the session state is not Connected. - // QNetworkAccessManager will call reply->backend->start() again for us when the session + // QNetworkAccessManager will call _q_startOperation again for us when the session // state changes. state = WaitingForSession; - QNetworkSession *session = manager->d_func()->networkSession.data(); - if (session) { - Q_Q(QNetworkReplyImpl); - - QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)), + QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)), q, SLOT(_q_networkSessionFailed())); - if (!session->isOpen()) + if (!session->isOpen()) { + session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground); session->open(); + } } else { qWarning("Backend is waiting for QNetworkSession to connect, but there is none!"); + state = Working; + error(QNetworkReplyImpl::NetworkSessionFailedError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); } - +#else + qWarning("Backend start failed"); + state = Working; + error(QNetworkReplyImpl::UnknownNetworkError, + QCoreApplication::translate("QNetworkReply", "backend start error.")); + finished(); +#endif return; } + +#ifndef QT_NO_BEARERMANAGEMENT + if (session) { + //get notification of policy changes. + QObject::connect(session.data(), SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)), + q, SLOT(_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))); + } #endif + // Prepare timer for progress notifications + downloadProgressSignalChoke.start(); + uploadProgressSignalChoke.invalidate(); + if (backend && backend->isSynchronous()) { state = Finished; q_func()->setFinished(true); @@ -180,8 +214,11 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() // emit readyRead before downloadProgress incase this will cause events to be // processed and we get into a recursive call (as in QProgressDialog). emit q->readyRead(); - emit q->downloadProgress(bytesDownloaded, + if (downloadProgressSignalChoke.elapsed() >= progressSignalInterval) { + downloadProgressSignalChoke.restart(); + emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); + } resumeNotificationHandling(); } @@ -258,7 +295,7 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() if (manager.isNull()) return; - QNetworkSession *session = manager->d_func()->networkSession.data(); + QSharedPointer session = manager->d_func()->getNetworkSession(); if (!session) return; @@ -286,11 +323,32 @@ void QNetworkReplyImplPrivate::_q_networkSessionFailed() // Abort waiting and working replies. if (state == WaitingForSession || state == Working) { state = Working; - error(QNetworkReplyImpl::UnknownNetworkError, - QCoreApplication::translate("QNetworkReply", "Network session error.")); + QSharedPointer session(manager->d_func()->getNetworkSession()); + QString errorStr; + if (session) + errorStr = session->errorString(); + else + errorStr = QCoreApplication::translate("QNetworkReply", "Network session error."); + error(QNetworkReplyImpl::NetworkSessionFailedError, errorStr); finished(); } } + +void QNetworkReplyImplPrivate::_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies newPolicies) +{ + if (backend->request().attribute(QNetworkRequest::BackgroundRequestAttribute).toBool()) { + if (newPolicies & QNetworkSession::NoBackgroundTrafficPolicy) { + // Abort waiting and working replies. + if (state == WaitingForSession || state == Working) { + state = Working; + error(QNetworkReply::BackgroundRequestNotAllowedError, + QCoreApplication::translate("QNetworkReply", "Background request not allowed.")); + finished(); + } + // ### if backend->canResume(), then we could resume automatically, however no backend supports resuming + } + } +} #endif void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, @@ -441,10 +499,7 @@ void QNetworkReplyImplPrivate::createCache() { // check if we can save and if we're allowed to if (!networkCache() - || !request.attribute(QNetworkRequest::CacheSaveControlAttribute, true).toBool() - || request.attribute(QNetworkRequest::CacheLoadControlAttribute, - QNetworkRequest::PreferNetwork).toInt() - == QNetworkRequest::AlwaysNetwork) + || !request.attribute(QNetworkRequest::CacheSaveControlAttribute, true).toBool()) return; cacheEnabled = true; } @@ -496,6 +551,17 @@ void QNetworkReplyImplPrivate::emitUploadProgress(qint64 bytesSent, qint64 bytes { Q_Q(QNetworkReplyImpl); bytesUploaded = bytesSent; + + //choke signal emissions, except the first and last signals which are unconditional + if (uploadProgressSignalChoke.isValid()) { + if (bytesSent != bytesTotal && uploadProgressSignalChoke.elapsed() < progressSignalInterval) { + return; + } + uploadProgressSignalChoke.restart(); + } else { + uploadProgressSignalChoke.start(); + } + pauseNotificationHandling(); emit q->uploadProgress(bytesSent, bytesTotal); resumeNotificationHandling(); @@ -592,8 +658,11 @@ void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() emit q->readyRead(); // emit readyRead before downloadProgress incase this will cause events to be // processed and we get into a recursive call (as in QProgressDialog). - emit q->downloadProgress(bytesDownloaded, + if (downloadProgressSignalChoke.elapsed() >= progressSignalInterval) { + downloadProgressSignalChoke.restart(); + emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); + } resumeNotificationHandling(); // do we still have room in the buffer? @@ -652,7 +721,7 @@ char* QNetworkReplyImplPrivate::getDownloadBuffer(qint64 size) downloadBuffer = new char[downloadBufferMaximumSize]; // throws if allocation fails downloadBufferPointer = QSharedPointer(downloadBuffer, downloadBufferDeleter); - q->setAttribute(QNetworkRequest::DownloadBufferAttribute, qVariantFromValue > (downloadBufferPointer)); + q->setAttribute(QNetworkRequest::DownloadBufferAttribute, QVariant::fromValue > (downloadBufferPointer)); } } @@ -667,7 +736,7 @@ void QNetworkReplyImplPrivate::setDownloadBuffer(QSharedPointer sp, qint64 downloadBuffer = downloadBufferPointer.data(); downloadBufferCurrentSize = 0; downloadBufferMaximumSize = size; - q->setAttribute(QNetworkRequest::DownloadBufferAttribute, qVariantFromValue > (downloadBufferPointer)); + q->setAttribute(QNetworkRequest::DownloadBufferAttribute, QVariant::fromValue > (downloadBufferPointer)); } @@ -699,7 +768,10 @@ void QNetworkReplyImplPrivate::appendDownstreamDataDownloadBuffer(qint64 bytesRe // processed and we get into a recursive call (as in QProgressDialog). if (bytesDownloaded > 0) emit q->readyRead(); - emit q->downloadProgress(bytesDownloaded, bytesTotal); + if (downloadProgressSignalChoke.elapsed() >= progressSignalInterval) { + downloadProgressSignalChoke.restart(); + emit q->downloadProgress(bytesDownloaded, bytesTotal); + } } void QNetworkReplyImplPrivate::finished() @@ -716,7 +788,7 @@ void QNetworkReplyImplPrivate::finished() if (!manager.isNull()) { #ifndef QT_NO_BEARERMANAGEMENT - QNetworkSession *session = manager->d_func()->networkSession.data(); + QSharedPointer session (manager->d_func()->getNetworkSession()); if (session && session->state() == QNetworkSession::Roaming && state == Working && errorCode != QNetworkReply::OperationCanceledError) { // only content with a known size will fail with a temporary network failure error @@ -747,6 +819,8 @@ void QNetworkReplyImplPrivate::finished() pauseNotificationHandling(); if (totalSize.isNull() || totalSize == -1) { emit q->downloadProgress(bytesDownloaded, bytesDownloaded); + } else { + emit q->downloadProgress(bytesDownloaded, totalSize.toLongLong()); } if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer)) @@ -771,7 +845,7 @@ void QNetworkReplyImplPrivate::error(QNetworkReplyImpl::NetworkError code, const Q_Q(QNetworkReplyImpl); // Can't set and emit multiple errors. if (errorCode != QNetworkReply::NoError) { - qWarning() << "QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once."; + qWarning( "QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once."); return; } @@ -809,7 +883,7 @@ void QNetworkReplyImplPrivate::redirectionRequested(const QUrl &target) void QNetworkReplyImplPrivate::sslErrors(const QList &errors) { -#ifndef QT_NO_OPENSSL +#ifndef QT_NO_SSL Q_Q(QNetworkReplyImpl); emit q->sslErrors(errors); #else @@ -850,6 +924,8 @@ void QNetworkReplyImpl::abort() if (d->state != QNetworkReplyImplPrivate::Finished) { // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); + if (d->state == QNetworkReplyImplPrivate::WaitingForSession) + d->state = QNetworkReplyImplPrivate::Working; d->finished(); } d->state = QNetworkReplyImplPrivate::Aborted; @@ -918,14 +994,12 @@ void QNetworkReplyImpl::setReadBufferSize(qint64 size) d->backend->setDownstreamLimited(d->readBufferMaxSize > 0); } -#ifndef QT_NO_OPENSSL -QSslConfiguration QNetworkReplyImpl::sslConfigurationImplementation() const +#ifndef QT_NO_SSL +void QNetworkReplyImpl::sslConfigurationImplementation(QSslConfiguration &configuration) const { Q_D(const QNetworkReplyImpl); - QSslConfiguration config; if (d->backend) - d->backend->fetchSslConfiguration(config); - return config; + d->backend->fetchSslConfiguration(configuration); } void QNetworkReplyImpl::setSslConfigurationImplementation(const QSslConfiguration &config) @@ -948,7 +1022,7 @@ void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList &er if (d->backend) d->backend->ignoreSslErrors(errors); } -#endif // QT_NO_OPENSSL +#endif // QT_NO_SSL /*! \internal @@ -963,7 +1037,7 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) if (maxAvail == 0) return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; // FIXME what about "Aborted" state? - qMemCopy(data, d->downloadBuffer + d->downloadBufferReadPosition, maxAvail); + memcpy(data, d->downloadBuffer + d->downloadBufferReadPosition, maxAvail); d->downloadBufferReadPosition += maxAvail; return maxAvail; } @@ -1009,10 +1083,6 @@ bool QNetworkReplyImplPrivate::migrateBackend() if (state == Finished || state == Aborted) return true; - // Backend does not support resuming download. - if (!backend->canResume()) - return false; - // Request has outgoing data, not migrating. if (outgoingData) return false; @@ -1021,6 +1091,10 @@ bool QNetworkReplyImplPrivate::migrateBackend() if (copyDevice) return true; + // Backend does not support resuming download. + if (!backend->canResume()) + return false; + state = QNetworkReplyImplPrivate::Reconnecting; if (backend) {