diff options
| author | Christian Strømme <christian.stromme@theqtcompany.com> | 2015-01-21 13:47:38 +0100 |
|---|---|---|
| committer | Christian Stromme <christian.stromme@theqtcompany.com> | 2015-02-09 16:35:47 +0000 |
| commit | b8fc57ba4aa5b25ae31df0ec74c62730dd0fa9d0 (patch) | |
| tree | cd7def072034c2d14b213cfd5c8b2269bee869c0 /src/webview/qquickwebview.cpp | |
| parent | 011069957991ac884f6e5cbacc6391570c7091e8 (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.cpp | 75 |
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); |
