summaryrefslogtreecommitdiff
path: root/src/imports
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2014-01-10 14:21:05 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-06 16:32:20 +0100
commit54f66cc7a1e17155e90a1d3b5c33f627dbd0d50f (patch)
tree6dd4b35eda74487977bfae5bb0b81a133dfc1bf4 /src/imports
parent05bafd509ca302fc63465fece7cd0c33ec602e31 (diff)
downloadqtwebchannel-54f66cc7a1e17155e90a1d3b5c33f627dbd0d50f.tar.gz
Make the underlying transport mechanism of the webchannel pluggable.
This enables us to optionally use navigator.qt instead of a WebSocket, which is nicer setup-wise and is also slightly faster: navigator.qt: 284.0 msecs per iteration (total: 2,840, iterations: 10) WebSocket: 295.8 msecs per iteration (total: 2,959, iterations: 10) The baseline is ca. 203 msecs, which would mean a performance boost of ca. 12.7%. Furthermore, this sets the fundation to eventually add a WebEngine transport mechanism. The WebViewTransport should also be removed and instead the WebView itself should directly implement the WebChannelTransportInterface. Change-Id: I368bb27e38ffa2f17ffeb7f5ae695690f6f5ad21 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/imports')
-rw-r--r--src/imports/webchannel/plugin.cpp10
-rw-r--r--src/imports/webchannel/qmlwebchannel.cpp66
-rw-r--r--src/imports/webchannel/qmlwebchannel.h18
-rw-r--r--src/imports/webchannel/qmlwebviewtransport.cpp103
-rw-r--r--src/imports/webchannel/qmlwebviewtransport.h79
-rw-r--r--src/imports/webchannel/webchannel.pro6
6 files changed, 276 insertions, 6 deletions
diff --git a/src/imports/webchannel/plugin.cpp b/src/imports/webchannel/plugin.cpp
index 92aac79..589e3cb 100644
--- a/src/imports/webchannel/plugin.cpp
+++ b/src/imports/webchannel/plugin.cpp
@@ -43,6 +43,11 @@
#include <QtQml/QQmlExtensionPlugin>
#include "qmlwebchannel.h"
+#include "qwebsockettransport.h"
+#include "qmlwebviewtransport.h"
+#include "qwebchanneltransportinterface.h"
+
+QML_DECLARE_INTERFACE_HASMETATYPE(QWebChannelTransportInterface);
QT_BEGIN_NAMESPACE
@@ -57,10 +62,13 @@ 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/qmlwebchannel.cpp b/src/imports/webchannel/qmlwebchannel.cpp
index 7c70f5c..dc7398d 100644
--- a/src/imports/webchannel/qmlwebchannel.cpp
+++ b/src/imports/webchannel/qmlwebchannel.cpp
@@ -51,7 +51,6 @@ QT_USE_NAMESPACE
QmlWebChannel::QmlWebChannel(QObject *parent)
: QWebChannel(parent)
{
-
}
QmlWebChannel::~QmlWebChannel()
@@ -99,6 +98,37 @@ QmlWebChannelAttached *QmlWebChannel::qmlAttachedProperties(QObject *obj)
return new QmlWebChannelAttached(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);
+ } else {
+ qWarning() << "Cannot connect to transport" << transport << " - it does not implement the QWebChannelTransportInterface.";
+ }
+}
+
+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);
+ } 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);
+ }
+}
+
QQmlListProperty<QObject> QmlWebChannel::registeredObjects()
{
return QQmlListProperty<QObject>(this, 0,
@@ -144,3 +174,37 @@ void QmlWebChannel::registeredObjects_clear(QQmlListProperty<QObject> *prop)
}
return channel->m_registeredObjects.clear();
}
+
+QQmlListProperty<QWebChannelTransportInterface> QmlWebChannel::transports()
+{
+ return QQmlListProperty<QWebChannelTransportInterface>(this, 0,
+ transports_append,
+ transports_count,
+ transports_at,
+ transports_clear);
+}
+
+void QmlWebChannel::transports_append(QQmlListProperty<QWebChannelTransportInterface> *prop, QWebChannelTransportInterface *transport)
+{
+ QWebChannel *channel = static_cast<QWebChannel*>(prop->object);
+ channel->connectTo(transport);
+}
+
+int QmlWebChannel::transports_count(QQmlListProperty<QWebChannelTransportInterface> *prop)
+{
+ return static_cast<QmlWebChannel*>(prop->object)->d->transports.size();
+}
+
+QWebChannelTransportInterface *QmlWebChannel::transports_at(QQmlListProperty<QWebChannelTransportInterface> *prop, int index)
+{
+ return static_cast<QmlWebChannel*>(prop->object)->d->transports.at(index);
+}
+
+void QmlWebChannel::transports_clear(QQmlListProperty<QWebChannelTransportInterface> *prop)
+{
+ QWebChannel *channel = static_cast<QWebChannel*>(prop->object);
+ foreach (QWebChannelTransportInterface *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 bcbb9cf..c45796f 100644
--- a/src/imports/webchannel/qmlwebchannel.h
+++ b/src/imports/webchannel/qmlwebchannel.h
@@ -45,6 +45,7 @@
#include <qwebchannel.h>
#include "qmlwebchannelattached.h"
+#include "qwebchanneltransportinterface.h"
#include <QVector>
@@ -53,13 +54,13 @@
QT_BEGIN_NAMESPACE
-class QmlWebChannelAttached;
-
class QmlWebChannel : public QWebChannel
{
Q_OBJECT
+ Q_PROPERTY( QQmlListProperty<QWebChannelTransportInterface> connections READ transports );
Q_PROPERTY( QQmlListProperty<QObject> registeredObjects READ registeredObjects )
+
public:
QmlWebChannel(QObject *parent = 0);
virtual ~QmlWebChannel();
@@ -67,13 +68,19 @@ public:
Q_INVOKABLE void registerObjects(const QVariantMap& objects);
QQmlListProperty<QObject> registeredObjects();
+ QQmlListProperty<QWebChannelTransportInterface> transports();
+
// TODO: remove this by replacing QML with C++ tests
Q_INVOKABLE bool test_clientIsIdle() const;
static QmlWebChannelAttached* qmlAttachedProperties(QObject *obj);
+ Q_INVOKABLE void connectTo(QObject *transport);
+ Q_INVOKABLE void disconnectFrom(QObject *transport);
+
private slots:
void objectIdChanged(const QString &newId);
+ void transportDestroyed(QObject *transport);
private:
static void registeredObjects_append(QQmlListProperty<QObject> *prop, QObject* item);
@@ -81,7 +88,14 @@ 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);
+
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
new file mode 100644
index 0000000..7fb9d16
--- /dev/null
+++ b/src/imports/webchannel/qmlwebviewtransport.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** 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) 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) const
+{
+ sendMessage(QString::fromUtf8(message));
+}
+
+void QmlWebViewTransport::handleWebViewMessage(const QVariantMap &message)
+{
+ if (m_handler) {
+ const QString &data = message[QStringLiteral("data")].toString();
+ m_handler->handleMessage(data);
+ emit messageReceived(data);
+ }
+}
+
+void QmlWebViewTransport::setMessageHandler(QWebChannelMessageHandlerInterface *handler)
+{
+ m_handler = handler;
+}
diff --git a/src/imports/webchannel/qmlwebviewtransport.h b/src/imports/webchannel/qmlwebviewtransport.h
new file mode 100644
index 0000000..98dc504
--- /dev/null
+++ b/src/imports/webchannel/qmlwebviewtransport.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QMLWEBVIEWTRANSPORT_H
+#define QMLWEBVIEWTRANSPORT_H
+
+#include <qwebchanneltransportinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlWebViewTransport : public QObject, public QWebChannelTransportInterface
+{
+ 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;
+
+ void sendMessage(const QString &message) const Q_DECL_OVERRIDE;
+ void sendMessage(const QByteArray &message) const Q_DECL_OVERRIDE;
+ void setMessageHandler(QWebChannelMessageHandlerInterface *handler) Q_DECL_OVERRIDE;
+
+ void setWebViewExperimental(QObject *webViewExperimental);
+ QObject *webViewExperimental() const;
+
+signals:
+ void webViewChanged(QObject *webViewExperimental);
+ void messageReceived(const QString &message);
+
+private slots:
+ void handleWebViewMessage(const QVariantMap &message);
+
+private:
+ QObject *m_webViewExperimental;
+ QWebChannelMessageHandlerInterface *m_handler;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLWEBVIEWTRANSPORT_H
diff --git a/src/imports/webchannel/webchannel.pro b/src/imports/webchannel/webchannel.pro
index c1959f5..3042854 100644
--- a/src/imports/webchannel/webchannel.pro
+++ b/src/imports/webchannel/webchannel.pro
@@ -6,10 +6,12 @@ VPATH += ../../webchannel
SOURCES += \
plugin.cpp \
qmlwebchannel.cpp \
- qmlwebchannelattached.cpp
+ qmlwebchannelattached.cpp \
+ qmlwebviewtransport.cpp
HEADERS += \
qmlwebchannel.h \
- qmlwebchannelattached.h
+ qmlwebchannelattached.h \
+ qmlwebviewtransport.h
load(qml_plugin)