summaryrefslogtreecommitdiffstats
path: root/src/network/access/qnetworkreplyfileimpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/access/qnetworkreplyfileimpl.cpp')
-rw-r--r--src/network/access/qnetworkreplyfileimpl.cpp150
1 files changed, 96 insertions, 54 deletions
diff --git a/src/network/access/qnetworkreplyfileimpl.cpp b/src/network/access/qnetworkreplyfileimpl.cpp
index 36bc4b41df..ef319ebf0d 100644
--- a/src/network/access/qnetworkreplyfileimpl.cpp
+++ b/src/network/access/qnetworkreplyfileimpl.cpp
@@ -40,31 +40,45 @@
#include "qnetworkreplyfileimpl_p.h"
#include "QtCore/qdatetime.h"
+#include "qnetworkaccessmanager_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QFileInfo>
+#include <QtCore/QThread>
+#include "qnetworkfile_p.h"
+#include "qnetworkrequest.h"
QT_BEGIN_NAMESPACE
QNetworkReplyFileImplPrivate::QNetworkReplyFileImplPrivate()
- : QNetworkReplyPrivate(), realFileSize(0)
+ : QNetworkReplyPrivate(), managerPrivate(0), realFile(0)
{
+ qRegisterMetaType<QNetworkRequest::KnownHeaders>();
+ qRegisterMetaType<QNetworkReply::NetworkError>();
}
QNetworkReplyFileImpl::~QNetworkReplyFileImpl()
{
+ QNetworkReplyFileImplPrivate *d = (QNetworkReplyFileImplPrivate*) d_func();
+ if (d->realFile) {
+ if (d->realFile->thread() == QThread::currentThread())
+ delete d->realFile;
+ else
+ QMetaObject::invokeMethod(d->realFile, "deleteLater", Qt::QueuedConnection);
+ }
}
-QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op)
- : QNetworkReply(*new QNetworkReplyFileImplPrivate(), parent)
+QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, const QNetworkRequest &req, const QNetworkAccessManager::Operation op)
+ : QNetworkReply(*new QNetworkReplyFileImplPrivate(), manager)
{
setRequest(req);
setUrl(req.url());
setOperation(op);
- setFinished(true);
QNetworkReply::open(QIODevice::ReadOnly);
QNetworkReplyFileImplPrivate *d = (QNetworkReplyFileImplPrivate*) d_func();
+ d->managerPrivate = manager->d_func();
+
QUrl url = req.url();
if (url.host() == QLatin1String("localhost"))
url.setHost(QString());
@@ -77,7 +91,7 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ
setError(QNetworkReply::ProtocolInvalidOperationError, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError));
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+ fileOpenFinished(false);
return;
}
#endif
@@ -85,7 +99,6 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ
url.setPath(QLatin1String("/"));
setUrl(url);
-
QString fileName = url.toLocalFile();
if (fileName.isEmpty()) {
const QString scheme = url.scheme();
@@ -101,68 +114,85 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ
}
}
- QFileInfo fi(fileName);
- if (fi.isDir()) {
- QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString());
- setError(QNetworkReply::ContentOperationNotPermittedError, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError));
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
- return;
- }
-
- d->realFile.setFileName(fileName);
- bool opened = d->realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered);
-
- // could we open the file?
- if (!opened) {
- QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2")
- .arg(d->realFile.fileName(), d->realFile.errorString());
-
- if (d->realFile.exists()) {
- setError(QNetworkReply::ContentAccessDenied, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied));
- } else {
- setError(QNetworkReply::ContentNotFoundError, msg);
+ if (req.attribute(QNetworkRequest::BackgroundRequestAttribute).toBool()) { // Asynchronous open
+ auto realFile = new QNetworkFile(fileName);
+ connect(realFile, &QNetworkFile::headerRead, this, &QNetworkReplyFileImpl::setHeader,
+ Qt::QueuedConnection);
+ connect(realFile, &QNetworkFile::error, this, &QNetworkReplyFileImpl::setError,
+ Qt::QueuedConnection);
+ connect(realFile, SIGNAL(finished(bool)), SLOT(fileOpenFinished(bool)),
+ Qt::QueuedConnection);
+
+ realFile->moveToThread(d->managerPrivate->createThread());
+ QMetaObject::invokeMethod(realFile, "open", Qt::QueuedConnection);
+
+ d->realFile = realFile;
+ } else { // Synch open
+ setFinished(true);
+
+ QFileInfo fi(fileName);
+ if (fi.isDir()) {
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString());
+ setError(QNetworkReply::ContentOperationNotPermittedError, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError));
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError));
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+ return;
+ }
+ d->realFile = new QFile(fileName, this);
+ bool opened = d->realFile->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+
+ // could we open the file?
+ if (!opened) {
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2")
+ .arg(d->realFile->fileName(), d->realFile->errorString());
+
+ if (fi.exists()) {
+ setError(QNetworkReply::ContentAccessDenied, msg);
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied));
+ } else {
+ setError(QNetworkReply::ContentNotFoundError, msg);
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError));
+ }
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+ return;
}
+ setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified());
+ setHeader(QNetworkRequest::ContentLengthHeader, fi.size());
+
+ QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection,
+ Q_ARG(qint64, fi.size()), Q_ARG(qint64, fi.size()));
+ QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
- return;
}
-
- setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified());
- d->realFileSize = fi.size();
- setHeader(QNetworkRequest::ContentLengthHeader, d->realFileSize);
-
- QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection);
- QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection,
- Q_ARG(qint64, d->realFileSize), Q_ARG(qint64, d->realFileSize));
- QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}
void QNetworkReplyFileImpl::close()
{
Q_D(QNetworkReplyFileImpl);
QNetworkReply::close();
- d->realFile.close();
+ if (d->realFile) {
+ if (d->realFile->thread() == thread())
+ d->realFile->close();
+ else
+ QMetaObject::invokeMethod(d->realFile, "close", Qt::QueuedConnection);
+ }
}
void QNetworkReplyFileImpl::abort()
{
- Q_D(QNetworkReplyFileImpl);
- QNetworkReply::close();
- d->realFile.close();
+ close();
}
qint64 QNetworkReplyFileImpl::bytesAvailable() const
{
Q_D(const QNetworkReplyFileImpl);
- if (!d->realFile.isOpen())
+ if (!d->isFinished || !d->realFile || !d->realFile->isOpen())
return QNetworkReply::bytesAvailable();
- return QNetworkReply::bytesAvailable() + d->realFile.bytesAvailable();
+ return QNetworkReply::bytesAvailable() + d->realFile->bytesAvailable();
}
bool QNetworkReplyFileImpl::isSequential () const
@@ -172,8 +202,9 @@ bool QNetworkReplyFileImpl::isSequential () const
qint64 QNetworkReplyFileImpl::size() const
{
- Q_D(const QNetworkReplyFileImpl);
- return d->realFileSize;
+ bool ok;
+ int size = header(QNetworkRequest::ContentLengthHeader).toInt(&ok);
+ return ok ? size : 0;
}
/*!
@@ -182,11 +213,11 @@ qint64 QNetworkReplyFileImpl::size() const
qint64 QNetworkReplyFileImpl::readData(char *data, qint64 maxlen)
{
Q_D(QNetworkReplyFileImpl);
- if (!d->realFile.isOpen())
+ if (!d->isFinished || !d->realFile || !d->realFile->isOpen())
return -1;
- qint64 ret = d->realFile.read(data, maxlen);
- if (bytesAvailable() == 0 && d->realFile.isOpen())
- d->realFile.close();
+ qint64 ret = d->realFile->read(data, maxlen);
+ if (bytesAvailable() == 0)
+ d->realFile->close();
if (ret == 0 && bytesAvailable() == 0)
return -1;
else {
@@ -196,6 +227,17 @@ qint64 QNetworkReplyFileImpl::readData(char *data, qint64 maxlen)
}
}
+void QNetworkReplyFileImpl::fileOpenFinished(bool isOpen)
+{
+ setFinished(true);
+ if (isOpen) {
+ const auto fileSize = size();
+ Q_EMIT metaDataChanged();
+ Q_EMIT downloadProgress(fileSize, fileSize);
+ Q_EMIT readyRead();
+ }
+ Q_EMIT finished();
+}
QT_END_NAMESPACE