diff options
| -rw-r--r-- | src/plugins/android/qandroidwebview.cpp | 31 | ||||
| -rw-r--r-- | src/plugins/android/qandroidwebview_p.h | 11 | ||||
| -rw-r--r-- | src/plugins/darwin/qdarwinwebview.mm | 11 | ||||
| -rw-r--r-- | src/plugins/darwin/qdarwinwebview_p.h | 5 | ||||
| -rw-r--r-- | src/plugins/wasm/qwasmwebview.cpp | 7 | ||||
| -rw-r--r-- | src/plugins/wasm/qwasmwebview_p.h | 5 | ||||
| -rw-r--r-- | src/plugins/webengine/qwebenginewebview.cpp | 6 | ||||
| -rw-r--r-- | src/plugins/webengine/qwebenginewebview_p.h | 10 | ||||
| -rw-r--r-- | src/plugins/windows/qwebview2webview.cpp | 22 | ||||
| -rw-r--r-- | src/plugins/windows/qwebview2webview_p.h | 5 | ||||
| -rw-r--r-- | src/quick/qquickwebview.cpp | 51 | ||||
| -rw-r--r-- | src/quick/qquickwebview_p.h | 6 | ||||
| -rw-r--r-- | src/webview/qwebview.cpp | 6 | ||||
| -rw-r--r-- | src/webview/qwebview.h | 7 | ||||
| -rw-r--r-- | src/webview/qwebview_p.h | 3 | ||||
| -rw-r--r-- | tests/auto/webview/qwebview/tst_qwebview.cpp | 19 |
16 files changed, 101 insertions, 104 deletions
diff --git a/src/plugins/android/qandroidwebview.cpp b/src/plugins/android/qandroidwebview.cpp index ee33e2c..42cddc0 100644 --- a/src/plugins/android/qandroidwebview.cpp +++ b/src/plugins/android/qandroidwebview.cpp @@ -190,19 +190,19 @@ QString QAndroidWebViewPrivate::title() const return m_viewController.callMethod<QString>("getTitle"); } -void QAndroidWebViewPrivate::runJavaScriptPrivate(const QString &script, - int callbackId) +void QAndroidWebViewPrivate::runJavaScript( + const QString &script, const std::function<void(const QVariant &)> &resultCallback) { if (QtAndroidPrivate::androidSdkVersion() < 19) { qWarning("runJavaScript() requires API level 19 or higher."); - if (callbackId == -1) - return; - - // Emit signal here to remove the callback. - emit q_ptr->javaScriptResult(callbackId, QVariant()); + if (resultCallback) + resultCallback(QVariant()); + return; } - m_viewController.callMethod<void>("runJavaScript", script, jlong(callbackId)); + m_callbacks.insert(m_callbackId, resultCallback); + m_viewController.callMethod<void>("runJavaScript", script, jlong(m_callbackId)); + ++m_callbackId; } QWebViewSettingsPrivate *QAndroidWebViewPrivate::settings() const @@ -259,6 +259,17 @@ void QAndroidWebViewPrivate::onApplicationStateChanged(Qt::ApplicationState stat m_viewController.callMethod<void>("onPause"); } +void QAndroidWebViewPrivate::javaScriptResult(int id, const QVariant &result) +{ + auto it = m_callbacks.find(id); + if (it != m_callbacks.end()) { + auto callback = it.value(); + if (callback) + callback(result); + m_callbacks.erase(it); + } +} + static void c_onRunJavaScriptResult(JNIEnv *env, jobject thiz, jlong id, @@ -285,8 +296,8 @@ static void c_onRunJavaScriptResult(JNIEnv *env, jsonValue = object.value(QStringLiteral("data")); } - emit wc->q_ptr->javaScriptResult(int(callbackId), - jsonValue.isNull() ? resultString : jsonValue.toVariant()); + wc->javaScriptResult(int(callbackId), + jsonValue.isNull() ? resultString : jsonValue.toVariant()); } Q_DECLARE_JNI_NATIVE_METHOD(c_onRunJavaScriptResult) diff --git a/src/plugins/android/qandroidwebview_p.h b/src/plugins/android/qandroidwebview_p.h index 1cacd19..5a8d229 100644 --- a/src/plugins/android/qandroidwebview_p.h +++ b/src/plugins/android/qandroidwebview_p.h @@ -80,16 +80,21 @@ public: void deleteCookie(const QString &domain, const QString &name) override; void deleteAllCookies() override; + void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) override; + + void javaScriptResult(int id, const QVariant &result); + protected: - void runJavaScriptPrivate(const QString& script, - int callbackId) override; QWebViewSettingsPrivate *settings() const override; private Q_SLOTS: void onApplicationStateChanged(Qt::ApplicationState state); private: - quint64 m_callbackId; + int m_callbackId; + QMap<int, std::function<void(const QVariant &)>> m_callbacks; + QWindow *m_window; QtJniTypes::WebViewController m_viewController; QtJniTypes::WebView m_webView; diff --git a/src/plugins/darwin/qdarwinwebview.mm b/src/plugins/darwin/qdarwinwebview.mm index 967eaa0..0727768 100644 --- a/src/plugins/darwin/qdarwinwebview.mm +++ b/src/plugins/darwin/qdarwinwebview.mm @@ -460,13 +460,16 @@ QVariant fromJSValue(id result) return QVariant(); } -void QDarwinWebViewPrivate::runJavaScriptPrivate(const QString &script, int callbackId) +void QDarwinWebViewPrivate::runJavaScript( + const QString &script, const std::function<void(const QVariant &)> &resultCallback) { + std::function<void(const QVariant &)> callbackCopy = resultCallback; QPointer<QDarwinWebViewPrivate> observer(this); [wkWebView evaluateJavaScript:script.toNSString() - completionHandler:^(id result, NSError *) { - if (callbackId != -1 && observer) - emit q_ptr->javaScriptResult(callbackId, fromJSValue(result)); + completionHandler:^(id result, NSError *error) { + QVariant r = error ? QVariant() : fromJSValue(result); + if (callbackCopy && observer) + callbackCopy(r); }]; } diff --git a/src/plugins/darwin/qdarwinwebview_p.h b/src/plugins/darwin/qdarwinwebview_p.h index a7d8b83..a23e12c 100644 --- a/src/plugins/darwin/qdarwinwebview_p.h +++ b/src/plugins/darwin/qdarwinwebview_p.h @@ -82,9 +82,8 @@ public: void deleteCookie(const QString &domain, const QString &name) override; void deleteAllCookies() override; -protected: - void runJavaScriptPrivate(const QString& script, - int callbackId) override; + void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) override; public: WKWebView *wkWebView; diff --git a/src/plugins/wasm/qwasmwebview.cpp b/src/plugins/wasm/qwasmwebview.cpp index ca93c5e..31a7579 100644 --- a/src/plugins/wasm/qwasmwebview.cpp +++ b/src/plugins/wasm/qwasmwebview.cpp @@ -195,11 +195,12 @@ void QWasmWebViewPrivate::deleteAllCookies() qWarning("deleteAllCookies() not supported on this platform"); } -void QWasmWebViewPrivate::runJavaScriptPrivate(const QString &script, int callbackId) +void QWasmWebViewPrivate::runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) { Q_UNUSED(script); - Q_UNUSED(callbackId); - qWarning("runJavaScriptPrivate() not supported on this platform"); + Q_UNUSED(resultCallback); + qWarning("runJavaScript() not supported on this platform"); } QWebViewSettingsPrivate *QWasmWebViewPrivate::settings() const diff --git a/src/plugins/wasm/qwasmwebview_p.h b/src/plugins/wasm/qwasmwebview_p.h index 6695f66..bb251ed 100644 --- a/src/plugins/wasm/qwasmwebview_p.h +++ b/src/plugins/wasm/qwasmwebview_p.h @@ -76,9 +76,10 @@ public: void deleteCookie(const QString &domain, const QString &name) final; void deleteAllCookies() final; + void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) final; + protected: - void runJavaScriptPrivate(const QString& script, - int callbackId) final; QWebViewSettingsPrivate *settings() const final; private: diff --git a/src/plugins/webengine/qwebenginewebview.cpp b/src/plugins/webengine/qwebenginewebview.cpp index 8dd3421..2c58a2f 100644 --- a/src/plugins/webengine/qwebenginewebview.cpp +++ b/src/plugins/webengine/qwebenginewebview.cpp @@ -121,10 +121,10 @@ QString QWebEngineWebViewPrivate::title() const return m_webEngineView->title(); } -void QWebEngineWebViewPrivate::runJavaScriptPrivate(const QString &script, - int callbackId) +void QWebEngineWebViewPrivate::runJavaScript( + const QString &script, const std::function<void(const QVariant &)> &resultCallback) { - m_webEngineView->runJavaScript(script, QQuickWebView::takeCallback(callbackId)); + m_webEngineView->runJavaScript(script, resultCallback); } void QWebEngineWebViewPrivate::setCookie(const QString &domain, const QString &name, const QString &value) diff --git a/src/plugins/webengine/qwebenginewebview_p.h b/src/plugins/webengine/qwebenginewebview_p.h index 4681f16..a73c712 100644 --- a/src/plugins/webengine/qwebenginewebview_p.h +++ b/src/plugins/webengine/qwebenginewebview_p.h @@ -22,12 +22,12 @@ #include <QtQml/qqmlcomponent.h> -#include <private/qwebview_p.h> +#include <QtWebView/private/qwebview_p.h> #include <QtWebEngineQuick/QQuickWebEngineProfile> #include <QtWebEngineQuick/private/qquickwebenginesettings_p.h> #include <QtCore/qpointer.h> - +#include <QVariant> QT_BEGIN_NAMESPACE class QQuickItem; @@ -84,7 +84,6 @@ public: QWebViewSettingsPrivate *settings() const override; QWindow *nativeWindow() const override { return nullptr; } -public Q_SLOTS: void goBack() override; void goForward() override; void reload() override; @@ -94,6 +93,8 @@ public Q_SLOTS: const QString &value) override; void deleteCookie(const QString &domain, const QString &name) override; void deleteAllCookies() override; + void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) override; private Q_SLOTS: void q_urlChanged(); @@ -105,9 +106,6 @@ private Q_SLOTS: void q_cookieAdded(const QNetworkCookie &cookie); void q_cookieRemoved(const QNetworkCookie &cookie); -protected: - void runJavaScriptPrivate(const QString& script, - int callbackId) override; private: friend class QWebEngineWebViewSettingsPrivate; diff --git a/src/plugins/windows/qwebview2webview.cpp b/src/plugins/windows/qwebview2webview.cpp index 204d9d8..205f7bb 100644 --- a/src/plugins/windows/qwebview2webview.cpp +++ b/src/plugins/windows/qwebview2webview.cpp @@ -637,14 +637,15 @@ void QWebView2WebViewPrivate::updateWindowGeometry() } } -void QWebView2WebViewPrivate::runJavaScriptPrivate(const QString &script, int callbackId) +void QWebView2WebViewPrivate::runJavaScript( + const QString &script, const std::function<void(const QVariant &)> &resultCallback) { if (m_webview) { - const HRESULT hr = m_webview->ExecuteScript( + m_webview->ExecuteScript( (wchar_t *)script.utf16(), Microsoft::WRL::Callback<ICoreWebView2ExecuteScriptCompletedHandler>( - [this, callbackId](HRESULT errorCode, - LPCWSTR resultObjectAsJson) -> HRESULT { + [this, resultCallback](HRESULT errorCode, + LPCWSTR resultObjectAsJson) -> HRESULT { QString resultStr = QString::fromWCharArray(resultObjectAsJson); QJsonParseError parseError; @@ -664,15 +665,16 @@ void QWebView2WebViewPrivate::runJavaScriptPrivate(const QString &script, int ca resultVariant = val.toVariant(); } } - if (errorCode != S_OK) - emit q_ptr->javaScriptResult(callbackId, - qt_error_string(errorCode)); - else - emit q_ptr->javaScriptResult(callbackId, resultVariant); + QVariant r = + errorCode == S_OK ? resultVariant : qt_error_string(errorCode); + if (resultCallback) + resultCallback(r); return errorCode; }) .Get()); - Q_ASSERT_SUCCEEDED(hr); + } else { + if (resultCallback) + resultCallback(QVariant()); } } diff --git a/src/plugins/windows/qwebview2webview_p.h b/src/plugins/windows/qwebview2webview_p.h index 60201f0..2b00277 100644 --- a/src/plugins/windows/qwebview2webview_p.h +++ b/src/plugins/windows/qwebview2webview_p.h @@ -86,8 +86,10 @@ public: void setCookie(const QString &domain, const QString &name, const QString &value) override; void deleteCookie(const QString &domain, const QString &name) override; void deleteAllCookies() override; + void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) override; -private Q_SLOTS: +private: HRESULT onNavigationStarting(ICoreWebView2* webview, ICoreWebView2NavigationStartingEventArgs* args); HRESULT onNavigationCompleted(ICoreWebView2* webview, ICoreWebView2NavigationCompletedEventArgs* args); HRESULT onWebResourceRequested(ICoreWebView2* sender, ICoreWebView2WebResourceRequestedEventArgs* args); @@ -97,7 +99,6 @@ private Q_SLOTS: void initialize(HWND hWnd); protected: - void runJavaScriptPrivate(const QString &script, int callbackId) override; QWebViewSettingsPrivate *settings() const override; private: diff --git a/src/quick/qquickwebview.cpp b/src/quick/qquickwebview.cpp index 2d67df6..3dc1ed8 100644 --- a/src/quick/qquickwebview.cpp +++ b/src/quick/qquickwebview.cpp @@ -72,7 +72,6 @@ QQuickWebView::QQuickWebView(QQuickItem *parent) connect(m_webView, &QWebView::urlChanged, this, &QQuickWebView::urlChanged); connect(m_webView, &QWebView::loadProgressChanged, this, &QQuickWebView::loadProgressChanged); connect(m_webView, &QWebView::loadingChanged, this, &QQuickWebView::onLoadingChanged); - connect(m_webView, &QWebView::javaScriptResult, this, &QQuickWebView::onRunJavaScriptResult); connect(m_webView, &QWebView::httpUserAgentChanged, this, &QQuickWebView::httpUserAgentChanged); connect(m_webView, &QWebView::cookieAdded, this, &QQuickWebView::cookieAdded); connect(m_webView, &QWebView::cookieRemoved, this, &QQuickWebView::cookieRemoved); @@ -272,13 +271,24 @@ void QQuickWebView::loadHtml(const QString &html, const QUrl &baseUrl) */ 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); + if (callback.isCallable()) { + int callbackId = callbacks->insertCallback(callback); + QPointer<QQmlEngine> weakEngine = qmlEngine(this); + m_webView->runJavaScript(script, [callbackId, weakEngine](const QVariant &result) { + QJSValue callback = callbacks->takeCallback(callbackId); + if (!weakEngine) { + qWarning("No JavaScript engine, unable to handle JavaScript callback!"); + return; + } + + Q_ASSERT(callback.isCallable()); + QJSValueList args; + args.append(weakEngine->toScriptValue(result)); + callback.call(args); + }); + } else { + m_webView->runJavaScript(script); + } } /*! @@ -333,37 +343,12 @@ void QQuickWebView::deleteAllCookies() m_webView->deleteAllCookies(); } -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::onLoadingChanged(const QWebViewLoadRequest &loadRequest) { QQuickWebViewLoadRequest qqLoadRequest(loadRequest); Q_EMIT loadingChanged(&qqLoadRequest); } -QJSValue QQuickWebView::takeCallback(int id) -{ - return callbacks->takeCallback(id); -} - /*! \qmlproperty WebViewSettings WebView::settings \readonly diff --git a/src/quick/qquickwebview_p.h b/src/quick/qquickwebview_p.h index 4e8d5c7..8cd9752 100644 --- a/src/quick/qquickwebview_p.h +++ b/src/quick/qquickwebview_p.h @@ -93,17 +93,11 @@ Q_SIGNALS: Q_REVISION(6, 3) void cookieAdded(const QString &domain, const QString &name); Q_REVISION(6, 3) void cookieRemoved(const QString &domain, const QString &name); -protected: - void runJavaScriptPrivate(const QString &script, int callbackId); - private Q_SLOTS: - void onRunJavaScriptResult(int id, const QVariant &variant); void onLoadingChanged(const QWebViewLoadRequest &loadRequest); private: friend class QWebEngineWebViewPrivate; - static QJSValue takeCallback(int id); - QWebView *m_webView; QQuickWebViewSettings *m_settings; }; diff --git a/src/webview/qwebview.cpp b/src/webview/qwebview.cpp index 8ba9662..75ab2f9 100644 --- a/src/webview/qwebview.cpp +++ b/src/webview/qwebview.cpp @@ -102,10 +102,10 @@ void QWebView::loadHtml(const QString &html, const QUrl &baseUrl) d->loadHtml(html, baseUrl); } -void QWebView::runJavaScriptPrivate(const QString &script, - int callbackId) +void QWebView::runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) { - d->runJavaScriptPrivate(script, callbackId); + return d->runJavaScript(script, resultCallback); } void QWebView::setCookie(const QString &domain, const QString &name, const QString &value) diff --git a/src/webview/qwebview.h b/src/webview/qwebview.h index 94681b1..1e3a160 100644 --- a/src/webview/qwebview.h +++ b/src/webview/qwebview.h @@ -61,21 +61,18 @@ public: Q_INVOKABLE void deleteCookie(const QString &domain, const QString &name); Q_INVOKABLE void deleteAllCookies(); - // FIXME runjavascript + void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback = {}); Q_SIGNALS: void titleChanged(QString title); void urlChanged(QUrl url); void loadingChanged(const QWebViewLoadRequest &loadRequest); void loadProgressChanged(int loadProgress); - void javaScriptResult(int id, const QVariant &result); void httpUserAgentChanged(QString userAgent); void cookieAdded(const QString &domain, const QString &name); void cookieRemoved(const QString &domain, const QString &name); -protected: - void runJavaScriptPrivate(const QString &script, int callbackId); - private: Q_DISABLE_COPY(QWebView) diff --git a/src/webview/qwebview_p.h b/src/webview/qwebview_p.h index 4134f2a..ea7869d 100644 --- a/src/webview/qwebview_p.h +++ b/src/webview/qwebview_p.h @@ -65,11 +65,12 @@ public: virtual void stop() = 0; virtual void reload() = 0; virtual void loadHtml(const QString &html, const QUrl &baseUrl) = 0; - virtual void runJavaScriptPrivate(const QString &script, int callbackId) = 0; virtual void setCookie(const QString &domain, const QString &name, const QString &value) = 0; virtual void deleteCookie(const QString &domain, const QString &name) = 0; virtual void deleteAllCookies() = 0; virtual QWindow *nativeWindow() const = 0; + virtual void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &resultCallback) = 0; protected: explicit QWebViewPrivate(QWebView *view) : q_ptr(view) { }; diff --git a/tests/auto/webview/qwebview/tst_qwebview.cpp b/tests/auto/webview/qwebview/tst_qwebview.cpp index 85108e7..4360aaa 100644 --- a/tests/auto/webview/qwebview/tst_qwebview.cpp +++ b/tests/auto/webview/qwebview/tst_qwebview.cpp @@ -142,7 +142,6 @@ void tst_QWebView::loadHtml() QWebView view; QCOMPARE(view.loadProgress(), 0); QSignalSpy loadChangedSingalSpy(&view, SIGNAL(loadingChanged(QWebViewLoadRequest))); - QSignalSpy javaScriptResultSpy(&view, SIGNAL(javaScriptResult(int, QVariant))); view.loadHtml(content, loadUrl); QTRY_COMPARE(view.loadProgress(), 100); QTRY_VERIFY(!view.isLoading()); @@ -151,15 +150,15 @@ void tst_QWebView::loadHtml() // take load finished const QWebViewLoadRequest &lr = loadChangedSingalSpy.at(1).at(0).value<QWebViewLoadRequest>(); QCOMPARE(lr.status(), QWebViewLoadRequest::LoadStatus::LoadSucceededStatus); - if (QWebViewFactory::loadedPluginHasKey("android_view")) { - // WebEngine javascript calls work only with qmlengine, however here we use - // c++ interface - int callback = 1; - view.runJavaScriptPrivate("document.baseURI", callback); - QTRY_COMPARE(javaScriptResultSpy.size(), 1); - QCOMPARE(javaScriptResultSpy.at(0).at(0), callback); - QCOMPARE(javaScriptResultSpy.at(0).at(1).value<QUrl>(), resultUrl); - } + bool called = false; + QUrl url; + auto callback = [&](const QVariant &result) { + called = true; + url = result.value<QUrl>(); + }; + view.runJavaScript("document.baseURI", callback); + QTRY_COMPARE(called, true); + QCOMPARE(url, resultUrl); QVERIFY(view.url().isValid()); QCOMPARE(view.url(), resultUrl); |
