diff options
-rw-r--r-- | dist/changes-5.14.1 | 81 | ||||
-rw-r--r-- | src/core/browser_accessibility_qt.cpp | 13 | ||||
-rw-r--r-- | src/core/browser_accessibility_qt.h | 1 | ||||
-rw-r--r-- | src/core/web_engine_context.cpp | 14 | ||||
-rw-r--r-- | src/core/web_engine_context.h | 3 | ||||
-rw-r--r-- | src/core/web_engine_context_threads.cpp | 20 | ||||
-rw-r--r-- | src/webengine/doc/src/qtwebengine-platform-notes.qdoc | 34 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebengineview.cpp | 22 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebengineview_p.h | 1 | ||||
-rw-r--r-- | src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp | 28 | ||||
-rw-r--r-- | src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h | 17 | ||||
-rw-r--r-- | tests/auto/widgets/accessibility/tst_accessibility.cpp | 80 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/BLACKLIST | 1 |
13 files changed, 291 insertions, 24 deletions
diff --git a/dist/changes-5.14.1 b/dist/changes-5.14.1 new file mode 100644 index 000000000..c9395e81f --- /dev/null +++ b/dist/changes-5.14.1 @@ -0,0 +1,81 @@ +Qt 5.14.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.14.1 Changes * +**************************************************************************** + +Important changes +----------------- + + - [QTBUG-51170] Sandbox is now enabled by default on Windows like on + other platforms. If it causes any trouble it can be disabled with + --no-sandbox on the command line or in QTWEBENGINE_CHROMIUM_FLAGS. + +General +------- + + - [QTBUG-74602] Fixed builds with -no-gui + - [QTBUG-76564] Now supports accept attribute in file input + - [QTBUG-77442] Added macOS entitlements to QtWebEngineProcess.app + - [QTBUG-80089] Fixed touch flinging in multithreaded OpenGL mode + - [QTBUG-80566] Fixed setDownloadDirectory, so order compared to + setDownloadFilename doesn't matter + - [QTBUG-80893] Fixed crash when handling QEvent::TouchCancel + - Fixed clang-cl build + - Fixed youtube in linux ltcg builds + + +Chromium +-------- + + - Security fixes from Chromium up to version 79.0.3945.117, including: + + * CVE-2019-13701 + * CVE-2019-13727 + * CVE-2019-13728 + * CVE-2019-13730 + * CVE-2019-13732 + * CVE-2019-13734 + * CVE-2019-13735 + * CVE-2019-13736 + * CVE-2019-13737 + * CVE-2019-13738 + * CVE-2019-13739 + * CVE-2019-13741 + * CVE-2019-13745 + * CVE-2019-13746 + * CVE-2019-13747 + * CVE-2019-13754 + * CVE-2019-13755 + * CVE-2019-13757 + * CVE-2019-13758 + * CVE-2019-13761 + * CVE-2019-13762 + * CVE-2019-13764 + * CVE-2020-6377 + * Security bug 889276 + * Security bug 974375 + * Security bug 1016703 + * Security bug 1017020 + * Security bug 1017961 + * Security bug 1025089 + * Security bug 1027905 + * Security bug 1028191 + * Security bug 1033260 diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index db6f371d3..816a46041 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -148,6 +148,19 @@ QAccessibleInterface *BrowserAccessibilityQt::child(int index) const return static_cast<BrowserAccessibilityQt*>(BrowserAccessibility::PlatformGetChild(index)); } +QAccessibleInterface *BrowserAccessibilityQt::focusChild() const +{ + if (state().focused) + return const_cast<BrowserAccessibilityQt *>(this); + + for (int i = 0; i < childCount(); ++i) { + if (QAccessibleInterface *iface = child(i)->focusChild()) + return iface; + } + + return nullptr; +} + int BrowserAccessibilityQt::childCount() const { return PlatformChildCount(); diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index decfc1e9d..4acac6aa7 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -68,6 +68,7 @@ public: // navigation, hierarchy QAccessibleInterface *parent() const override; QAccessibleInterface *child(int index) const override; + QAccessibleInterface *focusChild() const override; int childCount() const override; int indexOfChild(const QAccessibleInterface *) const override; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 08e7f2b41..7ccd8ce8d 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -261,7 +261,7 @@ void WebEngineContext::destroy() // Normally the GPU thread is shut down when the GpuProcessHost is destroyed // on IO thread (triggered by ~BrowserMainRunner). But by that time the UI // task runner is not working anymore so we need to do this earlier. - destroyGpuProcess(); + destroyGpuProcess(m_threadedGpu); base::MessagePump::Delegate *delegate = static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( @@ -413,7 +413,8 @@ static void appendToFeatureSwitch(base::CommandLine *commandLine, const char *fe } WebEngineContext::WebEngineContext() - : m_mainDelegate(new ContentMainDelegateQt) + : m_threadedGpu(true) + , m_mainDelegate(new ContentMainDelegateQt) , m_globalQObject(new QObject()) { #if defined(Q_OS_MACOS) @@ -516,13 +517,12 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); #endif - bool threadedGpu = true; #ifndef QT_NO_OPENGL - threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); + m_threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); #endif - threadedGpu = threadedGpu && !qEnvironmentVariableIsSet(kDisableInProcGpuThread); + m_threadedGpu = m_threadedGpu && !qEnvironmentVariableIsSet(kDisableInProcGpuThread); - bool enableViz = ((threadedGpu && !parsedCommandLine->HasSwitch("disable-viz-display-compositor")) + bool enableViz = ((m_threadedGpu && !parsedCommandLine->HasSwitch("disable-viz-display-compositor")) || parsedCommandLine->HasSwitch("enable-viz-display-compositor")); parsedCommandLine->RemoveSwitch("disable-viz-display-compositor"); parsedCommandLine->RemoveSwitch("enable-viz-display-compositor"); @@ -665,7 +665,7 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableGpu); } - registerMainThreadFactories(threadedGpu); + registerMainThreadFactories(m_threadedGpu); SetContentClient(new ContentClientQt); diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index ac0536596..edced9b42 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -129,8 +129,9 @@ private: ~WebEngineContext(); static void registerMainThreadFactories(bool threaded); - static void destroyGpuProcess(); + static void destroyGpuProcess(bool threaded); + bool m_threadedGpu; std::unique_ptr<base::RunLoop> m_runLoop; std::unique_ptr<ContentMainDelegateQt> m_mainDelegate; std::unique_ptr<content::ContentMainRunner> m_contentRunner; diff --git a/src/core/web_engine_context_threads.cpp b/src/core/web_engine_context_threads.cpp index e92cf3e9b..f0f055676 100644 --- a/src/core/web_engine_context_threads.cpp +++ b/src/core/web_engine_context_threads.cpp @@ -57,6 +57,8 @@ #include <memory> +#include <QEventLoop> + namespace QtWebEngineCore { struct GpuThreadControllerQt : content::GpuThreadController @@ -90,6 +92,20 @@ struct GpuThreadControllerQt : content::GpuThreadController s_gpuProcess->set_main_thread(childThread); } + static void cleanupVizProcess() + { + auto gpuChildThread = content::GpuChildThread::instance(); + if (!gpuChildThread) + return; + auto vizMain = gpuChildThread->viz_main(); + auto vizCompositorThreadRunner = vizMain->viz_compositor_thread_runner(); + if (!vizCompositorThreadRunner) + return; + QEventLoop loop; + vizCompositorThreadRunner->CleanupForShutdown(base::BindOnce(&QEventLoop::quit, base::Unretained(&loop))); + loop.exec(); + } + static void destroyGpuProcess() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -117,8 +133,10 @@ static std::unique_ptr<content::GpuThreadController> createGpuThreadController( } // static -void WebEngineContext::destroyGpuProcess() +void WebEngineContext::destroyGpuProcess(bool threaded) { + if (!threaded) + GpuThreadControllerQt::cleanupVizProcess(); GpuThreadControllerQt::destroyGpuProcess(); } diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc index 1b8320c0c..1af2141b1 100644 --- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc +++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc @@ -174,20 +174,32 @@ \section1 Sandboxing Support - \QWE provides out-of-the-box sandboxing support for Chromium render processes on Linux - and \macos. Sandboxing is currently not supported on Windows due to a limitation in how - the sandbox is set up and how it interacts with the host process provided by the \QWE - libraries. + \QWE provides out-of-the-box sandboxing support for Chromium render + processes. - On \macos, there are no special requirements for enabling sandbox support. + On Linux, note the following restrictions: - On Linux, the kernel has to support the anonymous namespaces feature (kernel version >= 3.8) - and seccomp-bpf feature (kernel version >= 3.5). Setuid sandboxes are not supported and are thus - disabled. + \list + \li The kernel has to support the anonymous namespaces feature + (kernel version 3.8 or later). However, on Debian, Ubuntu, + and other Debian-derived distributions, this feature is off + by default. It can be turned on by setting + \c /proc/sys/kernel/unprivileged_userns_clone to 1. + \li The kernel has to support the \c seccomp-bpf feature (kernel + version 3.5 or later). + \li Setuid sandboxes are not supported and are thus disabled. + \endlist + + To explicitly disable sandboxing, use one of the following options: + + \list + \li Set the \c QTWEBENGINE_DISABLE_SANDBOX environment variable to 1. + \li Pass the \c{--no-sandbox} command line argument to the user + application executable. + \li Set \c QTWEBENGINE_CHROMIUM_FLAGS to \c{--no-sandbox}. + \endlist - To explicitly disable sandboxing, the \c QTWEBENGINE_DISABLE_SANDBOX environment variable can be - set to 1 or alternatively the \c{--no-sandbox} command line argument can be passed to the user - application executable. + For more information, see \l{Using Command-Line Arguments}. \section1 Accessibility and Performance diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index de81448a9..a51f9b7a5 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -107,9 +107,18 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::RenderWidgetHostViewQ if (oldWidget) { q->layout()->removeWidget(oldWidget); oldWidget->hide(); +#if QT_CONFIG(accessibility) + QAccessible::deleteAccessibleInterface(QAccessible::uniqueId(QAccessible::queryAccessibleInterface(oldWidget))); +#endif } if (newWidget) { +#if QT_CONFIG(accessibility) + // An earlier QAccessible::queryAccessibleInterface() call may have already registered a default + // QAccessibleInterface for newWidget: remove it first to avoid assert in QAccessibleCache::insert(). + QAccessible::deleteAccessibleInterface(QAccessible::uniqueId(QAccessible::queryAccessibleInterface(newWidget))); + QAccessible::registerAccessibleInterface(new QtWebEngineCore::RenderWidgetHostViewQtDelegateWidgetAccessible(newWidget, q)); +#endif q->layout()->addWidget(newWidget); q->setFocusProxy(newWidget); newWidget->show(); @@ -462,11 +471,16 @@ void QWebEngineView::dropEvent(QDropEvent *e) #endif // QT_CONFIG(draganddrop) #ifndef QT_NO_ACCESSIBILITY +QAccessibleInterface *QWebEngineViewAccessible::focusChild() const +{ + if (child(0) && child(0)->focusChild()) + return child(0)->focusChild(); + return const_cast<QWebEngineViewAccessible *>(this); +} + int QWebEngineViewAccessible::childCount() const { - if (view() && child(0)) - return 1; - return 0; + return child(0) ? 1 : 0; } QAccessibleInterface *QWebEngineViewAccessible::child(int index) const @@ -478,7 +492,7 @@ QAccessibleInterface *QWebEngineViewAccessible::child(int index) const int QWebEngineViewAccessible::indexOfChild(const QAccessibleInterface *c) const { - if (c == child(0)) + if (child(0) && c == child(0)) return 0; return -1; } diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h index 7848e0cf3..dd0a5bedf 100644 --- a/src/webenginewidgets/api/qwebengineview_p.h +++ b/src/webenginewidgets/api/qwebengineview_p.h @@ -87,6 +87,7 @@ public: QWebEngineViewAccessible(QWebEngineView *o) : QAccessibleWidget(o) {} + QAccessibleInterface *focusChild() const override; int childCount() const override; QAccessibleInterface *child(int index) const override; int indexOfChild(const QAccessibleInterface *child) const override; diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index 894dca4fa..8ba312822 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -483,4 +483,32 @@ void RenderWidgetHostViewQtDelegateWidget::onWindowPosChanged() m_client->visualPropertiesChanged(); } +#if QT_CONFIG(accessibility) +RenderWidgetHostViewQtDelegateWidgetAccessible::RenderWidgetHostViewQtDelegateWidgetAccessible(RenderWidgetHostViewQtDelegateWidget *o, QWebEngineView *view) + : QAccessibleWidget(o) + , m_view(view) +{ +} + +QAccessibleInterface *RenderWidgetHostViewQtDelegateWidgetAccessible::focusChild() const +{ + return QAccessible::queryAccessibleInterface(m_view)->focusChild(); +} + +int RenderWidgetHostViewQtDelegateWidgetAccessible::childCount() const +{ + return QAccessible::queryAccessibleInterface(m_view)->childCount(); +} + +QAccessibleInterface *RenderWidgetHostViewQtDelegateWidgetAccessible::child(int index) const +{ + return QAccessible::queryAccessibleInterface(m_view)->child(index); +} + +int RenderWidgetHostViewQtDelegateWidgetAccessible::indexOfChild(const QAccessibleInterface *c) const +{ + return QAccessible::queryAccessibleInterface(m_view)->indexOfChild(c); +} +#endif // QT_CONFIG(accessibility) + } // namespace QtWebEngineCore diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h index 18f848da5..df1806b6f 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h @@ -43,11 +43,13 @@ #include "render_widget_host_view_qt_delegate.h" #include "web_contents_adapter_client.h" +#include <QAccessibleWidget> #include <QQuickItem> #include <QQuickWidget> QT_BEGIN_NAMESPACE class QWebEnginePage; +class QWebEngineView; class QWebEnginePagePrivate; QT_END_NAMESPACE @@ -115,6 +117,21 @@ private: QMetaObject::Connection m_parentDestroyedConnection; }; +#if QT_CONFIG(accessibility) +class RenderWidgetHostViewQtDelegateWidgetAccessible : public QAccessibleWidget +{ +public: + RenderWidgetHostViewQtDelegateWidgetAccessible(RenderWidgetHostViewQtDelegateWidget *o, QWebEngineView *view); + + QAccessibleInterface *focusChild() const override; + int childCount() const override; + QAccessibleInterface *child(int index) const override; + int indexOfChild(const QAccessibleInterface *child) const override; +private: + QWebEngineView *m_view; +}; +#endif // QT_CONFIG(accessibility) + } // namespace QtWebEngineCore #endif diff --git a/tests/auto/widgets/accessibility/tst_accessibility.cpp b/tests/auto/widgets/accessibility/tst_accessibility.cpp index b5def4cd7..117a9e573 100644 --- a/tests/auto/widgets/accessibility/tst_accessibility.cpp +++ b/tests/auto/widgets/accessibility/tst_accessibility.cpp @@ -20,9 +20,13 @@ #include <qtest.h> #include "../util.h" +#include <QHBoxLayout> +#include <QMainWindow> + #include <qaccessible.h> #include <qwebengineview.h> #include <qwebenginepage.h> +#include <qwebenginesettings.h> #include <qwidget.h> class tst_Accessibility : public QObject @@ -38,6 +42,8 @@ public Q_SLOTS: private Q_SLOTS: void noPage(); void hierarchy(); + void focusChild(); + void focusChild_data(); void text(); void value(); void roles_data(); @@ -142,6 +148,80 @@ void tst_Accessibility::hierarchy() QCOMPARE(input, child); } +void tst_Accessibility::focusChild_data() +{ + QTest::addColumn<QString>("interfaceName"); + QTest::addColumn<QVector<QAccessible::Role>>("ancestorRoles"); + + QTest::newRow("QWebEngineView") << QString("QWebEngineView") << QVector<QAccessible::Role>({QAccessible::Client}); + QTest::newRow("RenderWidgetHostViewQtDelegate") << QString("RenderWidgetHostViewQtDelegate") << QVector<QAccessible::Role>({QAccessible::Client}); + QTest::newRow("QMainWindow") << QString("QMainWindow") << QVector<QAccessible::Role>({QAccessible::Window, QAccessible::Client /* central widget */, QAccessible::Client /* view */}); +} + +void tst_Accessibility::focusChild() +{ + auto traverseToWebDocumentAccessibleInterface = [](QAccessibleInterface *iface) -> QAccessibleInterface * { + QFETCH(QVector<QAccessible::Role>, ancestorRoles); + for (int i = 0; i < ancestorRoles.size(); ++i) { + if (iface->childCount() == 0 || iface->role() != ancestorRoles[i]) + return nullptr; + iface = iface->child(0); + } + + if (iface->role() != QAccessible::WebDocument) + return nullptr; + + return iface; + }; + + QMainWindow mainWindow; + QWebEngineView *webView = new QWebEngineView; + QWidget *centralWidget = new QWidget; + QHBoxLayout *centralLayout = new QHBoxLayout; + centralWidget->setLayout(centralLayout); + mainWindow.setCentralWidget(centralWidget); + centralLayout->addWidget(webView); + + mainWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); + + webView->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); + webView->setHtml("<html><body>" \ + "<input id='input1' type='text' value='some text'/>" \ + "</body></html>"); + webView->show(); + QSignalSpy spyFinished(webView, &QWebEngineView::loadFinished); + QVERIFY(spyFinished.wait()); + + QVERIFY(webView->focusWidget()); + QAccessibleInterface *iface = nullptr; + QFETCH(QString, interfaceName); + if (interfaceName == "QWebEngineView") + iface = QAccessible::queryAccessibleInterface(webView); + else if (interfaceName == "RenderWidgetHostViewQtDelegate") + iface = QAccessible::queryAccessibleInterface(webView->focusWidget()); + else if (interfaceName == "QMainWindow") + iface = QAccessible::queryAccessibleInterface(&mainWindow); + QVERIFY(iface); + + // Make sure the input field does not have the focus. + evaluateJavaScriptSync(webView->page(), "document.getElementById('input1').blur()"); + QTRY_VERIFY(evaluateJavaScriptSync(webView->page(), "document.activeElement.id").toString().isEmpty()); + + QVERIFY(iface->focusChild()); + QTRY_COMPARE(iface->focusChild()->role(), QAccessible::WebDocument); + QCOMPARE(traverseToWebDocumentAccessibleInterface(iface), iface->focusChild()); + + // Set active focus on the input field. + evaluateJavaScriptSync(webView->page(), "document.getElementById('input1').focus()"); + QTRY_COMPARE(evaluateJavaScriptSync(webView->page(), "document.activeElement.id").toString(), QStringLiteral("input1")); + + QVERIFY(iface->focusChild()); + QTRY_COMPARE(iface->focusChild()->role(), QAccessible::EditableText); + // <html> -> <body> -> <input> + QCOMPARE(traverseToWebDocumentAccessibleInterface(iface)->child(0)->child(0), iface->focusChild()); +} + void tst_Accessibility::text() { QWebEngineView webView; diff --git a/tests/auto/widgets/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST index d9d6a03f1..086b39fb1 100644 --- a/tests/auto/widgets/qwebenginepage/BLACKLIST +++ b/tests/auto/widgets/qwebenginepage/BLACKLIST @@ -3,6 +3,7 @@ osx [mouseMovementProperties] windows +macos # Can't move cursor (QTBUG-76312) # QTBUG-81614 [setHtmlWithBaseURL] |