diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/api/qwebenginecertificateerror.cpp | 13 | ||||
-rw-r--r-- | src/core/api/qwebenginecertificateerror.h | 2 | ||||
-rw-r--r-- | src/core/api/qwebengineframe.cpp | 74 | ||||
-rw-r--r-- | src/core/api/qwebengineframe.h | 10 | ||||
-rw-r--r-- | src/core/api/qwebenginepage.cpp | 55 | ||||
-rw-r--r-- | src/core/api/qwebenginepage.h | 3 | ||||
-rw-r--r-- | src/core/api/qwebenginepage_p.h | 5 | ||||
-rw-r--r-- | src/core/certificate_error_controller.cpp | 9 | ||||
-rw-r--r-- | src/core/certificate_error_controller.h | 4 | ||||
-rw-r--r-- | src/core/compositor/native_skia_output_device_direct3d11.cpp | 1 | ||||
-rw-r--r-- | src/core/compositor/native_skia_output_device_vulkan.cpp | 1 | ||||
-rw-r--r-- | src/core/content_browser_client_qt.cpp | 4 | ||||
-rw-r--r-- | src/core/doc/src/qtwebengine-overview.qdoc | 9 | ||||
-rw-r--r-- | src/core/doc/src/qwebengine-licensing.qdoc | 53 | ||||
-rw-r--r-- | src/core/doc/src/qwebenginepage_lgpl.qdoc | 13 | ||||
-rw-r--r-- | src/core/ozone/surface_factory_qt.cpp | 4 | ||||
-rw-r--r-- | src/core/web_contents_adapter.cpp | 79 | ||||
-rw-r--r-- | src/core/web_contents_adapter.h | 18 | ||||
-rw-r--r-- | src/core/web_contents_adapter_client.h | 4 |
19 files changed, 275 insertions, 86 deletions
diff --git a/src/core/api/qwebenginecertificateerror.cpp b/src/core/api/qwebenginecertificateerror.cpp index 90d8a542d..85c5d5127 100644 --- a/src/core/api/qwebenginecertificateerror.cpp +++ b/src/core/api/qwebenginecertificateerror.cpp @@ -88,6 +88,19 @@ QUrl QWebEngineCertificateError::url() const } /*! + \property QWebEngineCertificateError::isMainFrame + \since 6.8 + + Returns whether the certificate error comes from the main frame. If false, + the error comes from a sub-resource and most likely needs to be rejected without + user input. +*/ +bool QWebEngineCertificateError::isMainFrame() const +{ + return d->isMainFrame(); +} + +/*! Returns the type of the error. \sa description(), isOverridable() diff --git a/src/core/api/qwebenginecertificateerror.h b/src/core/api/qwebenginecertificateerror.h index c4a3585f4..3eef3dcca 100644 --- a/src/core/api/qwebenginecertificateerror.h +++ b/src/core/api/qwebenginecertificateerror.h @@ -24,6 +24,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineCertificateError Q_PROPERTY(Type type READ type CONSTANT FINAL) Q_PROPERTY(QString description READ description CONSTANT FINAL) Q_PROPERTY(bool overridable READ isOverridable CONSTANT FINAL) + Q_PROPERTY(bool isMainFrame READ isMainFrame CONSTANT FINAL REVISION(6, 8)) public: QWebEngineCertificateError(const QWebEngineCertificateError &other); @@ -57,6 +58,7 @@ public: QUrl url() const; bool isOverridable() const; QString description() const; + bool isMainFrame() const; Q_INVOKABLE void defer(); Q_INVOKABLE void rejectCertificate(); diff --git a/src/core/api/qwebengineframe.cpp b/src/core/api/qwebengineframe.cpp index edd89d663..1eedc4b92 100644 --- a/src/core/api/qwebengineframe.cpp +++ b/src/core/api/qwebengineframe.cpp @@ -3,6 +3,9 @@ #include "qwebengineframe.h" +#include "qwebenginescript.h" +#include <QtQml/qqmlengine.h> + #include "web_contents_adapter_client.h" #include "web_contents_adapter.h" @@ -101,6 +104,77 @@ QSizeF QWebEngineFrame::size() const return m_adapterClient->webContentsAdapter()->frameSize(m_id); } +/*! \fn void QWebEngineFrame::runJavaScript(const QString &script, const std::function<void(const QVariant &)> &callback) + \fn void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId) + \fn void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, const + std::function<void(const QVariant &)> &callback) + + Runs the JavaScript code contained in \a script on this frame, without checking + whether the DOM of the page has been constructed. + To avoid conflicts with other scripts executed on the page, the world in + which the script is run is specified by \a worldId. The world ID values are + the same as provided by QWebEngineScript::ScriptWorldId, and between \c 0 + and \c 256. If you leave out the \c world ID, the script is run in the + \c MainWorld. + When the script has been executed, \a callback is called with the result of the last + executed statement. \c callback can be any of a function pointer, a functor or a lambda, + and it is expected to take a QVariant parameter. For example: + \code + page.runJavaScript("document.title", [](const QVariant &v) { qDebug() << v.toString(); }); + \endcode + Only plain data can be returned from JavaScript as the result value. + Supported data types include all of the JSON data types as well as, for + example, \c{Date} and \c{ArrayBuffer}. Unsupported data types include, for + example, \c{Function} and \c{Promise}. + \warning Do not execute lengthy routines in the callback function, because it might block the + rendering of the web engine page. + \warning We guarantee that the \a callback is always called, but it might be + done during page destruction. When QWebEnginePage is deleted, the callback is triggered with an + invalid value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView + instance inside it. + \sa QWebEngineScript::ScriptWorldId, QWebEnginePage::runJavaScript, {Script Injection} + */ +void QWebEngineFrame::runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &callback) +{ + runJavaScript(script, QWebEngineScript::MainWorld, callback); +} + +void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, + const std::function<void(const QVariant &)> &callback) +{ + m_adapterClient->runJavaScript(script, worldId, m_id, callback); +} + +void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId) +{ + runJavaScript(script, worldId, std::function<void(const QVariant &)>{}); +} + +void QWebEngineFrame::runJavaScript(const QString &script, const QJSValue &callback) +{ + runJavaScript(script, QWebEngineScript::MainWorld, callback); +} + +void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, + const QJSValue &callback) +{ + std::function<void(const QVariant &)> wrappedCallback; + if (!callback.isUndefined()) { + const QObject *holdingObject = m_adapterClient->holdingQObject(); + wrappedCallback = [holdingObject, callback](const QVariant &result) { + if (auto engine = qmlEngine(holdingObject)) { + QJSValueList args; + args.append(engine->toScriptValue(result)); + callback.call(args); + } else { + qWarning("No QML engine found to execute runJavaScript() callback"); + } + }; + } + runJavaScript(script, worldId, wrappedCallback); +} + /*! \fn bool QWebEngineFrame::operator==(const QWebEngineFrame &left, const QWebEngineFrame &right) noexcept Returns \c{true} if \a left and \a right represent the same frame in the same web page, diff --git a/src/core/api/qwebengineframe.h b/src/core/api/qwebengineframe.h index e58961848..988d50d8e 100644 --- a/src/core/api/qwebengineframe.h +++ b/src/core/api/qwebengineframe.h @@ -6,6 +6,7 @@ #include <QtWebEngineCore/qtwebenginecoreglobal.h> #include <QtQml/qqmlregistration.h> +#include <QtQml/qjsvalue.h> #include <QtCore/qcompare.h> #include <QtCore/QList> #include <QtCore/QSizeF> @@ -39,6 +40,15 @@ public: QUrl url() const; QSizeF size() const; + void runJavaScript(const QString &script, + const std::function<void(const QVariant &)> &callback); + void runJavaScript(const QString &script, quint32 worldId, + const std::function<void(const QVariant &)> &callback); + Q_INVOKABLE void runJavaScript(const QString &script, quint32 worldId = 0); + Q_INVOKABLE void runJavaScript(const QString &script, const QJSValue &callback); + Q_INVOKABLE void runJavaScript(const QString &script, quint32 worldId, + const QJSValue &callback); + friend inline bool comparesEqual(const QWebEngineFrame &lhs, const QWebEngineFrame &rhs) noexcept { diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index c2a737d72..439214235 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -199,6 +199,12 @@ void QWebEnginePagePrivate::iconChanged(const QUrl &url) Q_EMIT q->iconChanged(iconUrl.isEmpty() ? QIcon() : adapter->icon()); } +void QWebEnginePagePrivate::zoomFactorChanged(qreal factor) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->zoomFactorChanged(factor); +} + void QWebEnginePagePrivate::loadProgressChanged(int progress) { Q_Q(QWebEnginePage); @@ -489,10 +495,16 @@ void QWebEnginePagePrivate::windowCloseRejected() // Do nothing for now. } -void QWebEnginePagePrivate::didRunJavaScript(quint64 requestId, const QVariant& result) +void QWebEnginePagePrivate::runJavaScript(const QString &script, quint32 worldId, quint64 frameId, + const std::function<void(const QVariant &)> &callback) { - if (auto callback = m_variantCallbacks.take(requestId)) - callback(result); + ensureInitialized(); + if (adapter->lifecycleState() == WebContentsAdapter::LifecycleState::Discarded) { + qWarning("runJavaScript: disabled in Discarded state"); + if (callback) + callback(QVariant()); + } else + adapter->runJavaScript(script, worldId, frameId, callback); } void QWebEnginePagePrivate::didFetchDocumentMarkup(quint64 requestId, const QString& result) @@ -971,11 +983,9 @@ QWebEnginePage::~QWebEnginePage() setDevToolsPage(nullptr); emit _q_aboutToDelete(); - for (auto varFun : std::as_const(d_ptr->m_variantCallbacks)) - varFun(QVariant()); + d_ptr->adapter->clearJavaScriptCallbacks(); for (auto strFun : std::as_const(d_ptr->m_stringCallbacks)) strFun(QString()); - d_ptr->m_variantCallbacks.clear(); d_ptr->m_stringCallbacks.clear(); } } @@ -2020,7 +2030,7 @@ void QWebEnginePage::setZoomFactor(qreal factor) Q_D(QWebEnginePage); d->defaultZoomFactor = factor; - if (d->adapter->isInitialized()) { + if (d->adapter->isInitialized() && !qFuzzyCompare(factor, zoomFactor())) { d->adapter->setZoomFactor(factor); // MEMO: should reset if factor was not applied due to being invalid d->defaultZoomFactor = zoomFactor(); @@ -2029,40 +2039,13 @@ void QWebEnginePage::setZoomFactor(qreal factor) void QWebEnginePage::runJavaScript(const QString& scriptSource, const std::function<void(const QVariant &)> &resultCallback) { - Q_D(QWebEnginePage); - d->ensureInitialized(); - if (d->adapter->lifecycleState() == WebContentsAdapter::LifecycleState::Discarded) { - qWarning("runJavaScript: disabled in Discarded state"); - if (resultCallback) - resultCallback(QVariant()); - return; - } - quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource, QWebEngineScript::MainWorld); - if (requestId) - d->m_variantCallbacks.insert(requestId, resultCallback); - else if (resultCallback) - resultCallback(QVariant()); + runJavaScript(scriptSource, QWebEngineScript::MainWorld, resultCallback); } void QWebEnginePage::runJavaScript(const QString& scriptSource, quint32 worldId, const std::function<void(const QVariant &)> &resultCallback) { Q_D(QWebEnginePage); - d->ensureInitialized(); - if (d->adapter->lifecycleState() == WebContentsAdapter::LifecycleState::Discarded) { - qWarning("runJavaScript: disabled in Discarded state"); - if (resultCallback) - resultCallback(QVariant()); - return; - } - if (resultCallback) { - quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource, worldId); - if (requestId) - d->m_variantCallbacks.insert(requestId, resultCallback); - else - resultCallback(QVariant()); - } else { - d->adapter->runJavaScript(scriptSource, worldId); - } + d->runJavaScript(scriptSource, worldId, WebContentsAdapter::kUseMainFrameId, resultCallback); } /*! diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h index e5a4e9551..13c582931 100644 --- a/src/core/api/qwebenginepage.h +++ b/src/core/api/qwebenginepage.h @@ -51,7 +51,7 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject Q_PROPERTY(QString selectedText READ selectedText) Q_PROPERTY(bool hasSelection READ hasSelection) Q_PROPERTY(QUrl requestedUrl READ requestedUrl) - Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged) Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) Q_PROPERTY(QUrl iconUrl READ iconUrl NOTIFY iconUrlChanged) @@ -344,6 +344,7 @@ Q_SIGNALS: void iconUrlChanged(const QUrl &url); void iconChanged(const QIcon &icon); + void zoomFactorChanged(qreal factor); void scrollPositionChanged(const QPointF &position); void contentsSizeChanged(const QSizeF &size); void audioMutedChanged(bool muted); diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h index 31ace7e9d..f0e179ea8 100644 --- a/src/core/api/qwebenginepage_p.h +++ b/src/core/api/qwebenginepage_p.h @@ -102,6 +102,7 @@ public: void titleChanged(const QString &) override; void urlChanged() override; void iconChanged(const QUrl &) override; + void zoomFactorChanged(qreal factor) override; void loadProgressChanged(int progress) override; void didUpdateTargetURL(const QUrl &) override; void selectionChanged() override; @@ -130,7 +131,8 @@ public: void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) override; void runFileChooser(QSharedPointer<QtWebEngineCore::FilePickerController>) override; void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>) override; - void didRunJavaScript(quint64 requestId, const QVariant &result) override; + void runJavaScript(const QString &script, quint32 worldId, quint64 frameId, + const std::function<void(const QVariant &)> &callback) override; void didFetchDocumentMarkup(quint64 requestId, const QString &result) override; void didFetchDocumentInnerText(quint64 requestId, const QString &result) override; void didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) override; @@ -214,7 +216,6 @@ public: QPrinter *currentPrinter = nullptr; #endif - mutable QMap<quint64, std::function<void(const QVariant &)>> m_variantCallbacks; mutable QMap<quint64, std::function<void(const QString &)>> m_stringCallbacks; QMap<quint64, std::function<void(const QByteArray &)>> m_pdfResultCallbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp index 014d74500..51f9f3edb 100644 --- a/src/core/certificate_error_controller.cpp +++ b/src/core/certificate_error_controller.cpp @@ -77,10 +77,12 @@ static int IsCertErrorFatal(int cert_error) CertificateErrorController::CertificateErrorController( int cert_error, const net::SSLInfo &ssl_info, const GURL &request_url, - bool strict_enforcement, base::OnceCallback<void(content::CertificateRequestResultType)> cb) + bool main_frame, bool strict_enforcement, + base::OnceCallback<void(content::CertificateRequestResultType)> cb) : m_certError(QWebEngineCertificateError::Type(cert_error)) , m_requestUrl(toQt(request_url)) , m_overridable(!IsCertErrorFatal(cert_error) && !strict_enforcement) + , m_mainFrame(main_frame) { // MEMO set callback anyway even for non overridable error since chromium halts load until it's called // callback will be executed either explicitly by use code or implicitly when error goes out of scope @@ -204,4 +206,9 @@ QList<QSslCertificate> CertificateErrorController::certificateChain() const return m_certificateChain; } +bool CertificateErrorController::isMainFrame() const +{ + return m_mainFrame; +} + } diff --git a/src/core/certificate_error_controller.h b/src/core/certificate_error_controller.h index cbcb60f8a..b0d38fd57 100644 --- a/src/core/certificate_error_controller.h +++ b/src/core/certificate_error_controller.h @@ -37,7 +37,7 @@ class Q_WEBENGINECORE_EXPORT CertificateErrorController { public: CertificateErrorController( int cert_error, const net::SSLInfo &ssl_info, const GURL &request_url, - bool strict_enforcement, + bool main_frame, bool strict_enforcement, base::OnceCallback<void(content::CertificateRequestResultType)> callback); ~CertificateErrorController(); @@ -47,6 +47,7 @@ public: QString errorString() const; QDateTime validExpiry() const; QList<QSslCertificate> certificateChain() const; + bool isMainFrame() const; bool deferred() const; void defer(); @@ -65,6 +66,7 @@ public: bool m_overridable; base::OnceCallback<void(content::CertificateRequestResultType)> m_callback; QList<QSslCertificate> m_certificateChain; + bool m_mainFrame; bool m_answered = false, m_deferred = false; diff --git a/src/core/compositor/native_skia_output_device_direct3d11.cpp b/src/core/compositor/native_skia_output_device_direct3d11.cpp index 352fa9f92..2f1ed5f61 100644 --- a/src/core/compositor/native_skia_output_device_direct3d11.cpp +++ b/src/core/compositor/native_skia_output_device_direct3d11.cpp @@ -56,6 +56,7 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_ status = resource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ, NULL, &sharedHandle); Q_ASSERT(status == S_OK); Q_ASSERT(sharedHandle); + resource->Release(); // Pass texture between two D3D devices: ID3D11Device1 *device = static_cast<ID3D11Device1 *>( diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index c2ad7a382..f51eba985 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -187,6 +187,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te Q_ASSERT(status == S_OK); status = resource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ, NULL, &sharedHandle); Q_ASSERT(status == S_OK); + resource->Release(); if (!sharedHandle) qFatal("VULKAN: Unable to extract shared handle."); diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 7192edbc2..28ed6ef7c 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -276,14 +276,14 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont int cert_error, const net::SSLInfo &ssl_info, const GURL &request_url, - bool /* is_main_frame_request */, + bool is_main_frame_request, bool strict_enforcement, base::OnceCallback<void(content::CertificateRequestResultType)> callback) { WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); QSharedPointer<CertificateErrorController> errorController(new CertificateErrorController( - cert_error, ssl_info, request_url, strict_enforcement, std::move(callback))); + cert_error, ssl_info, request_url, is_main_frame_request, strict_enforcement, std::move(callback))); contentsDelegate->allowCertificateError(errorController); } diff --git a/src/core/doc/src/qtwebengine-overview.qdoc b/src/core/doc/src/qtwebengine-overview.qdoc index 6eccc669e..3a5d30338 100644 --- a/src/core/doc/src/qtwebengine-overview.qdoc +++ b/src/core/doc/src/qtwebengine-overview.qdoc @@ -44,8 +44,13 @@ dedicated profile for a \e {private browsing} mode, where no information is permanently saved. \note The \QWE Widgets module uses the \l{Qt Quick Scene Graph}{Qt Quick scene graph} - to compose the elements of a web page into one view. This means that the UI process - requires OpenGL ES 2.0 or OpenGL 2.0 for its rendering. + to compose the elements of a web page into one view. + + The content is rendered using the graphics card (GPU) capabilities. The scene + graph, in turn, relies on the Qt Rendering Hardware Interface as an abstraction + layer for the different capabilities and APIs a GPU might feature. For more + advice on how to tweak the rendering pipeline, see therefore + \l{Rendering via the Qt Rendering Hardware Interface}. \section2 Qt WebEngine Module diff --git a/src/core/doc/src/qwebengine-licensing.qdoc b/src/core/doc/src/qwebengine-licensing.qdoc index 796a9664d..936ceff97 100644 --- a/src/core/doc/src/qwebengine-licensing.qdoc +++ b/src/core/doc/src/qwebengine-licensing.qdoc @@ -5,20 +5,49 @@ \group qtwebengine-licensing \title Qt WebEngine Licensing -The Qt specific parts of the \QWE module are dual-licensed -under Commercial and GNU Lesser General Public License (LGPLv3). -In addition, the module contains code licensed under LGPLv2. - -The module includes a snapshot of Chromium. As such, users need to -respect the licenses of Chromium, and third-party code included in -Chromium. The arguably most restrictive license to be respected by -all users is LGPLv2.1. +The \QWE module uses Chromium to provide most of its +functionality. During the build process, Chromium becomes +a part of the \l{Qt WebEngine Core} library. +Therefore, when distributing \QWE, users need to comply +to both the licenses of the \QWE part as developed under +the Qt Project, as well as the licenses that are part of +Chromium. + +The Qt specific parts of the \QWE module are available under +commercial licenses from The Qt Company. Alternatively, +they are available under GNU Lesser General Public License v3.0, +or GNU General Public License v3.0, or +GNU General Public License v2.0. + +The Chromium part contains code available under various +licenses, with the most restrictive license being the +\e{GNU Lesser General Public License v2.1} (LGPL 2.1). +For a full list, see \l{Third-Party Licenses} below. + +\section1 Complying with LGPL 2.1 + +The Qt Company allows commercial customers to +distribute the source code of the \QWE module alongside the +\QWE binaries, and allows recipients to customize and build +\QWE from sources. This includes building and using +such a modified \QWE with an application or system using +an otherwise commercially licensed Qt. + +The Qt Company also keeps the Qt specific parts of the \QWE +module available under the GNU Lesser General Public License v3.0, +or the GNU General Public License v3.0, or +the GNU General Public License v2.0, even if WebEngine is released +as part of a commercial-only Long-Term Support release (LTS, see +also \l{Long-Term Support releases}). + +\section1 Third-Party Licenses + +Third party licenses included in the sources as part of Chromium +are found below. \note Any GPL licenses listed below are only used to access Linux system -resources. \QWE does not link to nor distribute GPL binary code, and -it does not affect users of \QWE. - -Third party licenses included in the sources are: +resources. The \QWE libraries and plugins does not link to nor distribute +GPL binary code, and it does not affect users of \QWE. */ /*! diff --git a/src/core/doc/src/qwebenginepage_lgpl.qdoc b/src/core/doc/src/qwebenginepage_lgpl.qdoc index c2515cd13..1640ca8be 100644 --- a/src/core/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/core/doc/src/qwebenginepage_lgpl.qdoc @@ -735,6 +735,8 @@ \brief The zoom factor for the page content. Valid values are within the range from \c{0.25} to \c{5.0}. The default factor is \c{1.0}. + + \sa zoomFactorChanged() */ /*! @@ -772,7 +774,7 @@ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. - \sa scripts(), QWebEngineScript::ScriptWorldId, {Script Injection} + \sa scripts(), QWebEngineScript::ScriptWorldId, QWebEngineFrame::runJavaScript, {Script Injection} */ /*! @@ -836,3 +838,12 @@ \sa QWebEngineWebAuthUxRequest */ + +/*! + \fn void QWebEnginePage::zoomFactorChanged(qreal factor) + \since 6.8 + + This signal is emitted whenever the zoom \a factor for the page changes. + + \sa zoomFactor(), setZoomFactor() +*/ diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index 04e6ec28f..2d311a02a 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -226,7 +226,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( int fd = fds[i]; int stride = strides[i]; int offset = offsets[i]; - int size = handle.planes[i].size; + int planeSize = handle.planes[i].size; if (fd == -1) { fd = fds[0]; @@ -234,7 +234,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( offset = handle.planes[i].offset; } - gfx::NativePixmapPlane plane(stride, offset, size, base::ScopedFD(::dup(fd))); + gfx::NativePixmapPlane plane(stride, offset, planeSize, base::ScopedFD(::dup(fd))); bufferHandle.planes.push_back(std::move(plane)); } diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 6decf8780..b06ed2121 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -174,10 +174,9 @@ static QVariant fromJSValue(const base::Value *result) return ret; } -static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint64 requestId, base::Value result) +static void callbackOnEvaluateJS(WebContentsAdapter *adapter, quint64 requestId, base::Value result) { - if (requestId) - adapterClient->didRunJavaScript(requestId, fromJSValue(&result)); + adapter->didRunJavaScript(requestId, result); } #if QT_CONFIG(webengine_printing_and_pdf) @@ -993,6 +992,9 @@ void WebContentsAdapter::setZoomFactor(qreal factor) const content::GlobalRenderFrameHostId global_id = m_webContents->GetPrimaryMainFrame()->GetGlobalId(); zoomMap->SetTemporaryZoomLevel(global_id, zoomLevel); } + + if (m_adapterClient) + m_adapterClient->zoomFactorChanged(currentZoomFactor()); } qreal WebContentsAdapter::currentZoomFactor() const @@ -1039,36 +1041,67 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible() } #endif // QT_CONFIG(accessibility) -void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId) +content::RenderFrameHost *WebContentsAdapter::renderFrameHostFromFrameId(quint64 frameId) const { - CHECK_INITIALIZED(); - content::RenderFrameHost *rfh = m_webContents->GetPrimaryMainFrame(); - Q_ASSERT(rfh); - if (!static_cast<content::RenderFrameHostImpl*>(rfh)->GetAssociatedLocalFrame()) { - qWarning() << "Local frame is gone, not running script"; - return; + content::RenderFrameHost *result; + if (frameId == kUseMainFrameId) { + result = m_webContents->GetPrimaryMainFrame(); + } else { + auto *ftn = content::FrameTreeNode::GloballyFindByID(static_cast<int>(frameId)); + if (!ftn) + return nullptr; + + result = ftn->current_frame_host(); } - if (worldId == 0) - rfh->ExecuteJavaScript(toString16(javaScript), base::NullCallback()); - else - rfh->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), base::NullCallback(), worldId); + Q_ASSERT(result); + return result; } -quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId) +void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId, quint64 frameId, + const std::function<void(const QVariant &)> &callback) { - CHECK_INITIALIZED(0); - content::RenderFrameHost *rfh = m_webContents->GetPrimaryMainFrame(); - Q_ASSERT(rfh); + auto exit = [&] { + if (callback) + callback(QVariant()); + }; + + if (!isInitialized()) + return exit(); + auto *rfh = renderFrameHostFromFrameId(frameId); + if (!rfh) + return exit(); if (!static_cast<content::RenderFrameHostImpl*>(rfh)->GetAssociatedLocalFrame()) { qWarning() << "Local frame is gone, not running script"; - return 0; + return exit(); + } + + content::RenderFrameHost::JavaScriptResultCallback internalCallback = base::NullCallback(); + if (callback) { + internalCallback = base::BindOnce(&callbackOnEvaluateJS, this, m_nextRequestId); + m_javaScriptCallbacks.insert(m_nextRequestId, callback); + ++m_nextRequestId; } - content::RenderFrameHost::JavaScriptResultCallback callback = base::BindOnce(&callbackOnEvaluateJS, m_adapterClient, m_nextRequestId); if (worldId == 0) - rfh->ExecuteJavaScript(toString16(javaScript), std::move(callback)); + rfh->ExecuteJavaScript(toString16(javaScript), std::move(internalCallback)); else - rfh->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), std::move(callback), worldId); - return m_nextRequestId++; + rfh->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), std::move(internalCallback), + worldId); +} + +void WebContentsAdapter::didRunJavaScript(quint64 requestId, const base::Value &result) +{ + Q_ASSERT(requestId); + auto callback = m_javaScriptCallbacks.take(requestId); + Q_ASSERT(callback); + callback(fromJSValue(&result)); +} + +// Called when QWebEnginePage is deleted +void WebContentsAdapter::clearJavaScriptCallbacks() +{ + for (auto varFun : std::as_const(m_javaScriptCallbacks)) + varFun(QVariant()); + m_javaScriptCallbacks.clear(); } quint64 WebContentsAdapter::fetchDocumentMarkup() diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index a5cad8664..24de7eb1b 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -16,8 +16,10 @@ #define WEB_CONTENTS_ADAPTER_H #include <QtCore/QSharedPointer> +#include <QtCore/QMap> #include <QtCore/QString> #include <QtCore/QUrl> +#include <QtCore/QVariant> #include <QtCore/QPointer> #include <QtGui/qtgui-config.h> #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h> @@ -27,6 +29,7 @@ #include "web_contents_adapter_client.h" +#include <functional> #include <memory> #include <optional> @@ -36,9 +39,14 @@ struct WebPreferences; } } +namespace base { +class Value; +} + namespace content { class WebContents; class SiteInstance; +class RenderFrameHost; } QT_BEGIN_NAMESPACE @@ -64,6 +72,8 @@ class WebChannelIPCTransportHost; class Q_WEBENGINECORE_EXPORT WebContentsAdapter : public QEnableSharedFromThis<WebContentsAdapter> { public: + // Sentinel to indicate that a behavior should happen on the main frame + static constexpr quint64 kUseMainFrameId = -2; // Sentinel to indicate a frame doesn't exist, for example with `findFrameByName` static constexpr quint64 kInvalidFrameId = -3; @@ -129,8 +139,10 @@ public: void serializeNavigationHistory(QDataStream &output); void setZoomFactor(qreal); qreal currentZoomFactor() const; - void runJavaScript(const QString &javaScript, quint32 worldId); - quint64 runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId); + void runJavaScript(const QString &javaScript, quint32 worldId, quint64 frameId, + const std::function<void(const QVariant &)> &callback); + void didRunJavaScript(quint64 requestId, const base::Value &result); + void clearJavaScriptCallbacks(); quint64 fetchDocumentMarkup(); quint64 fetchDocumentInnerText(); void updateWebPreferences(const blink::web_pref::WebPreferences &webPreferences); @@ -230,6 +242,7 @@ private: Q_DISABLE_COPY(WebContentsAdapter) void waitForUpdateDragActionCalled(); bool handleDropDataFileContents(const content::DropData &dropData, QMimeData *mimeData); + content::RenderFrameHost *renderFrameHostFromFrameId(quint64 frameId) const; void wasShown(); void wasHidden(); @@ -255,6 +268,7 @@ private: WebContentsAdapterClient *m_adapterClient; quint64 m_nextRequestId; QMap<QUrl, bool> m_pendingMouseLockPermissions; + QMap<quint64, std::function<void(const QVariant &)>> m_javaScriptCallbacks; std::unique_ptr<content::DropData> m_currentDropData; uint m_currentDropAction; bool m_updateDragActionCalled; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index a1ad301ed..4c664fd21 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -147,6 +147,7 @@ public: virtual void titleChanged(const QString&) = 0; virtual void urlChanged() = 0; virtual void iconChanged(const QUrl&) = 0; + virtual void zoomFactorChanged(qreal factor) = 0; virtual void loadProgressChanged(int progress) = 0; virtual void didUpdateTargetURL(const QUrl&) = 0; virtual void selectionChanged() = 0; @@ -175,7 +176,8 @@ public: virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) = 0; virtual void runFileChooser(QSharedPointer<FilePickerController>) = 0; virtual void showColorDialog(QSharedPointer<ColorChooserController>) = 0; - virtual void didRunJavaScript(quint64 requestId, const QVariant& result) = 0; + virtual void runJavaScript(const QString &script, quint32 worldId, quint64 frameId, + const std::function<void(const QVariant &)> &callback) = 0; virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) = 0; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; virtual void didPrintPage(quint64 requestId, QSharedPointer<QByteArray>) = 0; |