summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/imports/webchannel/plugins.qmltypes62
-rw-r--r--src/imports/webchannel/webchannel.pro2
-rw-r--r--src/webchannel/qmetaobjectpublisher.cpp112
-rw-r--r--src/webchannel/qmetaobjectpublisher_p.h15
-rw-r--r--src/webchannel/qwebchannel.js36
-rw-r--r--src/webchannel/signalhandler_p.h25
-rw-r--r--tests/auto/qml/tst_multiclient.qml21
-rw-r--r--tests/auto/qml/tst_webchannel.qml17
-rw-r--r--tests/auto/qml/tst_webchannelseparation.qml26
-rw-r--r--tests/auto/webchannel/tst_webchannel.cpp32
-rw-r--r--tests/auto/webchannel/tst_webchannel.h1
11 files changed, 230 insertions, 119 deletions
diff --git a/src/imports/webchannel/plugins.qmltypes b/src/imports/webchannel/plugins.qmltypes
index 789f2b4..4d0155d 100644
--- a/src/imports/webchannel/plugins.qmltypes
+++ b/src/imports/webchannel/plugins.qmltypes
@@ -4,49 +4,21 @@ import QtQuick.tooling 1.1
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -notrelocatable QtWebChannel 1.0'
+// 'qmlplugindump -nonrelocatable QtWebChannel 1.0'
Module {
Component {
- name: "QWebChannel"
- prototype: "QObject"
- Property { name: "blockUpdates"; type: "bool" }
- Signal {
- name: "blockUpdatesChanged"
- Parameter { name: "block"; type: "bool" }
- }
- Method {
- name: "sendMessage"
- Parameter { name: "id"; type: "QJsonValue" }
- Parameter { name: "data"; type: "QJsonValue" }
- }
- Method {
- name: "sendMessage"
- Parameter { name: "id"; type: "QJsonValue" }
- }
- Method {
- name: "registerObject"
- Parameter { name: "id"; type: "string" }
- Parameter { name: "object"; type: "QObject"; isPointer: true }
- }
- Method {
- name: "deregisterObject"
- Parameter { name: "object"; type: "QObject"; isPointer: true }
- }
- }
- Component {
- name: "QmlWebChannel"
+ name: "QQmlWebChannel"
prototype: "QWebChannel"
exports: ["QtWebChannel/WebChannel 1.0"]
exportMetaObjectRevisions: [0]
- attachedType: "QmlWebChannelAttached"
+ attachedType: "QQmlWebChannelAttached"
Property { name: "transports"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "registeredObjects"; type: "QObject"; isList: true; isReadonly: true }
Method {
name: "registerObjects"
Parameter { name: "objects"; type: "QVariantMap" }
}
- Method { name: "test_clientIsIdle"; type: "bool" }
Method {
name: "connectTo"
Parameter { name: "transport"; type: "QObject"; isPointer: true }
@@ -57,7 +29,7 @@ Module {
}
}
Component {
- name: "QmlWebChannelAttached"
+ name: "QQmlWebChannelAttached"
prototype: "QObject"
Property { name: "id"; type: "string" }
Signal {
@@ -65,4 +37,30 @@ Module {
Parameter { name: "id"; type: "string" }
}
}
+ Component {
+ name: "QWebChannel"
+ prototype: "QObject"
+ Property { name: "blockUpdates"; type: "bool" }
+ Signal {
+ name: "blockUpdatesChanged"
+ Parameter { name: "block"; type: "bool" }
+ }
+ Method {
+ name: "connectTo"
+ Parameter { name: "transport"; type: "QWebChannelAbstractTransport"; isPointer: true }
+ }
+ Method {
+ name: "disconnectFrom"
+ Parameter { name: "transport"; type: "QWebChannelAbstractTransport"; isPointer: true }
+ }
+ Method {
+ name: "registerObject"
+ Parameter { name: "id"; type: "string" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "deregisterObject"
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ }
}
diff --git a/src/imports/webchannel/webchannel.pro b/src/imports/webchannel/webchannel.pro
index 8ae6ef5..4c8d322 100644
--- a/src/imports/webchannel/webchannel.pro
+++ b/src/imports/webchannel/webchannel.pro
@@ -3,6 +3,8 @@ QT = core quick webchannel-private
INCLUDEPATH += ../../webchannel
VPATH += ../../webchannel
+IMPORT_VERSION = 1.0
+
SOURCES += \
plugin.cpp
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp
index c476011..0c22798 100644
--- a/src/webchannel/qmetaobjectpublisher.cpp
+++ b/src/webchannel/qmetaobjectpublisher.cpp
@@ -104,15 +104,18 @@ QMetaObjectPublisher::~QMetaObjectPublisher()
void QMetaObjectPublisher::registerObject(const QString &id, QObject *object)
{
- if (propertyUpdatesInitialized) {
- qWarning("Registered new object after initialization. This does not work!");
- return;
- }
registeredObjects[id] = object;
registeredObjectIds[object] = id;
+ if (propertyUpdatesInitialized) {
+ if (!webChannel->d_func()->transports.isEmpty()) {
+ qWarning("Registered new object after initialization, existing clients won't be notified!");
+ // TODO: send a message to clients that an object was added
+ }
+ initializePropertyUpdates(object, classInfoForObject(object, Q_NULLPTR));
+ }
}
-QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object) const
+QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object, QWebChannelAbstractTransport *transport)
{
QJsonObject data;
if (!object) {
@@ -160,7 +163,7 @@ QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object) cons
prop.name(), object->metaObject()->className());
}
propertyInfo.append(signalInfo);
- propertyInfo.append(QJsonValue::fromVariant(prop.read(object)));
+ propertyInfo.append(wrapResult(prop.read(object), transport));
qtProperties.append(propertyInfo);
}
for (int i = 0; i < metaObject->methodCount(); ++i) {
@@ -217,13 +220,13 @@ void QMetaObjectPublisher::setClientIsIdle(bool isIdle)
}
}
-QJsonObject QMetaObjectPublisher::initializeClient()
+QJsonObject QMetaObjectPublisher::initializeClient(QWebChannelAbstractTransport *transport)
{
QJsonObject objectInfos;
{
const QHash<QString, QObject *>::const_iterator end = registeredObjects.constEnd();
for (QHash<QString, QObject *>::const_iterator it = registeredObjects.constBegin(); it != end; ++it) {
- const QJsonObject &info = classInfoForObject(it.value());
+ const QJsonObject &info = classInfoForObject(it.value(), transport);
if (!propertyUpdatesInitialized) {
initializePropertyUpdates(it.value(), info);
}
@@ -280,6 +283,7 @@ void QMetaObjectPublisher::sendPendingPropertyUpdates()
for (PendingPropertyUpdates::const_iterator it = pendingPropertyUpdates.constBegin(); it != end; ++it) {
const QObject *object = it.key();
const QMetaObject *const metaObject = object->metaObject();
+ const QString objectId = registeredObjectIds.value(object);
const SignalToPropertyNameMap &objectsSignalToPropertyMap = signalToPropertyMap.value(object);
// maps property name to current property value
QJsonObject properties;
@@ -291,12 +295,11 @@ void QMetaObjectPublisher::sendPendingPropertyUpdates()
foreach (const int propertyIndex, objectsSignalToPropertyMap.value(sigIt.key())) {
const QMetaProperty &property = metaObject->property(propertyIndex);
Q_ASSERT(property.isValid());
- properties[QString::number(propertyIndex)] = QJsonValue::fromVariant(property.read(object));
+ properties[QString::number(propertyIndex)] = wrapResult(property.read(object), Q_NULLPTR, objectId);
}
sigs[QString::number(sigIt.key())] = QJsonArray::fromVariantList(sigIt.value());
}
QJsonObject obj;
- const QString objectId = registeredObjectIds.value(object);
obj[KEY_OBJECT] = objectId;
obj[KEY_SIGNALS] = sigs;
obj[KEY_PROPERTIES] = properties;
@@ -400,9 +403,7 @@ void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signal
message[KEY_OBJECT] = objectName;
message[KEY_SIGNAL] = signalIndex;
if (!arguments.isEmpty()) {
- // TODO: wrap (new) objects on the fly
- QJsonArray args = QJsonArray::fromVariantList(arguments);
- message[KEY_ARGS] = args;
+ message[KEY_ARGS] = wrapList(arguments, Q_NULLPTR, objectName);
}
message[KEY_TYPE] = TypeSignal;
@@ -435,52 +436,77 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object)
Q_ASSERT(removed);
Q_UNUSED(removed);
+ signalHandler.remove(object);
signalToPropertyMap.remove(object);
pendingPropertyUpdates.remove(object);
}
-QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelAbstractTransport *transport)
+// NOTE: transport can be a nullptr
+// in such a case, we need to ensure that the property is registered to
+// the target transports of the parentObjectId
+QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelAbstractTransport *transport,
+ const QString &parentObjectId)
{
if (QObject *object = result.value<QObject *>()) {
QString id = registeredObjectIds.value(object);
-
- QJsonObject objectInfo;
-
- if (!id.isEmpty() && wrappedObjects.contains(id)) {
- Q_ASSERT(object == wrappedObjects.value(id).object);
- // check if this transport is already assigned to the object
- if (!wrappedObjects.value(id).transports.contains(transport))
- wrappedObjects[id].transports.append(transport);
- return wrappedObjects.value(id).classinfo;
- } else {
+ QJsonObject classInfo;
+ if (id.isEmpty()) {
+ // neither registered, nor wrapped, do so now
id = QUuid::createUuid().toString();
+ Q_ASSERT(!registeredObjects.contains(id));
- QJsonObject info = classInfoForObject(object);
- objectInfo[KEY_QOBJECT] = true;
- objectInfo[KEY_ID] = id;
- objectInfo[KEY_DATA] = info;
+ classInfo = classInfoForObject(object, transport);
- if (!registeredObjects.contains(id)) {
- registeredObjectIds[object] = id;
- ObjectInfo oi(object, objectInfo);
- oi.transports.append(transport);
- wrappedObjects.insert(id, oi);
+ registeredObjectIds[object] = id;
- initializePropertyUpdates(object, info);
+ ObjectInfo oi(object, classInfo);
+ if (transport) {
+ oi.transports.append(transport);
+ } else {
+ // use the transports from the parent object
+ oi.transports = wrappedObjects.value(parentObjectId).transports;
+ // or fallback to all transports if the parent is not wrapped
+ if (oi.transports.isEmpty())
+ oi.transports = webChannel->d_func()->transports;
}
+ wrappedObjects.insert(id, oi);
+
+ initializePropertyUpdates(object, classInfo);
+ } else if (wrappedObjects.contains(id)) {
+ Q_ASSERT(object == wrappedObjects.value(id).object);
+ // check if this transport is already assigned to the object
+ if (transport && !wrappedObjects.value(id).transports.contains(transport))
+ wrappedObjects[id].transports.append(transport);
+ classInfo = wrappedObjects.value(id).classinfo;
}
+
+ QJsonObject objectInfo;
+ objectInfo[KEY_QOBJECT] = true;
+ objectInfo[KEY_ID] = id;
+ if (!classInfo.isEmpty())
+ objectInfo[KEY_DATA] = classInfo;
return objectInfo;
+ } else if (result.canConvert<QJSValue>()) {
+ // Workaround for keeping QJSValues from QVariant.
+ // Calling QJSValue::toVariant() converts JS-objects/arrays to QVariantMap/List
+ // instead of stashing a QJSValue itself into a variant.
+ // TODO: Improve QJSValue-QJsonValue conversion in Qt.
+ return wrapResult(result.value<QJSValue>().toVariant(), transport, parentObjectId);
+ } else if (result.canConvert<QVariantList>()) {
+ // recurse and potentially wrap contents of the array
+ return wrapList(result.toList(), transport);
}
- // Workaround for keeping QJSValues from QVariant.
- // Calling QJSValue::toVariant() converts JS-objects/arrays to QVariantMap/List
- // instead of stashing a QJSValue itself into a variant.
- // TODO: Improve QJSValue-QJsonValue conversion in Qt.
- QVariant jsvVariant = result;
- if (result.canConvert<QJSValue>())
- jsvVariant = result.value<QJSValue>().toVariant();
+ return QJsonValue::fromVariant(result);
+}
- return QJsonValue::fromVariant(jsvVariant);
+QJsonArray QMetaObjectPublisher::wrapList(const QVariantList &list, QWebChannelAbstractTransport *transport, const QString &parentObjectId)
+{
+ QJsonArray array;
+ foreach (const QVariant &arg, list) {
+ array.append(wrapResult(arg, transport, parentObjectId));
+ }
+ return array;
}
void QMetaObjectPublisher::deleteWrappedObject(QObject *object) const
@@ -525,7 +551,7 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel
QJsonDocument(message).toJson().constData());
return;
}
- transport->sendMessage(createResponse(message.value(KEY_ID), initializeClient()));
+ transport->sendMessage(createResponse(message.value(KEY_ID), initializeClient(transport)));
} else if (type == TypeDebug) {
static QTextStream out(stdout);
out << "DEBUG: " << message.value(KEY_DATA).toString() << endl;
diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h
index 1d269f1..359135c 100644
--- a/src/webchannel/qmetaobjectpublisher_p.h
+++ b/src/webchannel/qmetaobjectpublisher_p.h
@@ -95,7 +95,7 @@ public:
/**
* Serialize the QMetaObject of @p object and return it in JSON form.
*/
- QJsonObject classInfoForObject(const QObject *object) const;
+ QJsonObject classInfoForObject(const QObject *object, QWebChannelAbstractTransport *transport);
/**
* Set the client to idle or busy, based on the value of @p isIdle.
@@ -109,7 +109,7 @@ public:
*
* Furthermore, if that was not done already, connect to their property notify signals.
*/
- QJsonObject initializeClient();
+ QJsonObject initializeClient(QWebChannelAbstractTransport *transport);
/**
* Go through all properties of the given object and connect to their notify signal.
@@ -155,10 +155,17 @@ public:
* return the objects class information.
*
* All other input types are returned as-is.
+ */
+ QJsonValue wrapResult(const QVariant &result, QWebChannelAbstractTransport *transport,
+ const QString &parentObjectId = QString());
+
+ /**
+ * Convert a list of variant values for consumption by the client.
*
- * TODO: support wrapping of initially-registered objects
+ * This properly handles QML values and also wraps the result if required.
*/
- QJsonValue wrapResult(const QVariant &result, QWebChannelAbstractTransport *transport);
+ QJsonArray wrapList(const QVariantList &list, QWebChannelAbstractTransport *transport,
+ const QString &parentObjectId = QString());
/**
* Invoke delete later on @p object.
diff --git a/src/webchannel/qwebchannel.js b/src/webchannel/qwebchannel.js
index 13e9da5..4a1c784 100644
--- a/src/webchannel/qwebchannel.js
+++ b/src/webchannel/qwebchannel.js
@@ -155,6 +155,10 @@ var QWebChannel = function(transport, initCallback)
for (var objectName in data) {
var object = new QObject(objectName, data[objectName], channel);
}
+ // now unwrap properties, which might reference other registered objects
+ for (var objectName in channel.objects) {
+ channel.objects[objectName].unwrapProperties();
+ }
if (initCallback) {
initCallback(channel);
}
@@ -177,18 +181,31 @@ function QObject(name, data, webChannel)
// ----------------------------------------------------------------------
- function unwrapQObject( response )
+ this.unwrapQObject = function(response)
{
+ if (response instanceof Array) {
+ // support list of objects
+ var ret = new Array(response.length);
+ for (var i = 0; i < response.length; ++i) {
+ ret[i] = object.unwrapQObject(response[i]);
+ }
+ return ret;
+ }
if (!response
|| !response["__QObject*__"]
- || response["id"] === undefined
- || response["data"] === undefined) {
+ || response["id"] === undefined) {
return response;
}
+
var objectId = response.id;
if (webChannel.objects[objectId])
return webChannel.objects[objectId];
+ if (!response.data) {
+ console.error("Cannot unwrap unknown QObject " + objectId + " without data.");
+ return;
+ }
+
var qObject = new QObject( objectId, response.data, webChannel );
qObject.destroyed.connect(function() {
if (webChannel.objects[objectId] === qObject) {
@@ -206,9 +223,18 @@ function QObject(name, data, webChannel)
}
}
});
+ // here we are already initialized, and thus must directly unwrap the properties
+ qObject.unwrapProperties();
return qObject;
}
+ this.unwrapProperties = function()
+ {
+ for (var propertyIdx in object.__propertyCache__) {
+ object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]);
+ }
+ }
+
function addSignal(signalData, isPropertyNotifySignal)
{
var signalName = signalData[0];
@@ -311,7 +337,7 @@ function QObject(name, data, webChannel)
"args": args
}, function(response) {
if (response !== undefined) {
- var result = unwrapQObject(response);
+ var result = object.unwrapQObject(response);
if (callback) {
(callback)(result);
}
@@ -326,6 +352,8 @@ function QObject(name, data, webChannel)
var propertyName = propertyInfo[1];
var notifySignalData = propertyInfo[2];
// initialize property cache with current value
+ // NOTE: if this is an object, it is not directly unwrapped as it might
+ // reference other QObject that we do not know yet
object.__propertyCache__[propertyIndex] = propertyInfo[3];
if (notifySignalData) {
diff --git a/src/webchannel/signalhandler_p.h b/src/webchannel/signalhandler_p.h
index 2560cdb..03fbca9 100644
--- a/src/webchannel/signalhandler_p.h
+++ b/src/webchannel/signalhandler_p.h
@@ -84,6 +84,11 @@ public:
*/
void clear();
+ /**
+ * Fully remove and disconnect an object from handler
+ */
+ void remove(const QObject *object);
+
private:
/**
* Exctract the arguments of a signal call and pass them to the receiver.
@@ -252,15 +257,6 @@ int SignalHandler<Receiver>::qt_metacall(QMetaObject::Call call, int methodId, v
dispatch(object, methodId, args);
- if (methodId == s_destroyedSignalIndex) {
- // disconnect on QObject::destroyed
- ConnectionHash::iterator it = m_connectionsCounter.find(object);
- Q_ASSERT(it != m_connectionsCounter.end());
- foreach (const ConnectionPair &connection, *it) {
- QObject::disconnect(connection.first);
- }
- m_connectionsCounter.erase(it);
- }
return -1;
}
return methodId;
@@ -280,6 +276,17 @@ void SignalHandler<Receiver>::clear()
m_signalArgumentTypes[&QObject::staticMetaObject] = keep;
}
+template<class Receiver>
+void SignalHandler<Receiver>::remove(const QObject *object)
+{
+ Q_ASSERT(m_connectionsCounter.contains(object));
+ const SignalConnectionHash &connections = m_connectionsCounter.value(object);
+ foreach (const ConnectionPair &connection, connections) {
+ QObject::disconnect(connection.first);
+ }
+ m_connectionsCounter.remove(object);
+}
+
QT_END_NAMESPACE
#endif // SIGNALHANDLER_H
diff --git a/tests/auto/qml/tst_multiclient.qml b/tests/auto/qml/tst_multiclient.qml
index 115857d..4977e50 100644
--- a/tests/auto/qml/tst_multiclient.qml
+++ b/tests/auto/qml/tst_multiclient.qml
@@ -87,14 +87,14 @@ TestCase {
WebChannel.id: "myOtherObj"
}
+ property var lastFactoryObj
+ property var createdFactoryObjects: []
QtObject {
id: myFactory
- property var lastObj
- property var createdObjects: []
function cleanup() {
- while (createdObjects.length) {
- var obj = createdObjects.shift();
+ while (createdFactoryObjects.length) {
+ var obj = createdFactoryObjects.shift();
if (obj) {
obj.destroy();
}
@@ -103,9 +103,9 @@ TestCase {
function create(id)
{
- lastObj = component.createObject(myFactory, {objectName: id});
- createdObjects.push(lastObj);
- return lastObj;
+ lastFactoryObj = component.createObject(myFactory, {objectName: id});
+ createdFactoryObjects.push(lastFactoryObj);
+ return lastFactoryObj;
}
WebChannel.id: "myFactory"
}
@@ -139,7 +139,8 @@ TestCase {
client2.debug = false;
// delete all created objects
myFactory.cleanup();
- myFactory.lastObj = undefined;
+ lastFactoryObj = undefined;
+ createdFactoryObjects = [];
// reschedule current task to end of event loop
wait(1);
}
@@ -180,7 +181,7 @@ TestCase {
var channel1 = client1.createChannel(function (channel1) {
channel1.objects.myFactory.create("testObj1", function (obj1) {
- testObj1 = myFactory.lastObj;
+ testObj1 = lastFactoryObj;
testObj1Id = obj1.__id__;
// create second channel after factory has created first
@@ -227,7 +228,7 @@ TestCase {
channel2 = client2.createChannel(function (channel2) {
channel2.objects.myFactory.create("testObj2", function (obj2) {
- testObj2 = myFactory.lastObj;
+ testObj2 = lastFactoryObj;
testObj2Id = obj2.__id__;
});
});
diff --git a/tests/auto/qml/tst_webchannel.qml b/tests/auto/qml/tst_webchannel.qml
index f41c4fa..3bfbfc9 100644
--- a/tests/auto/qml/tst_webchannel.qml
+++ b/tests/auto/qml/tst_webchannel.qml
@@ -67,6 +67,8 @@ TestCase {
WebChannel.id: "myOtherObj"
}
property var lastFactoryObj
+ QtObject{ id: bar; objectName: "bar" }
+ QtObject{ id: baz; objectName: "baz" }
QtObject {
id: myFactory
function create(id)
@@ -74,9 +76,13 @@ TestCase {
lastFactoryObj = component.createObject(myFactory, {objectName: id});
return lastFactoryObj;
}
+ property var objectInProperty: QtObject {
+ objectName: "foo"
+ }
+ property var otherObject: myObj
+ property var objects: [ bar, baz ];
WebChannel.id: "myFactory"
}
-
Component {
id: component
QtObject {
@@ -276,6 +282,15 @@ TestCase {
lastFactoryObj.mySignal("foobar", 42);
client.awaitSignal();
+ // property should be wrapped
+ compare(channel.objects.myFactory.objectInProperty.objectName, "foo");
+ // list property as well
+ compare(channel.objects.myFactory.objects.length, 2);
+ compare(channel.objects.myFactory.objects[0].objectName, "bar");
+ compare(channel.objects.myFactory.objects[1].objectName, "baz");
+ // also works with properties that reference other registered objects
+ compare(channel.objects.myFactory.otherObject, channel.objects.myObj);
+
// deleteLater call
msg = client.awaitMessage();
compare(msg.type, JSClient.QWebChannelMessageTypes.invokeMethod);
diff --git a/tests/auto/qml/tst_webchannelseparation.qml b/tests/auto/qml/tst_webchannelseparation.qml
index 289f8b2..8a74243 100644
--- a/tests/auto/qml/tst_webchannelseparation.qml
+++ b/tests/auto/qml/tst_webchannelseparation.qml
@@ -91,15 +91,16 @@ TestCase {
}
WebChannel.id: "myObj3"
}
+
+ property var lastFactoryObj
+ property var createdFactoryObjects: []
QtObject {
id: myFactory
- property var lastObj
- property var createdObjects: []
function cleanup()
{
- while (createdObjects.length) {
- var obj = createdObjects.shift();
+ while (createdFactoryObjects.length) {
+ var obj = createdFactoryObjects.shift();
if (obj) {
obj.destroy();
}
@@ -108,9 +109,9 @@ TestCase {
function create(id)
{
- lastObj = component.createObject(myFactory, {objectName: id});
- createdObjects.push(lastObj);
- return lastObj;
+ lastFactoryObj = component.createObject(myFactory, {objectName: id});
+ createdFactoryObjects.push(lastFactoryObj);
+ return lastFactoryObj;
}
WebChannel.id: "myFactory"
}
@@ -146,7 +147,8 @@ TestCase {
client2.debug = false;
// delete all created objects
myFactory.cleanup();
- myFactory.lastObj = undefined;
+ lastFactoryObj = undefined;
+ createdFactoryObjects = [];
// reschedule current task to end of event loop
wait(1);
}
@@ -160,7 +162,7 @@ TestCase {
var channel1 = client1.createChannel(function (channel1) {
channel1.objects.myFactory.create("testObj1", function (obj1) {
- testObj1 = myFactory.lastObj;
+ testObj1 = lastFactoryObj;
testObj1Id = obj1.__id__;
obj1.mySignal.connect(function (arg1_1, arg1_2) {
@@ -182,7 +184,7 @@ TestCase {
channel2 = client2.createChannel(function (channel2) {
channel2.objects.myFactory.create("testObj2", function (obj2) {
- testObj2 = myFactory.lastObj;
+ testObj2 = lastFactoryObj;
testObj2Id = obj2.__id__;
obj2.mySignal.connect(function (arg2_1, arg2_2) {
console.debug("client 2 received signal 'mySignal'");
@@ -278,7 +280,7 @@ TestCase {
var channel1 = client1.createChannel(function (channel1) {
channel1.objects.myFactory.create("testObj1", function (obj1) {
- testObj1 = myFactory.lastObj;
+ testObj1 = lastFactoryObj;
testObj1Id = obj1.__id__;
obj1.myPropertyChanged.connect(function (arg1_1) {
@@ -300,7 +302,7 @@ TestCase {
channel2 = client2.createChannel(function (channel2) {
channel2.objects.myFactory.create("testObj2", function (obj2) {
- testObj2 = myFactory.lastObj;
+ testObj2 = lastFactoryObj;
testObj2Id = obj2.__id__;
obj2.myPropertyChanged.connect(function (arg1_1) {
console.debug("client 2 received property update 'myProperty' " + obj2.myProperty);
diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp
index 5060028..3d77b42 100644
--- a/tests/auto/webchannel/tst_webchannel.cpp
+++ b/tests/auto/webchannel/tst_webchannel.cpp
@@ -83,13 +83,37 @@ void TestWebChannel::testRegisterObjects()
channel.registerObjects(objects);
}
+void TestWebChannel::testDeregisterObjects()
+{
+ QWebChannel channel;
+ TestObject testObject;
+ testObject.setObjectName("myTestObject");
+
+
+ channel.registerObject(testObject.objectName(), &testObject);
+
+ channel.connectTo(m_dummyTransport);
+ channel.d_func()->publisher->initializeClient(m_dummyTransport);
+
+ QJsonObject connectMessage =
+ QJsonDocument::fromJson(("{\"type\": 7,"
+ "\"object\": \"myTestObject\","
+ "\"signal\": " + QString::number(testObject.metaObject()->indexOfSignal("sig1()"))
+ + "}").toLatin1()).object();
+ channel.d_func()->publisher->handleMessage(connectMessage, m_dummyTransport);
+
+ emit testObject.sig1();
+ channel.deregisterObject(&testObject);
+ emit testObject.sig1();
+}
+
void TestWebChannel::testInfoForObject()
{
TestObject obj;
obj.setObjectName("myTestObject");
QWebChannel channel;
- const QJsonObject info = channel.d_func()->publisher->classInfoForObject(&obj);
+ const QJsonObject info = channel.d_func()->publisher->classInfoForObject(&obj, m_dummyTransport);
QCOMPARE(info.keys(), QStringList() << "enums" << "methods" << "properties" << "signals");
@@ -267,7 +291,7 @@ void TestWebChannel::benchClassInfo()
QBENCHMARK {
foreach (const QObject *object, objects) {
- channel.d_func()->publisher->classInfoForObject(object);
+ channel.d_func()->publisher->classInfoForObject(object, m_dummyTransport);
}
}
}
@@ -282,7 +306,7 @@ void TestWebChannel::benchInitializeClients()
QMetaObjectPublisher *publisher = channel.d_func()->publisher;
QBENCHMARK {
- publisher->initializeClient();
+ publisher->initializeClient(m_dummyTransport);
publisher->propertyUpdatesInitialized = false;
publisher->signalToPropertyMap.clear();
@@ -304,7 +328,7 @@ void TestWebChannel::benchPropertyUpdates()
}
channel.registerObjects(objects);
- channel.d_func()->publisher->initializeClient();
+ channel.d_func()->publisher->initializeClient(m_dummyTransport);
QBENCHMARK {
foreach (BenchObject *obj, objectList) {
diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h
index ad8c6a4..6564944 100644
--- a/tests/auto/webchannel/tst_webchannel.h
+++ b/tests/auto/webchannel/tst_webchannel.h
@@ -214,6 +214,7 @@ public:
private slots:
void testRegisterObjects();
+ void testDeregisterObjects();
void testInfoForObject();
void testInvokeMethodConversion();
void testDisconnect();