From f7103bc5fd099dd0a0772ef28930dd368e9fcf47 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 4 Dec 2017 10:29:25 +0100 Subject: Fix Message Bubble position for High-DPI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-64812 Change-Id: I9df71253cf6c541622e431b1ff444fc49269d0c3 Reviewed-by: Jüri Valdmann Reviewed-by: Allan Sandfeld Jensen --- src/core/web_contents_delegate_qt.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 7d4c671b0..26da6348a 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -79,6 +79,16 @@ namespace QtWebEngineCore { +static gfx::Rect rootViewToScreenRect(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view) +{ + RenderWidgetHostViewQt *rwhv = static_cast(web_contents->GetRenderWidgetHostView()); + if (!rwhv) + return gfx::Rect(); + content::ScreenInfo screenInfo; + rwhv->GetScreenInfo(&screenInfo); + return gfx::ScaleToEnclosingRect(anchor_in_root_view, 1 / screenInfo.device_scale_factor); +} + // Maps the LogSeverity defines in base/logging.h to the web engines message levels. static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(int32_t messageLevel) { if (messageLevel < 1) @@ -457,8 +467,10 @@ void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransitio void WebContentsDelegateQt::ShowValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view, const base::string16 &main_text, const base::string16 &sub_text) { - Q_UNUSED(web_contents); - m_viewClient->showValidationMessage(toQt(anchor_in_root_view), toQt(main_text), toQt(sub_text)); + gfx::Rect anchor = rootViewToScreenRect(web_contents, anchor_in_root_view); + if (anchor.IsEmpty()) + return; + m_viewClient->showValidationMessage(toQt(anchor), toQt(main_text), toQt(sub_text)); } void WebContentsDelegateQt::HideValidationMessage(content::WebContents *web_contents) @@ -469,8 +481,10 @@ void WebContentsDelegateQt::HideValidationMessage(content::WebContents *web_cont void WebContentsDelegateQt::MoveValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view) { - Q_UNUSED(web_contents); - m_viewClient->moveValidationMessage(toQt(anchor_in_root_view)); + gfx::Rect anchor = rootViewToScreenRect(web_contents, anchor_in_root_view); + if (anchor.IsEmpty()) + return; + m_viewClient->moveValidationMessage(toQt(anchor)); } void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool proceed, bool *proceed_to_fire_unload) -- cgit v1.2.3 From 9f798b787a2542688c30503d3f62fe2d7c4d5a72 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 8 Dec 2017 11:03:33 +0100 Subject: Refactor QWebEngineView tooltip handling Hide tooltip on empty text and make tooltips more fluent by ignoring duplicate requests. Task-number: QTBUG-64933 Change-Id: Ib82cb06ceda938548429cd694b849a2faadd2633 Reviewed-by: Allan Sandfeld Jensen --- src/webenginewidgets/api/qwebenginepage.cpp | 19 ++++++++++++++----- src/webenginewidgets/api/qwebengineview.cpp | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 75ec44b5d..3290a2a70 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -1553,12 +1553,21 @@ bool QWebEnginePagePrivate::isEnabled() const void QWebEnginePagePrivate::setToolTip(const QString &toolTipText) { - if (view) { - QString wrappedTip; - if (!toolTipText.isEmpty()) - wrappedTip = QLatin1String("

") % toolTipText.toHtmlEscaped().left(MaxTooltipLength) % QLatin1String("

"); - view->setToolTip(wrappedTip); + if (!view) + return; + + // Hide tooltip if shown. + if (toolTipText.isEmpty()) { + if (!view->toolTip().isEmpty()) + view->setToolTip(QString()); + + return; } + + // Update tooltip if text was changed. + QString wrappedTip = QLatin1String("

") % toolTipText.toHtmlEscaped().left(MaxTooltipLength) % QLatin1String("

"); + if (view->toolTip() != wrappedTip) + view->setToolTip(wrappedTip); } QMenu *QWebEnginePage::createStandardContextMenu() diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 0037f7e50..c03d9fde6 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -50,8 +50,9 @@ #include #include #include -#include #include +#include +#include QT_BEGIN_NAMESPACE @@ -321,6 +322,18 @@ bool QWebEngineView::event(QEvent *ev) ev->accept(); return true; } + + // Override QWidget's default ToolTip handler since it doesn't hide tooltip on empty text. + if (ev->type() == QEvent::ToolTip) { + if (!toolTip().isEmpty()) + QToolTip::showText(static_cast(ev)->globalPos(), toolTip(), this, QRect(), toolTipDuration()); + else + QToolTip::hideText(); + + ev->accept(); + return true; + } + return QWidget::event(ev); } -- cgit v1.2.3 From 2f7667ba5f58eefbc47ef8cbe319b12922bfafc9 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 7 Dec 2017 13:39:00 +0100 Subject: Check for null renderView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can according to documentation potentially be null, even if it might not happen in our cases. Task-number: QTBUG-63854 Change-Id: I76029c83fe32c163c2707568fe81b7590a79b4fe Reviewed-by: Alexandru Croitor Reviewed-by: Michael Brüning Reviewed-by: Viktor Engelmann --- src/core/renderer/user_resource_controller.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index b172c762b..36125d189 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -129,6 +129,8 @@ void UserResourceController::RenderViewObserverHelper::runScripts(UserScriptData void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame) { content::RenderView *renderView = content::RenderView::FromWebView(frame->view()); + if (!renderView) + return; const bool isMainFrame = (frame == renderView->GetWebView()->mainFrame()); QList scriptsToRun = m_viewUserScriptMap.value(globalScriptsIndex).toList(); @@ -192,7 +194,8 @@ void UserResourceController::RenderViewObserverHelper::FrameDetached(blink::WebF void UserResourceController::RenderViewObserverHelper::OnDestruct() { - UserResourceController::instance()->renderViewDestroyed(render_view()); + if (content::RenderView *view = render_view()) + UserResourceController::instance()->renderViewDestroyed(view); } bool UserResourceController::RenderViewObserverHelper::OnMessageReceived(const IPC::Message &message) @@ -209,17 +212,20 @@ bool UserResourceController::RenderViewObserverHelper::OnMessageReceived(const I void UserResourceController::RenderViewObserverHelper::onUserScriptAdded(const UserScriptData &script) { - UserResourceController::instance()->addScriptForView(script, render_view()); + if (content::RenderView *view = render_view()) + UserResourceController::instance()->addScriptForView(script, view); } void UserResourceController::RenderViewObserverHelper::onUserScriptRemoved(const UserScriptData &script) { - UserResourceController::instance()->removeScriptForView(script, render_view()); + if (content::RenderView *view = render_view()) + UserResourceController::instance()->removeScriptForView(script, view); } void UserResourceController::RenderViewObserverHelper::onScriptsCleared() { - UserResourceController::instance()->clearScriptsForView(render_view()); + if (content::RenderView *view = render_view()) + UserResourceController::instance()->clearScriptsForView(view); } UserResourceController *UserResourceController::instance() -- cgit v1.2.3 From 260e9dd9b98c2bc90229f7d2f7aba8cc0029d24d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 12 Dec 2017 09:55:33 +0100 Subject: Bump version Change-Id: I88eb85ea51a5d0b0b98b21e7213ed963995b255a --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index efbcc0615..2e43b6509 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ QTWEBENGINE_OUT_ROOT = $$shadowed($$PWD) load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.9.3 +MODULE_VERSION = 5.9.4 -- cgit v1.2.3 From fda2f858bef4d25c711f02fbb0f2aa0127a6c3b5 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 7 Dec 2017 16:09:25 +0100 Subject: Fix favicon update from JavaScript Task-number: QTBUG-64967 Change-Id: Ida79d6cdb682d510e9a2e91e3e3ca263acf34a99 Reviewed-by: Viktor Engelmann --- src/core/web_contents_delegate_qt.cpp | 3 + tests/auto/quick/qmltests/data/tst_favicon.qml | 91 +++++++++++++++++----- .../tst_qwebenginefaviconmanager.cpp | 30 +++++++ 3 files changed, 103 insertions(+), 21 deletions(-) diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 26da6348a..4fe877e67 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -289,6 +289,9 @@ void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vectorresetCandidates(); m_faviconManager->update(faviconCandidates); } diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index f8ad998ef..cc000c7fc 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -54,6 +54,35 @@ TestWebEngineView { return url.toString().substring(16) } + function getFaviconPixel(faviconImage) { + var grabImage = Qt.createQmlObject(" + import QtQuick 2.5\n + Image { }", test) + var faviconCanvas = Qt.createQmlObject(" + import QtQuick 2.5\n + Canvas { }", test) + + test.tryVerify(function() { return faviconImage.status == Image.Ready }); + faviconImage.grabToImage(function(result) { + grabImage.source = result.url + }); + test.tryVerify(function() { return grabImage.status == Image.Ready }); + + faviconCanvas.width = faviconImage.width; + faviconCanvas.height = faviconImage.height; + var ctx = faviconCanvas.getContext("2d"); + ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height); + var imageData = ctx.getImageData(Math.round(faviconCanvas.width/2), + Math.round(faviconCanvas.height/2), + faviconCanvas.width, + faviconCanvas.height); + + grabImage.destroy(); + faviconCanvas.destroy(); + + return imageData.data; + } + SignalSpy { id: iconChangedSpy target: webEngineView @@ -284,12 +313,6 @@ TestWebEngineView { var faviconImage = Qt.createQmlObject(" import QtQuick 2.5\n Image { sourceSize: Qt.size(width, height) }", test) - var grabImage = Qt.createQmlObject(" - import QtQuick 2.5\n - Image { }", test) - var faviconCanvas = Qt.createQmlObject(" - import QtQuick 2.5\n - Canvas { }", test) compare(iconChangedSpy.count, 0) @@ -302,27 +325,53 @@ TestWebEngineView { faviconImage.width = row.size faviconImage.height = row.size faviconImage.source = webEngineView.icon - verify(_waitFor(function() { return faviconImage.status == Image.Ready } )) - faviconImage.grabToImage(function(result) { - grabImage.source = result.url - }) - verify(_waitFor(function() { return grabImage.status == Image.Ready } )) + var pixel = getFaviconPixel(faviconImage); + compare(pixel[0], row.value) - faviconCanvas.width = faviconImage.width - faviconCanvas.height = faviconImage.height - var ctx = faviconCanvas.getContext("2d") - ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height) + faviconImage.destroy() + } - var center = Math.round(row.size/2) - var imageData = ctx.getImageData(center, center, center, center) - var pixel = imageData.data + function test_dynamicFavicon() { + var faviconImage = Qt.createQmlObject(" + import QtQuick 2.5\n + Image { width: 16; height: 16; sourceSize: Qt.size(width, height); }", test) + faviconImage.source = Qt.binding(function() { return webEngineView.icon; }); - compare(pixel[0], row.value) + var colors = [ + {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==", "r": 255, "g": 0, "b": 0}, + {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg==", "r": 0, "g": 255, "b": 0}, + {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg==", "r": 0, "g": 0, "b": 255}, + ]; + var pixel; + + compare(iconChangedSpy.count, 0); + webEngineView.loadHtml( + "" + + "" + + "" + ); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(iconChangedSpy, "count", 1); + + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 0); + compare(pixel[1], 0); + compare(pixel[2], 0); + + for (var i = 0; i < colors.length; ++i) { + iconChangedSpy.clear(); + runJavaScript("document.getElementsByTagName('link')[0].href = 'data:image/png;base64," + colors[i]["url"] + "';"); + tryCompare(faviconImage, "source", "image://favicon/data:image/png;base64," + colors[i]["url"]); + compare(iconChangedSpy.count, 1); + + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], colors[i]["r"]); + compare(pixel[1], colors[i]["g"]); + compare(pixel[2], colors[i]["b"]); + } faviconImage.destroy() - grabImage.destroy() - faviconCanvas.destroy() } } } diff --git a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp index 38311cad2..8dcdb9f7a 100644 --- a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp +++ b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp @@ -60,6 +60,7 @@ private Q_SLOTS: void downloadIconsDisabled(); void downloadTouchIconsEnabled_data(); void downloadTouchIconsEnabled(); + void dynamicFavicon(); private: QWebEngineView *m_view; @@ -473,6 +474,35 @@ void tst_QWebEngineFaviconManager::downloadTouchIconsEnabled() QVERIFY(icon.availableSizes().contains(expectedIconSize)); } +void tst_QWebEngineFaviconManager::dynamicFavicon() +{ + QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool))); + QSignalSpy iconUrlChangedSpy(m_page, SIGNAL(iconUrlChanged(QUrl))); + QSignalSpy iconChangedSpy(m_page, SIGNAL(iconChanged(QIcon))); + + QMap colors; + colors.insert(Qt::red, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==")); + colors.insert(Qt::green, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg==")); + colors.insert(Qt::blue, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg==")); + + m_page->setHtml("" + "" + ""); + QTRY_COMPARE(loadFinishedSpy.count(), 1); + QTRY_COMPARE(iconUrlChangedSpy.count(), 1); + QTRY_COMPARE(iconChangedSpy.count(), 1); + + QCOMPARE(m_page->icon().pixmap(1, 1).toImage().pixelColor(0, 0), QColor(Qt::black)); + + for (Qt::GlobalColor color : colors.keys()) { + iconChangedSpy.clear(); + evaluateJavaScriptSync(m_page, "document.getElementsByTagName('link')[0].href = 'data:image/png;base64," + colors[color] + "';"); + QTRY_COMPARE(iconChangedSpy.count(), 1); + QTRY_COMPARE(m_page->iconUrl().toString(), QString("data:image/png;base64," + colors[color])); + QCOMPARE(m_page->icon().pixmap(1, 1).toImage().pixelColor(0, 0), QColor(color)); + } +} + QTEST_MAIN(tst_QWebEngineFaviconManager) #include "tst_qwebenginefaviconmanager.moc" -- cgit v1.2.3 From 8f7ae2efd14f837914512e2072ccf5d942a90b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Tue, 12 Dec 2017 10:02:01 +0100 Subject: Fix QSGSoftwareLayer rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Software layers (added in qtdeclarative 5.8) also need updating. Task-number: QTBUG-62867 Change-Id: If7a941d7e360871822e1776cde3845abcb1f7efa Reviewed-by: Michael Brüning --- src/core/delegated_frame_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 7547e24f7..8ed88ea5d 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -753,6 +753,7 @@ void DelegatedFrameNode::preprocess() if (!mailboxesToFetch.isEmpty()) fetchAndSyncMailboxes(mailboxesToFetch); +#endif // Then render any intermediate RenderPass in order. typedef QPair > Pair; @@ -762,7 +763,6 @@ void DelegatedFrameNode::preprocess() // Proceed with the actual update. pair.second->updateTexture(); } -#endif } static YUVVideoMaterial::ColorSpace toQt(cc::YUVVideoDrawQuad::ColorSpace color_space) -- cgit v1.2.3 From aead0729aaab970b95220bd864520d7635d7a33f Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 14 Dec 2017 11:21:31 +0100 Subject: Fix invalid access in currentTimeForEvent The method currentTimeForEvent() tried to access the timestamp() method for a QEvent::Leave event. Leave events are regular QEvents and not QInputEvents, and thus have no such method. Change-Id: Iecc20d239b0e2a5b39b995dabdd7ca8fb44491aa Reviewed-by: Allan Sandfeld Jensen --- src/core/web_event_factory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 919ba730f..7245e29e6 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -1023,7 +1023,8 @@ static inline double currentTimeForEvent(const QEvent *event) { Q_ASSERT(event); - if (const QInputEvent *inputEvent = static_cast(event)) { + if (event->type() != QEvent::Leave) { + const QInputEvent *inputEvent = static_cast(event); if (inputEvent->timestamp()) return static_cast(inputEvent->timestamp()) / 1000; } -- cgit v1.2.3 From d4b3d9457bbe090c4ecc0d5a7d70e7bb08b22b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Thu, 14 Dec 2017 12:43:16 +0100 Subject: Turn off caching of images rendered for the printer When printing very large documents using the QPrinter-based API, it was possible to run out of memory because the images that pdfium has generated was cached for reuse when printing multiple copies of the document. Caching the images is now removed as printing multiple copies is not the default use case and is nowadays often also handled by the printer itself. Task-number: QTBUG-58400 Change-Id: I27bd17b33a839a845ca1b387b0c3bd0466b6592f Reviewed-by: Allan Sandfeld Jensen --- src/core/pdfium_document_wrapper_qt.cpp | 20 +++++++------------- src/core/pdfium_document_wrapper_qt.h | 6 +++--- src/webenginewidgets/api/qwebenginepage.cpp | 8 +++++--- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/core/pdfium_document_wrapper_qt.cpp b/src/core/pdfium_document_wrapper_qt.cpp index 7c43c77db..ccf8e15fe 100644 --- a/src/core/pdfium_document_wrapper_qt.cpp +++ b/src/core/pdfium_document_wrapper_qt.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -124,7 +124,9 @@ private: }; -PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize& imageSize, const char *password) +PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t size, + const QSize& imageSize, + const char *password) : m_imageSize(imageSize * 2.0) { Q_ASSERT(pdfData); @@ -148,21 +150,13 @@ QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t index) return QImage(); } - PdfiumPageWrapperQt *pageWrapper = nullptr; - if (!m_cachedPages.contains(index)) { - pageWrapper = new PdfiumPageWrapperQt(m_documentHandle, index, - m_imageSize.width(), m_imageSize.height()); - m_cachedPages.insert(index, pageWrapper); - } else { - pageWrapper = m_cachedPages.value(index); - } - - return pageWrapper->image(); + PdfiumPageWrapperQt pageWrapper(m_documentHandle, index, + m_imageSize.width(), m_imageSize.height()); + return pageWrapper.image(); } PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt() { - qDeleteAll(m_cachedPages); FPDF_CloseDocument(m_documentHandle); if (--m_libraryUsers == 0) FPDF_DestroyLibrary(); diff --git a/src/core/pdfium_document_wrapper_qt.h b/src/core/pdfium_document_wrapper_qt.h index 42ac94a28..28c490ae5 100644 --- a/src/core/pdfium_document_wrapper_qt.h +++ b/src/core/pdfium_document_wrapper_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -53,7 +53,8 @@ class PdfiumPageWrapperQt; class QWEBENGINE_EXPORT PdfiumDocumentWrapperQt { public: - PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize &imageSize, const char *password = nullptr); + PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize &imageSize, + const char *password = nullptr); virtual ~PdfiumDocumentWrapperQt(); QImage pageAsQImage(size_t index); int pageCount() const { return m_pageCount; } @@ -63,7 +64,6 @@ private: int m_pageCount; void *m_documentHandle; QSize m_imageSize; - QHash m_cachedPages; }; } // namespace QtWebEngineCore diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 3290a2a70..ae6276fdc 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -143,9 +143,11 @@ static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) QPainter painter; if (!painter.begin(&printer)) { #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - qWarning("Failure to print on printer %ls: Could not open printer for painting.", qUtf16Printable(printer.printerName())); + qWarning("Failure to print on printer %ls: Could not open printer for painting.", + qUtf16Printable(printer.printerName())); #else - qWarning("Failure to print on printer %s: Could not open printer for painting.", qPrintable(printer.printerName())); + qWarning("Failure to print on printer %s: Could not open printer for painting.", + qPrintable(printer.printerName())); #endif return false; } -- cgit v1.2.3 From b9a12f07441d345797787f7142a240a386e513b2 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 4 Dec 2017 11:27:03 +0100 Subject: Hardcode default argument for mimetype in ::setContent The docs were wrong in that the default is actually text/plain with US-ASCII encoding (see e.g. data_url_unittest.cc). Anyhow, saying it might change in the future does not help anyone, and is actually a potential security risk - see e.g. the discussion about 'magic' in QTextEdit::setText(). Because of this, it's unlikely that Chromium ever changes the default. Anyhow, we can as well hardcode the default, and document it then. Change-Id: I949111598a30fa69d152d3e98d76e9d96df92d54 Reviewed-by: Leena Miettinen Reviewed-by: Viktor Engelmann Reviewed-by: Allan Sandfeld Jensen --- src/core/web_contents_adapter.cpp | 8 +++++--- src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc | 5 ++--- src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc | 5 ++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 1930e7a0e..53bb55b6a 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -591,9 +591,11 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT { Q_D(WebContentsAdapter); QByteArray encodedData = data.toPercentEncoding(); - std::string urlString("data:"); - urlString.append(mimeType.toStdString()); - urlString.append(","); + std::string urlString; + if (!mimeType.isEmpty()) + urlString = std::string("data:") + mimeType.toStdString() + std::string(","); + else + urlString = std::string("data:text/plain;charset=US-ASCII,"); urlString.append(encodedData.constData(), encodedData.length()); GURL dataUrlToLoad(urlString); diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index 715fce6d0..b7c876ddd 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -638,9 +638,8 @@ /*! \fn void QWebEnginePage::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) - Sets the content of this page to \a data. If the \a mimeType argument - is empty, it is currently assumed that the content is HTML but in future versions we may introduce - auto-detection. + Sets the content of the web page to \a data. If the \a mimeType argument + is empty, it is assumed that the content is \c{text/plain,charset=US-ASCII}. External objects referenced in the content are located relative to \a baseUrl. diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index e54c5d507..9de0609b7 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -152,9 +152,8 @@ /*! \fn void QWebEngineView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) - Sets the content of the web view to the specified content \a data. If the \a mimeType argument - is empty, it is currently assumed that the content is HTML but in future versions we may - introduce auto-detection. + Sets the content of the web view to \a data. If the \a mimeType argument + is empty, it is assumed that the content is \c{text/plain,charset=US-ASCII}. External objects referenced in the content are located relative to \a baseUrl. -- cgit v1.2.3 From 5b160be90599d13707610f253f541ff0c97c08e3 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 18 Dec 2017 13:17:34 +0100 Subject: Update Chromium 2ee59e45bd Fix hanging of process when application is closed too fast cdecf3ca05 Silence most spurious warnings with gcc Change-Id: I220ec63538e13cd5e71552a5f6d99de564a3f0ea Reviewed-by: Allan Sandfeld Jensen --- src/3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index a83d8cdb8..2ee59e45b 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit a83d8cdb8d8361eadb86ac48d020486f56543114 +Subproject commit 2ee59e45bd9c26ab26ac221696367584020b00ed -- cgit v1.2.3 From 17ecc4e7e0c88d891e1b18d5810a7ac2fd0b83ba Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 12 Mar 2017 22:59:59 +0100 Subject: Doc: QWebEngineUrlRequestJob: mention when to delete the device It's used from another thread, so it shouldn't be deleted immediately, and it's not deleted by the QtWebEngine code, so tell people to do it themselves at the right time. Change-Id: I54786be320f5fe82f144e7b1c2e6137260d9ceab Reviewed-by: Leena Miettinen Reviewed-by: Allan Sandfeld Jensen --- src/core/api/qwebengineurlrequestjob.cpp | 7 +++++++ .../qwebengineprofile/tst_qwebengineprofile.cpp | 20 +++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp index 1db23f6ab..e95f58863 100644 --- a/src/core/api/qwebengineurlrequestjob.cpp +++ b/src/core/api/qwebengineurlrequestjob.cpp @@ -114,6 +114,13 @@ QByteArray QWebEngineUrlRequestJob::requestMethod() const /*! Replies to the request with \a device and the MIME type \a contentType. + + The device should remain available at least as long as the job exists. + When calling this method with a newly constructed device, one solution is to + make the device delete itself when closed, like this: + \code + connect(device, &QIODevice::aboutToClose, device, &QObject::deleteLater); + \endcode */ void QWebEngineUrlRequestJob::reply(const QByteArray &contentType, QIODevice *device) { diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 093bc2e43..639a8456f 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -162,20 +162,25 @@ public: class ReplyingUrlSchemeHandler : public QWebEngineUrlSchemeHandler { - QBuffer m_buffer; - QByteArray m_bufferData; public: ReplyingUrlSchemeHandler(QObject *parent = nullptr) : QWebEngineUrlSchemeHandler(parent) { - m_buffer.setBuffer(&m_bufferData); + } + ~ReplyingUrlSchemeHandler() + { } void requestStarted(QWebEngineUrlRequestJob *job) { - m_bufferData = job->requestUrl().toString().toUtf8(); - job->reply("text/plain;charset=utf-8", &m_buffer); + QBuffer *buffer = new QBuffer; + buffer->setData(job->requestUrl().toString().toUtf8()); + connect(buffer, &QIODevice::aboutToClose, buffer, &QObject::deleteLater); + m_buffers.append(buffer); + job->reply("text/plain;charset=utf-8", buffer); } + + QList> m_buffers; }; static bool loadSync(QWebEngineView *view, const QUrl &url, int timeout = 5000) @@ -234,6 +239,11 @@ void tst_QWebEngineProfile::urlSchemeHandlers() url = QUrl(QStringLiteral("aviancarrier:inspector.mortensen@politistyrke.dk")); QVERIFY(loadSync(&view, url)); QCOMPARE(toPlainTextSync(view.page()), url.toString()); + + // Check that all buffers got deleted + QCOMPARE(gopherHandler.m_buffers.count(), 2); + for (int i = 0; i < gopherHandler.m_buffers.count(); ++i) + QVERIFY(gopherHandler.m_buffers.at(i).isNull()); } class FailingUrlSchemeHandler : public QWebEngineUrlSchemeHandler -- cgit v1.2.3 From 6f242a9389369242b23a61dcb59fc610dc27bb05 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Fri, 22 Dec 2017 13:50:45 +0100 Subject: Remove QT_LIBDIR_EGL/GLES2 leftovers Since e812237b69 we do not longer use QT_LIBDIR_EGL and QT_LIBDIR_GLES2 to dynamically load gl libraries. Remove leftovers from gn generator. Task-number: QTBUG-65442 Change-Id: I045242b49be411373d36eb9c333916d27b0f169d Reviewed-by: Viktor Engelmann --- mkspecs/features/gn_generator.prf | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/mkspecs/features/gn_generator.prf b/mkspecs/features/gn_generator.prf index 072b0444e..a54a96c5a 100644 --- a/mkspecs/features/gn_generator.prf +++ b/mkspecs/features/gn_generator.prf @@ -148,17 +148,6 @@ for (define, DEFINES): { define = $$replace(define,\',) GN_CONTENTS += " \"$$define\"," } -!isEmpty(QT_SYSROOT) { - !isEmpty(QMAKE_LIBDIR_EGL): - GN_CONTENTS += " \"QT_LIBDIR_EGL=\\\"$${QMAKE_DIR_SEP}$$relative_path($$QMAKE_LIBDIR_EGL, $$[QT_SYSROOT])\\\"\"," - !isEmpty(QMAKE_LIBDIR_OPENGL_ES2) - GN_CONTENTS += " \"QT_LIBDIR_GLES2=\\\"$${QMAKE_DIR_SEP}$$relative_path($$QMAKE_LIBDIR_OPENGL_ES2, $$[QT_SYSROOT])\\\"\"," -} else { - !isEmpty(QMAKE_LIBDIR_EGL): - GN_CONTENTS += " \"QT_LIBDIR_EGL=\\\"$$QMAKE_LIBDIR_EGL\\\"\"," - !isEmpty(QMAKE_LIBDIR_OPENGL_ES2) - GN_CONTENTS += " \"QT_LIBDIR_GLES2=\\\"$$QMAKE_LIBDIR_OPENGL_ES2\\\"\"," -} GN_CONTENTS += " ]" # Source files to compile -- cgit v1.2.3 From 196ae04aa7c9b274880409fb38a050db99197900 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 13 Dec 2017 12:10:39 +0100 Subject: Initialize ScreenWin singleton to fix dpi glitches on Windows Static function ScreenWin::GetSystemMetricsInDIP returned an incorrect (already scaled) size for the scrollbars. To take system scaling into account an instance of the ScreenWin singleton has to be created once. So let's use ScreenWin directly, instead of DesktopScreenQt, which is just a mock object anyway. [ChangeLog][Windows] Fixed issues with too large scrollbars on Hi-DPI monitors. Task-number: QTBUG-60705 Change-Id: I7cbc10e98b2a5217b0a0e78afb32818c1cb199d7 Reviewed-by: Alexandru Croitor Reviewed-by: Viktor Engelmann --- src/core/content_browser_client_qt.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index d446d8ff4..14ec42fb7 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -102,6 +102,10 @@ #include "web_engine_context.h" #include "web_engine_library_info.h" +#if defined(Q_OS_WIN) +#include "ui/display/win/screen_win.h" +#endif + #if defined(Q_OS_LINUX) #include "global_descriptors_qt.h" #include "ui/base/resource/resource_bundle.h" @@ -292,8 +296,11 @@ public: { base::ThreadRestrictions::SetIOAllowed(true); // Like ChromeBrowserMainExtraPartsViews::PreCreateThreads does. +#if defined(Q_OS_WIN) + display::Screen::SetScreenInstance(new display::win::ScreenWin); +#else display::Screen::SetScreenInstance(new DesktopScreenQt); - +#endif return 0; } -- cgit v1.2.3 From 9ef3a8263098c6a32db8b824aabf85587d1f1140 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 16 Nov 2017 14:36:33 +0100 Subject: Fix access after free on shutdown After we keep around the browser-context after the profile is deleted it was keeping pointers to deleted objects and would sometimes use them on shutdown. Change-Id: Ib67d0ee0b27cb1a1b64d9b8b4c348ed418b9bbc3 Reviewed-by: Peter Varga Reviewed-by: Michal Klocek --- src/core/browser_context_adapter.cpp | 14 ++++++++++++-- src/core/browser_context_adapter.h | 2 ++ src/core/web_engine_context.cpp | 21 ++++++++++++++++----- src/core/web_engine_context.h | 5 +++-- src/webenginewidgets/api/qwebengineprofile.cpp | 9 +++++++++ src/webenginewidgets/api/qwebengineprofile_p.h | 2 ++ 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index bec76ad81..41b5b1932 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -41,6 +41,7 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_manager.h" #include "browser_context_qt.h" #include "content_client_qt.h" @@ -100,10 +101,17 @@ BrowserContextAdapter::BrowserContextAdapter(const QString &storageName) } BrowserContextAdapter::~BrowserContextAdapter() +{ + Q_ASSERT(!m_downloadManagerDelegate); +} + +void BrowserContextAdapter::shutdown() { m_browserContext->ShutdownStoragePartitions(); - if (m_downloadManagerDelegate) - content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, m_downloadManagerDelegate.take()); + if (m_downloadManagerDelegate) { + m_browserContext->GetDownloadManager(m_browserContext.data())->Shutdown(); + m_downloadManagerDelegate.reset(); + } BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(m_browserContext.data()); } @@ -177,6 +185,8 @@ void BrowserContextAdapter::addClient(BrowserContextAdapterClient *adapterClient void BrowserContextAdapter::removeClient(BrowserContextAdapterClient *adapterClient) { m_clients.removeOne(adapterClient); + if (m_clients.isEmpty() && this != WebEngineContext::current()->m_defaultBrowserContext.data()) + shutdown(); } void BrowserContextAdapter::cancelDownload(quint32 downloadId) diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index f6ebfd51c..2e7b66a7e 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -73,6 +73,8 @@ public: static QSharedPointer defaultContext(); static QObject* globalQObjectRoot(); + void shutdown(); + VisitedLinksManagerQt *visitedLinksManager(); DownloadManagerDelegateQt *downloadManagerDelegate(); diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 900b82eb9..6a8c8ae73 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -117,7 +117,11 @@ void destroyContext() // Before destroying MessageLoop via destroying BrowserMainRunner destructor // WebEngineContext's pointer is used. sContext->destroy(); - sContext = 0; +#if !defined(NDEBUG) + if (!sContext->HasOneRef()) + qWarning("WebEngineContext leaked on exit, likely due to leaked WebEngine View or Page"); +#endif + sContext = nullptr; s_destroyed = true; } @@ -193,19 +197,26 @@ void WebEngineContext::destroy() { if (m_devtoolsServer) m_devtoolsServer->stop(); - delete m_globalQObject; - m_globalQObject = 0; base::MessagePump::Delegate *delegate = m_runLoop->loop_; // Flush the UI message loop before quitting. while (delegate->DoWork()) { } + + if (m_defaultBrowserContext) + m_defaultBrowserContext->shutdown(); + // Delete the global object and thus custom profiles + delete m_globalQObject; + m_globalQObject = nullptr; + // Handle any events posted by browser-context shutdown. + while (delegate->DoWork()) { } + GLContextHelper::destroy(); - m_devtoolsServer.reset(0); + m_devtoolsServer.reset(); m_runLoop->AfterRun(); // Force to destroy RenderProcessHostImpl by destroying BrowserMainRunner. // RenderProcessHostImpl should be destroyed before WebEngineContext since // default BrowserContext might be used by the RenderprocessHostImpl's destructor. - m_browserRunner.reset(0); + m_browserRunner.reset(); // Drop the false reference. sContext->Release(); diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 92c45e260..1b4be48b1 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -80,7 +80,7 @@ class WebEngineContext : public base::RefCounted { public: static scoped_refptr current(); - QSharedPointer defaultBrowserContext(); + QSharedPointer defaultBrowserContext(); QObject *globalQObject(); #if BUILDFLAG(ENABLE_BASIC_PRINTING) printing::PrintJobManager* getPrintJobManager(); @@ -90,6 +90,7 @@ public: private: friend class base::RefCounted; + friend class BrowserContextAdapter; WebEngineContext(); ~WebEngineContext(); @@ -98,7 +99,7 @@ private: std::unique_ptr m_contentRunner; std::unique_ptr m_browserRunner; QObject* m_globalQObject; - QSharedPointer m_defaultBrowserContext; + QSharedPointer m_defaultBrowserContext; std::unique_ptr m_devtoolsServer; #if BUILDFLAG(ENABLE_BASIC_PRINTING) std::unique_ptr m_printJobManager; diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index f120ae51e..e1e72aa45 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -154,12 +154,19 @@ QWebEngineBrowserContext::QWebEngineBrowserContext(QSharedPointersetRequestInterceptor(nullptr); browserContextRef->removeClient(m_profile); + m_profile = 0; } QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer browserContext) @@ -181,6 +188,8 @@ QWebEngineProfilePrivate::~QWebEngineProfilePrivate() } m_ongoingDownloads.clear(); + if (m_browserContext) + m_browserContext->shutdown(); } QSharedPointer QWebEngineProfilePrivate::browserContext() const diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h index 067a5bd7e..61ad4f81c 100644 --- a/src/webenginewidgets/api/qwebengineprofile_p.h +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -76,6 +76,8 @@ public: QWebEngineBrowserContext(QSharedPointer browserContext, QWebEngineProfilePrivate *profile); ~QWebEngineBrowserContext(); + void shutdown(); + QSharedPointer browserContextRef; private: -- cgit v1.2.3