From 5e2796c35fb829aae3e9870ac1d738a296b08a6e Mon Sep 17 00:00:00 2001
From: Markus Goetz <Markus.Goetz@nokia.com>
Date: Wed, 28 Jul 2010 10:36:33 +0200
Subject: QNAM: New specialized QNetworkReply for data: URLs

Implement a QNetworkReplyDataImpl for data: URLs.
This avoids having the overhead of a special
backend class of QNetworkReplyImpl.
Also move the instantiation to the begin of
QNAM::createRequest() so no network sesssion is needed.

Reviewed-by: Thiago Macieira
Reviewed-by: Peter Hartmann
---
 src/network/access/access.pri                |   2 +
 src/network/access/qnetworkaccessmanager.cpp |   6 ++
 src/network/access/qnetworkreplydataimpl.cpp | 146 +++++++++++++++++++++++++++
 src/network/access/qnetworkreplydataimpl_p.h |  98 ++++++++++++++++++
 4 files changed, 252 insertions(+)
 create mode 100644 src/network/access/qnetworkreplydataimpl.cpp
 create mode 100644 src/network/access/qnetworkreplydataimpl_p.h

diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index e255a0d..9cd2096 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -27,6 +27,7 @@ HEADERS += \
     access/qnetworkreply.h \
     access/qnetworkreply_p.h \
     access/qnetworkreplyimpl_p.h \
+    access/qnetworkreplydataimpl_p.h \
     access/qnetworkreplyfileimpl_p.h \
     access/qabstractnetworkcache_p.h \
     access/qabstractnetworkcache.h \
@@ -55,6 +56,7 @@ SOURCES += \
     access/qnetworkrequest.cpp \
     access/qnetworkreply.cpp \
     access/qnetworkreplyimpl.cpp \
+    access/qnetworkreplydataimpl.cpp \
     access/qnetworkreplyfileimpl.cpp \
     access/qabstractnetworkcache.cpp \
     access/qnetworkdiskcache.cpp
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 9738a4f..add75bf 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -54,6 +54,7 @@
 #include "qnetworkaccessfilebackend_p.h"
 #include "qnetworkaccessdatabackend_p.h"
 #include "qnetworkaccessdebugpipebackend_p.h"
+#include "qnetworkreplydataimpl_p.h"
 #include "qnetworkreplyfileimpl_p.h"
 
 #include "QtCore/qbuffer.h"
@@ -955,6 +956,11 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
         return new QNetworkReplyFileImpl(this, req, op);
     }
 
+    if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
+            && req.url().scheme().toLower() == QLatin1String("data")) {
+        return new QNetworkReplyDataImpl(this, req, op);
+    }
+
 #ifndef QT_NO_BEARERMANAGEMENT
     // Return a disabled network reply if network access is disabled.
     // Except if the scheme is empty or file://.
