From 0a43a43a166d2e2b551f543de61090637bd8b387 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 30 Jul 2014 12:20:08 +0200 Subject: Do not broadcast initialization data to all clients. Instead, send the data as a response to the initialization request message. This simplifies the code and makes it more predictable, as we do not spam all clients with initialization broadcasts anymore. Note that the pending initialization "feature" is removed, but I don't see a need for it anymore. If you want to delay client initialization, do it on the client side. Change-Id: I1ab71fd6c9e809ccb6085f1a3fbac3eb9b2e910b Reviewed-by: Jocelyn Turcotte --- src/webchannel/qmetaobjectpublisher.cpp | 45 ++++++++++++++------------------ src/webchannel/qmetaobjectpublisher_p.h | 6 +---- src/webchannel/qwebchannel.js | 29 ++++++-------------- tests/auto/webchannel/tst_webchannel.cpp | 4 +-- 4 files changed, 31 insertions(+), 53 deletions(-) diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index eeab014..527b3df 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -73,6 +73,15 @@ const QString KEY_ARGS = QStringLiteral("args"); const QString KEY_PROPERTY = QStringLiteral("property"); const QString KEY_VALUE = QStringLiteral("value"); +QJsonObject createResponse(const QJsonValue &id, const QJsonValue &data) +{ + QJsonObject response; + response[KEY_TYPE] = TypeResponse; + response[KEY_ID] = id; + response[KEY_DATA] = data; + return response; +} + /// TODO: what is the proper value here? const int PROPERTY_UPDATE_INTERVAL = 50; } @@ -83,7 +92,6 @@ QMetaObjectPublisher::QMetaObjectPublisher(QWebChannel *webChannel) , signalHandler(this) , clientIsIdle(false) , blockUpdates(false) - , pendingInit(false) , propertyUpdatesInitialized(false) { } @@ -208,12 +216,8 @@ void QMetaObjectPublisher::setClientIsIdle(bool isIdle) } } -void QMetaObjectPublisher::initializeClients() +QJsonObject QMetaObjectPublisher::initializeClient() { - if (!webChannel) { - return; - } - QJsonObject objectInfos; { const QHash::const_iterator end = registeredObjects.constEnd(); @@ -225,12 +229,8 @@ void QMetaObjectPublisher::initializeClients() objectInfos[it.key()] = info; } } - QJsonObject message; - message[KEY_TYPE] = TypeInit; - message[KEY_DATA] = objectInfos; - broadcastMessage(message); propertyUpdatesInitialized = true; - pendingInit = false; + return objectInfos; } void QMetaObjectPublisher::initializePropertyUpdates(const QObject *const object, const QJsonObject &objectInfo) @@ -474,11 +474,12 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel if (type == TypeIdle) { setClientIsIdle(true); } else if (type == TypeInit) { - if (!blockUpdates) { - initializeClients(); - } else { - pendingInit = true; + if (!message.contains(KEY_ID)) { + qWarning("JSON message object is missing the id property: %s", + QJsonDocument(message).toJson().constData()); + return; } + transport->sendMessage(createResponse(message.value(KEY_ID), initializeClient())); } else if (type == TypeDebug) { static QTextStream out(stdout); out << "DEBUG: " << message.value(KEY_DATA).toString() << endl; @@ -496,11 +497,9 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel QJsonDocument(message).toJson().constData()); return; } - QJsonObject response; - response[KEY_TYPE] = TypeResponse; - response[KEY_ID] = message.value(KEY_ID); - response[KEY_DATA] = invokeMethod(object, message.value(KEY_METHOD).toInt(-1), message.value(KEY_ARGS).toArray()); - transport->sendMessage(response); + transport->sendMessage(createResponse(message.value(KEY_ID), + invokeMethod(object, message.value(KEY_METHOD).toInt(-1), + message.value(KEY_ARGS).toArray()))); } else if (type == TypeConnectToSignal) { signalHandler.connectTo(object, message.value(KEY_SIGNAL).toInt(-1)); } else if (type == TypeDisconnectFromSignal) { @@ -526,11 +525,7 @@ void QMetaObjectPublisher::setBlockUpdates(bool block) blockUpdates = block; if (!blockUpdates) { - if (pendingInit) { - initializeClients(); - } else { - sendPendingPropertyUpdates(); - } + sendPendingPropertyUpdates(); } else if (timer.isActive()) { timer.stop(); } diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index a7cdda7..eda17d9 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -108,7 +108,7 @@ public: * * Furthermore, if that was not done already, connect to their property notify signals. */ - void initializeClients(); + QJsonObject initializeClient(); /** * Go through all properties of the given object and connect to their notify signal. @@ -195,10 +195,6 @@ private: // true when no property updates should be sent, false otherwise bool blockUpdates; - // true when at least one client needs to be initialized, - // i.e. when a Qt.init came in which was not handled yet. - bool pendingInit; - // true when at least one client was initialized and thus // the property updates have been initialized and the // object info map set. diff --git a/src/webchannel/qwebchannel.js b/src/webchannel/qwebchannel.js index d2c6525..13e9da5 100644 --- a/src/webchannel/qwebchannel.js +++ b/src/webchannel/qwebchannel.js @@ -82,9 +82,6 @@ var QWebChannel = function(transport, initCallback) case QWebChannelMessageTypes.propertyUpdate: channel.handlePropertyUpdate(data); break; - case QWebChannelMessageTypes.init: - channel.handleInit(data); - break; default: console.error("invalid message received:", message.data); break; @@ -149,30 +146,20 @@ var QWebChannel = function(transport, initCallback) channel.exec({type: QWebChannelMessageTypes.idle}); } - // prevent multiple initialization which might happen with multiple webchannel clients. - this.initialized = false; - this.handleInit = function(message) + this.debug = function(message) { - if (channel.initialized) { - return; - } - channel.initialized = true; - for (var objectName in message.data) { - var data = message.data[objectName]; - var object = new QObject(objectName, data, channel); + channel.send({type: QWebChannelMessageTypes.debug, data: message}); + }; + + channel.exec({type: QWebChannelMessageTypes.init}, function(data) { + for (var objectName in data) { + var object = new QObject(objectName, data[objectName], channel); } if (initCallback) { initCallback(channel); } channel.exec({type: QWebChannelMessageTypes.idle}); - } - - this.debug = function(message) - { - channel.send({type: QWebChannelMessageTypes.debug, data: message}); - }; - - channel.exec({type: QWebChannelMessageTypes.init}); + }); }; function QObject(name, data, webChannel) diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp index 4827ea7..5060028 100644 --- a/tests/auto/webchannel/tst_webchannel.cpp +++ b/tests/auto/webchannel/tst_webchannel.cpp @@ -282,7 +282,7 @@ void TestWebChannel::benchInitializeClients() QMetaObjectPublisher *publisher = channel.d_func()->publisher; QBENCHMARK { - publisher->initializeClients(); + publisher->initializeClient(); publisher->propertyUpdatesInitialized = false; publisher->signalToPropertyMap.clear(); @@ -304,7 +304,7 @@ void TestWebChannel::benchPropertyUpdates() } channel.registerObjects(objects); - channel.d_func()->publisher->initializeClients(); + channel.d_func()->publisher->initializeClient(); QBENCHMARK { foreach (BenchObject *obj, objectList) { -- cgit v1.2.1