From 1f77d4709946511b919810354f19875824399096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Mon, 18 Feb 2019 16:10:17 +0100 Subject: Fix crash on dynamic_cast in global event filter Installing an event filter on QApplication which uses dynamic_cast will crash the application since QtWebEngine is sending QTimerEvents to classes without RTTI information. Fix by 1. Moving the QObject part of MessagePumpForUIQt into api/ as a private class. 2. Using QTimer directly in WebEngineSettings, without subclassing. Fixes: QTBUG-73833 Change-Id: Ida73006a4fef76637c964f8f05468adcc4a190ce Reviewed-by: Allan Sandfeld Jensen --- src/core/api/core_api.pro | 2 + src/core/api/qwebenginemessagepumpscheduler.cpp | 72 ++++++++++++++++++++++ src/core/api/qwebenginemessagepumpscheduler_p.h | 80 +++++++++++++++++++++++++ src/core/browser_main_parts_qt.cpp | 48 ++++----------- src/core/web_engine_settings.cpp | 34 +++-------- src/core/web_engine_settings.h | 5 +- 6 files changed, 175 insertions(+), 66 deletions(-) create mode 100644 src/core/api/qwebenginemessagepumpscheduler.cpp create mode 100644 src/core/api/qwebenginemessagepumpscheduler_p.h (limited to 'src') diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 38dc6b39d..4b69b348a 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -37,6 +37,7 @@ HEADERS = \ qwebenginecookiestore.h \ qwebenginecookiestore_p.h \ qwebenginehttprequest.h \ + qwebenginemessagepumpscheduler_p.h \ qwebenginequotarequest.h \ qwebengineregisterprotocolhandlerrequest.h \ qwebengineurlrequestinterceptor.h \ @@ -50,6 +51,7 @@ SOURCES = \ qtwebenginecoreglobal.cpp \ qwebenginecookiestore.cpp \ qwebenginehttprequest.cpp \ + qwebenginemessagepumpscheduler.cpp \ qwebenginequotarequest.cpp \ qwebengineregisterprotocolhandlerrequest.cpp \ qwebengineurlrequestinfo.cpp \ diff --git a/src/core/api/qwebenginemessagepumpscheduler.cpp b/src/core/api/qwebenginemessagepumpscheduler.cpp new file mode 100644 index 000000000..34cbc49bf --- /dev/null +++ b/src/core/api/qwebenginemessagepumpscheduler.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebenginemessagepumpscheduler_p.h" + +#include +#include +#include + +QWebEngineMessagePumpScheduler::QWebEngineMessagePumpScheduler(std::function callback) + : m_callback(std::move(callback)) +{} + +void QWebEngineMessagePumpScheduler::scheduleWork() +{ + QCoreApplication::postEvent(this, new QTimerEvent(0)); +} + +void QWebEngineMessagePumpScheduler::scheduleDelayedWork(int delay) +{ + if (delay < 0) { + killTimer(m_timerId); + m_timerId = 0; + } else if (!m_timerId || delay < QAbstractEventDispatcher::instance()->remainingTime(m_timerId)) { + killTimer(m_timerId); + m_timerId = startTimer(delay); + } +} + +void QWebEngineMessagePumpScheduler::timerEvent(QTimerEvent *ev) +{ + Q_ASSERT(!ev->timerId() || m_timerId == ev->timerId()); + killTimer(m_timerId); + m_timerId = 0; + m_callback(); +} diff --git a/src/core/api/qwebenginemessagepumpscheduler_p.h b/src/core/api/qwebenginemessagepumpscheduler_p.h new file mode 100644 index 000000000..4c9e4d600 --- /dev/null +++ b/src/core/api/qwebenginemessagepumpscheduler_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEMESSAGEPUMPSCHEDULER_P_H +#define QWEBENGINEMESSAGEPUMPSCHEDULER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtwebenginecoreglobal_p.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QWEBENGINECORE_PRIVATE_EXPORT QWebEngineMessagePumpScheduler : public QObject +{ + Q_OBJECT +public: + QWebEngineMessagePumpScheduler(std::function callback); + void scheduleWork(); + void scheduleDelayedWork(int delay); + +protected: + void timerEvent(QTimerEvent *ev) override; + +private: + int m_timerId = 0; + std::function m_callback; +}; + +QT_END_NAMESPACE + +#endif // !QWEBENGINEMESSAGEPUMPSCHEDULER_P_H diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp index 8f39386d4..3d85c04c4 100644 --- a/src/core/browser_main_parts_qt.cpp +++ b/src/core/browser_main_parts_qt.cpp @@ -39,6 +39,8 @@ #include "browser_main_parts_qt.h" +#include "api/qwebenginemessagepumpscheduler_p.h" + #include "base/message_loop/message_loop.h" #include "base/process/process.h" #include "base/threading/thread_restrictions.h" @@ -54,11 +56,7 @@ #include "service/service_qt.h" #include "web_engine_context.h" -#include -#include #include -#include -#include #if defined(OS_MACOSX) #include "ui/base/idle/idle.h" @@ -91,16 +89,12 @@ int GetTimeIntervalMilliseconds(const base::TimeTicks &from) return delay < 0 ? 0 : delay; } -class MessagePumpForUIQt : public QObject, - public base::MessagePump +class MessagePumpForUIQt : public base::MessagePump { public: MessagePumpForUIQt() - : m_delegate(nullptr) - , m_explicitLoop(nullptr) - , m_timerId(0) - { - } + : m_scheduler([this]() { handleScheduledWork(); }) + {} void Run(Delegate *delegate) override { @@ -123,36 +117,17 @@ public: void ScheduleWork() override { + // NOTE: This method may called from any thread at any time. if (!m_delegate) m_delegate = base::MessageLoopForUI::current(); - QCoreApplication::postEvent(this, new QTimerEvent(0)); - m_timerScheduledTime = base::TimeTicks::Now(); + m_scheduler.scheduleWork(); } void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) override { if (!m_delegate) m_delegate = base::MessageLoopForUI::current(); - if (delayed_work_time.is_null()) { - killTimer(m_timerId); - m_timerId = 0; - m_timerScheduledTime = base::TimeTicks(); - } else if (!m_timerId || delayed_work_time < m_timerScheduledTime) { - killTimer(m_timerId); - m_timerId = startTimer(GetTimeIntervalMilliseconds(delayed_work_time)); - m_timerScheduledTime = delayed_work_time; - } - } - -protected: - void timerEvent(QTimerEvent *ev) override - { - Q_ASSERT(!ev->timerId() || m_timerId == ev->timerId()); - killTimer(m_timerId); - m_timerId = 0; - m_timerScheduledTime = base::TimeTicks(); - - handleScheduledWork(); + m_scheduler.scheduleDelayedWork(GetTimeIntervalMilliseconds(delayed_work_time)); } private: @@ -173,10 +148,9 @@ private: ScheduleDelayedWork(delayed_work_time); } - Delegate *m_delegate; - QEventLoop *m_explicitLoop; - int m_timerId; - base::TimeTicks m_timerScheduledTime; + Delegate *m_delegate = nullptr; + QEventLoop *m_explicitLoop = nullptr; + QWebEngineMessagePumpScheduler m_scheduler; }; } // anonymous namespace diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 2e48a806a..664951e66 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -67,27 +67,6 @@ QHash WebEngineSettings::s_defaultFontSizes; static const int batchTimerTimeout = 0; -class BatchTimer : public QTimer { - Q_OBJECT -public: - BatchTimer(WebEngineSettings *settings) - : m_settings(settings) - { - setSingleShot(true); - setInterval(batchTimerTimeout); - connect(this, SIGNAL(timeout()), SLOT(onTimeout())); - } - -private Q_SLOTS: - void onTimeout() - { - m_settings->doApply(); - } - -private: - WebEngineSettings *m_settings; -}; - static inline bool isTouchEventsAPIEnabled() { static bool initialized = false; static bool touchEventsAPIEnabled = false; @@ -113,12 +92,17 @@ static inline bool isTouchEventsAPIEnabled() { WebEngineSettings::WebEngineSettings(WebEngineSettings *_parentSettings) : m_adapter(0) - , m_batchTimer(new BatchTimer(this)) , parentSettings(_parentSettings) , m_unknownUrlSchemePolicy(WebEngineSettings::InheritedUnknownUrlSchemePolicy) { if (parentSettings) parentSettings->childSettings.insert(this); + + m_batchTimer.setSingleShot(true); + m_batchTimer.setInterval(batchTimerTimeout); + QObject::connect(&m_batchTimer, &QTimer::timeout, [this]() { + doApply(); + }); } WebEngineSettings::~WebEngineSettings() @@ -335,8 +319,8 @@ void WebEngineSettings::initDefaults() void WebEngineSettings::scheduleApply() { - if (!m_batchTimer->isActive()) - m_batchTimer->start(); + if (!m_batchTimer.isActive()) + m_batchTimer.start(); } void WebEngineSettings::doApply() @@ -448,5 +432,3 @@ void WebEngineSettings::setParentSettings(WebEngineSettings *_parentSettings) } } // namespace QtWebEngineCore - -#include "web_engine_settings.moc" diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 06a7a6004..8930d7c27 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -57,6 +57,7 @@ #include #include #include +#include namespace content { struct RendererPreferences; @@ -65,7 +66,6 @@ struct WebPreferences; } namespace QtWebEngineCore { -class BatchTimer; class WebContentsAdapter; class QWEBENGINECORE_PRIVATE_EXPORT WebEngineSettings { @@ -177,7 +177,7 @@ private: QHash m_fontSizes; QString m_defaultEncoding; QScopedPointer webPreferences; - QScopedPointer m_batchTimer; + QTimer m_batchTimer; WebEngineSettings *parentSettings; QSet childSettings; @@ -187,7 +187,6 @@ private: static QHash s_defaultFontSizes; UnknownUrlSchemePolicy m_unknownUrlSchemePolicy; - friend class BatchTimer; friend class WebContentsAdapter; }; -- cgit v1.2.3