From c0db708f0876ede1f6feb0f3d87d05c2f32b729f Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 25 Feb 2020 14:43:36 +0100 Subject: Suppress error message on ACCESSIBILITY_EVENTS permission type The ACCESSIBILITY_EVENTS permission is used to enable AOM (Accessibility Object Model) event listeners in blink. The current implementation of the AOM is deprecated and it doesn't seem to be supported in the foreseeable future by QtWebEngine. Avoid the "Not implemented" error message in case of this permission type because it is kept unsupported on purpose but blink still registers permission status listener when AXObjectCache is created. Change-Id: I4e9babb06015635e6c4c94c8fe433c714329692b Reviewed-by: Kirill Burtsev --- src/core/permission_manager_qt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 9e8687a47..decc6dd7c 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -67,6 +67,8 @@ ProfileAdapter::PermissionType toQt(content::PermissionType type) return ProfileAdapter::ClipboardWrite; case content::PermissionType::NOTIFICATIONS: return ProfileAdapter::NotificationPermission; + case content::PermissionType::ACCESSIBILITY_EVENTS: + return ProfileAdapter::UnsupportedPermission; case content::PermissionType::FLASH: case content::PermissionType::MIDI_SYSEX: case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER: @@ -74,7 +76,6 @@ ProfileAdapter::PermissionType toQt(content::PermissionType type) case content::PermissionType::DURABLE_STORAGE: case content::PermissionType::BACKGROUND_SYNC: case content::PermissionType::SENSORS: - case content::PermissionType::ACCESSIBILITY_EVENTS: case content::PermissionType::PAYMENT_HANDLER: case content::PermissionType::BACKGROUND_FETCH: case content::PermissionType::IDLE_DETECTION: -- cgit v1.2.3 From a44d7aeef75c73ede4fb21df91f8e7d173d95c68 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 20 Feb 2020 10:57:37 +0100 Subject: Invalidate accessible interfaces on destruction of view or page The RenderWidgetHostViewQtDelegate(Widget|Quick)Accessible interfaces are forwarding their queries to the WebEngineView. In case of widget, the view also forwards the query to the page. The accessible interfaces may outlive the view and page. The interfaces are not supposed to be used after the destruction of the underlying objects. Thus, set the RenderWidgetHostViewQtDelegate and WebEngineView accessible interfaces invalid if the corresponding pointers are null. Also fix querying the root accessible interface of the web page when the render frame host is not available. This fixes crash when QT_LOGGING_RULES="qt.accessibility.cache.debug=true" is set and logger tries to pretty-print QAccessibleInterfaces during destruction. Task-number: QTBUG-78284 Change-Id: If18af0605061fcd82d019d0042dbf1c9d3a910be Reviewed-by: Kirill Burtsev --- src/core/web_contents_adapter.cpp | 5 ++++- src/webengine/api/qquickwebengineview.cpp | 15 ++++++++++++-- src/webengine/api/qquickwebengineview_p_p.h | 1 + .../render_widget_host_view_qt_delegate_quick.cpp | 24 ++++++++++++++++------ .../render_widget_host_view_qt_delegate_quick.h | 3 +++ src/webenginewidgets/api/qwebengineview.cpp | 13 +++++++++++- src/webenginewidgets/api/qwebengineview.h | 4 ++++ src/webenginewidgets/api/qwebengineview_p.h | 1 + .../render_widget_host_view_qt_delegate_widget.cpp | 22 ++++++++++++++++---- .../render_widget_host_view_qt_delegate_widget.h | 4 ++++ 10 files changed, 78 insertions(+), 14 deletions(-) diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index a7579f916..31731fe99 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1011,7 +1011,10 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible() CHECK_INITIALIZED(nullptr); content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); - content::BrowserAccessibilityManager *manager = static_cast(rvh->GetMainFrame())->GetOrCreateBrowserAccessibilityManager(); + content::RenderFrameHostImpl *rfh = static_cast(rvh->GetMainFrame()); + if (!rfh) + return nullptr; + content::BrowserAccessibilityManager *manager = rfh->GetOrCreateBrowserAccessibilityManager(); if (!manager) // FIXME! return nullptr; content::BrowserAccessibility *acc = manager->GetRoot(); diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 3ce202695..dead005b0 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -744,6 +744,17 @@ QQuickWebEngineViewAccessible::QQuickWebEngineViewAccessible(QQuickWebEngineView : QAccessibleObject(o) {} +bool QQuickWebEngineViewAccessible::isValid() const +{ + if (!QAccessibleObject::isValid()) + return false; + + if (!engineView() || !engineView()->d_func()) + return false; + + return true; +} + QAccessibleInterface *QQuickWebEngineViewAccessible::parent() const { QQuickItem *parent = engineView()->parentItem(); @@ -767,9 +778,9 @@ int QQuickWebEngineViewAccessible::childCount() const QAccessibleInterface *QQuickWebEngineViewAccessible::child(int index) const { - if (index == 0 && engineView()) + if (index == 0 && isValid()) return engineView()->d_func()->adapter->browserAccessible(); - return 0; + return nullptr; } int QQuickWebEngineViewAccessible::indexOfChild(const QAccessibleInterface *c) const diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 6408767b3..3969ee244 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -234,6 +234,7 @@ class QQuickWebEngineViewAccessible : public QAccessibleObject { public: QQuickWebEngineViewAccessible(QQuickWebEngineView *o); + bool isValid() const override; QAccessibleInterface *parent() const override; QAccessibleInterface *focusChild() const override; int childCount() const override; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index ede85ca69..e2ce08ebf 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -380,9 +380,17 @@ RenderWidgetHostViewQtDelegateQuickAccessible::RenderWidgetHostViewQtDelegateQui { } +bool RenderWidgetHostViewQtDelegateQuickAccessible::isValid() const +{ + if (!viewAccessible() || !viewAccessible()->isValid()) + return false; + + return QAccessibleObject::isValid(); +} + QAccessibleInterface *RenderWidgetHostViewQtDelegateQuickAccessible::parent() const { - return QAccessible::queryAccessibleInterface(m_view)->parent(); + return viewAccessible()->parent(); } QString RenderWidgetHostViewQtDelegateQuickAccessible::text(QAccessible::Text) const @@ -397,29 +405,33 @@ QAccessible::Role RenderWidgetHostViewQtDelegateQuickAccessible::role() const QAccessible::State RenderWidgetHostViewQtDelegateQuickAccessible::state() const { - return QAccessible::queryAccessibleInterface(m_view)->state(); + return viewAccessible()->state(); } QAccessibleInterface *RenderWidgetHostViewQtDelegateQuickAccessible::focusChild() const { - return QAccessible::queryAccessibleInterface(m_view)->focusChild(); + return viewAccessible()->focusChild(); } int RenderWidgetHostViewQtDelegateQuickAccessible::childCount() const { - return QAccessible::queryAccessibleInterface(m_view)->childCount(); + return viewAccessible()->childCount(); } QAccessibleInterface *RenderWidgetHostViewQtDelegateQuickAccessible::child(int index) const { - return QAccessible::queryAccessibleInterface(m_view)->child(index); + return viewAccessible()->child(index); } int RenderWidgetHostViewQtDelegateQuickAccessible::indexOfChild(const QAccessibleInterface *c) const { - return QAccessible::queryAccessibleInterface(m_view)->indexOfChild(c); + return viewAccessible()->indexOfChild(c); } +QQuickWebEngineViewAccessible *RenderWidgetHostViewQtDelegateQuickAccessible::viewAccessible() const +{ + return static_cast(QAccessible::queryAccessibleInterface(m_view)); +} #endif // QT_CONFIG(accessibility) } // namespace QtWebEngineCore diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h index 6874aac2b..f70de50d7 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE class QQuickWebEngineView; +class QQuickWebEngineViewAccessible; class QQuickWebEngineViewPrivate; QT_END_NAMESPACE @@ -122,6 +123,7 @@ class RenderWidgetHostViewQtDelegateQuickAccessible : public QAccessibleObject public: RenderWidgetHostViewQtDelegateQuickAccessible(RenderWidgetHostViewQtDelegateQuick *o, QQuickWebEngineView *view); + bool isValid() const override; QAccessibleInterface *parent() const override; QString text(QAccessible::Text t) const override; QAccessible::Role role() const override; @@ -133,6 +135,7 @@ public: int indexOfChild(const QAccessibleInterface *) const override; private: + QQuickWebEngineViewAccessible *viewAccessible() const; QQuickWebEngineView *m_view; }; #endif // QT_CONFIG(accessibility) diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index a51f9b7a5..b06d99478 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -471,6 +471,17 @@ void QWebEngineView::dropEvent(QDropEvent *e) #endif // QT_CONFIG(draganddrop) #ifndef QT_NO_ACCESSIBILITY +bool QWebEngineViewAccessible::isValid() const +{ + if (!QAccessibleWidget::isValid()) + return false; + + if (!view() || !view()->d_func() || !view()->d_func()->page || !view()->d_func()->page->d_func()) + return false; + + return true; +} + QAccessibleInterface *QWebEngineViewAccessible::focusChild() const { if (child(0) && child(0)->focusChild()) @@ -485,7 +496,7 @@ int QWebEngineViewAccessible::childCount() const QAccessibleInterface *QWebEngineViewAccessible::child(int index) const { - if (index == 0 && view() && view()->page()) + if (index == 0 && isValid()) return view()->page()->d_func()->adapter->browserAccessible(); return nullptr; } diff --git a/src/webenginewidgets/api/qwebengineview.h b/src/webenginewidgets/api/qwebengineview.h index 63a68f46c..04c8ece74 100644 --- a/src/webenginewidgets/api/qwebengineview.h +++ b/src/webenginewidgets/api/qwebengineview.h @@ -53,6 +53,7 @@ class QContextMenuEvent; class QUrl; class QWebEnginePage; class QWebEngineSettings; +class QWebEngineViewAccessible; class QWebEngineViewPrivate; class QWEBENGINEWIDGETS_EXPORT QWebEngineView : public QWidget { @@ -141,6 +142,9 @@ private: friend class QWebEnginePage; friend class QWebEnginePagePrivate; +#if QT_CONFIG(accessibility) + friend class QWebEngineViewAccessible; +#endif }; QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h index dd0a5bedf..a3c619cea 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) {} + bool isValid() const override; QAccessibleInterface *focusChild() const override; int childCount() const override; QAccessibleInterface *child(int index) 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 8ba312822..fdd6d1c4f 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -41,6 +41,7 @@ #include "qwebenginepage_p.h" #include "qwebengineview.h" +#include "qwebengineview_p.h" #include #include #include @@ -490,24 +491,37 @@ RenderWidgetHostViewQtDelegateWidgetAccessible::RenderWidgetHostViewQtDelegateWi { } +bool RenderWidgetHostViewQtDelegateWidgetAccessible::isValid() const +{ + if (!viewAccessible() || !viewAccessible()->isValid()) + return false; + + return QAccessibleWidget::isValid(); +} + QAccessibleInterface *RenderWidgetHostViewQtDelegateWidgetAccessible::focusChild() const { - return QAccessible::queryAccessibleInterface(m_view)->focusChild(); + return viewAccessible()->focusChild(); } int RenderWidgetHostViewQtDelegateWidgetAccessible::childCount() const { - return QAccessible::queryAccessibleInterface(m_view)->childCount(); + return viewAccessible()->childCount(); } QAccessibleInterface *RenderWidgetHostViewQtDelegateWidgetAccessible::child(int index) const { - return QAccessible::queryAccessibleInterface(m_view)->child(index); + return viewAccessible()->child(index); } int RenderWidgetHostViewQtDelegateWidgetAccessible::indexOfChild(const QAccessibleInterface *c) const { - return QAccessible::queryAccessibleInterface(m_view)->indexOfChild(c); + return viewAccessible()->indexOfChild(c); +} + +QWebEngineViewAccessible *RenderWidgetHostViewQtDelegateWidgetAccessible::viewAccessible() const +{ + return static_cast(QAccessible::queryAccessibleInterface(m_view)); } #endif // QT_CONFIG(accessibility) 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 df1806b6f..c7783117a 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE class QWebEnginePage; class QWebEngineView; +class QWebEngineViewAccessible; class QWebEnginePagePrivate; QT_END_NAMESPACE @@ -123,11 +124,14 @@ class RenderWidgetHostViewQtDelegateWidgetAccessible : public QAccessibleWidget public: RenderWidgetHostViewQtDelegateWidgetAccessible(RenderWidgetHostViewQtDelegateWidget *o, QWebEngineView *view); + bool isValid() const override; QAccessibleInterface *focusChild() const override; int childCount() const override; QAccessibleInterface *child(int index) const override; int indexOfChild(const QAccessibleInterface *child) const override; + private: + QWebEngineViewAccessible *viewAccessible() const; QWebEngineView *m_view; }; #endif // QT_CONFIG(accessibility) -- cgit v1.2.3 From 616781369e8787a02e5629b73a0c8cfffe3c5239 Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Thu, 27 Feb 2020 17:00:13 +0100 Subject: Stabilize tst_QWebEnginePage::localStorageVisibility() Toggling page's setting is actually first batched and then executed asynchronously by timer. So javascript code might not necessarily see this update immediately after change on UI thread. Change-Id: I1a1f373b5fd0b96c5b937a2dca1ce0ed99364c33 Reviewed-by: Allan Sandfeld Jensen --- tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 94b3f16c1..d0453e1e6 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -823,11 +823,13 @@ void tst_QWebEnginePage::localStorageVisibility() QVERIFY(evaluateJavaScriptSync(&webPage1, QString("(window.localStorage != undefined)")).toBool()); QVERIFY(!evaluateJavaScriptSync(&webPage2, QString("(window.localStorage != undefined)")).toBool()); - // Switching the feature off does not actively remove the object from webPage1. + // Toggle local setting for every page and... webPage1.settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, false); webPage2.settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true); + // ...first check second page (for storage to appear) as applying settings is batched and done asynchronously + QTRY_VERIFY(evaluateJavaScriptSync(&webPage2, QString("(window.localStorage != undefined)")).toBool()); + // Switching the feature off does not actively remove the object from webPage1. QVERIFY(evaluateJavaScriptSync(&webPage1, QString("(window.localStorage != undefined)")).toBool()); - QVERIFY(evaluateJavaScriptSync(&webPage2, QString("(window.localStorage != undefined)")).toBool()); // The object disappears only after reloading. webPage1.triggerAction(QWebEnginePage::Reload); -- cgit v1.2.3 From 19444168395424fef4daff76ce64b9813aef0610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Wed, 26 Feb 2020 14:27:57 +0100 Subject: Stabilize tst_QQuickWebEngineView::transparentWebEngineViews Change-Id: I847a1750ce5c9533db43fb60f91b9739c544791a Reviewed-by: Allan Sandfeld Jensen --- tests/auto/quick/qquickwebengineview/BLACKLIST | 2 -- .../tst_qquickwebengineview.cpp | 31 ++++++++++------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/tests/auto/quick/qquickwebengineview/BLACKLIST b/tests/auto/quick/qquickwebengineview/BLACKLIST index d4d5c9844..e69de29bb 100644 --- a/tests/auto/quick/qquickwebengineview/BLACKLIST +++ b/tests/auto/quick/qquickwebengineview/BLACKLIST @@ -1,2 +0,0 @@ -[transparentWebEngineViews] -windows diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 6f9cb9c69..04be25abe 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -421,32 +421,29 @@ void tst_QQuickWebEngineView::transparentWebEngineViews() webEngineView1->setSize(QSizeF(300, 400)); webEngineView1->loadHtml(""); - QVERIFY(waitForLoadSucceeded(webEngineView1.data())); - webEngineView1->setVisible(true); + QVERIFY(waitForLoadSucceeded(webEngineView1.data(), 30000)); webEngineView2->setSize(QSizeF(300, 400)); webEngineView2->setUrl(urlFromTestPath("/html/basic_page.html")); QVERIFY(waitForLoadSucceeded(webEngineView2.data())); // Result image: black text on red background. - const QImage grabbedWindow = tryToGrabWindowUntil(m_window.data(), [] (const QImage &image) { - return image.pixelColor(0, 0) == QColor(Qt::red); + QSet colors; + tryToGrabWindowUntil(m_window.data(), [&colors] (const QImage &image) { + colors.clear(); + for (int i = 0; i < image.width(); i++) + for (int j = 0; j < image.height(); j++) + colors.insert(image.pixel(i, j)); + return colors.count() > 1; }); - QSet redComponents; - for (int i = 0, width = grabbedWindow.width(); i < width; i++) { - for (int j = 0, height = grabbedWindow.height(); j < height; j++) { - QColor color(grabbedWindow.pixel(i, j)); - redComponents.insert(color.red()); - // There are no green or blue components between red and black. - QVERIFY(color.green() == 0); - QVERIFY(color.blue() == 0); - } + QVERIFY(colors.count() > 1); + QVERIFY(colors.contains(qRgb(0, 0, 0))); // black + QVERIFY(colors.contains(qRgb(255, 0, 0))); // red + for (auto color : colors) { + QCOMPARE(qGreen(color), 0); + QCOMPARE(qBlue(color), 0); } - - QVERIFY(redComponents.count() > 1); - QVERIFY(redComponents.contains(0)); // black - QVERIFY(redComponents.contains(255)); // red } void tst_QQuickWebEngineView::inputMethod() -- cgit v1.2.3 From 171bdc9f0e9a563b0d70643637d0b6a8e5661d17 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 20 Jan 2020 11:02:03 +0100 Subject: Update accessibility focus on FocusIn events for Quick Without this, an already focused web element might not be read when QQuickWebEngineView gets the active focus. QWidget::setFocus() does this for Widget. Fixes: QTBUG-81539 Change-Id: Iaa418c416871e580583ea05e50b223dea3501fd8 Reviewed-by: Allan Sandfeld Jensen --- src/webengine/render_widget_host_view_qt_delegate_quick.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index e2ce08ebf..d5aae271f 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -226,6 +226,13 @@ bool RenderWidgetHostViewQtDelegateQuick::event(QEvent *event) void RenderWidgetHostViewQtDelegateQuick::focusInEvent(QFocusEvent *event) { +#if QT_CONFIG(accessibility) + if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(this)->focusChild()) { + QAccessibleEvent focusEvent(iface, QAccessible::Focus); + QAccessible::updateAccessibility(&focusEvent); + } +#endif // QT_CONFIG(accessibility) + m_client->forwardEvent(event); } -- cgit v1.2.3