diff --git a/src/network/access/qnetworkreplydataimpl.cpp b/src/network/access/qnetworkreplydataimpl.cpp
new file mode 100644
index 0000000..9e74a21
--- /dev/null
+++ b/src/network/access/qnetworkreplydataimpl.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "qnetworkreplydataimpl_p.h"
+#include "private/qdataurl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QNetworkReplyDataImplPrivate::QNetworkReplyDataImplPrivate()
+    : QNetworkReplyPrivate()
+{
+}
+
+QNetworkReplyDataImplPrivate::~QNetworkReplyDataImplPrivate()
+{
+}
+
+QNetworkReplyDataImpl::~QNetworkReplyDataImpl()
+{
+}
+
+QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op)
+    : QNetworkReply(*new QNetworkReplyDataImplPrivate(), parent)
+{
+    Q_D(QNetworkReplyDataImpl);
+    setRequest(req);
+    setUrl(req.url());
+    setOperation(op);
+    setFinished(true);
+    QNetworkReply::open(QIODevice::ReadOnly);
+
+    QUrl url = req.url();
+
+    // FIXME qDecodeDataUrl should instead be rewritten to have the QByteArray
+    // and the mime type as an output parameter and return a bool instead
+    d->decodeDataUrlResult = qDecodeDataUrl(url);
+
+    if (! d->decodeDataUrlResult.first.isNull()) {
+        QString &mimeType = d->decodeDataUrlResult.first;
+        qint64 size = d->decodeDataUrlResult.second.size();
+        setHeader(QNetworkRequest::ContentTypeHeader, mimeType);
+        setHeader(QNetworkRequest::ContentLengthHeader, size);
+        QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection);
+
+        d->decodedData.setBuffer(&d->decodeDataUrlResult.second);
+        d->decodedData.open(QIODevice::ReadOnly);
+
+        QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection,
+                                  Q_ARG(qint64,size), Q_ARG(qint64, size));
+        QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
+        QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+    } else {
+        // something wrong with this URI
+        const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
+                                                        "Invalid URI: %1").arg(url.toString());
+        setError(QNetworkReply::ProtocolFailure, msg);
+        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+                                  Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure));
+        QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+    }
+}
+
+void QNetworkReplyDataImpl::close()
+{
+    QNetworkReply::close();
+}
+
+void QNetworkReplyDataImpl::abort()
+{
+    QNetworkReply::close();
+}
+
+qint64 QNetworkReplyDataImpl::bytesAvailable() const
+{
+    Q_D(const QNetworkReplyDataImpl);
+    return QNetworkReply::bytesAvailable() + d->decodedData.bytesAvailable();
+}
+
+bool QNetworkReplyDataImpl::isSequential () const
+{
+    return true;
+}
+
+qint64 QNetworkReplyDataImpl::size() const
+{
+    Q_D(const QNetworkReplyDataImpl);
+    return d->decodedData.size();
+}
+
+/*!
+    \internal
+*/
+qint64 QNetworkReplyDataImpl::readData(char *data, qint64 maxlen)
+{
+    Q_D(QNetworkReplyDataImpl);
+
+    // TODO idea:
+    // Instead of decoding the whole data into new memory, we could decode on demand.
+    // Note that this might be tricky to do.
+
+    return d->decodedData.read(data, maxlen);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qnetworkreplydataimpl_p.cpp"
+
diff --git a/src/network/access/qnetworkreplydataimpl_p.h b/src/network/access/qnetworkreplydataimpl_p.h
new file mode 100644
index 0000000..6c62d28
--- /dev/null
+++ b/src/network/access/qnetworkreplydataimpl_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+#ifndef QNETWORKREPLYDATAIMPL_H
+#define QNETWORKREPLYDATAIMPL_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of the Network Access API.  This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworkreply.h"
+#include "qnetworkreply_p.h"
+#include "qnetworkaccessmanager.h"
+#include <QBuffer>
+
+QT_BEGIN_NAMESPACE
+
+
+class QNetworkReplyDataImplPrivate;
+class QNetworkReplyDataImpl: public QNetworkReply
+{
+    Q_OBJECT
+public:
+    QNetworkReplyDataImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op);
+    ~QNetworkReplyDataImpl();
+    virtual void abort();
+
+    // reimplemented from QNetworkReply
+    virtual void close();
+    virtual qint64 bytesAvailable() const;
+    virtual bool isSequential () const;
+    qint64 size() const;
+
+    virtual qint64 readData(char *data, qint64 maxlen);
+
+    Q_DECLARE_PRIVATE(QNetworkReplyDataImpl)
+};
+
+class QNetworkReplyDataImplPrivate: public QNetworkReplyPrivate
+{
+public:
+    QNetworkReplyDataImplPrivate();
+    ~QNetworkReplyDataImplPrivate();
+
+    QPair<QString, QByteArray> decodeDataUrlResult;
+    QBuffer decodedData;
+
+    Q_DECLARE_PUBLIC(QNetworkReplyDataImpl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QNETWORKREPLYDATAIMPL_H
-- 
cgit v0.12


From edcec6164cb96a1e26586025e7c72532a9220a38 Mon Sep 17 00:00:00 2001
From: Markus Goetz <Markus.Goetz@nokia.com>
Date: Tue, 5 Oct 2010 13:29:12 +0200
Subject: QNAM: Fix usage of toString of QUrl

Reviewed-by: Thiago Macieira
---
 src/network/access/qnetworkreplydataimpl.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/network/access/qnetworkreplydataimpl.cpp b/src/network/access/qnetworkreplydataimpl.cpp
index 9e74a21..36f9356 100644
--- a/src/network/access/qnetworkreplydataimpl.cpp
+++ b/src/network/access/qnetworkreplydataimpl.cpp
@@ -90,7 +90,7 @@ QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequ
     } else {
         // something wrong with this URI
         const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
-                                                        "Invalid URI: %1").arg(url.toString());
+                                                        "Invalid URI: %1").arg(QString::fromLatin1(url.toEncoded()));
         setError(QNetworkReply::ProtocolFailure, msg);
         QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                   Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure));
