summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-04 11:43:54 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-04 11:45:58 +0100
commit2b3f5b66af4f06a57216575a44f54c1d20fb12a0 (patch)
treeb58f6a31b9d97b4693d485ea1a794fa6b8c5d875
parent4dc312011bcaa2ee2cf812b5b84dc9238130e608 (diff)
parent56fadb571f32b721d8b99554e6e38692009ec37f (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
-rw-r--r--dist/changes-5.12.273
-rw-r--r--examples/webengine/quicknanobrowser/BrowserWindow.qml15
-rw-r--r--src/core/api/core_api.pro2
-rw-r--r--src/core/api/qwebenginecookiestore.cpp2
-rw-r--r--src/core/api/qwebenginemessagepumpscheduler.cpp72
-rw-r--r--src/core/api/qwebenginemessagepumpscheduler_p.h80
-rw-r--r--src/core/api/qwebengineurlschemehandler.cpp2
-rw-r--r--src/core/browser_accessibility_manager_qt.cpp6
-rw-r--r--src/core/browser_accessibility_manager_qt.h3
-rw-r--r--src/core/browser_accessibility_qt.cpp3
-rw-r--r--src/core/browser_main_parts_qt.cpp48
-rw-r--r--src/core/favicon_manager.cpp20
-rw-r--r--src/core/favicon_manager.h15
-rw-r--r--src/core/profile_adapter.cpp17
-rw-r--r--src/core/profile_adapter.h5
-rw-r--r--src/core/profile_adapter_client.h2
-rw-r--r--src/core/type_conversion.cpp2
-rw-r--r--src/core/web_contents_adapter_client.h1
-rw-r--r--src/core/web_engine_settings.cpp34
-rw-r--r--src/core/web_engine_settings.h5
-rw-r--r--src/webengine/api/qquickwebenginedialogrequests.cpp6
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem.cpp26
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem_p_p.h1
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp45
-rw-r--r--src/webengine/api/qquickwebengineprofile_p.h9
-rw-r--r--src/webengine/api/qquickwebengineview.cpp4
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h2
-rw-r--r--src/webengine/doc/src/qtwebengine-examples.qdoc2
-rw-r--r--src/webengine/doc/src/qtwebengine-overview.qdoc16
-rw-r--r--src/webengine/doc/src/qtwebengine-qmlmodule.qdoc2
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem.cpp23
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem_p.h4
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp34
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h1
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp40
-rw-r--r--src/webenginewidgets/api/qwebengineprofile_p.h5
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp2
-rw-r--r--src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc2
-rw-r--r--src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc20
-rw-r--r--src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc14
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp46
-rw-r--r--tests/auto/quick/qmltests/data/tst_favicon.qml33
-rw-r--r--tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp38
-rw-r--r--tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp32
44 files changed, 633 insertions, 181 deletions
diff --git a/dist/changes-5.12.2 b/dist/changes-5.12.2
new file mode 100644
index 000000000..ad427ecce
--- /dev/null
+++ b/dist/changes-5.12.2
@@ -0,0 +1,73 @@
+Qt 5.12.2 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.1.
+
+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.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+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.12.2 Changes *
+****************************************************************************
+
+Behavior Changes
+----------------
+
+ - Deleting a download item will now also cancel the download if it is
+ still in progress.
+
+
+Chromium
+--------
+
+ - Security fixes from Chromium up to version 72.0.3626.96, including:
+ * CVE-2019-5754
+ * CVE-2019-5755
+ * CVE-2019-5756
+ * CVE-2019-5757
+ * CVE-2019-5758
+ * CVE-2019-5759
+ * CVE-2019-5760
+ * CVE-2019-5762
+ * CVE-2019-5763
+ * CVE-2019-5764
+ * CVE-2019-5769
+ * CVE-2019-5770
+ * CVE-2019-5775
+ * CVE-2019-5776
+ * CVE-2019-5777
+ * CVE-2019-5779
+ * CVE-2019-5781
+ * CVE-2019-5782
+ * CVE-2019-5783
+ * CVE-2019-5784
+ * Security issue 895117
+ * Security issue 895970
+ * Security issue 899689
+ * Security issue 901677
+ * Security issue 903500
+ * Security issue 907047
+ * Security issue 908358
+ * Security issue 911253
+ * Security issue 912508
+ * Security issue 912520
+ * Security issue 922677
+
+General
+-------
+
+ - [QTBUG-72021] Improved tooltip wrapping to match other browsers.
+ - [QTBUG-72714] Fixed clipboard API not being permitted when settings allowed it.
+ - [QTBUG-73839] Fixed minor memory leak per download.
+ - Fixed regression in certificate transparency checking.
diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index 94e7ac37a..d3d597e2b 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -387,11 +387,12 @@ ApplicationWindow {
focus: true
onLinkHovered: function(hoveredUrl) {
- if (hoveredUrl === "")
- resetStatusText.start();
+ if (hoveredUrl == "")
+ hideStatusText.start();
else {
- resetStatusText.stop();
statusText.text = hoveredUrl;
+ statusBubble.visible = true;
+ hideStatusText.stop();
}
}
@@ -578,6 +579,7 @@ ApplicationWindow {
id: statusBubble
color: "oldlace"
property int padding: 8
+ visible: false
anchors.left: parent.left
anchors.bottom: parent.bottom
@@ -590,9 +592,12 @@ ApplicationWindow {
elide: Qt.ElideMiddle
Timer {
- id: resetStatusText
+ id: hideStatusText
interval: 750
- onTriggered: statusText.text = ""
+ onTriggered: {
+ statusText.text = "";
+ statusBubble.visible = false;
+ }
}
}
}
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 4d3ddcc8e..326d4481f 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -38,6 +38,7 @@ HEADERS = \
qwebenginecookiestore.h \
qwebenginecookiestore_p.h \
qwebenginehttprequest.h \
+ qwebenginemessagepumpscheduler_p.h \
qwebenginenotification.h \
qwebenginequotarequest.h \
qwebengineregisterprotocolhandlerrequest.h \
@@ -53,6 +54,7 @@ SOURCES = \
qwebengineclientcertificatestore.cpp \
qwebenginecookiestore.cpp \
qwebenginehttprequest.cpp \
+ qwebenginemessagepumpscheduler.cpp \
qwebenginenotification.cpp \
qwebenginequotarequest.cpp \
qwebengineregisterprotocolhandlerrequest.cpp \
diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp
index 035c98342..3897fb128 100644
--- a/src/core/api/qwebenginecookiestore.cpp
+++ b/src/core/api/qwebenginecookiestore.cpp
@@ -382,7 +382,7 @@ void QWebEngineCookieStore::setCookieFilter(std::function<bool(const FilterReque
\inmodule QtWebEngineCore
\since 5.11
- \brief This struct is used in conjunction with QWebEngineCookieStore::setCookieFilter() and is
+ \brief The QWebEngineCookieStore::FilterRequest struct is used in conjunction with QWebEngineCookieStore::setCookieFilter() and is
the type \a filterCallback operates on.
\sa QWebEngineCookieStore::setCookieFilter()
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 <QAbstractEventDispatcher>
+#include <QCoreApplication>
+#include <QTimerEvent>
+
+QWebEngineMessagePumpScheduler::QWebEngineMessagePumpScheduler(std::function<void()> 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 <QtCore/qobject.h>
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+class QWEBENGINECORE_PRIVATE_EXPORT QWebEngineMessagePumpScheduler : public QObject
+{
+ Q_OBJECT
+public:
+ QWebEngineMessagePumpScheduler(std::function<void()> callback);
+ void scheduleWork();
+ void scheduleDelayedWork(int delay);
+
+protected:
+ void timerEvent(QTimerEvent *ev) override;
+
+private:
+ int m_timerId = 0;
+ std::function<void()> m_callback;
+};
+
+QT_END_NAMESPACE
+
+#endif // !QWEBENGINEMESSAGEPUMPSCHEDULER_P_H
diff --git a/src/core/api/qwebengineurlschemehandler.cpp b/src/core/api/qwebengineurlschemehandler.cpp
index 2e93f4b73..aecee5044 100644
--- a/src/core/api/qwebengineurlschemehandler.cpp
+++ b/src/core/api/qwebengineurlschemehandler.cpp
@@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QWebEngineUrlSchemeHandler
- \brief The QWebEngineUrlSchemeHandler is a base class for handling custom URL schemes.
+ \brief The QWebEngineUrlSchemeHandler class is a base class for handling custom URL schemes.
\since 5.6
To implement a custom URL scheme for QtWebEngine, you first have to create an instance of
diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp
index 644a0a9f0..7fb1386c5 100644
--- a/src/core/browser_accessibility_manager_qt.cpp
+++ b/src/core/browser_accessibility_manager_qt.cpp
@@ -76,6 +76,12 @@ BrowserAccessibilityManagerQt::BrowserAccessibilityManagerQt(
, m_parentObject(parentObject)
{
Initialize(initialTree);
+ m_valid = true; // BrowserAccessibilityQt can start using the AXTree
+}
+
+BrowserAccessibilityManagerQt::~BrowserAccessibilityManagerQt()
+{
+ m_valid = false; // BrowserAccessibilityQt should stop using the AXTree
}
QAccessibleInterface *BrowserAccessibilityManagerQt::rootParentAccessible()
diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h
index a2d6db458..87c8875ba 100644
--- a/src/core/browser_accessibility_manager_qt.h
+++ b/src/core/browser_accessibility_manager_qt.h
@@ -57,14 +57,17 @@ public:
const ui::AXTreeUpdate& initialTree,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
+ ~BrowserAccessibilityManagerQt() override;
void FireBlinkEvent(ax::mojom::Event event_type,
BrowserAccessibility* node) override;
QAccessibleInterface *rootParentAccessible();
+ bool isValid() const { return m_valid; }
private:
Q_DISABLE_COPY(BrowserAccessibilityManagerQt)
QObject *m_parentObject;
+ bool m_valid = false;
};
}
diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp
index c906071f2..75527ea95 100644
--- a/src/core/browser_accessibility_qt.cpp
+++ b/src/core/browser_accessibility_qt.cpp
@@ -73,7 +73,8 @@ BrowserAccessibilityQt::BrowserAccessibilityQt()
bool BrowserAccessibilityQt::isValid() const
{
- return true;
+ auto managerQt = static_cast<BrowserAccessibilityManagerQt *>(manager_);
+ return managerQt && managerQt->isValid();
}
QObject *BrowserAccessibilityQt::object() const
diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp
index e6c76fb4f..4dbff086b 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"
@@ -63,11 +65,7 @@
#include "service/service_qt.h"
#include "web_engine_context.h"
-#include <QCoreApplication>
-#include <QEvent>
#include <QEventLoop>
-#include <QObject>
-#include <QTimerEvent>
#include <QtGui/qtgui-config.h>
#if QT_CONFIG(opengl)
@@ -106,16 +104,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
{
@@ -138,36 +132,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:
@@ -235,10 +210,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/favicon_manager.cpp b/src/core/favicon_manager.cpp
index de6a0f183..f7ba858c1 100644
--- a/src/core/favicon_manager.cpp
+++ b/src/core/favicon_manager.cpp
@@ -253,7 +253,7 @@ void FaviconManager::update(const QList<FaviconInfo> &candidates)
const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
continue;
if (it->isValid())
@@ -272,6 +272,14 @@ void FaviconManager::update(const QList<FaviconInfo> &candidates)
void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
{
+ // Invalidate types of the already stored candidate icons because it might differ
+ // among pages.
+ for (FaviconInfo candidateFaviconInfo : candidates) {
+ const QUrl &candidateUrl = candidateFaviconInfo.url;
+ if (m_faviconInfoMap.contains(candidateUrl))
+ m_faviconInfoMap[candidateUrl].type = FaviconInfo::InvalidIcon;
+ }
+
m_candidateCount = candidates.count();
for (FaviconInfo candidateFaviconInfo : candidates) {
const QUrl &candidateUrl = candidateFaviconInfo.url;
@@ -279,8 +287,8 @@ void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
if (!m_faviconInfoMap.contains(candidateUrl))
m_faviconInfoMap.insert(candidateUrl, candidateFaviconInfo);
else {
- // The same icon can be used for more than one page with different types.
- m_faviconInfoMap[candidateUrl].type = candidateFaviconInfo.type;
+ // The same icon URL can be used for different types.
+ m_faviconInfoMap[candidateUrl].type |= candidateFaviconInfo.type;
}
m_faviconInfoMap[candidateUrl].candidate = true;
@@ -311,7 +319,7 @@ QUrl FaviconManager::candidateIconUrl(bool touchIconsEnabled) const
unsigned bestArea = 0;
for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
continue;
if (it->isValid() && bestArea < area(it->size)) {
@@ -331,7 +339,7 @@ void FaviconManager::generateCandidateIcon(bool touchIconsEnabled)
const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
continue;
if (!it->isValid() || !it->isDownloaded())
@@ -373,7 +381,7 @@ FaviconInfo::FaviconInfo(const FaviconInfo &other)
{
}
-FaviconInfo::FaviconInfo(const QUrl &url, FaviconInfo::FaviconType type)
+FaviconInfo::FaviconInfo(const QUrl &url, FaviconInfo::FaviconTypeFlags type)
: url(url)
, type(type)
, size(QSize(0, 0))
diff --git a/src/core/favicon_manager.h b/src/core/favicon_manager.h
index f9758d0f0..60d194c4b 100644
--- a/src/core/favicon_manager.h
+++ b/src/core/favicon_manager.h
@@ -84,23 +84,24 @@ class WebContentsAdapterClient;
// Based on src/3rdparty/chromium/content/public/common/favicon_url.h
class QWEBENGINECORE_PRIVATE_EXPORT FaviconInfo {
public:
- enum FaviconType {
- InvalidIcon,
- Favicon,
- TouchIcon,
- TouchPrecomposedIcon
+ enum FaviconTypeFlag {
+ InvalidIcon = 0,
+ Favicon = 1 << 0,
+ TouchIcon = 1 << 1,
+ TouchPrecomposedIcon = 1 << 2
};
+ Q_DECLARE_FLAGS(FaviconTypeFlags, FaviconTypeFlag);
FaviconInfo();
FaviconInfo(const FaviconInfo &);
- FaviconInfo(const QUrl &, FaviconInfo::FaviconType);
+ FaviconInfo(const QUrl &, FaviconInfo::FaviconTypeFlags);
~FaviconInfo();
bool isValid() const;
bool isDownloaded() const;
QUrl url;
- FaviconType type;
+ FaviconTypeFlags type;
// Stores the largest size in case of multi-size icon
QSize size;
bool candidate;
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 4625d238e..7070292d6 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -55,6 +55,7 @@
#include "type_conversion.h"
#include "visited_links_manager_qt.h"
#include "web_engine_context.h"
+#include "web_contents_adapter_client.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -105,6 +106,9 @@ ProfileAdapter::ProfileAdapter(const QString &storageName):
ProfileAdapter::~ProfileAdapter()
{
+ while (!m_webContentsAdapterClients.isEmpty()) {
+ m_webContentsAdapterClients.first()->releaseProfile();
+ }
WebEngineContext::current()->removeProfileAdapter(this);
if (m_downloadManagerDelegate) {
m_profile->GetDownloadManager(m_profile.data())->Shutdown();
@@ -231,7 +235,8 @@ ProfileAdapter *ProfileAdapter::createDefaultProfileAdapter()
ProfileAdapter *ProfileAdapter::defaultProfileAdapter()
{
- return WebEngineContext::current()->defaultProfileAdapter();
+ WebEngineContext *context = WebEngineContext::current();
+ return context ? context->defaultProfileAdapter() : nullptr;
}
QObject* ProfileAdapter::globalQObjectRoot()
@@ -618,6 +623,16 @@ bool ProfileAdapter::isSpellCheckEnabled() const
#endif
}
+void ProfileAdapter::addWebContentsAdapterClient(WebContentsAdapterClient *client)
+{
+ m_webContentsAdapterClients.append(client);
+}
+
+void ProfileAdapter::removeWebContentsAdapterClient(WebContentsAdapterClient *client)
+{
+ m_webContentsAdapterClients.removeAll(client);
+}
+
void ProfileAdapter::resetVisitedLinksManager()
{
m_visitedLinksManager.reset(new VisitedLinksManagerQt(m_profile.data(), persistVisitedLinks()));
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index 480ca61f6..1aff145b2 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -76,6 +76,7 @@ class ProfileAdapterClient;
class ProfileQt;
class UserResourceControllerHost;
class VisitedLinksManagerQt;
+class WebContentsAdapterClient;
class QWEBENGINECORE_PRIVATE_EXPORT ProfileAdapter : public QObject
{
@@ -133,6 +134,9 @@ public:
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
+ void addWebContentsAdapterClient(WebContentsAdapterClient *client);
+ void removeWebContentsAdapterClient(WebContentsAdapterClient *client);
+
// KEEP IN SYNC with API or add mapping layer
enum HttpCacheType {
MemoryHttpCache = 0,
@@ -237,6 +241,7 @@ private:
QHash<QByteArray, QSharedPointer<UserNotificationController>> m_persistentNotifications;
QList<ProfileAdapterClient*> m_clients;
+ QVector<WebContentsAdapterClient *> m_webContentsAdapterClients;
int m_httpCacheMaxSize;
int m_pageRequestInterceptors;
QrcUrlSchemeHandler m_qrcHandler;
diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h
index 0309200b4..8ee9d240e 100644
--- a/src/core/profile_adapter_client.h
+++ b/src/core/profile_adapter_client.h
@@ -147,6 +147,8 @@ public:
virtual void useForGlobalCertificateVerificationChanged() {}
virtual void showNotification(QSharedPointer<UserNotificationController> &) { }
+ virtual void addWebContentsAdapterClient(WebContentsAdapterClient *adapter) = 0;
+ virtual void removeWebContentsAdapterClient(WebContentsAdapterClient *adapter) = 0;
static QString downloadInterruptReasonToString(DownloadInterruptReason reason);
};
diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp
index ef16e2add..02d2db448 100644
--- a/src/core/type_conversion.cpp
+++ b/src/core/type_conversion.cpp
@@ -218,7 +218,7 @@ int flagsFromModifiers(Qt::KeyboardModifiers modifiers)
return modifierFlags;
}
-FaviconInfo::FaviconType toQt(content::FaviconURL::IconType type)
+FaviconInfo::FaviconTypeFlags toQt(content::FaviconURL::IconType type)
{
switch (type) {
case content::FaviconURL::IconType::kFavicon:
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index d155ed391..cdfcae450 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -485,6 +485,7 @@ public:
virtual ProfileAdapter *profileAdapter() = 0;
virtual WebContentsAdapter* webContentsAdapter() = 0;
+ virtual void releaseProfile() = 0;
};
diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp
index a652469cb..705c0c106 100644
--- a/src/core/web_engine_settings.cpp
+++ b/src/core/web_engine_settings.cpp
@@ -67,27 +67,6 @@ QHash<WebEngineSettings::FontSize, int> 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()
@@ -340,8 +324,8 @@ void WebEngineSettings::initDefaults()
void WebEngineSettings::scheduleApply()
{
- if (!m_batchTimer->isActive())
- m_batchTimer->start();
+ if (!m_batchTimer.isActive())
+ m_batchTimer.start();
}
void WebEngineSettings::doApply()
@@ -453,5 +437,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 8ed727524..8e1bb741c 100644
--- a/src/core/web_engine_settings.h
+++ b/src/core/web_engine_settings.h
@@ -57,6 +57,7 @@
#include <QHash>
#include <QUrl>
#include <QSet>
+#include <QTimer>
namespace content {
struct RendererPreferences;
@@ -65,7 +66,6 @@ struct WebPreferences;
}
namespace QtWebEngineCore {
-class BatchTimer;
class WebContentsAdapter;
class QWEBENGINECORE_PRIVATE_EXPORT WebEngineSettings {
@@ -178,7 +178,7 @@ private:
QHash<FontSize, int> m_fontSizes;
QString m_defaultEncoding;
QScopedPointer<content::WebPreferences> webPreferences;
- QScopedPointer<BatchTimer> m_batchTimer;
+ QTimer m_batchTimer;
WebEngineSettings *parentSettings;
QSet<WebEngineSettings *> childSettings;
@@ -188,7 +188,6 @@ private:
static QHash<FontSize, int> s_defaultFontSizes;
UnknownUrlSchemePolicy m_unknownUrlSchemePolicy;
- friend class BatchTimer;
friend class WebContentsAdapter;
};
diff --git a/src/webengine/api/qquickwebenginedialogrequests.cpp b/src/webengine/api/qquickwebenginedialogrequests.cpp
index b1f52a6b1..d6bba9a98 100644
--- a/src/webengine/api/qquickwebenginedialogrequests.cpp
+++ b/src/webengine/api/qquickwebenginedialogrequests.cpp
@@ -340,8 +340,8 @@ QString QQuickWebEngineJavaScriptDialogRequest::title() const
\qmlproperty enumeration JavaScriptDialogRequest::type
\readonly
- Returns the type of the requested dialog box, see HTML5's
-
+ Returns the type of the requested dialog box. For more information, see
+ HTML5's
\l{https://www.w3.org/TR/html5/webappapis.html#simple-dialogs}{Simple Dialogs}.
\value JavaScriptDialogRequest.DialogTypeAlert
@@ -350,7 +350,7 @@ QString QQuickWebEngineJavaScriptDialogRequest::title() const
A JavaScript confirmation dialog.
\value JavaScriptDialogRequest.DialogTypePrompt
A JavaScript prompt dialog.
- \value JavaScriptDialogRequest.DialogTypeUnload
+ \value JavaScriptDialogRequest.DialogTypeBeforeUnload
The users should be asked if they want to leave the page.
*/
diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp
index a80f163d5..981d11633 100644
--- a/src/webengine/api/qquickwebenginedownloaditem.cpp
+++ b/src/webengine/api/qquickwebenginedownloaditem.cpp
@@ -185,10 +185,8 @@ void QQuickWebEngineDownloadItemPrivate::update(const ProfileAdapterClient::Down
Q_EMIT q->totalBytesChanged();
}
- if (info.done != downloadFinished) {
- downloadFinished = info.done;
- Q_EMIT q->isFinishedChanged();
- }
+ if (info.done)
+ setFinished();
if (info.paused != downloadPaused) {
downloadPaused = info.paused;
@@ -206,6 +204,17 @@ void QQuickWebEngineDownloadItemPrivate::updateState(QQuickWebEngineDownloadItem
}
}
+void QQuickWebEngineDownloadItemPrivate::setFinished()
+{
+ Q_Q(QQuickWebEngineDownloadItem);
+
+ if (downloadFinished)
+ return;
+
+ downloadFinished = true;
+ Q_EMIT q->isFinishedChanged();
+}
+
/*!
\qmlmethod void WebEngineDownloadItem::accept()
@@ -255,6 +264,7 @@ void QQuickWebEngineDownloadItem::cancel()
return;
d->updateState(QQuickWebEngineDownloadItem::DownloadCancelled);
+ d->setFinished();
// We directly cancel the download if the user cancels before
// it even started, so no need to notify the profile here.
@@ -593,12 +603,14 @@ bool QQuickWebEngineDownloadItem::isPaused() const
}
/*!
- \qmlproperty bool WebEngineDownloadItem::view
+ \qmlproperty WebEngineView WebEngineDownloadItem::view
\readonly
\since QtWebEngine 1.8
Returns the view the download was requested on. If the download was not triggered by content in a view,
\c nullptr is returned.
+
+ \sa WebEngineView
*/
QQuickWebEngineView *QQuickWebEngineDownloadItem::view() const
{
@@ -615,8 +627,8 @@ QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownload
QQuickWebEngineDownloadItem::~QQuickWebEngineDownloadItem()
{
- if (d_ptr->profile)
- d_ptr->profile->d_ptr->profileAdapter()->removeDownload(d_ptr->downloadId);
+ if (!isFinished())
+ cancel();
}
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
index 4b89335bd..f444c04a5 100644
--- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h
+++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
@@ -85,6 +85,7 @@ public:
void update(const QtWebEngineCore::ProfileAdapterClient::DownloadItemInfo &info);
void updateState(QQuickWebEngineDownloadItem::DownloadState newState);
+ void setFinished();
};
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 0ec4b19ce..3c4ec0595 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -171,11 +171,6 @@ QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(ProfileAdapter *pro
QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate()
{
-
- while (!m_webContentsAdapterClients.isEmpty()) {
- m_webContentsAdapterClients.first()->destroy();
- }
-
if (m_profileAdapter) {
// In the case the user sets this profile as the parent of the interceptor
// it can be deleted before the browser-context still referencing it is.
@@ -183,25 +178,20 @@ QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate()
m_profileAdapter->removeClient(this);
}
- for (QQuickWebEngineDownloadItem *download : qAsConst(m_ongoingDownloads)) {
- if (download)
- download->cancel();
- }
-
- m_ongoingDownloads.clear();
-
if (m_profileAdapter != QtWebEngineCore::ProfileAdapter::defaultProfileAdapter())
delete m_profileAdapter;
}
-void QQuickWebEngineProfilePrivate::addWebContentsAdapterClient(QQuickWebEngineViewPrivate *adapter)
+void QQuickWebEngineProfilePrivate::addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter)
{
- m_webContentsAdapterClients.append(adapter);
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->addWebContentsAdapterClient(adapter);
}
-void QQuickWebEngineProfilePrivate::removeWebContentsAdapterClient(QQuickWebEngineViewPrivate*adapter)
+void QQuickWebEngineProfilePrivate::removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient*adapter)
{
- m_webContentsAdapterClients.removeAll(adapter);
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->removeWebContentsAdapterClient(adapter);
}
QtWebEngineCore::ProfileAdapter *QQuickWebEngineProfilePrivate::profileAdapter() const
@@ -223,6 +213,23 @@ void QQuickWebEngineProfilePrivate::cancelDownload(quint32 downloadId)
void QQuickWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
{
m_ongoingDownloads.remove(downloadId);
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(downloadId);
+}
+
+void QQuickWebEngineProfilePrivate::cleanDownloads()
+{
+ for (auto download : m_ongoingDownloads.values()) {
+ if (!download)
+ continue;
+
+ if (!download->isFinished())
+ download->cancel();
+
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(download->id());
+ }
+ m_ongoingDownloads.clear();
}
void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
@@ -247,6 +254,7 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q);
m_ongoingDownloads.insert(info.id, download);
+ QObject::connect(download, &QQuickWebEngineDownloadItem::destroyed, q, [id = info.id, this] () { downloadDestroyed(id); });
QQmlEngine::setObjectOwnership(download, QQmlEngine::JavaScriptOwnership);
Q_EMIT q->downloadRequested(download);
@@ -260,7 +268,6 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
if (state == QQuickWebEngineDownloadItem::DownloadRequested) {
// Delete unaccepted downloads.
info.accepted = false;
- m_ongoingDownloads.remove(info.id);
delete download;
}
}
@@ -283,7 +290,6 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info
if (info.state != ProfileAdapterClient::DownloadInProgress) {
Q_EMIT q->downloadFinished(download);
- m_ongoingDownloads.remove(info.id);
}
}
@@ -410,6 +416,7 @@ QQuickWebEngineProfile::QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *pr
*/
QQuickWebEngineProfile::~QQuickWebEngineProfile()
{
+ d_ptr->cleanDownloads();
}
/*!
@@ -1057,7 +1064,7 @@ QQuickWebEngineSettings *QQuickWebEngineProfile::settings() const
\property QQuickWebEngineProfile::userScripts
\since 5.9
- \brief the collection of scripts that are injected into all pages that share
+ \brief The collection of scripts that are injected into all pages that share
this profile.
\sa QQuickWebEngineScript, QQmlListReference
diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h
index 322ec0101..c6d412ab3 100644
--- a/src/webengine/api/qquickwebengineprofile_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p.h
@@ -53,7 +53,7 @@
#include "profile_adapter_client.h"
#include "profile_adapter.h"
-#include "qquickwebengineprofile_p.h"
+#include "qquickwebengineprofile.h"
#include <QExplicitlySharedDataPointer>
#include <QMap>
@@ -71,8 +71,8 @@ public:
Q_DECLARE_PUBLIC(QQuickWebEngineProfile)
QQuickWebEngineProfilePrivate(QtWebEngineCore::ProfileAdapter *profileAdapter);
~QQuickWebEngineProfilePrivate();
- void addWebContentsAdapterClient(QQuickWebEngineViewPrivate *adapter);
- void removeWebContentsAdapterClient(QQuickWebEngineViewPrivate *adapter);
+ void addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
+ void removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
QtWebEngineCore::ProfileAdapter* profileAdapter() const;
QQuickWebEngineSettings *settings() const;
@@ -80,6 +80,8 @@ public:
void cancelDownload(quint32 downloadId);
void downloadDestroyed(quint32 downloadId);
+ void cleanDownloads();
+
void downloadRequested(DownloadItemInfo &info) override;
void downloadUpdated(const DownloadItemInfo &info) override;
@@ -100,7 +102,6 @@ private:
QPointer<QtWebEngineCore::ProfileAdapter> m_profileAdapter;
QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads;
QList<QQuickWebEngineScript *> m_userScripts;
- QVector<QQuickWebEngineViewPrivate *> m_webContentsAdapterClients;
};
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index e7b2d8c9c..3290fe448 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -190,7 +190,7 @@ bool QQuickWebEngineViewPrivate::profileInitialized() const
return m_profileInitialized;
}
-void QQuickWebEngineViewPrivate::destroy()
+void QQuickWebEngineViewPrivate::releaseProfile()
{
// The profile for this web contents is about to be
// garbage collected, delete WebContents first and
@@ -1320,7 +1320,7 @@ void QQuickWebEngineView::setBackgroundColor(const QColor &color)
/*!
\property QQuickWebEngineView::audioMuted
- \brief the state of whether the current page audio is muted.
+ \brief The state of whether the current page audio is muted.
\since 5.7
The default value is false.
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 543d7b119..e625e0ccc 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -94,7 +94,7 @@ public:
QQuickWebEngineView *q_ptr;
QQuickWebEngineViewPrivate();
~QQuickWebEngineViewPrivate();
- void destroy();
+ void releaseProfile() override;
void initializeProfile();
QtWebEngineCore::UIDelegatesManager *ui();
diff --git a/src/webengine/doc/src/qtwebengine-examples.qdoc b/src/webengine/doc/src/qtwebengine-examples.qdoc
index 1f1780764..24604e3dd 100644
--- a/src/webengine/doc/src/qtwebengine-examples.qdoc
+++ b/src/webengine/doc/src/qtwebengine-examples.qdoc
@@ -28,7 +28,7 @@
/*!
\group webengine-examples
\title Qt WebEngine Examples
- \brief Examples demonstrating the Qt WebEngine usage
+ \brief Examples demonstrating the Qt WebEngine usage.
\ingroup all-examples
These examples and demonstrations show a range of different uses for \l{Qt WebEngine},
diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc
index 4ac5108b1..58c0708cc 100644
--- a/src/webengine/doc/src/qtwebengine-overview.qdoc
+++ b/src/webengine/doc/src/qtwebengine-overview.qdoc
@@ -149,9 +149,19 @@
engine must be initialized by using \l QtWebEngine::initialize in the application main source
file, as illustrated by the following code snippet:
- \quotefromfile webengine/minimal/main.cpp
- \skipto main
- \printuntil }
+ \code
+ int main(int argc, char *argv[])
+ {
+ QGuiApplication app(argc, argv);
+
+ QtWebEngine::initialize();
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl("qrc:/main.qml"));
+
+ return app.exec();
+ }
+ \endcode
An application can load pages into the WebEngineView, using either an URL or HTML string, and
navigate within session history. By default, links to different pages load within the same
diff --git a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
index 51e0613dc..540d74035 100644
--- a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
+++ b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
@@ -28,7 +28,7 @@
/*!
\qmlmodule QtWebEngine 1.9
\title Qt WebEngine QML Types
- \brief Provides QML types for rendering web content within a QML application
+ \brief Provides QML types for rendering web content within a QML application.
\ingroup qtwebengine-modules
\ingroup qmlmodules
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
index 55d4fcca8..deb92bfd3 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp
+++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
@@ -197,11 +197,8 @@ void QWebEngineDownloadItemPrivate::update(const ProfileAdapterClient::DownloadI
Q_EMIT q->downloadProgress(receivedBytes, totalBytes);
}
- if (info.done != downloadFinished) {
- downloadFinished = info.done;
- if (downloadFinished)
- Q_EMIT q->finished();
- }
+ if (info.done)
+ setFinished();
if (downloadPaused != info.paused) {
downloadPaused = info.paused;
@@ -209,6 +206,15 @@ void QWebEngineDownloadItemPrivate::update(const ProfileAdapterClient::DownloadI
}
}
+void QWebEngineDownloadItemPrivate::setFinished()
+{
+ if (downloadFinished)
+ return;
+
+ downloadFinished = true;
+ Q_EMIT q_ptr->finished();
+}
+
/*!
Accepts the current download request, which will start the download.
@@ -262,6 +268,7 @@ void QWebEngineDownloadItem::cancel()
} else {
d->downloadState = QWebEngineDownloadItem::DownloadCancelled;
Q_EMIT stateChanged(d->downloadState);
+ d->setFinished();
}
}
@@ -653,8 +660,10 @@ QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p,
*/
QWebEngineDownloadItem::~QWebEngineDownloadItem()
{
- if (auto profileAdapter = d_ptr->profile->profileAdapter())
- profileAdapter->removeDownload(d_ptr->downloadId);
+ // MEMO Items are owned by profile by default and will be destroyed on profile's destruction
+ // It's not safe to access profile in that case, so we rely on profile to clean up items
+ if (!isFinished())
+ cancel();
}
QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
index bdcda5be6..b3bc8a3fe 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h
+++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
@@ -53,7 +53,7 @@
#include "qtwebenginewidgetsglobal.h"
-#include "qwebenginedownloaditem_p.h"
+#include "qwebenginedownloaditem.h"
#include "qwebengineprofile_p.h"
#include <QString>
@@ -84,6 +84,8 @@ public:
QWebEnginePage *page;
void update(const QtWebEngineCore::ProfileAdapterClient::DownloadItemInfo &info);
+
+ void setFinished();
};
QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index b1e7cce4e..696b6723f 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -177,6 +177,8 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
ensureInitialized();
wasShown();
});
+
+ profile->d_ptr->addWebContentsAdapterClient(this);
}
QWebEnginePagePrivate::~QWebEnginePagePrivate()
@@ -185,6 +187,7 @@ QWebEnginePagePrivate::~QWebEnginePagePrivate()
profile->d_ptr->profileAdapter()->removePageRequestInterceptor();
delete history;
delete settings;
+ profile->d_ptr->removeWebContentsAdapterClient(this);
}
RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client)
@@ -479,6 +482,13 @@ void QWebEnginePagePrivate::authenticationRequired(QSharedPointer<Authentication
controller->accept(networkAuth.user(), networkAuth.password());
}
+void QWebEnginePagePrivate::releaseProfile()
+{
+ qDebug("Release of profile requested but WebEnginePage still not deleted. Expect troubles !");
+ // this is not the way to go, but might avoid the crash if user code does not make any calls to page.
+ delete q_ptr->d_ptr.take();
+}
+
void QWebEnginePagePrivate::showColorDialog(QSharedPointer<ColorChooserController> controller)
{
#if QT_CONFIG(colordialog)
@@ -845,7 +855,7 @@ QWebEnginePage::QWebEnginePage(QObject* parent)
\property QWebEnginePage::contentsSize
\since 5.7
- The size of the page contents.
+ \brief The size of the page contents.
*/
/*!
@@ -907,11 +917,13 @@ QWebEnginePage::QWebEnginePage(QWebEngineProfile *profile, QObject* parent)
QWebEnginePage::~QWebEnginePage()
{
- Q_D(QWebEnginePage);
- setDevToolsPage(nullptr);
- d->adapter->stopFinding();
- QWebEnginePagePrivate::bindPageAndView(this, nullptr);
- QWebEnginePagePrivate::bindPageAndWidget(this, nullptr);
+ if (d_ptr) {
+ // d_ptr might be exceptionally null if profile adapter got deleted first
+ setDevToolsPage(nullptr);
+ d_ptr->adapter->stopFinding();
+ QWebEnginePagePrivate::bindPageAndView(this, nullptr);
+ QWebEnginePagePrivate::bindPageAndWidget(this, nullptr);
+ }
}
QWebEngineHistory *QWebEnginePage::history() const
@@ -994,7 +1006,7 @@ void QWebEnginePage::setWebChannel(QWebChannel *channel, uint worldId)
/*!
\property QWebEnginePage::backgroundColor
- \brief the page's background color behind the document's body.
+ \brief The page's background color behind the document's body.
\since 5.6
You can set the background color to Qt::transparent or to a translucent
@@ -1045,7 +1057,7 @@ void QWebEnginePage::save(const QString &filePath,
/*!
\property QWebEnginePage::audioMuted
- \brief whether the current page audio is muted.
+ \brief Whether the current page audio is muted.
\since 5.7
The default value is \c false.
@@ -1067,7 +1079,7 @@ void QWebEnginePage::setAudioMuted(bool muted) {
/*!
\property QWebEnginePage::recentlyAudible
- \brief the current page's \e {audible state}, that is, whether audio was recently played
+ \brief The current page's \e {audible state}, that is, whether audio was recently played
or not.
\since 5.7
@@ -2022,7 +2034,7 @@ QUrl QWebEnginePage::requestedUrl() const
/*!
\property QWebEnginePage::iconUrl
- \brief the URL of the icon associated with the page currently viewed
+ \brief The URL of the icon associated with the page currently viewed.
By default, this property contains an empty URL.
@@ -2036,7 +2048,7 @@ QUrl QWebEnginePage::iconUrl() const
/*!
\property QWebEnginePage::icon
- \brief the icon associated with the page currently viewed
+ \brief The icon associated with the page currently viewed.
\since 5.7
By default, this property contains a null icon. If the web page specifies more than one icon,
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index d597383e2..0db462a0a 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -130,6 +130,7 @@ public:
void passOnFocus(bool reverse) override;
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override;
void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) override;
+ void releaseProfile() override;
void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override;
void runGeolocationPermissionRequest(const QUrl &securityOrigin) override;
void runUserNotificationPermissionRequest(const QUrl &securityOrigin) override;
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index e183a66e1..50de63e9a 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -182,13 +182,6 @@ QWebEngineProfilePrivate::~QWebEngineProfilePrivate()
m_profileAdapter->removeClient(this);
}
- for (QWebEngineDownloadItem *download : qAsConst(m_ongoingDownloads)) {
- if (download)
- download->cancel();
- }
-
- m_ongoingDownloads.clear();
-
if (m_profileAdapter != QtWebEngineCore::ProfileAdapter::defaultProfileAdapter())
delete m_profileAdapter;
@@ -203,6 +196,23 @@ ProfileAdapter* QWebEngineProfilePrivate::profileAdapter() const
void QWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
{
m_ongoingDownloads.remove(downloadId);
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(downloadId);
+}
+
+void QWebEngineProfilePrivate::cleanDownloads()
+{
+ for (auto download : m_ongoingDownloads.values()) {
+ if (!download)
+ continue;
+
+ if (!download->isFinished())
+ download->cancel();
+
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(download->id());
+ }
+ m_ongoingDownloads.clear();
}
void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
@@ -226,6 +236,7 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
QWebEngineDownloadItem *download = new QWebEngineDownloadItem(itemPrivate, q);
m_ongoingDownloads.insert(info.id, download);
+ QObject::connect(download, &QWebEngineDownloadItem::destroyed, q, [id = info.id, this] () { downloadDestroyed(id); });
Q_EMIT q->downloadRequested(download);
@@ -239,7 +250,6 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
if (state == QWebEngineDownloadItem::DownloadRequested) {
// Delete unaccepted downloads.
info.accepted = false;
- m_ongoingDownloads.remove(info.id);
delete download;
}
}
@@ -257,9 +267,18 @@ void QWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info)
}
download->d_func()->update(info);
+}
- if (download->isFinished())
- m_ongoingDownloads.remove(info.id);
+void QWebEngineProfilePrivate::addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter)
+{
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->addWebContentsAdapterClient(adapter);
+}
+
+void QWebEngineProfilePrivate::removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter)
+{
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->removeWebContentsAdapterClient(adapter);
}
/*!
@@ -308,6 +327,7 @@ QWebEngineProfile::QWebEngineProfile(QWebEngineProfilePrivate *privatePtr, QObje
*/
QWebEngineProfile::~QWebEngineProfile()
{
+ d_ptr->cleanDownloads();
}
/*!
diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h
index 3dd024ffd..91c43cf0a 100644
--- a/src/webenginewidgets/api/qwebengineprofile_p.h
+++ b/src/webenginewidgets/api/qwebengineprofile_p.h
@@ -84,11 +84,16 @@ public:
void downloadDestroyed(quint32 downloadId);
+ void cleanDownloads();
+
void downloadRequested(DownloadItemInfo &info) override;
void downloadUpdated(const DownloadItemInfo &info) override;
void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &) override;
+ void addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
+ void removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
+
private:
QWebEngineProfile *q_ptr;
QWebEngineSettings *m_settings;
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 576baad17..966b30100 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -238,7 +238,7 @@ QUrl QWebEngineView::iconUrl() const
/*!
\property QWebEngineView::icon
- \brief the icon associated with the page currently viewed
+ \brief The icon associated with the page currently viewed.
\since 5.7
By default, this property contains a null icon.
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
index 8accdf062..b6c5cb497 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
@@ -28,7 +28,7 @@
/*!
\group webengine-widgetexamples
\title Qt WebEngine Widgets Examples
- \brief Examples demonstrating the Qt WebEngine Widgets usage
+ \brief Examples demonstrating the Qt WebEngine Widgets usage.
\ingroup all-examples
Qt provides an integrated Web browser component based on Chromium, the popular
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index 877bf7175..f9ab710d1 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -451,14 +451,14 @@
/*!
\property QWebEnginePage::hasSelection
- \brief whether this page contains selected content or not.
+ \brief Whether this page contains selected content or not.
\sa selectionChanged()
*/
/*!
\property QWebEnginePage::selectedText
- \brief the text currently selected
+ \brief The text currently selected.
By default, this property contains an empty string.
@@ -643,14 +643,20 @@
/*!
\property QWebEnginePage::title
- \brief the title of the page as defined by the HTML \c <title> element
+ \brief The title of the page as defined by the HTML \c <title> element.
+
+ If the page has no \c <title> element, then the URL is used instead. For \c
+ file:// URLs only the filename is used and not the full path.
+
+ By default, before any content has been loaded, this property contains an
+ empty string.
\sa titleChanged()
*/
/*!
\property QWebEnginePage::url
- \brief the URL of the page currently viewed
+ \brief The URL of the page currently viewed.
Setting this property clears the view and loads the URL.
@@ -661,8 +667,8 @@
/*!
\property QWebEnginePage::requestedUrl
- \brief the URL that was originally requested to be loaded by the page
- that is currently viewed
+ \brief The URL that was originally requested to be loaded by the page
+ that is currently viewed.
\note The URL may differ from the one returned by url(), which is the actual
URL that results from DNS resolution or redirection.
@@ -729,7 +735,7 @@
/*!
\property QWebEnginePage::zoomFactor
- \brief the zoom factor for the page content
+ \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}.
*/
diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
index 501959ab9..568e7a63a 100644
--- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
@@ -173,16 +173,16 @@
/*!
\property QWebEngineView::title
- \brief the title of the web page currently viewed
+ \brief The title of the page as defined by the HTML \c <title> element.
- By default, this property contains an empty string.
+ Equivalent to \l {QWebEnginePage::title()}.
\sa titleChanged()
*/
/*!
\property QWebEngineView::url
- \brief the URL of the web page currently viewed
+ \brief The URL of the web page currently viewed.
Setting this property clears the view and loads the URL.
@@ -193,7 +193,7 @@
/*!
\property QWebEngineView::iconUrl
- \brief the URL of the icon associated with the page currently viewed
+ \brief The URL of the icon associated with the page currently viewed.
By default, this property contains an empty URL.
@@ -202,7 +202,7 @@
/*!
\property QWebEngineView::hasSelection
- \brief whether this page contains selected content or not.
+ \brief Whether this page contains selected content or not.
By default, this property is \c false.
@@ -211,7 +211,7 @@
/*!
\property QWebEngineView::selectedText
- \brief the text currently selected
+ \brief The text currently selected.
By default, this property contains an empty string.
@@ -238,7 +238,7 @@
/*!
\property QWebEngineView::zoomFactor
- \brief the zoom factor for the view
+ \brief The zoom factor for the view.
Valid values are within the range from \c{0.25} to \c{5.0}. The default factor is \c{1.0}.
*/
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index b50a7d782..450ee91da 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -141,8 +141,28 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineCertificateError.url --> QUrl"
<< "QQuickWebEngineColorDialogRequest.accepted --> bool"
<< "QQuickWebEngineColorDialogRequest.color --> QColor"
+ << "QQuickWebEngineContextMenuRequest.CanUndo --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanRedo --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanCut --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanCopy --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanPaste --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanDelete --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanSelectAll --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanTranslate --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanEditRichly --> EditFlags"
<< "QQuickWebEngineColorDialogRequest.dialogAccept(QColor) --> void"
<< "QQuickWebEngineColorDialogRequest.dialogReject() --> void"
+ << "QQuickWebEngineContextMenuRequest.editFlags --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaInError --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaPaused --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaMuted --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaLoop --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanSave --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaHasAudio --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanToggleControls --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaControls --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanPrint --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanRotate --> MediaFlags"
<< "QQuickWebEngineContextMenuRequest.MediaTypeAudio --> MediaType"
<< "QQuickWebEngineContextMenuRequest.MediaTypeCanvas --> MediaType"
<< "QQuickWebEngineContextMenuRequest.MediaTypeFile --> MediaType"
@@ -154,6 +174,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineContextMenuRequest.isContentEditable --> bool"
<< "QQuickWebEngineContextMenuRequest.linkText --> QString"
<< "QQuickWebEngineContextMenuRequest.linkUrl --> QUrl"
+ << "QQuickWebEngineContextMenuRequest.mediaFlags --> MediaFlags"
<< "QQuickWebEngineContextMenuRequest.mediaType --> MediaType"
<< "QQuickWebEngineContextMenuRequest.mediaUrl --> QUrl"
<< "QQuickWebEngineContextMenuRequest.misspelledWord --> QString"
@@ -225,6 +246,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineDownloadItem.totalBytesChanged() --> void"
<< "QQuickWebEngineDownloadItem.type --> DownloadType"
<< "QQuickWebEngineDownloadItem.typeChanged() --> void"
+ << "QQuickWebEngineDownloadItem.view --> QQuickWebEngineView*"
<< "QQuickWebEngineFileDialogRequest.FileModeOpen --> FileMode"
<< "QQuickWebEngineFileDialogRequest.FileModeOpenMultiple --> FileMode"
<< "QQuickWebEngineFileDialogRequest.FileModeSave --> FileMode"
@@ -352,6 +374,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineSettings.autoLoadImagesChanged() --> void"
<< "QQuickWebEngineSettings.defaultTextEncoding --> QString"
<< "QQuickWebEngineSettings.defaultTextEncodingChanged() --> void"
+ << "QQuickWebEngineSettings.dnsPrefetchEnabled --> bool"
+ << "QQuickWebEngineSettings.dnsPrefetchEnabledChanged() --> void"
<< "QQuickWebEngineSettings.errorPageEnabled --> bool"
<< "QQuickWebEngineSettings.errorPageEnabledChanged() --> void"
<< "QQuickWebEngineSettings.focusOnNavigationEnabled --> bool"
@@ -364,6 +388,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineSettings.javascriptCanAccessClipboardChanged() --> void"
<< "QQuickWebEngineSettings.javascriptCanOpenWindows --> bool"
<< "QQuickWebEngineSettings.javascriptCanOpenWindowsChanged() --> void"
+ << "QQuickWebEngineSettings.javascriptCanPaste --> bool"
+ << "QQuickWebEngineSettings.javascriptCanPasteChanged() --> void"
<< "QQuickWebEngineSettings.javascriptEnabled --> bool"
<< "QQuickWebEngineSettings.javascriptEnabledChanged() --> void"
<< "QQuickWebEngineSettings.linksIncludedInFocusChain --> bool"
@@ -659,6 +685,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.navigationRequested(QQuickWebEngineNavigationRequest*) --> void"
<< "QQuickWebEngineView.newViewRequested(QQuickWebEngineNewViewRequest*) --> void"
<< "QQuickWebEngineView.pdfPrintingFinished(QString,bool) --> void"
+ << "QQuickWebEngineView.printRequested() --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue) --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId) --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId,PrintedPageOrientation) --> void"
@@ -684,8 +711,10 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.setActiveFocusOnPress(bool) --> void"
<< "QQuickWebEngineView.settings --> QQuickWebEngineSettings*"
<< "QQuickWebEngineView.stop() --> void"
+#if QT_CONFIG(webengine_testsupport)
<< "QQuickWebEngineView.testSupport --> QQuickWebEngineTestSupport*"
<< "QQuickWebEngineView.testSupportChanged() --> void"
+#endif
<< "QQuickWebEngineView.title --> QString"
<< "QQuickWebEngineView.titleChanged() --> void"
<< "QQuickWebEngineView.triggerWebAction(WebAction) --> void"
@@ -815,18 +844,23 @@ void tst_publicapi::publicAPI()
// for (const QString &actual : qAsConst(sortedAPI))
// printf(" << \"%s\"\n", qPrintable(actual));
+ bool apiMatch = true;
// Make sure that nothing slips in the public API unintentionally.
for (const QString &actual : qAsConst(actualAPI)) {
- if (!expectedAPI.contains(actual))
- QEXPECT_FAIL("", qPrintable("Expected list is not up-to-date: " + actual), Continue);
- QVERIFY2(expectedAPI.contains(actual), qPrintable(actual));
+ if (!expectedAPI.contains(actual)) {
+ QWARN(qPrintable("Expected list is not up-to-date: " + actual));
+ apiMatch = false;
+ }
}
// Make sure that the expected list is up-to-date with intentionally added APIs.
for (const QString &expected : expectedAPI) {
- if (!actualAPI.contains(expected))
- QEXPECT_FAIL("", qPrintable("Not implemented: " + expected), Continue);
- QVERIFY2(actualAPI.contains(expected), qPrintable(expected));
+ if (!actualAPI.contains(expected)) {
+ apiMatch = false;
+ QWARN(qPrintable("Not implemented: " + expected));
+ }
}
+
+ QVERIFY2(apiMatch, "Unexpected, missing or misspelled API!");
}
QTEST_MAIN(tst_publicapi)
diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml
index 563a87c83..50a412384 100644
--- a/tests/auto/quick/qmltests/data/tst_favicon.qml
+++ b/tests/auto/quick/qmltests/data/tst_favicon.qml
@@ -375,5 +375,38 @@ TestWebEngineView {
faviconImage.destroy()
}
+
+ function test_touchIconWithSameURL()
+ {
+ WebEngine.settings.touchIconsEnabled = false;
+
+ var icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
+
+ webEngineView.loadHtml(
+ "<html>" +
+ "<link rel='icon' type='image/png' href='" + icon + "'/>" +
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>" +
+ "</html>"
+ );
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // The default favicon has to be loaded even if its URL is also set as a touch icon while touch icons are disabled.
+ tryCompare(iconChangedSpy, "count", 1);
+ compare(webEngineView.icon.toString().replace(/^image:\/\/favicon\//, ''), icon);
+
+ iconChangedSpy.clear();
+
+ webEngineView.loadHtml(
+ "<html>" +
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>" +
+ "</html>"
+ );
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // This page only has a touch icon. With disabled touch icons we don't expect any icon to be shown even if the same icon
+ // was loaded previously.
+ tryCompare(iconChangedSpy, "count", 1);
+ verify(!webEngineView.icon.toString().replace(/^image:\/\/favicon\//, ''));
+ }
}
}
diff --git a/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp b/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp
index 606d05d9e..540c8d505 100644
--- a/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp
+++ b/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp
@@ -62,6 +62,7 @@ private Q_SLOTS:
void downloadTouchIconsEnabled_data();
void downloadTouchIconsEnabled();
void dynamicFavicon();
+ void touchIconWithSameURL();
private:
QWebEngineView *m_view;
@@ -508,6 +509,43 @@ void tst_FaviconManager::dynamicFavicon()
}
}
+void tst_FaviconManager::touchIconWithSameURL()
+{
+ m_page->settings()->setAttribute(QWebEngineSettings::TouchIconsEnabled, false);
+
+ const QString icon("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=");
+ QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool)));
+ QSignalSpy iconUrlChangedSpy(m_page, SIGNAL(iconUrlChanged(QUrl)));
+ QSignalSpy iconChangedSpy(m_page, SIGNAL(iconChanged(QIcon)));
+
+ m_page->setHtml("<html>"
+ "<link rel='icon' type='image/png' href='" + icon + "'/>"
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>"
+ "</html>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+
+ // The default favicon has to be loaded even if its URL is also set as a touch icon while touch icons are disabled.
+ QTRY_COMPARE(iconUrlChangedSpy.count(), 1);
+ QCOMPARE(m_page->iconUrl().toString(), icon);
+ QTRY_COMPARE(iconChangedSpy.count(), 1);
+
+ loadFinishedSpy.clear();
+ iconUrlChangedSpy.clear();
+ iconChangedSpy.clear();
+
+ m_page->setHtml("<html>"
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>"
+ "</html>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+
+ // This page only has a touch icon. With disabled touch icons we don't expect any icon to be shown even if the same icon
+ // was loaded previously.
+ QTRY_COMPARE(iconUrlChangedSpy.count(), 1);
+ QVERIFY(m_page->iconUrl().toString().isEmpty());
+ QTRY_COMPARE(iconChangedSpy.count(), 1);
+
+}
+
QTEST_MAIN(tst_FaviconManager)
#include "tst_faviconmanager.moc"
diff --git a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
index 32823d30d..ee1e6ee04 100644
--- a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
+++ b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
@@ -70,6 +70,7 @@ private Q_SLOTS:
void downloadFileNot1();
void downloadFileNot2();
void downloadDeleted();
+ void downloadDeletedByProfile();
void downloadUniqueFilename_data();
void downloadUniqueFilename();
void downloadUniqueFileNameWithTimeStamp();
@@ -821,6 +822,37 @@ void tst_QWebEngineDownloadItem::downloadDeleted()
QTRY_COMPARE(finishedCount, 1);
}
+void tst_QWebEngineDownloadItem::downloadDeletedByProfile()
+{
+ m_server->setExpectError(true);
+
+ QPointer<QWebEngineProfile> profile(new QWebEngineProfile);
+ profile->setHttpCacheType(QWebEngineProfile::NoCache);
+ profile->settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false);
+
+ bool downloadFinished = false;
+ QPointer<QWebEngineDownloadItem> downloadItem;
+ connect(profile, &QWebEngineProfile::downloadRequested, [&] (QWebEngineDownloadItem *item) {
+ connect(item, &QWebEngineDownloadItem::finished, [&] () {
+ downloadFinished = true;
+ });
+ downloadItem = item;
+ item->accept();
+ });
+
+ QPointer<QWebEnginePage> page(new QWebEnginePage(profile));
+ page->download(m_server->url(QByteArrayLiteral("/file")));
+
+ QTRY_COMPARE(downloadItem.isNull(), false);
+ QVERIFY(downloadItem);
+
+ page->deleteLater();
+ profile->deleteLater();
+
+ QTRY_COMPARE(downloadFinished, true);
+ QTRY_COMPARE(downloadItem.isNull(), true);
+}
+
void tst_QWebEngineDownloadItem::downloadUniqueFilename_data()
{
QTest::addColumn<QString>("baseName");