summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLutz Schönemann <lutz.schoenemann@basyskom.com>2014-12-17 16:27:35 +0100
committerTony Sarajärvi <tony.sarajarvi@digia.com>2015-05-15 17:58:17 +0000
commit368adbf8e75c00712c7a30eb6b8d7a7e175e89d7 (patch)
treedab3625745d0add6087c5fc69f27dbbb87d87d06
parentc3bcbd1dcd8df8c93924853308d7f2ec95aba825 (diff)
downloadqtwebchannel-368adbf8e75c00712c7a30eb6b8d7a7e175e89d7.tar.gz
Fix wrap registered object issue
When wrapping a registered object the code generated a new ID for an already known object. That new ID wasn't stored but returned to the client including the objects information. That resulted in a new created object on client side but the remote object (on the server) was not accessible. This patch fixes the issue by just returning the known ID of a known object. Because the client already has a local representation of that object it does not have to unwrap the object description. Change-Id: I31964823c84c84fd7ebce4386865c18fb5518be7 Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
-rw-r--r--src/webchannel/qmetaobjectpublisher.cpp9
-rw-r--r--src/webchannel/qwebchannel.js2
-rw-r--r--tests/auto/webchannel/tst_webchannel.cpp56
-rw-r--r--tests/auto/webchannel/tst_webchannel.h20
4 files changed, 83 insertions, 4 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp
index 0cad569..42c95d2 100644
--- a/src/webchannel/qmetaobjectpublisher.cpp
+++ b/src/webchannel/qmetaobjectpublisher.cpp
@@ -449,16 +449,18 @@ QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelA
{
if (QObject *object = result.value<QObject *>()) {
QString id = registeredObjectIds.value(object);
+
QJsonObject classInfo;
if (id.isEmpty()) {
// neither registered, nor wrapped, do so now
id = QUuid::createUuid().toString();
- Q_ASSERT(!registeredObjects.contains(id));
+ // store ID before the call to classInfoForObject()
+ // in case of self-contained objects it avoids
+ // infinite loops
+ registeredObjectIds[object] = id;
classInfo = classInfoForObject(object, transport);
- registeredObjectIds[object] = id;
-
ObjectInfo oi(object, classInfo);
if (transport) {
oi.transports.append(transport);
@@ -485,6 +487,7 @@ QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelA
objectInfo[KEY_ID] = id;
if (!classInfo.isEmpty())
objectInfo[KEY_DATA] = classInfo;
+
return objectInfo;
} else if (result.canConvert<QJSValue>()) {
// Workaround for keeping QJSValues from QVariant.
diff --git a/src/webchannel/qwebchannel.js b/src/webchannel/qwebchannel.js
index c270a95..f114e77 100644
--- a/src/webchannel/qwebchannel.js
+++ b/src/webchannel/qwebchannel.js
@@ -193,7 +193,7 @@ function QObject(name, data, webChannel)
}
if (!response
|| !response["__QObject*__"]
- || response["id"] === undefined) {
+ || response.id === undefined) {
return response;
}
diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp
index 55fd2d9..e36a1b3 100644
--- a/tests/auto/webchannel/tst_webchannel.cpp
+++ b/tests/auto/webchannel/tst_webchannel.cpp
@@ -148,6 +148,12 @@ void TestWebChannel::testInfoForObject()
}
{
QJsonArray method;
+ method.append(QStringLiteral("setObjectProperty"));
+ method.append(obj.metaObject()->indexOfMethod("setObjectProperty(QObject*)"));
+ expected.append(method);
+ }
+ {
+ QJsonArray method;
method.append(QStringLiteral("method1"));
method.append(obj.metaObject()->indexOfMethod("method1()"));
expected.append(method);
@@ -230,6 +236,19 @@ void TestWebChannel::testInfoForObject()
property.append(obj.bar());
expected.append(property);
}
+ {
+ QJsonArray property;
+ property.append(obj.metaObject()->indexOfProperty("objectProperty"));
+ property.append(QStringLiteral("objectProperty"));
+ {
+ QJsonArray signal;
+ signal.append(1);
+ signal.append(obj.metaObject()->indexOfMethod("objectPropertyChanged()"));
+ property.append(signal);
+ }
+ property.append(QJsonValue::fromVariant(QVariant::fromValue(obj.objectProperty())));
+ expected.append(property);
+ }
QCOMPARE(info["properties"].toArray(), expected);
}
}
@@ -270,6 +289,43 @@ void TestWebChannel::testDisconnect()
m_dummyTransport->emitMessageReceived(QJsonObject());
}
+void TestWebChannel::testWrapRegisteredObject()
+{
+ QWebChannel channel;
+ TestObject obj;
+ obj.setObjectName("myTestObject");
+
+ channel.registerObject(obj.objectName(), &obj);
+ channel.connectTo(m_dummyTransport);
+ channel.d_func()->publisher->initializeClient(m_dummyTransport);
+
+ QJsonObject objectInfo = channel.d_func()->publisher->wrapResult(QVariant::fromValue(&obj), m_dummyTransport).toObject();
+
+ QCOMPARE(2, objectInfo.length());
+ QVERIFY(objectInfo.contains("id"));
+ QVERIFY(objectInfo.contains("__QObject*__"));
+ QVERIFY(objectInfo.value("__QObject*__").isBool() && objectInfo.value("__QObject*__").toBool());
+
+ QString returnedId = objectInfo.value("id").toString();
+
+ QCOMPARE(&obj, channel.d_func()->publisher->registeredObjects.value(obj.objectName()));
+ QCOMPARE(obj.objectName(), channel.d_func()->publisher->registeredObjectIds.value(&obj));
+ QCOMPARE(obj.objectName(), returnedId);
+}
+
+void TestWebChannel::testInfiniteRecursion()
+{
+ QWebChannel channel;
+ TestObject obj;
+ obj.setObjectProperty(&obj);
+ obj.setObjectName("myTestObject");
+
+ channel.connectTo(m_dummyTransport);
+ channel.d_func()->publisher->initializeClient(m_dummyTransport);
+
+ QJsonObject objectInfo = channel.d_func()->publisher->wrapResult(QVariant::fromValue(&obj), m_dummyTransport).toObject();
+}
+
static QHash<QString, QObject*> createObjects(QObject *parent)
{
const int num = 100;
diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h
index 7b9a1e3..649e61f 100644
--- a/tests/auto/webchannel/tst_webchannel.h
+++ b/tests/auto/webchannel/tst_webchannel.h
@@ -69,9 +69,12 @@ class TestObject : public QObject
Q_PROPERTY(Foo foo READ foo CONSTANT)
Q_PROPERTY(int asdf READ asdf NOTIFY asdfChanged)
Q_PROPERTY(QString bar READ bar NOTIFY theBarHasChanged)
+ Q_PROPERTY(QObject * objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectPropertyChanged)
+
public:
explicit TestObject(QObject *parent = 0)
: QObject(parent)
+ , mObjectProperty(0)
{ }
enum Foo {
@@ -83,6 +86,11 @@ public:
int asdf() const {return 42;}
QString bar() const {return QString();}
+ QObject *objectProperty() const
+ {
+ return mObjectProperty;
+ }
+
Q_INVOKABLE void method1() {}
protected:
@@ -96,16 +104,26 @@ signals:
void sig2(const QString&);
void asdfChanged();
void theBarHasChanged();
+ void objectPropertyChanged();
public slots:
void slot1() {}
void slot2(const QString&) {}
+ void setObjectProperty(QObject *object)
+ {
+ mObjectProperty = object;
+ emit objectPropertyChanged();
+ }
+
protected slots:
void slot3() {}
private slots:
void slot4() {}
+
+public:
+ QObject *mObjectProperty;
};
class BenchObject : public QObject
@@ -218,6 +236,8 @@ private slots:
void testInfoForObject();
void testInvokeMethodConversion();
void testDisconnect();
+ void testWrapRegisteredObject();
+ void testInfiniteRecursion();
void benchClassInfo();
void benchInitializeClients();