From cfaa49a9e5ec5e01c57a5621702c881ae07ab515 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 15 Feb 2019 18:36:37 +0100 Subject: Update Chromium MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: 61b45663dff1 [Backport] Fix for security issue 903500 a3b4be8d0247 [Backport] Fix security issue 901677 82b53e95166e [Backport] Fix security issue 895117 a26c352168ec [Backport] Fix for CVE-2019-5784 Task-number: QTBUG-73417 Change-Id: I149ae5a5cd4d83f17bd0c603dd2e3a1079c86e82 Reviewed-by: Michael Brüning --- src/3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index 7b5e48775..a26c35216 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 7b5e48775b3ac89f49d4b0f74b7db03540cc212b +Subproject commit a26c352168ec12cb917318b626a31f569a711980 -- cgit v1.2.3 From 0f2fe6447aa057587b08584a43767447e04982d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Thu, 14 Feb 2019 10:42:04 +0100 Subject: Fix crash in tst_Spellchecking::spellcheck The test tst_Spellchecking::spellcheck crashes when run with QT_LOGGING_RULES=qt.accessibility.cache.debug=true which triggers debug output from QAccessible::registerAccessibleInterface and QAccessible::deleteAccessibleInterface These functions are called during the construction/destruction of BrowserAccessibilityQt. The problem is that BrowserAccessibilityQt is not necessarily in a valid state at these times: BrowserAccessibilityQt relies on it's manager to be *fully* initialized yet BrowserAccessibilityQt may be constructed/destructed *during* the managers construction/destruction. The solution is to override QAccessibleInterface::isValid to return true only if the manager is in a valid state too. This disables the debug output and avoids the crash. Fixes: QTBUG-72878 Change-Id: Icffe4e503145133c24535fb094bbcb606568e57c Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Peter Varga --- src/core/browser_accessibility_manager_qt.cpp | 6 ++++++ src/core/browser_accessibility_manager_qt.h | 3 +++ src/core/browser_accessibility_qt.cpp | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) 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 a672ccc06..29fbbc542 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -68,7 +68,8 @@ BrowserAccessibilityQt::BrowserAccessibilityQt() bool BrowserAccessibilityQt::isValid() const { - return true; + auto managerQt = static_cast(manager_); + return managerQt && managerQt->isValid(); } QObject *BrowserAccessibilityQt::object() const -- cgit v1.2.3 From c8dcc8cffa82c482734bcafce64496840c1e4988 Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Tue, 5 Feb 2019 15:48:13 +0100 Subject: Doc: Fix type of WebEngineDownloadItem::view property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I46fc228d99ad6d89d6f2a79a7f3c3352befe0a64 Reviewed-by: Leena Miettinen Reviewed-by: Jüri Valdmann --- src/webengine/api/qquickwebenginedownloaditem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp index a80f163d5..b69e6b7da 100644 --- a/src/webengine/api/qquickwebenginedownloaditem.cpp +++ b/src/webengine/api/qquickwebenginedownloaditem.cpp @@ -593,12 +593,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 { -- cgit v1.2.3 From 9c59897f9d24041e3e1bb9553d5b4bc1f1ec538a Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Tue, 5 Feb 2019 16:01:41 +0100 Subject: Update public QML API test and enforce failure check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie6dd101b15ac5bd7b6d60b61922b5db688aff785 Reviewed-by: Jüri Valdmann --- tests/auto/quick/publicapi/tst_publicapi.cpp | 46 ++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 0e48e280d..59973f7d0 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -134,8 +134,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" @@ -147,6 +167,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" @@ -218,6 +239,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" @@ -344,6 +366,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" @@ -356,6 +380,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" @@ -650,6 +676,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" @@ -675,8 +702,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" @@ -792,18 +821,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) -- cgit v1.2.3 From 755f7e414583c5458c2d421d047a1c7890c8d8d2 Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Mon, 11 Feb 2019 19:13:01 +0100 Subject: Set download state to finished when cancelling or destroying the download item MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-73839 Change-Id: Ieebaa802bdfe0c410618e4213a9bedbbae9d0f61 Reviewed-by: Michael Brüning Reviewed-by: Jüri Valdmann --- src/webengine/api/qquickwebenginedownloaditem.cpp | 20 ++++++++++++++++---- src/webengine/api/qquickwebenginedownloaditem_p_p.h | 1 + src/webenginewidgets/api/qwebenginedownloaditem.cpp | 19 ++++++++++++++----- src/webenginewidgets/api/qwebenginedownloaditem_p.h | 4 +++- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp index b69e6b7da..7d1382876 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. @@ -617,6 +627,8 @@ QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownload QQuickWebEngineDownloadItem::~QQuickWebEngineDownloadItem() { + if (!isFinished()) + cancel(); if (d_ptr->profile) d_ptr->profile->d_ptr->profileAdapter()->removeDownload(d_ptr->downloadId); } 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/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index 55d4fcca8..f0f0958a5 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,6 +660,8 @@ QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, */ QWebEngineDownloadItem::~QWebEngineDownloadItem() { + if (!isFinished()) + cancel(); if (auto profileAdapter = d_ptr->profile->profileAdapter()) profileAdapter->removeDownload(d_ptr->downloadId); } 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 @@ -84,6 +84,8 @@ public: QWebEnginePage *page; void update(const QtWebEngineCore::ProfileAdapterClient::DownloadItemInfo &info); + + void setFinished(); }; QT_END_NAMESPACE -- cgit v1.2.3 From 7537526093c92e89672d1e952a9baceecaa91730 Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Mon, 11 Feb 2019 19:21:03 +0100 Subject: Remove download properly on profile destruction to avoid use after free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the Widgets API, download items are children of the profile and are destroyed when the parent profile destroys its children. The download item's destructor can therefore not access the profile, as it would cause a heap-use-after-free crashes. On quick side turn ongoing downloads cleanup to match widgets one. Fixes: QTBUG-73839 Change-Id: Iabb379e91187e3e68ebcd4693fec35883b72b1f2 Reviewed-by: Michael Brüning Reviewed-by: Jüri Valdmann --- src/webengine/api/qquickwebenginedownloaditem.cpp | 2 -- src/webengine/api/qquickwebengineprofile.cpp | 28 +++++++++++++------ src/webengine/api/qquickwebengineprofile_p.h | 4 ++- .../api/qwebenginedownloaditem.cpp | 4 +-- src/webenginewidgets/api/qwebengineprofile.cpp | 30 ++++++++++++-------- src/webenginewidgets/api/qwebengineprofile_p.h | 2 ++ .../tst_qwebenginedownloaditem.cpp | 32 ++++++++++++++++++++++ 7 files changed, 77 insertions(+), 25 deletions(-) diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp index 7d1382876..981d11633 100644 --- a/src/webengine/api/qquickwebenginedownloaditem.cpp +++ b/src/webengine/api/qquickwebenginedownloaditem.cpp @@ -629,8 +629,6 @@ QQuickWebEngineDownloadItem::~QQuickWebEngineDownloadItem() { if (!isFinished()) cancel(); - if (d_ptr->profile) - d_ptr->profile->d_ptr->profileAdapter()->removeDownload(d_ptr->downloadId); } QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index ddc71602b..26fcf28f7 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -175,13 +175,6 @@ 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; } @@ -215,6 +208,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) @@ -239,6 +249,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); @@ -252,7 +263,6 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) if (state == QQuickWebEngineDownloadItem::DownloadRequested) { // Delete unaccepted downloads. info.accepted = false; - m_ongoingDownloads.remove(info.id); delete download; } } @@ -275,7 +285,6 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info if (info.state != ProfileAdapterClient::DownloadInProgress) { Q_EMIT q->downloadFinished(download); - m_ongoingDownloads.remove(info.id); } } @@ -380,6 +389,7 @@ QQuickWebEngineProfile::QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *pr */ QQuickWebEngineProfile::~QQuickWebEngineProfile() { + d_ptr->cleanDownloads(); } /*! diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h index d31ded0ec..2b1a5b134 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 #include @@ -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; diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index f0f0958a5..deb92bfd3 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -660,10 +660,10 @@ QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, */ QWebEngineDownloadItem::~QWebEngineDownloadItem() { + // 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(); - if (auto profileAdapter = d_ptr->profile->profileAdapter()) - profileAdapter->removeDownload(d_ptr->downloadId); } QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 03ce5e0bc..0d12fdae1 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -175,13 +175,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; @@ -196,6 +189,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) @@ -219,6 +229,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); @@ -232,7 +243,6 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) if (state == QWebEngineDownloadItem::DownloadRequested) { // Delete unaccepted downloads. info.accepted = false; - m_ongoingDownloads.remove(info.id); delete download; } } @@ -250,9 +260,6 @@ void QWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) } download->d_func()->update(info); - - if (download->isFinished()) - m_ongoingDownloads.remove(info.id); } /*! @@ -301,6 +308,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 9ff8df849..4a76f457f 100644 --- a/src/webenginewidgets/api/qwebengineprofile_p.h +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -81,6 +81,8 @@ public: void downloadDestroyed(quint32 downloadId); + void cleanDownloads(); + void downloadRequested(DownloadItemInfo &info) override; void downloadUpdated(const DownloadItemInfo &info) override; diff --git a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp index 2af818928..b30fc7258 100644 --- a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp +++ b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp @@ -69,6 +69,7 @@ private Q_SLOTS: void downloadFileNot1(); void downloadFileNot2(); void downloadDeleted(); + void downloadDeletedByProfile(); private: void saveLink(QPoint linkPos); @@ -812,5 +813,36 @@ void tst_QWebEngineDownloadItem::downloadDeleted() QTRY_COMPARE(finishedCount, 1); } +void tst_QWebEngineDownloadItem::downloadDeletedByProfile() +{ + m_server->setExpectError(true); + + QPointer profile(new QWebEngineProfile); + profile->setHttpCacheType(QWebEngineProfile::NoCache); + profile->settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false); + + bool downloadFinished = false; + QPointer downloadItem; + connect(profile, &QWebEngineProfile::downloadRequested, [&] (QWebEngineDownloadItem *item) { + connect(item, &QWebEngineDownloadItem::finished, [&] () { + downloadFinished = true; + }); + downloadItem = item; + item->accept(); + }); + + QPointer 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); +} + QTEST_MAIN(tst_QWebEngineDownloadItem) #include "tst_qwebenginedownloaditem.moc" -- cgit v1.2.3 From 8fefc0d9b8ae46d65e8c05f9cc55bbfc0e88b632 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 19 Feb 2019 10:16:52 +0100 Subject: Update Chromium MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last of the security fixes from Chrome 72 Changes: 493fab1afff5 [Backport] Fix for security issue 895970 Fixes: QTBUG-73417 Change-Id: If6a4f6f5773c99db3498e3b178cce39e36c85e79 Reviewed-by: Michael Brüning --- src/3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index a26c35216..493fab1af 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit a26c352168ec12cb917318b626a31f569a711980 +Subproject commit 493fab1afff5034cb5552455add3af3aaf41f9e9 -- cgit v1.2.3 From f5bad87426599ff52e382aa7e0698a7e4b4b62de Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 21 Feb 2019 16:08:37 +0100 Subject: Doc: Copy minimal example code into overview page After change cfe53bce9, the 'minimal' example isn't that minimal anymore. Rather copy the few lines, like we already do for the widget example. Change-Id: I9dd818738edb8d229f54ff24822d4c1723376ccc Reviewed-by: Leena Miettinen --- src/webengine/doc/src/qtwebengine-overview.qdoc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc index bd5569e3f..d83a65bdb 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 -- cgit v1.2.3 From fd2acd57df7d62490a9a7c1f7b5b60ae50c51ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Thu, 21 Feb 2019 13:23:41 +0100 Subject: Clarify documentation of QWebEnginePage::title() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explain what happens when the HTML has no proper defined and clarify the meaning of 'by default': it refers to the state before load()/setUrl()/etc. Fixes: QTBUG-71799 Change-Id: Ib2669007573b3ea53e205d9228237bae392f6f78 Reviewed-by: Michael Brüning <michael.bruning@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> --- src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc | 6 ++++++ src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index 035b45a6d..ef1166601 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -643,6 +643,12 @@ \property QWebEnginePage::title \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() */ diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index 501959ab9..1c51a2a52 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -173,9 +173,9 @@ /*! \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() */ -- cgit v1.2.3 From 598bfc652edffb047948e01c3c76eb9e0cb7db4e Mon Sep 17 00:00:00 2001 From: Kai Koehne <kai.koehne@qt.io> Date: Thu, 21 Feb 2019 17:01:03 +0100 Subject: Doc: Always treat \brief as full sentence Make sure all \brief descriptions start with an upper-case letter and end with a . Also start descriptions of \class with the name of the class or struct. Change-Id: Ifd2656201f9c1dff092085508a5423ce516e2d3f Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> --- src/core/api/qwebenginecookiestore.cpp | 2 +- src/core/api/qwebengineurlschemehandler.cpp | 2 +- src/webengine/api/qquickwebengineprofile.cpp | 2 +- src/webengine/api/qquickwebengineview.cpp | 2 +- src/webengine/doc/src/qtwebengine-examples.qdoc | 2 +- src/webengine/doc/src/qtwebengine-qmlmodule.qdoc | 2 +- src/webenginewidgets/api/qwebenginepage.cpp | 12 ++++++------ src/webenginewidgets/api/qwebengineview.cpp | 2 +- .../doc/src/qtwebenginewidgets-examples.qdoc | 2 +- src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc | 14 +++++++------- src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc | 12 ++++++------ 11 files changed, 27 insertions(+), 27 deletions(-) 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/qwebengineurlschemehandler.cpp b/src/core/api/qwebengineurlschemehandler.cpp index 6f06b2c6e..b5912703d 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/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index 26fcf28f7..b7abb13fc 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -958,7 +958,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/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index b9ae06aeb..35f797cb1 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -1277,7 +1277,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/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-qmlmodule.qdoc b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc index 17c29a126..5e172087d 100644 --- a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc +++ b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc @@ -28,7 +28,7 @@ /*! \qmlmodule QtWebEngine 1.8 \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/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 67f3d7a76..aa1f7be7c 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -905,7 +905,7 @@ QWebEnginePage::QWebEnginePage(QObject* parent) \property QWebEnginePage::contentsSize \since 5.7 - The size of the page contents. + \brief The size of the page contents. */ /*! @@ -1054,7 +1054,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 @@ -1105,7 +1105,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. @@ -1127,7 +1127,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 @@ -2046,7 +2046,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. @@ -2060,7 +2060,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/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 ef1166601..517fdc7d9 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -449,14 +449,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. @@ -641,7 +641,7 @@ /*! \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. @@ -654,7 +654,7 @@ /*! \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. @@ -665,8 +665,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. @@ -733,7 +733,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 1c51a2a52..568e7a63a 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -173,7 +173,7 @@ /*! \property QWebEngineView::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. Equivalent to \l {QWebEnginePage::title()}. @@ -182,7 +182,7 @@ /*! \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}. */ -- cgit v1.2.3 From b47b28d3cfb8b249cce343031507864de99117a7 Mon Sep 17 00:00:00 2001 From: Antti Kokko <antti.kokko@qt.io> Date: Wed, 20 Feb 2019 15:21:30 +0200 Subject: Add changes file for Qt 5.12.2 Change-Id: I41bb4f924b9091b550354065211672e31088d1cb Reviewed-by: Kai Koehne <kai.koehne@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> --- dist/changes-5.12.2 | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 dist/changes-5.12.2 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. -- cgit v1.2.3 From 837347e1901086a9757b5aca7e5bbee7b0d8e20e Mon Sep 17 00:00:00 2001 From: Peter Varga <pvarga@inf.u-szeged.hu> Date: Mon, 11 Feb 2019 16:38:47 +0100 Subject: Fix handling of touch icons when it is disabled Store the icon type in a bitfield because the same icon URL might be used for various types on same page. This way webengine won't ignore to download a default icon what is also set as a touch icon when touch icons are disabled. Moreover, do not store the icon types from the previous page because a subsequent page might use the same icon URL but with different type. With this change the type of the cached icons are updated after each page load. Fixes: QTBUG-70081 Change-Id: I8031a740b07b0c6a8e5759a994f386b13ce87be2 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> --- src/core/favicon_manager.cpp | 20 ++++++++---- src/core/favicon_manager.h | 15 +++++---- src/core/type_conversion.cpp | 2 +- tests/auto/quick/qmltests/data/tst_favicon.qml | 33 +++++++++++++++++++ .../widgets/faviconmanager/tst_faviconmanager.cpp | 38 ++++++++++++++++++++++ 5 files changed, 94 insertions(+), 14 deletions(-) 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/type_conversion.cpp b/src/core/type_conversion.cpp index d35426ac3..f69b2a297 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -216,7 +216,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/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" -- cgit v1.2.3 From 1f77d4709946511b919810354f19875824399096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= <juri.valdmann@qt.io> 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 <allan.jensen@qt.io> --- 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 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 <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/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 <QCoreApplication> -#include <QEvent> #include <QEventLoop> -#include <QObject> -#include <QTimerEvent> #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::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() @@ -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 <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 { @@ -177,7 +177,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; @@ -187,7 +187,6 @@ private: static QHash<FontSize, int> s_defaultFontSizes; UnknownUrlSchemePolicy m_unknownUrlSchemePolicy; - friend class BatchTimer; friend class WebContentsAdapter; }; -- cgit v1.2.3 From 4263778b2cf06dbdba24c7dfe2e54268a50de257 Mon Sep 17 00:00:00 2001 From: Szabolcs David <davidsz@inf.u-szeged.hu> Date: Thu, 21 Feb 2019 14:04:44 +0100 Subject: Quicknanobrowser: Hide status bubble properly Status bubble is always visible in the lower left corner. Change-Id: I334246d65261b8c762aafb7d276122f63fe3a8ba Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> --- examples/webengine/quicknanobrowser/BrowserWindow.qml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml index 8d62482da..0ac69ef24 100644 --- a/examples/webengine/quicknanobrowser/BrowserWindow.qml +++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml @@ -380,11 +380,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(); } } @@ -566,6 +567,7 @@ ApplicationWindow { id: statusBubble color: "oldlace" property int padding: 8 + visible: false anchors.left: parent.left anchors.bottom: parent.bottom @@ -578,9 +580,12 @@ ApplicationWindow { elide: Qt.ElideMiddle Timer { - id: resetStatusText + id: hideStatusText interval: 750 - onTriggered: statusText.text = "" + onTriggered: { + statusText.text = ""; + statusBubble.visible = false; + } } } } -- cgit v1.2.3 From 0091ec9046c2c4812dee109fcbfb8372d9435461 Mon Sep 17 00:00:00 2001 From: Leena Miettinen <riitta-leena.miettinen@qt.io> Date: Tue, 26 Feb 2019 11:31:46 +0100 Subject: Doc: Fix JavaScriptDialogRequest.DialogTypeBeforeUnload enum value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTBUG-74070 Change-Id: Iad514671a588c0a3e0405dd0141ef54320ae8c86 Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io> --- src/webengine/api/qquickwebenginedialogrequests.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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. */ -- cgit v1.2.3 From 8600d3d22d86be364a4c29e559dda7990594d0c5 Mon Sep 17 00:00:00 2001 From: Tamas Zakor <ztamas@inf.u-szeged.hu> Date: Tue, 12 Feb 2019 16:54:20 +0100 Subject: Fix incrementing download ID Adapt DownloadManagerDelegateQt::m_currentId to https://chromium-review.googlesource.com/1144311 Update Chromium: 09516a434b [Backport] Allow DownloadManagerImpl to get InProgressDownloadManager from DownloadManagerService b3edbf2a84 [Backport] Make DownloadManagerImpl to generate download IDs for in-progress DB Task-number: QTBUG-70702 Change-Id: I1224643398a2084fcd5d70d2c04b105ed69c1f3d Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> --- src/3rdparty | 2 +- src/core/download_manager_delegate_qt.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/3rdparty b/src/3rdparty index 493fab1af..b3edbf2a8 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 493fab1afff5034cb5552455add3af3aaf41f9e9 +Subproject commit b3edbf2a84d96ed1d0307a8ef909b2f1f6c2a971 diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 948a62047..f0f0c93b9 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -79,7 +79,7 @@ DownloadManagerDelegateQt::~DownloadManagerDelegateQt() void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& callback) { - callback.Run(++m_currentId); + callback.Run(m_currentId); } download::DownloadItem *DownloadManagerDelegateQt::findDownloadById(quint32 downloadId) @@ -124,6 +124,8 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId) bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* item, const content::DownloadTargetCallback& callback) { + m_currentId = item->GetId(); + // Keep the forced file path if set, also as the temporary file, so the check for existence // will already return that the file exists. Forced file paths seem to be only used for // store downloads and other special downloads, so they might never end up here anyway. @@ -184,6 +186,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* if (webContents) adapterClient = static_cast<WebContentsDelegateQt *>(webContents->GetDelegate())->adapterClient(); + Q_ASSERT(m_currentId == item->GetId()); ProfileAdapterClient::DownloadItemInfo info = { item->GetId(), toQt(item->GetURL()), @@ -284,8 +287,9 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content if (web_contents) adapterClient = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())->adapterClient(); + // Chromium doesn't increase download ID when saving page. ProfileAdapterClient::DownloadItemInfo info = { - m_currentId + 1, + ++m_currentId, toQt(web_contents->GetURL()), download::DownloadItem::IN_PROGRESS, 0, /* totalBytes */ -- cgit v1.2.3 From ddfa2997939fc4de2993b3e0de2201eca534af61 Mon Sep 17 00:00:00 2001 From: Michal Klocek <michal.klocek@qt.io> Date: Thu, 28 Feb 2019 13:21:48 +0100 Subject: Fix destruction of qt quick profile after WebEngineContext gets deleted Issue takes place when QQmlApplicationEngine is a child of qApp. In case WebEngineContext gets destructed do not try to get default profile, which is anyway already gone. Task-number: QTBUG-74116 Change-Id: I24ea87baf677360a420d444b4c964feb722ab317 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> --- src/core/profile_adapter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 462be9f48..50a97a6ac 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -200,7 +200,8 @@ ProfileAdapter *ProfileAdapter::createDefaultProfileAdapter() ProfileAdapter *ProfileAdapter::defaultProfileAdapter() { - return WebEngineContext::current()->defaultProfileAdapter(); + WebEngineContext *context = WebEngineContext::current(); + return context ? context->defaultProfileAdapter() : nullptr; } QObject* ProfileAdapter::globalQObjectRoot() -- cgit v1.2.3 From 56fadb571f32b721d8b99554e6e38692009ec37f Mon Sep 17 00:00:00 2001 From: Michal Klocek <michal.klocek@qt.io> Date: Thu, 28 Feb 2019 10:49:22 +0100 Subject: Force destruction of webcontent client before profile adapter Currently users might forget to delete webcontent client before profile adapter. This might be nasty if users are not aware of default profile. Instead of asserting badly in chromium, clean up and release chromium resources. This avoids the crash, but might leak memory if users never deletes page. Task-number: QTBUG-74021 Change-Id: I66f466f169d12f7ee08866d505260dca47800bb0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> --- src/core/profile_adapter.cpp | 14 ++++++++++++++ src/core/profile_adapter.h | 5 +++++ src/core/profile_adapter_client.h | 2 ++ src/core/web_contents_adapter_client.h | 1 + src/webengine/api/qquickwebengineprofile.cpp | 15 ++++++--------- src/webengine/api/qquickwebengineprofile_p.h | 5 ++--- src/webengine/api/qquickwebengineview.cpp | 2 +- src/webengine/api/qquickwebengineview_p_p.h | 2 +- src/webenginewidgets/api/qwebenginepage.cpp | 22 +++++++++++++++++----- src/webenginewidgets/api/qwebenginepage_p.h | 1 + src/webenginewidgets/api/qwebengineprofile.cpp | 12 ++++++++++++ src/webenginewidgets/api/qwebengineprofile_p.h | 3 +++ 12 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 50a97a6ac..1b946949a 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -53,6 +53,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" @@ -92,6 +93,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(); @@ -547,6 +551,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(this)); diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 9bc92b54a..7ed5c13f5 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -73,6 +73,7 @@ class DownloadManagerDelegateQt; class ProfileQt; class UserResourceControllerHost; class VisitedLinksManagerQt; +class WebContentsAdapterClient; class QWEBENGINECORE_PRIVATE_EXPORT ProfileAdapter : public QObject { @@ -127,6 +128,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, @@ -211,6 +215,7 @@ private: VisitedLinksPolicy m_visitedLinksPolicy; QHash<QByteArray, QWebEngineUrlSchemeHandler *> m_customUrlSchemeHandlers; QList<ProfileAdapterClient*> m_clients; + QVector<WebContentsAdapterClient *> m_webContentsAdapterClients; int m_httpCacheMaxSize; Q_DISABLE_COPY(ProfileAdapter) diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h index 06051fab6..19af12ca4 100644 --- a/src/core/profile_adapter_client.h +++ b/src/core/profile_adapter_client.h @@ -142,6 +142,8 @@ public: virtual void downloadRequested(DownloadItemInfo &info) = 0; virtual void downloadUpdated(const DownloadItemInfo &info) = 0; + virtual void addWebContentsAdapterClient(WebContentsAdapterClient *adapter) = 0; + virtual void removeWebContentsAdapterClient(WebContentsAdapterClient *adapter) = 0; static QString downloadInterruptReasonToString(DownloadInterruptReason reason); }; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 55cbe13dd..28be33c23 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -478,6 +478,7 @@ public: virtual ProfileAdapter *profileAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; + virtual void releaseProfile() = 0; }; diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index b7abb13fc..73577a04c 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -163,11 +163,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. @@ -179,14 +174,16 @@ QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate() 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 diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h index 2b1a5b134..41e513f4c 100644 --- a/src/webengine/api/qquickwebengineprofile_p.h +++ b/src/webengine/api/qquickwebengineprofile_p.h @@ -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; @@ -98,7 +98,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 35f797cb1..53f12fa97 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -189,7 +189,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 diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index cbba9b568..bc7a05b67 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -90,7 +90,7 @@ public: QQuickWebEngineView *q_ptr; QQuickWebEngineViewPrivate(); ~QQuickWebEngineViewPrivate(); - void destroy(); + void releaseProfile() override; void initializeProfile(); QtWebEngineCore::UIDelegatesManager *ui(); diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index aa1f7be7c..fae34ae8d 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -256,12 +256,15 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) ensureInitialized(); wasShown(); }); + + profile->d_ptr->addWebContentsAdapterClient(this); } QWebEnginePagePrivate::~QWebEnginePagePrivate() { delete history; delete settings; + profile->d_ptr->removeWebContentsAdapterClient(this); } RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client) @@ -545,6 +548,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) @@ -967,11 +977,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 diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index eecbf0b65..a50a1972a 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -129,6 +129,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 runMouseLockPermissionRequest(const QUrl &securityOrigin) override; diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 0d12fdae1..929c2aaa1 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -262,6 +262,18 @@ void QWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) download->d_func()->update(info); } +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); +} + /*! Constructs a new off-the-record profile with the parent \a parent. diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h index 4a76f457f..cb43dace5 100644 --- a/src/webenginewidgets/api/qwebengineprofile_p.h +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -86,6 +86,9 @@ public: void downloadRequested(DownloadItemInfo &info) override; void downloadUpdated(const DownloadItemInfo &info) override; + void addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override; + void removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override; + private: QWebEngineProfile *q_ptr; QWebEngineSettings *m_settings; -- cgit v1.2.3