summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/WebKit2/Target.pri7
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp53
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h20
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h4
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport.cpp74
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport_p.h63
-rw-r--r--Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_webchannel.qml117
-rw-r--r--Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/webchannel.html21
-rw-r--r--Source/WebKit2/UIProcess/qt/QtWebContext.cpp15
-rw-r--r--Source/WebKit2/WebKit2.pri8
-rw-r--r--Source/WebKit2/WebProcess/qt/QtBuiltinBundle.cpp18
-rw-r--r--Source/WebKit2/WebProcess/qt/QtBuiltinBundle.h3
-rw-r--r--Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.cpp241
-rw-r--r--Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.h13
-rw-r--r--Source/sync.profile1
15 files changed, 579 insertions, 79 deletions
diff --git a/Source/WebKit2/Target.pri b/Source/WebKit2/Target.pri
index c4f57b0e0..a9179d971 100644
--- a/Source/WebKit2/Target.pri
+++ b/Source/WebKit2/Target.pri
@@ -860,6 +860,13 @@ have?(QTQUICK) {
SOURCES += \
UIProcess/qt/WebColorPickerQt.cpp
}
+
+ qtHaveModule(webchannel) {
+ SOURCES += \
+ UIProcess/API/qt/qwebchannelwebkittransport.cpp
+ HEADERS += \
+ UIProcess/API/qt/qwebchannelwebkittransport_p.h
+ }
}
mac: {
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
index a46b6972e..86b8cb4d4 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
@@ -84,6 +84,11 @@
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
+#ifdef HAVE_WEBCHANNEL
+#include <QtWebChannel/QQmlWebChannel>
+#include "qwebchannelwebkittransport_p.h"
+#endif
+
using namespace WebCore;
using namespace WebKit;
@@ -959,6 +964,14 @@ void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(WKStringRef me
emit q_ptr->experimental()->messageReceived(variantMap);
}
+#ifdef HAVE_WEBCHANNEL
+void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtWebChannelTransportObject(WKStringRef message)
+{
+ // TODO: can I convert a WKStringRef to a UTF8 QByteArray directly?
+ q_ptr->experimental()->m_webChannelTransport->receiveMessage(WKStringCopyQString(message).toUtf8());
+}
+#endif
+
CoordinatedGraphicsScene* QQuickWebViewPrivate::coordinatedGraphicsScene()
{
if (webPageProxy && webPageProxy->drawingArea() && webPageProxy->drawingArea()->coordinatedLayerTreeHostProxy())
@@ -1074,7 +1087,14 @@ QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView, QQu
, d_ptr(webViewPrivate)
, schemeParent(new QObject(this))
, m_test(new QWebKitTest(webViewPrivate, this))
+#ifdef HAVE_WEBCHANNEL
+ , m_webChannel(new QQmlWebChannel(this))
+ , m_webChannelTransport(new QWebChannelWebKitTransport(this))
+#endif
{
+#ifdef HAVE_WEBCHANNEL
+ m_webChannel->connectTo(m_webChannelTransport);
+#endif
}
QQuickWebViewExperimental::~QQuickWebViewExperimental()
@@ -1163,6 +1183,29 @@ bool QQuickWebViewExperimental::flickableViewportEnabled()
return s_flickableViewportEnabled;
}
+#ifdef HAVE_WEBCHANNEL
+QQmlWebChannel* QQuickWebViewExperimental::webChannel() const
+{
+ return m_webChannel;
+}
+
+void QQuickWebViewExperimental::setWebChannel(QQmlWebChannel* channel)
+{
+ if (channel == m_webChannel)
+ return;
+
+ if (m_webChannel)
+ m_webChannel->disconnectFrom(m_webChannelTransport);
+
+ m_webChannel = channel;
+
+ if (m_webChannel)
+ m_webChannel->connectTo(m_webChannelTransport);
+
+ emit webChannelChanged(channel);
+}
+#endif
+
/*!
\internal
@@ -1182,6 +1225,16 @@ void QQuickWebViewExperimental::postMessage(const QString& message)
WKPagePostMessageToInjectedBundle(d->webPage.get(), messageName, contents.get());
}
+#ifdef HAVE_WEBCHANNEL
+void QQuickWebViewExperimental::postQtWebChannelTransportMessage(const QByteArray& message)
+{
+ Q_D(QQuickWebView);
+ static WKStringRef messageName = WKStringCreateWithUTF8CString("MessageToNavigatorQtWebChannelTransportObject");
+ WKRetainPtr<WKStringRef> contents = adoptWK(WKStringCreateWithUTF8CString(message.constData()));
+ WKPagePostMessageToInjectedBundle(d->webPage.get(), messageName, contents.get());
+}
+#endif
+
QQmlComponent* QQuickWebViewExperimental::alertDialog() const
{
Q_D(const QQuickWebView);
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
index 86d68fc15..8604dead2 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
@@ -30,6 +30,7 @@
QT_BEGIN_NAMESPACE
class QQmlComponent;
+class QQmlWebChannel;
QT_END_NAMESPACE
class QWebNavigationRequest;
class QQuickWebPage;
@@ -43,6 +44,7 @@ class QWebPreferences;
class QWebPermissionRequest;
class QWebKitTest;
class QQuickNetworkReply;
+class QWebChannelWebKitTransport;
namespace WTR {
class PlatformWebView;
@@ -280,6 +282,9 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject {
Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent NOTIFY userAgentChanged)
Q_PROPERTY(QList<QUrl> userScripts READ userScripts WRITE setUserScripts NOTIFY userScriptsChanged)
Q_PROPERTY(QUrl remoteInspectorUrl READ remoteInspectorUrl NOTIFY remoteInspectorUrlChanged FINAL)
+#ifdef HAVE_WEBCHANNEL
+ Q_PROPERTY(QQmlWebChannel* webChannel READ webChannel WRITE setWebChannel NOTIFY webChannelChanged)
+#endif
Q_ENUMS(NavigationRequestActionExperimental)
Q_FLAGS(FindFlags)
@@ -357,6 +362,12 @@ public:
static void setFlickableViewportEnabled(bool enable);
static bool flickableViewportEnabled();
+#ifdef HAVE_WEBCHANNEL
+ QQmlWebChannel* webChannel() const;
+ void setWebChannel(QQmlWebChannel* channel);
+ void postQtWebChannelTransportMessage(const QByteArray& message);
+#endif
+
public Q_SLOTS:
void goBackTo(int index);
void goForwardTo(int index);
@@ -394,6 +405,10 @@ Q_SIGNALS:
void processDidBecomeUnresponsive();
void processDidBecomeResponsive();
+#ifdef HAVE_WEBCHANNEL
+ void webChannelChanged(QQmlWebChannel* channel);
+#endif
+
private:
QQuickWebViewExperimental(QQuickWebView* webView, QQuickWebViewPrivate* webViewPrivate);
QQuickWebView* q_ptr;
@@ -401,6 +416,11 @@ private:
QObject* schemeParent;
QWebKitTest* m_test;
+#ifdef HAVE_WEBCHANNEL
+ QQmlWebChannel* m_webChannel;
+ QWebChannelWebKitTransport* m_webChannelTransport;
+#endif
+
friend class WebKit::QtWebPageUIClient;
Q_DECLARE_PRIVATE(QQuickWebView)
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h
index b39a4f071..f09c16e90 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h
@@ -55,6 +55,7 @@ class WebPageProxy;
class QWebNavigationHistory;
class QWebKitTest;
+class QWebChannelWebKitTransport;
QT_BEGIN_NAMESPACE
class QQmlComponent;
@@ -137,6 +138,9 @@ public:
void handleDownloadRequest(WebKit::DownloadProxy*);
void didReceiveMessageFromNavigatorQtObject(WKStringRef message);
+#ifdef HAVE_WEBCHANNEL
+ void didReceiveMessageFromNavigatorQtWebChannelTransportObject(WKStringRef message);
+#endif
WebCore::CoordinatedGraphicsScene* coordinatedGraphicsScene();
float deviceScaleFactor();
diff --git a/Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport.cpp b/Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport.cpp
new file mode 100644
index 000000000..209596954
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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 "qwebchannelwebkittransport_p.h"
+
+#include <QJsonObject>
+#include <QJsonDocument>
+
+#include "qquickwebview_p.h"
+
+QWebChannelWebKitTransport::QWebChannelWebKitTransport(QQuickWebViewExperimental* experimental)
+ : QWebChannelAbstractTransport(experimental)
+ , m_experimental(experimental)
+{
+}
+
+void QWebChannelWebKitTransport::sendMessage(const QJsonObject& message)
+{
+ const QByteArray data = QJsonDocument(message).toJson(QJsonDocument::Compact);
+ m_experimental->postQtWebChannelTransportMessage(data);
+}
+
+void QWebChannelWebKitTransport::receiveMessage(const QByteArray& message)
+{
+ QJsonParseError error;
+ const QJsonDocument doc = QJsonDocument::fromJson(message, &error);
+ if (error.error != QJsonParseError::NoError) {
+ qWarning() << "Failed to parse the client WebKit QWebChannel message as JSON: " << message
+ << "Error message is:" << error.errorString();
+ return;
+ } else if (!doc.isObject()) {
+ qWarning() << "Received WebKit QWebChannel message is not a JSON object: " << message;
+ return;
+ }
+ emit messageReceived(doc.object(), this);
+}
diff --git a/Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport_p.h b/Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport_p.h
new file mode 100644
index 000000000..ef6140359
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/qt/qwebchannelwebkittransport_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 QWEBCHANNELWEBKITTRANSPORT_H
+#define QWEBCHANNELWEBKITTRANSPORT_H
+
+#include <QtWebChannel/QWebChannelAbstractTransport>
+
+class QQuickWebViewExperimental;
+
+class QWebChannelWebKitTransport : public QWebChannelAbstractTransport
+{
+ Q_OBJECT
+public:
+ explicit QWebChannelWebKitTransport(QQuickWebViewExperimental* experimental);
+
+ void sendMessage(const QJsonObject& message) Q_DECL_OVERRIDE;
+
+ void receiveMessage(const QByteArray& message);
+
+private:
+ QQuickWebViewExperimental* m_experimental;
+};
+
+#endif // QWEBCHANNELWEBKITTRANSPORT_H
diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_webchannel.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_webchannel.qml
new file mode 100644
index 000000000..e16b7866e
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_webchannel.qml
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** 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.0
+import QtTest 1.0
+import QtWebKit 3.0
+import QtWebKit.experimental 1.0
+import "../common"
+
+import QtWebChannel 1.0
+
+Item {
+ id: test
+ signal barCalled(var arg)
+ signal clientInitializedCalled(var arg)
+
+ QtObject {
+ id: testObject
+ WebChannel.id: "testObject"
+
+ property var foo: 42
+
+ function clientInitialized(arg)
+ {
+ clientInitializedCalled(arg);
+ }
+
+ function bar(arg) {
+ barCalled(arg);
+ }
+
+ signal runTest(var foo)
+ }
+
+ TestWebView {
+ id: webView
+ experimental.windowObjects: [testObject]
+ experimental.preferences.developerExtrasEnabled: true
+ }
+
+ SignalSpy {
+ id: initializedSpy
+ target: test
+ signalName: "clientInitializedCalled"
+ }
+
+ SignalSpy {
+ id: barSpy
+ target: test
+ signalName: "barCalled"
+ }
+
+ TestCase {
+ name: "WebViewWebChannel"
+ property url testUrl: Qt.resolvedUrl("../common/webchannel.html")
+
+ function init() {
+ initializedSpy.clear();
+ barSpy.clear();
+ }
+
+ function test_basic() {
+ webView.url = testUrl;
+ verify(webView.waitForLoadSucceeded());
+
+ initializedSpy.wait();
+ compare(initializedSpy.signalArguments.length, 1);
+ compare(initializedSpy.signalArguments[0][0], 42);
+
+ var newValue = "roundtrip";
+ testObject.runTest(newValue);
+ barSpy.wait();
+ compare(barSpy.signalArguments.length, 1);
+ compare(barSpy.signalArguments[0][0], newValue);
+
+ compare(testObject.foo, newValue);
+ }
+ }
+}
diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/webchannel.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/webchannel.html
new file mode 100644
index 000000000..940821209
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/webchannel.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
+ <script type="text/javascript">
+ //BEGIN SETUP
+ var channel = new QWebChannel(navigator.qtWebChannelTransport, function(channel) {
+ window.testObject = channel.objects.testObject;
+ testObject.runTest.connect(function(foo) {
+ testObject.foo = foo;
+ testObject.bar(foo);
+ });
+ testObject.clientInitialized(testObject.foo);
+ });
+ //END SETUP
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp
index 4489d74c8..6d80596dd 100644
--- a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp
+++ b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp
@@ -89,8 +89,14 @@ static void globalInitialization()
static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, const void*)
{
- if (!WKStringIsEqualToUTF8CString(messageName, "MessageFromNavigatorQtObject"))
+ if (!WKStringIsEqualToUTF8CString(messageName, "MessageFromNavigatorQtObject")
+#ifdef HAVE_WEBCHANNEL
+ && !WKStringIsEqualToUTF8CString(messageName, "MessageFromNavigatorQtWebChannelTransportObject")
+#endif
+ )
+ {
return;
+ }
ASSERT(messageBody);
ASSERT(WKGetTypeID(messageBody) == WKArrayGetTypeID());
@@ -103,7 +109,12 @@ static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messag
WKPageRef page = static_cast<WKPageRef>(WKArrayGetItemAtIndex(body, 0));
WKStringRef str = static_cast<WKStringRef>(WKArrayGetItemAtIndex(body, 1));
- QQuickWebViewPrivate::get(page)->didReceiveMessageFromNavigatorQtObject(str);
+ if (WKStringIsEqualToUTF8CString(messageName, "MessageFromNavigatorQtObject"))
+ QQuickWebViewPrivate::get(page)->didReceiveMessageFromNavigatorQtObject(str);
+#ifdef HAVE_WEBCHANNEL
+ else if (WKStringIsEqualToUTF8CString(messageName, "MessageFromNavigatorQtWebChannelTransportObject"))
+ QQuickWebViewPrivate::get(page)->didReceiveMessageFromNavigatorQtWebChannelTransportObject(str);
+#endif
}
static void initializeContextInjectedBundleClient(WKContextRef context)
diff --git a/Source/WebKit2/WebKit2.pri b/Source/WebKit2/WebKit2.pri
index e8d4b80d0..3611524e6 100644
--- a/Source/WebKit2/WebKit2.pri
+++ b/Source/WebKit2/WebKit2.pri
@@ -80,7 +80,13 @@ linux-*:!android {
LIBS += -lrt
}
-have?(QTQUICK): QT += qml quick
+have?(QTQUICK): {
+ QT += qml quick
+ qtHaveModule(webchannel) {
+ QT += webchannel
+ DEFINES += HAVE_WEBCHANNEL
+ }
+}
have?(qtpositioning):enable?(GEOLOCATION): QT += positioning
diff --git a/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.cpp b/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.cpp
index c75a446dd..3bb795cad 100644
--- a/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.cpp
+++ b/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.cpp
@@ -93,6 +93,10 @@ void QtBuiltinBundle::didReceiveMessageToPage(WKBundlePageRef page, WKStringRef
handleMessageToNavigatorQtObject(page, messageBody);
else if (WKStringIsEqualToUTF8CString(messageName, "SetNavigatorQtObjectEnabled"))
handleSetNavigatorQtObjectEnabled(page, messageBody);
+#ifdef HAVE_WEBCHANNEL
+ else if (WKStringIsEqualToUTF8CString(messageName, "MessageToNavigatorQtWebChannelTransportObject"))
+ handleMessageToNavigatorQtWebChannelTransport(page, messageBody);
+#endif
}
void QtBuiltinBundle::handleMessageToNavigatorQtObject(WKBundlePageRef page, WKTypeRef messageBody)
@@ -119,4 +123,18 @@ void QtBuiltinBundle::handleSetNavigatorQtObjectEnabled(WKBundlePageRef page, WK
bundlePage->setNavigatorQtObjectEnabled(enabled);
}
+#ifdef HAVE_WEBCHANNEL
+void QtBuiltinBundle::handleMessageToNavigatorQtWebChannelTransport(WKBundlePageRef page, WKTypeRef messageBody)
+{
+ ASSERT(messageBody);
+ ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
+ WKStringRef contents = static_cast<WKStringRef>(messageBody);
+
+ QtBuiltinBundlePage* bundlePage = m_pages.get(page);
+ if (!bundlePage)
+ return;
+ bundlePage->didReceiveMessageToNavigatorQtWebChannelTransport(contents);
+}
+#endif
+
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.h b/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.h
index 2a6a414f3..55f042b6c 100644
--- a/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.h
+++ b/Source/WebKit2/WebProcess/qt/QtBuiltinBundle.h
@@ -57,6 +57,9 @@ public:
private:
void handleMessageToNavigatorQtObject(WKBundlePageRef, WKTypeRef messageBody);
void handleSetNavigatorQtObjectEnabled(WKBundlePageRef, WKTypeRef messageBody);
+#ifdef HAVE_WEBCHANNEL
+ void handleMessageToNavigatorQtWebChannelTransport(WKBundlePageRef, WKTypeRef messageBody);
+#endif
HashMap<WKBundlePageRef, OwnPtr<QtBuiltinBundlePage> > m_pages;
WKBundleRef m_bundle;
diff --git a/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.cpp b/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.cpp
index b32fedf91..4abd77d37 100644
--- a/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.cpp
+++ b/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.cpp
@@ -39,11 +39,127 @@
namespace WebKit {
+typedef JSClassRef (*CreateClassRefCallback)();
+
+static void registerNavigatorObject(JSObjectRef *object, JSStringRef name,
+ JSGlobalContextRef context, void* data,
+ CreateClassRefCallback createClassRefCallback,
+ JSStringRef postMessageName, JSObjectCallAsFunctionCallback postMessageCallback)
+{
+ static JSStringRef navigatorName = JSStringCreateWithUTF8CString("navigator");
+
+ if (*object)
+ JSValueUnprotect(context, *object);
+ *object = JSObjectMake(context, createClassRefCallback(), data);
+ JSValueProtect(context, *object);
+
+ JSObjectRef postMessage = JSObjectMakeFunctionWithCallback(context, postMessageName, postMessageCallback);
+ JSObjectSetProperty(context, *object, postMessageName, postMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
+
+ JSValueRef navigatorValue = JSObjectGetProperty(context, JSContextGetGlobalObject(context), navigatorName, 0);
+ if (!JSValueIsObject(context, navigatorValue))
+ return;
+ JSObjectRef navigatorObject = JSValueToObject(context, navigatorValue, 0);
+ JSObjectSetProperty(context, navigatorObject, name, *object, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
+}
+
+static JSClassRef createEmptyJSClassRef()
+{
+ const JSClassDefinition definition = kJSClassDefinitionEmpty;
+ return JSClassCreate(&definition);
+}
+
+static JSClassRef navigatorQtObjectClass()
+{
+ static JSClassRef classRef = createEmptyJSClassRef();
+ return classRef;
+}
+
+static JSValueRef qt_postMessageCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
+{
+ // FIXME: should it work regardless of the thisObject?
+
+ if (argumentCount < 1 || !JSValueIsString(context, arguments[0]))
+ return JSValueMakeUndefined(context);
+
+ QtBuiltinBundlePage* bundlePage = reinterpret_cast<QtBuiltinBundlePage*>(JSObjectGetPrivate(thisObject));
+ ASSERT(bundlePage);
+
+ // FIXME: needed?
+ if (!bundlePage->navigatorQtObjectEnabled())
+ return JSValueMakeUndefined(context);
+
+ JSRetainPtr<JSStringRef> jsContents = JSValueToStringCopy(context, arguments[0], 0);
+ WKRetainPtr<WKStringRef> contents(AdoptWK, WKStringCreateWithJSString(jsContents.get()));
+ bundlePage->postMessageFromNavigatorQtObject(contents.get());
+ return JSValueMakeUndefined(context);
+}
+
+static JSObjectRef createWrappedMessage(JSGlobalContextRef context, WKStringRef data)
+{
+ static JSStringRef dataName = JSStringCreateWithUTF8CString("data");
+
+ JSRetainPtr<JSStringRef> jsData = WKStringCopyJSString(data);
+ JSObjectRef wrappedMessage = JSObjectMake(context, 0, 0);
+ JSObjectSetProperty(context, wrappedMessage, dataName, JSValueMakeString(context, jsData.get()), kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
+ return wrappedMessage;
+}
+
+static void callOnMessage(JSObjectRef object, WKStringRef contents, WKBundlePageRef page)
+{
+ static JSStringRef onmessageName = JSStringCreateWithUTF8CString("onmessage");
+
+ if (!object)
+ return;
+
+ WKBundleFrameRef frame = WKBundlePageGetMainFrame(page);
+ JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
+
+ JSValueRef onmessageValue = JSObjectGetProperty(context, object, onmessageName, 0);
+ if (!JSValueIsObject(context, onmessageValue))
+ return;
+
+ JSObjectRef onmessageFunction = JSValueToObject(context, onmessageValue, 0);
+ if (!JSObjectIsFunction(context, onmessageFunction))
+ return;
+
+ JSObjectRef wrappedMessage = createWrappedMessage(context, contents);
+ JSObjectCallAsFunction(context, onmessageFunction, 0, 1, &wrappedMessage, 0);
+}
+
+#ifdef HAVE_WEBCHANNEL
+static JSClassRef navigatorQtWebChannelTransportObjectClass()
+{
+ static JSClassRef classRef = createEmptyJSClassRef();
+ return classRef;
+}
+
+static JSValueRef qt_postWebChannelMessageCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
+{
+ // FIXME: should it work regardless of the thisObject?
+
+ if (argumentCount < 1 || !JSValueIsString(context, arguments[0]))
+ return JSValueMakeUndefined(context);
+
+ QtBuiltinBundlePage* bundlePage = reinterpret_cast<QtBuiltinBundlePage*>(JSObjectGetPrivate(thisObject));
+ ASSERT(bundlePage);
+
+ // TODO: can we transmit the data as JS object, instead of as a string?
+ JSRetainPtr<JSStringRef> jsContents = JSValueToStringCopy(context, arguments[0], 0);
+ WKRetainPtr<WKStringRef> contents(AdoptWK, WKStringCreateWithJSString(jsContents.get()));
+ bundlePage->postMessageFromNavigatorQtWebChannelTransport(contents.get());
+ return JSValueMakeUndefined(context);
+}
+#endif
+
QtBuiltinBundlePage::QtBuiltinBundlePage(QtBuiltinBundle* bundle, WKBundlePageRef page)
: m_bundle(bundle)
, m_page(page)
, m_navigatorQtObject(0)
, m_navigatorQtObjectEnabled(false)
+#ifdef HAVE_WEBCHANNEL
+ , m_navigatorQtWebChannelTransportObject(0)
+#endif
{
WKBundlePageLoaderClient loaderClient = {
kWKBundlePageLoaderClientCurrentVersion,
@@ -88,11 +204,25 @@ QtBuiltinBundlePage::QtBuiltinBundlePage(QtBuiltinBundle* bundle, WKBundlePageRe
QtBuiltinBundlePage::~QtBuiltinBundlePage()
{
- if (!m_navigatorQtObject)
+ if (!m_navigatorQtObject
+#ifdef HAVE_WEBCHANNEL
+ && !m_navigatorQtWebChannelTransportObject
+#endif
+ )
+ {
return;
+ }
+
WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
- JSValueUnprotect(context, m_navigatorQtObject);
+
+ if (m_navigatorQtObject)
+ JSValueUnprotect(context, m_navigatorQtObject);
+
+#ifdef HAVE_WEBCHANNEL
+ if (m_navigatorQtWebChannelTransportObject)
+ JSValueUnprotect(context, m_navigatorQtWebChannelTransportObject);
+#endif
}
void QtBuiltinBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void* clientInfo)
@@ -100,72 +230,26 @@ void QtBuiltinBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleF
static_cast<QtBuiltinBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, world);
}
-static JSValueRef qt_postMessageCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
-{
- // FIXME: should it work regardless of the thisObject?
-
- if (argumentCount < 1 || !JSValueIsString(context, arguments[0]))
- return JSValueMakeUndefined(context);
-
- QtBuiltinBundlePage* bundlePage = reinterpret_cast<QtBuiltinBundlePage*>(JSObjectGetPrivate(thisObject));
- ASSERT(bundlePage);
-
- // FIXME: needed?
- if (!bundlePage->navigatorQtObjectEnabled())
- return JSValueMakeUndefined(context);
-
- JSRetainPtr<JSStringRef> jsContents = JSValueToStringCopy(context, arguments[0], 0);
- WKRetainPtr<WKStringRef> contents(AdoptWK, WKStringCreateWithJSString(jsContents.get()));
- bundlePage->postMessageFromNavigatorQtObject(contents.get());
- return JSValueMakeUndefined(context);
-}
-
void QtBuiltinBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
{
if (!WKBundleFrameIsMainFrame(frame) || WKBundleScriptWorldNormalWorld() != world)
return;
JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
registerNavigatorQtObject(context);
+#ifdef HAVE_WEBCHANNEL
+ registerNavigatorQtWebChannelTransportObject(context);
+#endif
}
-void QtBuiltinBundlePage::postMessageFromNavigatorQtObject(WKStringRef contents)
+void QtBuiltinBundlePage::postMessageFromNavigatorQtObject(WKStringRef message)
{
static WKStringRef messageName = WKStringCreateWithUTF8CString("MessageFromNavigatorQtObject");
- WKTypeRef body[] = { page(), contents };
- WKRetainPtr<WKArrayRef> messageBody(AdoptWK, WKArrayCreate(body, sizeof(body) / sizeof(WKTypeRef)));
- WKBundlePostMessage(m_bundle->toRef(), messageName, messageBody.get());
-}
-
-static JSObjectRef createWrappedMessage(JSGlobalContextRef context, WKStringRef data)
-{
- static JSStringRef dataName = JSStringCreateWithUTF8CString("data");
-
- JSRetainPtr<JSStringRef> jsData = WKStringCopyJSString(data);
- JSObjectRef wrappedMessage = JSObjectMake(context, 0, 0);
- JSObjectSetProperty(context, wrappedMessage, dataName, JSValueMakeString(context, jsData.get()), kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
- return wrappedMessage;
+ postNavigatorMessage(messageName, message);
}
-void QtBuiltinBundlePage::didReceiveMessageToNavigatorQtObject(WKStringRef contents)
+void QtBuiltinBundlePage::didReceiveMessageToNavigatorQtObject(WKStringRef message)
{
- static JSStringRef onmessageName = JSStringCreateWithUTF8CString("onmessage");
-
- if (!m_navigatorQtObject)
- return;
-
- WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
- JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
-
- JSValueRef onmessageValue = JSObjectGetProperty(context, m_navigatorQtObject, onmessageName, 0);
- if (!JSValueIsObject(context, onmessageValue))
- return;
-
- JSObjectRef onmessageFunction = JSValueToObject(context, onmessageValue, 0);
- if (!JSObjectIsFunction(context, onmessageFunction))
- return;
-
- JSObjectRef wrappedMessage = createWrappedMessage(context, contents);
- JSObjectCallAsFunction(context, onmessageFunction, 0, 1, &wrappedMessage, 0);
+ callOnMessage(m_navigatorQtObject, message, m_page);
}
void QtBuiltinBundlePage::setNavigatorQtObjectEnabled(bool enabled)
@@ -178,33 +262,40 @@ void QtBuiltinBundlePage::setNavigatorQtObjectEnabled(bool enabled)
void QtBuiltinBundlePage::registerNavigatorQtObject(JSGlobalContextRef context)
{
+ static JSStringRef name = JSStringCreateWithUTF8CString("qt");
static JSStringRef postMessageName = JSStringCreateWithUTF8CString("postMessage");
- static JSStringRef navigatorName = JSStringCreateWithUTF8CString("navigator");
- static JSStringRef qtName = JSStringCreateWithUTF8CString("qt");
+ registerNavigatorObject(&m_navigatorQtObject, name, context, this,
+ &navigatorQtObjectClass,
+ postMessageName, &qt_postMessageCallback);
+}
- if (m_navigatorQtObject)
- JSValueUnprotect(context, m_navigatorQtObject);
- m_navigatorQtObject = JSObjectMake(context, navigatorQtObjectClass(), this);
- JSValueProtect(context, m_navigatorQtObject);
+#ifdef HAVE_WEBCHANNEL
+void QtBuiltinBundlePage::registerNavigatorQtWebChannelTransportObject(JSGlobalContextRef context)
+{
+ static JSStringRef name = JSStringCreateWithUTF8CString("qtWebChannelTransport");
+ static JSStringRef postMessageName = JSStringCreateWithUTF8CString("send");
+ registerNavigatorObject(&m_navigatorQtWebChannelTransportObject, name, context, this,
+ &navigatorQtWebChannelTransportObjectClass,
+ postMessageName, &qt_postWebChannelMessageCallback);
+}
- JSObjectRef postMessage = JSObjectMakeFunctionWithCallback(context, postMessageName, qt_postMessageCallback);
- JSObjectSetProperty(context, m_navigatorQtObject, postMessageName, postMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
+void QtBuiltinBundlePage::didReceiveMessageToNavigatorQtWebChannelTransport(WKStringRef contents)
+{
+ callOnMessage(m_navigatorQtWebChannelTransportObject, contents, m_page);
+}
- JSValueRef navigatorValue = JSObjectGetProperty(context, JSContextGetGlobalObject(context), navigatorName, 0);
- if (!JSValueIsObject(context, navigatorValue))
- return;
- JSObjectRef navigatorObject = JSValueToObject(context, navigatorValue, 0);
- JSObjectSetProperty(context, navigatorObject, qtName, m_navigatorQtObject, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
+void QtBuiltinBundlePage::postMessageFromNavigatorQtWebChannelTransport(WKStringRef message)
+{
+ static WKStringRef messageName = WKStringCreateWithUTF8CString("MessageFromNavigatorQtWebChannelTransportObject");
+ postNavigatorMessage(messageName, message);
}
+#endif
-JSClassRef QtBuiltinBundlePage::navigatorQtObjectClass()
+void QtBuiltinBundlePage::postNavigatorMessage(WKStringRef messageName, WKStringRef message)
{
- static JSClassRef classRef = 0;
- if (!classRef) {
- const JSClassDefinition navigatorQtObjectClass = kJSClassDefinitionEmpty;
- classRef = JSClassCreate(&navigatorQtObjectClass);
- }
- return classRef;
+ WKTypeRef body[] = { page(), message };
+ WKRetainPtr<WKArrayRef> messageBody(AdoptWK, WKArrayCreate(body, sizeof(body) / sizeof(WKTypeRef)));
+ WKBundlePostMessage(m_bundle->toRef(), messageName, messageBody.get());
}
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.h b/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.h
index 3ffb3f008..3c466f040 100644
--- a/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.h
+++ b/Source/WebKit2/WebProcess/qt/QtBuiltinBundlePage.h
@@ -53,15 +53,26 @@ public:
bool navigatorQtObjectEnabled() const { return m_navigatorQtObjectEnabled; }
void setNavigatorQtObjectEnabled(bool);
+#ifdef HAVE_WEBCHANNEL
+ void postMessageFromNavigatorQtWebChannelTransport(WKStringRef message);
+ void didReceiveMessageToNavigatorQtWebChannelTransport(WKStringRef message);
+#endif
+
private:
void registerNavigatorQtObject(JSGlobalContextRef);
+#ifdef HAVE_WEBCHANNEL
+ void registerNavigatorQtWebChannelTransportObject(JSGlobalContextRef);
+#endif
- static JSClassRef navigatorQtObjectClass();
+ void postNavigatorMessage(WKStringRef messageName, WKStringRef message);
QtBuiltinBundle* m_bundle;
WKBundlePageRef m_page;
JSObjectRef m_navigatorQtObject;
bool m_navigatorQtObjectEnabled;
+#ifdef HAVE_WEBCHANNEL
+ JSObjectRef m_navigatorQtWebChannelTransportObject;
+#endif
};
} // namespace WebKit
diff --git a/Source/sync.profile b/Source/sync.profile
index 9eb0fe910..c0f687dc0 100644
--- a/Source/sync.profile
+++ b/Source/sync.profile
@@ -24,4 +24,5 @@
"qtlocation" => "",
"qtmultimedia" => "",
"qtsensors" => "",
+ "qtwebchannel" => "",
);