summaryrefslogtreecommitdiffstats
path: root/src/webview/qquickwebview.cpp
diff options
context:
space:
mode:
authorChristian Strømme <christian.stromme@theqtcompany.com>2015-01-21 13:47:38 +0100
committerChristian Stromme <christian.stromme@theqtcompany.com>2015-02-09 16:35:47 +0000
commitb8fc57ba4aa5b25ae31df0ec74c62730dd0fa9d0 (patch)
treecd7def072034c2d14b213cfd5c8b2269bee869c0 /src/webview/qquickwebview.cpp
parent011069957991ac884f6e5cbacc6391570c7091e8 (diff)
Add runJavaScript() on Android and iOS.
This is a rough implementation on both Android and iOS and both comes with certain limitations. On Android we require API level 19 or higher and on iOS the runJavaScript function is not asynchronous. Change-Id: Ia19782505e5e30d5517a4d627565e5432cc27bfa Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>
Diffstat (limited to 'src/webview/qquickwebview.cpp')
-rw-r--r--src/webview/qquickwebview.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/webview/qquickwebview.cpp b/src/webview/qquickwebview.cpp
index be51fb7..1803994 100644
--- a/src/webview/qquickwebview.cpp
+++ b/src/webview/qquickwebview.cpp
@@ -38,6 +38,38 @@
#include <QtQml/qqmlengine.h>
#include <QtCore/qmutex.h>
+namespace {
+
+class CallbackStorage
+{
+public:
+ int insertCallback(const QJSValue &callback)
+ {
+ QMutexLocker locker(&m_mtx);
+ const int nextId = qMax(++m_counter, 0);
+ if (nextId == 0)
+ m_counter = 1;
+
+ m_callbacks.insert(nextId, callback);
+ return nextId;
+ }
+
+ QJSValue takeCallback(int callbackId)
+ {
+ QMutexLocker lock(&m_mtx);
+ return m_callbacks.take(callbackId);
+ }
+
+private:
+ QMutex m_mtx;
+ int m_counter;
+ QHash<int, QJSValue> m_callbacks;
+};
+
+} // namespace
+
+Q_GLOBAL_STATIC(CallbackStorage, callbacks)
+
/*!
\qmltype WebView
\inqmlmodule QtWebView
@@ -64,6 +96,7 @@ QQuickWebView::QQuickWebView(QQuickItem *parent)
connect(m_webView.data(), &QWebView::loadingChanged, this, &QQuickWebView::loadingChanged);
connect(m_webView.data(), &QWebView::loadProgressChanged, this, &QQuickWebView::loadProgressChanged);
connect(m_webView.data(), &QWebView::requestFocus, this, &QQuickWebView::onFocusRequest);
+ connect(m_webView.data(), &QWebView::javaScriptResult, this, &QQuickWebView::onRunJavaScriptResult);
}
QQuickWebView::~QQuickWebView()
@@ -185,6 +218,48 @@ void QQuickWebView::stop()
m_webView->stop();
}
+/*!
+ \qmlmethod void QtWebView::WebView::runJavaScript(string script, variant callback)
+
+ Runs the specified JavaScript.
+ In case a callback function is provided, it will be invoked after the script finished running.
+
+ \badcode
+ runJavaScript("document.title", function(result) { console.log(result); });
+ \endcode
+*/
+void QQuickWebView::runJavaScript(const QString &script, const QJSValue &callback)
+{
+ const int callbackId = callback.isCallable() ? callbacks->insertCallback(callback)
+ : -1;
+ runJavaScriptPrivate(script, callbackId);
+}
+
+void QQuickWebView::runJavaScriptPrivate(const QString &script, int callbackId)
+{
+ m_webView->runJavaScriptPrivate(script, callbackId);
+}
+
+void QQuickWebView::onRunJavaScriptResult(int id, const QVariant &variant)
+{
+ if (id == -1)
+ return;
+
+ QJSValue callback = callbacks->takeCallback(id);
+ if (callback.isUndefined())
+ return;
+
+ QQmlEngine *engine = qmlEngine(this);
+ if (engine == 0) {
+ qWarning() << "No JavaScript engine, unable to handle JavaScript callback!";
+ return;
+ }
+
+ QJSValueList args;
+ args.append(engine->toScriptValue(variant));
+ callback.call(args);
+}
+
void QQuickWebView::onFocusRequest(bool focus)
{
setFocus(focus);