diff options
Diffstat (limited to 'src/webchannel')
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 140 | ||||
-rw-r--r-- | src/webchannel/qmetaobjectpublisher_p.h | 33 | ||||
-rw-r--r-- | src/webchannel/qqmlwebchannel.h | 4 | ||||
-rw-r--r-- | src/webchannel/qwebchannel.cpp | 31 | ||||
-rw-r--r-- | src/webchannel/qwebchannel.h | 2 | ||||
-rw-r--r-- | src/webchannel/qwebchannel.js | 218 | ||||
-rw-r--r-- | src/webchannel/qwebchannel_p.h | 2 | ||||
-rw-r--r-- | src/webchannel/qwebchannelabstracttransport.h | 5 |
8 files changed, 198 insertions, 237 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index 646398d..d9aa548 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -59,30 +59,11 @@ QT_BEGIN_NAMESPACE namespace { -// NOTE: keep in sync with corresponding maps in qwebchannel.js and WebChannelTest.qml -enum Type { - TypeInvalid = 0, - - TYPES_FIRST_VALUE = 1, - - TypeSignal = 1, - TypePropertyUpdate = 2, - TypeInit = 3, - TypeIdle = 4, - TypeDebug = 5, - TypeInvokeMethod = 6, - TypeConnectToSignal = 7, - TypeDisconnectFromSignal = 8, - TypeSetProperty = 9, - - TYPES_LAST_VALUE = 9 -}; - -Type toType(const QJsonValue &value) +MessageType toType(const QJsonValue &value) { int i = value.toInt(-1); if (i >= TYPES_FIRST_VALUE && i <= TYPES_LAST_VALUE) { - return static_cast<Type>(i); + return static_cast<MessageType>(i); } else { return TypeInvalid; } @@ -99,13 +80,11 @@ const QString KEY_OBJECT = QStringLiteral("object"); const QString KEY_DESTROYED = QStringLiteral("destroyed"); const QString KEY_SIGNAL = QStringLiteral("signal"); const QString KEY_TYPE = QStringLiteral("type"); -const QString KEY_MESSAGE = QStringLiteral("message"); const QString KEY_METHOD = QStringLiteral("method"); const QString KEY_ARGS = QStringLiteral("args"); const QString KEY_PROPERTY = QStringLiteral("property"); const QString KEY_VALUE = QStringLiteral("value"); - QString objectId(const QObject *object) { return QString::number(quintptr(object), 16); @@ -261,7 +240,10 @@ void QMetaObjectPublisher::initializeClients() objectInfos[it.key()] = info; } } - webChannel->sendMessage(TypeInit, objectInfos); + QJsonObject message; + message[KEY_TYPE] = TypeInit; + message[KEY_DATA] = objectInfos; + broadcastMessage(message); propertyUpdatesInitialized = true; pendingInit = false; } @@ -334,31 +316,34 @@ void QMetaObjectPublisher::sendPendingPropertyUpdates() } pendingPropertyUpdates.clear(); - webChannel->sendMessage(TypePropertyUpdate, data); + QJsonObject message; + message[KEY_TYPE] = TypePropertyUpdate; + message[KEY_DATA] = data; + broadcastMessage(message); setClientIsIdle(false); } -QByteArray QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodIndex, - const QJsonArray &args, const QJsonValue &id) +QJsonValue QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodIndex, + const QJsonArray &args) { const QMetaMethod &method = object->metaObject()->method(methodIndex); if (method.name() == QByteArrayLiteral("deleteLater")) { // invoke `deleteLater` on wrapped QObject indirectly deleteWrappedObject(object); - return QByteArray(); + return QJsonValue(); } else if (!method.isValid()) { qWarning() << "Cannot invoke unknown method of index" << methodIndex << "on object" << object << '.'; - return QByteArray(); + return QJsonValue(); } else if (method.access() != QMetaMethod::Public) { qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.'; - return QByteArray(); + return QJsonValue(); } else if (method.methodType() != QMetaMethod::Method && method.methodType() != QMetaMethod::Slot) { qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.'; - return QByteArray(); + return QJsonValue(); } else if (args.size() > 10) { qWarning() << "Cannot invoke method" << method.name() << "on object" << object << "with more than 10 arguments, as that is not supported by QMetaMethod::invoke."; - return QByteArray(); + return QJsonValue(); } else if (args.size() > method.parameterCount()) { qWarning() << "Ignoring additional arguments while invoking method" << method.name() << "on object" << object << ':' << args.size() << "arguments given, but method only takes" << method.parameterCount() << '.'; @@ -389,8 +374,7 @@ QByteArray QMetaObjectPublisher::invokeMethod(QObject *const object, const int m arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]); - // and send the return value to the client - return generateJSONMessage(id, wrapResult(returnValue), true); + return wrapResult(returnValue); } void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments) @@ -399,11 +383,11 @@ void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signal return; } if (!signalToPropertyMap.value(object).contains(signalIndex)) { - QJsonObject data; + QJsonObject message; const QString &objectName = registeredObjectIds.value(object); Q_ASSERT(!objectName.isEmpty()); - data[KEY_OBJECT] = objectName; - data[KEY_SIGNAL] = signalIndex; + message[KEY_OBJECT] = objectName; + message[KEY_SIGNAL] = signalIndex; if (!arguments.isEmpty()) { // TODO: wrap (new) objects on the fly QJsonArray args; @@ -419,9 +403,10 @@ void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signal #else args = QJsonArray::fromVariantList(arguments); #endif - data[KEY_ARGS] = args; + message[KEY_ARGS] = args; } - webChannel->sendMessage(TypeSignal, data); + message[KEY_TYPE] = TypeSignal; + broadcastMessage(message); if (signalIndex == s_destroyedSignalIndex) { objectDestroyed(object); @@ -486,78 +471,71 @@ void QMetaObjectPublisher::deleteWrappedObject(QObject *object) const object->deleteLater(); } -QByteArray QMetaObjectPublisher::handleRequest(const QJsonObject &message) +void QMetaObjectPublisher::broadcastMessage(const QJsonObject &message) const { - if (!message.contains(KEY_DATA)) { - return QByteArray(); + if (webChannel->d_func()->transports.isEmpty()) { + qWarning("QWebChannel is not connected to any transports, cannot send messages."); + return; + } + + foreach (QWebChannelAbstractTransport *transport, webChannel->d_func()->transports) { + transport->sendMessage(message); } +} - const QJsonObject &payload = message.value(KEY_DATA).toObject(); - if (!payload.contains(KEY_TYPE)) { - return QByteArray(); +void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannelAbstractTransport *transport) +{ + if (!message.contains(KEY_TYPE)) { + qWarning("JSON message object is missing the type property: %s", QJsonDocument(message).toJson().constData()); + return; } - const Type type = toType(payload.value(KEY_TYPE)); + const MessageType type = toType(message.value(KEY_TYPE)); if (type == TypeIdle) { setClientIsIdle(true); - return QByteArray(); } else if (type == TypeInit) { if (!blockUpdates) { initializeClients(); } else { pendingInit = true; } - return QByteArray(); } else if (type == TypeDebug) { static QTextStream out(stdout); - out << "DEBUG: " << payload.value(KEY_MESSAGE).toString() << endl; - return QByteArray(); - } else if (payload.contains(KEY_OBJECT)) { - const QString &objectName = payload.value(KEY_OBJECT).toString(); + out << "DEBUG: " << message.value(KEY_DATA).toString() << endl; + } else if (message.contains(KEY_OBJECT)) { + const QString &objectName = message.value(KEY_OBJECT).toString(); QObject *object = registeredObjects.value(objectName); if (!object) { qWarning() << "Unknown object encountered" << objectName; - return QByteArray(); + return; } if (type == TypeInvokeMethod) { - return invokeMethod(object, payload.value(KEY_METHOD).toInt(-1), payload.value(KEY_ARGS).toArray(), message.value(KEY_ID)); + if (!message.contains(KEY_ID)) { + qWarning("JSON message object is missing the id property: %s", + 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); } else if (type == TypeConnectToSignal) { - signalHandler.connectTo(object, payload.value(KEY_SIGNAL).toInt(-1)); - return QByteArray(); + signalHandler.connectTo(object, message.value(KEY_SIGNAL).toInt(-1)); } else if (type == TypeDisconnectFromSignal) { - signalHandler.disconnectFrom(object, payload.value(KEY_SIGNAL).toInt(-1)); - return QByteArray(); + signalHandler.disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1)); } else if (type == TypeSetProperty) { - const int propertyIdx = payload.value(KEY_PROPERTY).toInt(-1); + const int propertyIdx = message.value(KEY_PROPERTY).toInt(-1); QMetaProperty property = object->metaObject()->property(propertyIdx); if (!property.isValid()) { - qWarning() << "Cannot set unknown property" << payload.value(KEY_PROPERTY) << "of object" << objectName; - return QByteArray(); - } else if (!object->metaObject()->property(propertyIdx).write(object, payload.value(KEY_VALUE).toVariant())) { - qWarning() << "Could not write value " << payload.value(KEY_VALUE) + qWarning() << "Cannot set unknown property" << message.value(KEY_PROPERTY) << "of object" << objectName; + } else if (!object->metaObject()->property(propertyIdx).write(object, message.value(KEY_VALUE).toVariant())) { + qWarning() << "Could not write value " << message.value(KEY_VALUE) << "to property" << property.name() << "of object" << objectName; - return QByteArray(); } - return QByteArray(); } } - return QByteArray(); -} - -void QMetaObjectPublisher::handleMessage(const QString &message) -{ - QWebChannelAbstractTransport *transport = qobject_cast<QWebChannelAbstractTransport*>(sender()); - Q_ASSERT(transport); - - const QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8()); - if (!doc.isObject()) { - return; - } - const QByteArray &response = handleRequest(doc.object()); - if (!response.isEmpty()) { - transport->sendTextMessage(QString::fromUtf8(response)); - } } void QMetaObjectPublisher::setBlockUpdates(bool block) diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index 4da0c26..82afe57 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -54,7 +54,28 @@ QT_BEGIN_NAMESPACE +// NOTE: keep in sync with corresponding maps in qwebchannel.js and WebChannelTest.qml +enum MessageType { + TypeInvalid = 0, + + TYPES_FIRST_VALUE = 1, + + TypeSignal = 1, + TypePropertyUpdate = 2, + TypeInit = 3, + TypeIdle = 4, + TypeDebug = 5, + TypeInvokeMethod = 6, + TypeConnectToSignal = 7, + TypeDisconnectFromSignal = 8, + TypeSetProperty = 9, + TypeResponse = 10, + + TYPES_LAST_VALUE = 10 +}; + class QWebChannel; +class QWebChannelAbstractTransport; class Q_WEBCHANNEL_EXPORT QMetaObjectPublisher : public QObject { Q_OBJECT @@ -75,11 +96,9 @@ public: void registerObject(const QString &id, QObject *object); /** - * Handle the given WebChannel client request and potentially give a response. - * - * @return true if the request was handled, false otherwise. + * Send the given message to all known transports. */ - QByteArray handleRequest(const QJsonObject &message); + void broadcastMessage(const QJsonObject &message) const; /** * Serialize the QMetaObject of @p object and return it in JSON form. @@ -125,7 +144,7 @@ public: * The return value of the method invocation is then serialized and a response message * is returned. */ - QByteArray invokeMethod(QObject *const object, const int methodIndex, const QJsonArray &args, const QJsonValue &id); + QJsonValue invokeMethod(QObject *const object, const int methodIndex, const QJsonArray &args); /** * Callback of the signalHandler which forwards the signal invocation to the webchannel clients. @@ -164,9 +183,9 @@ Q_SIGNALS: public Q_SLOTS: /** - * Parse the message as JSON and if it succeeds, call handleRequest with the obtained JSON object. + * Handle the @p message and if needed send a response to @p transport. */ - void handleMessage(const QString &message); + void handleMessage(const QJsonObject &message, QWebChannelAbstractTransport *transport); protected: void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE; diff --git a/src/webchannel/qqmlwebchannel.h b/src/webchannel/qqmlwebchannel.h index 3bbd2a0..96ffdd3 100644 --- a/src/webchannel/qqmlwebchannel.h +++ b/src/webchannel/qqmlwebchannel.h @@ -89,9 +89,9 @@ private: static void transports_clear(QQmlListProperty<QObject> *prop); }; +QT_END_NAMESPACE + QML_DECLARE_TYPE( QQmlWebChannel ) QML_DECLARE_TYPEINFO( QQmlWebChannel, QML_HAS_ATTACHED_PROPERTIES ) -QT_END_NAMESPACE - #endif // QQMLWEBCHANNEL_H diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp index d0b968e..3aebb14 100644 --- a/src/webchannel/qwebchannel.cpp +++ b/src/webchannel/qwebchannel.cpp @@ -50,20 +50,6 @@ QT_BEGIN_NAMESPACE -QByteArray generateJSONMessage(const QJsonValue &id, const QJsonValue &data, bool response) -{ - QJsonObject obj; - if (response) { - obj[QStringLiteral("response")] = true; - } - obj[QStringLiteral("id")] = id; - if (!data.isNull()) { - obj[QStringLiteral("data")] = data; - } - QJsonDocument doc(obj); - return doc.toJson(QJsonDocument::Compact); -} - void QWebChannelPrivate::_q_transportDestroyed(QObject *object) { const int idx = transports.indexOf(static_cast<QWebChannelAbstractTransport*>(object)); @@ -144,7 +130,7 @@ void QWebChannel::connectTo(QWebChannelAbstractTransport *transport) Q_ASSERT(transport); if (!d->transports.contains(transport)) { d->transports << transport; - connect(transport, &QWebChannelAbstractTransport::textMessageReceived, + connect(transport, &QWebChannelAbstractTransport::messageReceived, d->publisher, &QMetaObjectPublisher::handleMessage, Qt::UniqueConnection); connect(transport, SIGNAL(destroyed(QObject*)), @@ -162,21 +148,6 @@ void QWebChannel::disconnectFrom(QWebChannelAbstractTransport *transport) } } -void QWebChannel::sendMessage(const QJsonValue &id, const QJsonValue &data) const -{ - Q_D(const QWebChannel); - if (d->transports.isEmpty()) { - qWarning("QWebChannel is not connected to any transports, cannot send messages."); - return; - } - - const QByteArray &message = generateJSONMessage(id, data, false); - const QString &messageText = QString::fromUtf8(message); - foreach (QWebChannelAbstractTransport *transport, d->transports) { - transport->sendTextMessage(messageText); - } -} - QT_END_NAMESPACE #include "moc_qwebchannel.cpp" diff --git a/src/webchannel/qwebchannel.h b/src/webchannel/qwebchannel.h index a65a4ee..46d77a3 100644 --- a/src/webchannel/qwebchannel.h +++ b/src/webchannel/qwebchannel.h @@ -97,8 +97,6 @@ public Q_SLOTS: void connectTo(QWebChannelAbstractTransport *transport); void disconnectFrom(QWebChannelAbstractTransport *transport); - void sendMessage(const QJsonValue &id, const QJsonValue &data = QJsonValue()) const; - private: Q_DECLARE_PRIVATE(QWebChannel) QWebChannel(QWebChannelPrivate &dd, QObject *parent = 0); diff --git a/src/webchannel/qwebchannel.js b/src/webchannel/qwebchannel.js index dd6c4b3..3274d65 100644 --- a/src/webchannel/qwebchannel.js +++ b/src/webchannel/qwebchannel.js @@ -52,9 +52,12 @@ var QWebChannelMessageTypes = { connectToSignal: 7, disconnectFromSignal: 8, setProperty: 9, + response: 10, }; -var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel) +// TODO: always expect an initialized transport object with a defined interface +// to be passed in, remove automagic WebSocket code +var QWebChannel = function(baseUrlOrSocket, initCallback) { var channel = this; this.send = function(data) @@ -64,33 +67,115 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel) } channel.socket.send(data); } - this.messageReceived = function(message) + this.onMessageReceived = function(message) { - var jsonData = JSON.parse(message.data); - if (jsonData.id === undefined) { - console.error("invalid message received:", message.data); + var data = message.data; + if (typeof data === "string") { + data = JSON.parse(data); + } + switch (data.type) { + case QWebChannelMessageTypes.signal: + channel.handleSignal(data); + break; + case QWebChannelMessageTypes.response: + channel.handleResponse(data); + break; + case QWebChannelMessageTypes.propertyUpdate: + channel.handlePropertyUpdate(data); + break; + case QWebChannelMessageTypes.init: + channel.handleInit(data); + break; + default: + console.error("invalid message received:", message.data); + break; + } + } + + this.execCallbacks = {}; + this.execId = 0; + this.exec = function(data, callback) + { + if (!callback) { + // if no callback is given, send directly + channel.send(data); return; } - if (jsonData.data === undefined) { - jsonData.data = {}; + if (channel.execId === Number.MAX_VALUE) { + // wrap + channel.execId = Number.MIN_VALUE; } - if (jsonData.response) { - channel.execCallbacks[jsonData.id](jsonData.data); - delete channel.execCallbacks[jsonData.id]; - } else if (channel.subscriptions[jsonData.id]) { - channel.subscriptions[jsonData.id].forEach(function(callback) { - (callback)(jsonData.data); } - ); + if (data.hasOwnProperty("id")) { + console.error("Cannot exec message with property id: " + JSON.stringify(data)); + return; + } + data.id = channel.execId++; + channel.execCallbacks[data.id] = callback; + channel.send(data); + }; + + this.objects = {}; + + this.handleSignal = function(message) + { + var object = channel.objects[message.object]; + if (object) { + object.signalEmitted(message.signal, message.args); + } else { + console.warn("Unhandled signal: " + message.object + "::" + message.signal); } } - this.initialized = function() + this.handleResponse = function(message) { - if (rawChannel) { + if (!message.hasOwnProperty("id")) { + console.error("Invalid response message received: ", JSON.stringify(message)); + return; + } + channel.execCallbacks[message.id](message.data); + delete channel.execCallbacks[message.id]; + } + + this.handlePropertyUpdate = function(message) + { + for (var i in message.data) { + var data = message.data[i]; + var object = channel.objects[data.object]; + if (object) { + object.propertyUpdate(data.signals, data.properties); + } else { + console.warn("Unhandled property update: " + data.object + "::" + data.signal); + } + } + setTimeout(function() { channel.exec({type: QWebChannelMessageTypes.idle}); }, 0); + } + + // prevent multiple initialization which might happen with multiple webchannel clients. + this.initialized = false; + this.handleInit = 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); + } + if (initCallback) { initCallback(channel); - } else { - channel.initMetaObjectPublisher(initCallback); } + setTimeout(function() { channel.exec({type: QWebChannelMessageTypes.idle}); }, 0); + } + + this.debug = function(message) + { + channel.send({type: QWebChannelMessageTypes.debug, data: message}); + }; + + this.onSocketReady = function(doneCallback) + { + channel.exec({type: QWebChannelMessageTypes.init}); } if (typeof baseUrlOrSocket === 'object') { @@ -99,13 +184,13 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel) { channel.socket.postMessage(data); } - this.socket.onmessage = this.messageReceived - setTimeout(this.initialized, 0); + this.socket.onmessage = this.onMessageReceived + this.onSocketReady(); } else { ///TODO: use QWebChannel protocol, once custom protcols are supported by QtWebSocket this.socket = new WebSocket(baseUrlOrSocket/*, "QWebChannel" */); - this.socket.onopen = this.initialized + this.socket.onopen = this.onSocketReady this.socket.onclose = function() { console.error("web channel closed"); @@ -114,96 +199,7 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel) { console.error("web channel error: " + error); }; - this.socket.onmessage = this.messageReceived - } - - this.subscriptions = {}; - this.subscribe = function(id, callback) - { - if (channel.subscriptions[id]) { - channel.subscriptions[id].push(callback); - } else { - channel.subscriptions[id] = [callback]; - } - }; - - this.execCallbacks = {}; - this.execId = 0; - this.exec = function(data, callback) - { - if (!callback) { - // if no callback is given, send directly - channel.send({data: data}); - return; - } - if (channel.execId === Number.MAX_VALUE) { - // wrap - channel.execId = Number.MIN_VALUE; - } - var id = channel.execId++; - channel.execCallbacks[id] = callback; - channel.send({"id": id, "data": data}); - }; - - this.objects = {}; - - this.initMetaObjectPublisher = function(doneCallback) - { - // prevent multiple initialization which might happen with multiple webchannel clients. - var initialized = false; - - channel.subscribe( - QWebChannelMessageTypes.signal, - function(payload) { - var object = channel.objects[payload.object]; - if (object) { - object.signalEmitted(payload.signal, payload.args); - } else { - console.warn("Unhandled signal: " + payload.object + "::" + payload.signal); - } - } - ); - - channel.subscribe( - QWebChannelMessageTypes.propertyUpdate, - function(payload) { - for (var i in payload) { - var data = payload[i]; - var object = channel.objects[data.object]; - if (object) { - object.propertyUpdate(data.signals, data.properties); - } else { - console.warn("Unhandled property update: " + data.object + "::" + data.signal); - } - } - setTimeout(function() { channel.exec({type: QWebChannelMessageTypes.idle}); }, 0); - } - ); - - channel.subscribe( - QWebChannelMessageTypes.init, - function(payload) { - if (initialized) { - return; - } - initialized = true; - for (var objectName in payload) { - var data = payload[objectName]; - var object = new QObject(objectName, data, channel); - } - if (doneCallback) { - doneCallback(channel); - } - setTimeout(function() { channel.exec({type: QWebChannelMessageTypes.idle}); }, 0); - } - ); - - channel.debug = function(message) - { - channel.send({"data" : {"type" : QWebChannelMessageTypes.debug, "message" : message}}); - }; - - channel.exec({type: QWebChannelMessageTypes.init}); + this.socket.onmessage = this.onMessageReceived } }; diff --git a/src/webchannel/qwebchannel_p.h b/src/webchannel/qwebchannel_p.h index 62b2cd5..add55d1 100644 --- a/src/webchannel/qwebchannel_p.h +++ b/src/webchannel/qwebchannel_p.h @@ -53,8 +53,6 @@ class QJsonValue; class QWebChannelAbstractTransport; class QMetaObjectPublisher; -Q_WEBCHANNEL_EXPORT QByteArray generateJSONMessage(const QJsonValue &id, const QJsonValue &data, bool response); - class Q_WEBCHANNEL_EXPORT QWebChannelPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QWebChannel) diff --git a/src/webchannel/qwebchannelabstracttransport.h b/src/webchannel/qwebchannelabstracttransport.h index 0062fab..a13851c 100644 --- a/src/webchannel/qwebchannelabstracttransport.h +++ b/src/webchannel/qwebchannelabstracttransport.h @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE +class QJsonObject; class Q_WEBCHANNEL_EXPORT QWebChannelAbstractTransport : public QObject { Q_OBJECT @@ -58,13 +59,13 @@ public Q_SLOTS: /** * Send a text @p message to the remote client. */ - virtual void sendTextMessage(const QString &message) = 0; + virtual void sendMessage(const QJsonObject &message) = 0; Q_SIGNALS: /** * Emitted when a new text message was received from the remote client. */ - void textMessageReceived(const QString &message); + void messageReceived(const QJsonObject &message, QWebChannelAbstractTransport *transport); }; QT_END_NAMESPACE |