summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
m---------src/3rdparty0
-rw-r--r--src/core/api/CMakeLists.txt1
-rw-r--r--src/core/api/qwebenginecertificateerror.cpp13
-rw-r--r--src/core/api/qwebenginecertificateerror.h2
-rw-r--r--src/core/api/qwebengineframe.cpp118
-rw-r--r--src/core/api/qwebengineframe.h62
-rw-r--r--src/core/api/qwebenginenavigationrequest.cpp27
-rw-r--r--src/core/api/qwebenginenavigationrequest.h4
-rw-r--r--src/core/api/qwebenginepage.cpp86
-rw-r--r--src/core/api/qwebenginepage.h10
-rw-r--r--src/core/api/qwebenginepage_p.h7
-rw-r--r--src/core/certificate_error_controller.cpp9
-rw-r--r--src/core/certificate_error_controller.h4
-rw-r--r--src/core/compositor/native_skia_output_device.cpp8
-rw-r--r--src/core/compositor/native_skia_output_device_direct3d11.cpp1
-rw-r--r--src/core/compositor/native_skia_output_device_mac.mm9
-rw-r--r--src/core/compositor/native_skia_output_device_metal.cpp21
-rw-r--r--src/core/compositor/native_skia_output_device_metal.h3
-rw-r--r--src/core/compositor/native_skia_output_device_opengl.cpp2
-rw-r--r--src/core/compositor/native_skia_output_device_vulkan.cpp1
-rw-r--r--src/core/content_browser_client_qt.cpp7
-rw-r--r--src/core/doc/src/qwebengine-licensing.qdoc53
-rw-r--r--src/core/doc/src/qwebenginepage_lgpl.qdoc11
-rw-r--r--src/core/favicon_driver_qt.cpp7
-rw-r--r--src/core/favicon_driver_qt.h3
-rw-r--r--src/core/native_web_keyboard_event_qt_mac.mm2
-rw-r--r--src/core/ozone/gl_context_qt.cpp40
-rw-r--r--src/core/ozone/gl_context_qt.h10
-rw-r--r--src/core/ozone/ozone_platform_qt.cpp10
-rw-r--r--src/core/ozone/surface_factory_qt.cpp33
-rw-r--r--src/core/ozone/surface_factory_qt.h2
-rw-r--r--src/core/render_view_context_menu_qt.h2
-rw-r--r--src/core/web_contents_adapter.cpp134
-rw-r--r--src/core/web_contents_adapter.h28
-rw-r--r--src/core/web_contents_adapter_client.h6
-rw-r--r--src/core/web_contents_delegate_qt.cpp2
-rw-r--r--src/core/web_engine_context.cpp364
-rw-r--r--src/pdf/doc/snippets/pdfpageview.qml12
-rw-r--r--src/pdfquick/PdfPageView.qml2
-rw-r--r--src/pdfwidgets/qpdfview.cpp6
-rw-r--r--src/webenginequick/CMakeLists.txt6
-rw-r--r--src/webenginequick/api/qquickwebenginefaviconprovider.cpp224
-rw-r--r--src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h83
-rw-r--r--src/webenginequick/api/qquickwebengineprofile.cpp4
-rw-r--r--src/webenginequick/api/qquickwebengineprofile.h2
-rw-r--r--src/webenginequick/api/qquickwebengineview.cpp76
-rw-r--r--src/webenginequick/api/qquickwebengineview_p.h9
-rw-r--r--src/webenginequick/api/qquickwebengineview_p_p.h12
-rw-r--r--src/webenginequick/doc/src/webengineframe.qdoc65
-rw-r--r--src/webenginequick/doc/src/webengineview_lgpl.qdoc34
-rw-r--r--src/webenginequick/qquickwebengine_accessible.cpp2
-rw-r--r--src/webenginequick/qquickwebengine_accessible_p.h (renamed from src/webenginequick/qquickwebengine_accessible.h)11
-rw-r--r--src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp2
-rw-r--r--src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h (renamed from src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.h)11
-rw-r--r--src/webenginequick/ui_delegates_manager.cpp2
-rw-r--r--src/webenginequick/ui_delegates_manager_p.h (renamed from src/webenginequick/ui_delegates_manager.h)11
-rw-r--r--src/webenginewidgets/CMakeLists.txt2
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp2
-rw-r--r--src/webenginewidgets/qwebengine_accessible.cpp2
-rw-r--r--src/webenginewidgets/qwebengine_accessible_p.h (renamed from src/webenginewidgets/qwebengine_accessible.h)11
60 files changed, 1286 insertions, 407 deletions
diff --git a/src/3rdparty b/src/3rdparty
-Subproject c60705f47d06c2059743e8170de8e805880a741
+Subproject 814db44bc99f79d0c4a847e0cac4a398034ee2f
diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt
index f2ceb2dfd..c06f5e4ce 100644
--- a/src/core/api/CMakeLists.txt
+++ b/src/core/api/CMakeLists.txt
@@ -19,6 +19,7 @@ qt_internal_add_module(WebEngineCore
qwebenginedownloadrequest.cpp qwebenginedownloadrequest.h qwebenginedownloadrequest_p.h
qwebenginefilesystemaccessrequest.cpp qwebenginefilesystemaccessrequest.h
qwebenginefindtextresult.cpp qwebenginefindtextresult.h
+ qwebengineframe.cpp qwebengineframe.h
qwebenginefullscreenrequest.cpp qwebenginefullscreenrequest.h
qwebenginehistory.cpp qwebenginehistory.h qwebenginehistory_p.h
qwebenginehttprequest.cpp qwebenginehttprequest.h
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
new file mode 100644
index 000000000..edd89d663
--- /dev/null
+++ b/src/core/api/qwebengineframe.cpp
@@ -0,0 +1,118 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwebengineframe.h"
+
+#include "web_contents_adapter_client.h"
+#include "web_contents_adapter.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWebEngineFrame
+ \brief The QWebEngineFrame class gives information about and control over a page frame.
+ \since 6.8
+
+ \inmodule QtWebEngineCore
+
+ A web engine frame represents a single frame within a web page, such as those created by
+ \c <frame> or \c <iframe> HTML elements.
+ An active QWebEnginePage has one or more frames arranged in a tree structure. The top-level
+ frame, the root of this tree, can be accessed through the mainFrame() method, and
+ children() provides a frame's direct descendants.
+
+ A frame's lifetime is, at most, as long as the QWebEnginePage object that produced it.
+ However, frames may be created and deleted spontaneously and dynamically, for example through
+ navigation and script execution. Because of this, many QWebEngineFrame methods return
+ optional values, which will be \c std::nullopt if the frame no longer exists.
+*/
+
+/*! \internal
+ */
+QWebEngineFrame::QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *adapter, quint64 id)
+ : m_adapterClient(adapter), m_id(id)
+{
+}
+
+/*!
+ Returns \c{true} if this object represents an existing frame; \c{false} otherwise.
+
+ Once a frame is invalid, it never becomes valid again.
+*/
+bool QWebEngineFrame::isValid() const
+{
+ return m_adapterClient->webContentsAdapter()->hasFrame(m_id);
+}
+
+/*!
+ Returns the frame name; that is, what would be returned by \c window.name in JavaScript.
+
+ If the frame could not be found, returns a null QString.
+
+ \sa htmlName
+*/
+QString QWebEngineFrame::name() const
+{
+ return m_adapterClient->webContentsAdapter()->frameName(m_id);
+}
+
+/*!
+ Returns the value of the frame's \c name HTML attribute, or an empty string if it has none.
+
+ If the frame could not be found, returns a null QString.
+
+ \sa name
+*/
+QString QWebEngineFrame::htmlName() const
+{
+ return m_adapterClient->webContentsAdapter()->frameHtmlName(m_id);
+}
+
+/*!
+ Returns a list of the frame's children in an arbitrary order.
+
+ If the frame could not be found, returns an empty list.
+ */
+QList<QWebEngineFrame> QWebEngineFrame::children() const
+{
+ QList<QWebEngineFrame> result;
+ for (auto childId : m_adapterClient->webContentsAdapter()->frameChildren(m_id))
+ result.push_back(QWebEngineFrame{ m_adapterClient, childId });
+ return result;
+}
+
+/*!
+ Returns the URL of the content currently loaded in this frame.
+
+ If the frame could not be found, returns an empty QUrl.
+ */
+QUrl QWebEngineFrame::url() const
+{
+ return m_adapterClient->webContentsAdapter()->frameUrl(m_id);
+}
+
+/*!
+ Returns the size of the frame within the viewport.
+
+ If the frame could not be found, returns QSizeF().
+ */
+QSizeF QWebEngineFrame::size() const
+{
+ return m_adapterClient->webContentsAdapter()->frameSize(m_id);
+}
+
+/*! \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,
+ otherwise \c{false}.
+ */
+
+/*! \fn bool QWebEngineFrame::operator!=(const QWebEngineFrame &left, const QWebEngineFrame &right) noexcept
+
+ Returns \c{true} if \a left and \a right represent different frames in the same web page,
+ otherwise \c{false}.
+ */
+
+QT_END_NAMESPACE
+
+#include "moc_qwebengineframe.cpp"
diff --git a/src/core/api/qwebengineframe.h b/src/core/api/qwebengineframe.h
new file mode 100644
index 000000000..e58961848
--- /dev/null
+++ b/src/core/api/qwebengineframe.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWEBENGINEFRAME_H
+#define QWEBENGINEFRAME_H
+
+#include <QtWebEngineCore/qtwebenginecoreglobal.h>
+#include <QtQml/qqmlregistration.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/QList>
+#include <QtCore/QSizeF>
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+
+namespace QtWebEngineCore {
+class WebContentsAdapterClient;
+}
+
+QT_BEGIN_NAMESPACE
+
+class Q_WEBENGINECORE_EXPORT QWebEngineFrame
+{
+ Q_GADGET
+
+ Q_PROPERTY(bool isValid READ isValid FINAL)
+ Q_PROPERTY(QString name READ name FINAL)
+ Q_PROPERTY(QString htmlName READ htmlName FINAL)
+ Q_PROPERTY(QUrl url READ url FINAL)
+ Q_PROPERTY(QSizeF size READ size FINAL)
+
+public:
+ QML_VALUE_TYPE(webEngineFrame)
+ QML_ADDED_IN_VERSION(6, 8)
+
+ bool isValid() const;
+ QString name() const;
+ QString htmlName() const;
+ QList<QWebEngineFrame> children() const;
+ QUrl url() const;
+ QSizeF size() const;
+
+ friend inline bool comparesEqual(const QWebEngineFrame &lhs,
+ const QWebEngineFrame &rhs) noexcept
+ {
+ return lhs.m_adapterClient == rhs.m_adapterClient && lhs.m_id == rhs.m_id;
+ }
+
+ Q_DECLARE_EQUALITY_COMPARABLE(QWebEngineFrame);
+
+private:
+ friend class QWebEnginePage;
+ friend class QQuickWebEngineView;
+
+ QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *page, quint64 id);
+
+ QtWebEngineCore::WebContentsAdapterClient *m_adapterClient;
+ quint64 m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBENGINEFRAME_H
diff --git a/src/core/api/qwebenginenavigationrequest.cpp b/src/core/api/qwebenginenavigationrequest.cpp
index 0a30f6472..dc7447b88 100644
--- a/src/core/api/qwebenginenavigationrequest.cpp
+++ b/src/core/api/qwebenginenavigationrequest.cpp
@@ -9,15 +9,17 @@ QT_BEGIN_NAMESPACE
class QWebEngineNavigationRequestPrivate {
public:
- QWebEngineNavigationRequestPrivate(const QUrl& url, QWebEngineNavigationRequest::NavigationType navigationType, bool mainFrame)
+ QWebEngineNavigationRequestPrivate(const QUrl& url, QWebEngineNavigationRequest::NavigationType navigationType, bool mainFrame, bool formData)
: url(url)
, navigationType(navigationType)
, isMainFrame(mainFrame)
+ , hasFormData(formData)
{}
QUrl url;
QWebEngineNavigationRequest::NavigationType navigationType;
bool isMainFrame;
+ bool hasFormData;
bool isAccepted = true;
};
@@ -51,9 +53,9 @@ public:
/*! \internal
*/
-QWebEngineNavigationRequest::QWebEngineNavigationRequest(const QUrl& url, QWebEngineNavigationRequest::NavigationType navigationType, bool mainFrame, QObject* parent)
+QWebEngineNavigationRequest::QWebEngineNavigationRequest(const QUrl& url, QWebEngineNavigationRequest::NavigationType navigationType, bool mainFrame, bool formData, QObject* parent)
: QObject(parent)
- , d_ptr(new QWebEngineNavigationRequestPrivate(url, navigationType, mainFrame))
+ , d_ptr(new QWebEngineNavigationRequestPrivate(url, navigationType, mainFrame, formData))
{
}
@@ -174,6 +176,25 @@ bool QWebEngineNavigationRequest::isMainFrame() const
return d->isMainFrame;
}
+/*!
+ \property QWebEngineNavigationRequest::hasFormData
+ \brief Whether the navigation request contains form data
+ \since 6.8
+*/
+/*!
+ \qmlproperty bool WebEngineNavigationRequest::hasFormData
+ \since 6.8
+ \readonly
+
+ Whether the navigation request contains form data
+*/
+
+bool QWebEngineNavigationRequest::hasFormData() const
+{
+ Q_D(const QWebEngineNavigationRequest);
+ return d->hasFormData;
+}
+
/*! \internal */
bool QWebEngineNavigationRequest::isAccepted() const
{
diff --git a/src/core/api/qwebenginenavigationrequest.h b/src/core/api/qwebenginenavigationrequest.h
index 12fc2b4a1..a810a59fe 100644
--- a/src/core/api/qwebenginenavigationrequest.h
+++ b/src/core/api/qwebenginenavigationrequest.h
@@ -17,6 +17,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineNavigationRequest : public QObject
Q_OBJECT
Q_PROPERTY(QUrl url READ url CONSTANT FINAL)
Q_PROPERTY(bool isMainFrame READ isMainFrame CONSTANT FINAL)
+ Q_PROPERTY(bool hasFormData READ hasFormData CONSTANT REVISION(6, 8) FINAL)
Q_PROPERTY(NavigationType navigationType READ navigationType CONSTANT FINAL)
public:
@@ -36,6 +37,7 @@ public:
QUrl url() const;
bool isMainFrame() const;
+ bool hasFormData() const;
NavigationType navigationType() const;
Q_INVOKABLE void accept();
@@ -60,7 +62,7 @@ Q_SIGNALS:
#endif
private:
- QWebEngineNavigationRequest(const QUrl &url, NavigationType navigationType, bool mainFrame,
+ QWebEngineNavigationRequest(const QUrl &url, NavigationType navigationType, bool mainFrame, bool formData,
QObject *parent = nullptr);
friend class QWebEnginePagePrivate;
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp
index ac645c430..489a90518 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,
+ 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, 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();
}
}
@@ -1516,13 +1526,13 @@ void QWebEnginePagePrivate::contextMenuRequested(QWebEngineContextMenuRequest *d
\sa acceptNavigationRequest()
*/
-void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame)
+void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame, bool hasFormData)
{
Q_Q(QWebEnginePage);
accepted = q->acceptNavigationRequest(url, static_cast<QWebEnginePage::NavigationType>(navigationType), isMainFrame);
if (accepted) {
- QWebEngineNavigationRequest navigationRequest(url, static_cast<QWebEngineNavigationRequest::NavigationType>(navigationType), isMainFrame);
+ QWebEngineNavigationRequest navigationRequest(url, static_cast<QWebEngineNavigationRequest::NavigationType>(navigationType), isMainFrame, hasFormData);
Q_EMIT q->navigationRequested(navigationRequest);
accepted = navigationRequest.isAccepted();
}
@@ -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, resultCallback);
}
/*!
@@ -2501,6 +2484,33 @@ void QWebEnginePage::setVisible(bool visible)
d->adapter->setVisible(visible);
}
+/*!
+ \since 6.8
+
+ The main, top-level frame of the page. All other frames on this page are accessible
+ as children of the main frame.
+*/
+QWebEngineFrame QWebEnginePage::mainFrame()
+{
+ Q_D(QWebEnginePage);
+ return QWebEngineFrame(d, d->adapter->mainFrameId());
+}
+
+/*!
+ \since 6.8
+
+ Returns the frame with the given \a name. If there are multiple frames with the same
+ name, which one is returned is arbitrary. If no frame was found, returns \c std::nullopt.
+*/
+std::optional<QWebEngineFrame> QWebEnginePage::findFrameByName(const QString &name)
+{
+ Q_D(QWebEnginePage);
+ if (auto maybeId = d->adapter->findFrameIdByName(name)) {
+ return QWebEngineFrame(d, *maybeId);
+ }
+ return {};
+}
+
QDataStream &operator<<(QDataStream &stream, const QWebEngineHistory &history)
{
auto adapter = history.d_func()->adapter();
diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h
index 621dacdc8..13c582931 100644
--- a/src/core/api/qwebenginepage.h
+++ b/src/core/api/qwebenginepage.h
@@ -8,6 +8,7 @@
#include <QtWebEngineCore/qwebengineclientcertificateselection.h>
#include <QtWebEngineCore/qwebenginedownloadrequest.h>
#include <QtWebEngineCore/qwebenginequotarequest.h>
+#include <QtWebEngineCore/qwebengineframe.h>
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
@@ -16,6 +17,7 @@
#include <QtGui/qtgui-config.h>
#include <functional>
+#include <optional>
QT_BEGIN_NAMESPACE
@@ -49,8 +51,8 @@ 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(QString title READ title)
+ 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)
Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
@@ -301,6 +303,9 @@ public:
bool isVisible() const;
void setVisible(bool visible);
+ QWebEngineFrame mainFrame();
+ std::optional<QWebEngineFrame> findFrameByName(const QString &name);
+
void acceptAsNewWindow(QWebEngineNewWindowRequest &request);
Q_SIGNALS:
@@ -339,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 a51d8603b..92b4c19f5 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;
@@ -124,13 +125,14 @@ public:
void windowCloseRejected() override;
void desktopMediaRequested(QtWebEngineCore::DesktopMediaController *) override;
void contextMenuRequested(QWebEngineContextMenuRequest *request) override;
- void navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame) override;
+ void navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame, bool hasFormData) override;
void requestFullScreenMode(const QUrl &origin, bool fullscreen) override;
bool isFullScreenMode() const override;
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,
+ 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.cpp b/src/core/compositor/native_skia_output_device.cpp
index 8f11e5162..708692df7 100644
--- a/src/core/compositor/native_skia_output_device.cpp
+++ b/src/core/compositor/native_skia_output_device.cpp
@@ -309,11 +309,13 @@ std::vector<GrBackendSemaphore> NativeSkiaOutputDevice::Buffer::takeEndWriteSkia
void NativeSkiaOutputDevice::Buffer::createSkImageOnGPUThread()
{
- if (!m_scopedSkiaReadAccess)
+ if (!m_scopedSkiaReadAccess) {
+ m_skImageMutex.unlock();
return;
+ }
- QMutexLocker locker(&m_skImageMutex);
m_cachedSkImage = m_scopedSkiaReadAccess->CreateSkImage(m_parent->m_contextState.get());
+ m_skImageMutex.unlock();
if (!m_cachedSkImage)
qWarning("SKIA: Failed to create SkImage.");
}
@@ -341,6 +343,7 @@ void NativeSkiaOutputDevice::Buffer::beginPresent()
if (!beginSemaphores.empty())
qWarning("SKIA: Unexpected semaphores while reading texture, wait is not implemented.");
+ m_skImageMutex.tryLock();
m_parent->m_gpuTaskRunner->PostTask(FROM_HERE,
base::BindOnce(&NativeSkiaOutputDevice::Buffer::createSkImageOnGPUThread,
base::Unretained(this)));
@@ -390,6 +393,7 @@ void NativeSkiaOutputDevice::Buffer::consumeFence()
sk_sp<SkImage> NativeSkiaOutputDevice::Buffer::skImage()
{
+ QMutexLocker locker(&m_skImageMutex);
return m_cachedSkImage;
}
#if defined(USE_OZONE)
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_mac.mm b/src/core/compositor/native_skia_output_device_mac.mm
index fd3930a9f..bf21ef8d7 100644
--- a/src/core/compositor/native_skia_output_device_mac.mm
+++ b/src/core/compositor/native_skia_output_device_mac.mm
@@ -36,10 +36,17 @@ QSGTexture *makeMetalTexture(QQuickWindow *win, IOSurfaceRef ioSurface, uint ioS
QSGRendererInterface *ri = win->rendererInterface();
auto device = (__bridge id<MTLDevice>)(ri->getResource(win, QSGRendererInterface::DeviceResource));
- auto texture = [device newTextureWithDescriptor:desc iosurface:ioSurface plane:ioSurfacePlane];
+ id<MTLTexture> texture = [device newTextureWithDescriptor:desc
+ iosurface:ioSurface
+ plane:ioSurfacePlane];
return QNativeInterface::QSGMetalTexture::fromNative(texture, win, size, texOpts);
}
+void releaseMetalTexture(void *texture)
+{
+ [static_cast<id<MTLTexture>>(texture) release];
+}
+
#if QT_CONFIG(opengl)
uint32_t makeCGLTexture(QQuickWindow *win, IOSurfaceRef ioSurface, const QSize &size)
{
diff --git a/src/core/compositor/native_skia_output_device_metal.cpp b/src/core/compositor/native_skia_output_device_metal.cpp
index 95ed02779..a9d6e4fd5 100644
--- a/src/core/compositor/native_skia_output_device_metal.cpp
+++ b/src/core/compositor/native_skia_output_device_metal.cpp
@@ -4,6 +4,7 @@
#include "native_skia_output_device_metal.h"
#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qsgtexture.h>
namespace QtWebEngineCore {
@@ -28,6 +29,7 @@ NativeSkiaOutputDeviceMetal::~NativeSkiaOutputDeviceMetal() { }
QSGTexture *makeMetalTexture(QQuickWindow *win, IOSurfaceRef ioSurface, uint ioSurfacePlane,
const QSize &size, QQuickWindow::CreateTextureOptions texOpts);
+void releaseMetalTexture(void *texture);
QSGTexture *NativeSkiaOutputDeviceMetal::texture(QQuickWindow *win, uint32_t textureOptions)
{
@@ -40,8 +42,25 @@ QSGTexture *NativeSkiaOutputDeviceMetal::texture(QQuickWindow *win, uint32_t tex
return nullptr;
}
+ // This is a workaround to not to release metal texture too early.
+ // In RHI, QMetalTexture wraps MTLTexture. QMetalTexture seems to be only destructed after the
+ // next MTLTexture is imported. The "old" MTLTexture can be still pontentially used by RHI
+ // while QMetalTexture is not destructed. Metal Validation Layer also warns about it.
+ // Delay releasing MTLTexture after the next one is presented.
+ if (m_currentMetalTexture) {
+ m_frontBuffer->textureCleanupCallback = [texture = m_currentMetalTexture]() {
+ releaseMetalTexture(texture);
+ };
+ m_currentMetalTexture = nullptr;
+ }
+
QQuickWindow::CreateTextureOptions texOpts(textureOptions);
- return makeMetalTexture(win, ioSurface.release(), /* plane */ 0, size(), texOpts);
+ QSGTexture *qsgTexture = makeMetalTexture(win, ioSurface.get(), /* plane */ 0, size(), texOpts);
+
+ auto ni = qsgTexture->nativeInterface<QNativeInterface::QSGMetalTexture>();
+ m_currentMetalTexture = ni->nativeTexture();
+
+ return qsgTexture;
}
} // namespace QtWebEngineCore
diff --git a/src/core/compositor/native_skia_output_device_metal.h b/src/core/compositor/native_skia_output_device_metal.h
index e61665fb5..8e8d0fab8 100644
--- a/src/core/compositor/native_skia_output_device_metal.h
+++ b/src/core/compositor/native_skia_output_device_metal.h
@@ -21,6 +21,9 @@ public:
// Overridden from Compositor:
QSGTexture *texture(QQuickWindow *win, uint32_t textureOptions) override;
+
+private:
+ void *m_currentMetalTexture = nullptr;
};
} // namespace QtWebEngineCore
diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp
index ea4c0c500..058573b9e 100644
--- a/src/core/compositor/native_skia_output_device_opengl.cpp
+++ b/src/core/compositor/native_skia_output_device_opengl.cpp
@@ -68,7 +68,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te
// TODO: Add WGL support over ANGLE.
QT_NOT_YET_IMPLEMENTED
#elif defined(Q_OS_MACOS)
- uint32_t glTexture = makeCGLTexture(win, ioSurface.release(), size());
+ uint32_t glTexture = makeCGLTexture(win, ioSurface.get(), size());
texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts);
m_frontBuffer->textureCleanupCallback = [glTexture]() {
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 53c2caa2d..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);
}
@@ -827,7 +827,8 @@ static bool navigationThrottleCallback(content::NavigationHandle *handle)
client->navigationRequested(pageTransitionToNavigationType(transition_type),
toQt(handle->GetURL()),
navigationAccepted,
- handle->IsInPrimaryMainFrame());
+ handle->IsInPrimaryMainFrame(),
+ handle->IsFormSubmission());
return !navigationAccepted;
}
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..9cbdcbc76 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()
*/
/*!
@@ -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/favicon_driver_qt.cpp b/src/core/favicon_driver_qt.cpp
index bb4a734b4..e710d5358 100644
--- a/src/core/favicon_driver_qt.cpp
+++ b/src/core/favicon_driver_qt.cpp
@@ -263,13 +263,6 @@ void FaviconDriverQt::DidUpdateFaviconURL(
if (!entry)
return;
- // We update |m_faviconUrls| even if the list is believed to be partial
- // (checked below), because callers of our getter favicon_urls() expect so.
- std::vector<blink::mojom::FaviconURLPtr> faviconUrls;
- for (const auto &candidate : candidates)
- faviconUrls.push_back(candidate.Clone());
- m_faviconUrls = std::move(faviconUrls);
-
if (!rfh->IsDocumentOnLoadCompletedInMainFrame())
return;
diff --git a/src/core/favicon_driver_qt.h b/src/core/favicon_driver_qt.h
index 96bd682a2..6dc377969 100644
--- a/src/core/favicon_driver_qt.h
+++ b/src/core/favicon_driver_qt.h
@@ -137,9 +137,6 @@ private:
GURL m_bypassCachePageURL;
- // nullopt until the actual list is reported via DidUpdateFaviconURL().
- absl::optional<std::vector<blink::mojom::FaviconURLPtr>> m_faviconUrls;
-
int m_completedHandlersCount = 0;
FaviconStatusQt m_latestFavicon;
diff --git a/src/core/native_web_keyboard_event_qt_mac.mm b/src/core/native_web_keyboard_event_qt_mac.mm
index 57c575699..0f5b12db4 100644
--- a/src/core/native_web_keyboard_event_qt_mac.mm
+++ b/src/core/native_web_keyboard_event_qt_mac.mm
@@ -47,7 +47,7 @@ base::apple::OwnedNSEvent ToNativeEvent(QKeyEvent *keyEvent)
return base::apple::OwnedNSEvent([NSEvent
keyEventWithType:type
location:NSZeroPoint
- modifierFlags:keyEvent->nativeModifiers()
+ modifierFlags:QAppleKeyMapper::toCocoaModifiers(keyEvent->modifiers())
timestamp:keyEvent->timestamp() / 1000
windowNumber:0
context:nil
diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp
index 608d5c21a..2e358c0fb 100644
--- a/src/core/ozone/gl_context_qt.cpp
+++ b/src/core/ozone/gl_context_qt.cpp
@@ -175,11 +175,11 @@ bool GLContextHelper::isCreateContextRobustnessSupported()
return contextHelper->m_robustness;
}
-#if defined(USE_OZONE)
+#if QT_CONFIG(opengl) && defined(USE_OZONE)
class ScopedGLContext
{
public:
- ScopedGLContext()
+ ScopedGLContext(QOffscreenSurface *surface)
: m_context(new QOpenGLContext())
, m_previousContext(gl::GLContext::GetCurrent())
, m_previousSurface(gl::GLSurface::GetCurrent())
@@ -189,10 +189,7 @@ public:
return;
}
- QOffscreenSurface *surface = new QOffscreenSurface(m_context->screen(), m_context.get());
- surface->create();
Q_ASSERT(surface->isValid());
-
if (!m_context->makeCurrent(surface)) {
qWarning("Failed to make OpenGL context current.");
return;
@@ -269,7 +266,8 @@ EGLHelper *EGLHelper::instance()
return &eglHelper;
}
-EGLHelper::EGLHelper() : m_functions(new EGLHelper::EGLFunctions())
+EGLHelper::EGLHelper()
+ : m_functions(new EGLHelper::EGLFunctions()), m_offscreenSurface(new QOffscreenSurface())
{
const char *extensions = m_functions->eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (!extensions) {
@@ -288,6 +286,9 @@ EGLHelper::EGLHelper() : m_functions(new EGLHelper::EGLFunctions())
return;
}
+ Q_ASSERT(QThread::currentThread() == qApp->thread());
+ m_offscreenSurface->create();
+
const char *displayExtensions = m_functions->eglQueryString(eglDisplay, EGL_EXTENSIONS);
m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import")
&& strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers")
@@ -306,6 +307,16 @@ EGLHelper::EGLHelper() : m_functions(new EGLHelper::EGLFunctions())
const char *displayVendor = m_functions->eglQueryString(eglDisplay, EGL_VENDOR);
m_isDmaBufSupported = !strstr(displayVendor, "NVIDIA");
}
+
+ // Try to create dma-buf.
+ if (m_isDmaBufSupported) {
+ int fd = -1;
+ queryDmaBuf(2, 2, &fd, nullptr, nullptr, nullptr);
+ if (fd == -1)
+ m_isDmaBufSupported = false;
+ else
+ close(fd);
+ }
}
void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *stride, int *offset,
@@ -314,7 +325,7 @@ void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *str
if (!m_isDmaBufSupported)
return;
- ScopedGLContext context;
+ ScopedGLContext context(m_offscreenSurface.get());
if (!context.isValid())
return;
@@ -350,20 +361,9 @@ void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *str
bool EGLHelper::isDmaBufSupported()
{
- if (!m_isDmaBufSupported)
- return false;
-
- int fd = -1;
- queryDmaBuf(2, 2, &fd, nullptr, nullptr, nullptr);
- if (fd == -1) {
- m_isDmaBufSupported = false;
- return false;
- }
-
- close(fd);
- return true;
+ return m_isDmaBufSupported;
}
-#endif // defined(USE_OZONE)
+#endif // QT_CONFIG(opengl) && defined(USE_OZONE)
QT_END_NAMESPACE
diff --git a/src/core/ozone/gl_context_qt.h b/src/core/ozone/gl_context_qt.h
index c1524abf2..41c6a5f0c 100644
--- a/src/core/ozone/gl_context_qt.h
+++ b/src/core/ozone/gl_context_qt.h
@@ -6,10 +6,11 @@
#include <QObject>
#include <QtCore/qscopedpointer.h>
+#include <QtGui/qtgui-config.h>
#include "ui/gl/gl_context.h"
-#if defined(USE_OZONE)
+#if QT_CONFIG(opengl) && defined(USE_OZONE)
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif
@@ -20,6 +21,8 @@ class GLSurface;
QT_BEGIN_NAMESPACE
+class QOffscreenSurface;
+
class GLContextHelper : public QObject {
Q_OBJECT
public:
@@ -45,7 +48,7 @@ private:
bool m_robustness = false;
};
-#if defined(USE_OZONE)
+#if QT_CONFIG(opengl) && defined(USE_OZONE)
#undef eglCreateImage
#undef eglDestroyImage
#undef eglExportDMABUFImageMESA
@@ -79,9 +82,10 @@ private:
EGLHelper();
QScopedPointer<EGLFunctions> m_functions;
+ QScopedPointer<QOffscreenSurface> m_offscreenSurface;
bool m_isDmaBufSupported = false;
};
-#endif // defined(USE_OZONE)
+#endif // QT_CONFIG(opengl) && defined(USE_OZONE)
QT_END_NAMESPACE
diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp
index e8547fa87..623cf43cf 100644
--- a/src/core/ozone/ozone_platform_qt.cpp
+++ b/src/core/ozone/ozone_platform_qt.cpp
@@ -73,7 +73,8 @@ public:
if (has_initialized_gpu()) {
// This property is set when the GetPlatformRuntimeProperties is
// called on the gpu process side.
- properties.supports_native_pixmaps = surface_factory_ozone_->SupportsNativePixmaps();
+ DCHECK(m_supportsNativePixmaps);
+ properties.supports_native_pixmaps = m_supportsNativePixmaps.value();
}
return properties;
}
@@ -85,6 +86,7 @@ private:
void InitScreen(ui::PlatformScreen *) override {}
+ absl::optional<bool> m_supportsNativePixmaps;
std::unique_ptr<QtWebEngineCore::SurfaceFactoryQt> surface_factory_ozone_;
std::unique_ptr<CursorFactory> cursor_factory_;
@@ -109,9 +111,10 @@ const ui::OzonePlatform::PlatformProperties &OzonePlatformQt::GetPlatformPropert
static base::NoDestructor<ui::OzonePlatform::PlatformProperties> properties;
static bool initialized = false;
if (!initialized) {
- properties->fetch_buffer_formats_for_gmb_on_gpu = true;
+ DCHECK(m_supportsNativePixmaps);
+ properties->fetch_buffer_formats_for_gmb_on_gpu = m_supportsNativePixmaps.value();
#if BUILDFLAG(USE_VAAPI)
- properties->supports_vaapi = true;
+ properties->supports_vaapi = m_supportsNativePixmaps.value();
#endif
initialized = true;
}
@@ -227,6 +230,7 @@ bool OzonePlatformQt::InitializeUI(const ui::OzonePlatform::InitParams &)
input_controller_ = CreateStubInputController();
cursor_factory_.reset(new BitmapCursorFactory());
gpu_platform_support_host_.reset(ui::CreateStubGpuPlatformSupportHost());
+ m_supportsNativePixmaps = QtWebEngineCore::SurfaceFactoryQt::SupportsNativePixmaps();
return true;
}
diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp
index 374f870e2..2d311a02a 100644
--- a/src/core/ozone/surface_factory_qt.cpp
+++ b/src/core/ozone/surface_factory_qt.cpp
@@ -16,6 +16,7 @@
#include "ui/ozone/buildflags.h"
#include <QDebug>
+#include <QtGui/qtgui-config.h>
#if BUILDFLAG(OZONE_PLATFORM_X11)
#include "ozone/gl_ozone_glx_qt.h"
@@ -91,7 +92,10 @@ scoped_refptr<gfx::NativePixmap> SurfaceFactoryQt::CreateNativePixmap(
gfx::BufferUsage usage,
absl::optional<gfx::Size> framebuffer_size)
{
- Q_ASSERT(SupportsNativePixmaps());
+ if (!SupportsNativePixmaps())
+ return nullptr;
+
+#if QT_CONFIG(opengl)
if (framebuffer_size && !gfx::Rect(size).Contains(gfx::Rect(*framebuffer_size)))
return nullptr;
@@ -125,6 +129,9 @@ scoped_refptr<gfx::NativePixmap> SurfaceFactoryQt::CreateNativePixmap(
}
return base::MakeRefCounted<gfx::NativePixmapDmaBuf>(size, format, std::move(handle));
+#else
+ return nullptr;
+#endif // QT_CONFIG(opengl)
}
void SurfaceFactoryQt::CreateNativePixmapAsync(
@@ -135,7 +142,11 @@ void SurfaceFactoryQt::CreateNativePixmapAsync(
gfx::BufferUsage usage,
NativePixmapCallback callback)
{
- Q_ASSERT(SupportsNativePixmaps());
+ if (!SupportsNativePixmaps()) {
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
// CreateNativePixmap is non-blocking operation. Thus, it is safe to call it
// and return the result with the provided callback.
std::move(callback).Run(CreateNativePixmap(widget, device_queue, size, format, usage));
@@ -148,7 +159,10 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle(
gfx::BufferFormat format,
gfx::NativePixmapHandle handle)
{
- Q_ASSERT(SupportsNativePixmaps());
+ if (!SupportsNativePixmaps())
+ return nullptr;
+
+#if QT_CONFIG(opengl)
gfx::NativePixmapHandle bufferHandle;
#if BUILDFLAG(OZONE_PLATFORM_X11)
@@ -212,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];
@@ -220,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));
}
@@ -228,17 +242,22 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle(
}
return base::MakeRefCounted<gfx::NativePixmapDmaBuf>(size, format, std::move(bufferHandle));
+#else
+ return nullptr;
+#endif // QT_CONFIG(opengl)
}
-bool SurfaceFactoryQt::SupportsNativePixmaps() const
+bool SurfaceFactoryQt::SupportsNativePixmaps()
{
+#if QT_CONFIG(opengl)
#if BUILDFLAG(OZONE_PLATFORM_X11)
if (GLContextHelper::getGlxPlatformInterface())
return ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device();
-#endif
+#endif // BUILDFLAG(OZONE_PLATFORM_X11)
if (GLContextHelper::getEglPlatformInterface())
return EGLHelper::instance()->isDmaBufSupported();
+#endif // QT_CONFIG(opengl)
return false;
}
diff --git a/src/core/ozone/surface_factory_qt.h b/src/core/ozone/surface_factory_qt.h
index 07d7337ac..d69467a26 100644
--- a/src/core/ozone/surface_factory_qt.h
+++ b/src/core/ozone/surface_factory_qt.h
@@ -40,7 +40,7 @@ public:
gfx::BufferFormat format,
gfx::NativePixmapHandle handle) override;
- bool SupportsNativePixmaps() const;
+ static bool SupportsNativePixmaps();
private:
std::vector<gl::GLImplementationParts> m_impl;
diff --git a/src/core/render_view_context_menu_qt.h b/src/core/render_view_context_menu_qt.h
index 71901424c..1188f6cd4 100644
--- a/src/core/render_view_context_menu_qt.h
+++ b/src/core/render_view_context_menu_qt.h
@@ -15,7 +15,7 @@
#ifndef RENDER_VIEW_CONTEXT_MENU_QT_H
#define RENDER_VIEW_CONTEXT_MENU_QT_H
-#include "web_contents_adapter_client.h"
+#include "qtwebenginecoreglobal.h"
QT_FORWARD_DECLARE_CLASS(QWebEngineContextMenuRequest)
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 7ffeaaa5b..6cdc621a3 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,50 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible()
}
#endif // QT_CONFIG(accessibility)
-void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId)
+void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId,
+ const std::function<void(const QVariant &)> &callback)
{
- CHECK_INITIALIZED();
+ auto exit = [&] {
+ if (callback)
+ callback(QVariant());
+ };
+
+ if (!isInitialized())
+ return exit();
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;
+ return exit();
+ }
+
+ content::RenderFrameHost::JavaScriptResultCallback wrappedCallback = base::NullCallback();
+ if (callback) {
+ wrappedCallback = base::BindOnce(&callbackOnEvaluateJS, this, m_nextRequestId);
+ m_javaScriptCallbacks.insert(m_nextRequestId, callback);
+ ++m_nextRequestId;
}
if (worldId == 0)
- rfh->ExecuteJavaScript(toString16(javaScript), base::NullCallback());
+ rfh->ExecuteJavaScript(toString16(javaScript), std::move(wrappedCallback));
else
- rfh->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), base::NullCallback(), worldId);
+ rfh->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), std::move(wrappedCallback),
+ worldId);
}
-quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId)
+void WebContentsAdapter::didRunJavaScript(quint64 requestId, const base::Value &result)
{
- CHECK_INITIALIZED(0);
- 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 0;
- }
- content::RenderFrameHost::JavaScriptResultCallback callback = base::BindOnce(&callbackOnEvaluateJS, m_adapterClient, m_nextRequestId);
- if (worldId == 0)
- rfh->ExecuteJavaScript(toString16(javaScript), std::move(callback));
- else
- rfh->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), std::move(callback), worldId);
- return m_nextRequestId++;
+ 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()
@@ -1812,6 +1828,80 @@ void WebContentsAdapter::changeTextDirection(bool leftToRight)
}
}
+quint64 WebContentsAdapter::mainFrameId() const
+{
+ CHECK_INITIALIZED(content::RenderFrameHost::kNoFrameTreeNodeId);
+ return static_cast<quint64>(m_webContents->GetPrimaryMainFrame()->GetFrameTreeNodeId());
+}
+
+#define CHECK_INITIALIZED_AND_VALID_FRAME(webengine_frame_id_variable, frame_tree_node_variable, \
+ return_value) \
+ CHECK_INITIALIZED(return_value); \
+ if (webengine_frame_id_variable == kInvalidFrameId) \
+ return return_value; \
+ auto *frame_tree_node_variable = content::FrameTreeNode::GloballyFindByID( \
+ static_cast<int>(webengine_frame_id_variable)); \
+ if (!frame_tree_node_variable) \
+ return return_value
+
+QString WebContentsAdapter::frameName(quint64 id) const
+{
+ CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, QString());
+ return QString::fromStdString(ftn->frame_name());
+}
+
+QString WebContentsAdapter::frameHtmlName(quint64 id) const
+{
+ CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, QString());
+ auto &maybeName = ftn->html_name();
+ return maybeName ? QString::fromStdString(*maybeName) : QString("");
+}
+
+QList<quint64> WebContentsAdapter::frameChildren(quint64 id) const
+{
+ CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, {});
+ QList<quint64> result;
+ size_t numChildren = ftn->child_count();
+ result.reserve(numChildren);
+ for (size_t i = 0; i < numChildren; ++i) {
+ result.push_back(ftn->child_at(i)->frame_tree_node_id());
+ }
+ return result;
+}
+
+QUrl WebContentsAdapter::frameUrl(quint64 id) const
+{
+ CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, QUrl());
+ return toQt(ftn->current_url());
+}
+
+QSizeF WebContentsAdapter::frameSize(quint64 id) const
+{
+ CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, QSizeF());
+ auto *rfh = ftn->current_frame_host();
+ Q_ASSERT(rfh);
+ auto maybeSize = rfh->GetFrameSize();
+ return maybeSize ? toQt(*maybeSize) : QSizeF();
+}
+
+std::optional<quint64> WebContentsAdapter::findFrameIdByName(const QString &name) const
+{
+ CHECK_INITIALIZED({});
+ auto *ftn = content::FrameTreeNode::From(m_webContents->GetPrimaryMainFrame());
+ Q_ASSERT(ftn);
+ if (auto *foundFtn = ftn->frame_tree().FindByName(name.toStdString()))
+ return foundFtn->frame_tree_node_id();
+ return {};
+}
+
+bool WebContentsAdapter::hasFrame(quint64 id) const
+{
+ CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, false);
+ auto *rfh = ftn->current_frame_host();
+ Q_ASSERT(rfh);
+ return content::WebContents::FromRenderFrameHost(rfh) == m_webContents.get();
+}
+
WebContentsAdapterClient::RenderProcessTerminationStatus
WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) {
auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1);
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index 62c3f087c..0c46e7d81 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -16,17 +16,22 @@
#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>
#include <QtWebEngineCore/qwebenginecontextmenurequest.h>
#include <QtWebEngineCore/qwebenginehttprequest.h>
+#include <QtWebEngineCore/qwebengineframe.h>
#include "web_contents_adapter_client.h"
+#include <functional>
#include <memory>
+#include <optional>
namespace blink {
namespace web_pref {
@@ -34,6 +39,10 @@ struct WebPreferences;
}
}
+namespace base {
+class Value;
+}
+
namespace content {
class WebContents;
class SiteInstance;
@@ -62,6 +71,9 @@ class WebChannelIPCTransportHost;
class Q_WEBENGINECORE_EXPORT WebContentsAdapter : public QEnableSharedFromThis<WebContentsAdapter> {
public:
+ // Sentinel to indicate a frame doesn't exist, for example with `findFrameByName`
+ static constexpr quint64 kInvalidFrameId = -3;
+
static QSharedPointer<WebContentsAdapter> createFromSerializedNavigationHistory(QDataStream &input, WebContentsAdapterClient *adapterClient);
WebContentsAdapter();
WebContentsAdapter(std::unique_ptr<content::WebContents> webContents);
@@ -124,8 +136,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,
+ 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);
@@ -204,6 +218,15 @@ public:
void resetTouchSelectionController();
void changeTextDirection(bool leftToRight);
+ quint64 mainFrameId() const;
+ QString frameName(quint64 id) const;
+ QString frameHtmlName(quint64 id) const;
+ QList<quint64> frameChildren(quint64 id) const;
+ QUrl frameUrl(quint64 id) const;
+ QSizeF frameSize(quint64 id) const;
+ std::optional<quint64> findFrameIdByName(const QString &name) const;
+ bool hasFrame(quint64 id) const;
+
// meant to be used within WebEngineCore only
void initialize(content::SiteInstance *site);
content::WebContents *webContents() const;
@@ -241,6 +264,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 1a1474644..45e35a5ba 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;
@@ -169,13 +170,14 @@ public:
virtual void windowCloseRejected() = 0;
virtual void contextMenuRequested(QWebEngineContextMenuRequest *request) = 0;
virtual void desktopMediaRequested(DesktopMediaController *) = 0;
- virtual void navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame) = 0;
+ virtual void navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame, bool hasFormData) = 0;
virtual void requestFullScreenMode(const QUrl &origin, bool fullscreen) = 0;
virtual bool isFullScreenMode() const = 0;
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,
+ 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;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 194274fcb..4df73fb69 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -760,7 +760,7 @@ void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransitio
}
if (navigationAllowedByPolicy) {
- m_viewClient->navigationRequested(pageTransitionToNavigationType(page_transition), url, navigationRequestAccepted, is_main_frame);
+ m_viewClient->navigationRequested(pageTransitionToNavigationType(page_transition), url, navigationRequestAccepted, is_main_frame, false);
#if QT_CONFIG(desktopservices)
if (navigationRequestAccepted)
QDesktopServices::openUrl(url);
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index 2402e9570..faf9bd542 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -3,6 +3,7 @@
#include "web_engine_context.h"
+#include <map>
#include <math.h>
#include <QtGui/private/qrhi_p.h>
@@ -105,10 +106,6 @@
#include <QGuiApplication>
#include <QMutex>
#include <QOffscreenSurface>
-#if QT_CONFIG(opengl)
-#include <QOpenGLContext>
-#include <qopenglcontext_platform.h>
-#endif
#include <QQuickWindow>
#include <QRegularExpression>
#include <QStringList>
@@ -120,6 +117,9 @@
#include <QLoggingCategory>
#if QT_CONFIG(opengl)
+#include <QOpenGLContext>
+#include <qopenglcontext_platform.h>
+
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
QT_END_NAMESPACE
@@ -132,7 +132,188 @@ namespace QtWebEngineCore {
Q_LOGGING_CATEGORY(webEngineContextLog, "qt.webenginecontext")
+class GPUInfo
+{
+public:
+ enum Vendor {
+ Unknown = -1,
+ AMD,
+ Apple,
+ ARM,
+ Google,
+ ImgTec,
+ Intel,
+ Microsoft,
+ Mesa,
+ Nvidia,
+ Qualcomm,
+ Samsung
+ };
+
+ static GPUInfo *instance()
+ {
+ static GPUInfo instance;
+ return &instance;
+ }
+
+ static Vendor vendorIdToVendor(quint64 vendorId)
+ {
+ // clang-format off
+ // Based on //third_party/dawn/src/dawn/gpu_info.json
+ static const std::map<quint64, Vendor> vendorIdMap = {
+ {0x0, Unknown},
+ {0x1002, AMD},
+ {0x106B, Apple},
+ {0x13B5, ARM},
+ {0x1AE0, Google},
+ {0x1010, ImgTec},
+ {0x8086, Intel},
+ {0x10005, Mesa},
+ {0x1414, Microsoft},
+ {0x10DE, Nvidia},
+ {0x5143, Qualcomm},
+ {0x144D, Samsung}
+ };
+ // clang-format on
+
+ auto it = vendorIdMap.find(vendorId);
+ if (it != vendorIdMap.end())
+ return it->second;
+
+ qWarning() << "Unknown Vendor ID:" << QString("0x%1").arg(vendorId, 0, 16);
+ return Unknown;
+ }
+
+ static Vendor deviceNameToVendor(QString deviceName)
+ {
+ // TODO: Test and add more vendors to the list.
+ if (deviceName.contains(QLatin1String("AMD"), Qt::CaseInsensitive))
+ return AMD;
+ if (deviceName.contains(QLatin1String("Intel"), Qt::CaseInsensitive))
+ return Intel;
+ if (deviceName.contains(QLatin1String("Nvidia"), Qt::CaseInsensitive))
+ return Nvidia;
+
+#if defined(USE_OZONE)
+ if (deviceName.contains(QLatin1String("Mesa llvmpipe")))
+ return Mesa;
+#endif
+
+#if defined(Q_OS_MACOS)
+ if (deviceName.contains(QLatin1String("Apple")))
+ return Apple;
+#endif
+
+ return Unknown;
+ }
+
+ static std::string vendorToString(Vendor vendor)
+ {
+ // clang-format off
+ static const std::map<Vendor, std::string> vendorNameMap = {
+ {Unknown, "Unknown"},
+ {AMD, "AMD"},
+ {Apple, "Apple"},
+ {ARM, "ARM"},
+ {Google, "Google"},
+ {ImgTec, "Img Tec"},
+ {Intel, "Intel"},
+ {Mesa, "Mesa"},
+ {Microsoft, "Microsoft"},
+ {Nvidia, "Nvidia"},
+ {Qualcomm, "Qualcomm"},
+ {Samsung, "Samsung"}
+ };
+ // clang-format on
+
+ auto it = vendorNameMap.find(vendor);
+ if (it != vendorNameMap.end())
+ return it->second;
+
+ Q_UNREACHABLE();
+ return "Unknown";
+ }
+
+ Vendor vendor() const { return m_vendor; }
+ QString getAdapterLuid() const { return m_adapterLuid; }
+
+private:
+ GPUInfo()
+ {
+#if defined(Q_OS_WIN)
+ {
+ static const bool preferSoftwareDevice =
+ qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER");
+ QRhiD3D11InitParams params;
+ QRhi::Flags flags;
+ if (preferSoftwareDevice) {
+ flags |= QRhi::PreferSoftwareRenderer;
+ }
+ QScopedPointer<QRhi> d3d11Rhi(QRhi::create(QRhi::D3D11, &params, flags, nullptr));
+ // mimic what QSGRhiSupport and QBackingStoreRhi does
+ if (!d3d11Rhi && !preferSoftwareDevice) {
+ flags |= QRhi::PreferSoftwareRenderer;
+ d3d11Rhi.reset(QRhi::create(QRhi::D3D11, &params, flags, nullptr));
+ }
+ if (d3d11Rhi) {
+ m_vendor = vendorIdToVendor(d3d11Rhi->driverInfo().vendorId);
+
+ const QRhiD3D11NativeHandles *handles =
+ static_cast<const QRhiD3D11NativeHandles *>(d3d11Rhi->nativeHandles());
+ Q_ASSERT(handles);
+ m_adapterLuid =
+ QString("%1,%2").arg(handles->adapterLuidHigh).arg(handles->adapterLuidLow);
+ }
+ }
+#elif defined(Q_OS_MACOS)
+ {
+ QRhiMetalInitParams params;
+ QScopedPointer<QRhi> metalRhi(
+ QRhi::create(QRhi::Metal, &params, QRhi::Flags(), nullptr));
+ if (metalRhi)
+ m_vendor = deviceNameToVendor(metalRhi->driverInfo().deviceName);
+ }
+#endif
+
#if QT_CONFIG(opengl)
+ if (m_vendor == Unknown) {
+ QRhiGles2InitParams params;
+ params.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QScopedPointer<QRhi> glRhi(
+ QRhi::create(QRhi::OpenGLES2, &params, QRhi::Flags(), nullptr));
+ if (glRhi)
+ m_vendor = deviceNameToVendor(glRhi->driverInfo().deviceName);
+ }
+#endif
+
+#if QT_CONFIG(webengine_vulkan)
+ if (m_vendor == Unknown) {
+ QVulkanInstance vulkanInstance;
+ vulkanInstance.setApiVersion(QVersionNumber(1, 1));
+ if (vulkanInstance.create()) {
+ QRhiVulkanInitParams params;
+ params.inst = &vulkanInstance;
+ QScopedPointer<QRhi> vulkanRhi(
+ QRhi::create(QRhi::Vulkan, &params, QRhi::Flags(), nullptr));
+ if (vulkanRhi) {
+ // TODO: The primary GPU is not necessarily the one which is connected to the
+ // display in case of a Multi-GPU setup on Linux. This can be workarounded by
+ // installing the Mesa's Device Selection Layer,
+ // see https://www.phoronix.com/news/Mesa-20.1-Vulkan-Dev-Selection
+ // Try to detect this case and at least warn about it.
+ m_vendor = vendorIdToVendor(vulkanRhi->driverInfo().vendorId);
+ }
+ }
+ }
+#endif
+
+ if (m_vendor == Unknown)
+ qWarning("Unable to detect GPU vendor.");
+ }
+
+ Vendor m_vendor = Unknown;
+ QString m_adapterLuid;
+};
static bool usingSupportedSGBackend()
{
@@ -162,6 +343,7 @@ static bool usingSupportedSGBackend()
return device.isEmpty() || device == QLatin1String("rhi");
}
+#if QT_CONFIG(opengl)
bool usingSoftwareDynamicGL()
{
const char openGlVar[] = "QT_OPENGL";
@@ -190,14 +372,12 @@ static bool openGLPlatformSupport()
QPlatformIntegration::OpenGL);
}
-static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
+static std::string getGLType(bool enableGLSoftwareRendering, bool disableGpu)
{
- const char *glType = gl::kGLImplementationDisabledName;
const bool tryGL =
usingSupportedSGBackend() && !usingSoftwareDynamicGL() && openGLPlatformSupport();
-
if (disableGpu || (!tryGL && !enableGLSoftwareRendering))
- return glType;
+ return gl::kGLImplementationDisabledName;
#if defined(Q_OS_MACOS)
return gl::kGLImplementationANGLEName;
@@ -212,7 +392,7 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
if (!qt_gl_global_share_context() || !qt_gl_global_share_context()->isValid()) {
qWarning("WebEngineContext is used before QtWebEngineQuick::initialize() or OpenGL context "
"creation failed.");
- return glType;
+ return gl::kGLImplementationDisabledName;
}
const QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format();
@@ -220,17 +400,13 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
switch (sharedFormat.renderableType()) {
case QSurfaceFormat::OpenGL:
if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) {
- glType = gl::kGLImplementationDesktopName;
qWarning("An OpenGL Core Profile was requested, but it is not supported "
"on the current platform. Falling back to a non-Core profile. "
"Note that this might cause rendering issues.");
- } else {
- glType = gl::kGLImplementationDesktopName;
}
- break;
+ return gl::kGLImplementationDesktopName;
case QSurfaceFormat::OpenGLES:
- glType = gl::kGLImplementationEGLName;
- break;
+ return gl::kGLImplementationEGLName;
case QSurfaceFormat::OpenVG:
case QSurfaceFormat::DefaultRenderableType:
default:
@@ -238,11 +414,12 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
qWarning("Unsupported rendering surface format. Please open bug report at "
"https://bugreports.qt.io");
}
- return glType;
+
+ return gl::kGLImplementationDisabledName;
#endif // defined(Q_OS_MACOS)
}
#else
-static const char *getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu)
+static std::string getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu)
{
if (disableGpu)
return gl::kGLImplementationDisabledName;
@@ -258,30 +435,33 @@ static const char *getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu
}
#endif // QT_CONFIG(opengl)
+static std::string getVulkanType(base::CommandLine *cmd)
+{
+#if QT_CONFIG(webengine_vulkan)
+ if (cmd->HasSwitch(switches::kUseVulkan))
+ return cmd->GetSwitchValueASCII(switches::kUseVulkan);
+#endif
+
+ return "disabled";
+}
+
+static std::string getAngleType(const std::string &glType, base::CommandLine *cmd)
+{
+ if (glType == gl::kGLImplementationANGLEName) {
+ if (cmd->HasSwitch(switches::kUseANGLE))
+ return cmd->GetSwitchValueASCII(switches::kUseANGLE);
+
#if defined(Q_OS_WIN)
-static QString getAdapterLuid() {
- static const bool preferSoftwareDevice = qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER");
- QRhiD3D11InitParams rhiParams;
- QRhi::Flags flags;
- if (preferSoftwareDevice) {
- flags |= QRhi::PreferSoftwareRenderer;
- }
- QScopedPointer<QRhi> rhi(QRhi::create(QRhi::D3D11,&rhiParams,flags,nullptr));
- // mimic what QSGRhiSupport and QBackingStoreRhi does
- if (!rhi && !preferSoftwareDevice) {
- flags |= QRhi::PreferSoftwareRenderer;
- rhi.reset(QRhi::create(QRhi::D3D11, &rhiParams, flags));
- }
- if (rhi) {
- const QRhiD3D11NativeHandles *handles =
- static_cast<const QRhiD3D11NativeHandles *>(rhi->nativeHandles());
- Q_ASSERT(handles);
- return QString("%1,%2").arg(handles->adapterLuidHigh).arg(handles->adapterLuidLow);
- } else {
- return QString();
+ return gl::kANGLEImplementationD3D11Name;
+#elif defined(Q_OS_MACOS)
+ return gl::kANGLEImplementationMetalName;
+#else
+ return gl::kANGLEImplementationDefaultName;
+#endif
}
+
+ return "disabled";
}
-#endif
#if QT_CONFIG(webengine_pepper_plugins)
void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&)
@@ -289,43 +469,57 @@ void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&)
}
#endif
-static void logContext(const char *glType, base::CommandLine *cmd)
+static void logContext(const std::string &glType, base::CommandLine *cmd)
{
if (Q_UNLIKELY(webEngineContextLog().isDebugEnabled())) {
- const base::CommandLine::SwitchMap switch_map = cmd->GetSwitches();
- QStringList params;
- for (const auto &pair : switch_map)
- params << " * " << toQt(pair.first)
- << toQt(pair.second) << "\n";
+ QStringList log;
+ log << "\n";
+
+ log << "Chromium GL Backend:" << glType.c_str() << "\n";
+ log << "Chromium ANGLE Backend:" << getAngleType(glType, cmd).c_str() << "\n";
+ log << "Chromium Vulkan Backend:" << getVulkanType(cmd).c_str() << "\n";
+ log << "\n";
+
+ log << "QSG RHI Backend:" << QSGRhiSupport::instance()->rhiBackendName() << "\n";
+ log << "QSG RHI Backend Supported:" << (usingSupportedSGBackend() ? "yes" : "no") << "\n";
+ log << "GPU Vendor:" << GPUInfo::vendorToString(GPUInfo::instance()->vendor()).c_str();
+ log << "\n";
+
#if QT_CONFIG(opengl)
- const QSurfaceFormat sharedFormat = qt_gl_global_share_context() ? qt_gl_global_share_context()->format() : QSurfaceFormat::defaultFormat();
- const auto profile = QMetaEnum::fromType<QSurfaceFormat::OpenGLContextProfile>().valueToKey(
- sharedFormat.profile());
- const auto type = QMetaEnum::fromType<QSurfaceFormat::RenderableType>().valueToKey(
- sharedFormat.renderableType());
- qCDebug(webEngineContextLog,
- "\n\nChromium GL Backend: %s\n"
- "Surface Type: %s\n"
- "Surface Profile: %s\n"
- "Surface Version: %d.%d\n"
- "QSG RHI Backend: %s\n"
- "Using Supported QSG Backend: %s\n"
- "Using Software Dynamic GL: %s\n"
- "Using Shared GL: %s\n"
- "Init Parameters:\n %s",
- glType, type, profile, sharedFormat.majorVersion(), sharedFormat.minorVersion(),
- qUtf8Printable(QSGRhiSupport::instance()->rhiBackendName()),
- usingSupportedSGBackend() ? "yes" : "no", usingSoftwareDynamicGL() ? "yes" : "no",
- qt_gl_global_share_context() ? "yes" : "no",
- qPrintable(params.join(" ")));
-#else
- qCDebug(webEngineContextLog,
- "\n\nChromium GL Backend: %s\n"
- "QSG RHI Backend: %s\n\n"
- "Init Parameters:\n %s",
- glType, qUtf8Printable(QSGRhiSupport::instance()->rhiBackendName()),
- qPrintable(params.join(" ")));
-#endif //QT_CONFIG(opengl)
+#if defined(USE_OZONE)
+ log << "Using GLX:" << (GLContextHelper::getGlxPlatformInterface() ? "yes" : "no") << "\n";
+ log << "Using EGL:" << (GLContextHelper::getEglPlatformInterface() ? "yes" : "no") << "\n";
+#endif
+ log << "Using Shared GL:" << (qt_gl_global_share_context() ? "yes" : "no") << "\n";
+ if (qt_gl_global_share_context()) {
+ log << "Using Software Dynamic GL:" << (usingSoftwareDynamicGL() ? "yes" : "no")
+ << "\n";
+
+ const QSurfaceFormat sharedFormat = qt_gl_global_share_context()
+ ? qt_gl_global_share_context()->format()
+ : QSurfaceFormat::defaultFormat();
+ const auto profile =
+ QMetaEnum::fromType<QSurfaceFormat::OpenGLContextProfile>().valueToKey(
+ sharedFormat.profile());
+ const auto type = QMetaEnum::fromType<QSurfaceFormat::RenderableType>().valueToKey(
+ sharedFormat.renderableType());
+ log << "Surface Type:" << type << "\n";
+ log << "Surface Profile:" << profile << "\n";
+ log << "Surface Version:"
+ << QString("%1.%2")
+ .arg(sharedFormat.majorVersion())
+ .arg(sharedFormat.minorVersion())
+ << "\n";
+ }
+ log << "\n";
+#endif // QT_CONFIG(opengl)
+
+ log << "Init Parameters:\n";
+ const base::CommandLine::SwitchMap switchMap = cmd->GetSwitches();
+ for (const auto &pair : switchMap)
+ log << " * " << toQt(pair.first) << toQt(pair.second) << "\n";
+
+ qCDebug(webEngineContextLog) << qPrintable(log.join(" "));
}
}
@@ -732,7 +926,13 @@ WebEngineContext::WebEngineContext()
parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing);
}
-#if QT_CONFIG(webengine_vulkan) && defined(USE_OZONE)
+#if defined(USE_OZONE)
+ if (GPUInfo::instance()->vendor() == GPUInfo::Nvidia) {
+ disableFeatures.push_back(media::kVaapiVideoDecodeLinux.name);
+ parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames);
+ }
+
+#if QT_CONFIG(webengine_vulkan)
if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) {
enableFeatures.push_back(features::kVulkan.name);
parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan,
@@ -759,12 +959,13 @@ WebEngineContext::WebEngineContext()
qputenv(deviceExtensionsVar, requiredDeviceExtensions.join(';'));
}
}
-#endif // QT_CONFIG(webengine_vulkan) && defined(USE_OZONE)
+#endif // QT_CONFIG(webengine_vulkan)
+#endif // defined(USE_OZONE)
#if defined(Q_OS_WIN)
if (QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11
|| QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) {
- const QString luid = getAdapterLuid();
+ const QString luid = GPUInfo::instance()->getAdapterLuid();
if (!luid.isEmpty())
parsedCommandLine->AppendSwitchASCII(switches::kUseAdapterLuid, luid.toStdString());
}
@@ -779,9 +980,14 @@ WebEngineContext::WebEngineContext()
// performant, but at least provides WebGL support.
// TODO(miklocek), check if this still works with latest chromium
const bool disableGpu = parsedCommandLine->HasSwitch(switches::kDisableGpu);
- const char *glType = getGLType(enableGLSoftwareRendering, disableGpu);
+ std::string glType;
+ if (parsedCommandLine->HasSwitch(switches::kUseGL))
+ glType = parsedCommandLine->GetSwitchValueASCII(switches::kUseGL);
+ else {
+ glType = getGLType(enableGLSoftwareRendering, disableGpu);
+ parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType);
+ }
- parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType);
parsedCommandLine->AppendSwitch(switches::kInProcessGPU);
if (glType != gl::kGLImplementationDisabledName) {
@@ -791,7 +997,9 @@ WebEngineContext::WebEngineContext()
}
#if QT_CONFIG(opengl)
if (glType != gl::kGLImplementationANGLEName) {
- const QSurfaceFormat sharedFormat = QOpenGLContext::globalShareContext()->format();
+ QOpenGLContext *shareContext = QOpenGLContext::globalShareContext();
+ Q_ASSERT(shareContext);
+ const QSurfaceFormat sharedFormat = shareContext->format();
if (sharedFormat.profile() == QSurfaceFormat::CompatibilityProfile)
parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext);
#if defined(Q_OS_WIN)
diff --git a/src/pdf/doc/snippets/pdfpageview.qml b/src/pdf/doc/snippets/pdfpageview.qml
new file mode 100644
index 000000000..5e233961a
--- /dev/null
+++ b/src/pdf/doc/snippets/pdfpageview.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+import QtQuick
+import QtQuick.Pdf
+
+PdfPageView {
+ document: PdfDocument { source: "my.pdf" }
+}
+//! [0]
+
diff --git a/src/pdfquick/PdfPageView.qml b/src/pdfquick/PdfPageView.qml
index 290570f2b..e1d97f57b 100644
--- a/src/pdfquick/PdfPageView.qml
+++ b/src/pdfquick/PdfPageView.qml
@@ -30,7 +30,7 @@ Rectangle {
A PdfDocument object with a valid \c source URL is required:
- \snippet multipageview.qml 0
+ \snippet pdfpageview.qml 0
*/
required property PdfDocument document
diff --git a/src/pdfwidgets/qpdfview.cpp b/src/pdfwidgets/qpdfview.cpp
index a67667fed..a19b77a7f 100644
--- a/src/pdfwidgets/qpdfview.cpp
+++ b/src/pdfwidgets/qpdfview.cpp
@@ -19,7 +19,7 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(qLcLink, "qt.pdf.links")
+Q_LOGGING_CATEGORY(qLcWLink, "qt.pdf.widgets.links")
//#define DEBUG_LINKS
static const QColor SearchResultHighlight("#80B0C4DE");
@@ -681,7 +681,7 @@ void QPdfView::mouseMoveEvent(QMouseEvent *event)
auto dest = d->m_linkModel.linkAt(posInPoints);
setCursor(dest.isValid() ? Qt::PointingHandCursor : Qt::ArrowCursor);
if (dest.isValid())
- qCDebug(qLcLink) << event->position() << ":" << posInPoints << "pt ->" << dest;
+ qCDebug(qLcWLink) << event->position() << ":" << posInPoints << "pt ->" << dest;
}
}
}
@@ -699,7 +699,7 @@ void QPdfView::mouseReleaseEvent(QMouseEvent *event)
d->m_linkModel.setPage(page);
auto dest = d->m_linkModel.linkAt(posInPoints);
if (dest.isValid()) {
- qCDebug(qLcLink) << event << ": jumping to" << dest;
+ qCDebug(qLcWLink) << event << ": jumping to" << dest;
d->m_pageNavigator->jump(dest.page(), dest.location(), dest.zoom());
// TODO scroll and zoom to where the link tells us to
}
diff --git a/src/webenginequick/CMakeLists.txt b/src/webenginequick/CMakeLists.txt
index 5f8344f08..b7de1c2af 100644
--- a/src/webenginequick/CMakeLists.txt
+++ b/src/webenginequick/CMakeLists.txt
@@ -37,8 +37,8 @@ qt_internal_add_qml_module(WebEngineQuick
api/qquickwebengineforeigntypes_p.h
api/qtwebenginequickglobal.cpp api/qtwebenginequickglobal.h
api/qtwebenginequickglobal_p.h
- render_widget_host_view_qt_delegate_quickwindow.cpp render_widget_host_view_qt_delegate_quickwindow.h
- ui_delegates_manager.cpp ui_delegates_manager.h
+ render_widget_host_view_qt_delegate_quickwindow.cpp render_widget_host_view_qt_delegate_quickwindow_p.h
+ ui_delegates_manager.cpp ui_delegates_manager_p.h
DEFINES
QT_BUILD_WEBENGINE_LIB
INCLUDE_DIRECTORIES
@@ -65,7 +65,7 @@ qt_internal_extend_target(WebEngineQuick CONDITION QT_FEATURE_webengine_webchann
qt_internal_extend_target(WebEngineQuick CONDITION QT_FEATURE_accessibility
SOURCES
- qquickwebengine_accessible.cpp qquickwebengine_accessible.h
+ qquickwebengine_accessible.cpp qquickwebengine_accessible_p.h
)
qt_internal_extend_target(qtwebenginequickplugin
diff --git a/src/webenginequick/api/qquickwebenginefaviconprovider.cpp b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
index 56bbb97ac..00c7f1949 100644
--- a/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
+++ b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
@@ -11,9 +11,9 @@
#include "web_contents_adapter.h"
#include <QtCore/qmimedatabase.h>
-#include <QtCore/qtimer.h>
#include <QtGui/qicon.h>
#include <QtGui/qpixmap.h>
+#include <QThread>
QT_BEGIN_NAMESPACE
@@ -79,123 +79,167 @@ static bool isIconURL(const QUrl &url)
return false;
}
-static QQuickWebEngineView *findViewById(const QString &id, QList<QQuickWebEngineView *> *views)
-{
- QQuickWebEngineView *result = nullptr;
- for (QQuickWebEngineView *view : *views) {
- if (isIconURL(QUrl(id))) {
- if (view->icon() == QQuickWebEngineFaviconProvider::faviconProviderUrl(QUrl(id))) {
- result = view;
- break;
- }
- } else if (view->url() == QUrl(id)) {
- result = view;
- break;
- }
- }
-
- return result;
-}
-
-FaviconImageResponseRunnable::FaviconImageResponseRunnable(const QString &id,
- const QSize &requestedSize,
- QList<QQuickWebEngineView *> *views)
- : m_id(id), m_requestedSize(requestedSize), m_views(views)
+FaviconImageRequester::FaviconImageRequester(const QUrl &imageSource, const QSize &requestedSize)
+ : m_imageSource(imageSource), m_requestedSize(requestedSize)
{
}
-void FaviconImageResponseRunnable::run()
+void FaviconImageRequester::start()
{
- if (tryNextView() == -1) {
+ if (!tryNextView()) {
// There is no non-otr view to access icon database.
Q_EMIT done(QPixmap());
}
}
-void FaviconImageResponseRunnable::iconRequestDone(const QIcon &icon)
+void FaviconImageRequester::iconRequestDone(const QIcon &icon)
{
if (icon.isNull()) {
- if (tryNextView() == -1) {
+ if (!tryNextView()) {
// Ran out of views.
Q_EMIT done(QPixmap());
}
return;
}
- Q_EMIT done(extractPixmap(icon, m_requestedSize).copy());
+ Q_EMIT done(extractPixmap(icon, m_requestedSize));
+}
+
+bool FaviconImageRequester::tryNextView()
+{
+ if (auto view = getNextViewForProcessing()) {
+ requestFaviconFromDatabase(view);
+ return true;
+ }
+
+ return false;
+}
+
+void FaviconImageRequester::requestFaviconFromDatabase(QPointer<QQuickWebEngineView> view)
+{
+ QtWebEngineCore::ProfileAdapter *profileAdapter = view->d_ptr->profileAdapter();
+ bool touchIconsEnabled = view->profile()->settings()->touchIconsEnabled();
+ if (isIconURL(m_imageSource)) {
+ profileAdapter->requestIconForIconURL(
+ m_imageSource, qMax(m_requestedSize.width(), m_requestedSize.height()),
+ touchIconsEnabled, [this](const QIcon &icon, const QUrl &) {
+ QMetaObject::invokeMethod(this, "iconRequestDone", Qt::QueuedConnection,
+ Q_ARG(const QIcon &, icon));
+ });
+ } else {
+ profileAdapter->requestIconForPageURL(
+ m_imageSource, qMax(m_requestedSize.width(), m_requestedSize.height()),
+ touchIconsEnabled, [this](const QIcon &icon, const QUrl &, const QUrl &) {
+ QMetaObject::invokeMethod(this, "iconRequestDone", Qt::QueuedConnection,
+ Q_ARG(const QIcon &, icon));
+ });
+ }
}
-int FaviconImageResponseRunnable::tryNextView()
+QPointer<QQuickWebEngineView> FaviconImageRequester::getNextViewForProcessing()
{
- for (; m_nextViewIndex < m_views->size(); ++m_nextViewIndex) {
- QQuickWebEngineView *view = m_views->at(m_nextViewIndex);
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+
+ for (QPointer<QQuickWebEngineView> view : FaviconProviderHelper::instance()->views()) {
+ if (view.isNull())
+ continue;
if (view->profile()->isOffTheRecord())
continue;
+ if (m_processedViews.contains(view))
+ continue;
+ m_processedViews.append(view);
+ return view;
+ }
+ return nullptr;
+}
- requestIconOnUIThread(view);
+FaviconProviderHelper::FaviconProviderHelper()
+{
+ moveToThread(qApp->thread());
+}
- return m_nextViewIndex++;
- }
+FaviconProviderHelper *FaviconProviderHelper::instance()
+{
+ static FaviconProviderHelper instance;
+ return &instance;
+}
- return -1;
+void FaviconProviderHelper::attach(QPointer<QQuickWebEngineView> view)
+{
+ if (!m_views.contains(view))
+ m_views.append(view);
}
-void FaviconImageResponseRunnable::requestIconOnUIThread(QQuickWebEngineView *view)
+void FaviconProviderHelper::detach(QPointer<QQuickWebEngineView> view)
{
- QTimer *timer = new QTimer();
- timer->moveToThread(qApp->thread());
- timer->setSingleShot(true);
- QObject::connect(timer, &QTimer::timeout, [this, view, timer]() {
- QtWebEngineCore::ProfileAdapter *profileAdapter = view->d_ptr->profileAdapter();
- bool touchIconsEnabled = view->profile()->settings()->touchIconsEnabled();
- if (isIconURL(QUrl(m_id))) {
- profileAdapter->requestIconForIconURL(QUrl(m_id),
- qMax(m_requestedSize.width(), m_requestedSize.height()),
- touchIconsEnabled,
- [this](const QIcon &icon, const QUrl &) { iconRequestDone(icon); });
- } else {
- profileAdapter->requestIconForPageURL(QUrl(m_id),
- qMax(m_requestedSize.width(), m_requestedSize.height()),
- touchIconsEnabled,
- [this](const QIcon &icon, const QUrl &, const QUrl &) { iconRequestDone(icon); });
- }
- timer->deleteLater();
- });
- QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
+ m_views.removeAll(view);
}
-FaviconImageResponse::FaviconImageResponse()
+void FaviconProviderHelper::handleImageRequest(QPointer<FaviconImageResponse> faviconResponse)
{
- Q_EMIT finished();
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+
+ if (faviconResponse.isNull())
+ return;
+
+ if (m_views.isEmpty()) {
+ QMetaObject::invokeMethod(faviconResponse, "handleDone", Qt::QueuedConnection,
+ Q_ARG(QPixmap, QPixmap()));
+ return;
+ }
+
+ auto view = findViewByImageSource(faviconResponse->imageSource());
+ if (view) {
+ QIcon icon = view->d_ptr->adapter->icon();
+ if (!icon.isNull()) {
+ QMetaObject::invokeMethod(
+ faviconResponse, "handleDone", Qt::QueuedConnection,
+ Q_ARG(QPixmap, extractPixmap(icon, faviconResponse->requestedSize())));
+ return;
+ }
+ }
+ startFaviconRequest(faviconResponse);
}
-FaviconImageResponse::FaviconImageResponse(const QString &id, const QSize &requestedSize,
- QList<QQuickWebEngineView *> *views, QThreadPool *pool)
+QPointer<QQuickWebEngineView> FaviconProviderHelper::findViewByImageSource(const QUrl &imageSource) const
{
- if (QQuickWebEngineView *view = findViewById(id, views)) {
- QTimer *timer = new QTimer();
- timer->moveToThread(qApp->thread());
- timer->setSingleShot(true);
- QObject::connect(timer, &QTimer::timeout, [this, id, requestedSize, views, pool, view, timer]() {
- QIcon icon = view->d_ptr->adapter->icon();
- if (icon.isNull())
- startRunnable(id, requestedSize, views, pool);
- else
- handleDone(extractPixmap(icon, requestedSize).copy());
- timer->deleteLater();
- });
- QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
- } else {
- startRunnable(id, requestedSize, views, pool);
+ for (QPointer<QQuickWebEngineView> view : m_views) {
+ if (view.isNull())
+ continue;
+
+ if (isIconURL(imageSource)) {
+ if (view->icon() == QQuickWebEngineFaviconProvider::faviconProviderUrl(imageSource)) {
+ return view;
+ }
+ } else if (view->url() == imageSource) {
+ return view;
+ }
}
+
+ return nullptr;
}
-FaviconImageResponse::~FaviconImageResponse() { }
+void FaviconProviderHelper::startFaviconRequest(QPointer<FaviconImageResponse> faviconResponse)
+{
+ FaviconImageRequester *requester = new FaviconImageRequester(faviconResponse->imageSource(),
+ faviconResponse->requestedSize());
+
+ connect(requester, &FaviconImageRequester::done, [requester, faviconResponse](QPixmap pixmap) {
+ QMetaObject::invokeMethod(faviconResponse, "handleDone", Qt::QueuedConnection,
+ Q_ARG(QPixmap, pixmap));
+ requester->deleteLater();
+ });
+
+ requester->start();
+}
+
+FaviconImageResponse::FaviconImageResponse(const QUrl &imageSource, const QSize &requestedSize)
+ : m_imageSource(imageSource), m_requestedSize(requestedSize)
+{
+}
void FaviconImageResponse::handleDone(QPixmap pixmap)
{
- if (m_runnable)
- delete m_runnable;
m_image = pixmap.toImage();
Q_EMIT finished();
}
@@ -205,16 +249,6 @@ QQuickTextureFactory *FaviconImageResponse::textureFactory() const
return QQuickTextureFactory::textureFactoryForImage(m_image);
}
-void FaviconImageResponse::startRunnable(const QString &id, const QSize &requestedSize,
- QList<QQuickWebEngineView *> *views, QThreadPool *pool)
-{
- m_runnable = new FaviconImageResponseRunnable(id, requestedSize, views);
- m_runnable->setAutoDelete(false);
- connect(m_runnable, &FaviconImageResponseRunnable::done, this,
- &FaviconImageResponse::handleDone);
- pool->start(m_runnable);
-}
-
QString QQuickWebEngineFaviconProvider::identifier()
{
return QStringLiteral("favicon");
@@ -238,17 +272,17 @@ QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url)
return providerUrl;
}
-QQuickWebEngineFaviconProvider::QQuickWebEngineFaviconProvider() { }
-
-QQuickWebEngineFaviconProvider::~QQuickWebEngineFaviconProvider() { }
+QQuickWebEngineFaviconProvider::QQuickWebEngineFaviconProvider()
+{
+ connect(this, &QQuickWebEngineFaviconProvider::imageResponseRequested,
+ FaviconProviderHelper::instance(), &FaviconProviderHelper::handleImageRequest);
+}
QQuickImageResponse *
QQuickWebEngineFaviconProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
{
- if (m_views.empty())
- return new FaviconImageResponse;
-
- FaviconImageResponse *response = new FaviconImageResponse(id, requestedSize, &m_views, &m_pool);
+ FaviconImageResponse *response = new FaviconImageResponse(QUrl(id), requestedSize);
+ emit imageResponseRequested(response);
return response;
}
diff --git a/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h b/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h
index 89bfb6e73..f1d948413 100644
--- a/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h
+++ b/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h
@@ -17,8 +17,6 @@
#include <QtWebEngineQuick/private/qtwebenginequickglobal_p.h>
#include <QtCore/qlist.h>
-#include <QtCore/qrunnable.h>
-#include <QtCore/qthreadpool.h>
#include <QtGui/qimage.h>
#include <QtQuick/qquickimageprovider.h>
@@ -26,65 +24,84 @@ QT_BEGIN_NAMESPACE
class QQuickWebEngineView;
-class FaviconImageResponseRunnable : public QObject, public QRunnable
+class FaviconImageResponse : public QQuickImageResponse
{
Q_OBJECT
public:
- FaviconImageResponseRunnable(const QString &id, const QSize &requestedSize,
- QList<QQuickWebEngineView *> *views);
- void run() override;
- void iconRequestDone(const QIcon &icon);
+ FaviconImageResponse(const QUrl &imageSource, const QSize &requestedSize);
-signals:
- void done(QPixmap pixmap);
+ QQuickTextureFactory *textureFactory() const override;
+ const QUrl &imageSource() const { return m_imageSource; }
+ const QSize &requestedSize() const { return m_requestedSize; }
-private:
- int tryNextView();
- void requestIconOnUIThread(QQuickWebEngineView *view);
+public slots:
+ void handleDone(QPixmap pixmap);
- QString m_id;
+private:
+ QImage m_image;
+ QUrl m_imageSource;
QSize m_requestedSize;
- QList<QQuickWebEngineView *> *m_views;
- int m_nextViewIndex = 0;
};
-class FaviconImageResponse : public QQuickImageResponse
+class FaviconImageRequester : public QObject
{
+ Q_OBJECT
+
public:
- FaviconImageResponse();
- FaviconImageResponse(const QString &id, const QSize &requestedSize,
- QList<QQuickWebEngineView *> *views, QThreadPool *pool);
- ~FaviconImageResponse();
- void handleDone(QPixmap pixmap);
- QQuickTextureFactory *textureFactory() const override;
+ FaviconImageRequester(const QUrl &imageSource, const QSize &requestedSize);
+ void start();
+
+public slots:
+ void iconRequestDone(const QIcon &icon);
+
+signals:
+ void done(QPixmap pixmap);
private:
- void startRunnable(const QString &id, const QSize &requestedSize,
- QList<QQuickWebEngineView *> *views, QThreadPool *pool);
+ bool tryNextView();
+ void requestFaviconFromDatabase(QPointer<QQuickWebEngineView> view);
+ QPointer<QQuickWebEngineView> getNextViewForProcessing();
- FaviconImageResponseRunnable *m_runnable = nullptr;
- QImage m_image;
+ QUrl m_imageSource;
+ QSize m_requestedSize;
+ QList<QPointer<QQuickWebEngineView>> m_processedViews;
};
class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineFaviconProvider : public QQuickAsyncImageProvider
{
+ Q_OBJECT
+
public:
static QString identifier();
static QUrl faviconProviderUrl(const QUrl &);
QQuickWebEngineFaviconProvider();
- ~QQuickWebEngineFaviconProvider();
-
- void attach(QQuickWebEngineView *view) { m_views.append(view); }
- void detach(QQuickWebEngineView *view) { m_views.removeAll(view); }
-
QQuickImageResponse *requestImageResponse(const QString &id,
const QSize &requestedSize) override;
+signals:
+ void imageResponseRequested(QPointer<FaviconImageResponse> faviconResponse);
+};
+
+class Q_WEBENGINEQUICK_EXPORT FaviconProviderHelper : public QObject
+{
+ Q_OBJECT
+
+public:
+ static FaviconProviderHelper *instance();
+ void attach(QPointer<QQuickWebEngineView> view);
+ void detach(QPointer<QQuickWebEngineView> view);
+ const QList<QPointer<QQuickWebEngineView>> &views() const { return m_views; }
+
+public slots:
+ void handleImageRequest(QPointer<FaviconImageResponse> faviconResponse);
+
private:
- QThreadPool m_pool;
- QList<QQuickWebEngineView *> m_views;
+ FaviconProviderHelper();
+ void startFaviconRequest(QPointer<FaviconImageResponse> faviconResponse);
+ QPointer<QQuickWebEngineView> findViewByImageSource(const QUrl &imageSource) const;
+ QList<QPointer<QQuickWebEngineView>> m_views;
};
QT_END_NAMESPACE
diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp
index 7c3d11fcf..edca5e99c 100644
--- a/src/webenginequick/api/qquickwebengineprofile.cpp
+++ b/src/webenginequick/api/qquickwebengineprofile.cpp
@@ -105,6 +105,8 @@ QT_BEGIN_NAMESPACE
The download item is parented by the profile. If it is not accepted, it
will be deleted immediately after the signal emission.
This signal cannot be used with a queued connection.
+
+ \note To use from C++ static_cast \a download to QWebEngineDownloadRequest
*/
/*!
@@ -113,6 +115,8 @@ QT_BEGIN_NAMESPACE
This signal is emitted whenever downloading stops, because it finished successfully, was
cancelled, or was interrupted (for example, because connectivity was lost).
The \a download argument holds the state of the finished download instance.
+
+ \note To use from C++ static_cast \a download to QWebEngineDownloadRequest
*/
/*!
diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h
index 088a971e0..cbeb91147 100644
--- a/src/webenginequick/api/qquickwebengineprofile.h
+++ b/src/webenginequick/api/qquickwebengineprofile.h
@@ -144,7 +144,7 @@ private:
QQuickWebEngineSettings *settings() const;
void ensureQmlContext(const QObject *object);
- friend class FaviconImageResponseRunnable;
+ friend class FaviconImageRequester;
friend class QQuickWebEngineSingleton;
friend class QQuickWebEngineViewPrivate;
friend class QQuickWebEngineView;
diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp
index 31e5d572e..5a68cf687 100644
--- a/src/webenginequick/api/qquickwebengineview.cpp
+++ b/src/webenginequick/api/qquickwebengineview.cpp
@@ -25,9 +25,9 @@
#include "find_text_helper.h"
#include "javascript_dialog_controller.h"
#include "render_widget_host_view_qt_delegate_item.h"
-#include "render_widget_host_view_qt_delegate_quickwindow.h"
+#include "render_widget_host_view_qt_delegate_quickwindow_p.h"
#include "touch_selection_menu_controller.h"
-#include "ui_delegates_manager.h"
+#include "ui_delegates_manager_p.h"
#include "web_contents_adapter.h"
#include <QtWebEngineCore/qwebenginecertificateerror.h>
@@ -63,7 +63,7 @@
#include <QtQml/qqmlproperty.h>
#if QT_CONFIG(accessibility)
-#include "qquickwebengine_accessible.h"
+#include "qquickwebengine_accessible_p.h"
#include <QtGui/qaccessible.h>
#endif
@@ -332,8 +332,7 @@ QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate()
{
Q_ASSERT(m_profileInitialized);
m_profile->d_ptr->removeWebContentsAdapterClient(this);
- if (m_faviconProvider)
- m_faviconProvider->detach(q_ptr);
+ FaviconProviderHelper::instance()->detach(q_ptr);
bindViewAndDelegateItem(this, nullptr);
}
@@ -446,10 +445,10 @@ void QQuickWebEngineViewPrivate::contextMenuRequested(QWebEngineContextMenuReque
ui()->showMenu(menu);
}
-void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame)
+void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame, bool hasFrameData)
{
Q_Q(QQuickWebEngineView);
- auto request = new QWebEngineNavigationRequest(url, static_cast<QWebEngineNavigationRequest::NavigationType>(navigationType), isMainFrame);
+ auto request = new QWebEngineNavigationRequest(url, static_cast<QWebEngineNavigationRequest::NavigationType>(navigationType), isMainFrame, hasFrameData);
qmlEngine(q)->newQObject(request);
Q_EMIT q->navigationRequested(request);
@@ -573,6 +572,12 @@ void QQuickWebEngineViewPrivate::iconChanged(const QUrl &url)
QTimer::singleShot(0, q, &QQuickWebEngineView::iconChanged);
}
+void QQuickWebEngineViewPrivate::zoomFactorChanged(qreal factor)
+{
+ Q_Q(QQuickWebEngineView);
+ Q_EMIT q->zoomFactorChanged(factor);
+}
+
void QQuickWebEngineViewPrivate::loadProgressChanged(int progress)
{
Q_Q(QQuickWebEngineView);
@@ -951,16 +956,7 @@ void QQuickWebEngineViewPrivate::ensureContentsAdapter()
adapter->loadDefault();
}
- if (!m_faviconProvider) {
- QQmlEngine *engine = qmlEngine(q_ptr);
- // TODO: this is a workaround for QTBUG-65044
- if (!engine)
- return;
- m_faviconProvider = static_cast<QQuickWebEngineFaviconProvider *>(
- engine->imageProvider(QQuickWebEngineFaviconProvider::identifier()));
- m_faviconProvider->attach(q_ptr);
- Q_ASSERT(m_faviconProvider);
- }
+ FaviconProviderHelper::instance()->attach(q_ptr);
}
void QQuickWebEngineViewPrivate::initializationFinished()
@@ -1235,7 +1231,6 @@ void QQuickWebEngineView::setZoomFactor(qreal arg)
d->adapter->setZoomFactor(arg);
// MEMO: should reset if factor was not applied due to being invalid
d->m_zoomFactor = zoomFactor();
- emit zoomFactorChanged(d->m_zoomFactor);
} else {
d->m_zoomFactor = arg;
}
@@ -1306,19 +1301,18 @@ bool QQuickWebEngineView::activeFocusOnPress() const
return d->m_activeFocusOnPress;
}
-void QQuickWebEngineViewPrivate::didRunJavaScript(quint64 requestId, const QVariant &result)
+void QQuickWebEngineViewPrivate::runJavaScript(
+ const QString &script, quint32 worldId,
+ const std::function<void(const QVariant &)> &callback)
{
- Q_Q(QQuickWebEngineView);
- QJSValue callback = m_callbacks.take(requestId);
- QJSValueList args;
- args.append(qmlEngine(q)->toScriptValue(result));
- callback.call(args);
+ ensureContentsAdapter();
+ adapter->runJavaScript(script, worldId, callback);
}
void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result)
{
Q_Q(QQuickWebEngineView);
- QJSValue callback = m_callbacks.take(requestId);
+ QJSValue callback = m_printCallbacks.take(requestId);
QJSValueList args;
args.append(qmlEngine(q)->toScriptValue(*(result.data())));
callback.call(args);
@@ -1497,16 +1491,15 @@ void QQuickWebEngineView::runJavaScript(const QString &script, const QJSValue &c
void QQuickWebEngineView::runJavaScript(const QString &script, quint32 worldId, const QJSValue &callback)
{
Q_D(QQuickWebEngineView);
- d->ensureContentsAdapter();
+ std::function<void(const QVariant &)> wrappedCallback;
if (!callback.isUndefined()) {
- quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script, worldId);
- if (requestId) {
- d->m_callbacks.insert(requestId, callback);
- } else {
- callback.call();
- }
- } else
- d->adapter->runJavaScript(script, worldId);
+ wrappedCallback = [this, callback](const QVariant &result) {
+ QJSValueList args;
+ args.append(qmlEngine(this)->toScriptValue(result));
+ callback.call(args);
+ };
+ }
+ d->runJavaScript(script, worldId, wrappedCallback);
}
qreal QQuickWebEngineView::zoomFactor() const
@@ -1603,7 +1596,7 @@ void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId
d->ensureContentsAdapter();
quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout, ranges);
- d->m_callbacks.insert(requestId, callback);
+ d->m_printCallbacks.insert(requestId, callback);
#else
Q_UNUSED(pageSizeId);
Q_UNUSED(orientation);
@@ -2529,6 +2522,19 @@ QQmlComponent *QQuickWebEngineView::touchHandleDelegate() const
return d_ptr->m_touchHandleDelegate;
}
+QWebEngineFrame QQuickWebEngineView::mainFrame()
+{
+ Q_D(QQuickWebEngineView);
+ return QWebEngineFrame(d, d->adapter->mainFrameId());
+}
+
+QWebEngineFrame QQuickWebEngineView::findFrameByName(const QString &name)
+{
+ Q_D(QQuickWebEngineView);
+ auto maybeId = d->adapter->findFrameIdByName(name);
+ return QWebEngineFrame(d, maybeId.value_or(WebContentsAdapter::kInvalidFrameId));
+}
+
void QQuickWebEngineView::save(const QString &filePath,
QWebEngineDownloadRequest::SavePageFormat format) const
{
diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h
index 0fdd9f787..37e39dfed 100644
--- a/src/webenginequick/api/qquickwebengineview_p.h
+++ b/src/webenginequick/api/qquickwebengineview_p.h
@@ -19,6 +19,7 @@
#include <QtWebEngineCore/qwebenginequotarequest.h>
#include <QtWebEngineCore/qwebenginedesktopmediarequest.h>
#include <QtWebEngineCore/qwebenginedownloadrequest.h>
+#include <QtWebEngineCore/qwebengineframe.h>
#include <QtWebEngineQuick/private/qtwebenginequickglobal_p.h>
#include <QtGui/qcolor.h>
#include <QtQml/qqmlregistration.h>
@@ -91,6 +92,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineView : public QQuickItem {
Q_PROPERTY(qint64 renderProcessPid READ renderProcessPid NOTIFY renderProcessPidChanged FINAL REVISION(1,11))
Q_PROPERTY(QQmlComponent *touchHandleDelegate READ touchHandleDelegate WRITE
setTouchHandleDelegate NOTIFY touchHandleDelegateChanged REVISION(0) FINAL)
+ Q_PROPERTY(QWebEngineFrame mainFrame READ mainFrame FINAL REVISION(6, 8))
QML_NAMED_ELEMENT(WebEngineView)
QML_ADDED_IN_VERSION(1, 0)
QML_EXTRA_VERSION(2, 0)
@@ -472,6 +474,9 @@ QT_WARNING_POP
QQmlComponent *touchHandleDelegate() const;
void setTouchHandleDelegate(QQmlComponent *delegagte);
+ QWebEngineFrame mainFrame();
+ Q_REVISION(6, 8) Q_INVOKABLE QWebEngineFrame findFrameByName(const QString &name);
+
public Q_SLOTS:
void runJavaScript(const QString&, const QJSValue & = QJSValue());
Q_REVISION(1,3) void runJavaScript(const QString&, quint32 worldId, const QJSValue & = QJSValue());
@@ -572,8 +577,8 @@ private:
QScopedPointer<QQuickWebEngineViewPrivate> d_ptr;
friend class QQuickContextMenuBuilder;
- friend class FaviconImageResponse;
- friend class FaviconImageResponseRunnable;
+ friend class FaviconProviderHelper;
+ friend class FaviconImageRequester;
#if QT_CONFIG(accessibility)
friend class QQuickWebEngineViewAccessible;
#endif // QT_CONFIG(accessibility)
diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h
index ee7da99b9..addb15408 100644
--- a/src/webenginequick/api/qquickwebengineview_p_p.h
+++ b/src/webenginequick/api/qquickwebengineview_p_p.h
@@ -19,7 +19,7 @@
#include "qquickwebengineview_p.h"
#include "render_view_context_menu_qt.h"
#include "touch_handle_drawable_client.h"
-#include "ui_delegates_manager.h"
+#include "ui_delegates_manager_p.h"
#include "web_contents_adapter_client.h"
#include <QtCore/qcompilerdetection.h>
@@ -37,7 +37,6 @@ class WebContentsAdapter;
QT_BEGIN_NAMESPACE
class QQmlComponent;
-class QQuickWebEngineFaviconProvider;
class QQuickWebEngineScriptCollection;
class QQuickWebEngineSettings;
class QQuickWebEngineView;
@@ -65,6 +64,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;
@@ -88,12 +88,13 @@ public:
void requestFullScreenMode(const QUrl &origin, bool fullscreen) override;
bool isFullScreenMode() const override;
void contextMenuRequested(QWebEngineContextMenuRequest *request) override;
- void navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame) override;
+ void navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame, bool hasFrameData) override;
void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) override;
void runFileChooser(QSharedPointer<QtWebEngineCore::FilePickerController>) override;
void desktopMediaRequested(QtWebEngineCore::DesktopMediaController *) override;
void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>) override;
- void didRunJavaScript(quint64, const QVariant&) override;
+ void runJavaScript(const QString &script, quint32 worldId,
+ const std::function<void(const QVariant &)> &callback) override;
void didFetchDocumentMarkup(quint64, const QString&) override { }
void didFetchDocumentInnerText(quint64, const QString&) override { }
void didPrintPage(quint64 requestId, QSharedPointer<QByteArray>) override;
@@ -158,7 +159,7 @@ public:
bool m_fullscreenMode;
bool isLoading;
bool m_activeFocusOnPress;
- QMap<quint64, QJSValue> m_callbacks;
+ QMap<quint64, QJSValue> m_printCallbacks;
QQmlWebChannel *m_webChannel;
QPointer<QQuickWebEngineView> inspectedView;
QPointer<QQuickWebEngineView> devToolsView;
@@ -178,7 +179,6 @@ private:
bool m_profileInitialized;
QWebEngineContextMenuRequest *m_contextMenuRequest;
QScopedPointer<QQuickWebEngineScriptCollection> m_scriptCollection;
- QPointer<QQuickWebEngineFaviconProvider> m_faviconProvider;
QQmlComponent *m_touchHandleDelegate;
};
diff --git a/src/webenginequick/doc/src/webengineframe.qdoc b/src/webenginequick/doc/src/webengineframe.qdoc
new file mode 100644
index 000000000..ef2a5c33d
--- /dev/null
+++ b/src/webenginequick/doc/src/webengineframe.qdoc
@@ -0,0 +1,65 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \qmltype webEngineFrame
+ \instantiates QQuickWebEngineFrame
+ \brief webEngineFrame provides information about and control over a page frame.
+ \since 6.8
+ \ingroup qmlvaluetypes
+ \inqmlmodule QtWebEngine
+
+ A web engine frame represents a single frame within a web page, such as those created by
+ \c <frame> or \c <iframe> HTML elements.
+ An active \l WebEngineView has one or more frames arranged in a tree structure. The top-level
+ frame, the root of this tree, can be accessed through the view's \l {WebEngineView::mainFrame}
+ {mainFrame} property.
+
+ A frame's lifetime is, at most, as long as the \l WebEngineView object that produced it.
+ However, frames may be created and deleted spontaneously and dynamically, for example through
+ navigation and script execution.
+*/
+
+/*!
+ \qmlproperty bool webEngineFrame::isValid
+
+ Returns \c{true} if this object represents an existing frame; \c{false} otherwise.
+
+ Once a frame is invalid, it never becomes valid again.
+*/
+
+/*!
+ \qmlproperty string webEngineFrame::name
+
+ Returns the frame name; that is, what would be returned by \c window.name in JavaScript.
+
+ If the frame could not be found, returns an empty string.
+
+ \sa htmlName
+*/
+
+/*!
+ \qmlproperty string webEngineFrame::htmlName
+
+ Returns the value of the frame's \c name HTML attribute, or an empty string if it has none.
+
+ If the frame could not be found, returns an empty string.
+
+ \sa name
+*/
+
+/*!
+ \qmlproperty url webEngineFrame::url
+
+ Returns the URL of the content currently loaded in this frame.
+
+ If the frame could not be found, returns an empty URL.
+*/
+
+/*!
+ \qmlproperty size webEngineFrame::size
+
+ Returns the size of the frame within the viewport.
+
+ If the frame could not be found, returns a default size with dimensions (-1, -1).
+*/
diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
index eeae34dcc..bbefcd2bc 100644
--- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc
+++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
@@ -367,6 +367,8 @@
/*!
\qmlmethod void WebEngineView::runJavaScript(string script, variant callback)
+ \qmlmethod void WebEngineView::runJavaScript(string script, int worldId, variant callback)
+
Runs the specified \a script in the content of the web view.
The \a callback parameter is optional. If a callback function is provided,
@@ -381,8 +383,10 @@
example, \c{Date} and \c{ArrayBuffer}. Unsupported data types include, for
example, \c{Function} and \c{Promise}.
- The script will run in the same \e world as other scripts that are
- part of the loaded site.
+ To avoid conflicts with other scripts executed on the page, the world in
+ which the script is run can be specified by \a worldId. The world ID must be
+ between \c 0 and \c 256. If you leave out the \c world ID, the script is
+ run in the \c MainWorld.
\warning Do not execute lengthy routines in the callback function, because it might block the
rendering of the web content.
@@ -1551,6 +1555,23 @@
*/
/*!
+ \qmlproperty webEngineFrame WebEngineView::mainFrame
+ \since QtWebEngine 6.8
+
+ The main, top-level frame of the page. All other frames on this page are accessible
+ as children of the main frame.
+ */
+
+/*!
+ \qmlmethod webEngineFrame WebEngineView::findFrameByName(string name)
+ \since QtWebEngine 6.8
+
+ Returns the frame with the given \a name. If there are multiple frames with the same
+ name, which one is returned is arbitrary. If no frame was found, returns an
+ \l{webEngineFrame::isValid}{invalid} frame.
+*/
+
+/*!
\qmlmethod void WebEngineView::save(const QString &filePath, QWebEngineDownloadRequest::SavePageFormat format)
\since QtWebEngine 6.6
@@ -1581,5 +1602,14 @@
\sa QWebEngineWebAuthUxRequest
*/
+/*!
+ \qmlsignal WebEngineView::zoomFactorChanged(qreal factor);
+ \since QtWebEngine 6.8
+
+ This signal is emitted whenever the zoom \a factor for the page changes.
+
+ \sa zoomFactor
+*/
+
\sa {WebEngine Qt Quick Custom Touch Handle Example}
*/
diff --git a/src/webenginequick/qquickwebengine_accessible.cpp b/src/webenginequick/qquickwebengine_accessible.cpp
index 2941f01b5..e156a5e8b 100644
--- a/src/webenginequick/qquickwebengine_accessible.cpp
+++ b/src/webenginequick/qquickwebengine_accessible.cpp
@@ -1,7 +1,7 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "qquickwebengine_accessible.h"
+#include "qquickwebengine_accessible_p.h"
#include <QQuickItem>
#include <QQuickWindow>
diff --git a/src/webenginequick/qquickwebengine_accessible.h b/src/webenginequick/qquickwebengine_accessible_p.h
index 479de9789..2f774f898 100644
--- a/src/webenginequick/qquickwebengine_accessible.h
+++ b/src/webenginequick/qquickwebengine_accessible_p.h
@@ -4,6 +4,17 @@
#ifndef QQUICKWEBENGINE_ACCESSIBLE_H
#define QQUICKWEBENGINE_ACCESSIBLE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qpointer.h>
#include <QtGui/qaccessibleobject.h>
diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp
index b003dabe4..090b09281 100644
--- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp
+++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp
@@ -1,7 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "render_widget_host_view_qt_delegate_quickwindow.h"
+#include "render_widget_host_view_qt_delegate_quickwindow_p.h"
#include "api/qquickwebengineview_p_p.h"
diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.h b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h
index 712eef732..3559bd2f0 100644
--- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.h
+++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h
@@ -4,6 +4,17 @@
#ifndef RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_QUICKWINDOW_H
#define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_QUICKWINDOW_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "render_widget_host_view_qt_delegate.h"
#include "render_widget_host_view_qt_delegate_item.h"
diff --git a/src/webenginequick/ui_delegates_manager.cpp b/src/webenginequick/ui_delegates_manager.cpp
index 3d6eff649..a4a22fedd 100644
--- a/src/webenginequick/ui_delegates_manager.cpp
+++ b/src/webenginequick/ui_delegates_manager.cpp
@@ -1,7 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "ui_delegates_manager.h"
+#include "ui_delegates_manager_p.h"
#include "api/qquickwebengineaction_p.h"
#include "api/qquickwebengineview_p_p.h"
diff --git a/src/webenginequick/ui_delegates_manager.h b/src/webenginequick/ui_delegates_manager_p.h
index 24dde656c..3502757d7 100644
--- a/src/webenginequick/ui_delegates_manager.h
+++ b/src/webenginequick/ui_delegates_manager_p.h
@@ -4,6 +4,17 @@
#ifndef UI_DELEGATES_MANAGER_H
#define UI_DELEGATES_MANAGER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qcoreapplication.h> // Q_DECLARE_TR_FUNCTIONS
#include <QtCore/qobject.h>
#include <QtCore/qpoint.h>
diff --git a/src/webenginewidgets/CMakeLists.txt b/src/webenginewidgets/CMakeLists.txt
index dd11e48be..ff043b45a 100644
--- a/src/webenginewidgets/CMakeLists.txt
+++ b/src/webenginewidgets/CMakeLists.txt
@@ -37,7 +37,7 @@ qt_internal_add_module(WebEngineWidgets
qt_internal_extend_target(WebEngineWidgets CONDITION QT_FEATURE_accessibility
SOURCES
- qwebengine_accessible.cpp qwebengine_accessible.h
+ qwebengine_accessible.cpp qwebengine_accessible_p.h
)
qt_internal_extend_target(WebEngineWidgets CONDITION QT_FEATURE_webengine_printing_and_pdf
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index e28f70b5f..5b47d67bf 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -32,7 +32,7 @@
#include <QQuickWidget>
#if QT_CONFIG(accessibility)
-#include "qwebengine_accessible.h"
+#include "qwebengine_accessible_p.h"
#endif
#if QT_CONFIG(action)
diff --git a/src/webenginewidgets/qwebengine_accessible.cpp b/src/webenginewidgets/qwebengine_accessible.cpp
index 6880a5a3a..cbdd90104 100644
--- a/src/webenginewidgets/qwebengine_accessible.cpp
+++ b/src/webenginewidgets/qwebengine_accessible.cpp
@@ -1,7 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "qwebengine_accessible.h"
+#include "qwebengine_accessible_p.h"
#include "qwebengineview.h"
#include "qwebengineview_p.h"
diff --git a/src/webenginewidgets/qwebengine_accessible.h b/src/webenginewidgets/qwebengine_accessible_p.h
index f47996cf7..99604d90d 100644
--- a/src/webenginewidgets/qwebengine_accessible.h
+++ b/src/webenginewidgets/qwebengine_accessible_p.h
@@ -4,6 +4,17 @@
#ifndef QWEBENGINE_ACCESSIBLE_H
#define QWEBENGINE_ACCESSIBLE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QPointer>
#include <QtWidgets/QAccessibleWidget>