summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2014-03-21 16:15:47 +0100
committerPierre Rossi <pierre.rossi@gmail.com>2014-07-04 12:37:29 +0200
commit856dc072acb649be03e02ac64c81015d3f2675c2 (patch)
tree649985d553d6ea92360a66ca291af91c1114596e
parent9f78e0985d2f4fdc2588be57c5f25afdd59c6365 (diff)
downloadqtwebchannel-856dc072acb649be03e02ac64c81015d3f2675c2.tar.gz
Refactor code to use QWebChannelAbstractTransport and QtWebSockets.
This is a quite big changeset, but necessary to get the roadmap implemented that was discussed at QtCS. With this patchset landed, the QWebChannel does not depend on QtWebKit anymore, not even for the tests. Rather, we will introduce the dependency in the other way (i.e. QtWebKit will optionally use QtWebChannel if available). For the pure Qt/C++ use-case, we ship a utility implementation of a QWebChannelAbstractTransport that uses a QWebSocket for the server-client communication. This way, we can get rid of the custom WebSocket implementation. The tests are refactored to run the qwebchannel.js code directly inside QML. Integration tests for QtWebKit/QtWebEngine as well as examples will be added to these repositories. Change-Id: Icc1c1c5918ec46e31d5070937c14c4ca25a3e2d6 Reviewed-by: Pierre Rossi <pierre.rossi@gmail.com>
-rw-r--r--examples/qml/README3
-rw-r--r--examples/qml/example.qml117
-rw-r--r--examples/qml/index.html59
-rw-r--r--examples/standalone/main.cpp60
-rw-r--r--examples/standalone/standalone.pro2
-rw-r--r--src/imports/webchannel/plugin.cpp9
-rw-r--r--src/imports/webchannel/plugins.qmltypes96
-rw-r--r--src/imports/webchannel/qmlwebchannel.cpp45
-rw-r--r--src/imports/webchannel/qmlwebchannel.h16
-rw-r--r--src/imports/webchannel/qmlwebviewtransport.cpp103
-rw-r--r--src/imports/webchannel/webchannel.pro6
-rw-r--r--src/webchannel/qmetaobjectpublisher.cpp10
-rw-r--r--src/webchannel/qmetaobjectpublisher_p.h15
-rw-r--r--src/webchannel/qwebchannel.cpp32
-rw-r--r--src/webchannel/qwebchannel.h8
-rw-r--r--src/webchannel/qwebchannel.js30
-rw-r--r--src/webchannel/qwebchannel_p.h7
-rw-r--r--src/webchannel/qwebchannelabstracttransport.cpp (renamed from tests/auto/qml/data/testsetup.js)19
-rw-r--r--src/webchannel/qwebchannelabstracttransport.h (renamed from src/webchannel/qwebsockettransport_p.h)51
-rw-r--r--src/webchannel/qwebchanneltransportinterface.h94
-rw-r--r--src/webchannel/qwebchannelwebsockettransport.cpp (renamed from tests/auto/qml/TestWebView.qml)62
-rw-r--r--src/webchannel/qwebchannelwebsockettransport.h68
-rw-r--r--src/webchannel/qwebsockettransport.cpp212
-rw-r--r--src/webchannel/qwebsockettransport.h81
-rw-r--r--src/webchannel/webchannel.pro8
-rw-r--r--sync.profile3
-rw-r--r--tests/auto/qml/Client.qml (renamed from tests/auto/qml/WebChannelTest.qml)133
-rw-r--r--tests/auto/qml/data/bench_init.html13
-rw-r--r--tests/auto/qml/data/disconnect.html21
-rw-r--r--tests/auto/qml/data/grouping.html17
-rw-r--r--tests/auto/qml/data/method.html17
-rw-r--r--tests/auto/qml/data/multiclient.html19
-rw-r--r--tests/auto/qml/data/property.html21
-rw-r--r--tests/auto/qml/data/receiveRaw.html15
-rw-r--r--tests/auto/qml/data/send.html17
-rw-r--r--tests/auto/qml/data/signal.html17
-rw-r--r--tests/auto/qml/data/wrapper.html28
-rw-r--r--tests/auto/qml/qml.cpp14
-rw-r--r--tests/auto/qml/qml.pro6
-rw-r--r--tests/auto/qml/testtransport.cpp57
-rw-r--r--tests/auto/qml/testtransport.h (renamed from src/imports/webchannel/qmlwebviewtransport.h)32
-rw-r--r--tests/auto/qml/tst_bench.qml38
-rw-r--r--tests/auto/qml/tst_metaobjectpublisher.qml177
-rw-r--r--tests/auto/qml/tst_multiclient.qml56
-rw-r--r--tests/auto/qml/tst_webchannel.qml37
-rw-r--r--tests/auto/webchannel/tst_webchannel.cpp15
-rw-r--r--tests/auto/webchannel/tst_webchannel.h19
47 files changed, 662 insertions, 1323 deletions
diff --git a/examples/qml/README b/examples/qml/README
deleted file mode 100644
index cf0e041..0000000
--- a/examples/qml/README
+++ /dev/null
@@ -1,3 +0,0 @@
-To run this example, install QtWebKit, QtWebChannel and QtQuickControls modules, then run:
-
-qmlscene ./example.qml
diff --git a/examples/qml/example.qml b/examples/qml/example.qml
deleted file mode 100644
index 2d51f27..0000000
--- a/examples/qml/example.qml
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWebChannel module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.1
-
-import QtWebChannel 1.0
-
-import QtQuick.Controls 1.0
-import QtQuick.Layouts 1.0
-
-import QtWebKit 3.0
-import QtWebKit.experimental 1.0
-
-ApplicationWindow {
- id: window
- title: "QtWebChannel Example: QML Server to QtWebKit WebView Client"
- width: 600
- height: 400
-
- WebChannel {
- id: webChannel
-
- connections: WebViewTransport {
- webViewExperimental: webView.experimental
- onMessageReceived: {
- textEdit.text += "Received message: " + message + "\n";
- }
- }
- }
-
- RowLayout {
- id: myRow
- anchors.fill: parent
- ColumnLayout {
- id: myCol
- Label {
- id: caption
- text: "QML Server"
- font.bold: true
- }
- TextArea {
- Layout.fillHeight: true
- Layout.fillWidth: true
- id: textEdit
- readOnly: true
- }
- RowLayout {
- Label {
- id: label
- text: "Input: "
- }
- TextField {
- id: input
- Layout.fillWidth: true
- }
- Button {
- id: send
- text: "Send"
- onClicked: {
- if (input.text) {
- webChannel.sendMessage("message", input.text);
- textEdit.text += "Sent message: " + input.text + "\n";
- input.text = ""
- }
- }
- }
- }
- }
- WebView {
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.minimumWidth: window.width / 2
- id: webView
- url: "index.html"
- experimental.preferences.developerExtrasEnabled: true
- experimental.preferences.navigatorQtObjectEnabled: true
- }
- }
-}
diff --git a/examples/qml/index.html b/examples/qml/index.html
deleted file mode 100644
index 8b65dd2..0000000
--- a/examples/qml/index.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- new QWebChannel(navigator.qt, function(channel) {
- document.getElementById("send").onclick = function() {
- var input = document.getElementById("input");
- var text = input.value;
- if (!text) {
- return;
- }
- var output = document.getElementById("output");
- output.innerHTML = output.innerHTML + "Sent message: " + text + "\n";
- input.value = "";
- channel.send(text);
- }
-
- channel.subscribe("message", function(text) {
- var output = document.getElementById("output");
- output.innerHTML = output.innerHTML + "Received message: " + text + "\n";
- });
- }, true /* raw web channel */);
- //END SETUP
- </script>
- <style type="text/css">
- * {
- padding: 0;
- margin: 0;
- font-size: 40px;
- }
- html, body {
- height: 100%;
- width: 100%;
- }
- #div {
- height: 100%;
- padding: 0 10%;
- }
- #input {
- width: 50%;
- margin: 0 10px;
- }
- #output {
- width: 100%;
- height: 80%;
- }
- </style>
- </head>
- <body>
- <div id="div">
- <h1>HTML Client</h1>
- <textarea id="output" readonly></textarea><br />
- Input: <input id="input" /><input type="submit" id="send" value="Send" onclick="javascript:click();" />
- </div>
- </body>
-</html>
diff --git a/examples/standalone/main.cpp b/examples/standalone/main.cpp
index 47f7ea2..05deb24 100644
--- a/examples/standalone/main.cpp
+++ b/examples/standalone/main.cpp
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qwebchannel.h"
-#include "qwebsockettransport.h"
#include <QApplication>
#include <QDialog>
@@ -49,6 +48,10 @@
#include <QUrl>
#include <QDebug>
+#include <QtWebSockets/QWebSocketServer>
+#include <QtWebSockets/QWebSocket>
+#include <QtWebChannel/QWebChannelWebSocketTransport>
+
#include "ui_dialog.h"
class Dialog : public QObject
@@ -56,15 +59,18 @@ class Dialog : public QObject
Q_OBJECT
public:
- explicit Dialog(QWebSocketTransport *transport, QObject *parent = 0)
+ explicit Dialog(const QString &baseUrl, QObject *parent = 0)
: QObject(parent)
{
ui.setupUi(&dialog);
dialog.show();
connect(ui.send, SIGNAL(clicked()), SLOT(clicked()));
- connect(transport, SIGNAL(baseUrlChanged(QString)),
- SLOT(baseUrlChanged(QString)));
+
+ QUrl url = QUrl::fromLocalFile(SOURCE_DIR "/index.html");
+ url.setQuery(QStringLiteral("webChannelBaseUrl=") + baseUrl);
+ ui.output->appendPlainText(tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString()));
+ QDesktopServices::openUrl(url);
}
signals:
@@ -91,29 +97,55 @@ private slots:
ui.input->clear();
}
- void baseUrlChanged(const QString &baseUrl)
+private:
+ QDialog dialog;
+ Ui::Dialog ui;
+};
+
+// boiler plate code to connect incoming WebSockets to the WebChannel, such that they receive
+// messages and can access the published objects.
+class TransportHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ TransportHandler(QWebChannel *channel, QObject *parent = 0)
+ : QObject(parent)
+ , m_server(QStringLiteral("QWebChannel Standalone Example Server"), QWebSocketServer::NonSecureMode)
+ , m_channel(channel)
+ {
+ if (!m_server.listen(QHostAddress::LocalHost)) {
+ qFatal("Failed to open web socket server.");
+ }
+
+ connect(&m_server, &QWebSocketServer::newConnection,
+ this, &TransportHandler::handleNewConnection);
+ }
+
+ QString baseUrl() const
{
- ui.output->appendPlainText(tr("Initialization complete, opening browser."));
+ return m_server.serverUrl().toString();
+ }
- QUrl url = QUrl::fromLocalFile(SOURCE_DIR "/index.html");
- url.setQuery(QStringLiteral("webChannelBaseUrl=") + baseUrl);
- QDesktopServices::openUrl(url);
+private slots:
+ void handleNewConnection()
+ {
+ m_channel->connectTo(new QWebChannelWebSocketTransport(m_server.nextPendingConnection()));
}
private:
- QDialog dialog;
- Ui::Dialog ui;
+ QWebSocketServer m_server;
+ QWebChannel *m_channel;
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
- QWebSocketTransport transport;
QWebChannel channel;
- channel.connectTo(&transport);
+ TransportHandler transportHandler(&channel);
- Dialog dialog(&transport);
+ Dialog dialog(transportHandler.baseUrl());
channel.registerObject(QStringLiteral("dialog"), &dialog);
diff --git a/examples/standalone/standalone.pro b/examples/standalone/standalone.pro
index 7ce0f2b..114be58 100644
--- a/examples/standalone/standalone.pro
+++ b/examples/standalone/standalone.pro
@@ -1,4 +1,4 @@
-QT += gui webchannel widgets
+QT += gui webchannel widgets websockets
CONFIG += warn_on
diff --git a/src/imports/webchannel/plugin.cpp b/src/imports/webchannel/plugin.cpp
index 589e3cb..6507112 100644
--- a/src/imports/webchannel/plugin.cpp
+++ b/src/imports/webchannel/plugin.cpp
@@ -43,11 +43,6 @@
#include <QtQml/QQmlExtensionPlugin>
#include "qmlwebchannel.h"
-#include "qwebsockettransport.h"
-#include "qmlwebviewtransport.h"
-#include "qwebchanneltransportinterface.h"
-
-QML_DECLARE_INTERFACE_HASMETATYPE(QWebChannelTransportInterface);
QT_BEGIN_NAMESPACE
@@ -62,13 +57,9 @@ public:
void QWebChannelPlugin::registerTypes(const char *uri)
{
- qmlRegisterInterface<QWebChannelTransportInterface>("QWebChannelTransportInterface");
-
int major = 1;
int minor = 0;
qmlRegisterType<QmlWebChannel>(uri, major, minor, "WebChannel");
- qmlRegisterType<QWebSocketTransport>(uri, major, minor, "WebSocketTransport");
- qmlRegisterType<QmlWebViewTransport>(uri, major, minor, "WebViewTransport");
}
QT_END_NAMESPACE
diff --git a/src/imports/webchannel/plugins.qmltypes b/src/imports/webchannel/plugins.qmltypes
index 6d08f9c..789f2b4 100644
--- a/src/imports/webchannel/plugins.qmltypes
+++ b/src/imports/webchannel/plugins.qmltypes
@@ -4,95 +4,65 @@ import QtQuick.tooling 1.1
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -notrelocatable QtWebChannel 5.3'
+// 'qmlplugindump -notrelocatable QtWebChannel 1.0'
Module {
Component {
- name: "QMetaObjectPublisher"
+ name: "QWebChannel"
prototype: "QObject"
- exports: ["QtWebChannel/MetaObjectPublisher 5.3"]
- exportMetaObjectRevisions: [0]
- Property { name: "webChannel"; type: "QWebChannel"; isPointer: true }
Property { name: "blockUpdates"; type: "bool" }
Signal {
- name: "webChannelChanged"
- Parameter { name: "channel"; type: "QWebChannel"; isPointer: true }
- }
- Signal {
name: "blockUpdatesChanged"
Parameter { name: "block"; type: "bool" }
}
Method {
- name: "classInfoForObjects"
- type: "QVariantMap"
- Parameter { name: "objects"; type: "QVariantMap" }
- }
- Method {
- name: "classInfoForObject"
- type: "QVariantMap"
- Parameter { name: "object"; type: "QObject"; isPointer: true }
+ name: "sendMessage"
+ Parameter { name: "id"; type: "QJsonValue" }
+ Parameter { name: "data"; type: "QJsonValue" }
}
Method {
- name: "registerObjects"
- Parameter { name: "objects"; type: "QVariantMap" }
+ name: "sendMessage"
+ Parameter { name: "id"; type: "QJsonValue" }
}
Method {
- name: "handleRequest"
- type: "bool"
- Parameter { name: "message"; type: "QJsonObject" }
+ name: "registerObject"
+ Parameter { name: "id"; type: "string" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
}
- Method { name: "bench_ensureUpdatesInitialized" }
- Method { name: "bench_sendPendingPropertyUpdates" }
Method {
- name: "bench_registerObjects"
- Parameter { name: "objects"; type: "QVariantMap" }
+ name: "deregisterObject"
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
}
- Method { name: "bench_initializeClients" }
- Method { name: "test_clientIsIdle"; type: "bool" }
}
Component {
- name: "QWebChannel"
- prototype: "QObject"
- exports: ["QtWebChannel/WebChannel 5.3"]
+ name: "QmlWebChannel"
+ prototype: "QWebChannel"
+ exports: ["QtWebChannel/WebChannel 1.0"]
exportMetaObjectRevisions: [0]
- Property { name: "baseUrl"; type: "string"; isReadonly: true }
- Property { name: "useSecret"; type: "bool" }
- Signal {
- name: "baseUrlChanged"
- Parameter { name: "baseUrl"; type: "string" }
- }
- Signal {
- name: "rawMessageReceived"
- Parameter { name: "rawMessage"; type: "string" }
- }
- Signal { name: "pongReceived" }
- Signal { name: "initialized" }
- Signal {
- name: "failed"
- Parameter { name: "reason"; type: "string" }
- }
+ attachedType: "QmlWebChannelAttached"
+ Property { name: "transports"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "registeredObjects"; type: "QObject"; isList: true; isReadonly: true }
Method {
- name: "sendMessage"
- Parameter { name: "id"; type: "QJsonValue" }
- Parameter { name: "data"; type: "QJsonValue" }
- }
- Method {
- name: "sendMessage"
- Parameter { name: "id"; type: "QJsonValue" }
+ name: "registerObjects"
+ Parameter { name: "objects"; type: "QVariantMap" }
}
+ Method { name: "test_clientIsIdle"; type: "bool" }
Method {
- name: "respond"
- Parameter { name: "messageId"; type: "QJsonValue" }
- Parameter { name: "data"; type: "QJsonValue" }
+ name: "connectTo"
+ Parameter { name: "transport"; type: "QObject"; isPointer: true }
}
Method {
- name: "respond"
- Parameter { name: "messageId"; type: "QJsonValue" }
+ name: "disconnectFrom"
+ Parameter { name: "transport"; type: "QObject"; isPointer: true }
}
- Method {
- name: "sendRawMessage"
- Parameter { name: "rawMessage"; type: "string" }
+ }
+ Component {
+ name: "QmlWebChannelAttached"
+ prototype: "QObject"
+ Property { name: "id"; type: "string" }
+ Signal {
+ name: "idChanged"
+ Parameter { name: "id"; type: "string" }
}
- Method { name: "ping" }
}
}
diff --git a/src/imports/webchannel/qmlwebchannel.cpp b/src/imports/webchannel/qmlwebchannel.cpp
index dc7398d..e61e9c8 100644
--- a/src/imports/webchannel/qmlwebchannel.cpp
+++ b/src/imports/webchannel/qmlwebchannel.cpp
@@ -43,6 +43,7 @@
#include "qwebchannel_p.h"
#include "qmetaobjectpublisher_p.h"
+#include "qwebchannelabstracttransport.h"
#include <QtQml/QQmlContext>
@@ -100,32 +101,19 @@ QmlWebChannelAttached *QmlWebChannel::qmlAttachedProperties(QObject *obj)
void QmlWebChannel::connectTo(QObject *transport)
{
- if (QWebChannelTransportInterface *iface = qobject_cast<QWebChannelTransportInterface*>(transport)) {
- m_connectedObjects.insert(transport, iface);
- QWebChannel::connectTo(iface);
- connect(transport, SIGNAL(destroyed(QObject*)), SLOT(transportDestroyed(QObject*)), Qt::UniqueConnection);
+ if (QWebChannelAbstractTransport *realTransport = qobject_cast<QWebChannelAbstractTransport*>(transport)) {
+ QWebChannel::connectTo(realTransport);
} else {
- qWarning() << "Cannot connect to transport" << transport << " - it does not implement the QWebChannelTransportInterface.";
+ qWarning() << "Cannot connect to transport" << transport << " - it is not a QWebChannelAbstractTransport.";
}
}
void QmlWebChannel::disconnectFrom(QObject *transport)
{
- if (QWebChannelTransportInterface *iface = qobject_cast<QWebChannelTransportInterface*>(transport)) {
- QWebChannel::disconnectFrom(iface);
- disconnect(transport, SIGNAL(destroyed(QObject*)), this, SLOT(transportDestroyed(QObject*)));
- m_connectedObjects.remove(transport);
+ if (QWebChannelAbstractTransport *realTransport = qobject_cast<QWebChannelAbstractTransport*>(transport)) {
+ QWebChannel::disconnectFrom(realTransport);
} else {
- qWarning() << "Cannot disconnect from transport" << transport << " - it does not implement the QWebChannelTransportInterface.";
- }
-}
-
-void QmlWebChannel::transportDestroyed(QObject *transport)
-{
- QWebChannelTransportInterface *iface = m_connectedObjects.take(transport);
- const int idx = d->transports.indexOf(iface);
- if (idx != -1) {
- d->transports.remove(idx);
+ qWarning() << "Cannot disconnect from transport" << transport << " - it is not a QWebChannelAbstractTransport.";
}
}
@@ -175,35 +163,36 @@ void QmlWebChannel::registeredObjects_clear(QQmlListProperty<QObject> *prop)
return channel->m_registeredObjects.clear();
}
-QQmlListProperty<QWebChannelTransportInterface> QmlWebChannel::transports()
+QQmlListProperty<QObject> QmlWebChannel::transports()
{
- return QQmlListProperty<QWebChannelTransportInterface>(this, 0,
+ return QQmlListProperty<QObject>(this, 0,
transports_append,
transports_count,
transports_at,
transports_clear);
}
-void QmlWebChannel::transports_append(QQmlListProperty<QWebChannelTransportInterface> *prop, QWebChannelTransportInterface *transport)
+void QmlWebChannel::transports_append(QQmlListProperty<QObject> *prop, QObject *transport)
{
- QWebChannel *channel = static_cast<QWebChannel*>(prop->object);
+ QmlWebChannel *channel = static_cast<QmlWebChannel*>(prop->object);
channel->connectTo(transport);
}
-int QmlWebChannel::transports_count(QQmlListProperty<QWebChannelTransportInterface> *prop)
+int QmlWebChannel::transports_count(QQmlListProperty<QObject> *prop)
{
return static_cast<QmlWebChannel*>(prop->object)->d->transports.size();
}
-QWebChannelTransportInterface *QmlWebChannel::transports_at(QQmlListProperty<QWebChannelTransportInterface> *prop, int index)
+QObject *QmlWebChannel::transports_at(QQmlListProperty<QObject> *prop, int index)
{
- return static_cast<QmlWebChannel*>(prop->object)->d->transports.at(index);
+ QmlWebChannel *channel = static_cast<QmlWebChannel*>(prop->object);
+ return dynamic_cast<QObject*>(channel->d->transports.at(index));
}
-void QmlWebChannel::transports_clear(QQmlListProperty<QWebChannelTransportInterface> *prop)
+void QmlWebChannel::transports_clear(QQmlListProperty<QObject> *prop)
{
QWebChannel *channel = static_cast<QWebChannel*>(prop->object);
- foreach (QWebChannelTransportInterface *transport, channel->d->transports) {
+ foreach (QWebChannelAbstractTransport *transport, channel->d->transports) {
channel->disconnectFrom(transport);
}
Q_ASSERT(channel->d->transports.isEmpty());
diff --git a/src/imports/webchannel/qmlwebchannel.h b/src/imports/webchannel/qmlwebchannel.h
index 3610307..6bc7127 100644
--- a/src/imports/webchannel/qmlwebchannel.h
+++ b/src/imports/webchannel/qmlwebchannel.h
@@ -45,7 +45,6 @@
#include <qwebchannel.h>
#include "qmlwebchannelattached.h"
-#include "qwebchanneltransportinterface.h"
#include <QVector>
@@ -58,7 +57,7 @@ class QmlWebChannel : public QWebChannel
{
Q_OBJECT
- Q_PROPERTY( QQmlListProperty<QWebChannelTransportInterface> connections READ transports );
+ Q_PROPERTY( QQmlListProperty<QObject> transports READ transports );
Q_PROPERTY( QQmlListProperty<QObject> registeredObjects READ registeredObjects )
public:
@@ -68,7 +67,7 @@ public:
Q_INVOKABLE void registerObjects(const QVariantMap &objects);
QQmlListProperty<QObject> registeredObjects();
- QQmlListProperty<QWebChannelTransportInterface> transports();
+ QQmlListProperty<QObject> transports();
// TODO: remove this by replacing QML with C++ tests
Q_INVOKABLE bool test_clientIsIdle() const;
@@ -80,7 +79,6 @@ public:
private Q_SLOTS:
void objectIdChanged(const QString &newId);
- void transportDestroyed(QObject *transport);
private:
static void registeredObjects_append(QQmlListProperty<QObject> *prop, QObject *item);
@@ -88,14 +86,12 @@ private:
static QObject *registeredObjects_at(QQmlListProperty<QObject> *prop, int index);
static void registeredObjects_clear(QQmlListProperty<QObject> *prop);
- static void transports_append(QQmlListProperty<QWebChannelTransportInterface> *prop, QWebChannelTransportInterface *item);
- static int transports_count(QQmlListProperty<QWebChannelTransportInterface> *prop);
- static QWebChannelTransportInterface *transports_at(QQmlListProperty<QWebChannelTransportInterface> *prop, int index);
- static void transports_clear(QQmlListProperty<QWebChannelTransportInterface> *prop);
+ static void transports_append(QQmlListProperty<QObject> *prop, QObject *item);
+ static int transports_count(QQmlListProperty<QObject> *prop);
+ static QObject *transports_at(QQmlListProperty<QObject> *prop, int index);
+ static void transports_clear(QQmlListProperty<QObject> *prop);
QVector<QObject*> m_registeredObjects;
- // required as when the object is destroyed, we must still find the address of the base class somehow
- QHash<QObject*, QWebChannelTransportInterface*> m_connectedObjects;
};
QML_DECLARE_TYPE( QmlWebChannel )
diff --git a/src/imports/webchannel/qmlwebviewtransport.cpp b/src/imports/webchannel/qmlwebviewtransport.cpp
deleted file mode 100644
index 3d4e2ed..0000000
--- a/src/imports/webchannel/qmlwebviewtransport.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWebChannel module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmlwebviewtransport.h"
-
-#include <QVariantMap>
-
-QT_USE_NAMESPACE
-
-QmlWebViewTransport::QmlWebViewTransport(QObject *parent)
- : QObject(parent)
- , m_webViewExperimental(Q_NULLPTR)
- , m_handler(Q_NULLPTR)
-{
-}
-
-QmlWebViewTransport::~QmlWebViewTransport()
-{
-
-}
-
-void QmlWebViewTransport::setWebViewExperimental(QObject *webViewExperimental)
-{
- if (webViewExperimental != m_webViewExperimental) {
- if (m_webViewExperimental) {
- disconnect(m_webViewExperimental, 0, this, 0);
- }
- m_webViewExperimental = webViewExperimental;
- connect(m_webViewExperimental, SIGNAL(messageReceived(QVariantMap)), this, SLOT(handleWebViewMessage(QVariantMap)));
- emit webViewChanged(webViewExperimental);
- }
-}
-
-QObject *QmlWebViewTransport::webViewExperimental() const
-{
- return m_webViewExperimental;
-}
-
-void QmlWebViewTransport::sendMessage(const QString &message, int /*clientId*/) const
-{
- if (!m_webViewExperimental) {
- qWarning("Cannot send message - did you forget to set the webViewExperimental property?");
- return;
- }
- QMetaObject::invokeMethod(m_webViewExperimental, "postMessage", Q_ARG(QString, message));
-}
-
-void QmlWebViewTransport::sendMessage(const QByteArray &message, int clientId) const
-{
- sendMessage(QString::fromUtf8(message), clientId);
-}
-
-void QmlWebViewTransport::handleWebViewMessage(const QVariantMap &message)
-{
- if (m_handler) {
- const QString &data = message[QStringLiteral("data")].toString();
- m_handler->handleMessage(data, this, -1);
- emit messageReceived(data);
- }
-}
-
-void QmlWebViewTransport::setMessageHandler(QWebChannelMessageHandlerInterface *handler)
-{
- m_handler = handler;
-}
diff --git a/src/imports/webchannel/webchannel.pro b/src/imports/webchannel/webchannel.pro
index 3042854..c1959f5 100644
--- a/src/imports/webchannel/webchannel.pro
+++ b/src/imports/webchannel/webchannel.pro
@@ -6,12 +6,10 @@ VPATH += ../../webchannel
SOURCES += \
plugin.cpp \
qmlwebchannel.cpp \
- qmlwebchannelattached.cpp \
- qmlwebviewtransport.cpp
+ qmlwebchannelattached.cpp
HEADERS += \
qmlwebchannel.h \
- qmlwebchannelattached.h \
- qmlwebviewtransport.h
+ qmlwebchannelattached.h
load(qml_plugin)
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp
index 2914714..096bf7b 100644
--- a/src/webchannel/qmetaobjectpublisher.cpp
+++ b/src/webchannel/qmetaobjectpublisher.cpp
@@ -42,6 +42,7 @@
#include "qmetaobjectpublisher_p.h"
#include "qwebchannel.h"
#include "qwebchannel_p.h"
+#include "qwebchannelabstracttransport.h"
#include <QEvent>
#include <QJsonDocument>
@@ -394,7 +395,7 @@ QByteArray QMetaObjectPublisher::invokeMethod(QObject *const object, const int m
void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments)
{
- if (!webChannel) {
+ if (!webChannel || webChannel->d->transports.isEmpty()) {
return;
}
if (!signalToPropertyMap.value(object).contains(signalIndex)) {
@@ -544,15 +545,18 @@ QByteArray QMetaObjectPublisher::handleRequest(const QJsonObject &message)
return QByteArray();
}
-void QMetaObjectPublisher::handleMessage(const QString &message, QWebChannelTransportInterface *transport, int clientId)
+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->sendMessage(response, clientId);
+ transport->sendTextMessage(QString::fromUtf8(response));
}
}
diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h
index 49b3ed0..dda18ae 100644
--- a/src/webchannel/qmetaobjectpublisher_p.h
+++ b/src/webchannel/qmetaobjectpublisher_p.h
@@ -51,16 +51,14 @@
#include <QPointer>
#include "qwebchannelglobal.h"
-#include "qwebchanneltransportinterface.h"
QT_BEGIN_NAMESPACE
class QWebChannel;
-
-class Q_WEBCHANNEL_EXPORT QMetaObjectPublisher : public QObject, public QWebChannelMessageHandlerInterface
+class Q_WEBCHANNEL_EXPORT QMetaObjectPublisher : public QObject
{
Q_OBJECT
- Q_INTERFACES(QWebChannelMessageHandlerInterface)
+
public:
explicit QMetaObjectPublisher(QWebChannel *webChannel);
virtual ~QMetaObjectPublisher();
@@ -161,13 +159,14 @@ public:
*/
void setBlockUpdates(bool block);
+Q_SIGNALS:
+ void blockUpdatesChanged(bool block);
+
+public Q_SLOTS:
/**
* Parse the message as JSON and if it succeeds, call handleRequest with the obtained JSON object.
*/
- void handleMessage(const QString &message, QWebChannelTransportInterface* transport, int clientId) Q_DECL_OVERRIDE;
-
-Q_SIGNALS:
- void blockUpdatesChanged(bool block);
+ void handleMessage(const QString &message);
protected:
void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE;
diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp
index 75d1a4b..e4cf0d6 100644
--- a/src/webchannel/qwebchannel.cpp
+++ b/src/webchannel/qwebchannel.cpp
@@ -43,7 +43,7 @@
#include "qwebchannel.h"
#include "qwebchannel_p.h"
#include "qmetaobjectpublisher_p.h"
-#include "qwebchanneltransportinterface.h"
+#include "qwebchannelabstracttransport.h"
#include <QJsonDocument>
#include <QJsonObject>
@@ -64,6 +64,14 @@ QByteArray generateJSONMessage(const QJsonValue &id, const QJsonValue &data, boo
return doc.toJson(QJsonDocument::Compact);
}
+void QWebChannelPrivate::_q_transportDestroyed(QObject *object)
+{
+ const int idx = transports.indexOf(static_cast<QWebChannelAbstractTransport*>(object));
+ if (idx != -1) {
+ transports.remove(idx);
+ }
+}
+
QWebChannel::QWebChannel(QObject *parent)
: QObject(parent)
, d(new QWebChannelPrivate)
@@ -75,9 +83,6 @@ QWebChannel::QWebChannel(QObject *parent)
QWebChannel::~QWebChannel()
{
- foreach (QWebChannelTransportInterface *transport, d->transports) {
- transport->setMessageHandler(Q_NULLPTR);
- }
}
void QWebChannel::registerObjects(const QHash< QString, QObject * > &objects)
@@ -109,20 +114,24 @@ void QWebChannel::setBlockUpdates(bool block)
d->publisher->setBlockUpdates(block);
}
-void QWebChannel::connectTo(QWebChannelTransportInterface *transport)
+void QWebChannel::connectTo(QWebChannelAbstractTransport *transport)
{
Q_ASSERT(transport);
if (!d->transports.contains(transport)) {
d->transports << transport;
- transport->setMessageHandler(d->publisher);
+ connect(transport, &QWebChannelAbstractTransport::textMessageReceived,
+ d->publisher, &QMetaObjectPublisher::handleMessage,
+ Qt::UniqueConnection);
+ connect(transport, SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_transportDestroyed(QObject*)));
}
}
-void QWebChannel::disconnectFrom(QWebChannelTransportInterface *transport)
+void QWebChannel::disconnectFrom(QWebChannelAbstractTransport *transport)
{
const int idx = d->transports.indexOf(transport);
if (idx != -1) {
- transport->setMessageHandler(Q_NULLPTR);
+ disconnect(transport, 0, this, 0);
d->transports.remove(idx);
}
}
@@ -135,9 +144,12 @@ void QWebChannel::sendMessage(const QJsonValue &id, const QJsonValue &data) cons
}
const QByteArray &message = generateJSONMessage(id, data, false);
- foreach (QWebChannelTransportInterface *transport, d->transports) {
- transport->sendMessage(message);
+ 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 76e77b8..5016b52 100644
--- a/src/webchannel/qwebchannel.h
+++ b/src/webchannel/qwebchannel.h
@@ -51,7 +51,7 @@
QT_BEGIN_NAMESPACE
struct QWebChannelPrivate;
-class QWebChannelTransportInterface;
+class QWebChannelAbstractTransport;
class Q_WEBCHANNEL_EXPORT QWebChannel : public QObject
{
@@ -89,8 +89,8 @@ public:
*/
void setBlockUpdates(bool block);
- void connectTo(QWebChannelTransportInterface *transport);
- void disconnectFrom(QWebChannelTransportInterface *transport);
+ void connectTo(QWebChannelAbstractTransport *transport);
+ void disconnectFrom(QWebChannelAbstractTransport *transport);
Q_SIGNALS:
void blockUpdatesChanged(bool block);
@@ -100,6 +100,8 @@ public Q_SLOTS:
private:
QScopedPointer<QWebChannelPrivate> d;
+ Q_PRIVATE_SLOT(d, void _q_transportDestroyed(QObject*));
+ friend class QMetaObjectPublisher;
friend class QmlWebChannel;
friend class TestWebChannel;
};
diff --git a/src/webchannel/qwebchannel.js b/src/webchannel/qwebchannel.js
index 278f423..291c10b 100644
--- a/src/webchannel/qwebchannel.js
+++ b/src/webchannel/qwebchannel.js
@@ -102,10 +102,8 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel)
this.socket.onmessage = this.messageReceived
setTimeout(this.initialized, 0);
} else {
- ///TODO: use ssl?
- var socketUrl = "ws://" + baseUrlOrSocket;
///TODO: use QWebChannel protocol, once custom protcols are supported by QtWebSocket
- this.socket = new WebSocket(socketUrl /*, "QWebChannel" */);
+ this.socket = new WebSocket(baseUrlOrSocket/*, "QWebChannel" */);
this.socket.onopen = this.initialized
this.socket.onclose = function()
@@ -147,7 +145,7 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel)
channel.send({"id": id, "data": data});
};
- this.objectMap = {};
+ this.objects = {};
this.initMetaObjectPublisher = function(doneCallback)
{
@@ -157,7 +155,7 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel)
channel.subscribe(
QWebChannelMessageTypes.signal,
function(payload) {
- var object = window[payload.object] || channel.objectMap[payload.object];
+ var object = channel.objects[payload.object];
if (object) {
object.signalEmitted(payload.signal, payload.args);
} else {
@@ -171,7 +169,7 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel)
function(payload) {
for (var i in payload) {
var data = payload[i];
- var object = window[data.object] || channel.objectMap[data.object];
+ var object = channel.objects[data.object];
if (object) {
object.propertyUpdate(data.signals, data.properties);
} else {
@@ -192,7 +190,6 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel)
for (var objectName in payload) {
var data = payload[objectName];
var object = new QObject(objectName, data, channel);
- window[objectName] = object;
}
if (doneCallback) {
doneCallback(channel);
@@ -213,7 +210,7 @@ var QWebChannel = function(baseUrlOrSocket, initCallback, rawChannel)
function QObject(name, data, webChannel)
{
this.__id__ = name;
- webChannel.objectMap[name] = this;
+ webChannel.objects[name] = this;
// List of callbacks that get invoked upon signal emission
this.__objectSignals__ = {};
@@ -233,18 +230,23 @@ function QObject(name, data, webChannel)
return response;
}
var objectId = response.id;
- if (webChannel.objectMap[objectId])
- return webChannel.objectMap[objectId];
+ if (webChannel.objects[objectId])
+ return webChannel.objects[objectId];
var qObject = new QObject( objectId, response.data, webChannel );
qObject.destroyed.connect(function() {
- if (webChannel.objectMap[objectId] === qObject) {
- delete webChannel.objectMap[objectId];
+ if (webChannel.objects[objectId] === qObject) {
+ delete webChannel.objects[objectId];
// reset the now deleted QObject to an empty {} object
// just assigning {} though would not have the desired effect, but the
// below also ensures all external references will see the empty map
- for (var prop in qObject) {
- delete qObject[prop];
+ // NOTE: this detour is necessary to workaround QTBUG-40021
+ var propertyNames = [];
+ for (var propertyName in qObject) {
+ propertyNames.push(propertyName);
+ }
+ for (var idx in propertyNames) {
+ delete qObject[propertyNames[idx]];
}
}
});
diff --git a/src/webchannel/qwebchannel_p.h b/src/webchannel/qwebchannel_p.h
index b81640e..fbdf2ef 100644
--- a/src/webchannel/qwebchannel_p.h
+++ b/src/webchannel/qwebchannel_p.h
@@ -43,22 +43,23 @@
#define QWEBCHANNEL_P_H
#include "qwebchannelglobal.h"
-#include "qwebchanneltransportinterface.h"
#include <QVector>
QT_BEGIN_NAMESPACE
class QJsonValue;
-class QWebChannelTransportInterface;
+class QWebChannelAbstractTransport;
class QMetaObjectPublisher;
Q_WEBCHANNEL_EXPORT QByteArray generateJSONMessage(const QJsonValue &id, const QJsonValue &data, bool response);
struct Q_WEBCHANNEL_EXPORT QWebChannelPrivate
{
- QVector<QWebChannelTransportInterface*> transports;
+ QVector<QWebChannelAbstractTransport*> transports;
QMetaObjectPublisher *publisher;
+
+ void _q_transportDestroyed(QObject* object);
};
QT_END_NAMESPACE
diff --git a/tests/auto/qml/data/testsetup.js b/src/webchannel/qwebchannelabstracttransport.cpp
index c0db83a..86c3121 100644
--- a/tests/auto/qml/data/testsetup.js
+++ b/src/webchannel/qwebchannelabstracttransport.cpp
@@ -39,9 +39,20 @@
**
****************************************************************************/
-window.createWebChannel = function(callback, raw)
+#include "qwebchannelabstracttransport.h"
+
+QT_BEGIN_NAMESPACE
+
+QWebChannelAbstractTransport::QWebChannelAbstractTransport(QObject *parent)
+: QObject(parent)
{
- var baseUrlMatch = /[?&]webChannelBaseUrl=([A-Za-z0-9\-:/\.]+)/.exec(location.search);
- var transport = baseUrlMatch ? baseUrlMatch[1] : navigator.qt;
- return new QWebChannel(transport, callback, raw);
+
}
+
+QWebChannelAbstractTransport::~QWebChannelAbstractTransport()
+{
+
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/webchannel/qwebsockettransport_p.h b/src/webchannel/qwebchannelabstracttransport.h
index b9bd9b0..c90f4b1 100644
--- a/src/webchannel/qwebsockettransport_p.h
+++ b/src/webchannel/qwebchannelabstracttransport.h
@@ -39,51 +39,34 @@
**
****************************************************************************/
-#ifndef QWEBCHANNELSOCKET_P_H
-#define QWEBCHANNELSOCKET_P_H
+#ifndef QWEBCHANNELABSTRACTTRANSPORT_H
+#define QWEBCHANNELABSTRACTTRANSPORT_H
-#include <QtWebSockets/QWebSocketServer>
-
-#include "qwebchanneltransportinterface.h"
+#include <QObject>
+#include <qwebchannelglobal.h>
QT_BEGIN_NAMESPACE
-class QWebSocketTransport;
-class QWebSocketTransportPrivate : public QWebSocketServer
+class Q_WEBCHANNEL_EXPORT QWebChannelAbstractTransport : public QObject
{
Q_OBJECT
public:
- QString m_secret;
- QString m_baseUrl;
- QWebChannelMessageHandlerInterface *m_messageHandler;
- QWebSocketTransport *m_transport;
-
- bool m_useSecret;
- bool m_starting;
-
- explicit QWebSocketTransportPrivate(QWebSocketTransport* transport, QObject *parent = 0);
- virtual ~QWebSocketTransportPrivate();
+ explicit QWebChannelAbstractTransport(QObject *parent = 0);
+ virtual ~QWebChannelAbstractTransport();
- void initLater();
- void sendMessage(const QString &message, int clientId);
+public Q_SLOTS:
+ /**
+ * Send a text @p message to the remote client.
+ */
+ virtual void sendTextMessage(const QString &message) = 0;
Q_SIGNALS:
- void failed(const QString &reason);
- void initialized();
- void baseUrlChanged(const QString &baseUrl);
- void textDataReceived(const QString &message);
-
-private Q_SLOTS:
- void validateNewConnection();
- void init();
- void socketError();
- void messageReceived(const QString &message);
- void clientDisconnected();
-
-private:
- QVector<QWebSocket*> m_clients;
+ /**
+ * Emitted when a new text message was received from the remote client.
+ */
+ void textMessageReceived(const QString &message);
};
QT_END_NAMESPACE
-#endif // QWEBCHANNELSOCKET_P_H
+#endif // QWEBCHANNELABSTRACTTRANSPORT_H
diff --git a/src/webchannel/qwebchanneltransportinterface.h b/src/webchannel/qwebchanneltransportinterface.h
deleted file mode 100644
index c532732..0000000
--- a/src/webchannel/qwebchanneltransportinterface.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWebChannel module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QWEBCHANNELTRANSPORTINTERFACE_H
-#define QWEBCHANNELTRANSPORTINTERFACE_H
-
-#include <QObject>
-
-#include <QtWebChannel/qwebchannelglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-class QWebChannelTransportInterface;
-class Q_WEBCHANNEL_EXPORT QWebChannelMessageHandlerInterface
-{
-public:
- virtual ~QWebChannelMessageHandlerInterface() {}
-
- /**
- * Handle a text message from a web channel client.
- */
- virtual void handleMessage(const QString &message, QWebChannelTransportInterface* transport, int clientId) = 0;
-};
-
-#define QWebChannelMessageHandlerInterface_iid "org.qt-project.Qt.QWebChannelMessageHandlerInterface"
-Q_DECLARE_INTERFACE(QWebChannelMessageHandlerInterface, QWebChannelMessageHandlerInterface_iid);
-Q_DECLARE_METATYPE(QWebChannelMessageHandlerInterface*)
-
-class Q_WEBCHANNEL_EXPORT QWebChannelTransportInterface
-{
-public:
- virtual ~QWebChannelTransportInterface() {}
-
- /**
- * Send a text message to all web channel clients.
- */
- virtual void sendMessage(const QString &message, int clientId = -1) const = 0;
-
- /**
- * Send a binary message to all web channel clients.
- */
- virtual void sendMessage(const QByteArray &message, int clientId = -1) const = 0;
-
- /**
- * Sets the message handler that will be called on incoming messages from web channel clients.
- */
- virtual void setMessageHandler(QWebChannelMessageHandlerInterface *handler) = 0;
-};
-
-#define QWebChannelTransportInterface_iid "org.qt-project.Qt.QWebChannelTransportInterface"
-Q_DECLARE_INTERFACE(QWebChannelTransportInterface, QWebChannelTransportInterface_iid);
-Q_DECLARE_METATYPE(QWebChannelTransportInterface*)
-
-QT_END_NAMESPACE
-
-#endif // QWEBCHANNELTRANSPORTINTERFACE_H
diff --git a/tests/auto/qml/TestWebView.qml b/src/webchannel/qwebchannelwebsockettransport.cpp
index 3b12f38..59c9538 100644
--- a/tests/auto/qml/TestWebView.qml
+++ b/src/webchannel/qwebchannelwebsockettransport.cpp
@@ -39,43 +39,41 @@
**
****************************************************************************/
-import QtQuick 2.0
-import QtTest 1.0
+#include "qwebchannelwebsockettransport.h"
-import QtWebKit 3.0
-import QtWebKit.experimental 1.0
+/*!
+ \inmodule QtWebChannel
+ \brief QWebChannelAbstractSocket implementation that uses a QWebSocket internally.
-WebView {
- id: view
- property var lastLoadStatus
+ The transport delegates all messages received over the QWebSocket over its
+ textMessageReceived signal. Analogously, all calls to sendTextMessage will
+ be send over the QWebSocket to the remote client.
+*/
- experimental.preferences.developerExtrasEnabled: true
- experimental.preferences.navigatorQtObjectEnabled: true
+QT_BEGIN_NAMESPACE
- onLoadingChanged: {
- // NOTE: we cannot use spy.signalArguments nor save the loadRequest anywhere, as it gets
- // deleted after the slots connected to the signal have finished... i.e. it's a weak pointer,
- // not a shared pointer. As such, we have to copy out the interesting data we need later on here...
- lastLoadStatus = loadRequest.status
- }
+struct QWebChannelWebSocketTransportPrivate
+{
+ QWebSocket *socket;
+};
- SignalSpy {
- id: loadingSpy
- target: view
- signalName: "onLoadingChanged"
- }
+QWebChannelWebSocketTransport::QWebChannelWebSocketTransport(QWebSocket *socket)
+: QWebChannelAbstractTransport(socket)
+, d(new QWebChannelWebSocketTransportPrivate)
+{
+ d->socket = socket;
+ connect(socket, &QWebSocket::textMessageReceived,
+ this, &QWebChannelWebSocketTransport::textMessageReceived);
+}
+
+QWebChannelWebSocketTransport::~QWebChannelWebSocketTransport()
+{
- function waitForLoaded()
- {
- do {
- loadingSpy.wait(500);
- } while (loading);
- return lastLoadStatus == WebView.LoadSucceededStatus;
- }
+}
- function clear()
- {
- url = "";
- loadingSpy.clear()
- }
+void QWebChannelWebSocketTransport::sendTextMessage(const QString &message)
+{
+ d->socket->sendTextMessage(message);
}
+
+QT_END_NAMESPACE
diff --git a/src/webchannel/qwebchannelwebsockettransport.h b/src/webchannel/qwebchannelwebsockettransport.h
new file mode 100644
index 0000000..b718b9b
--- /dev/null
+++ b/src/webchannel/qwebchannelwebsockettransport.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebChannel module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBCHANNELWEBSOCKETTRANSPORT_H
+#define QWEBCHANNELWEBSOCKETTRANSPORT_H
+
+#include <QObject>
+#include <QtWebChannel/QWebChannelAbstractTransport>
+#include <QtWebChannel/qwebchannelglobal.h>
+#include <QtWebSockets/QWebSocket>
+
+QT_BEGIN_NAMESPACE
+
+struct QWebChannelWebSocketTransportPrivate;
+class Q_WEBCHANNEL_EXPORT QWebChannelWebSocketTransport : public QWebChannelAbstractTransport
+{
+ Q_OBJECT
+public:
+ explicit QWebChannelWebSocketTransport(QWebSocket *socket);
+ virtual ~QWebChannelWebSocketTransport();
+
+ void sendTextMessage(const QString &message) Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWebChannelWebSocketTransportPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBCHANNELWEBSOCKETTRANSPORT_H
diff --git a/src/webchannel/qwebsockettransport.cpp b/src/webchannel/qwebsockettransport.cpp
deleted file mode 100644
index 8c25a9b..0000000
--- a/src/webchannel/qwebsockettransport.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWebChannel module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwebsockettransport.h"
-#include "qwebsockettransport_p.h"
-
-#include <QUuid>
-
-#include <QtWebSockets/QWebSocket>
-
-QT_USE_NAMESPACE
-
-//BEGIN QWebSocketTransportPrivate
-
-QWebSocketTransportPrivate::QWebSocketTransportPrivate(QWebSocketTransport *transport, QObject *parent)
- : QWebSocketServer(QStringLiteral("QWebChannel Server"), NonSecureMode, parent)
- , m_messageHandler(Q_NULLPTR)
- , m_transport(transport)
- , m_useSecret(true)
- , m_starting(false)
-{
- connect(this, SIGNAL(acceptError(QAbstractSocket::SocketError)),
- SLOT(socketError()));
- connect(this, SIGNAL(newConnection()),
- SLOT(validateNewConnection()));
-}
-
-QWebSocketTransportPrivate::~QWebSocketTransportPrivate()
-{
- close();
- qDeleteAll(m_clients);
-}
-
-void QWebSocketTransportPrivate::initLater()
-{
- if (m_starting)
- return;
- metaObject()->invokeMethod(this, "init", Qt::QueuedConnection);
- m_starting = true;
-}
-
-void QWebSocketTransportPrivate::sendMessage(const QString &message, int clientId)
-{
- if (clientId == -1) {
- foreach (QWebSocket *client, m_clients) {
- client->sendTextMessage(message);
- }
- } else {
- m_clients.at(clientId)->sendTextMessage(message);
- }
-}
-
-void QWebSocketTransportPrivate::validateNewConnection()
-{
- QWebSocket *client = nextPendingConnection();
- // FIXME: client->protocol() != QStringLiteral("QWebChannel")
- // protocols are not supported in QtWebSockets yet...
- if (m_useSecret && client->requestUrl().path() != m_secret)
- {
- client->close(QWebSocketProtocol::CloseCodeBadOperation);
- client->deleteLater();
- } else {
- connect(client, SIGNAL(textMessageReceived(QString)),
- SLOT(messageReceived(QString)));
- connect(client, SIGNAL(disconnected()),
- SLOT(clientDisconnected()));
- m_clients << client;
- }
-}
-
-void QWebSocketTransportPrivate::init()
-{
- close();
-
- m_starting = false;
- if (m_useSecret) {
- m_secret = QUuid::createUuid().toString();
- // replace { by /
- m_secret[0] = QLatin1Char('/');
- // chop of trailing }
- m_secret.chop(1);
- }
-
- if (!listen(QHostAddress::LocalHost)) {
- emit failed(errorString());
- return;
- }
-
- m_baseUrl = QStringLiteral("127.0.0.1:%1%2").arg(serverPort()).arg(m_secret);
- emit initialized();
- emit baseUrlChanged(m_baseUrl);
-}
-
-void QWebSocketTransportPrivate::socketError()
-{
- emit failed(errorString());
-}
-
-void QWebSocketTransportPrivate::messageReceived(const QString &message)
-{
- if (m_messageHandler) {
- QWebSocket *client = qobject_cast<QWebSocket*>(sender());
- m_messageHandler->handleMessage(message, m_transport, m_clients.indexOf(client));
- }
- emit textDataReceived(message);
-}
-
-void QWebSocketTransportPrivate::clientDisconnected()
-{
- QWebSocket *client = qobject_cast<QWebSocket*>(sender());
- if (!client) {
- return;
- }
- const int idx = m_clients.indexOf(client);
- Q_ASSERT(idx != -1);
- m_clients.remove(idx);
- client->deleteLater();
-}
-
-//END QWebSocketTransportPrivate
-
-QWebSocketTransport::QWebSocketTransport(QObject *parent)
- : QObject(parent)
- , d(new QWebSocketTransportPrivate(this))
-{
- connect(d.data(), SIGNAL(textDataReceived(QString)),
- SIGNAL(messageReceived(QString)));
- connect(d.data(), SIGNAL(failed(QString)),
- SIGNAL(failed(QString)));
- connect(d.data(), SIGNAL(initialized()),
- SIGNAL(initialized()));
- connect(d.data(), SIGNAL(baseUrlChanged(QString)),
- SIGNAL(baseUrlChanged(QString)));
-
- d->initLater();
-}
-
-QWebSocketTransport::~QWebSocketTransport()
-{
-
-}
-
-void QWebSocketTransport::sendMessage(const QByteArray &message, int clientId) const
-{
- d->sendMessage(QString::fromUtf8(message), clientId);
-}
-
-void QWebSocketTransport::sendMessage(const QString &message, int clientId) const
-{
- d->sendMessage(message, clientId);
-}
-
-void QWebSocketTransport::setMessageHandler(QWebChannelMessageHandlerInterface *handler)
-{
- d->m_messageHandler = handler;
-}
-
-QString QWebSocketTransport::baseUrl() const
-{
- return d->m_baseUrl;
-}
-
-void QWebSocketTransport::setUseSecret(bool s)
-{
- if (d->m_useSecret == s)
- return;
- d->m_useSecret = s;
- d->initLater();
-}
-
-bool QWebSocketTransport::useSecret() const
-{
- return d->m_useSecret;
-}
diff --git a/src/webchannel/qwebsockettransport.h b/src/webchannel/qwebsockettransport.h
deleted file mode 100644
index b3e484f..0000000
--- a/src/webchannel/qwebsockettransport.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtWebChannel module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QWEBSOCKETTRANSPORT_H
-#define QWEBSOCKETTRANSPORT_H
-
-#include "qwebchanneltransportinterface.h"
-
-QT_BEGIN_NAMESPACE
-
-class QWebSocketTransportPrivate;
-class Q_WEBCHANNEL_EXPORT QWebSocketTransport : public QObject, public QWebChannelTransportInterface
-{
- Q_OBJECT
- Q_INTERFACES(QWebChannelTransportInterface)
- Q_PROPERTY(QString baseUrl READ baseUrl NOTIFY baseUrlChanged)
- Q_PROPERTY(bool useSecret READ useSecret WRITE setUseSecret)
-public:
- explicit QWebSocketTransport(QObject *parent = 0);
- ~QWebSocketTransport() Q_DECL_OVERRIDE;
-
- void sendMessage(const QByteArray &message, int clientId = -1) const Q_DECL_OVERRIDE;
- void sendMessage(const QString &message, int clientId = -1) const Q_DECL_OVERRIDE;
- void setMessageHandler(QWebChannelMessageHandlerInterface *handler) Q_DECL_OVERRIDE;
-
- QString baseUrl() const;
-
- void setUseSecret(bool);
- bool useSecret() const;
-
-Q_SIGNALS:
- void baseUrlChanged(const QString &baseUrl);
- void failed(const QString &reason);
- void initialized();
- void messageReceived(const QString &message);
-
-private:
- QScopedPointer<QWebSocketTransportPrivate> d;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWEBSOCKETTRANSPORT_H
diff --git a/src/webchannel/webchannel.pro b/src/webchannel/webchannel.pro
index c6e6d69..a50beaa 100644
--- a/src/webchannel/webchannel.pro
+++ b/src/webchannel/webchannel.pro
@@ -12,20 +12,20 @@ OTHER_FILES = \
PUBLIC_HEADERS += \
qwebchannel.h \
- qwebchanneltransport.h \
- qwebsockettransport.h
+ qwebchannelabstracttransport.h \
+ qwebchannelwebsockettransport.h
PRIVATE_HEADERS += \
qwebchannel_p.h \
qmetaobjectpublisher_p.h \
- qwebsockettransport_p.h \
variantargument_p.h \
signalhandler_p.h
SOURCES += \
qwebchannel.cpp \
qmetaobjectpublisher.cpp \
- qwebsockettransport.cpp
+ qwebchannelabstracttransport.cpp \
+ qwebchannelwebsockettransport.cpp
qtHaveModule(qml) {
QT += qml
diff --git a/sync.profile b/sync.profile
index 5d7cd6b..f0e6c33 100644
--- a/sync.profile
+++ b/sync.profile
@@ -15,7 +15,4 @@
"qtwebsockets" => "refs/heads/dev",
# optional dependencies:
"qtdeclarative" => "refs/heads/dev",
- # TODO: disabled for now as it breaks CI builds on OSX
- # requires changes to qtqa scripts as discussed with sifalt, sahumada, tronical
- # "qtwebkit" => "",
);
diff --git a/tests/auto/qml/WebChannelTest.qml b/tests/auto/qml/Client.qml
index 9a0baa9..609fbac 100644
--- a/tests/auto/qml/WebChannelTest.qml
+++ b/tests/auto/qml/Client.qml
@@ -43,77 +43,86 @@ import QtQuick 2.0
import QtTest 1.0
import QtWebChannel 1.0
+import QtWebChannel.Tests 1.0
+import "qrc:///qwebchannel/qwebchannel.js" as Client
-TestCase {
- property var lastLoadStatus
- property bool useWebViewTransport: false
+Item {
+ TestTransport {
+ id: serverTransport
+ }
+ readonly property var serverTransport: serverTransport
- // only run after the webchannel has finished initialization
- when: webSocketTransport.baseUrl != ""
+ property var clientMessages: []
- WebViewTransport {
- id: webViewTransport
- webViewExperimental: defaultView.experimental
- }
- WebSocketTransport {
- id: webSocketTransport
- }
+ property bool debug: false
- TestWebView {
- id: defaultView
- }
+ QtObject {
+ id: clientTransport
+
+ property var send;
+ property var onmessage;
- WebChannel {
- id: webChannel
+ function postMessage(message)
+ {
+ if (debug) {
+ console.log("client posts message: ", message);
+ }
+ clientMessages.push(message);
+ serverTransport.textMessageReceived(message);
+ }
+
+ Component.onCompleted: {
+ serverTransport.sendTextMessageRequested.connect(function(message) {
+ if (debug) {
+ console.log("client received message: ", message);
+ }
+ onmessage({data:message});
+ });
+ }
}
- property var webChannel: webChannel
+ readonly property var clientTransport: clientTransport
+
+ Timer {
+ id: timer
+ running: false
+ repeat: false
- SignalSpy {
- id: rawMessageSpy
- target: useWebViewTransport ? webViewTransport : webSocketTransport;
- signalName: "onMessageReceived"
+ property var callback
+
+ onTriggered: {
+ callback();
+ }
}
- property var rawMessageSpy: rawMessageSpy
- property var rawMessageIdx: 0;
- function urlForFile(file)
+ function setTimeout(callback, delay)
{
- verify(useWebViewTransport || webSocketTransport.baseUrl != "", "webSocketTransport.baseUrl is empty");
- return "data/" + file + (!useWebViewTransport ? "?webChannelBaseUrl=" + webSocketTransport.baseUrl : "");
+ if (timer.running) {
+ console.error("nested calls to setTimeout are not supported!", JSON.stringify(callback), JSON.stringify(timer.callback));
+ return;
+ }
+ timer.callback = callback;
+ // note: an interval of 0 is directly triggered, so add a little padding
+ timer.interval = delay + 1;
+ timer.running = true;
}
- // load file in the given view or use the global one by default
- function loadUrl(file, view)
+ function createChannel(callback, raw)
{
- if (useWebViewTransport) {
- webChannel.disconnectFrom(webSocketTransport);
- webChannel.connectTo(webViewTransport);
- } else {
- webChannel.disconnectFrom(webViewTransport);
- webChannel.connectTo(webSocketTransport);
- }
- if (!view) {
- view = defaultView;
- }
- view.url = urlForFile(file);
- view.waitForLoaded();
+ return new Client.QWebChannel(clientTransport, callback, raw);
}
function cleanup()
{
- defaultView.clear();
- rawMessageSpy.clear();
- rawMessageIdx = 0;
+ clientMessages = [];
+ timer.running = false;
}
function awaitRawMessage()
{
- rawMessageSpy.wait(500);
- if (rawMessageSpy.signalArguments.length <= rawMessageIdx) {
- // still no message received, fail
- return null;
+ for (var i = 0; i < 10 && !clientMessages.length; ++i) {
+ wait(10);
}
- return rawMessageSpy.signalArguments[rawMessageIdx++][0];
+ return clientMessages.shift();
}
function awaitMessage()
@@ -131,7 +140,7 @@ TestCase {
verify(msg);
verify(msg.data);
verify(msg.data.type);
- compare(msg.data.type, qWebChannelMessageTypes.init);
+ compare(msg.data.type, Client.QWebChannelMessageTypes.init);
}
function awaitIdle()
@@ -139,19 +148,19 @@ TestCase {
var msg = awaitMessage();
verify(msg);
verify(msg.data);
- compare(msg.data.type, qWebChannelMessageTypes.idle);
+ compare(msg.data.type, Client.QWebChannelMessageTypes.idle);
verify(webChannel.test_clientIsIdle())
}
- property var qWebChannelMessageTypes: ({
- signal: 1,
- propertyUpdate: 2,
- init: 3,
- idle: 4,
- debug: 5,
- invokeMethod: 6,
- connectToSignal: 7,
- disconnectFromSignal: 8,
- setProperty: 9,
- });
+ function awaitMessageSkipIdle()
+ {
+ var msg;
+ do {
+ msg = awaitMessage();
+ verify(msg);
+ verify(msg.data);
+ } while (msg.data.type === Client.QWebChannelMessageTypes.idle);
+ return msg;
+ }
+
}
diff --git a/tests/auto/qml/data/bench_init.html b/tests/auto/qml/data/bench_init.html
deleted file mode 100644
index 7d3af5b..0000000
--- a/tests/auto/qml/data/bench_init.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {});
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/disconnect.html b/tests/auto/qml/data/disconnect.html
deleted file mode 100644
index a9a479c..0000000
--- a/tests/auto/qml/data/disconnect.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- myObj.mySignal.connect(function(arg) {
- channel.exec({label: "mySignalReceived", args: [arg]});
- myObj.mySignal.disconnect(this);
- });
- channel.subscribe("report", function() {
- channel.exec({label: "report"});
- });
- });
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/grouping.html b/tests/auto/qml/data/grouping.html
deleted file mode 100644
index f6bc33c..0000000
--- a/tests/auto/qml/data/grouping.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- window.channel = createWebChannel(function(channel) {
- channel.subscribe(QWebChannelMessageTypes.propertyUpdate, function() {
- channel.exec({label: "gotPropertyUpdate", values: [myObj.myProperty, myOtherObj.foo, myOtherObj.bar]});
- });
- });
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/method.html b/tests/auto/qml/data/method.html
deleted file mode 100644
index 6dbaa90..0000000
--- a/tests/auto/qml/data/method.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- channel.subscribe("invokeMethod", function(arg) {
- myObj.myMethod(arg);
- });
- });
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/multiclient.html b/tests/auto/qml/data/multiclient.html
deleted file mode 100644
index 1573a1a..0000000
--- a/tests/auto/qml/data/multiclient.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- foo.ping.connect(function() {
- foo.pong(function(value) {
- channel.exec({pongAnswer: value});
- });
- });
- });
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/property.html b/tests/auto/qml/data/property.html
deleted file mode 100644
index 49b3811..0000000
--- a/tests/auto/qml/data/property.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- channel.exec({label: "init", value: myObj.myProperty});
- myObj.myPropertyChanged.connect(function() {
- channel.exec({label: "changed", value: myObj.myProperty});
- });
- channel.subscribe("setProperty", function(newValue) {
- myObj.myProperty = newValue;
- });
- });
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/receiveRaw.html b/tests/auto/qml/data/receiveRaw.html
deleted file mode 100644
index 139b2b1..0000000
--- a/tests/auto/qml/data/receiveRaw.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- channel.send("foobar");
- }, true /* raw */);
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/send.html b/tests/auto/qml/data/send.html
deleted file mode 100644
index c60fbf4..0000000
--- a/tests/auto/qml/data/send.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- channel.subscribe("myMessage", function(payload) {
- channel.send("myMessagePong:" + payload);
- });
- }, true /* raw */);
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/signal.html b/tests/auto/qml/data/signal.html
deleted file mode 100644
index bdce0c7..0000000
--- a/tests/auto/qml/data/signal.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- myObj.mySignal.connect(function(arg) {
- channel.exec({label: "signalReceived", value: arg});
- });
- });
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/data/wrapper.html b/tests/auto/qml/data/wrapper.html
deleted file mode 100644
index df368ee..0000000
--- a/tests/auto/qml/data/wrapper.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
- <head>
- <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script>
- <script type="text/javascript" src="testsetup.js"></script>
- <script type="text/javascript">
- //BEGIN SETUP
- createWebChannel(function(channel) {
- myFactory.create("testObj", function(obj) {
- window[obj.objectName] = obj;
- obj.mySignal.connect(function(arg1, arg2) {
- channel.exec({label: "signalReceived", args: [arg1, arg2]});
- });
- obj.myProperty = 42;
- obj.myMethod("foobar");
- });
- channel.subscribe("triggerDelete", function() {
- testObj.deleteLater();
- });
- channel.subscribe("report", function() {
- channel.exec({label:"report", obj: testObj})
- });
- });
- //END SETUP
- </script>
- </head>
- <body>
- </body>
-</html>
diff --git a/tests/auto/qml/qml.cpp b/tests/auto/qml/qml.cpp
index 7267842..0612bdb 100644
--- a/tests/auto/qml/qml.cpp
+++ b/tests/auto/qml/qml.cpp
@@ -40,5 +40,17 @@
****************************************************************************/
#include <QtQuickTest/quicktest.h>
+#include <QtQml/qqml.h>
-QUICK_TEST_MAIN(qml)
+#ifndef QUICK_TEST_SOURCE_DIR
+#define QUICK_TEST_SOURCE_DIR Q_NULLPTR
+#endif
+
+#include "testtransport.h"
+
+int main(int argc, char **argv)
+{
+ qmlRegisterType<TestTransport>("QtWebChannel.Tests", 1, 0, "TestTransport");
+
+ return quick_test_main(argc, argv, "qml", QUICK_TEST_SOURCE_DIR);
+}
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index f86dc90..ddef2cb 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -8,7 +8,11 @@ CONFIG += warn_on qmltestcase
IMPORTPATH += $$OUT_PWD/../../../qml $$PWD
SOURCES += \
- qml.cpp
+ qml.cpp \
+ testtransport.cpp
+
+HEADERS += \
+ testtransport.h
OTHER_FILES += \
WebChannelTest.qml \
diff --git a/tests/auto/qml/testtransport.cpp b/tests/auto/qml/testtransport.cpp
new file mode 100644
index 0000000..a332955
--- /dev/null
+++ b/tests/auto/qml/testtransport.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebChannel module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "testtransport.h"
+
+QT_BEGIN_NAMESPACE
+
+TestTransport::TestTransport(QObject *parent)
+: QWebChannelAbstractTransport(parent)
+{
+
+}
+
+void TestTransport::sendTextMessage(const QString &message)
+{
+ emit sendTextMessageRequested(message);
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/webchannel/qmlwebviewtransport.h b/tests/auto/qml/testtransport.h
index 8fbfdd9..dd07832 100644
--- a/src/imports/webchannel/qmlwebviewtransport.h
+++ b/tests/auto/qml/testtransport.h
@@ -39,41 +39,25 @@
**
****************************************************************************/
-#ifndef QMLWEBVIEWTRANSPORT_H
-#define QMLWEBVIEWTRANSPORT_H
+#ifndef TESTTRANSPORT_H
+#define TESTTRANSPORT_H
-#include <qwebchanneltransportinterface.h>
+#include <QtWebChannel/QWebChannelAbstractTransport>
QT_BEGIN_NAMESPACE
-class QmlWebViewTransport : public QObject, public QWebChannelTransportInterface
+class TestTransport : public QWebChannelAbstractTransport
{
Q_OBJECT
- Q_INTERFACES(QWebChannelTransportInterface)
- Q_PROPERTY(QObject *webViewExperimental READ webViewExperimental WRITE setWebViewExperimental NOTIFY webViewChanged)
public:
- explicit QmlWebViewTransport(QObject *parent = 0);
- ~QmlWebViewTransport() Q_DECL_OVERRIDE;
+ explicit TestTransport(QObject *parent = 0);
- void sendMessage(const QString &message, int clientId) const Q_DECL_OVERRIDE;
- void sendMessage(const QByteArray &message, int clientId) const Q_DECL_OVERRIDE;
- void setMessageHandler(QWebChannelMessageHandlerInterface *handler) Q_DECL_OVERRIDE;
-
- void setWebViewExperimental(QObject *webViewExperimental);
- QObject *webViewExperimental() const;
+ virtual void sendTextMessage(const QString &message);
Q_SIGNALS:
- void webViewChanged(QObject *webViewExperimental);
- void messageReceived(const QString &message);
-
-private Q_SLOTS:
- void handleWebViewMessage(const QVariantMap &message);
-
-private:
- QObject *m_webViewExperimental;
- QWebChannelMessageHandlerInterface *m_handler;
+ void sendTextMessageRequested(const QString &message);
};
QT_END_NAMESPACE
-#endif // QMLWEBVIEWTRANSPORT_H
+#endif // TESTTRANSPORT_H
diff --git a/tests/auto/qml/tst_bench.qml b/tests/auto/qml/tst_bench.qml
index 056dda9..833720e 100644
--- a/tests/auto/qml/tst_bench.qml
+++ b/tests/auto/qml/tst_bench.qml
@@ -40,13 +40,24 @@
****************************************************************************/
import QtQuick 2.0
+import QtTest 1.0
import QtWebChannel 1.0
+import "qrc:///qwebchannel/qwebchannel.js" as Client
-WebChannelTest {
+TestCase {
name: "Bench"
id: test
+ Client {
+ id: client
+ }
+
+ WebChannel {
+ id: webChannel
+ transports: [client.serverTransport]
+ }
+
Component {
id: component
QtObject {
@@ -96,28 +107,15 @@ WebChannelTest {
webChannel.registerObjects(objects);
}
- function benchmark_init_baseline()
- {
- loadUrl("bench_init.html");
- }
-
- function benchmark_init_webview()
+ function cleanup()
{
- useWebViewTransport = true;
- loadUrl("bench_init.html");
- // init
- awaitMessage();
- // idle
- awaitMessage();
+ client.cleanup();
}
- function benchmark_init_websocket()
+ function benchmark_init()
{
- useWebViewTransport = false;
- loadUrl("bench_init.html");
- // init
- awaitMessage();
- // idle
- awaitMessage();
+ var channel = client.createChannel(function() {});
+ client.awaitInit();
+ client.awaitIdle();
}
}
diff --git a/tests/auto/qml/tst_metaobjectpublisher.qml b/tests/auto/qml/tst_metaobjectpublisher.qml
index e07f105..880b30d 100644
--- a/tests/auto/qml/tst_metaobjectpublisher.qml
+++ b/tests/auto/qml/tst_metaobjectpublisher.qml
@@ -40,12 +40,17 @@
****************************************************************************/
import QtQuick 2.0
+import QtTest 1.0
import QtWebChannel 1.0
+import "qrc:///qwebchannel/qwebchannel.js" as Client
-WebChannelTest {
+TestCase {
name: "MetaObjectPublisher"
- id: test
+
+ Client {
+ id: client
+ }
property var lastMethodArg
@@ -90,62 +95,71 @@ WebChannelTest {
}
}
- function initTestCase()
- {
- webChannel.registeredObjects = [myObj, myOtherObj, myFactory];
+ WebChannel {
+ id: webChannel
+ transports: [client.serverTransport]
+ registeredObjects: [myObj, myOtherObj, myFactory]
}
- function awaitMessageSkipIdle()
+ function init()
{
- var msg;
- do {
- msg = awaitMessage();
- verify(msg);
- verify(msg.data);
- } while (msg.data.type === qWebChannelMessageTypes.idle);
- return msg;
+ myObj.myProperty = 1
+ client.cleanup();
}
function test_property()
{
- myObj.myProperty = 1
- loadUrl("property.html");
- awaitInit();
- var msg = awaitMessageSkipIdle();
+ var channel = client.createChannel(function(channel) {
+ channel.exec({label: "init", value: channel.objects.myObj.myProperty});
+ channel.objects.myObj.myPropertyChanged.connect(function() {
+ channel.exec({label: "changed", value: channel.objects.myObj.myProperty});
+ });
+ channel.subscribe("setProperty", function(newValue) {
+ channel.objects.myObj.myProperty = newValue;
+ });
+ });
+
+ client.awaitInit();
+ var msg = client.awaitMessageSkipIdle();
compare(msg.data.label, "init");
compare(msg.data.value, 1);
compare(myObj.myProperty, 1);
// change property, should be propagated to HTML client and a message be send there
myObj.myProperty = 2;
- msg = awaitMessageSkipIdle();
+ msg = client.awaitMessageSkipIdle();
compare(msg.data.label, "changed");
compare(msg.data.value, 2);
compare(myObj.myProperty, 2);
// now trigger a write from the client side
webChannel.sendMessage("setProperty", 3);
- msg = awaitMessageSkipIdle();
+ msg = client.awaitMessageSkipIdle();
compare(myObj.myProperty, 3);
// the above write is also propagated to the HTML client
- msg = awaitMessageSkipIdle();
+ msg = client.awaitMessageSkipIdle();
compare(msg.data.label, "changed");
compare(msg.data.value, 3);
- awaitIdle();
+ client.awaitIdle();
}
function test_method()
{
- loadUrl("method.html");
- awaitInit();
- awaitIdle();
+ var channel = client.createChannel(function (channel) {
+ channel.subscribe("invokeMethod", function (arg) {
+ channel.objects.myObj.myMethod(arg);
+ });
+ });
+
+ client.awaitInit();
+ client.awaitIdle();
webChannel.sendMessage("invokeMethod", "test");
- var msg = awaitMessage();
- compare(msg.data.type, qWebChannelMessageTypes.invokeMethod);
+ var msg = client.awaitMessage();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.invokeMethod);
compare(msg.data.object, "myObj");
compare(msg.data.args, ["test"]);
@@ -154,27 +168,35 @@ WebChannelTest {
function test_signal()
{
- loadUrl("signal.html");
- awaitInit();
-
- var msg = awaitMessage();
- compare(msg.data.type, qWebChannelMessageTypes.connectToSignal);
+ var channel = client.createChannel(function(channel) {
+ channel.objects.myObj.mySignal.connect(function(arg) {
+ channel.exec({label: "signalReceived", value: arg});
+ });
+ });
+ client.awaitInit();
+
+ var msg = client.awaitMessage();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.connectToSignal);
compare(msg.data.object, "myObj");
- awaitIdle();
+ client.awaitIdle();
myObj.mySignal("test");
- msg = awaitMessage();
+ msg = client.awaitMessageSkipIdle();
compare(msg.data.label, "signalReceived");
compare(msg.data.value, "test");
}
function test_grouping()
{
- loadUrl("grouping.html");
- awaitInit();
- awaitIdle();
+ var channel = client.createChannel(function(channel) {
+ channel.subscribe(Client.QWebChannelMessageTypes.propertyUpdate, function() {
+ channel.exec({label: "gotPropertyUpdate", values: [channel.objects.myObj.myProperty, channel.objects.myOtherObj.foo, channel.objects.myOtherObj.bar]});
+ });
+ });
+ client.awaitInit();
+ client.awaitIdle();
// change properties a lot, we expect this to be grouped into a single update notification
for (var i = 0; i < 10; ++i) {
@@ -183,81 +205,106 @@ WebChannelTest {
myOtherObj.bar = i;
}
- var msg = awaitMessage();
+ var msg = client.awaitMessage();
verify(msg);
compare(msg.data.label, "gotPropertyUpdate");
compare(msg.data.values, [myObj.myProperty, myOtherObj.foo, myOtherObj.bar]);
- awaitIdle();
+ client.awaitIdle();
}
function test_wrapper()
{
- loadUrl("wrapper.html");
- awaitInit();
-
- var msg = awaitMessageSkipIdle();
- compare(msg.data.type, qWebChannelMessageTypes.invokeMethod);
+ var channel = client.createChannel(function(channel) {
+ channel.objects.myFactory.create("testObj", function(obj) {
+ channel.objects["testObj"] = obj;
+ obj.mySignal.connect(function(arg1, arg2) {
+ channel.exec({label: "signalReceived", args: [arg1, arg2]});
+ });
+ obj.myProperty = 42;
+ obj.myMethod("foobar");
+ });
+ channel.subscribe("triggerDelete", function() {
+ channel.objects.testObj.deleteLater();
+ });
+ channel.subscribe("report", function() {
+ channel.exec({label:"report", obj: channel.objects.testObj})
+ });
+ });
+ client.awaitInit();
+
+ var msg = client.awaitMessageSkipIdle();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.invokeMethod);
compare(msg.data.object, "myFactory");
verify(myFactory.lastObj);
compare(myFactory.lastObj.objectName, "testObj");
- msg = awaitMessageSkipIdle();
- compare(msg.data.type, qWebChannelMessageTypes.connectToSignal);
+ msg = client.awaitMessageSkipIdle();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.connectToSignal);
verify(msg.data.object);
var objId = msg.data.object;
- msg = awaitMessageSkipIdle();
- compare(msg.data.type, qWebChannelMessageTypes.connectToSignal);
+ msg = client.awaitMessageSkipIdle();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.connectToSignal);
compare(msg.data.object, objId);
- msg = awaitMessageSkipIdle();
- compare(msg.data.type, qWebChannelMessageTypes.setProperty);
+ msg = client.awaitMessageSkipIdle();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.setProperty);
compare(msg.data.object, objId);
compare(myFactory.lastObj.myProperty, 42);
- msg = awaitMessageSkipIdle();
- compare(msg.data.type, qWebChannelMessageTypes.invokeMethod);
+ msg = client.awaitMessageSkipIdle();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.invokeMethod);
compare(msg.data.object, objId);
compare(msg.data.args, ["foobar"]);
- msg = awaitMessageSkipIdle();
+ msg = client.awaitMessageSkipIdle();
compare(msg.data.label, "signalReceived");
compare(msg.data.args, ["foobar", 42]);
// pass QObject* on the fly and trigger deleteLater from client side
webChannel.sendMessage("triggerDelete");
- msg = awaitMessageSkipIdle();
- compare(msg.data.type, qWebChannelMessageTypes.invokeMethod);
+ msg = client.awaitMessageSkipIdle();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.invokeMethod);
compare(msg.data.object, objId);
+ client.awaitIdle();
+
webChannel.sendMessage("report");
- msg = awaitMessageSkipIdle();
+ msg = client.awaitMessageSkipIdle();
compare(msg.data.label, "report");
compare(msg.data.obj, {});
}
function test_disconnect()
{
- loadUrl("disconnect.html");
- awaitInit();
-
- var msg = awaitMessage();
- compare(msg.data.type, qWebChannelMessageTypes.connectToSignal);
+ var channel = client.createChannel(function(channel) {
+ channel.objects.myObj.mySignal.connect(function(arg) {
+ channel.exec({label: "mySignalReceived", args: [arg]});
+ channel.objects.myObj.mySignal.disconnect(this);
+ });
+ channel.subscribe("report", function() {
+ channel.exec({label: "report"});
+ });
+ });
+ client.awaitInit();
+
+ var msg = client.awaitMessage();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.connectToSignal);
compare(msg.data.object, "myObj");
- awaitIdle();
+ client.awaitIdle();
myObj.mySignal(42);
- msg = awaitMessage();
+ msg = client.awaitMessage();
compare(msg.data.label, "mySignalReceived");
compare(msg.data.args, [42]);
- msg = awaitMessage();
- compare(msg.data.type, qWebChannelMessageTypes.disconnectFromSignal);
+ msg = client.awaitMessage();
+ compare(msg.data.type, Client.QWebChannelMessageTypes.disconnectFromSignal);
compare(msg.data.object, "myObj");
myObj.mySignal(0);
@@ -266,7 +313,7 @@ WebChannelTest {
// and verify no mySignalReceived was triggered by the above emission
webChannel.sendMessage("report");
- msg = awaitMessage();
+ msg = client.awaitMessage();
compare(msg.data.label, "report");
}
}
diff --git a/tests/auto/qml/tst_multiclient.qml b/tests/auto/qml/tst_multiclient.qml
index 519a63c..6c4b9b7 100644
--- a/tests/auto/qml/tst_multiclient.qml
+++ b/tests/auto/qml/tst_multiclient.qml
@@ -40,12 +40,21 @@
****************************************************************************/
import QtQuick 2.0
+import QtTest 1.0
import QtWebChannel 1.0
+import "qrc:///qwebchannel/qwebchannel.js" as Client
-WebChannelTest {
+TestCase {
name: "MultiClient"
- id: test
+
+ Client {
+ id: client1
+ }
+
+ Client {
+ id: client2
+ }
QtObject {
id: foo
@@ -61,39 +70,50 @@ WebChannelTest {
WebChannel.id: "foo"
}
- TestWebView {
- id: client1
+ WebChannel {
+ id: webChannel
+ transports: [client1.serverTransport, client2.serverTransport]
+ registeredObjects: [foo]
}
- TestWebView {
- id: client2
+
+ function init()
+ {
+ client1.cleanup();
+ client2.cleanup();
}
- function initTestCase()
+ function clientInitCallback(channel)
{
- webChannel.registeredObjects = [foo];
+ channel.objects.foo.ping.connect(function() {
+ channel.objects.foo.pong(function(value) {
+ channel.exec({pongAnswer: value});
+ });
+ });
}
function test_multiclient()
{
- loadUrl("multiclient.html", client1);
- loadUrl("multiclient.html", client2);
+ var c1 = client1.createChannel(clientInitCallback);
+ var c2 = client2.createChannel(clientInitCallback);
+
// init, connect & idle messages for two clients
- for (var i = 0; i < 3 * 2; ++i) {
- awaitMessage();
+ for (var i = 0; i < 3; ++i) {
+ client1.awaitMessage();
+ client2.awaitMessage();
}
foo.ping();
// invoke of pong method
- awaitMessage();
- awaitMessage();
+ client1.awaitMessage();
+ client2.awaitMessage();
- var msg = awaitMessage();
+ var msg = client1.awaitMessage();
compare(msg.data.pongAnswer, 1);
- msg = awaitMessage();
+ msg = client2.awaitMessage();
compare(msg.data.pongAnswer, 2);
- awaitIdle();
- awaitIdle();
+ client1.awaitIdle();
+ client2.awaitIdle();
}
}
diff --git a/tests/auto/qml/tst_webchannel.qml b/tests/auto/qml/tst_webchannel.qml
index dddba71..3c404d3 100644
--- a/tests/auto/qml/tst_webchannel.qml
+++ b/tests/auto/qml/tst_webchannel.qml
@@ -40,20 +40,47 @@
****************************************************************************/
import QtQuick 2.0
+import QtTest 1.0
-WebChannelTest {
+import QtWebChannel 1.0
+import "qrc:///qwebchannel/qwebchannel.js" as Client
+
+TestCase {
name: "WebChannel"
+ Client {
+ id: client
+ }
+
+ WebChannel {
+ id: webChannel
+ transports: [client.serverTransport]
+ }
+
+ function cleanup()
+ {
+ client.cleanup();
+ }
+
function test_receiveRawMessage()
{
- loadUrl("receiveRaw.html");
- compare(awaitRawMessage(), "foobar");
+ var channel = client.createChannel(function (channel) {
+ channel.send("foobar");
+ }, true /* raw */);
+ compare(client.awaitRawMessage(), "foobar");
}
function test_sendMessage()
{
- loadUrl("send.html");
+ var channel = client.createChannel(function (channel) {
+ channel.subscribe("myMessage", function(payload) {
+ channel.send("myMessagePong:" + payload);
+ });
+ channel.send("initialized");
+ }, true /* raw */);
+
+ compare(client.awaitRawMessage(), "initialized");
webChannel.sendMessage("myMessage", "foobar");
- compare(awaitRawMessage(), "myMessagePong:foobar");
+ compare(client.awaitRawMessage(), "myMessagePong:foobar");
}
}
diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp
index ece02a8..10baaa3 100644
--- a/tests/auto/webchannel/tst_webchannel.cpp
+++ b/tests/auto/webchannel/tst_webchannel.cpp
@@ -44,7 +44,6 @@
#include <qwebchannel.h>
#include <qwebchannel_p.h>
#include <qmetaobjectpublisher_p.h>
-#include <qwebsockettransport.h>
#include <QtTest>
@@ -76,20 +75,6 @@ void TestWebChannel::setVariant(const QVariant &v)
m_lastVariant = v;
}
-void TestWebChannel::testInitWebSocketTransport()
-{
- QWebSocketTransport transport;
- QSignalSpy initSpy(&transport, SIGNAL(initialized()));
- QSignalSpy baseUrlSpy(&transport, SIGNAL(baseUrlChanged(QString)));
-
- QVERIFY(initSpy.wait());
- QCOMPARE(initSpy.size(), 1);
- QCOMPARE(baseUrlSpy.size(), 1);
- QCOMPARE(baseUrlSpy.first().size(), 1);
- QCOMPARE(transport.baseUrl(), baseUrlSpy.first().first().toString());
- QVERIFY(!transport.baseUrl().isEmpty());
-}
-
void TestWebChannel::testRegisterObjects()
{
QWebChannel channel;
diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h
index 314fe99..4811a5c 100644
--- a/tests/auto/webchannel/tst_webchannel.h
+++ b/tests/auto/webchannel/tst_webchannel.h
@@ -44,24 +44,22 @@
#include <QObject>
#include <QVariant>
-#include <qwebchanneltransportinterface.h>
-class DummyTransport : public QObject, public QWebChannelTransportInterface
+#include <QtWebChannel/QWebChannelAbstractTransport>
+
+class DummyTransport : public QWebChannelAbstractTransport
{
Q_OBJECT
- Q_INTERFACES(QWebChannelTransportInterface)
public:
explicit DummyTransport(QObject *parent)
- : QObject(parent)
+ : QWebChannelAbstractTransport(parent)
{}
~DummyTransport() {};
- void sendMessage(const QString &/*message*/, int /*clientId*/) const Q_DECL_OVERRIDE
- {}
- void sendMessage(const QByteArray &/*message*/, int /*clientId*/) const Q_DECL_OVERRIDE
- {}
- void setMessageHandler(QWebChannelMessageHandlerInterface * /*handler*/) Q_DECL_OVERRIDE
- {}
+public slots:
+ void sendTextMessage(const QString &/*message*/) Q_DECL_OVERRIDE
+ {
+ }
};
class TestObject : public QObject
@@ -216,7 +214,6 @@ public:
Q_INVOKABLE void setVariant(const QVariant &v);
private slots:
- void testInitWebSocketTransport();
void testRegisterObjects();
void testInfoForObject();
void testInvokeMethodConversion();