-- 
cgit v0.12


From dda652beae0de6931071be599f7ee4020a81a499 Mon Sep 17 00:00:00 2001
From: Markus Goetz <Markus.Goetz@nokia.com>
Date: Tue, 5 Oct 2010 13:33:23 +0200
Subject: QNAM: Remove QNetworkAccessDataBackend

The QNetworkReplyDataImpl is now used instead.
---
 src/network/access/access.pri                    |   2 -
 src/network/access/qnetworkaccessdatabackend.cpp | 125 -----------------------
 src/network/access/qnetworkaccessmanager.cpp     |   4 +-
 3 files changed, 1 insertion(+), 130 deletions(-)
 delete mode 100644 src/network/access/qnetworkaccessdatabackend.cpp

diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index 9cd2096..4c21ba5 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -12,7 +12,6 @@ HEADERS += \
     access/qnetworkaccessmanager_p.h \
     access/qnetworkaccesscache_p.h \
     access/qnetworkaccessbackend_p.h \
-    access/qnetworkaccessdatabackend_p.h \
     access/qnetworkaccessdebugpipebackend_p.h \
     access/qnetworkaccesshttpbackend_p.h \
     access/qnetworkaccessfilebackend_p.h \
@@ -45,7 +44,6 @@ SOURCES += \
     access/qnetworkaccessmanager.cpp \
     access/qnetworkaccesscache.cpp \
     access/qnetworkaccessbackend.cpp \
-    access/qnetworkaccessdatabackend.cpp \
     access/qnetworkaccessdebugpipebackend.cpp \
     access/qnetworkaccessfilebackend.cpp \
     access/qnetworkaccesscachebackend.cpp \
