aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorValery Kotov <kotov.valery@gmail.com>2015-03-04 21:57:14 +0200
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2015-03-09 19:41:41 +0000
commitd988310434b00cc0e159fdf6ff3f586eefc47eed (patch)
tree6dd1bdfb543a3ca8a2a1d0c51273b1e6a9fe5bb8
parent0294702c9c174c67de563cfdea5c32548d111a58 (diff)
QML Engine: ArrayBuffer XHR response type support
Support for "arraybuffer" response type for QQmlXMLHttpRequest was added. [ChangeLog][QtQml][QQmlXMLHttpRequest] QQmlXMLHttpRequest now supports "arraybuffer" binary response type. Change-Id: I866e543cc7bc6ab037ffff1ef6628057b73daf90 Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
-rw-r--r--src/qml/jsruntime/qv4engine.cpp10
-rw-r--r--src/qml/jsruntime/qv4engine_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp76
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/qml_logo.pngbin0 -> 27151 bytes
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml27
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect7
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.reply3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp19
8 files changed, 144 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 2c8a68812a..54dd5979cf 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -582,6 +582,16 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *pr
return object->d();
}
+Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array)
+{
+ Scope scope(this);
+ Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array.size()));
+ if (!hasException) {
+ memcpy(object->d()->data->data(), array.data(), array.size());
+ }
+ return object->d();
+}
+
Heap::DateObject *ExecutionEngine::newDateObject(const Value &value)
{
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 098510e91a..bcb74ab694 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -268,6 +268,8 @@ public:
Heap::ArrayObject *newArrayObject(const QStringList &list);
Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype);
+ Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
+
Heap::DateObject *newDateObject(const Value &value);
Heap::DateObject *newDateObject(const QDateTime &dt);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index afa79ee6b1..a2c5f09061 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -59,6 +59,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4arraybuffer_p.h>
using namespace QV4;
@@ -1022,6 +1023,9 @@ public:
QString responseBody();
const QByteArray & rawResponseBody() const;
bool receivedXml() const;
+
+ const QString & responseType() const;
+ void setResponseType(const QString &);
private slots:
void readyRead();
void error(QNetworkReply::NetworkError);
@@ -1070,12 +1074,15 @@ private:
QNetworkAccessManager *m_nam;
QNetworkAccessManager *networkAccessManager() { return m_nam; }
+
+ QString m_responseType;
};
QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager)
: v4(engine)
, m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
, m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
+ , m_responseType()
{
}
@@ -1461,6 +1468,16 @@ bool QQmlXMLHttpRequest::receivedXml() const
return m_gotXml;
}
+const QString & QQmlXMLHttpRequest::responseType() const
+{
+ return m_responseType;
+}
+
+void QQmlXMLHttpRequest::setResponseType(const QString &responseType)
+{
+ m_responseType = responseType;
+}
+
#ifndef QT_NO_TEXTCODEC
QTextCodec* QQmlXMLHttpRequest::findTextCodec() const
@@ -1640,6 +1657,9 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
static ReturnedValue method_get_statusText(CallContext *ctx);
static ReturnedValue method_get_responseText(CallContext *ctx);
static ReturnedValue method_get_responseXML(CallContext *ctx);
+ static ReturnedValue method_get_response(CallContext *ctx);
+ static ReturnedValue method_get_responseType(CallContext *ctx);
+ static ReturnedValue method_set_responseType(CallContext *ctx);
};
}
@@ -1686,6 +1706,10 @@ void QQmlXMLHttpRequestCtor::setupProto()
p->defineAccessorProperty(QStringLiteral("statusText"),method_get_statusText, 0);
p->defineAccessorProperty(QStringLiteral("responseText"),method_get_responseText, 0);
p->defineAccessorProperty(QStringLiteral("responseXML"),method_get_responseXML, 0);
+ p->defineAccessorProperty(QStringLiteral("response"),method_get_response, 0);
+
+ // Read-write properties
+ p->defineAccessorProperty(QStringLiteral("responseType"), method_get_responseType, method_set_responseType);
// State values
p->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
@@ -1945,6 +1969,58 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
}
}
+ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ if (!w)
+ V4THROW_REFERENCE("Not an XMLHttpRequest object");
+ QQmlXMLHttpRequest *r = w->d()->request;
+
+ if (r->readyState() != QQmlXMLHttpRequest::Loading &&
+ r->readyState() != QQmlXMLHttpRequest::Done)
+ return QV4::Encode(scope.engine->newString(QString()));
+
+ const QString& responseType = r->responseType();
+ if (responseType.compare(QLatin1String("text"), Qt::CaseInsensitive) == 0) {
+ return QV4::Encode(scope.engine->newString(r->responseBody()));
+ } else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) {
+ return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody()));
+ } else {
+ return QV4::Encode(scope.engine->newString(QString()));
+ }
+
+ return Encode::undefined();
+}
+
+
+ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseType(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ if (!w)
+ V4THROW_REFERENCE("Not an XMLHttpRequest object");
+ QQmlXMLHttpRequest *r = w->d()->request;
+ return QV4::Encode(scope.engine->newString(r->responseType()));
+}
+
+ReturnedValue QQmlXMLHttpRequestCtor::method_set_responseType(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ if (!w)
+ V4THROW_REFERENCE("Not an XMLHttpRequest object");
+ QQmlXMLHttpRequest *r = w->d()->request;
+
+ if (ctx->argc() < 1)
+ V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
+
+ // Argument 0 - response type
+ r->setResponseType(ctx->args()[0].toQStringNoThrow());
+
+ return Encode::undefined();
+}
+
void qt_rem_qmlxmlhttprequest(ExecutionEngine * /* engine */, void *d)
{
QQmlXMLHttpRequestData *data = (QQmlXMLHttpRequestData *)d;
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/qml_logo.png b/tests/auto/qml/qqmlxmlhttprequest/data/qml_logo.png
new file mode 100644
index 0000000000..681aef8aa2
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/qml_logo.png
Binary files differ
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
new file mode 100644
index 0000000000..234d759284
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+
+QtObject {
+ property string url
+ property int readSize: 0
+
+ Component.onCompleted: {
+
+ var request = new XMLHttpRequest();
+ request.open("GET", url);
+ request.responseType = "arraybuffer";
+
+ request.onreadystatechange = function() {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ var arrayBuffer = request.response;
+ if (arrayBuffer) {
+ var byteArray = new Uint8Array(arrayBuffer);
+ readSize = byteArray.byteLength;
+ }
+ }
+ }
+
+ request.send(null);
+
+ }
+}
+
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
new file mode 100644
index 0000000000..79a61383e3
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
@@ -0,0 +1,7 @@
+GET /gml_logo.png HTTP/1.1
+Accept-Language: en-US,*
+Content-Type: image/png
+Connection: Keep-Alive
+Accept-Encoding: gzip, deflate
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.reply b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.reply
new file mode 100644
index 0000000000..44ba138213
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.reply
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Connection: close
+Content-Type: image/png
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index fe1b8b1505..dd70f81d5e 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -87,6 +87,7 @@ private slots:
void getAllResponseHeaders_unsent();
void getAllResponseHeaders_sent();
void getAllResponseHeaders_args();
+ void getBinaryData();
void status();
void status_data();
void statusText();
@@ -816,6 +817,24 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders_args()
QTRY_VERIFY(object->property("exceptionThrown").toBool() == true);
}
+void tst_qqmlxmlhttprequest::getBinaryData()
+{
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("receive_binary_data.expect"),
+ testFileUrl("receive_binary_data.reply"),
+ testFileUrl("qml_logo.png")));
+
+ QQmlComponent component(&engine, testFileUrl("receiveBinaryData.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", "http://127.0.0.1:14445/gml_logo.png");
+ component.completeCreate();
+
+ QFileInfo fileInfo("data/qml_logo.png");
+ QTRY_VERIFY(object->property("readSize").toInt() == fileInfo.size());
+}
+
void tst_qqmlxmlhttprequest::status()
{
QFETCH(QUrl, replyUrl);