diff --git a/src/network/access/qnetworkaccessdatabackend.cpp b/src/network/access/qnetworkaccessdatabackend.cpp
deleted file mode 100644
index efb6e3e..0000000
--- a/src/network/access/qnetworkaccessdatabackend.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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 "qnetworkaccessdatabackend_p.h"
-#include "qnetworkrequest.h"
-#include "qnetworkreply.h"
-#include "qurlinfo.h"
-#include "private/qdataurl_p.h"
-#include <qcoreapplication.h>
-
-QT_BEGIN_NAMESPACE
-
-QNetworkAccessBackend *
-QNetworkAccessDataBackendFactory::create(QNetworkAccessManager::Operation,
-                                         const QNetworkRequest &request) const
-{
-    if (request.url().scheme() == QLatin1String("data"))
-        return new QNetworkAccessDataBackend;
-
-    return 0;
-}
-
-QNetworkAccessDataBackend::QNetworkAccessDataBackend()
-{
-}
-
-QNetworkAccessDataBackend::~QNetworkAccessDataBackend()
-{
-}
-
-void QNetworkAccessDataBackend::open()
-{
-    QUrl uri = request().url();
-
-    if (operation() != QNetworkAccessManager::GetOperation &&
-        operation() != QNetworkAccessManager::HeadOperation) {
-        // data: doesn't support anything but GET
-        const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
-                                                        "Operation not supported on %1")
-                      .arg(uri.toString());
-        error(QNetworkReply::ContentOperationNotPermittedError, msg);
-        finished();
-        return;
-    }
-
-    QPair<QString, QByteArray> decoded = qDecodeDataUrl(uri);
-
-    if (! decoded.first.isNull()) {
-        setHeader(QNetworkRequest::ContentTypeHeader, decoded.first);
-        setHeader(QNetworkRequest::ContentLengthHeader, decoded.second.size());
-        emit metaDataChanged();
-
-        QByteDataBuffer list;
-        list.append(decoded.second);
-        decoded.second.clear(); // important because of implicit sharing!
-        writeDownstreamData(list);
-
-        finished();
-        return;
-    }
-
-    // something wrong with this URI
-    const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
-                                                    "Invalid URI: %1").arg(uri.toString());
-    error(QNetworkReply::ProtocolFailure, msg);
-    finished();
-}
-
-void QNetworkAccessDataBackend::closeDownstreamChannel()
-{
-}
-
-void QNetworkAccessDataBackend::closeUpstreamChannel()
-{
-}
-
-bool QNetworkAccessDataBackend::waitForDownstreamReadyRead(int)
-{
-    return false;
-}
-
-bool QNetworkAccessDataBackend::waitForUpstreamBytesWritten(int)
-{
-    return false;
-}
-
-QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index add75bf..85b0f92 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -52,7 +52,6 @@
 #include "qnetworkaccesshttpbackend_p.h"
 #include "qnetworkaccessftpbackend_p.h"
 #include "qnetworkaccessfilebackend_p.h"
-#include "qnetworkaccessdatabackend_p.h"
 #include "qnetworkaccessdebugpipebackend_p.h"
 #include "qnetworkreplydataimpl_p.h"
 #include "qnetworkreplyfileimpl_p.h"
@@ -70,7 +69,6 @@ QT_BEGIN_NAMESPACE
 Q_GLOBAL_STATIC(QNetworkAccessHttpBackendFactory, httpBackend)
 #endif // QT_NO_HTTP
 Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
-Q_GLOBAL_STATIC(QNetworkAccessDataBackendFactory, dataBackend)
 #ifndef QT_NO_FTP
 Q_GLOBAL_STATIC(QNetworkAccessFtpBackendFactory, ftpBackend)
 #endif // QT_NO_FTP
@@ -84,7 +82,7 @@ static void ensureInitialized()
 #ifndef QT_NO_HTTP
     (void) httpBackend();
 #endif // QT_NO_HTTP
-    (void) dataBackend();
+
 #ifndef QT_NO_FTP
     (void) ftpBackend();
 #endif
-- 
cgit v0.12


From 2b47265f59b1874a829aff539fe88fb0b70de147 Mon Sep 17 00:00:00 2001
From: Markus Goetz <Markus.Goetz@nokia.com>
Date: Tue, 5 Oct 2010 13:35:35 +0200
Subject: QNAM: Move out function calls to new variable

---
 src/network/access/qnetworkaccessmanager.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 85b0f92..8c17916 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -946,16 +946,17 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
     Q_D(QNetworkAccessManager);
 
     bool isLocalFile = req.url().isLocalFile();
+    QString scheme = req.url().scheme().toLower();
 
     // fast path for GET on file:// URLs
     // The QNetworkAccessFileBackend will right now only be used for PUT
     if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
-        && (isLocalFile || req.url().scheme() == QLatin1String("qrc"))) {
+        && (isLocalFile || scheme == QLatin1String("qrc"))) {
         return new QNetworkReplyFileImpl(this, req, op);
     }
 
     if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
-            && req.url().scheme().toLower() == QLatin1String("data")) {
+            && scheme == QLatin1String("data")) {
         return new QNetworkReplyDataImpl(this, req, op);
     }
 
-- 
cgit v0.12