From b6fda272f56b147664970581fa84e68cbb736681 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Mon, 27 May 2024 17:08:34 +0200 Subject: [PATCH 001/341] Add QWebEngineFrame::printToPdf Provide API calls to (1) save to file (QString) and (2) get the bytes in a callback. Change-Id: I0ff44a25328b99080491b8c3b36a7b632c065131 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit ece3b065828bc6ca09dd2ad8654b48cdaddf1178) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineframe.cpp | 63 ++++++++++ src/core/api/qwebengineframe.h | 4 + src/core/api/qwebenginepage.cpp | 16 +-- src/core/api/qwebenginepage_p.h | 6 +- src/core/printing/print_view_manager_qt.cpp | 41 +++--- src/core/printing/print_view_manager_qt.h | 15 +-- src/core/web_contents_adapter.cpp | 15 ++- src/core/web_contents_adapter.h | 6 +- src/core/web_contents_adapter_client.h | 5 +- .../api/qquickwebengineview.cpp | 14 ++- .../api/qquickwebengineview_p_p.h | 6 +- .../doc/src/webengineframe.qdoc | 24 ++++ src/webenginewidgets/api/qwebengineview.cpp | 3 +- .../auto/core/qwebengineframe/CMakeLists.txt | 2 + .../resources/printing-inner-document.html | 7 ++ .../resources/printing-outer-document.html | 8 ++ .../qwebengineframe/tst_qwebengineframe.cpp | 119 ++++++++++++++++++ tests/auto/quick/publicapi/tst_publicapi.cpp | 2 + 18 files changed, 299 insertions(+), 57 deletions(-) create mode 100644 tests/auto/core/qwebengineframe/resources/printing-inner-document.html create mode 100644 tests/auto/core/qwebengineframe/resources/printing-outer-document.html diff --git a/src/core/api/qwebengineframe.cpp b/src/core/api/qwebengineframe.cpp index 1eedc4b9254..52fd5e60273 100644 --- a/src/core/api/qwebengineframe.cpp +++ b/src/core/api/qwebengineframe.cpp @@ -5,6 +5,8 @@ #include "qwebenginescript.h" #include +#include +#include #include "web_contents_adapter_client.h" #include "web_contents_adapter.h" @@ -175,6 +177,67 @@ void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, runJavaScript(script, worldId, wrappedCallback); } +/*! + Renders the current content of the frame into a PDF document and saves it in the location + specified in \a filePath. Printing uses a page size of A4, portrait layout, and includes the + full range of pages. + + This method issues an asynchronous request for printing the web page into a PDF and returns + immediately. To be informed about the result of the request, connect to the \l + QWebEnginePage::pdfPrintingFinished() signal. + + \note The \l QWebEnginePage::Stop web action can be used to interrupt this asynchronous + operation. + + If a file already exists at the provided file path, it will be overwritten. + + \sa QWebEnginePage::pdfPrintingFinished() + */ +void QWebEngineFrame::printToPdf(const QString &filePath) +{ + QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); + m_adapterClient->printToPdf(filePath, layout, QPageRanges(), m_id); +} + +/*! + Renders the current content of the frame into a PDF document and returns a byte array containing + the PDF data as parameter to \a callback. Printing uses a page size of A4, portrait layout, and + includes the full range of pages. + + The \a callback must take a const reference to a QByteArray as parameter. If printing was + successful, this byte array will contain the PDF data, otherwise, the byte array will be empty. + + \note The \l QWebEnginePage::Stop web action can be used to interrupt this operation. +*/ +void QWebEngineFrame::printToPdf(const std::function &callback) +{ + std::function wrappedCallback = [callback](QSharedPointer result) { + if (callback) + callback(result ? *result : QByteArray()); + }; + QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); + m_adapterClient->printToPdf(std::move(wrappedCallback), layout, QPageRanges(), m_id); +} + +void QWebEngineFrame::printToPdf(const QJSValue &callback) +{ + std::function)> wrappedCallback; + if (!callback.isUndefined()) { + const QObject *holdingObject = m_adapterClient->holdingQObject(); + wrappedCallback = [holdingObject, callback](QSharedPointer result) { + if (auto engine = qmlEngine(holdingObject)) { + QJSValueList args; + args.append(engine->toScriptValue(result ? *result : QByteArray())); + callback.call(args); + } else { + qWarning("No QML engine found to execute runJavaScript() callback"); + } + }; + } + QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); + m_adapterClient->printToPdf(std::move(wrappedCallback), layout, QPageRanges(), m_id); +} + /*! \fn bool QWebEngineFrame::operator==(const QWebEngineFrame &left, const QWebEngineFrame &right) noexcept Returns \c{true} if \a left and \a right represent the same frame in the same web page, diff --git a/src/core/api/qwebengineframe.h b/src/core/api/qwebengineframe.h index 3042fbae074..34b72e08ea1 100644 --- a/src/core/api/qwebengineframe.h +++ b/src/core/api/qwebengineframe.h @@ -49,6 +49,10 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFrame Q_INVOKABLE void runJavaScript(const QString &script, quint32 worldId, const QJSValue &callback); + Q_INVOKABLE void printToPdf(const QString &filePath); + void printToPdf(const std::function &callback); + Q_INVOKABLE void printToPdf(const QJSValue &callback); + friend inline bool comparesEqual(const QWebEngineFrame &lhs, const QWebEngineFrame &rhs) noexcept { diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 7c6a53d0f08..d7ab7030598 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -275,15 +275,17 @@ void QWebEnginePagePrivate::loadFinished(QWebEngineLoadingInfo info) } void QWebEnginePagePrivate::printToPdf(const QString &filePath, const QPageLayout &layout, - const QPageRanges &ranges) + const QPageRanges &ranges, quint64 frameId) { - adapter->printToPDF(layout, ranges, filePath); + adapter->printToPDF(layout, ranges, filePath, frameId); } void QWebEnginePagePrivate::printToPdf(std::function)> &&callback, - const QPageLayout &layout, const QPageRanges &ranges) + const QPageLayout &layout, const QPageRanges &ranges, + quint64 frameId) { - adapter->printToPDFCallbackResult(std::move(callback), layout, ranges); + adapter->printToPDFCallbackResult(std::move(callback), layout, ranges, /*colorMode*/ true, + /*useCustomMargins*/ true, frameId); } void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool success) @@ -1692,7 +1694,7 @@ void QWebEnginePagePrivate::printRequested() This signal is emitted when the JavaScript \c{window.print()} method is called on \a frame. If the frame is the main frame, \c{printRequested} is emitted instead. - \sa printRequested(), printToPdf() + \sa printRequested(), printToPdf(), QWebEngineFrame::printToPdf() */ void QWebEnginePagePrivate::printRequestedByFrame(quint64 frameId) @@ -2330,7 +2332,7 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &layo #if QT_CONFIG(webengine_printing_and_pdf) Q_D(QWebEnginePage); d->ensureInitialized(); - d->printToPdf(filePath, layout, ranges); + d->printToPdf(filePath, layout, ranges, WebContentsAdapter::kUseMainFrameId); #else Q_UNUSED(filePath); Q_UNUSED(layout); @@ -2362,7 +2364,7 @@ void QWebEnginePage::printToPdf(const std::function &re if (resultCallback && result) resultCallback(*result); }; - d->printToPdf(std::move(wrappedCallback), layout, ranges); + d->printToPdf(std::move(wrappedCallback), layout, ranges, WebContentsAdapter::kUseMainFrameId); #else Q_UNUSED(layout); Q_UNUSED(ranges); diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h index 3aeda6711a1..6f536f3a622 100644 --- a/src/core/api/qwebenginepage_p.h +++ b/src/core/api/qwebenginepage_p.h @@ -136,10 +136,10 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePagePrivate : public QtWebEngineCore::Web const std::function &callback) override; void didFetchDocumentMarkup(quint64 requestId, const QString &result) override; void didFetchDocumentInnerText(quint64 requestId, const QString &result) override; - void printToPdf(const QString &filePath, const QPageLayout &layout, - const QPageRanges &ranges) override; + void printToPdf(const QString &filePath, const QPageLayout &layout, const QPageRanges &ranges, + quint64 frameId) override; void printToPdf(std::function)> &&callback, - const QPageLayout &layout, const QPageRanges &ranges) override; + const QPageLayout &layout, const QPageRanges &ranges, quint64 frameId) override; void didPrintPageToPdf(const QString &filePath, bool success) override; bool passOnFocus(bool reverse) override; void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp index db9dc8743d1..42bade52bdd 100644 --- a/src/core/printing/print_view_manager_qt.cpp +++ b/src/core/printing/print_view_manager_qt.cpp @@ -11,6 +11,7 @@ #include "pdf_util_qt.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" +#include "web_contents_adapter.h" #include "web_contents_view_qt.h" #include "web_engine_context.h" @@ -173,8 +174,8 @@ PrintViewManagerQt::~PrintViewManagerQt() void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayout, const QPageRanges &pageRanges, - bool printInColor, - const QString &filePath, + bool printInColor, const QString &filePath, + quint64 frameId, PrintToPDFFileCallback callback) { if (callback.is_null()) @@ -188,7 +189,8 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou m_pdfOutputPath = toFilePath(filePath); m_pdfSaveCallback = std::move(callback); - if (!PrintToPDFInternal(pageLayout, pageRanges, printInColor)) { + if (!PrintToPDFInternal(pageLayout, pageRanges, printInColor, /*useCustomMargins*/ true, + frameId)) { content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::BindOnce(std::move(m_pdfSaveCallback), false)); resetPdfState(); @@ -196,9 +198,8 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou } void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, - const QPageRanges &pageRanges, - bool printInColor, - bool useCustomMargins, + const QPageRanges &pageRanges, bool printInColor, + bool useCustomMargins, quint64 frameId, PrintToPDFCallback callback) { if (callback.is_null()) @@ -212,7 +213,7 @@ void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, } m_pdfPrintCallback = std::move(callback); - if (!PrintToPDFInternal(pageLayout, pageRanges, printInColor, useCustomMargins)) { + if (!PrintToPDFInternal(pageLayout, pageRanges, printInColor, useCustomMargins, frameId)) { content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::BindOnce(std::move(m_pdfPrintCallback), QSharedPointer())); @@ -221,9 +222,8 @@ void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, } bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, - const QPageRanges &pageRanges, - const bool printInColor, - const bool useCustomMargins) + const QPageRanges &pageRanges, const bool printInColor, + const bool useCustomMargins, quint64 frameId) { if (!pageLayout.isValid()) return false; @@ -239,11 +239,22 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, if (web_contents()->IsCrashed()) return false; - content::RenderFrameHost *rfh = web_contents()->GetPrimaryMainFrame(); - // Use the plugin frame for printing if web_contents() is a PDF viewer guest - content::RenderFrameHost *full_page_plugin = GetFullPagePlugin(web_contents()); - if (content::RenderFrameHost *pdf_rfh = FindPdfChildFrame(full_page_plugin ? full_page_plugin : rfh)) - rfh = pdf_rfh; + content::RenderFrameHost *rfh = nullptr; + if (frameId == WebContentsAdapter::kInvalidFrameId) { + return false; + } else if (frameId == WebContentsAdapter::kUseMainFrameId) { + rfh = web_contents()->GetPrimaryMainFrame(); + // Use the plugin frame for printing if web_contents() is a PDF viewer guest + content::RenderFrameHost *full_page_plugin = GetFullPagePlugin(web_contents()); + if (content::RenderFrameHost *pdf_rfh = + FindPdfChildFrame(full_page_plugin ? full_page_plugin : rfh)) + rfh = pdf_rfh; + } else { + auto *ftn = content::FrameTreeNode::GloballyFindByID(static_cast(frameId)); + if (!ftn) + return false; + rfh = ftn->current_frame_host(); + } GetPrintRenderFrame(rfh)->InitiatePrintPreview(false); DCHECK(!m_printPreviewRfh); diff --git a/src/core/printing/print_view_manager_qt.h b/src/core/printing/print_view_manager_qt.h index 956849ef9ee..879a89ef000 100644 --- a/src/core/printing/print_view_manager_qt.h +++ b/src/core/printing/print_view_manager_qt.h @@ -41,21 +41,18 @@ class PrintViewManagerQt typedef base::OnceCallback PrintToPDFFileCallback; // Method to print a page to a Pdf document with page size \a pageSize in location \a filePath. - void PrintToPDFFileWithCallback(const QPageLayout &pageLayout, - const QPageRanges &pageRanges, - bool printInColor, - const QString &filePath, + void PrintToPDFFileWithCallback(const QPageLayout &pageLayout, const QPageRanges &pageRanges, + bool printInColor, const QString &filePath, quint64 frameId, PrintToPDFFileCallback callback); - void PrintToPDFWithCallback(const QPageLayout &pageLayout, - const QPageRanges &pageRanges, - bool printInColor, - bool useCustomMargins, + void PrintToPDFWithCallback(const QPageLayout &pageLayout, const QPageRanges &pageRanges, + bool printInColor, bool useCustomMargins, quint64 frameId, PrintToPDFCallback callback); protected: explicit PrintViewManagerQt(content::WebContents*); - bool PrintToPDFInternal(const QPageLayout &, const QPageRanges &, bool printInColor, bool useCustomMargins = true); + bool PrintToPDFInternal(const QPageLayout &, const QPageRanges &, bool printInColor, + bool useCustomMargins, quint64 frameId); // content::WebContentsObserver implementation. // Cancels the print job. diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 4b21838a034..4774cf4dcc1 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1346,7 +1346,8 @@ void WebContentsAdapter::wasHidden() m_webContents->WasHidden(); } -void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QPageRanges &pageRanges, const QString &filePath) +void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QPageRanges &pageRanges, + const QString &filePath, quint64 frameId) { #if QT_CONFIG(webengine_printing_and_pdf) CHECK_INITIALIZED(); @@ -1356,17 +1357,15 @@ void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QPageRa content::WebContents *webContents = m_webContents.get(); if (content::WebContents *guest = guestWebContents()) webContents = guest; - PrintViewManagerQt::FromWebContents(webContents)->PrintToPDFFileWithCallback(pageLayout, - pageRanges, - true, - filePath, - std::move(callback)); + PrintViewManagerQt::FromWebContents(webContents) + ->PrintToPDFFileWithCallback(pageLayout, pageRanges, true, filePath, frameId, + std::move(callback)); #endif // QT_CONFIG(webengine_printing_and_pdf) } void WebContentsAdapter::printToPDFCallbackResult( std::function)> &&callback, const QPageLayout &pageLayout, - const QPageRanges &pageRanges, bool colorMode, bool useCustomMargins) + const QPageRanges &pageRanges, bool colorMode, bool useCustomMargins, quint64 frameId) { #if QT_CONFIG(webengine_printing_and_pdf) CHECK_INITIALIZED(); @@ -1377,7 +1376,7 @@ void WebContentsAdapter::printToPDFCallbackResult( if (content::WebContents *guest = guestWebContents()) webContents = guest; PrintViewManagerQt::FromWebContents(webContents) - ->PrintToPDFWithCallback(pageLayout, pageRanges, colorMode, useCustomMargins, + ->PrintToPDFWithCallback(pageLayout, pageRanges, colorMode, useCustomMargins, frameId, std::move(internalCallback)); m_printCallbacks.emplace(m_nextRequestId++, std::move(callback)); #else diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 9663c77eda7..61da0ba7bbe 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -206,10 +206,10 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapter : public QEnableSharedFromThis)> &&, - const QPageLayout &, const QPageRanges &, bool colorMode = true, - bool useCustomMargins = true); + const QPageLayout &, const QPageRanges &, bool colorMode, + bool useCustomMargins, quint64 frameId); void didPrintPage(quint64 requestId, QSharedPointer result); void replaceMisspelling(const QString &word); diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 3c50ac84011..6cb07a32bc3 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -183,9 +183,10 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapterClient { virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) = 0; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; virtual void printToPdf(const QString &filePath, const QPageLayout &layout, - const QPageRanges &ranges) = 0; + const QPageRanges &ranges, quint64 frameId) = 0; virtual void printToPdf(std::function)> &&callback, - const QPageLayout &layout, const QPageRanges &ranges) = 0; + const QPageLayout &layout, const QPageRanges &ranges, + quint64 frameId) = 0; virtual void didPrintPageToPdf(const QString &filePath, bool success) = 0; virtual bool passOnFocus(bool reverse) = 0; // returns the last QObject (QWidget/QQuickItem) based object in the accessibility diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp index f6bd3878044..0ff182c7a3e 100644 --- a/src/webenginequick/api/qquickwebengineview.cpp +++ b/src/webenginequick/api/qquickwebengineview.cpp @@ -1318,16 +1318,17 @@ void QQuickWebEngineViewPrivate::runJavaScript( } void QQuickWebEngineViewPrivate::printToPdf(const QString &filePath, const QPageLayout &layout, - const QPageRanges &ranges) + const QPageRanges &ranges, quint64 frameId) { - adapter->printToPDF(layout, ranges, filePath); + adapter->printToPDF(layout, ranges, filePath, frameId); } void QQuickWebEngineViewPrivate::printToPdf( std::function)> &&callback, const QPageLayout &layout, - const QPageRanges &ranges) + const QPageRanges &ranges, quint64 frameId) { - adapter->printToPDFCallbackResult(std::move(callback), layout, ranges); + adapter->printToPDFCallbackResult(std::move(callback), layout, ranges, /*colorMode*/ true, + /*useCustomMargins*/ true, frameId); } void QQuickWebEngineViewPrivate::didPrintPageToPdf(const QString &filePath, bool success) @@ -1586,7 +1587,7 @@ void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); QPageRanges ranges; d->ensureContentsAdapter(); - d->adapter->printToPDF(pageLayout, ranges, filePath); + d->printToPdf(filePath, pageLayout, ranges, WebContentsAdapter::kUseMainFrameId); #else Q_UNUSED(filePath); Q_UNUSED(pageSizeId); @@ -1613,7 +1614,8 @@ void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId callback.call(args); }; - d->printToPdf(std::move(wrappedCallback), pageLayout, ranges); + d->printToPdf(std::move(wrappedCallback), pageLayout, ranges, + WebContentsAdapter::kUseMainFrameId); #else Q_UNUSED(pageSizeId); Q_UNUSED(orientation); diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h index 5a968aaa44a..988a2f0b148 100644 --- a/src/webenginequick/api/qquickwebengineview_p_p.h +++ b/src/webenginequick/api/qquickwebengineview_p_p.h @@ -97,10 +97,10 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineViewPrivate : public QtWebEngineCor const std::function &callback) override; void didFetchDocumentMarkup(quint64, const QString&) override { } void didFetchDocumentInnerText(quint64, const QString&) override { } - void printToPdf(const QString &filePath, const QPageLayout &layout, - const QPageRanges &ranges) override; + void printToPdf(const QString &filePath, const QPageLayout &layout, const QPageRanges &ranges, + quint64 frameId) override; void printToPdf(std::function)> &&callback, - const QPageLayout &layout, const QPageRanges &ranges) override; + const QPageLayout &layout, const QPageRanges &ranges, quint64 frameId) override; void didPrintPageToPdf(const QString &filePath, bool success) override; bool passOnFocus(bool reverse) override; void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override; diff --git a/src/webenginequick/doc/src/webengineframe.qdoc b/src/webenginequick/doc/src/webengineframe.qdoc index a2368479a2f..7df4a1d2bfd 100644 --- a/src/webenginequick/doc/src/webengineframe.qdoc +++ b/src/webenginequick/doc/src/webengineframe.qdoc @@ -97,3 +97,27 @@ For more information about injecting scripts, see \l {Script Injection}. For an alternative way to inject scripts, see WebEngineView::userScripts. */ + +/*! + \qmlmethod void webEngineFrame::printToPdf(string filePath) + + Prints the frame's current content to a PDF document and stores it + under \a filePath. The resulting document will have A4 page size and + portrait orientation. + + This method issues an asynchronous request for printing the web page into a + PDF and returns immediately. To be informed about the result of the + request, connect to the signal \l WebEngineView::pdfPrintingFinished(). + + \sa WebEngineView::pdfPrintingFinished() +*/ + +/*! + \qmlmethod void webEngineFrame::printToPdf(variant callback) + + Prints the frame's current content to a PDF document and returns it in a byte array. The + resulting document will have A4 page size and portrait orientation. + + The \a callback must take a string parameter. This string will contain the document's data upon + successful printing and an empty string otherwise. +*/ diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index e72ad8fa96f..ebb818cbd71 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -1500,7 +1500,8 @@ void QWebEngineView::print(QPrinter *printer) }; dPage->adapter->printToPDFCallbackResult(std::move(callback), printer->pageLayout(), printer->pageRanges(), - printer->colorMode() == QPrinter::Color, false); + printer->colorMode() == QPrinter::Color, false, + QtWebEngineCore::WebContentsAdapter::kUseMainFrameId); #else Q_UNUSED(printer); Q_EMIT printFinished(false); diff --git a/tests/auto/core/qwebengineframe/CMakeLists.txt b/tests/auto/core/qwebengineframe/CMakeLists.txt index d02b4307d2c..7d73e5a4aac 100644 --- a/tests/auto/core/qwebengineframe/CMakeLists.txt +++ b/tests/auto/core/qwebengineframe/CMakeLists.txt @@ -19,4 +19,6 @@ qt_internal_add_resource(tst_qwebengineframe "tst_qwebengineframe" "resources/frameset.html" "resources/iframes.html" "resources/nesting-iframe.html" + "resources/printing-inner-document.html" + "resources/printing-outer-document.html" ) diff --git a/tests/auto/core/qwebengineframe/resources/printing-inner-document.html b/tests/auto/core/qwebengineframe/resources/printing-inner-document.html new file mode 100644 index 00000000000..2e5a53af5e0 --- /dev/null +++ b/tests/auto/core/qwebengineframe/resources/printing-inner-document.html @@ -0,0 +1,7 @@ + + + Printing Inner Document + +

Inner Header

+ + diff --git a/tests/auto/core/qwebengineframe/resources/printing-outer-document.html b/tests/auto/core/qwebengineframe/resources/printing-outer-document.html new file mode 100644 index 00000000000..c5947371e2d --- /dev/null +++ b/tests/auto/core/qwebengineframe/resources/printing-outer-document.html @@ -0,0 +1,8 @@ + + + Printing Outer Document + +

Outer Header

+ + + diff --git a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp index ce0b61ee27b..2fe0e27a265 100644 --- a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp +++ b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp @@ -39,6 +39,9 @@ private Q_SLOTS: void size(); void runJavaScript(); void printRequestedByFrame(); + void printToPdfFile(); + void printToPdfFileFailures(); + void printToPdfFunction(); private: }; @@ -208,6 +211,122 @@ void tst_QWebEngineFrame::printRequestedByFrame() QCOMPARE(*framePtr, *oFrame2); } +void tst_QWebEngineFrame::printToPdfFile() +{ + QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineframe-XXXXXX"); + QVERIFY(tempDir.isValid()); + + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/printing-outer-document.html")); + QTRY_COMPARE(loadSpy.size(), 1); + + auto outerFrame = page.mainFrame(); + auto maybeInnerFrame = page.findFrameByName("inner"); + QVERIFY(maybeInnerFrame); + auto innerFrame = *maybeInnerFrame; + + QSignalSpy savePdfSpy{ &page, SIGNAL(pdfPrintingFinished(QString, bool)) }; + + QString outerPath = tempDir.path() + "/outer.pdf"; + outerFrame.printToPdf(outerPath); + QTRY_COMPARE(savePdfSpy.size(), 1); + + QList outerArgs = savePdfSpy.takeFirst(); + QCOMPARE(outerArgs.at(0).toString(), outerPath); + QVERIFY(outerArgs.at(1).toBool()); + + QString innerPath = tempDir.path() + "/inner.pdf"; + innerFrame.printToPdf(innerPath); + QTRY_COMPARE(savePdfSpy.size(), 1); + + QList innerArgs = savePdfSpy.takeFirst(); + QCOMPARE(innerArgs.at(0).toString(), innerPath); + QVERIFY(innerArgs.at(1).toBool()); + + // The outer document encompasses more elements so its PDF should be larger. This is a + // roundabout way to check that we aren't just printing the same document twice. + auto outerSize = QFileInfo(outerPath).size(); + auto innerSize = QFileInfo(innerPath).size(); + QCOMPARE_GT(outerSize, innerSize); + QCOMPARE_GT(innerSize, 0); +} + +void tst_QWebEngineFrame::printToPdfFileFailures() +{ + QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineframe-XXXXXX"); + QVERIFY(tempDir.isValid()); + + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/printing-outer-document.html")); + QTRY_COMPARE(loadSpy.size(), 1); + + auto maybeInnerFrame = page.findFrameByName("inner"); + QVERIFY(maybeInnerFrame); + auto innerFrame = *maybeInnerFrame; + + QSignalSpy savePdfSpy{ &page, SIGNAL(pdfPrintingFinished(QString, bool)) }; + +#if !defined(Q_OS_WIN) + auto badPath = tempDir.path() + "/print_//2_failed.pdf"; +#else + auto badPath = tempDir.path() + "/print_|2_failed.pdf"; +#endif + innerFrame.printToPdf(badPath); + QTRY_COMPARE(savePdfSpy.size(), 1); + + QList badPathArgs = savePdfSpy.takeFirst(); + QCOMPARE(badPathArgs.at(0).toString(), badPath); + QVERIFY(!badPathArgs.at(1).toBool()); + + page.triggerAction(QWebEnginePage::WebAction::Reload); + QTRY_COMPARE(loadSpy.size(), 2); + + QVERIFY(!innerFrame.isValid()); + QString invalidFramePath = tempDir.path() + "/invalidFrame.pdf"; + innerFrame.printToPdf(invalidFramePath); + QTRY_COMPARE(savePdfSpy.size(), 1); + + QList invalidFrameArgs = savePdfSpy.takeFirst(); + QCOMPARE(invalidFrameArgs.at(0).toString(), invalidFramePath); + QVERIFY(!invalidFrameArgs.at(1).toBool()); +} + +void tst_QWebEngineFrame::printToPdfFunction() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/printing-outer-document.html")); + QTRY_COMPARE(loadSpy.size(), 1); + + auto outerFrame = page.mainFrame(); + auto maybeInnerFrame = page.findFrameByName("inner"); + QVERIFY(maybeInnerFrame); + auto innerFrame = *maybeInnerFrame; + + CallbackSpy outerSpy; + outerFrame.printToPdf(outerSpy.ref()); + auto outerPdfData = outerSpy.waitForResult(); + QCOMPARE_GT(outerPdfData.size(), 0); + + CallbackSpy innerSpy; + innerFrame.printToPdf(innerSpy.ref()); + auto innerPdfData = innerSpy.waitForResult(); + QCOMPARE_GT(innerPdfData.size(), 0); + QCOMPARE_GT(outerPdfData.size(), innerPdfData.size()); + + page.triggerAction(QWebEnginePage::WebAction::Reload); + QTRY_COMPARE(loadSpy.size(), 2); + QVERIFY(!innerFrame.isValid()); + + CallbackSpy invalidSpy; + innerFrame.printToPdf(invalidSpy.ref()); + auto invalidPdfData = invalidSpy.waitForResult(); + QVERIFY(invalidSpy.wasCalled()); + QCOMPARE(invalidPdfData.size(), 0); +} + QTEST_MAIN(tst_QWebEngineFrame) #include "tst_qwebengineframe.moc" diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index c95c45bb4ef..c4d889cbe8b 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -894,6 +894,8 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineFrame.htmlName --> QString" << "QWebEngineFrame.isValid --> bool" << "QWebEngineFrame.name --> QString" + << "QWebEngineFrame.printToPdf(QJSValue) --> void" + << "QWebEngineFrame.printToPdf(QString) --> void" << "QWebEngineFrame.runJavaScript(QString) --> void" << "QWebEngineFrame.runJavaScript(QString,uint) --> void" << "QWebEngineFrame.runJavaScript(QString,QJSValue) --> void" From c4acd649a825a0e3332143a90bba744ecc900db2 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 3 Jun 2024 14:13:44 +0000 Subject: [PATCH 002/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ic4f09b4f1810a533476bdce49524d210c1115675 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index f6db2abacf1..37198aaddc8 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 4ad3d0c6096e6caefec74681eed86c2fa92149fd + ref: b241e3f8bc951dfbac152bbf58532170ed910756 required: true ../qtpositioning: - ref: 413ede61f32da23c446654a98f285ce06ef035c8 + ref: edda8a2bba1e447ba08f977f8156d45f19cb0b72 required: false ../qttools: - ref: 49438275bdf6b08ba46e2ea2d89753f1f9c63d76 + ref: f7d623d562d55b75eef0a43e1045a5da8d7609fc required: false ../qtwebchannel: - ref: 9f1ca1c6bdde6adedeb215e487ebdb05a17ad2d0 + ref: 779185f6fa8e33bc183332c7e89b908904dea591 required: false From 3df5f39db2b5aff9494108dad96c6e9a744882d4 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Tue, 2 Apr 2024 16:08:15 +0200 Subject: [PATCH 003/341] Add QWebEnginePermission and rewrite permissions API With the addition of permission persistence, it's now important for us to have an API for querying previously granted/denied permissions, so that they can be revoked at a later point. This change does the bulk of the work to get us there, by introducing a new type representing a single permission for a given URL/Feature pair. This type holds no information about the permission's state; it is simply an accessor object which allows its user to query the current status of the permission, grant/deny it, or reset it back to its initial state (so, delete it from storage). This provides application developers an easy way to store/modify lists of permissions without having to define their own custom types. A subsequent change will expand the API to provide a list of all permissions for a given profile. The current API (in QWebEnginePage and QQuickWebEngineView) has been marked as deprecated, but has not been disabled to ensure a smooth transition for developers. [ChangeLog][QtWebEngineCore][QWebEnginePage] Deprecated old permissions API [ChangeLog][QtWebEngineQuick][WebEngineView] Deprecated old permissions API [ChangeLog][QtWebEngineCore] Added new API for querying and modifying website permissions. [ChangeLog][QtWebEngineQuick] Added new API for querying and modifying website permissions. Change-Id: I8661cdc26bbd6dcde6403d29cc083bcea1a49ccc Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 00d7de830a43a84a431511a55525f04c21b8ba49) Reviewed-by: Qt Cherry-pick Bot --- .../quicknanobrowser/BrowserWindow.qml | 44 ++- .../doc/src/quicknanobrowser.qdoc | 21 +- .../webenginewidgets/maps/doc/src/maps.qdoc | 11 +- examples/webenginewidgets/maps/mainwindow.cpp | 21 +- .../notifications/doc/src/notifications.qdoc | 4 +- .../webenginewidgets/notifications/main.cpp | 9 +- .../push-notifications/main.cpp | 9 +- .../simplebrowser/webview.cpp | 39 +-- .../webenginewidgets/simplebrowser/webview.h | 4 +- src/core/api/CMakeLists.txt | 1 + src/core/api/qwebenginepage.cpp | 260 ++++++++------- src/core/api/qwebenginepage.h | 38 ++- src/core/api/qwebenginepage_p.h | 3 +- src/core/api/qwebenginepermission.cpp | 307 ++++++++++++++++++ src/core/api/qwebenginepermission.h | 90 +++++ src/core/api/qwebenginepermission_p.h | 46 +++ src/core/doc/src/qwebenginepage_lgpl.qdoc | 15 + src/core/permission_manager_qt.cpp | 177 ++++++---- src/core/permission_manager_qt.h | 10 +- src/core/profile_adapter.cpp | 8 +- src/core/profile_adapter.h | 21 +- src/core/web_contents_adapter.cpp | 91 +++++- src/core/web_contents_adapter.h | 9 +- src/core/web_contents_adapter_client.h | 4 +- src/core/web_contents_delegate_qt.cpp | 6 +- src/core/web_contents_delegate_qt.h | 2 +- .../api/qquickwebengineforeigntypes_p.h | 25 ++ .../api/qquickwebenginesettings.cpp | 4 +- .../api/qquickwebengineview.cpp | 160 ++++++--- .../api/qquickwebengineview_p.h | 32 +- .../api/qquickwebengineview_p_p.h | 3 +- .../doc/src/webengine_permission.qdoc | 137 ++++++++ .../doc/src/webengineview_lgpl.qdoc | 19 +- tests/auto/quick/publicapi/tst_publicapi.cpp | 50 ++- .../quick/qmltests/data/tst_geopermission.qml | 22 +- .../quick/qmltests/data/tst_getUserMedia.qml | 30 +- .../quick/qmltests/data/tst_notification.qml | 17 +- .../qwebenginepage/tst_qwebenginepage.cpp | 235 +++++++++----- .../tst_qwebengineprofile.cpp | 14 + .../quick/geopermission/tst_geopermission.qml | 8 +- tests/manual/widgets/geolocation/main.cpp | 13 +- tests/manual/widgets/webrtc/main.cpp | 8 +- 42 files changed, 1502 insertions(+), 525 deletions(-) create mode 100644 src/core/api/qwebenginepermission.cpp create mode 100644 src/core/api/qwebenginepermission.h create mode 100644 src/core/api/qwebenginepermission_p.h create mode 100644 src/webenginequick/doc/src/webengine_permission.qdoc diff --git a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml index e2cb71fb3ca..2c5b3d86e75 100644 --- a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml +++ b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml @@ -648,10 +648,9 @@ ApplicationWindow { findBar.reset(); } - onFeaturePermissionRequested: function(securityOrigin, feature) { - featurePermissionDialog.securityOrigin = securityOrigin; - featurePermissionDialog.feature = feature; - featurePermissionDialog.visible = true; + onPermissionRequested: function(permission) { + permissionDialog.permission = permission; + permissionDialog.visible = true; } onWebAuthUxRequested: function(request) { webAuthDialog.init(request); @@ -736,7 +735,7 @@ ApplicationWindow { } } Dialog { - id: featurePermissionDialog + id: permissionDialog anchors.centerIn: parent width: Math.min(browserWindow.width, browserWindow.height) / 3 * 2 contentWidth: mainTextForPermissionDialog.width @@ -744,59 +743,58 @@ ApplicationWindow { standardButtons: Dialog.No | Dialog.Yes title: "Permission Request" - property var feature; - property url securityOrigin; + property var permission; contentItem: Item { Label { id: mainTextForPermissionDialog - text: featurePermissionDialog.questionForFeature() + text: permissionDialog.questionForFeature() } } - onAccepted: currentWebView && currentWebView.grantFeaturePermission(securityOrigin, feature, true) - onRejected: currentWebView && currentWebView.grantFeaturePermission(securityOrigin, feature, false) + onAccepted: permission.grant() + onRejected: permission.deny() onVisibleChanged: { if (visible) width = contentWidth + 20; } function questionForFeature() { - var question = "Allow " + securityOrigin + " to " + var question = "Allow " + permission.origin + " to " - switch (feature) { - case WebEngineView.Geolocation: + switch (permission.feature) { + case WebEnginePermission.Geolocation: question += "access your location information?"; break; - case WebEngineView.MediaAudioCapture: + case WebEnginePermission.MediaAudioCapture: question += "access your microphone?"; break; - case WebEngineView.MediaVideoCapture: + case WebEnginePermission.MediaVideoCapture: question += "access your webcam?"; break; - case WebEngineView.MediaVideoCapture: + case WebEnginePermission.MediaAudioVideoCapture: question += "access your microphone and webcam?"; break; - case WebEngineView.MouseLock: + case WebEnginePermission.MouseLock: question += "lock your mouse cursor?"; break; - case WebEngineView.DesktopVideoCapture: + case WebEnginePermission.DesktopVideoCapture: question += "capture video of your desktop?"; break; - case WebEngineView.DesktopAudioVideoCapture: + case WebEnginePermission.DesktopAudioVideoCapture: question += "capture audio and video of your desktop?"; break; - case WebEngineView.Notifications: + case WebEnginePermission.Notifications: question += "show notification on your desktop?"; break; - case WebEngineView.ClipboardReadWrite: + case WebEnginePermission.ClipboardReadWrite: question += "read from and write to your clipboard?"; break; - case WebEngineView.LocalFontsAccess: + case WebEnginePermission.LocalFontsAccess: question += "access the fonts stored on your machine?"; break; default: - question += "access unknown or unsupported feature [" + feature + "] ?"; + question += "access unknown or unsupported feature [" + permission.feature + "] ?"; break; } diff --git a/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc b/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc index 1e00402ff3f..cff4d3354e2 100644 --- a/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc +++ b/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc @@ -96,25 +96,22 @@ \skipto Dialog { \printuntil /^\ {4}\}/ - \section1 Handling Feature Permission Requests + \section1 Handling Permission Requests - We use the \c onFeaturePermissionRequested() signal handler to handle requests for - accessing a certain feature or device. The \c securityOrigin parameter identifies the - requester web site, and the \c feature parameter is the requested feature. We use these - to construct the message of the dialog: + We use the \c onPermissionRequested() signal handler to handle requests for + accessing a certain feature or device. The \c permission parameter is an object of the + WebEnginePermission type, which can be used to handle the incoming request. We temporarily store + this object, since we need to use it to construct the message of the dialog: \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml - \skipto onFeaturePermissionRequested + \skipto onPermissionRequested \printuntil } - We show a dialog where the user is asked to grant or deny access. The custom + We display a dialog where the user is asked to grant or deny access. The custom \c questionForFeature() JavaScript function generates a human-readable question about the request. - If users select \uicontrol Yes, we call the \l{WebEngineView::}{grantFeaturePermission()} - method with a third \c true parameter to grant the \c securityOrigin web site the permission - to access the \c feature. - If users select \uicontrol No, we call the same method but with the \c false parameter to - deny access: + If user selects \uicontrol Yes, we call the \l{webEnginePermission::grant}{grant()} + method, and if they select \uicontrol No we call \l{webEnginePermission::deny}{deny()}. \skipto id: sslDialog \skipto Dialog { diff --git a/examples/webenginewidgets/maps/doc/src/maps.qdoc b/examples/webenginewidgets/maps/doc/src/maps.qdoc index 0175f8b6511..f9bd19bfcd8 100644 --- a/examples/webenginewidgets/maps/doc/src/maps.qdoc +++ b/examples/webenginewidgets/maps/doc/src/maps.qdoc @@ -48,10 +48,10 @@ \printuntil setCentralWidget We then proceed to connect a lambda function to the \l - QWebEnginePage::featurePermissionRequested signal: + QWebEnginePage::permissionRequested signal: \skipto m_view->page() - \printuntil QWebEnginePage::Feature + \printuntil QWebEnginePermission permission This signal is emitted whenever a web page requests to make use of a certain feature or device, including not only location services but also audio @@ -62,15 +62,14 @@ Now comes the part where we actually ask the user for permission: - \printuntil securityOrigin \printuntil }); Note that the question includes the host component of the web site's URI (\c - securityOrigin) to inform the user as to exactly which web site will be + permission.origin()) to inform the user as to exactly which web site will be receiving their location data. - We use the \l QWebEnginePage::setFeaturePermission method to communicate the - user's answer back to the web page. + We use the \l QWebEnginePermission::grant() and \l QWebEnginePermission::deny() + methods to communicate the user's answer back to the web page. Finally we ask the \l QWebEnginePage to load the web page that might want to use location services: diff --git a/examples/webenginewidgets/maps/mainwindow.cpp b/examples/webenginewidgets/maps/mainwindow.cpp index 0d2b499117c..ca98ca2630f 100644 --- a/examples/webenginewidgets/maps/mainwindow.cpp +++ b/examples/webenginewidgets/maps/mainwindow.cpp @@ -13,25 +13,22 @@ MainWindow::MainWindow(QWidget *parent) QWebEnginePage *page = m_view->page(); - connect(page, &QWebEnginePage::featurePermissionRequested, - [this, page](const QUrl &securityOrigin, QWebEnginePage::Feature feature) { - if (feature != QWebEnginePage::Geolocation) + connect(page, &QWebEnginePage::permissionRequested, + [this, page](QWebEnginePermission permission) { + if (permission.feature() != QWebEnginePermission::Geolocation) return; QMessageBox msgBox(this); - msgBox.setText(tr("%1 wants to know your location").arg(securityOrigin.host())); + msgBox.setText(tr("%1 wants to know your location").arg(permission.origin().host())); msgBox.setInformativeText(tr("Do you want to send your current location to this website?")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); - if (msgBox.exec() == QMessageBox::Yes) { - page->setFeaturePermission( - securityOrigin, feature, QWebEnginePage::PermissionGrantedByUser); - } else { - page->setFeaturePermission( - securityOrigin, feature, QWebEnginePage::PermissionDeniedByUser); - } + if (msgBox.exec() == QMessageBox::Yes) + permission.grant(); + else + permission.deny(); }); - page->load(QUrl(QStringLiteral("https://maps.google.com/"))); + page->load(QUrl(QStringLiteral("https://bing.com/maps"))); } diff --git a/examples/webenginewidgets/notifications/doc/src/notifications.qdoc b/examples/webenginewidgets/notifications/doc/src/notifications.qdoc index f4fe1818fe1..bd0def910a2 100644 --- a/examples/webenginewidgets/notifications/doc/src/notifications.qdoc +++ b/examples/webenginewidgets/notifications/doc/src/notifications.qdoc @@ -45,11 +45,11 @@ \section2 Requesting Feature Permissions - We then use the \l QWebEnginePage::featurePermissionRequested() call to + We then use the \l QWebEnginePage::permissionRequested() call to request the user's permission to show notifications on their device. \quotefromfile webenginewidgets/notifications/main.cpp - \skipto featurePermissionRequested + \skipto permissionRequested \printuntil }); \section2 Handling New Notifications diff --git a/examples/webenginewidgets/notifications/main.cpp b/examples/webenginewidgets/notifications/main.cpp index c754aff3f84..df9ebff73c8 100644 --- a/examples/webenginewidgets/notifications/main.cpp +++ b/examples/webenginewidgets/notifications/main.cpp @@ -33,11 +33,11 @@ int main(int argc, char *argv[]) // set custom page to open all page's links for https scheme in system browser view.setPage(new WebEnginePage(&view)); - QObject::connect(view.page(), &QWebEnginePage::featurePermissionRequested, - [&] (const QUrl &origin, QWebEnginePage::Feature feature) { - if (feature != QWebEnginePage::Notifications) + QObject::connect(view.page(), &QWebEnginePage::permissionRequested, + [&] (QWebEnginePermission permission) { + if (permission.feature() != QWebEnginePermission::Notifications) return; - view.page()->setFeaturePermission(origin, feature, QWebEnginePage::PermissionGrantedByUser); + permission.grant(); }); auto profile = view.page()->profile(); @@ -50,4 +50,3 @@ int main(int argc, char *argv[]) view.setUrl(QStringLiteral("qrc:/index.html")); return app.exec(); } - diff --git a/examples/webenginewidgets/push-notifications/main.cpp b/examples/webenginewidgets/push-notifications/main.cpp index 18a862182b9..950ebfc9f14 100644 --- a/examples/webenginewidgets/push-notifications/main.cpp +++ b/examples/webenginewidgets/push-notifications/main.cpp @@ -20,13 +20,12 @@ int main(int argc, char *argv[]) QWebEngineView view(profile.data()); auto popup = new NotificationPopup(&view); - QObject::connect(view.page(), &QWebEnginePage::featurePermissionRequested, - [&](const QUrl &origin, QWebEnginePage::Feature feature) { - if (feature != QWebEnginePage::Notifications) + QObject::connect(view.page(), &QWebEnginePage::permissionRequested, + [&](QWebEnginePermission permission) { + if (permission.feature() != QWebEnginePage::Notifications) return; - view.page()->setFeaturePermission(origin, feature, - QWebEnginePage::PermissionGrantedByUser); + permission.grant(); }); profile->setPushServiceEnabled(true); diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp index 08e044f709e..3dcfc0c47c5 100644 --- a/examples/webenginewidgets/simplebrowser/webview.cpp +++ b/examples/webenginewidgets/simplebrowser/webview.cpp @@ -71,26 +71,26 @@ WebView::~WebView() m_imageAnimationGroup = nullptr; } -inline QString questionForFeature(QWebEnginePage::Feature feature) +inline QString questionForFeature(QWebEnginePermission::Feature feature) { switch (feature) { - case QWebEnginePage::Geolocation: + case QWebEnginePermission::Geolocation: return QObject::tr("Allow %1 to access your location information?"); - case QWebEnginePage::MediaAudioCapture: + case QWebEnginePermission::MediaAudioCapture: return QObject::tr("Allow %1 to access your microphone?"); - case QWebEnginePage::MediaVideoCapture: + case QWebEnginePermission::MediaVideoCapture: return QObject::tr("Allow %1 to access your webcam?"); - case QWebEnginePage::MediaAudioVideoCapture: + case QWebEnginePermission::MediaAudioVideoCapture: return QObject::tr("Allow %1 to access your microphone and webcam?"); - case QWebEnginePage::MouseLock: + case QWebEnginePermission::MouseLock: return QObject::tr("Allow %1 to lock your mouse cursor?"); - case QWebEnginePage::DesktopVideoCapture: + case QWebEnginePermission::DesktopVideoCapture: return QObject::tr("Allow %1 to capture video of your desktop?"); - case QWebEnginePage::DesktopAudioVideoCapture: + case QWebEnginePermission::DesktopAudioVideoCapture: return QObject::tr("Allow %1 to capture audio and video of your desktop?"); - case QWebEnginePage::Notifications: + case QWebEnginePermission::Notifications: return QObject::tr("Allow %1 to show notification on your desktop?"); - case QWebEnginePage::ClipboardReadWrite: + case QWebEnginePermission::ClipboardReadWrite: return QObject::tr("Allow %1 to read from and write to the clipboard?"); } return QString(); @@ -103,8 +103,8 @@ void WebView::setPage(WebPage *page) &WebView::handleCertificateError); disconnect(oldPage, &QWebEnginePage::authenticationRequired, this, &WebView::handleAuthenticationRequired); - disconnect(oldPage, &QWebEnginePage::featurePermissionRequested, this, - &WebView::handleFeaturePermissionRequested); + disconnect(oldPage, &QWebEnginePage::permissionRequested, this, + &WebView::handlePermissionRequested); disconnect(oldPage, &QWebEnginePage::proxyAuthenticationRequired, this, &WebView::handleProxyAuthenticationRequired); disconnect(oldPage, &QWebEnginePage::registerProtocolHandlerRequested, this, @@ -124,8 +124,8 @@ void WebView::setPage(WebPage *page) connect(page, &WebPage::createCertificateErrorDialog, this, &WebView::handleCertificateError); connect(page, &QWebEnginePage::authenticationRequired, this, &WebView::handleAuthenticationRequired); - connect(page, &QWebEnginePage::featurePermissionRequested, this, - &WebView::handleFeaturePermissionRequested); + connect(page, &QWebEnginePage::permissionRequested, this, + &WebView::handlePermissionRequested); connect(page, &QWebEnginePage::proxyAuthenticationRequired, this, &WebView::handleProxyAuthenticationRequired); connect(page, &QWebEnginePage::registerProtocolHandlerRequested, this, @@ -309,17 +309,14 @@ void WebView::handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticato } } -void WebView::handleFeaturePermissionRequested(const QUrl &securityOrigin, - QWebEnginePage::Feature feature) +void WebView::handlePermissionRequested(QWebEnginePermission permission) { QString title = tr("Permission Request"); - QString question = questionForFeature(feature).arg(securityOrigin.host()); + QString question = questionForFeature(permission.feature()).arg(permission.origin().host()); if (!question.isEmpty() && QMessageBox::question(window(), title, question) == QMessageBox::Yes) - page()->setFeaturePermission(securityOrigin, feature, - QWebEnginePage::PermissionGrantedByUser); + permission.grant(); else - page()->setFeaturePermission(securityOrigin, feature, - QWebEnginePage::PermissionDeniedByUser); + permission.deny(); } void WebView::handleProxyAuthenticationRequired(const QUrl &, QAuthenticator *auth, diff --git a/examples/webenginewidgets/simplebrowser/webview.h b/examples/webenginewidgets/simplebrowser/webview.h index c7e7f394c1b..d652fbdc9ac 100644 --- a/examples/webenginewidgets/simplebrowser/webview.h +++ b/examples/webenginewidgets/simplebrowser/webview.h @@ -14,6 +14,7 @@ #include #include #include +#include #include class WebPage; @@ -43,8 +44,7 @@ class WebView : public QWebEngineView private slots: void handleCertificateError(QWebEngineCertificateError error); void handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth); - void handleFeaturePermissionRequested(const QUrl &securityOrigin, - QWebEnginePage::Feature feature); + void handlePermissionRequested(QWebEnginePermission permission); void handleProxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth, const QString &proxyHost); void handleRegisterProtocolHandlerRequested(QWebEngineRegisterProtocolHandlerRequest request); diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt index c06f5e4ce24..e14d0cd5c18 100644 --- a/src/core/api/CMakeLists.txt +++ b/src/core/api/CMakeLists.txt @@ -29,6 +29,7 @@ qt_internal_add_module(WebEngineCore qwebenginenewwindowrequest.cpp qwebenginenewwindowrequest.h qwebenginenewwindowrequest_p.h qwebenginenotification.cpp qwebenginenotification.h qwebenginepage.cpp qwebenginepage.h qwebenginepage_p.h + qwebenginepermission.cpp qwebenginepermission.h qwebenginepermission_p.h qwebengineprofile.cpp qwebengineprofile.h qwebengineprofile_p.h qwebenginequotarequest.cpp qwebenginequotarequest.h qwebengineregisterprotocolhandlerrequest.cpp qwebengineregisterprotocolhandlerrequest.h diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index d7ab7030598..f0260fd0d31 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -24,6 +24,7 @@ #include "qwebenginescriptcollection_p.h" #include "qwebenginesettings.h" #include "qwebenginewebauthuxrequest.h" +#include "qwebenginepermission_p.h" #include "authentication_dialog_controller.h" #include "autofill_popup_controller.h" @@ -589,50 +590,121 @@ void QWebEnginePagePrivate::showColorDialog(QSharedPointerpermissionRequested(createFeaturePermissionObject(securityOrigin, feature)); + +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + QWebEnginePage::Feature deprecatedFeature; + + if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) + && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + deprecatedFeature = QWebEnginePage::MediaAudioVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) - feature = QWebEnginePage::MediaAudioCapture; + deprecatedFeature = QWebEnginePage::MediaAudioCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - feature = QWebEnginePage::MediaVideoCapture; - else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) && - requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) - feature = QWebEnginePage::DesktopAudioVideoCapture; + deprecatedFeature = QWebEnginePage::MediaVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) + && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + deprecatedFeature = QWebEnginePage::DesktopAudioVideoCapture; else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) - feature = QWebEnginePage::DesktopVideoCapture; - Q_EMIT q->featurePermissionRequested(securityOrigin, feature); + deprecatedFeature = QWebEnginePage::DesktopVideoCapture; + + Q_EMIT q->featurePermissionRequested(securityOrigin, deprecatedFeature); + QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) } -static QWebEnginePage::Feature toFeature(QtWebEngineCore::ProfileAdapter::PermissionType type) +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +static QWebEnginePage::Feature toDeprecatedFeature(QWebEnginePermission::Feature feature) { - switch (type) { - case QtWebEngineCore::ProfileAdapter::NotificationPermission: + switch (feature) { + case QWebEnginePermission::Feature::Notifications: return QWebEnginePage::Notifications; - case QtWebEngineCore::ProfileAdapter::GeolocationPermission: + case QWebEnginePermission::Feature::Geolocation: return QWebEnginePage::Geolocation; - case QtWebEngineCore::ProfileAdapter::ClipboardReadWrite: + case QWebEnginePermission::Feature::ClipboardReadWrite: return QWebEnginePage::ClipboardReadWrite; - case QtWebEngineCore::ProfileAdapter::LocalFontsPermission: + case QWebEnginePermission::Feature::LocalFontsAccess: return QWebEnginePage::LocalFontsAccess; - default: + case QWebEnginePermission::Feature::MediaAudioCapture: + return QWebEnginePage::MediaAudioCapture; + case QWebEnginePermission::Feature::MediaVideoCapture: + return QWebEnginePage::MediaVideoCapture; + case QWebEnginePermission::Feature::MediaAudioVideoCapture: + return QWebEnginePage::MediaAudioVideoCapture; + case QWebEnginePermission::Feature::DesktopVideoCapture: + return QWebEnginePage::DesktopVideoCapture; + case QWebEnginePermission::Feature::DesktopAudioVideoCapture: + return QWebEnginePage::DesktopAudioVideoCapture; + case QWebEnginePermission::Feature::MouseLock: + return QWebEnginePage::MouseLock; + case QWebEnginePermission::Feature::Unsupported: break; } + Q_UNREACHABLE(); return QWebEnginePage::Feature(-1); } +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) -void QWebEnginePagePrivate::runFeaturePermissionRequest(QtWebEngineCore::ProfileAdapter::PermissionType permission, const QUrl &securityOrigin) +void QWebEnginePagePrivate::runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &securityOrigin) { Q_Q(QWebEnginePage); - Q_EMIT q->featurePermissionRequested(securityOrigin, toFeature(permission)); + switch (feature) { + case QWebEnginePermission::Notifications: + case QWebEnginePermission::Geolocation: + case QWebEnginePermission::ClipboardReadWrite: + case QWebEnginePermission::LocalFontsAccess: + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, feature)); +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(feature)); + QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) + return; + case QWebEnginePermission::MouseLock: + case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::MediaAudioVideoCapture: + case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::DesktopVideoCapture: + case QWebEnginePermission::Unsupported: + Q_UNREACHABLE(); + return; + } } void QWebEnginePagePrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin) { Q_Q(QWebEnginePage); + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, QWebEnginePermission::MouseLock)); + +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED Q_EMIT q->featurePermissionRequested(securityOrigin, QWebEnginePage::MouseLock); + QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) } void QWebEnginePagePrivate::runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest request) @@ -821,6 +893,12 @@ void QWebEnginePagePrivate::showWebAuthDialog(QWebEngineWebAuthUxRequest *reques Q_EMIT q->webAuthUxRequested(request); } +QWebEnginePermission QWebEnginePagePrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) +{ + auto *returnPrivate = new QWebEnginePermissionPrivate{securityOrigin, feature, adapter, profileAdapter()}; + return QWebEnginePermission(returnPrivate); +} + QWebEnginePage::QWebEnginePage(QObject* parent) : QObject(parent) , d_ptr(new QWebEnginePagePrivate()) @@ -1773,104 +1851,64 @@ void QWebEnginePage::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *i d->adapter->setRequestInterceptor(interceptor); } +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy) { Q_D(QWebEnginePage); - if (policy == PermissionUnknown) { - switch (feature) { - case MediaAudioVideoCapture: - case MediaAudioCapture: - case MediaVideoCapture: - case DesktopAudioVideoCapture: - case DesktopVideoCapture: - case MouseLock: - break; - case Geolocation: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::GeolocationPermission, ProfileAdapter::AskPermission); - break; - case Notifications: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::NotificationPermission, ProfileAdapter::AskPermission); - break; - case ClipboardReadWrite: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, - ProfileAdapter::AskPermission); - break; - case LocalFontsAccess: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, ProfileAdapter::AskPermission); - break; - } - return; + QWebEnginePermission::Feature f; + QWebEnginePermission::State s; + + switch (feature) { + case QWebEnginePage::Notifications: + f = QWebEnginePermission::Notifications; + break; + case QWebEnginePage::Geolocation: + f = QWebEnginePermission::Geolocation; + break; + case QWebEnginePage::MediaAudioCapture: + f = QWebEnginePermission::MediaAudioCapture; + break; + case QWebEnginePage::MediaVideoCapture: + f = QWebEnginePermission::MediaVideoCapture; + break; + case QWebEnginePage::MediaAudioVideoCapture: + f = QWebEnginePermission::MediaAudioVideoCapture; + break; + case QWebEnginePage::MouseLock: + f = QWebEnginePermission::MouseLock; + break; + case QWebEnginePage::DesktopVideoCapture: + f = QWebEnginePermission::DesktopVideoCapture; + break; + case QWebEnginePage::DesktopAudioVideoCapture: + f = QWebEnginePermission::DesktopAudioVideoCapture; + break; + case QWebEnginePage::ClipboardReadWrite: + f = QWebEnginePermission::ClipboardReadWrite; + break; + case QWebEnginePage::LocalFontsAccess: + f = QWebEnginePermission::LocalFontsAccess; + break; } - const WebContentsAdapterClient::MediaRequestFlags audioVideoCaptureFlags( - WebContentsAdapterClient::MediaVideoCapture | - WebContentsAdapterClient::MediaAudioCapture); - const WebContentsAdapterClient::MediaRequestFlags desktopAudioVideoCaptureFlags( - WebContentsAdapterClient::MediaDesktopVideoCapture | - WebContentsAdapterClient::MediaDesktopAudioCapture); - - if (policy == PermissionGrantedByUser) { - switch (feature) { - case MediaAudioVideoCapture: - d->adapter->grantMediaAccessPermission(securityOrigin, audioVideoCaptureFlags); - break; - case MediaAudioCapture: - d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaAudioCapture); - break; - case MediaVideoCapture: - d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaVideoCapture); - break; - case DesktopAudioVideoCapture: - d->adapter->grantMediaAccessPermission(securityOrigin, desktopAudioVideoCaptureFlags); - break; - case DesktopVideoCapture: - d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaDesktopVideoCapture); - break; - case MouseLock: - d->adapter->grantMouseLockPermission(securityOrigin, true); - break; - case Geolocation: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::GeolocationPermission, ProfileAdapter::AllowedPermission); - break; - case Notifications: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::NotificationPermission, ProfileAdapter::AllowedPermission); - break; - case ClipboardReadWrite: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, - ProfileAdapter::AllowedPermission); - break; - case LocalFontsAccess: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, ProfileAdapter::AllowedPermission); - break; - } - } else { // if (policy == PermissionDeniedByUser) - switch (feature) { - case MediaAudioVideoCapture: - case MediaAudioCapture: - case MediaVideoCapture: - case DesktopAudioVideoCapture: - case DesktopVideoCapture: - d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone); - break; - case Geolocation: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::GeolocationPermission, ProfileAdapter::DeniedPermission); - break; - case MouseLock: - d->adapter->grantMouseLockPermission(securityOrigin, false); - break; - case Notifications: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::NotificationPermission, ProfileAdapter::DeniedPermission); - break; - case ClipboardReadWrite: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, - ProfileAdapter::DeniedPermission); - break; - case LocalFontsAccess: - d->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, ProfileAdapter::DeniedPermission); - break; - } + switch (policy) { + case QWebEnginePage::PermissionUnknown: + s = QWebEnginePermission::Ask; + break; + case QWebEnginePage::PermissionDeniedByUser: + s = QWebEnginePermission::Denied; + break; + case QWebEnginePage::PermissionGrantedByUser: + s = QWebEnginePermission::Granted; + break; } + + d->adapter->setFeaturePermission(securityOrigin, f, s); } +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) static inline QWebEnginePage::FileSelectionMode toPublic(FilePickerController::FileChooserMode mode) { diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h index 59eed2b9b4a..cca7c55e7a8 100644 --- a/src/core/api/qwebenginepage.h +++ b/src/core/api/qwebenginepage.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -147,12 +148,19 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject }; Q_ENUM(WebWindowType) - enum PermissionPolicy { +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + enum QT_DEPRECATED_VERSION_X_6_8( + "QWebEnginePage::PermissionPolicy has been deprecated. " + "The updated permissions API uses QWebEnginePermission::State.") + PermissionPolicy { PermissionUnknown, PermissionGrantedByUser, PermissionDeniedByUser }; Q_ENUM(PermissionPolicy) +QT_WARNING_POP +#endif // must match WebContentsAdapterClient::NavigationType enum NavigationType { @@ -166,7 +174,12 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject }; Q_ENUM(NavigationType) - enum Feature { +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + enum QT_DEPRECATED_VERSION_X_6_8( + "QWebEnginePage::Feature has been deprecated. " + "The updated permissions API uses QWebEnginePermission::Feature.") + Feature { Notifications = 0, Geolocation = 1, MediaAudioCapture = 2, @@ -179,6 +192,8 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject LocalFontsAccess, }; Q_ENUM(Feature) +QT_WARNING_POP +#endif // Ex-QWebFrame enum @@ -236,7 +251,12 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject void findText(const QString &subString, FindFlags options = {}, const std::function &resultCallback = std::function()); +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + QT_DEPRECATED_VERSION_X_6_8("Setting permissions through QWebEnginePage has been deprecated. Please use QWebEnginePermission instead.") void setFeaturePermission(const QUrl &securityOrigin, Feature feature, PermissionPolicy policy); +QT_WARNING_POP +#endif bool isLoading() const; @@ -319,9 +339,23 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject void geometryChangeRequested(const QRect &geom); void windowCloseRequested(); +#if QT_DEPRECATED_SINCE(6, 8) +#if !defined(Q_MOC_RUN) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +#endif // !defined(Q_MOC_RUN) + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated; please use permissionRequested instead.") void featurePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature); + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated, and no longer functions.") void featurePermissionRequestCanceled(const QUrl &securityOrigin, QWebEnginePage::Feature feature); +#if !defined(Q_MOC_RUN) +QT_WARNING_POP +#endif // !defined(Q_MOC_RUN) +#endif // QT_DEPRECATED_SINCE(6, 8) + void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); + void permissionRequested(QWebEnginePermission permissionRequest); + #if QT_DEPRECATED_SINCE(6, 5) QT_DEPRECATED_VERSION_X_6_5("Requesting host quota is no longer supported.") void quotaRequested(QWebEngineQuotaRequest quotaRequest); diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h index 6f536f3a622..77d3dd8c247 100644 --- a/src/core/api/qwebenginepage_p.h +++ b/src/core/api/qwebenginepage_p.h @@ -148,7 +148,7 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePagePrivate : public QtWebEngineCore::Web QSharedPointer) override; void releaseProfile() override; void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override; - void runFeaturePermissionRequest(QtWebEngineCore::ProfileAdapter::PermissionType permission, const QUrl &securityOrigin) override; + void runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &securityOrigin) override; void runMouseLockPermissionRequest(const QUrl &securityOrigin) override; void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) override; void runFileSystemAccessRequest(QWebEngineFileSystemAccessRequest) override; @@ -180,6 +180,7 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePagePrivate : public QtWebEngineCore::Web const QRect &bounds, bool autoselectFirstSuggestion) override; void hideAutofillPopup() override; void showWebAuthDialog(QWebEngineWebAuthUxRequest *controller) override; + QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) override; QtWebEngineCore::ProfileAdapter *profileAdapter() override; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp new file mode 100644 index 00000000000..d898b8c7e59 --- /dev/null +++ b/src/core/api/qwebenginepermission.cpp @@ -0,0 +1,307 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qwebenginepermission.h" +#include "qwebenginepermission_p.h" +#include "web_contents_adapter.h" +#include "profile_adapter.h" + +QT_BEGIN_NAMESPACE + +QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QWebEnginePermissionPrivate) + +QWebEnginePermissionPrivate::QWebEnginePermissionPrivate() + : QSharedData() + , feature(QWebEnginePermission::Unsupported) +{ +} + +QWebEnginePermissionPrivate::QWebEnginePermissionPrivate(const QUrl &origin_, QWebEnginePermission::Feature feature_, + QSharedPointer webContentsAdapter_, QtWebEngineCore::ProfileAdapter *profileAdapter_) + : QSharedData() + , origin(origin_) + , feature(feature_) + , webContentsAdapter(webContentsAdapter_) + , profileAdapter(profileAdapter_) +{ +} + +/*! + \class QWebEnginePermission + \inmodule QtWebEngineCore + \since 6.8 + \brief A QWebEnginePermission is an object used to access and modify the state of a single permission that's been + granted or denied to a specific origin URL. + + The typical usage pattern is as follows: + \list 1 + \li A website requests a specific feature, triggering the QWebEnginePage::permissionRequested() signal; + \li The signal handler triggers a prompt asking the user whether they want to grant the permission; + \li When the user has made their decision, the application calls \l grant() or \l deny(); + \endlist + + Alternatively, an application interested in modifying already granted permissions may use QWebEngineProfile::listPermissions() + to get a list of existing permissions associated with a profile, or QWebEngineProfile::getPermission() to get + a QWebEnginePermission object for a specific permission. + + The \l origin() property can be used to query which origin the QWebEnginePermission is associated with, while the + \l feature() property describes the associated feature. A website origin is the combination of its scheme, hostname, + and port. Permissions are granted on a per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} + requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. + + \l QWebEnginePermission::Feature describes all the feature types Qt WebEngine supports. Some Features are transient; + in practice, this means that they are never remembered, and a website that uses them will trigger a permission + prompt every time the Feature is needed. Transient Features cannot be granted in advance. + + The usability lifetime of a QWebEnginePermission is tied either to its associated QWebEnginePage + (for transient feature types), or QWebEngineProfile (for permanent feature types). A transient permission is one which + needs to be explicitly granted or denied every time it's needed (e.g. webcam/screen sharing permission), whereas a permanent + one might be stored inside the current profile, depending on the value of QWebEngineProfile::persistentPermissionsPolicy(). + You can check whether a QWebEnginePermission is in a valid state using its \l isValid() property. For invalid objects, calls to \l grant(), + \l deny(), or \l reset() will do nothing, while calls to \l state() will always return QWebEnginePermission::Invalid. + + \sa QWebEnginePage::permissionRequested(), QWebEngineProfile::getPermission(), QWebEngineProfile::listPermissions() +*/ + +/*! \fn QWebEnginePermission::QWebEnginePermission() + \internal +*/ + +/*! \internal */ +QWebEnginePermission::QWebEnginePermission() + : d_ptr(new QWebEnginePermissionPrivate()) +{ +} + +/*! \internal */ +QWebEnginePermission::QWebEnginePermission(QWebEnginePermissionPrivate *pvt) + : d_ptr(pvt) +{ +} + +QWebEnginePermission::QWebEnginePermission(const QWebEnginePermission &other) + : d_ptr(new QWebEnginePermissionPrivate(*other.d_ptr)) +{ +} + +QWebEnginePermission::~QWebEnginePermission() = default; + +QWebEnginePermission &QWebEnginePermission::operator=(const QWebEnginePermission &other) +{ + if (this == &other) + return *this; + + d_ptr.reset(new QWebEnginePermissionPrivate(*other.d_ptr)); + return *this; +} + +bool QWebEnginePermission::comparesEqual(const QWebEnginePermission &other) const +{ + if (this == &other) + return true; + + if (d_ptr->feature != other.d_ptr->feature || d_ptr->origin != other.d_ptr->origin) + return false; + + if (isTransient(d_ptr->feature)) { + if (d_ptr->webContentsAdapter != other.d_ptr->webContentsAdapter) + return false; + } else { + QtWebEngineCore::ProfileAdapter *thisProfile = d_ptr->webContentsAdapter + ? d_ptr->webContentsAdapter.toStrongRef()->profileAdapter() + : d_ptr->profileAdapter.get(); + QtWebEngineCore::ProfileAdapter *otherProfile = d_ptr->webContentsAdapter + ? other.d_ptr->webContentsAdapter.toStrongRef()->profileAdapter() + : other.d_ptr->profileAdapter.get(); + + if (thisProfile != otherProfile) + return false; + } + + return true; +} + +/*! + \property QWebEnginePermission::origin + \brief The URL of the permission's associated origin. + + A website origin is the combination of its scheme, hostname, and port. Permissions are granted on a + per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} + requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. +*/ +const QUrl QWebEnginePermission::origin() const +{ + return d_ptr->origin; +} + +/*! + \enum QWebEnginePermission::Feature + + This enum type holds the type of the requested feature: + + \value MediaAudioCapture Access to a microphone, or another audio source. This feature is transient. + \value MediaVideoCapture Access to a webcam, or another video source. This feature is transient. + \value MediaAudioVideoCapture Combination of \l MediaAudioCapture and \l MediaVideoCapture. This feature is transient. + \value DesktopVideoCapture Access to the contents of the user's screen. This feature is transient. + \value DesktopAudioVideoCapture Access to the contents of the user's screen, and application audio. This feature is transient. + \value MouseLock Locks the pointer inside an element on the web page. This feature is transient. + \value Notifications Allows the website to send notifications to the user. + \value Geolocation Access to the user's physical location. + \value ClipboardReadWrite Access to the user's clipboard. + \value LocalFontsAccess Access to the fonts installed on the user's machine. Only available on desktops. + \value Unsupported An unsupported feature type. + + \note Transient feature types are ones that will never be remembered by the underlying storage, and will trigger + a permission request every time a website tries to use them. Transient Features can only be denied/granted + as they're needed; any attempts to pre-grant a transient Feature will fail. +*/ + +/*! + \property QWebEnginePermission::feature + \brief The feature type associated with this permission. +*/ +QWebEnginePermission::Feature QWebEnginePermission::feature() const +{ + return d_ptr->feature; +} + +/*! + \enum QWebEnginePermission::State + + This enum type holds the current state of the requested feature: + + \value Invalid Object is in an invalid state, and any attempts to modify the described permission will fail. + \value Ask Either the permission has not been requested before, or the feature() is transient. + \value Granted Permission has already been granted. + \value Denied Permission has already been denied. +*/ + +/*! + \property QWebEnginePermission::state + \brief The current state of the permission. + + If a permission for the specified \l feature() and \l origin() has already been granted or denied, + the return value is QWebEnginePermission::Granted, or QWebEnginePermission::Denied, respectively. + When this is the first time the permission is requested, or if the \l feature() is transient, + the return value is QWebEnginePermission::Ask. If the object is in an invalid state, the returned + value is QWebEnginePermission::Invalid. + + \sa isValid(), isTransient() +*/ +QWebEnginePermission::State QWebEnginePermission::state() const +{ + if (!isValid()) + return Invalid; + if (d_ptr->webContentsAdapter) + return d_ptr->webContentsAdapter.toStrongRef()->getPermissionState(origin(), feature()); + if (d_ptr->profileAdapter) + return d_ptr->profileAdapter->getPermissionState(origin(), feature()); + Q_UNREACHABLE(); + return Ask; +} + +/*! + \property QWebEnginePermission::isValid + \brief Indicates whether attempts to change the permission's state will be successful. + + An invalid QWebEnginePermission is either: + \list + \li One whose \l feature() is unsupported; + \li One whose \l feature() is transient, and the associated page/view has been destroyed; + \li One whose \l feature() is permanent, but the associated profile has been destroyed; + \li One whose \l origin() is invalid. + \endlist + + \sa isTransient() +*/ +bool QWebEnginePermission::isValid() const +{ + if (feature() == Unsupported) + return false; + if (isTransient(feature()) && !d_ptr->webContentsAdapter) + return false; + if (!d_ptr->profileAdapter) + return false; + if (!d_ptr->origin.isValid()) + return false; + return true; +} + +/*! + Allows the associated origin to access the requested feature. Does nothing when \l isValid() evaluates to false. + + \sa deny(), reset(), isValid() +*/ +void QWebEnginePermission::grant() const +{ + if (!isValid()) + return; + if (d_ptr->webContentsAdapter) + d_ptr->webContentsAdapter.toStrongRef()->setFeaturePermission(origin(), feature(), Granted); + else if (d_ptr->profileAdapter) + d_ptr->profileAdapter->setPermission(origin(), feature(), Granted); +} + +/*! + Stops the associated origin from accessing the requested feature. Does nothing when \l isValid() evaluates to false. + + \sa grant(), reset(), isValid() +*/ +void QWebEnginePermission::deny() const +{ + if (!isValid()) + return; + if (d_ptr->webContentsAdapter) + d_ptr->webContentsAdapter.toStrongRef()->setFeaturePermission(origin(), feature(), Denied); + else if (d_ptr->profileAdapter) + d_ptr->profileAdapter->setPermission(origin(), feature(), Denied); +} + +/*! + Removes the permission from the profile's underlying storage. By default, permissions are stored on disk (except for + off-the-record profiles, where permissions are stored in memory and are destroyed with the profile). + This means that an already granted/denied permission will not be requested twice, but will get automatically + granted/denied every subsequent time a website requests it. Calling reset() allows the query to be asked + again the next time the website requests it. + + Does nothing when \l isValid() evaluates to false. + + \sa grant(), deny(), isValid(), QWebEngineProfile::persistentPermissionsPolicy() +*/ +void QWebEnginePermission::reset() const +{ + if (!isValid()) + return; + if (d_ptr->webContentsAdapter) + d_ptr->webContentsAdapter.toStrongRef()->setFeaturePermission(origin(), feature(), Ask); + else if (d_ptr->profileAdapter) + d_ptr->profileAdapter->setPermission(origin(), feature(), Ask); +} + +/*! + Returns whether \a feature is transient, meaning that a permission will be requested + every time the associated functionality is used by a web page. +*/ +bool QWebEnginePermission::isTransient(QWebEnginePermission::Feature feature) +{ + switch (feature) { + case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::MediaAudioVideoCapture: + case QWebEnginePermission::DesktopVideoCapture: + case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::MouseLock: + return true; + case QWebEnginePermission::Notifications: + case QWebEnginePermission::Geolocation: + case QWebEnginePermission::ClipboardReadWrite: + case QWebEnginePermission::LocalFontsAccess: + return false; + case QWebEnginePermission::Unsupported: + return false; + } +} + +QT_END_NAMESPACE + +#include "moc_qwebenginepermission.cpp" diff --git a/src/core/api/qwebenginepermission.h b/src/core/api/qwebenginepermission.h new file mode 100644 index 00000000000..09db8ce363d --- /dev/null +++ b/src/core/api/qwebenginepermission.h @@ -0,0 +1,90 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWEBENGINEPERMISSION_H +#define QWEBENGINEPERMISSION_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +struct QWebEnginePermissionPrivate; +QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QWebEnginePermissionPrivate, + Q_WEBENGINECORE_EXPORT) + +class QWebEnginePermission +{ + Q_GADGET_EXPORT(Q_WEBENGINECORE_EXPORT) + Q_PROPERTY(QUrl origin READ origin CONSTANT FINAL) + Q_PROPERTY(Feature feature READ feature CONSTANT FINAL) + Q_PROPERTY(State state READ state CONSTANT FINAL) + Q_PROPERTY(bool isValid READ isValid CONSTANT FINAL) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + Q_WEBENGINECORE_EXPORT QWebEnginePermission(); + + Q_WEBENGINECORE_EXPORT QWebEnginePermission(const QWebEnginePermission &other); + Q_WEBENGINECORE_EXPORT QWebEnginePermission(QWebEnginePermissionPrivate *pvt); + Q_WEBENGINECORE_EXPORT ~QWebEnginePermission(); + + Q_WEBENGINECORE_EXPORT QWebEnginePermission &operator=(const QWebEnginePermission &other); + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QWebEnginePermission) + void swap(QWebEnginePermission &other) noexcept { d_ptr.swap(other.d_ptr); } + + enum Feature : quint8 { + Unsupported, + MediaAudioCapture, + MediaVideoCapture, + MediaAudioVideoCapture, + DesktopVideoCapture, + DesktopAudioVideoCapture, + MouseLock, + Notifications, + Geolocation, + ClipboardReadWrite, + LocalFontsAccess, + }; + Q_ENUM(Feature) + + enum State : quint8 { + Invalid, + Ask, + Granted, + Denied + }; + Q_ENUM(State) + + Q_WEBENGINECORE_EXPORT const QUrl origin() const; + Q_WEBENGINECORE_EXPORT Feature feature() const; + Q_WEBENGINECORE_EXPORT State state() const; + Q_WEBENGINECORE_EXPORT bool isValid() const; + + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void grant() const; + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void deny() const; + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void reset() const; + + Q_WEBENGINECORE_EXPORT Q_INVOKABLE static bool isTransient(QWebEnginePermission::Feature feature); + +private: + inline friend bool operator==(const QWebEnginePermission &lhs, const QWebEnginePermission &rhs) + { return lhs.comparesEqual(rhs); }; + inline friend bool operator!=(const QWebEnginePermission &lhs, const QWebEnginePermission &rhs) + { return !lhs.comparesEqual(rhs); }; + + Q_WEBENGINECORE_EXPORT bool comparesEqual(const QWebEnginePermission &other) const; + +protected: + QExplicitlySharedDataPointer d_ptr; +}; + + + +Q_DECLARE_SHARED(QWebEnginePermission) + +QT_END_NAMESPACE + +#endif // QWEBENGINEPERMISSION_H diff --git a/src/core/api/qwebenginepermission_p.h b/src/core/api/qwebenginepermission_p.h new file mode 100644 index 00000000000..94c89887391 --- /dev/null +++ b/src/core/api/qwebenginepermission_p.h @@ -0,0 +1,46 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWEBENGINEPERMISSION_P_H +#define QWEBENGINEPERMISSION_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 "qwebenginepermission.h" + +#include +#include +#include + +namespace QtWebEngineCore { +class WebContentsAdapter; +class ProfileAdapter; +} + +QT_BEGIN_NAMESPACE + +struct QWebEnginePermissionPrivate : public QSharedData +{ + Q_WEBENGINECORE_EXPORT QWebEnginePermissionPrivate(); + Q_WEBENGINECORE_EXPORT QWebEnginePermissionPrivate(const QUrl &, QWebEnginePermission::Feature, + QSharedPointer, QtWebEngineCore::ProfileAdapter *); + + QUrl origin; + QWebEnginePermission::Feature feature; + + QWeakPointer webContentsAdapter; + QPointer profileAdapter; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEPERMISSION_P_H diff --git a/src/core/doc/src/qwebenginepage_lgpl.qdoc b/src/core/doc/src/qwebenginepage_lgpl.qdoc index 1640ca8be37..630ea507e26 100644 --- a/src/core/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/core/doc/src/qwebenginepage_lgpl.qdoc @@ -245,6 +245,7 @@ /*! \enum QWebEnginePage::PermissionPolicy + \deprecated [6.8] Replaced by QWebEnginePermission::State. This enum describes the permission policies that the user may set for data or device access: @@ -273,6 +274,7 @@ /*! \enum QWebEnginePage::Feature + \deprecated [6.8] Replaced by QWebEnginePermission::Feature. This enum describes the platform feature access categories that the user may be asked to grant or deny access to: @@ -779,6 +781,8 @@ /*! \fn void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, Feature feature, PermissionPolicy policy) + \deprecated [6.8] Use QWebEnginePermission's \l {QWebEnginePermission::grant} {grant}(), + \l {QWebEnginePermission::deny} {deny}(), and \l {QWebEnginePermission::reset} {reset}() functions instead. Sets the permission for the web site identified by \a securityOrigin to use \a feature to \a policy. @@ -792,6 +796,7 @@ /*! \fn void QWebEnginePage::featurePermissionRequested(const QUrl &securityOrigin, Feature feature) + \deprecated [6.8] Use permissionRequested() instead. This signal is emitted when the web site identified by \a securityOrigin requests to make use of the resource or device identified by \a feature. @@ -801,6 +806,7 @@ /*! \fn void QWebEnginePage::featurePermissionRequestCanceled(const QUrl &securityOrigin, Feature feature) + \deprecated [6.8] This signal is no longer emitted. This signal is emitted when the web site identified by \a securityOrigin cancels a previously issued request to make use of \a feature. @@ -809,6 +815,15 @@ */ +/*! + \fn void QWebEnginePage::permissionRequested(QWebEnginePermission permission) + \since 6.8 + + This signal is emitted when a web site requests to make use of a feature (e.g. geolocation access, + permission to send notifications). The \a permission object can queried for the requesting URL + and the \c{QWebEnginePermission::Feature} it's asking for, as well as to grant or deny permission. +*/ + /*! \fn void QWebEnginePage::titleChanged(const QString &title) diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 100b7eb7cb2..6883d222404 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -27,28 +27,30 @@ namespace QtWebEngineCore { -static ProfileAdapter::PermissionType toQt(blink::PermissionType type) +static QWebEnginePermission::Feature toQt(blink::PermissionType type) { switch (type) { case blink::PermissionType::GEOLOCATION: - return ProfileAdapter::GeolocationPermission; + return QWebEnginePermission::Geolocation; case blink::PermissionType::AUDIO_CAPTURE: - return ProfileAdapter::AudioCapturePermission; + return QWebEnginePermission::MediaAudioCapture; case blink::PermissionType::VIDEO_CAPTURE: - return ProfileAdapter::VideoCapturePermission; + return QWebEnginePermission::MediaVideoCapture; + case blink::PermissionType::DISPLAY_CAPTURE: + return QWebEnginePermission::DesktopAudioVideoCapture; // We treat these both as read/write since we do not currently have a // ClipboardSanitizedWrite feature. case blink::PermissionType::CLIPBOARD_READ_WRITE: case blink::PermissionType::CLIPBOARD_SANITIZED_WRITE: - return ProfileAdapter::ClipboardReadWrite; + return QWebEnginePermission::ClipboardReadWrite; case blink::PermissionType::NOTIFICATIONS: - return ProfileAdapter::NotificationPermission; + return QWebEnginePermission::Notifications; case blink::PermissionType::LOCAL_FONTS: - return ProfileAdapter::LocalFontsPermission; + return QWebEnginePermission::LocalFontsAccess; case blink::PermissionType::ACCESSIBILITY_EVENTS: case blink::PermissionType::CAMERA_PAN_TILT_ZOOM: case blink::PermissionType::WINDOW_MANAGEMENT: - return ProfileAdapter::UnsupportedPermission; + return QWebEnginePermission::Unsupported; case blink::PermissionType::MIDI_SYSEX: case blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER: case blink::PermissionType::MIDI: @@ -65,62 +67,92 @@ static ProfileAdapter::PermissionType toQt(blink::PermissionType type) case blink::PermissionType::AR: case blink::PermissionType::VR: case blink::PermissionType::STORAGE_ACCESS_GRANT: - case blink::PermissionType::DISPLAY_CAPTURE: case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS: case blink::PermissionType::NUM: - LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast(type); + LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast(type); break; } - return ProfileAdapter::UnsupportedPermission; + return QWebEnginePermission::Unsupported; } -static blink::PermissionType toBlink(ProfileAdapter::PermissionType type) +static blink::PermissionType toBlink(QWebEnginePermission::Feature feature) { - switch (type) { - case ProfileAdapter::GeolocationPermission: + switch (feature) { + case QWebEnginePermission::Notifications: + return blink::PermissionType::NOTIFICATIONS; + case QWebEnginePermission::Geolocation: return blink::PermissionType::GEOLOCATION; - case ProfileAdapter::AudioCapturePermission: + case QWebEnginePermission::MediaAudioCapture: return blink::PermissionType::AUDIO_CAPTURE; - case ProfileAdapter::VideoCapturePermission: + case QWebEnginePermission::MediaVideoCapture: return blink::PermissionType::VIDEO_CAPTURE; - case ProfileAdapter::ClipboardReadWrite: + case QWebEnginePermission::DesktopVideoCapture: + case QWebEnginePermission::DesktopAudioVideoCapture: + return blink::PermissionType::DISPLAY_CAPTURE; + case QWebEnginePermission::ClipboardReadWrite: return blink::PermissionType::CLIPBOARD_READ_WRITE; - case ProfileAdapter::NotificationPermission: - return blink::PermissionType::NOTIFICATIONS; - case ProfileAdapter::LocalFontsPermission: + case QWebEnginePermission::LocalFontsAccess: return blink::PermissionType::LOCAL_FONTS; + case QWebEnginePermission::MediaAudioVideoCapture: + case QWebEnginePermission::Unsupported: + LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast(feature); + return blink::PermissionType::NUM; } - LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast(type); - return blink::PermissionType::NUM; + Q_UNREACHABLE(); } -static bool canRequestPermissionFor(ProfileAdapter::PermissionType type) +static QWebEnginePermission::State toQt(blink::mojom::PermissionStatus state) { - switch (type) { - case ProfileAdapter::GeolocationPermission: - case ProfileAdapter::NotificationPermission: - case ProfileAdapter::ClipboardReadWrite: - case ProfileAdapter::LocalFontsPermission: - return true; - default: - break; + switch (state) { + case blink::mojom::PermissionStatus::ASK: + return QWebEnginePermission::Ask; + case blink::mojom::PermissionStatus::GRANTED: + return QWebEnginePermission::Granted; + case blink::mojom::PermissionStatus::DENIED: + return QWebEnginePermission::Denied; } - return false; } -static blink::mojom::PermissionStatus toBlink(ProfileAdapter::PermissionState reply) +static blink::mojom::PermissionStatus toBlink(QWebEnginePermission::State state) { - switch (reply) { - case ProfileAdapter::AskPermission: + switch (state) { + case QWebEnginePermission::Invalid: + case QWebEnginePermission::Ask: return blink::mojom::PermissionStatus::ASK; - case ProfileAdapter::AllowedPermission: + case QWebEnginePermission::Granted: return blink::mojom::PermissionStatus::GRANTED; - case ProfileAdapter::DeniedPermission: + case QWebEnginePermission::Denied: return blink::mojom::PermissionStatus::DENIED; } } +std::string featureString(QWebEnginePermission::Feature feature) +{ + // This is separate from blink::featureString() for the sake of future-proofing; + // e.g. in case we add extra Features that do not correspond to a PermissionType, and + // we need to store them. + switch (feature) { + case QWebEnginePermission::Notifications: + return "Notifications"; + case QWebEnginePermission::Geolocation: + return "Geolocation"; + case QWebEnginePermission::ClipboardReadWrite: + return "ClipboardReadWrite"; + case QWebEnginePermission::LocalFontsAccess: + return "LocalFontsAccess"; + case QWebEnginePermission::MediaAudioCapture: + return "MediaAudioCapture"; + case QWebEnginePermission::MediaVideoCapture: + return "MediaVideoCapture"; + case QWebEnginePermission::DesktopAudioVideoCapture: + return "DesktopAudioVideoCapture"; + default: + Q_UNREACHABLE(); + return nullptr; + } +} + static blink::mojom::PermissionStatus getStatusFromSettings(blink::PermissionType type, WebEngineSettings *settings) { switch (type) { @@ -159,12 +191,12 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) } // Register all preference types as keys prior to doing anything else - prefRegistry->RegisterDictionaryPref(GetPermissionString(toBlink(ProfileAdapter::GeolocationPermission))); - prefRegistry->RegisterDictionaryPref(GetPermissionString(toBlink(ProfileAdapter::AudioCapturePermission))); - prefRegistry->RegisterDictionaryPref(GetPermissionString(toBlink(ProfileAdapter::VideoCapturePermission))); - prefRegistry->RegisterDictionaryPref(GetPermissionString(toBlink(ProfileAdapter::ClipboardReadWrite))); - prefRegistry->RegisterDictionaryPref(GetPermissionString(toBlink(ProfileAdapter::NotificationPermission))); - prefRegistry->RegisterDictionaryPref(GetPermissionString(toBlink(ProfileAdapter::LocalFontsPermission))); + prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::Geolocation)); + prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::ClipboardReadWrite)); + prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::Notifications)); + prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::LocalFontsAccess)); + prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::MediaAudioCapture)); + prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::MediaVideoCapture)); PrefProxyConfigTrackerImpl::RegisterPrefs(prefRegistry.get()); if (policy == ProfileAdapter::NoPersistentPermissions) @@ -181,34 +213,35 @@ PermissionManagerQt::~PermissionManagerQt() commit(); } -void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter::PermissionType type, ProfileAdapter::PermissionState reply) +void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::Feature feature, QWebEnginePermission::State state) { // Normalize the QUrl to Chromium origin form. const GURL gorigin = toG/service/https://github.com/url(url).DeprecatedGetOriginAsURL(); const QUrl origin = gorigin.is_empty() ? url : toQt(gorigin); if (origin.isEmpty()) return; - if (reply == ProfileAdapter::AskPermission) - ResetPermission(toBlink(type), gorigin, gorigin); + if (state == QWebEnginePermission::Ask) + ResetPermission(toBlink(feature), gorigin, gorigin); else - setPermission(toBlink(type), gorigin, reply == ProfileAdapter::AllowedPermission); - blink::mojom::PermissionStatus status = toBlink(reply); - if (reply != ProfileAdapter::AskPermission) { + setPermission(toBlink(feature), gorigin, state == QWebEnginePermission::Granted); + blink::mojom::PermissionStatus status = toBlink(state); + if (state != QWebEnginePermission::Ask) { auto it = m_requests.begin(); while (it != m_requests.end()) { - if (it->origin == origin && it->type == type) { + if (it->origin == origin && it->type == feature) { std::move(it->callback).Run(status); it = m_requests.erase(it); } else ++it; } } + for (const auto &it: m_subscribers) { - if (it.second.origin == origin && it.second.type == type) + if (it.second.origin == origin && it.second.type == feature) it.second.callback.Run(status); } - if (reply == ProfileAdapter::AskPermission) + if (state == QWebEnginePermission::Ask) return; auto it = m_multiRequests.begin(); @@ -218,13 +251,13 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter std::vector result; result.reserve(it->types.size()); for (blink::PermissionType permission : it->types) { - if (toQt(permission) == ProfileAdapter::UnsupportedPermission) { + if (toQt(permission) == QWebEnginePermission::Unsupported) { result.push_back(blink::mojom::PermissionStatus::DENIED); continue; } blink::mojom::PermissionStatus permissionStatus = GetPermissionStatus(permission, gorigin, GURL()); - if (permissionStatus == toBlink(reply)) { + if (permissionStatus == toBlink(state)) { if (permissionStatus == blink::mojom::PermissionStatus::ASK) { answerable = false; break; @@ -233,7 +266,7 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter result.push_back(permissionStatus); } else { // Reached when the PersistentPermissionsPolicy is set to NoPersistentPermissions - result.push_back(toBlink(reply)); + result.push_back(toBlink(state)); } } if (answerable) { @@ -246,9 +279,9 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter } } -bool PermissionManagerQt::checkPermission(const QUrl &origin, ProfileAdapter::PermissionType type) +QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature) { - return GetPermissionStatus(toBlink(type), toGurl(https://github.com/origin), GURL()) == blink::mojom::PermissionStatus::GRANTED; + return toQt(GetPermissionStatus(toBlink(feature), toGurl(https://github.com/origin), GURL())); } void PermissionManagerQt::commit() @@ -275,8 +308,8 @@ void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost std::vector result; result.reserve(requestDescription.permissions.size()); for (blink::PermissionType permission : requestDescription.permissions) { - const ProfileAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == ProfileAdapter::UnsupportedPermission) { + const QWebEnginePermission::Feature feature = toQt(permission); + if (feature == QWebEnginePermission::Unsupported) { result.push_back(blink::mojom::PermissionStatus::DENIED); continue; } @@ -306,9 +339,9 @@ void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost auto requestOrigin = toQt(requestDescription.requesting_origin); m_multiRequests.push_back({ request_id, requestDescription.permissions, requestOrigin, std::move(callback) }); for (blink::PermissionType permission : requestDescription.permissions) { - const ProfileAdapter::PermissionType permissionType = toQt(permission); - if (canRequestPermissionFor(permissionType)) - contentsDelegate->requestFeaturePermission(permissionType, requestOrigin); + const QWebEnginePermission::Feature feature = toQt(permission); + if (!QWebEnginePermission::isTransient(feature)) + contentsDelegate->requestFeaturePermission(feature, requestOrigin); } } @@ -324,12 +357,12 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus( const GURL& requesting_origin, const GURL& /*embedding_origin*/) { - const ProfileAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == ProfileAdapter::UnsupportedPermission) + const QWebEnginePermission::Feature feature = toQt(permission); + if (feature == QWebEnginePermission::Unsupported) return blink::mojom::PermissionStatus::DENIED; permission = toBlink(toQt(permission)); // Filter out merged/unsupported permissions (e.g. clipboard) - auto *pref = m_prefService->FindPreference(GetPermissionString(permission)); + auto *pref = m_prefService->FindPreference(featureString(toQt(permission))); if (!pref) return blink::mojom::PermissionStatus::ASK; // Permission type not in database @@ -405,11 +438,11 @@ void PermissionManagerQt::ResetPermission( const GURL& requesting_origin, const GURL& /*embedding_origin*/) { - const ProfileAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == ProfileAdapter::UnsupportedPermission) + const QWebEnginePermission::Feature feature = toQt(permission); + if (feature == QWebEnginePermission::Unsupported) return; - ScopedDictPrefUpdate updater(m_prefService.get(), GetPermissionString(permission)); + ScopedDictPrefUpdate updater(m_prefService.get(), featureString(feature)); updater.Get().Remove(requesting_origin.spec()); } @@ -437,14 +470,14 @@ void PermissionManagerQt::setPermission( const GURL& requesting_origin, bool granted) { - const ProfileAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == ProfileAdapter::UnsupportedPermission) + const QWebEnginePermission::Feature feature = toQt(permission); + if (feature == QWebEnginePermission::Unsupported) return; - if (!m_prefService->FindPreference(GetPermissionString(permission))) + if (!m_prefService->FindPreference(featureString(feature))) return; - ScopedDictPrefUpdate updater(m_prefService.get(), GetPermissionString(permission)); + ScopedDictPrefUpdate updater(m_prefService.get(), featureString(feature)); updater.Get().Set(requesting_origin.spec(), granted); } diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 5dedaa612fb..e74a3fba126 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -7,6 +7,7 @@ #include "base/functional/callback.h" #include "content/public/browser/permission_controller_delegate.h" +#include #include "profile_adapter.h" #include @@ -21,8 +22,9 @@ class PermissionManagerQt : public content::PermissionControllerDelegate PermissionManagerQt(ProfileAdapter *adapter); ~PermissionManagerQt(); - void permissionRequestReply(const QUrl &origin, ProfileAdapter::PermissionType type, ProfileAdapter::PermissionState reply); - bool checkPermission(const QUrl &origin, ProfileAdapter::PermissionType type); + void setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state); + QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature); + void commit(); // content::PermissionManager implementation: @@ -66,7 +68,7 @@ class PermissionManagerQt : public content::PermissionControllerDelegate private: struct Request { int id; - ProfileAdapter::PermissionType type; + QWebEnginePermission::Feature type; QUrl origin; base::OnceCallback callback; }; @@ -77,7 +79,7 @@ class PermissionManagerQt : public content::PermissionControllerDelegate base::OnceCallback&)> callback; }; struct Subscription { - ProfileAdapter::PermissionType type; + QWebEnginePermission::Feature type; QUrl origin; base::RepeatingCallback callback; }; diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 6fec8aa2879..4b337e8ed3c 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -569,14 +569,14 @@ UserResourceControllerHost *ProfileAdapter::userResourceController() return m_userResourceController.data(); } -void ProfileAdapter::permissionRequestReply(const QUrl &origin, PermissionType type, PermissionState reply) +void ProfileAdapter::setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state) { - static_cast(profile()->GetPermissionControllerDelegate())->permissionRequestReply(origin, type, reply); + static_cast(profile()->GetPermissionControllerDelegate())->setPermission(origin, feature, state); } -bool ProfileAdapter::checkPermission(const QUrl &origin, PermissionType type) +QWebEnginePermission::State ProfileAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature) { - return static_cast(profile()->GetPermissionControllerDelegate())->checkPermission(origin, type); + return static_cast(profile()->GetPermissionControllerDelegate())->getPermissionState(origin, feature); } QString ProfileAdapter::httpAcceptLanguageWithoutQualities() const diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 18d82ba9631..644d7e03c32 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "net/qrc_url_scheme_handler.h" QT_FORWARD_DECLARE_CLASS(QObject) @@ -133,22 +134,6 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject PersistentPermissionsOnDisk, }; - enum PermissionType { - UnsupportedPermission = 0, - GeolocationPermission = 1, - NotificationPermission = 2, - AudioCapturePermission = 3, - VideoCapturePermission = 4, - ClipboardReadWrite = 5, - LocalFontsPermission = 6, - }; - - enum PermissionState { - AskPermission = 0, - AllowedPermission = 1, - DeniedPermission = 2 - }; - enum ClientHint : uchar { UAArchitecture, UAPlatform, @@ -187,8 +172,8 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject const QList customUrlSchemes() const; UserResourceControllerHost *userResourceController(); - void permissionRequestReply(const QUrl &origin, PermissionType type, PermissionState reply); - bool checkPermission(const QUrl &origin, PermissionType type); + void setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state); + QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature); QString httpAcceptLanguageWithoutQualities() const; QString httpAcceptLanguage() const; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 4774cf4dcc1..7d9e119e94a 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1411,21 +1411,92 @@ QSizeF WebContentsAdapter::lastContentsSize() const return QSizeF(); } -void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags) +void WebContentsAdapter::setFeaturePermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state) { + if (!QWebEnginePermission::isTransient(feature)) { + // Do not check for initialization in this path so permissions can be set before first navigation + Q_ASSERT(m_profileAdapter); + m_profileAdapter->setPermission(origin, feature, state); + return; + } + CHECK_INITIALIZED(); - // Let the permission manager remember the reply. - if (flags & WebContentsAdapterClient::MediaAudioCapture) - m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::AudioCapturePermission, ProfileAdapter::AllowedPermission); - if (flags & WebContentsAdapterClient::MediaVideoCapture) - m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::VideoCapturePermission, ProfileAdapter::AllowedPermission); - MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), securityOrigin, flags); + if (feature == QWebEnginePermission::MouseLock) { + switch (state) { + case QWebEnginePermission::Ask: + // Do nothing + break; + case QWebEnginePermission::Denied: + grantMouseLockPermission(origin, false); + break; + case QWebEnginePermission::Granted: + grantMouseLockPermission(origin, true); + break; + } + + return; + } + + const WebContentsAdapterClient::MediaRequestFlags audioVideoCaptureFlags( + WebContentsAdapterClient::MediaVideoCapture | + WebContentsAdapterClient::MediaAudioCapture); + const WebContentsAdapterClient::MediaRequestFlags desktopAudioVideoCaptureFlags( + WebContentsAdapterClient::MediaDesktopVideoCapture | + WebContentsAdapterClient::MediaDesktopAudioCapture); + + switch (state) { + case QWebEnginePermission::Ask: + // Do nothing + return; + case QWebEnginePermission::Denied: + // Deny all media access + grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaNone); + return; + case QWebEnginePermission::Granted: + // Enable only the requested capture type + break; + } + + switch (feature) { + case QWebEnginePermission::MediaAudioVideoCapture: + grantMediaAccessPermission(origin, audioVideoCaptureFlags); + break; + case QWebEnginePermission::MediaAudioCapture: + grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaAudioCapture); + break; + case QWebEnginePermission::MediaVideoCapture: + grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaVideoCapture); + break; + case QWebEnginePermission::DesktopAudioVideoCapture: + grantMediaAccessPermission(origin, desktopAudioVideoCaptureFlags); + break; + case QWebEnginePermission::DesktopVideoCapture: + grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaDesktopVideoCapture); + break; + default: + Q_UNREACHABLE(); + break; + } } -void WebContentsAdapter::grantFeaturePermission(const QUrl &securityOrigin, ProfileAdapter::PermissionType feature, ProfileAdapter::PermissionState allowed) +QWebEnginePermission::State WebContentsAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature) { - Q_ASSERT(m_profileAdapter); - m_profileAdapter->permissionRequestReply(securityOrigin, feature, allowed); + // For now, we just return Ask for transient Features + if (QWebEnginePermission::isTransient(feature)) + return QWebEnginePermission::Ask; + + return m_profileAdapter->getPermissionState(origin, feature); +} + +void WebContentsAdapter::grantMediaAccessPermission(const QUrl &origin, WebContentsAdapterClient::MediaRequestFlags flags) +{ + CHECK_INITIALIZED(); + // Let the permission manager remember the reply. + if (flags & WebContentsAdapterClient::MediaAudioCapture) + m_profileAdapter->setPermission(origin, QWebEnginePermission::MediaAudioCapture, QWebEnginePermission::Granted); + if (flags & WebContentsAdapterClient::MediaVideoCapture) + m_profileAdapter->setPermission(origin, QWebEnginePermission::MediaVideoCapture, QWebEnginePermission::Granted); + MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), origin, flags); } void WebContentsAdapter::grantMouseLockPermission(const QUrl &securityOrigin, bool granted) diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 61da0ba7bbe..66736dd2151 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "web_contents_adapter_client.h" @@ -178,10 +179,12 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapter : public QEnableSharedFromThis +#include #include "profile_adapter.h" @@ -194,7 +195,7 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapterClient { virtual QObject *accessibilityParentObject() = 0; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) = 0; virtual void authenticationRequired(QSharedPointer) = 0; - virtual void runFeaturePermissionRequest(ProfileAdapter::PermissionType, const QUrl &securityOrigin) = 0; + virtual void runFeaturePermissionRequest(QWebEnginePermission::Feature, const QUrl &securityOrigin) = 0; virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) = 0; virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) = 0; virtual void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) = 0; @@ -228,6 +229,7 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapterClient { virtual WebContentsAdapter* webContentsAdapter() = 0; virtual void releaseProfile() = 0; virtual void showWebAuthDialog(QWebEngineWebAuthUxRequest *request) = 0; + virtual QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) = 0; }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 4df73fb6999..e16f5d769a2 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -733,7 +733,7 @@ void WebContentsDelegateQt::selectClientCert(const QSharedPointerselectClientCert(selectController); } -void WebContentsDelegateQt::requestFeaturePermission(ProfileAdapter::PermissionType feature, const QUrl &requestingOrigin) +void WebContentsDelegateQt::requestFeaturePermission(QWebEnginePermission::Feature feature, const QUrl &requestingOrigin) { m_viewClient->runFeaturePermissionRequest(feature, requestingOrigin); } @@ -790,9 +790,9 @@ bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost { switch (type) { case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE: - return m_viewClient->profileAdapter()->checkPermission(toQt(security_origin), ProfileAdapter::AudioCapturePermission); + return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::MediaAudioCapture); case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE: - return m_viewClient->profileAdapter()->checkPermission(toQt(security_origin), ProfileAdapter::VideoCapturePermission); + return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::MediaVideoCapture); default: LOG(INFO) << "WebContentsDelegateQt::CheckMediaAccessPermission: " << "Unsupported media stream type checked " << type; diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 51004878d65..88056c3ca36 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -136,7 +136,7 @@ class WebContentsDelegateQt : public content::WebContentsDelegate void overrideWebPreferences(content::WebContents *, blink::web_pref::WebPreferences*); void allowCertificateError(const QSharedPointer &); void selectClientCert(const QSharedPointer &); - void requestFeaturePermission(ProfileAdapter::PermissionType feature, const QUrl &requestingOrigin); + void requestFeaturePermission(QWebEnginePermission::Feature feature, const QUrl &requestingOrigin); void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture); FindTextHelper *findTextHelper(); diff --git a/src/webenginequick/api/qquickwebengineforeigntypes_p.h b/src/webenginequick/api/qquickwebengineforeigntypes_p.h index 7ba3a412114..58dee066ffb 100644 --- a/src/webenginequick/api/qquickwebengineforeigntypes_p.h +++ b/src/webenginequick/api/qquickwebengineforeigntypes_p.h @@ -32,6 +32,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -240,6 +241,30 @@ struct ForeginWebEngineWebAuthPinRequest QML_UNCREATABLE("") }; +// To prevent the same type from being exported twice into qmltypes +// (for value type and for the enums) +class QWebEnginePermissionDerived : public QWebEnginePermission +{ + Q_GADGET +}; + +namespace ForeignWebEnginePermissionNamespace +{ + Q_NAMESPACE + QML_FOREIGN_NAMESPACE(QWebEnginePermissionDerived) + QML_NAMED_ELEMENT(WebEnginePermission) + QML_ADDED_IN_VERSION(6, 8) +} + +struct ForeignWebEnginePermission +{ + Q_GADGET + QML_FOREIGN(QWebEnginePermission) + QML_VALUE_TYPE(webEnginePermission) + QML_ADDED_IN_VERSION(6, 8) + QML_UNCREATABLE("") +}; + QT_END_NAMESPACE #endif // QQUICKWEBENGINEFOREIGNTYPES_H diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp index 31ed7a661b0..5dc093a4472 100644 --- a/src/webenginequick/api/qquickwebenginesettings.cpp +++ b/src/webenginequick/api/qquickwebenginesettings.cpp @@ -79,7 +79,7 @@ bool QQuickWebEngineSettings::javascriptCanOpenWindows() const Since unrestricted clipboard access is a potential security concern, it is recommended that applications leave this disabled and instead respond to - \l{WebEngineView::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. + \l{WebEnginePermission::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. Disabled by default. */ @@ -389,7 +389,7 @@ bool QQuickWebEngineSettings::webRTCPublicInterfacesOnly() const Since unrestricted clipboard access is a potential security concern, it is recommended that applications leave this disabled and instead respond to - \l{WebEngineView::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. + \l{WebEnginePermission::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. Disabled by default. */ diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp index 0ff182c7a3e..852d00c7642 100644 --- a/src/webenginequick/api/qquickwebengineview.cpp +++ b/src/webenginequick/api/qquickwebengineview.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include @@ -484,29 +486,67 @@ void QQuickWebEngineViewPrivate::selectClientCert( Q_EMIT q->selectClientCertificate(certSelection); } -static QQuickWebEngineView::Feature toFeature(QtWebEngineCore::ProfileAdapter::PermissionType type) +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::Feature feature) { - switch (type) { - case QtWebEngineCore::ProfileAdapter::NotificationPermission: + switch (feature) { + case QWebEnginePermission::Feature::Notifications: return QQuickWebEngineView::Notifications; - case QtWebEngineCore::ProfileAdapter::GeolocationPermission: + case QWebEnginePermission::Feature::Geolocation: return QQuickWebEngineView::Geolocation; - case QtWebEngineCore::ProfileAdapter::ClipboardReadWrite: + case QWebEnginePermission::Feature::ClipboardReadWrite: return QQuickWebEngineView::ClipboardReadWrite; - case QtWebEngineCore::ProfileAdapter::LocalFontsPermission: + case QWebEnginePermission::Feature::LocalFontsAccess: return QQuickWebEngineView::LocalFontsAccess; - default: + case QWebEnginePermission::Feature::MediaAudioCapture: + return QQuickWebEngineView::MediaAudioCapture; + case QWebEnginePermission::Feature::MediaVideoCapture: + return QQuickWebEngineView::MediaVideoCapture; + case QWebEnginePermission::Feature::MediaAudioVideoCapture: + return QQuickWebEngineView::MediaAudioVideoCapture; + case QWebEnginePermission::Feature::DesktopVideoCapture: + return QQuickWebEngineView::DesktopVideoCapture; + case QWebEnginePermission::Feature::DesktopAudioVideoCapture: + return QQuickWebEngineView::DesktopAudioVideoCapture; + case QWebEnginePermission::Feature::MouseLock: + case QWebEnginePermission::Feature::Unsupported: break; } + Q_UNREACHABLE(); return QQuickWebEngineView::Feature(-1); } +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) - -void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(QtWebEngineCore::ProfileAdapter::PermissionType permission, const QUrl &url) +void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &url) { Q_Q(QQuickWebEngineView); - Q_EMIT q->featurePermissionRequested(url, toFeature(permission)); + switch (feature) { + case QWebEnginePermission::Notifications: + case QWebEnginePermission::Geolocation: + case QWebEnginePermission::ClipboardReadWrite: + case QWebEnginePermission::LocalFontsAccess: + Q_EMIT q->permissionRequested(createFeaturePermissionObject(url, feature)); +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + Q_EMIT q->featurePermissionRequested(url, toDeprecatedFeature(feature)); + QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) + return; + case QWebEnginePermission::MouseLock: + case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::MediaAudioVideoCapture: + case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::DesktopVideoCapture: + case QWebEnginePermission::Unsupported: + Q_UNREACHABLE(); + return; + } } void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer controller) @@ -784,19 +824,41 @@ void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &sec Q_Q(QQuickWebEngineView); if (!requestFlags) return; - QQuickWebEngineView::Feature feature; + QWebEnginePermission::Feature feature; if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - feature = QQuickWebEngineView::MediaAudioVideoCapture; + feature = QWebEnginePermission::MediaAudioVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) - feature = QQuickWebEngineView::MediaAudioCapture; + feature = QWebEnginePermission::MediaAudioCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - feature = QQuickWebEngineView::MediaVideoCapture; + feature = QWebEnginePermission::MediaVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) - feature = QQuickWebEngineView::DesktopAudioVideoCapture; + feature = QWebEnginePermission::DesktopAudioVideoCapture; + else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QWebEnginePermission::DesktopVideoCapture; + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, feature)); + +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + QQuickWebEngineView::Feature deprecatedFeature; + + if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) + && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + deprecatedFeature = QQuickWebEngineView::MediaAudioVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) + deprecatedFeature = QQuickWebEngineView::MediaAudioCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + deprecatedFeature = QQuickWebEngineView::MediaVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) + && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + deprecatedFeature = QQuickWebEngineView::DesktopAudioVideoCapture; else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) - feature = QQuickWebEngineView::DesktopVideoCapture; - Q_EMIT q->featurePermissionRequested(securityOrigin, feature); + deprecatedFeature = QQuickWebEngineView::DesktopVideoCapture; + + Q_EMIT q->featurePermissionRequested(securityOrigin, deprecatedFeature); + QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) } void QQuickWebEngineViewPrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin) @@ -1466,6 +1528,12 @@ void QQuickWebEngineViewPrivate::showWebAuthDialog(QWebEngineWebAuthUxRequest *r Q_EMIT q->webAuthUxRequested(request); } +QWebEnginePermission QQuickWebEngineViewPrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) +{ + auto *returnPrivate = new QWebEnginePermissionPrivate(securityOrigin, feature, adapter, profileAdapter()); + return QWebEnginePermission(returnPrivate); +} + bool QQuickWebEngineView::isLoading() const { Q_D(const QQuickWebEngineView); @@ -1761,55 +1829,49 @@ void QQuickWebEngineView::setDevToolsView(QQuickWebEngineView *devToolsView) Q_EMIT devToolsViewChanged(); } +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature, bool granted) { - if (!granted && ((feature >= MediaAudioCapture && feature <= MediaAudioVideoCapture) || - (feature >= DesktopVideoCapture && feature <= DesktopAudioVideoCapture))) { - d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone); - return; - } + Q_D(QQuickWebEngineView); + QWebEnginePermission::Feature f; switch (feature) { - case MediaAudioCapture: - d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaAudioCapture); + case QQuickWebEngineView::Notifications: + f = QWebEnginePermission::Notifications; break; - case MediaVideoCapture: - d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaVideoCapture); + case QQuickWebEngineView::Geolocation: + f = QWebEnginePermission::Geolocation; break; - case MediaAudioVideoCapture: - d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaRequestFlags(WebContentsAdapterClient::MediaAudioCapture | WebContentsAdapterClient::MediaVideoCapture)); + case QQuickWebEngineView::MediaAudioCapture: + f = QWebEnginePermission::MediaAudioCapture; break; - case DesktopVideoCapture: - d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaDesktopVideoCapture); + case QQuickWebEngineView::MediaVideoCapture: + f = QWebEnginePermission::MediaVideoCapture; break; - case DesktopAudioVideoCapture: - d_ptr->adapter->grantMediaAccessPermission( - securityOrigin, - WebContentsAdapterClient::MediaRequestFlags( - WebContentsAdapterClient::MediaDesktopAudioCapture | - WebContentsAdapterClient::MediaDesktopVideoCapture)); + case QQuickWebEngineView::MediaAudioVideoCapture: + f = QWebEnginePermission::MediaAudioVideoCapture; break; - case Geolocation: - d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::GeolocationPermission, - granted ? ProfileAdapter::AllowedPermission : ProfileAdapter::DeniedPermission); + case QQuickWebEngineView::DesktopVideoCapture: + f = QWebEnginePermission::DesktopVideoCapture; break; - case Notifications: - d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::NotificationPermission, - granted ? ProfileAdapter::AllowedPermission : ProfileAdapter::DeniedPermission); + case QQuickWebEngineView::DesktopAudioVideoCapture: + f = QWebEnginePermission::DesktopAudioVideoCapture; break; - case ClipboardReadWrite: - d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, - granted ? ProfileAdapter::AllowedPermission - : ProfileAdapter::DeniedPermission); + case QQuickWebEngineView::ClipboardReadWrite: + f = QWebEnginePermission::ClipboardReadWrite; break; - case LocalFontsAccess: - d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, - granted ? ProfileAdapter::AllowedPermission : ProfileAdapter::DeniedPermission); + case QQuickWebEngineView::LocalFontsAccess: + f = QWebEnginePermission::LocalFontsAccess; break; default: Q_UNREACHABLE(); } + + d->adapter->setFeaturePermission(securityOrigin, f, granted ? QWebEnginePermission::Granted : QWebEnginePermission::Denied); } +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) void QQuickWebEngineView::setActiveFocusOnPress(bool arg) { diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h index a310e09345b..ea09dff9faf 100644 --- a/src/webenginequick/api/qquickwebengineview_p.h +++ b/src/webenginequick/api/qquickwebengineview_p.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -166,8 +167,12 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED Q_ENUM(NewViewDestination) QT_WARNING_POP #endif - - enum Feature { +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + enum QT_DEPRECATED_VERSION_X_6_8( + "WebEnginePage::Feature has been deprecated. " + "The updated permissions API uses WebEnginePermission::Feature.") + Feature { MediaAudioCapture, MediaVideoCapture, MediaAudioVideoCapture, @@ -179,6 +184,8 @@ QT_WARNING_POP LocalFontsAccess, }; Q_ENUM(Feature) +QT_WARNING_POP +#endif enum WebAction { NoWebAction = - 1, @@ -489,7 +496,17 @@ public Q_SLOTS: void stop(); Q_REVISION(1,1) void findText(const QString &subString, FindFlags options = { }, const QJSValue &callback = QJSValue()); Q_REVISION(1,1) void fullScreenCancelled(); +#if QT_DEPRECATED_SINCE(6, 8) +#if !defined(Q_MOC_RUN) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +#endif // !defined(Q_MOC_RUN) + QT_DEPRECATED_VERSION_X_6_8("Setting permissions through WebEngineView has been deprecated. Please use WebEnginePermission instead.") Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature, bool granted); +#if !defined(Q_MOC_RUN) +QT_WARNING_POP +#endif // !defined(Q_MOC_RUN) +#endif // QT_DEPRECATED_SINCE(6, 8) Q_REVISION(1,2) void setActiveFocusOnPress(bool arg); Q_REVISION(1,2) void triggerWebAction(WebAction action); Q_REVISION(1,3) void printToPdf(const QString &filePath, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait); @@ -515,9 +532,19 @@ private Q_SLOTS: Q_REVISION(1,1) void certificateError(const QWebEngineCertificateError &error); Q_REVISION(1,1) void fullScreenRequested(const QWebEngineFullScreenRequest &request); Q_REVISION(1,1) void isFullScreenChanged(); +#if QT_DEPRECATED_SINCE(6, 8) +#if !defined(Q_MOC_RUN) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +#endif // !defined(Q_MOC_RUN) + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated; please use permissionRequested instead.") Q_REVISION(1, 1) void featurePermissionRequested(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature); +#if !defined(Q_MOC_RUN) +QT_WARNING_POP +#endif // !defined(Q_MOC_RUN) +#endif // QT_DEPRECATED_SINCE(6, 8) Q_REVISION(1,1) void zoomFactorChanged(qreal arg); Q_REVISION(1,1) void profileChanged(); Q_REVISION(1,1) void webChannelChanged(); @@ -562,6 +589,7 @@ private Q_SLOTS: Q_REVISION(6, 7) void webAuthUxRequested(QWebEngineWebAuthUxRequest *request); Q_REVISION(6,7) void desktopMediaRequested(const QWebEngineDesktopMediaRequest &request); Q_REVISION(6, 8) void printRequestedByFrame(QWebEngineFrame frame); + Q_REVISION(6,8) void permissionRequested(QWebEnginePermission permissionRequest); protected: void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h index 988a2f0b148..e61f32bcb09 100644 --- a/src/webenginequick/api/qquickwebengineview_p_p.h +++ b/src/webenginequick/api/qquickwebengineview_p_p.h @@ -114,7 +114,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineViewPrivate : public QtWebEngineCor void allowCertificateError(const QWebEngineCertificateError &error) override; void selectClientCert(const QSharedPointer &selectController) override; - void runFeaturePermissionRequest(QtWebEngineCore::ProfileAdapter::PermissionType permission, const QUrl &securityOrigin) override; + void runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &securityOrigin) override; void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) override; void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) override; void updateScrollPosition(const QPointF &position) override; @@ -139,6 +139,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineViewPrivate : public QtWebEngineCor const QRect &bounds, bool autoselectFirstSuggestion) override; void hideAutofillPopup() override; void showWebAuthDialog(QWebEngineWebAuthUxRequest *request) override; + QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) override; void updateAction(QQuickWebEngineView::WebAction) const; bool adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); diff --git a/src/webenginequick/doc/src/webengine_permission.qdoc b/src/webenginequick/doc/src/webengine_permission.qdoc new file mode 100644 index 00000000000..f59f57fa07f --- /dev/null +++ b/src/webenginequick/doc/src/webengine_permission.qdoc @@ -0,0 +1,137 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype webEnginePermission + \instantiates QWebEnginePermission + \inqmlmodule QtWebEngine + \brief An object used to access and modify the state of a single permission that's been + granted or denied to a specific origin URL. + + The typical usage pattern is as follows: + \list 1 + \li A website requests a specific feature, triggering the WebEngineView::permissionRequested signal; + \li The signal handler triggers a prompt asking the user whether they want to grant the permission; + \li When the user has made their decision, the application calls \l grant() or \l deny(); + \endlist + + Alternatively, an application interested in modifying already granted permissions may use WebEngineProfile::listPermissions() + to get a list of existing permissions associated with a profile, or WebEngineProfile::getPermission() to get + a webEnginePermission object for a specific permission. + + The \l origin property can be used to query which origin the webEnginePermission is associated with, while the + \l feature property describes the associated feature. A website origin is the combination of its scheme, hostname, + and port. Permissions are granted on a per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} + requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. + + The usability lifetime of a webEnginePermission is tied either to its associated WebEngineView + (for transient feature types), or WebEngineProfile (for permanent feature types). A transient permission is one which + needs to be explicitly granted or denied every time it's needed (e.g. webcam/screen sharing permission), whereas a permanent + one might be stored inside the current profile, depending on the value of WebEngineProfile::persistentPermissionsPolicy. + You can check whether a webEnginePermission is in a valid state using its \l isValid() property. For invalid objects, calls to \l grant(), + \l deny(), or \l reset() will do nothing, and their \l state() will always be WebEnginePermission.Invalid. + + The feature types Qt WebEngine supports are described in \l feature. + + \sa WebEngineView::permissionRequested, WebEngineProfile::getPermission(), + WebEngineProfile::listPermissions() +*/ + +/*! + \qmlproperty url webEnginePermission::origin + \brief The URL of the permission's associated origin. + + A website origin is the combination of its scheme, hostname, and port. Permissions are granted on a + per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} + requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. +*/ + +/*! + \qmlproperty enumeration webEnginePermission::feature + \brief The feature type associated with this permission. + + \value WebEnginePermission.MediaAudioCapture Access to a microphone, or another audio source. This feature is transient. + \value WebEnginePermission.MediaVideoCapture Access to a webcam, or another video source. This feature is transient. + \value WebEnginePermission.MediaAudioVideoCapture Combination of \l MediaAudioCapture and \l MediaVideoCapture. This feature is transient. + \value WebEnginePermission.DesktopVideoCapture Access to the contents of the user's screen. This feature is transient. + \value WebEnginePermission.DesktopAudioVideoCapture Access to the contents of the user's screen, and application audio. This feature is transient. + \value WebEnginePermission.MouseLock Locks the pointer inside an element on the web page. This feature is transient. + \value WebEnginePermission.Notifications Allows the website to send notifications to the user. + \value WebEnginePermission.Geolocation Access to the user's physical location. + \value WebEnginePermission.ClipboardReadWrite Access to the user's clipboard. + \value WebEnginePermission.LocalFontsAccess Access to the fonts installed on the user's machine. Only available on desktops. + \value WebEnginePermission.Unsupported An unsupported feature type. + + \note Transient feature types are ones that will never be remembered by the underlying storage, and will trigger + a permission request every time a website tries to use them. +*/ + +/*! + \qmlproperty enumeration webEnginePermission::state + \brief The current state of the permission. + + \value WebEnginePermission.Invalid Object is in an invalid state, and any attempts to modify the described permission will fail. + \value WebEnginePermission.Ask Either the permission has not been requested before, or the feature() is transient. + \value WebEnginePermission.Granted Permission has already been granted. + \value WebEnginePermission.Denied Permission has already been denied. + + If a permission for the specified \l feature and \l origin has already been granted or denied, + the return value is WebEnginePermission.Granted, or WebEnginePermission.Denied, respectively. + When this is the first time the permission is requested, or if the \l feature is transient, + the return value is WebEnginePermission.Ask. If the object is in an invalid state, the returned + value is WebEnginePermission.Invalid. + + \sa isValid, isTransient +*/ + +/*! + \qmlproperty bool webEnginePermission::isValid + \brief Indicates whether attempts to change the permission's state will be successful. + + An invalid webEnginePermission is either: + \list + \li One whose \l feature is unsupported; + \li One whose \l feature is transient, and the associated page/view has been destroyed; + \li One whose \l feature is permanent, but the associated profile has been destroyed; + \li One whose \l origin is invalid. + \endlist + + \sa isTransient +*/ + +/*! + \qmlmethod void webEnginePermission::grant() + + Allows the associated origin to access the requested feature. Does nothing when \l isValid evaluates to false. + + \sa deny, reset, isValid +*/ + +/*! + \qmlmethod void webEnginePermission::deny() + + Stops the associated origin from accessing the requested feature. Does nothing when \l isValid evaluates to false. + + \sa grant, reset, isValid +*/ + +/*! + \qmlmethod void webEnginePermission::reset() + + Removes the permission from the profile's underlying storage. By default, permissions are stored on disk (except for + off-the-record profiles, where permissions are stored in memory and are destroyed with the profile). + This means that an already granted/denied permission will not be requested twice, but will get automatically + granted/denied every subsequent time a website requests it. Calling reset() allows the query to be asked + again the next time the website requests it. + + Does nothing when \l isValid evaluates to false. + + \sa grant, deny, isValid, WebEngineProfile::persistentPermissionsPolicy +*/ + +/*! + \qmlmethod void webEnginePermission::isTransient(WebEnginePermission.Feature feature) + + Returns whether \a feature is transient, meaning that a permission will be requested + every time the associated functionality is used by a web page. +*/ diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc index 82bf605ca86..f7b17fa7b62 100644 --- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc +++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc @@ -111,10 +111,9 @@ \section2 Platform Features Web pages can request access to platform features, such as geolocation or audio and video - capture devices. The \l featurePermissionRequested() signal is emitted when a web page requests - to make use of a resource. The supported platform features are described by the \l Feature - property. If users grant the permission, the \l grantFeaturePermission() method is used to set - it to \e granted. + capture devices. The \l permissionRequested() signal is emitted when a web page requests + to make use of a resource. The supported platform features are described by the QWebEnginePermission::Feature + property. \section2 Rendering to OpenGL Surface @@ -445,6 +444,7 @@ /*! \qmlmethod void WebEngineView::grantFeaturePermission(url securityOrigin, Feature feature, bool granted) \since QtWebEngine 1.1 + \deprecated [6.8] Use webEnginePermission.grant() or webEnginePermission.deny() instead. Sets or unsets the permission, depending on \a granted, for the web site identified by \a securityOrigin to use \a feature. @@ -501,6 +501,7 @@ /*! \qmlsignal WebEngineView::featurePermissionRequested(url securityOrigin, Feature feature) \since QtWebEngine 1.1 + \deprecated [6.8] Use \l permissionRequested() instead. This signal is emitted when the web site identified by \a securityOrigin requests to make use of the resource or device identified by \a feature. @@ -508,6 +509,15 @@ \sa grantFeaturePermission() */ +/*! + \qmlsignal WebEngineView::permissionRequested(webEnginePermission permission) + \since QtWebEngine 6.8 + + This signal is emitted when a web site requests to make use of a feature (e.g. geolocation access, + permission to send notifications). The \a permission object can queried for the requesting URL + and the \c{WebEnginePermission.Feature} it's asking for, as well as to grant or deny permission. +*/ + /*! \qmlsignal WebEngineView::loadingChanged(WebEngineLoadingInfo loadingInfo) @@ -844,6 +854,7 @@ /*! \qmlproperty enumeration WebEngineView::Feature + \deprecated [6.8] Replaced by WebEnginePermission.Feature. Describes the platform feature access categories that the user may be asked to grant or deny access to: diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index c4d889cbe8b..cf0e59274df 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ static const QList typesToCheck = QList typesToCheck = QList knownEnumNames = QList() << QWebEngineDownloadRequest::staticMetaObject.enumerator(QWebEngineDownloadRequest::staticMetaObject.indexOfEnumerator("SavePageFormat")) + << QWebEnginePermission::staticMetaObject.enumerator(QWebEnginePermission::staticMetaObject.indexOfEnumerator("Feature")) ; static const QStringList hardcodedTypes = QStringList() @@ -353,6 +356,29 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineNewWindowRequest.InNewDialog --> DestinationType" << "QWebEngineNewWindowRequest.InNewTab --> DestinationType" << "QWebEngineNewWindowRequest.InNewWindow --> DestinationType" + << "QWebEnginePermission.Unsupported --> Feature" + << "QWebEnginePermission.MediaAudioCapture --> Feature" + << "QWebEnginePermission.MediaVideoCapture --> Feature" + << "QWebEnginePermission.MediaAudioVideoCapture --> Feature" + << "QWebEnginePermission.DesktopVideoCapture --> Feature" + << "QWebEnginePermission.DesktopAudioVideoCapture --> Feature" + << "QWebEnginePermission.MouseLock --> Feature" + << "QWebEnginePermission.Notifications --> Feature" + << "QWebEnginePermission.Geolocation --> Feature" + << "QWebEnginePermission.ClipboardReadWrite --> Feature" + << "QWebEnginePermission.LocalFontsAccess --> Feature" + << "QWebEnginePermission.Invalid --> State" + << "QWebEnginePermission.Ask --> State" + << "QWebEnginePermission.Granted --> State" + << "QWebEnginePermission.Denied --> State" + << "QWebEnginePermission.origin --> QUrl" + << "QWebEnginePermission.feature --> QWebEnginePermission::Feature" + << "QWebEnginePermission.state --> QWebEnginePermission::State" + << "QWebEnginePermission.isValid --> bool" + << "QWebEnginePermission.grant() --> void" + << "QWebEnginePermission.deny() --> void" + << "QWebEnginePermission.reset() --> void" + << "QWebEnginePermission.isTransient(QWebEnginePermission::Feature) --> bool" << "QQuickWebEngineNewWindowRequest.openIn(QQuickWebEngineView*) --> void" << "QQuickWebEngineProfile.AllowPersistentCookies --> PersistentCookiesPolicy" << "QQuickWebEngineProfile.DiskHttpCache --> HttpCacheType" @@ -537,10 +563,20 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.B10 --> PrintedPageSizeId" << "QQuickWebEngineView.Back --> WebAction" << "QQuickWebEngineView.C5E --> PrintedPageSizeId" +#if QT_DEPRECATED_SINCE(6, 8) + << "QQuickWebEngineView.ClipboardReadWrite --> Feature" + << "QQuickWebEngineView.DesktopAudioVideoCapture --> Feature" + << "QQuickWebEngineView.DesktopVideoCapture --> Feature" + << "QQuickWebEngineView.Geolocation --> Feature" + << "QQuickWebEngineView.LocalFontsAccess --> Feature" + << "QQuickWebEngineView.MediaAudioCapture --> Feature" + << "QQuickWebEngineView.MediaAudioVideoCapture --> Feature" + << "QQuickWebEngineView.MediaVideoCapture --> Feature" + << "QQuickWebEngineView.Notifications --> Feature" +#endif << "QQuickWebEngineView.CertificateErrorDomain --> ErrorDomain" << "QQuickWebEngineView.ChangeTextDirectionLTR --> WebAction" << "QQuickWebEngineView.ChangeTextDirectionRTL --> WebAction" - << "QQuickWebEngineView.ClipboardReadWrite --> Feature" << "QQuickWebEngineView.Comm10E --> PrintedPageSizeId" << "QQuickWebEngineView.ConnectionErrorDomain --> ErrorDomain" << "QQuickWebEngineView.Copy --> WebAction" @@ -552,8 +588,6 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.Custom --> PrintedPageSizeId" << "QQuickWebEngineView.Cut --> WebAction" << "QQuickWebEngineView.DLE --> PrintedPageSizeId" - << "QQuickWebEngineView.DesktopAudioVideoCapture --> Feature" - << "QQuickWebEngineView.DesktopVideoCapture --> Feature" << "QQuickWebEngineView.DnsErrorDomain --> ErrorDomain" << "QQuickWebEngineView.DoublePostcard --> PrintedPageSizeId" << "QQuickWebEngineView.DownloadImageToDisk --> WebAction" @@ -608,7 +642,6 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.Folio --> PrintedPageSizeId" << "QQuickWebEngineView.Forward --> WebAction" << "QQuickWebEngineView.FtpErrorDomain --> ErrorDomain" - << "QQuickWebEngineView.Geolocation --> Feature" << "QQuickWebEngineView.HttpErrorDomain --> ErrorDomain" << "QQuickWebEngineView.Imperial10x11 --> PrintedPageSizeId" << "QQuickWebEngineView.Imperial10x13 --> PrintedPageSizeId" @@ -653,12 +686,7 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.LoadStartedStatus --> LoadStatus" << "QQuickWebEngineView.LoadStoppedStatus --> LoadStatus" << "QQuickWebEngineView.LoadSucceededStatus --> LoadStatus" - << "QQuickWebEngineView.LocalFontsAccess --> Feature" - << "QQuickWebEngineView.MediaAudioCapture --> Feature" - << "QQuickWebEngineView.MediaAudioVideoCapture --> Feature" - << "QQuickWebEngineView.MediaVideoCapture --> Feature" << "QQuickWebEngineView.NoErrorDomain --> ErrorDomain" - << "QQuickWebEngineView.Notifications --> Feature" << "QQuickWebEngineView.NoWebAction --> WebAction" << "QQuickWebEngineView.NormalTerminationStatus --> RenderProcessTerminationStatus" << "QQuickWebEngineView.Note --> PrintedPageSizeId" @@ -734,7 +762,9 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.goBack() --> void" << "QQuickWebEngineView.goBackOrForward(int) --> void" << "QQuickWebEngineView.goForward() --> void" +#if QT_DEPRECATED_SINCE(6, 8) << "QQuickWebEngineView.grantFeaturePermission(QUrl,QQuickWebEngineView::Feature,bool) --> void" +#endif << "QQuickWebEngineView.history --> QWebEngineHistory*" << "QQuickWebEngineView.icon --> QUrl" << "QQuickWebEngineView.iconChanged() --> void" @@ -769,6 +799,7 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.NewViewInDialog --> NewViewDestination" << "QQuickWebEngineView.NewViewInTab --> NewViewDestination" << "QQuickWebEngineView.NewViewInWindow --> NewViewDestination" + << "QQuickWebEngineView.permissionRequested(QWebEnginePermission) --> void" << "QQuickWebEngineView.pdfPrintingFinished(QString,bool) --> void" << "QQuickWebEngineView.printRequested() --> void" << "QQuickWebEngineView.printRequestedByFrame(QWebEngineFrame) --> void" @@ -1020,4 +1051,3 @@ void tst_publicapi::publicAPI() QTEST_MAIN(tst_publicapi) #include "tst_publicapi.moc" - diff --git a/tests/auto/quick/qmltests/data/tst_geopermission.qml b/tests/auto/quick/qmltests/data/tst_geopermission.qml index c474033a977..e425a82c742 100644 --- a/tests/auto/quick/qmltests/data/tst_geopermission.qml +++ b/tests/auto/quick/qmltests/data/tst_geopermission.qml @@ -16,19 +16,19 @@ TestWebEngineView { profile.persistentPermissionsPolicy: WebEngineProfile.NoPersistentPermissions SignalSpy { - id: featurePermissionSpy + id: permissionSpy target: webEngineView - signalName: "featurePermissionRequested" + signalName: "permissionRequested" } - onFeaturePermissionRequested: function(securityOrigin, feature) { - if (feature === WebEngineView.Geolocation) { + onPermissionRequested: function(perm) { + if (perm.feature === WebEnginePermission.Geolocation) { geoPermissionRequested = true if (deniedGeolocation) { - webEngineView.grantFeaturePermission(securityOrigin, feature, false) + perm.deny() } else { - webEngineView.grantFeaturePermission(securityOrigin, feature, true) + perm.grant() } } } @@ -57,15 +57,15 @@ TestWebEngineView { function init() { deniedGeolocation = false - featurePermissionSpy.clear() + permissionSpy.clear() } function test_geoPermissionRequest() { - compare(featurePermissionSpy.count, 0) + compare(permissionSpy.count, 0) webEngineView.url = Qt.resolvedUrl("geolocation.html") - featurePermissionSpy.wait() + permissionSpy.wait() verify(geoPermissionRequested) - compare(featurePermissionSpy.count, 1) + compare(permissionSpy.count, 1) tryVerify(isHandled, 5000) verify(getErrorMessage() === "") } @@ -73,7 +73,7 @@ TestWebEngineView { function test_deniedGeolocationByUser() { deniedGeolocation = true webEngineView.url = Qt.resolvedUrl("geolocation.html") - featurePermissionSpy.wait() + permissionSpy.wait() tryVerify(isHandled, 5000) compare(getErrorMessage(), "User denied Geolocation") } diff --git a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml index 653f7a5df3d..9a876778b37 100644 --- a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml +++ b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml @@ -22,17 +22,17 @@ TestWebEngineView { { tag: "device audio", constraints: { audio: true }, - feature: WebEngineView.MediaAudioCapture, + feature: WebEnginePermission.MediaAudioCapture, }, { tag: "device video", constraints: { video: true }, - feature: WebEngineView.MediaVideoCapture, + feature: WebEnginePermission.MediaVideoCapture, }, { tag: "device audio+video", constraints: { audio: true, video: true }, - feature: WebEngineView.MediaAudioVideoCapture, + feature: WebEnginePermission.MediaAudioVideoCapture, }, { tag: "desktop video", @@ -43,7 +43,7 @@ TestWebEngineView { } } }, - feature: WebEngineView.DesktopVideoCapture, + feature: WebEnginePermission.DesktopVideoCapture, }, { tag: "desktop audio+video", @@ -59,7 +59,7 @@ TestWebEngineView { } } }, - feature: WebEngineView.DesktopAudioVideoCapture, + feature: WebEnginePermission.DesktopAudioVideoCapture, } ] } @@ -116,28 +116,24 @@ TestWebEngineView { //// // synchronous permission requests - property variant requestedFeature - property variant requestedSecurityOrigin + property variant permissionObject - onFeaturePermissionRequested: function(securityOrigin, feature) { - requestedFeature = feature - requestedSecurityOrigin = securityOrigin + onPermissionRequested: function(perm) { + permissionObject = perm } function gotFeatureRequest(expectedFeature) { - return requestedFeature == expectedFeature + return permissionObject && permissionObject.feature == expectedFeature } function acceptPendingRequest() { - webEngineView.grantFeaturePermission(requestedSecurityOrigin, requestedFeature, true) - requestedFeature = undefined - requestedSecurityOrigin = undefined + permissionObject.grant() + permissionObject = undefined } function rejectPendingRequest() { - webEngineView.grantFeaturePermission(requestedSecurityOrigin, requestedFeature, false) - requestedFeature = undefined - requestedSecurityOrigin = undefined + permissionObject.deny() + permissionObject = undefined } //// diff --git a/tests/auto/quick/qmltests/data/tst_notification.qml b/tests/auto/quick/qmltests/data/tst_notification.qml index 0bb33b41ebd..5defbff4b6f 100644 --- a/tests/auto/quick/qmltests/data/tst_notification.qml +++ b/tests/auto/quick/qmltests/data/tst_notification.qml @@ -13,7 +13,7 @@ TestWebEngineView { property bool permissionRequested: false property bool grantPermission: false - property url securityOrigin: '' + property var permissionObject profile.persistentPermissionsPolicy: WebEngineProfile.NoPersistentPermissions @@ -22,14 +22,17 @@ TestWebEngineView { SignalSpy { id: spyRequest target: view - signalName: 'featurePermissionRequested' + signalName: 'permissionRequested' } - onFeaturePermissionRequested: function(securityOrigin, feature) { - if (feature === WebEngineView.Notifications) { + onPermissionRequested: function(perm) { + if (perm.feature === WebEnginePermission.Notifications) { view.permissionRequested = true - view.securityOrigin = securityOrigin - view.grantFeaturePermission(securityOrigin, feature, grantPermission) + view.permissionObject = perm + if (grantPermission) + perm.grant() + else + perm.deny() } } @@ -93,7 +96,7 @@ TestWebEngineView { compare(notification.title, title) compare(notification.message, message) compare(notification.direction, Qt.RightToLeft) - compare(notification.origin, securityOrigin) + compare(notification.origin, permissionObject.origin) compare(notification.tag, 'tst') compare(notification.language, 'de') } diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index f6eac2880b5..8b6ea31fd41 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -451,12 +452,12 @@ Q_OBJECT return true; } public Q_SLOTS: - void requestPermission(const QUrl &origin, QWebEnginePage::Feature feature) + void requestPermission(QWebEnginePermission permission) { if (m_allowGeolocation) - setFeaturePermission(origin, feature, PermissionGrantedByUser); + permission.grant(); else - setFeaturePermission(origin, feature, PermissionDeniedByUser); + permission.deny(); } public: @@ -488,8 +489,8 @@ void tst_QWebEnginePage::geolocationRequestJS() newPage->profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); newPage->setGeolocationPermission(allowed); - connect(newPage, SIGNAL(featurePermissionRequested(const QUrl&, QWebEnginePage::Feature)), - newPage, SLOT(requestPermission(const QUrl&, QWebEnginePage::Feature))); + connect(newPage, SIGNAL(permissionRequested(QWebEnginePermission)), + newPage, SLOT(requestPermission(QWebEnginePermission))); QSignalSpy spyLoadFinished(newPage, SIGNAL(loadFinished(bool))); newPage->setHtml(QString("test"), QUrl("qrc://secure/origin")); @@ -1656,8 +1657,9 @@ Q_OBJECT GetUserMediaTestPage() : m_gotRequest(false) , m_loadSucceeded(false) + , m_permission(nullptr) { - connect(this, &QWebEnginePage::featurePermissionRequested, this, &GetUserMediaTestPage::onFeaturePermissionRequested); + connect(this, &QWebEnginePage::permissionRequested, this, &GetUserMediaTestPage::onPermissionRequested); connect(this, &QWebEnginePage::loadFinished, [this](bool success){ m_loadSucceeded = success; }); @@ -1695,18 +1697,20 @@ Q_OBJECT void rejectPendingRequest() { - setFeaturePermission(m_requestSecurityOrigin, m_requestedFeature, QWebEnginePage::PermissionDeniedByUser); + QVERIFY(m_permission); + m_permission->deny(); m_gotRequest = false; } void acceptPendingRequest() { - setFeaturePermission(m_requestSecurityOrigin, m_requestedFeature, QWebEnginePage::PermissionGrantedByUser); + QVERIFY(m_permission); + m_permission->grant(); m_gotRequest = false; } - bool gotFeatureRequest(QWebEnginePage::Feature feature) + bool gotFeatureRequest(QWebEnginePermission::Feature feature) { - return m_gotRequest && m_requestedFeature == feature; + return m_gotRequest && m_permission && m_permission->feature() == feature; } bool gotFeatureRequest() const @@ -1720,50 +1724,47 @@ Q_OBJECT } private Q_SLOTS: - void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature) + void onPermissionRequested(QWebEnginePermission permission) { - m_requestedFeature = feature; - m_requestSecurityOrigin = securityOrigin; + m_permission.reset(new QWebEnginePermission(permission)); m_gotRequest = true; } private: bool m_gotRequest; bool m_loadSucceeded; - QWebEnginePage::Feature m_requestedFeature; - QUrl m_requestSecurityOrigin; - + std::unique_ptr m_permission; }; void tst_QWebEnginePage::getUserMediaRequest_data() { QTest::addColumn("call"); - QTest::addColumn("feature"); + QTest::addColumn("feature"); QTest::addRow("device audio") - << "getUserMedia({audio: true})" << QWebEnginePage::MediaAudioCapture; + << "getUserMedia({audio: true})" << QWebEnginePermission::MediaAudioCapture; QTest::addRow("device video") - << "getUserMedia({video: true})" << QWebEnginePage::MediaVideoCapture; + << "getUserMedia({video: true})" << QWebEnginePermission::MediaVideoCapture; QTest::addRow("device audio+video") - << "getUserMedia({audio: true, video: true})" << QWebEnginePage::MediaAudioVideoCapture; + << "getUserMedia({audio: true, video: true})" << QWebEnginePermission::MediaAudioVideoCapture; QTest::addRow("desktop video") << "getUserMedia({video: { mandatory: { chromeMediaSource: 'desktop' }}})" - << QWebEnginePage::DesktopVideoCapture; + << QWebEnginePermission::DesktopVideoCapture; QTest::addRow("desktop audio+video") << "getUserMedia({audio: { mandatory: { chromeMediaSource: 'desktop' }}, video: { mandatory: { chromeMediaSource: 'desktop' }}})" - << QWebEnginePage::DesktopAudioVideoCapture; + << QWebEnginePermission::DesktopAudioVideoCapture; QTest::addRow("display video") - << "getDisplayMedia()" << QWebEnginePage::DesktopVideoCapture; + << "getDisplayMedia()" << QWebEnginePermission::DesktopVideoCapture; } void tst_QWebEnginePage::getUserMediaRequest() { QFETCH(QString, call); - QFETCH(QWebEnginePage::Feature, feature); + QFETCH(QWebEnginePermission::Feature, feature); GetUserMediaTestPage page; QWebEngineView view; - if (feature == QWebEnginePage::DesktopVideoCapture || feature == QWebEnginePage::DesktopAudioVideoCapture) { + if (feature == QWebEnginePermission::DesktopVideoCapture || feature == QWebEnginePermission::DesktopAudioVideoCapture) { // Desktop capture needs to be on a desktop. view.setPage(&page); view.resize(640, 480); @@ -1833,7 +1834,7 @@ void tst_QWebEnginePage::getUserMediaRequestSettingDisabled() void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyPages() { const QString constraints = QStringLiteral("{video: { mandatory: { chromeMediaSource: 'desktop' }}}"); - const QWebEnginePage::Feature feature = QWebEnginePage::DesktopVideoCapture; + const QWebEnginePermission::Feature feature = QWebEnginePermission::DesktopVideoCapture; std::vector pages(10); // Desktop capture needs to be on a desktop @@ -1866,7 +1867,7 @@ void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyPages() void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyRequests() { const QString constraints = QStringLiteral("{video: { mandatory: { chromeMediaSource: 'desktop' }}}"); - const QWebEnginePage::Feature feature = QWebEnginePage::DesktopVideoCapture; + const QWebEnginePermission::Feature feature = QWebEnginePermission::DesktopVideoCapture; GetUserMediaTestPage page; // Desktop capture needs to be on a desktop @@ -3795,20 +3796,30 @@ void tst_QWebEnginePage::dynamicFrame() struct NotificationPage : ConsolePage { Q_OBJECT - const QWebEnginePage::PermissionPolicy policy; + const QWebEnginePermission::State policy; public: - NotificationPage(QWebEnginePage::PermissionPolicy ppolicy) : policy(ppolicy) { + NotificationPage(QWebEnginePermission::State ppolicy) : policy(ppolicy) { connect(this, &QWebEnginePage::loadFinished, [load = spyLoad.ref()] (bool result) mutable { load(result); }); - connect(this, &QWebEnginePage::featurePermissionRequested, - [this] (const QUrl &origin, QWebEnginePage::Feature feature) { - if (feature != QWebEnginePage::Notifications) + connect(this, &QWebEnginePage::permissionRequested, + [this] (QWebEnginePermission permission) { + if (permission.feature() != QWebEnginePermission::Notifications) return; if (spyRequest.wasCalled()) QFAIL("request executed twise!"); - setFeaturePermission(origin, feature, policy); - spyRequest.ref()(origin); + switch (policy) { + case QWebEnginePermission::Granted: + permission.grant(); + break; + case QWebEnginePermission::Denied: + permission.deny(); + break; + case QWebEnginePermission::Ask: + permission.reset(); + break; + } + spyRequest.ref()(permission.origin()); }); load(QStringLiteral("qrc:///shared/notification.html")); @@ -3828,18 +3839,18 @@ struct NotificationPage : ConsolePage { void tst_QWebEnginePage::notificationPermission_data() { QTest::addColumn("setOnInit"); - QTest::addColumn("policy"); + QTest::addColumn("policy"); QTest::addColumn("permission"); - QTest::newRow("denyOnInit") << true << QWebEnginePage::PermissionDeniedByUser << "denied"; - QTest::newRow("deny") << false << QWebEnginePage::PermissionDeniedByUser << "denied"; - QTest::newRow("grant") << false << QWebEnginePage::PermissionGrantedByUser << "granted"; - QTest::newRow("grantOnInit") << true << QWebEnginePage::PermissionGrantedByUser << "granted"; + QTest::newRow("denyOnInit") << true << QWebEnginePermission::Denied << "denied"; + QTest::newRow("deny") << false << QWebEnginePermission::Denied << "denied"; + QTest::newRow("grant") << false << QWebEnginePermission::Granted << "granted"; + QTest::newRow("grantOnInit") << true << QWebEnginePermission::Granted << "granted"; } void tst_QWebEnginePage::notificationPermission() { QFETCH(bool, setOnInit); - QFETCH(QWebEnginePage::PermissionPolicy, policy); + QFETCH(QWebEnginePermission::State, policy); QFETCH(QString, permission); QWebEngineProfile otr; @@ -3849,20 +3860,33 @@ void tst_QWebEnginePage::notificationPermission() QUrl baseUrl("https://www.example.com/somepage.html"); bool permissionRequested = false, errorState = false; - connect(&page, &QWebEnginePage::featurePermissionRequested, &page, [&] (const QUrl &o, QWebEnginePage::Feature f) { - if (f != QWebEnginePage::Notifications) + connect(&page, &QWebEnginePage::permissionRequested, &page, [&] (QWebEnginePermission permission) { + if (permission.feature() != QWebEnginePermission::Notifications) return; - if (permissionRequested || o != baseUrl.url(/service/qurl::RemoveFilename)) { - qWarning() << "Unexpected case. Can't proceed." << setOnInit << permissionRequested << o; + if (permissionRequested || permission.origin() != baseUrl.url(/service/qurl::RemoveFilename)) { + qWarning() << "Unexpected case. Can't proceed." << setOnInit << permissionRequested << permission.origin(); errorState = true; return; } permissionRequested = true; - page.setFeaturePermission(o, f, policy); + + if (policy == QWebEnginePermission::Granted) + permission.grant(); + else + permission.deny(); }); if (setOnInit) - page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, policy); +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + // FIXME: Replace with QWebEngineProfile permission API when that's implemented + page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, + policy == QWebEnginePermission::Granted ? QWebEnginePage::PermissionGrantedByUser : QWebEnginePage::PermissionDeniedByUser); + QT_WARNING_POP +#else + W_QSKIP("Compiled without deprecated APIs", SkipSingle); +#endif // QT_DEPRECATED_SINCE(6, 8) QSignalSpy spy(&page, &QWebEnginePage::loadFinished); page.setHtml(QString("Test"), baseUrl); @@ -3871,8 +3895,17 @@ void tst_QWebEnginePage::notificationPermission() QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), setOnInit ? permission : QLatin1String("default")); if (!setOnInit) { - page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, policy); +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + // FIXME: Replace with QWebEngineProfile permission API when that's implemented + page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, + policy == QWebEnginePermission::Granted ? QWebEnginePage::PermissionGrantedByUser : QWebEnginePage::PermissionDeniedByUser); QTRY_COMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), permission); + QT_WARNING_POP +#else + W_QSKIP("Compiled without deprecated APIs", SkipSingle); +#endif // QT_DEPRECATED_SINCE(6, 8) } auto js = QStringLiteral("var permission; Notification.requestPermission().then(p => { permission = p })"); @@ -3885,7 +3918,7 @@ void tst_QWebEnginePage::notificationPermission() void tst_QWebEnginePage::sendNotification() { - NotificationPage page(QWebEnginePage::PermissionGrantedByUser); + NotificationPage page(QWebEnginePermission::Granted); QVERIFY(page.spyLoad.waitForResult()); page.resetPermission(); @@ -3973,42 +4006,42 @@ void tst_QWebEnginePage::clipboardReadWritePermissionInitialState() void tst_QWebEnginePage::clipboardReadWritePermission_data() { QTest::addColumn("canAccessClipboard"); - QTest::addColumn("initialPolicy"); + QTest::addColumn("initialPolicy"); QTest::addColumn("initialPermission"); - QTest::addColumn("requestPolicy"); + QTest::addColumn("requestPolicy"); QTest::addColumn("finalPermission"); QTest::newRow("noAccessGrantGrant") - << false << QWebEnginePage::PermissionGrantedByUser << "granted" - << QWebEnginePage::PermissionGrantedByUser << "granted"; + << false << QWebEnginePermission::Granted << "granted" + << QWebEnginePermission::Granted << "granted"; QTest::newRow("noAccessGrantDeny") - << false << QWebEnginePage::PermissionGrantedByUser << "granted" - << QWebEnginePage::PermissionDeniedByUser << "denied"; + << false << QWebEnginePermission::Granted << "granted" + << QWebEnginePermission::Denied << "denied"; QTest::newRow("noAccessDenyGrant") - << false << QWebEnginePage::PermissionDeniedByUser << "denied" - << QWebEnginePage::PermissionGrantedByUser << "granted"; - QTest::newRow("noAccessDenyDeny") << false << QWebEnginePage::PermissionDeniedByUser << "denied" - << QWebEnginePage::PermissionDeniedByUser << "denied"; - QTest::newRow("noAccessAskGrant") << false << QWebEnginePage::PermissionUnknown << "prompt" - << QWebEnginePage::PermissionGrantedByUser << "granted"; + << false << QWebEnginePermission::Denied << "denied" + << QWebEnginePermission::Granted << "granted"; + QTest::newRow("noAccessDenyDeny") << false << QWebEnginePermission::Denied << "denied" + << QWebEnginePermission::Denied << "denied"; + QTest::newRow("noAccessAskGrant") << false << QWebEnginePermission::Ask << "prompt" + << QWebEnginePermission::Granted << "granted"; // All policies are ignored and overridden by setting JsCanAccessClipboard and JsCanPaste to // true QTest::newRow("accessGrantGrant") - << true << QWebEnginePage::PermissionGrantedByUser << "granted" - << QWebEnginePage::PermissionGrantedByUser << "granted"; - QTest::newRow("accessDenyDeny") << true << QWebEnginePage::PermissionDeniedByUser << "granted" - << QWebEnginePage::PermissionDeniedByUser << "granted"; - QTest::newRow("accessAskAsk") << true << QWebEnginePage::PermissionUnknown << "granted" - << QWebEnginePage::PermissionUnknown << "granted"; + << true << QWebEnginePermission::Granted << "granted" + << QWebEnginePermission::Granted << "granted"; + QTest::newRow("accessDenyDeny") << true << QWebEnginePermission::Denied << "granted" + << QWebEnginePermission::Denied << "granted"; + QTest::newRow("accessAskAsk") << true << QWebEnginePermission::Ask << "granted" + << QWebEnginePermission::Ask << "granted"; } void tst_QWebEnginePage::clipboardReadWritePermission() { QFETCH(bool, canAccessClipboard); - QFETCH(QWebEnginePage::PermissionPolicy, initialPolicy); + QFETCH(QWebEnginePermission::State, initialPolicy); QFETCH(QString, initialPermission); - QFETCH(QWebEnginePage::PermissionPolicy, requestPolicy); + QFETCH(QWebEnginePermission::State, requestPolicy); QFETCH(QString, finalPermission); QWebEngineProfile otr; @@ -4026,20 +4059,43 @@ void tst_QWebEnginePage::clipboardReadWritePermission() bool errorState = false; // if JavascriptCanAccessClipboard is true, this never fires - connect(&page, &QWebEnginePage::featurePermissionRequested, &page, - [&](const QUrl &o, QWebEnginePage::Feature f) { - if (f != QWebEnginePage::ClipboardReadWrite) + connect(&page, &QWebEnginePage::permissionRequested, &page, + [&](QWebEnginePermission permission) { + if (permission.feature() != QWebEnginePermission::ClipboardReadWrite) return; - if (o != baseUrl.url(/service/qurl::RemoveFilename)) { - qWarning() << "Unexpected case. Can't proceed." << o; + if (permission.origin() != baseUrl.url(/service/qurl::RemoveFilename)) { + qWarning() << "Unexpected case. Can't proceed." << permission.origin(); errorState = true; return; } permissionRequestCount++; - page.setFeaturePermission(o, f, requestPolicy); + switch (requestPolicy) { + case QWebEnginePermission::Granted: + permission.grant(); + break; + case QWebEnginePermission::Denied: + permission.deny(); + break; + case QWebEnginePermission::Ask: + permission.reset(); + break; + default: + break; + } }); - page.setFeaturePermission(baseUrl, QWebEnginePage::ClipboardReadWrite, initialPolicy); + // FIXME: Replace with QWebEngineProfile permission API when that's implemented +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + QWebEnginePage::PermissionPolicy deprecatedPolicy = + initialPolicy == QWebEnginePermission::Granted ? QWebEnginePage::PermissionGrantedByUser + : (initialPolicy == QWebEnginePermission::Denied ? QWebEnginePage::PermissionDeniedByUser : QWebEnginePage::PermissionUnknown); + page.setFeaturePermission(baseUrl, QWebEnginePage::ClipboardReadWrite, deprecatedPolicy); + QT_WARNING_POP +#else + W_QSKIP("Compiled without deprecated APIs", SkipSingle); +#endif // QT_DEPRECATED_SINCE(6, 8) QSignalSpy spy(&page, &QWebEnginePage::loadFinished); page.setHtml(QString("Test"), baseUrl); @@ -4099,17 +4155,17 @@ void tst_QWebEnginePage::contentsSize() void tst_QWebEnginePage::localFontAccessPermission_data() { - QTest::addColumn("policy"); + QTest::addColumn("policy"); QTest::addColumn("ignore"); QTest::addColumn("shouldBeEmpty"); - QTest::newRow("ignore") << QWebEnginePage::PermissionDeniedByUser << true << true; - QTest::newRow("setDeny") << QWebEnginePage::PermissionDeniedByUser << false << true; - QTest::newRow("setGrant") << QWebEnginePage::PermissionGrantedByUser << false << false; + QTest::newRow("ignore") << QWebEnginePermission::Denied << true << true; + QTest::newRow("setDeny") << QWebEnginePermission::Denied << false << true; + QTest::newRow("setGrant") << QWebEnginePermission::Granted << false << false; } void tst_QWebEnginePage::localFontAccessPermission() { - QFETCH(QWebEnginePage::PermissionPolicy, policy); + QFETCH(QWebEnginePermission::State, policy); QFETCH(bool, ignore); QFETCH(bool, shouldBeEmpty); @@ -4118,12 +4174,16 @@ void tst_QWebEnginePage::localFontAccessPermission() { page.profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); view.setPage(&page); - connect(&page, &QWebEnginePage::featurePermissionRequested, &page, [&] (const QUrl &o, QWebEnginePage::Feature f) { - if (f != QWebEnginePage::LocalFontsAccess) + connect(&page, &QWebEnginePage::permissionRequested, &page, [&] (QWebEnginePermission permission) { + if (permission.feature() != QWebEnginePermission::LocalFontsAccess) return; - if (!ignore) - page.setFeaturePermission(o, f, policy); + if (!ignore) { + if (policy == QWebEnginePermission::Granted) + permission.grant(); + else + permission.deny(); + } }); QSignalSpy spy(&page, &QWebEnginePage::loadFinished); @@ -5734,12 +5794,11 @@ void tst_QWebEnginePage::chooseDesktopMedia() desktopMediaRequested = true; }); - connect(&page, &QWebEnginePage::featurePermissionRequested, - [&](const QUrl &securityOrigin, QWebEnginePage::Feature feature) { + connect(&page, &QWebEnginePage::permissionRequested, + [&](QWebEnginePermission permission) { permissionRequested = true; // Handle permission to 'complete' the media request - page.setFeaturePermission(securityOrigin, feature, - QWebEnginePage::PermissionGrantedByUser); + permission.grant(); }); page.load(QUrl(server.url())); diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index ef069ac1c69..81800658650 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -1051,8 +1051,15 @@ void tst_QWebEngineProfile::permissionPersistence() QVariant variant = granted ? "granted" : "denied"; QVariant defaultVariant = "default"; +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED page->setFeaturePermission(server.url("https://github.com/hedgehog.html"), QWebEnginePage::Notifications, granted ? QWebEnginePage::PermissionGrantedByUser : QWebEnginePage::PermissionDeniedByUser); + QT_WARNING_POP +#else + W_QSKIP("Compiled without deprecated APIs", SkipSingle); +#endif // QT_DEPRECATED_SINCE(6, 8) QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), variant); page.reset(); @@ -1077,7 +1084,14 @@ void tst_QWebEngineProfile::permissionPersistence() QTRY_COMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), expectSame ? variant : defaultVariant); +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED page->setFeaturePermission(server.url("https://github.com/hedgehog.html"), QWebEnginePage::Notifications, QWebEnginePage::PermissionUnknown); + QT_WARNING_POP +#else + W_QSKIP("Compiled without deprecated APIs", SkipSingle); +#endif // QT_DEPRECATED_SINCE(6, 8) QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), defaultVariant); page.reset(); diff --git a/tests/manual/quick/geopermission/tst_geopermission.qml b/tests/manual/quick/geopermission/tst_geopermission.qml index 36317c176ae..ace48d464d4 100644 --- a/tests/manual/quick/geopermission/tst_geopermission.qml +++ b/tests/manual/quick/geopermission/tst_geopermission.qml @@ -13,14 +13,14 @@ WebEngineView { property bool deniedGeolocation: false property bool geoPermissionRequested: false - onFeaturePermissionRequested: function(securityOrigin, feature) { - if (feature === WebEngineView.Geolocation) { + onPermissionRequested: function(perm) { + if (perm.feature === WebEnginePermission.Geolocation) { geoPermissionRequested = true if (deniedGeolocation) { - webEngineView.grantFeaturePermission(securityOrigin, feature, false) + perm.deny() } else { - webEngineView.grantFeaturePermission(securityOrigin, feature, true) + perm.grant() } } } diff --git a/tests/manual/widgets/geolocation/main.cpp b/tests/manual/widgets/geolocation/main.cpp index f33cf5798b7..1f4cefe54e4 100644 --- a/tests/manual/widgets/geolocation/main.cpp +++ b/tests/manual/widgets/geolocation/main.cpp @@ -16,18 +16,15 @@ class GeoPermissionWebView : public QWebEngineView { Q_OBJECT public slots: - void handleFeaturePermissionRequested(const QUrl &securityOrigin, - QWebEnginePage::Feature feature) + void handlePermissionRequested(QWebEnginePermission permission) { qWarning("Feature Permission"); QString title = tr("Permission Request"); QString question = QLatin1String("Allow access to geolocation?"); if (!question.isEmpty() && QMessageBox::question(window(), title, question) == QMessageBox::Yes) - page()->setFeaturePermission(securityOrigin, feature, - QWebEnginePage::PermissionGrantedByUser); + permission.grant(); else - page()->setFeaturePermission(securityOrigin, feature, - QWebEnginePage::PermissionDeniedByUser); + permission.deny(); } }; @@ -38,8 +35,8 @@ int main(int argc, char *argv[]) QMainWindow w; GeoPermissionWebView webview; QWebEnginePage page; - QObject::connect(&page, &QWebEnginePage::featurePermissionRequested, &webview, - &GeoPermissionWebView::handleFeaturePermissionRequested); + QObject::connect(&page, &QWebEnginePage::permissionRequested, &webview, + &GeoPermissionWebView::handlePermissionRequested); webview.setPage(&page); page.load(QUrl("qrc:/geolocation.html")); w.setCentralWidget(&webview); diff --git a/tests/manual/widgets/webrtc/main.cpp b/tests/manual/widgets/webrtc/main.cpp index 328e4ae3674..b5718159c8b 100644 --- a/tests/manual/widgets/webrtc/main.cpp +++ b/tests/manual/widgets/webrtc/main.cpp @@ -35,19 +35,19 @@ private slots: Page::Page(QWebEngineProfile *profile, QObject *parent) : QWebEnginePage(profile, parent) { settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); - connect(this, &QWebEnginePage::featurePermissionRequested, this, + connect(this, &QWebEnginePage::permissionRequested, this, &Page::handlePermissionRequest); connect(this, &QWebEnginePage::desktopMediaRequested, this, &Page::handleDesktopMediaRequest); } -void Page::handlePermissionRequest(const QUrl &origin, Feature feature) +void Page::handlePermissionRequest(QWebEnginePermission permission) { if (QMessageBox::question(QApplication::activeWindow(), tr("Permission request"), tr("allow access?")) == QMessageBox::Yes) - setFeaturePermission(origin, feature, PermissionGrantedByUser); + permission.grant(); else - setFeaturePermission(origin, feature, PermissionDeniedByUser); + permission.deny(); } void Page::handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request) From ec2391243e3e6772fe1c87c72427148fae28cbe1 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Wed, 3 Apr 2024 16:46:57 +0200 Subject: [PATCH 004/341] Implement API for listing existing permissions in a profile QWebEngineProfile and QQuickWebEngineProfile now have methods for either getting one specific permission object, or for getting a list of all the permissions currently stored. The methods for listing also have overloads for filtering based on origin or Feature type. Change-Id: I07241bcb3ff171fa8b82547c2b5f094071bebe44 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 7ad9ee5c5ef109a91fbc83e86b351f399e96d194) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineprofile.cpp | 90 +++++++++++ src/core/api/qwebengineprofile.h | 6 + src/core/permission_manager_qt.cpp | 60 +++++++- src/core/permission_manager_qt.h | 2 + src/core/profile_adapter.cpp | 11 ++ src/core/profile_adapter.h | 2 + .../api/qquickwebengineprofile.cpp | 142 ++++++++++++++++++ .../api/qquickwebengineprofile.h | 6 + tests/auto/quick/publicapi/tst_publicapi.cpp | 8 +- .../qwebenginepage/tst_qwebenginepage.cpp | 60 ++++---- .../tst_qwebengineprofile.cpp | 128 +++++++++++++--- 11 files changed, 458 insertions(+), 57 deletions(-) diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index a9477929ba9..5d7bb5559b2 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -11,6 +11,7 @@ #include "qwebenginesettings.h" #include "qwebenginescriptcollection.h" #include "qwebenginescriptcollection_p.h" +#include "qwebenginepermission_p.h" #include "qtwebenginecoreglobal.h" #include "profile_adapter.h" #include "visited_links_manager_qt.h" @@ -976,6 +977,95 @@ void QWebEngineProfile::requestIconForIconURL(const QUrl &url, int desiredSizeIn iconAvailableCallback); } +/*! + * Returns a QWebEnginePermission object corresponding to a single permission for the provided \a securityOrigin and + * \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + * for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is + * known to use it. + * + * \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + * \since 6.8 + * \sa listPermissions(), QWebEnginePermission::Feature + */ +QWebEnginePermission QWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const +{ + Q_D(const QWebEngineProfile); + + if (feature == QWebEnginePermission::Unsupported) { + qWarning("Attempting to get unsupported permission. Returned object will be in an invalid state."); + return QWebEnginePermission(new QWebEnginePermissionPrivate()); + } + + if (QWebEnginePermission::isTransient(feature)) { + qWarning() << "Attempting to get permission for feature" << feature << ". Returned object will be in an invalid state."; + return QWebEnginePermission(new QWebEnginePermissionPrivate()); + } + + auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, feature, nullptr, d->profileAdapter()); + return QWebEnginePermission(pvt); +} + +/*! + * Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + * present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, + * except for those of a transient feature type. + * + * \since 6.8 + * \sa getPermission(), QWebEnginePermission::Feature + */ +QList QWebEngineProfile::listPermissions() const +{ + Q_D(const QWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList(); + return d->profileAdapter()->listPermissions(); +} + +/*! + * Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + * present in the permissions store. The returned list contains all previously granted/denied permissions associated with a + * specific \a securityOrigin for this profile, except for those of a transient feature type. + * + * \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its + * origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html + * is the same as passing just https://www.example.com/. + * \since 6.8 + * \sa getPermission(), QWebEnginePermission::Feature + */ +QList QWebEngineProfile::listPermissions(const QUrl &securityOrigin) const +{ + Q_D(const QWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList(); + return d->profileAdapter()->listPermissions(securityOrigin); +} + +/*! + * Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + * present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature + * type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + * \since 6.8 + * \sa getPermission(), QWebEnginePermission::Feature + */ +QList QWebEngineProfile::listPermissions(QWebEnginePermission::Feature feature) const +{ + Q_D(const QWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList(); + + if (feature == QWebEnginePermission::Unsupported) { + qWarning("Attempting to get permission list for an unsupported type. Returned list will be empty."); + return QList(); + } + + if (QWebEnginePermission::isTransient(feature)) { + qWarning() << "Attempting to get permission list for feature" << feature << ". Returned list will be empty."; + return QList(); + } + + return d->profileAdapter()->listPermissions(QUrl(), feature); +} + /*! Return the Client Hints settings associated with this browsing context. diff --git a/src/core/api/qwebengineprofile.h b/src/core/api/qwebengineprofile.h index 259de4bff4f..573f39e7dd3 100644 --- a/src/core/api/qwebengineprofile.h +++ b/src/core/api/qwebengineprofile.h @@ -5,6 +5,7 @@ #define QWEBENGINEPROFILE_H #include +#include #include #include @@ -120,6 +121,11 @@ class Q_WEBENGINECORE_EXPORT QWebEngineProfile : public QObject void requestIconForPageURL(const QUrl &url, int desiredSizeInPixel, std::function iconAvailableCallback) const; void requestIconForIconURL(const QUrl &url, int desiredSizeInPixel, std::function iconAvailableCallback) const; + QWebEnginePermission getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const; + QList listPermissions() const; + QList listPermissions(const QUrl &securityOrigin) const; + QList listPermissions(QWebEnginePermission::Feature feature) const; + static QWebEngineProfile *defaultProfile(); Q_SIGNALS: diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 6883d222404..63189c1d7a0 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -21,6 +21,7 @@ #include "components/proxy_config/pref_proxy_config_tracker_impl.h" #include "components/prefs/pref_service.h" +#include #include "type_conversion.h" #include "web_contents_delegate_qt.h" #include "web_engine_settings.h" @@ -190,13 +191,19 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) factory.set_user_prefs(new InMemoryPrefStore); } + m_featureTypes.push_back(QWebEnginePermission::Notifications); + m_featureTypes.push_back(QWebEnginePermission::Geolocation); + m_featureTypes.push_back(QWebEnginePermission::ClipboardReadWrite); + m_featureTypes.push_back(QWebEnginePermission::LocalFontsAccess); + + // Transient, but the implementation relies on them being written to storage + m_featureTypes.push_back(QWebEnginePermission::MediaAudioCapture); + m_featureTypes.push_back(QWebEnginePermission::MediaVideoCapture); + // Register all preference types as keys prior to doing anything else - prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::Geolocation)); - prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::ClipboardReadWrite)); - prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::Notifications)); - prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::LocalFontsAccess)); - prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::MediaAudioCapture)); - prefRegistry->RegisterDictionaryPref(featureString(QWebEnginePermission::MediaVideoCapture)); + for (auto &type : m_featureTypes) { + prefRegistry->RegisterDictionaryPref(featureString(type)); + } PrefProxyConfigTrackerImpl::RegisterPrefs(prefRegistry.get()); if (policy == ProfileAdapter::NoPersistentPermissions) @@ -284,6 +291,47 @@ QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl & return toQt(GetPermissionStatus(toBlink(feature), toGurl(https://github.com/origin), GURL())); } +QList PermissionManagerQt::listPermissions(const QUrl &origin, QWebEnginePermission::Feature feature) +{ + Q_ASSERT(origin.isEmpty() || feature == QWebEnginePermission::Unsupported); + QList returnList; + GURL gorigin = toGurl(https://github.com/origin).DeprecatedGetOriginAsURL(); + std::string originSpec = gorigin.spec(); + + if (!origin.isEmpty() && !gorigin.is_valid()) + return returnList; + + std::vector types; + if (feature == QWebEnginePermission::Unsupported) + types = m_featureTypes; + else + types.push_back(feature); + + for (auto &type : types) { + // Transient types may end up in the permission store as an implementation detail, + // but we do not want to expose them to callers. + if (QWebEnginePermission::isTransient(type)) + continue; + + auto *pref = m_prefService->FindPreference(featureString(type)); + if (!pref) + continue; + + auto *prefDict = pref->GetValue()->GetIfDict(); + Q_ASSERT(prefDict); + + for (const auto &entry : *prefDict) { + if (!originSpec.empty() && entry.first != originSpec) + continue; + + auto *pvt = new QWebEnginePermissionPrivate(toQt(GURL(std::string_view(entry.first))), type, nullptr, m_profileAdapter.get()); + returnList.push_back(QWebEnginePermission(pvt)); + } + } + + return returnList; +} + void PermissionManagerQt::commit() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index e74a3fba126..ebab613d616 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -24,6 +24,7 @@ class PermissionManagerQt : public content::PermissionControllerDelegate void setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state); QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature); + QList listPermissions(const QUrl &origin, QWebEnginePermission::Feature feature); void commit(); @@ -90,6 +91,7 @@ class PermissionManagerQt : public content::PermissionControllerDelegate std::vector m_requests; std::vector m_multiRequests; + std::vector m_featureTypes; std::map m_subscribers; content::PermissionControllerDelegate::SubscriptionId::Generator subscription_id_generator_; int m_requestIdCount; diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 4b337e8ed3c..c0906003acb 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -576,9 +576,20 @@ void ProfileAdapter::setPermission(const QUrl &origin, QWebEnginePermission::Fea QWebEnginePermission::State ProfileAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature) { + if (persistentPermissionsPolicy() == ProfileAdapter::NoPersistentPermissions) + return QWebEnginePermission::Ask; + return static_cast(profile()->GetPermissionControllerDelegate())->getPermissionState(origin, feature); } +QList ProfileAdapter::listPermissions(const QUrl &origin, QWebEnginePermission::Feature feature) +{ + if (persistentPermissionsPolicy() == ProfileAdapter::NoPersistentPermissions) + return QList(); + + return static_cast(profile()->GetPermissionControllerDelegate())->listPermissions(origin, feature); +} + QString ProfileAdapter::httpAcceptLanguageWithoutQualities() const { const QStringList list = m_httpAcceptLanguage.split(QLatin1Char(',')); diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 644d7e03c32..6550e617696 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -174,6 +174,7 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject void setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state); QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature); + QList listPermissions(const QUrl &origin = QUrl(), QWebEnginePermission::Feature feature = QWebEnginePermission::Unsupported); QString httpAcceptLanguageWithoutQualities() const; QString httpAcceptLanguage() const; @@ -185,6 +186,7 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject void setClientHintsEnabled(bool enabled); void resetClientHints(); + void clearHttpCache(); #if QT_CONFIG(ssl) diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index ae55bb1bd96..d3373d0b9b7 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -1113,6 +1114,147 @@ QWebEngineClientHints *QQuickWebEngineProfile::clientHints() const return d->m_clientHints.data(); } +/*! + \fn QQuickWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const + + Returns a QWebEnginePermission object corresponding to a single permission for the provided \a securityOrigin and + \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is + known to use it. + + \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + \since 6.8 + \sa listPermissions(), QWebEnginePermission::Feature + */ + +/*! + \qmlmethod void WebEngineProfile::getPermission(url securityOrigin, WebEnginePermission.Feature feature) const + + Returns a webEnginePermission object corresponding to a single permission for the provided \a securityOrigin and + \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is + known to use it. + + \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + \since 6.8 + \sa listPermissions() + */ +QWebEnginePermission QQuickWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const +{ + Q_D(const QQuickWebEngineProfile); + + if (feature == QWebEnginePermission::Unsupported) { + qWarning("Attempting to get unsupported permission. Returned object will be in an invalid state."); + return QWebEnginePermission(new QWebEnginePermissionPrivate()); + } + + if (QWebEnginePermission::isTransient(feature)) { + qWarning() << "Attempting to get permission for feature" << feature << ". Returned object will be in an invalid state."; + return QWebEnginePermission(new QWebEnginePermissionPrivate()); + } + + auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, feature, nullptr, d->profileAdapter()); + return QWebEnginePermission(pvt); +} + +/*! + \qmlmethod list WebEngineProfile::listPermissions() const + + Returns a \l list of webEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, + except for those of a transient feature type. + + \since 6.8 + \sa getPermission() + */ + +/*! + Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, + except for those of a transient feature type. + + \since 6.8 + \sa getPermission() + */ +QList QQuickWebEngineProfile::listPermissions() const +{ + Q_D(const QQuickWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList(); + return d->profileAdapter()->listPermissions(); +} + +/*! + \qmlmethod list WebEngineProfile::listPermissions(url securityOrigin) const + + Returns a \l list of webEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions associated with a + specific \a securityOrigin for this profile, except for those of a transient feature type. + + \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its + origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html + is the same as passing just https://www.example.com/. + \since 6.8 + \sa getPermission() + */ + +/*! + Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions associated with a + specific \a securityOrigin for this profile, except for those of a transient feature type. + + \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its + origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html + is the same as passing just https://www.example.com/. + \since 6.8 + \sa getPermission() + */ +QList QQuickWebEngineProfile::listPermissions(const QUrl &securityOrigin) const +{ + Q_D(const QQuickWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList(); + return d->profileAdapter()->listPermissions(securityOrigin); +} + +/*! + \qmlmethod list WebEngineProfile::listPermissions(WebEnginePermission.Feature feature) const + + Returns a \l list of webEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature + type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + + \since 6.8 + \sa getPermission() + */ + +/*! + Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature + type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + + \since 6.8 + \sa getPermission(), QWebEnginePermission::Feature + */ +QList QQuickWebEngineProfile::listPermissions(QWebEnginePermission::Feature feature) const +{ + Q_D(const QQuickWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList(); + + if (feature == QWebEnginePermission::Unsupported) { + qWarning("Attempting to get permission list for an unsupported type. Returned list will be empty."); + return QList(); + } + + if (QWebEnginePermission::isTransient(feature)) { + qWarning() << "Attempting to get permission list for feature" << feature << ". Returned list will be empty."; + return QList(); + } + + return d->profileAdapter()->listPermissions(QUrl(), feature); +} + void QQuickWebEngineProfile::ensureQmlContext(const QObject *object) { if (!qmlContext(this)) { diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h index 7ba9105ffa9..186a11d7bc4 100644 --- a/src/webenginequick/api/qquickwebengineprofile.h +++ b/src/webenginequick/api/qquickwebengineprofile.h @@ -5,6 +5,7 @@ #define QQUICKWEBENGINEPROFILE_H #include +#include #include #include #include @@ -127,6 +128,11 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject { QWebEngineClientCertificateStore *clientCertificateStore(); QWebEngineClientHints *clientHints() const; + Q_REVISION(6,8) Q_INVOKABLE QWebEnginePermission getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const; + Q_REVISION(6,8) Q_INVOKABLE QList listPermissions() const; + Q_REVISION(6,8) Q_INVOKABLE QList listPermissions(const QUrl &securityOrigin) const; + Q_REVISION(6,8) Q_INVOKABLE QList listPermissions(QWebEnginePermission::Feature feature) const; + static QQuickWebEngineProfile *defaultProfile(); Q_SIGNALS: diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index cf0e59274df..dbe9513f20e 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -98,7 +98,9 @@ static const QStringList hardcodedTypes = QStringList() << "Qt::LayoutDirection" << "QQuickWebEngineScriptCollection*" << "QQmlComponent*" - << "QMultiMap"; + << "QMultiMap" + << "QList" + ; static const QStringList expectedAPI = QStringList() << "QQuickWebEngineAction.text --> QString" @@ -397,6 +399,10 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadRequest*) --> void" << "QQuickWebEngineProfile.downloadPath --> QString" << "QQuickWebEngineProfile.downloadPathChanged() --> void" + << "QQuickWebEngineProfile.getPermission(QUrl,QWebEnginePermission::Feature) --> QWebEnginePermission" + << "QQuickWebEngineProfile.listPermissions() --> QList" + << "QQuickWebEngineProfile.listPermissions(QUrl) --> QList" + << "QQuickWebEngineProfile.listPermissions(QWebEnginePermission::Feature) --> QList" << "QQuickWebEngineProfile.persistentPermissionsPolicy --> QQuickWebEngineProfile::PersistentPermissionsPolicy" << "QQuickWebEngineProfile.persistentPermissionsPolicyChanged() --> void" << "QQuickWebEngineProfile.presentNotification(QWebEngineNotification*) --> void" diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 8b6ea31fd41..e7f2ce1cd7a 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -3818,6 +3818,8 @@ struct NotificationPage : ConsolePage { case QWebEnginePermission::Ask: permission.reset(); break; + default: + break; } spyRequest.ref()(permission.origin()); }); @@ -3876,17 +3878,13 @@ void tst_QWebEnginePage::notificationPermission() permission.deny(); }); - if (setOnInit) -#if QT_DEPRECATED_SINCE(6, 8) - QT_WARNING_PUSH - QT_WARNING_DISABLE_DEPRECATED - // FIXME: Replace with QWebEngineProfile permission API when that's implemented - page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, - policy == QWebEnginePermission::Granted ? QWebEnginePage::PermissionGrantedByUser : QWebEnginePage::PermissionDeniedByUser); - QT_WARNING_POP -#else - W_QSKIP("Compiled without deprecated APIs", SkipSingle); -#endif // QT_DEPRECATED_SINCE(6, 8) + QWebEnginePermission permissionObject = otr.getPermission(baseUrl, QWebEnginePermission::Notifications); + if (setOnInit) { + if (policy == QWebEnginePermission::Granted) + permissionObject.grant(); + else + permissionObject.deny(); + } QSignalSpy spy(&page, &QWebEnginePage::loadFinished); page.setHtml(QString("Test"), baseUrl); @@ -3895,17 +3893,11 @@ void tst_QWebEnginePage::notificationPermission() QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), setOnInit ? permission : QLatin1String("default")); if (!setOnInit) { -#if QT_DEPRECATED_SINCE(6, 8) - QT_WARNING_PUSH - QT_WARNING_DISABLE_DEPRECATED - // FIXME: Replace with QWebEngineProfile permission API when that's implemented - page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, - policy == QWebEnginePermission::Granted ? QWebEnginePage::PermissionGrantedByUser : QWebEnginePage::PermissionDeniedByUser); + if (policy == QWebEnginePermission::Granted) + permissionObject.grant(); + else + permissionObject.deny(); QTRY_COMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), permission); - QT_WARNING_POP -#else - W_QSKIP("Compiled without deprecated APIs", SkipSingle); -#endif // QT_DEPRECATED_SINCE(6, 8) } auto js = QStringLiteral("var permission; Notification.requestPermission().then(p => { permission = p })"); @@ -4084,18 +4076,20 @@ void tst_QWebEnginePage::clipboardReadWritePermission() } }); - // FIXME: Replace with QWebEngineProfile permission API when that's implemented -#if QT_DEPRECATED_SINCE(6, 8) - QT_WARNING_PUSH - QT_WARNING_DISABLE_DEPRECATED - QWebEnginePage::PermissionPolicy deprecatedPolicy = - initialPolicy == QWebEnginePermission::Granted ? QWebEnginePage::PermissionGrantedByUser - : (initialPolicy == QWebEnginePermission::Denied ? QWebEnginePage::PermissionDeniedByUser : QWebEnginePage::PermissionUnknown); - page.setFeaturePermission(baseUrl, QWebEnginePage::ClipboardReadWrite, deprecatedPolicy); - QT_WARNING_POP -#else - W_QSKIP("Compiled without deprecated APIs", SkipSingle); -#endif // QT_DEPRECATED_SINCE(6, 8) + QWebEnginePermission permissionObject = otr.getPermission(baseUrl, QWebEnginePermission::ClipboardReadWrite); + switch (initialPolicy) { + case QWebEnginePermission::Granted: + permissionObject.grant(); + break; + case QWebEnginePermission::Denied: + permissionObject.deny(); + break; + case QWebEnginePermission::Ask: + permissionObject.reset(); + break; + default: + break; + } QSignalSpy spy(&page, &QWebEnginePage::loadFinished); page.setHtml(QString("Test"), baseUrl); diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 81800658650..6245a6c7a23 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -58,6 +58,9 @@ private Q_SLOTS: void badDeleteOrder(); void permissionPersistence_data(); void permissionPersistence(); + void getPermission_data(); + void getPermission(); + void listPermissions(); void qtbug_71895(); // this should be the last test }; @@ -1051,15 +1054,12 @@ void tst_QWebEngineProfile::permissionPersistence() QVariant variant = granted ? "granted" : "denied"; QVariant defaultVariant = "default"; -#if QT_DEPRECATED_SINCE(6, 8) - QT_WARNING_PUSH - QT_WARNING_DISABLE_DEPRECATED - page->setFeaturePermission(server.url("https://github.com/hedgehog.html"), QWebEnginePage::Notifications, - granted ? QWebEnginePage::PermissionGrantedByUser : QWebEnginePage::PermissionDeniedByUser); - QT_WARNING_POP -#else - W_QSKIP("Compiled without deprecated APIs", SkipSingle); -#endif // QT_DEPRECATED_SINCE(6, 8) + + QWebEnginePermission permissionObject = profile->getPermission(server.url("https://github.com/hedgehog.html"), QWebEnginePermission::Notifications); + if (granted) + permissionObject.grant(); + else + permissionObject.deny(); QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), variant); page.reset(); @@ -1084,14 +1084,9 @@ void tst_QWebEngineProfile::permissionPersistence() QTRY_COMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), expectSame ? variant : defaultVariant); -#if QT_DEPRECATED_SINCE(6, 8) - QT_WARNING_PUSH - QT_WARNING_DISABLE_DEPRECATED - page->setFeaturePermission(server.url("https://github.com/hedgehog.html"), QWebEnginePage::Notifications, QWebEnginePage::PermissionUnknown); - QT_WARNING_POP -#else - W_QSKIP("Compiled without deprecated APIs", SkipSingle); -#endif // QT_DEPRECATED_SINCE(6, 8) + // Re-acquire the permission, since deleting the Profile makes it invalid + permissionObject = profile->getPermission(server.url("https://github.com/hedgehog.html"), QWebEnginePermission::Notifications); + permissionObject.reset(); QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), defaultVariant); page.reset(); @@ -1107,6 +1102,105 @@ void tst_QWebEngineProfile::permissionPersistence() QVERIFY(server.stop()); } +void tst_QWebEngineProfile::getPermission_data() +{ + QTest::addColumn("feature"); + QTest::addColumn("url"); + QTest::addColumn("expectedValid"); + + QTest::newRow("badUrl") << QWebEnginePermission::Notifications << QUrl(QStringLiteral("//:bad-url")) << false; + QTest::newRow("badFeature") << QWebEnginePermission::Unsupported << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << false; + QTest::newRow("transientFeature") << QWebEnginePermission::MouseLock << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << false; + QTest::newRow("good") << QWebEnginePermission::Notifications << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << true; +} + +void tst_QWebEngineProfile::getPermission() +{ + QFETCH(QWebEnginePermission::Feature, feature); + QFETCH(QUrl, url); + QFETCH(bool, expectedValid); + + QWebEngineProfile profile; + // In-memory is the default for otr profiles + QVERIFY(profile.persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsInMemory); + + QWebEnginePermission permission = profile.getPermission(url, feature); + bool valid = permission.isValid(); + QVERIFY(valid == expectedValid); + if (!valid) + QVERIFY(permission.state() == QWebEnginePermission::Invalid); + + // Verify that we can grant a valid permission, and we can't grant an invalid one... + permission.grant(); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::Granted : QWebEnginePermission::Invalid)); + + // ...and that doing so twice doesn't mess up the state... + permission.grant(); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::Granted : QWebEnginePermission::Invalid)); + + // ...and that the same thing applies to denying them... + permission.deny(); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::Denied : QWebEnginePermission::Invalid)); + permission.deny(); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::Denied : QWebEnginePermission::Invalid)); + + // ...and that resetting works + permission.reset(); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::Ask : QWebEnginePermission::Invalid)); + permission.reset(); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::Ask : QWebEnginePermission::Invalid)); +} + +void tst_QWebEngineProfile::listPermissions() +{ + QWebEngineProfile profile; + // In-memory is the default for otr profiles + QVERIFY(profile.persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsInMemory); + + QUrl commonUrl = QUrl(QStringLiteral("http://www.bing.com/maps")); + QWebEnginePermission::Feature commonFeature = QWebEnginePermission::Notifications; + + // First, set several permissions at once + profile.getPermission(commonUrl, QWebEnginePermission::Geolocation).deny(); + profile.getPermission(commonUrl, QWebEnginePermission::Unsupported).grant(); // Invalid + profile.getPermission(commonUrl, commonFeature).grant(); + profile.getPermission(QUrl(QStringLiteral("http://www.google.com/translate")), commonFeature).grant(); + + QList permissionsListAll = profile.listPermissions(); + QList permissionsListUrl = profile.listPermissions(commonUrl); + QList permissionsListFeature = profile.listPermissions(commonFeature); + + // Order of returned permissions is not guaranteed, so we must iterate until we find the one we need + auto findInList = [](QList list, const QUrl &url, + QWebEnginePermission::Feature feature, QWebEnginePermission::State state) + { + bool found = false; + for (auto &permission : list) { + if (permission.origin().adjusted(QUrl::RemovePath) == url.adjusted(QUrl::RemovePath) && permission.feature() == feature && permission.state() == state) { + found = true; + break; + } + } + return found; + }; + + // Check full list + QVERIFY(permissionsListAll.size() == 3); + QVERIFY(findInList(permissionsListAll, commonUrl, QWebEnginePermission::Geolocation, QWebEnginePermission::Denied)); + QVERIFY(findInList(permissionsListAll, commonUrl, commonFeature, QWebEnginePermission::Granted)); + QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("http://www.google.com/")), commonFeature, QWebEnginePermission::Granted)); + + // Check list filtered by URL + QVERIFY(permissionsListUrl.size() == 2); + QVERIFY(findInList(permissionsListUrl, commonUrl, QWebEnginePermission::Geolocation, QWebEnginePermission::Denied)); + QVERIFY(findInList(permissionsListAll, commonUrl, commonFeature, QWebEnginePermission::Granted)); + + // Check list filtered by feature + QVERIFY(permissionsListFeature.size() == 2); + QVERIFY(findInList(permissionsListAll, commonUrl, commonFeature, QWebEnginePermission::Granted)); + QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("http://www.google.com/")), commonFeature, QWebEnginePermission::Granted)); +} + void tst_QWebEngineProfile::qtbug_71895() { QWebEngineView view; From 5ab15e1ce3f4168de0380a23a242ff934d777008 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Fri, 31 May 2024 11:17:38 +0200 Subject: [PATCH 005/341] Add QWebEngineFrame::isMainFrame() Change-Id: I5360ebc88aeff2189071c971e4f24a69e765686d Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 91abf8036329a6e8830fa616d11cf27bd62a2a8d) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineframe.cpp | 8 ++++++++ src/core/api/qwebengineframe.h | 2 ++ src/webenginequick/doc/src/webengineframe.qdoc | 6 ++++++ .../core/qwebengineframe/tst_qwebengineframe.cpp | 14 ++++++++++++++ tests/auto/quick/publicapi/tst_publicapi.cpp | 1 + 5 files changed, 31 insertions(+) diff --git a/src/core/api/qwebengineframe.cpp b/src/core/api/qwebengineframe.cpp index 52fd5e60273..fa2cbb507b3 100644 --- a/src/core/api/qwebengineframe.cpp +++ b/src/core/api/qwebengineframe.cpp @@ -106,6 +106,14 @@ QSizeF QWebEngineFrame::size() const return m_adapterClient->webContentsAdapter()->frameSize(m_id); } +/*! + Returns \c{true} if this object represents the page's main frame; \c{false} otherwise. +*/ +bool QWebEngineFrame::isMainFrame() const +{ + return m_adapterClient->webContentsAdapter()->mainFrameId() == m_id; +} + /*! \fn void QWebEngineFrame::runJavaScript(const QString &script, const std::function &callback) \fn void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId) \fn void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, const diff --git a/src/core/api/qwebengineframe.h b/src/core/api/qwebengineframe.h index 34b72e08ea1..b6953cdd21f 100644 --- a/src/core/api/qwebengineframe.h +++ b/src/core/api/qwebengineframe.h @@ -28,6 +28,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFrame Q_PROPERTY(QString htmlName READ htmlName FINAL) Q_PROPERTY(QUrl url READ url FINAL) Q_PROPERTY(QSizeF size READ size FINAL) + Q_PROPERTY(bool isMainFrame READ isMainFrame FINAL) public: QML_VALUE_TYPE(webEngineFrame) @@ -39,6 +40,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFrame QList children() const; QUrl url() const; QSizeF size() const; + bool isMainFrame() const; void runJavaScript(const QString &script, const std::function &callback); diff --git a/src/webenginequick/doc/src/webengineframe.qdoc b/src/webenginequick/doc/src/webengineframe.qdoc index 7df4a1d2bfd..8f852501ef8 100644 --- a/src/webenginequick/doc/src/webengineframe.qdoc +++ b/src/webenginequick/doc/src/webengineframe.qdoc @@ -64,6 +64,12 @@ If the frame could not be found, returns a default size with dimensions (-1, -1). */ +/*! + \qmlproperty bool webEngineFrame::isMainFrame + + Returns \c{true} if this object represents the page's main frame; \c{false} otherwise. +*/ + /*! \qmlmethod void webEngineFrame::runJavaScript(string script, variant callback) \qmlmethod void webEngineFrame::runJavaScript(string script, uint worldId, variant callback) diff --git a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp index 2fe0e27a265..8bbefd5f58a 100644 --- a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp +++ b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp @@ -37,6 +37,7 @@ private Q_SLOTS: void childrenOfInvalidFrame(); void url(); void size(); + void isMainFrame(); void runJavaScript(); void printRequestedByFrame(); void printToPdfFile(); @@ -180,6 +181,19 @@ void tst_QWebEngineFrame::size() QCOMPARE(frame1.size(), QSizeF()); } +void tst_QWebEngineFrame::isMainFrame() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto frame = page.mainFrame(); + QVERIFY(frame.isMainFrame()); + for (auto child : frame.children()) { + QVERIFY(!child.isMainFrame()); + } +} + void tst_QWebEngineFrame::runJavaScript() { QWebEnginePage page; diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index dbe9513f20e..e6605dc4103 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -929,6 +929,7 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineSettings.imageAnimationPolicy --> QQuickWebEngineSettings::ImageAnimationPolicy" << "QQuickWebEngineSettings.imageAnimationPolicyChanged() --> void" << "QWebEngineFrame.htmlName --> QString" + << "QWebEngineFrame.isMainFrame --> bool" << "QWebEngineFrame.isValid --> bool" << "QWebEngineFrame.name --> QString" << "QWebEngineFrame.printToPdf(QJSValue) --> void" From bb988763684ae3e52f8274905e97a396d81f0975 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Fri, 12 Apr 2024 11:07:06 +0200 Subject: [PATCH 006/341] Add PermissionBrowser example The example demonstrates how to properly use the new QWebEnginePermission API to manage incoming and existing website permissions. Change-Id: I21fd01879f7bd89fc2239fde38f5b6456f193578 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 754160cc0951315fd7d4e712e151dd617910644b) Reviewed-by: Qt Cherry-pick Bot --- examples/webenginewidgets/CMakeLists.txt | 1 + .../permissionbrowser/CMakeLists.txt | 84 +++++ .../permissionbrowser/Info.cmake.macos.plist | 36 ++ .../doc/images/permissionbrowser-example.png | Bin 0 -> 50311 bytes .../doc/src/permissionbrowser.qdoc | 221 +++++++++++ .../permissionbrowser/main.cpp | 18 + .../permissionbrowser/mainwindow.cpp | 270 +++++++++++++ .../permissionbrowser/mainwindow.h | 74 ++++ .../permissionbrowser/mainwindow.ui | 356 ++++++++++++++++++ .../permissionbrowser.exe.manifest | 17 + .../permissionbrowser/permissionbrowser.qrc | 7 + .../permissionbrowser/permissiondialog.ui | 117 ++++++ .../permissionbrowser/permissionwidget.ui | 119 ++++++ .../resources/3rdparty/COPYING | 1 + .../resources/3rdparty/go-next.png | Bin 0 -> 1219 bytes .../resources/3rdparty/go-previous.png | Bin 0 -> 1200 bytes .../resources/3rdparty/qt_attribution.json | 24 ++ .../resources/3rdparty/view-refresh.png | Bin 0 -> 1364 bytes .../resources/AppLogoColor.png | Bin 0 -> 6113 bytes .../permissionbrowser/resources/landing.html | 88 +++++ 20 files changed, 1433 insertions(+) create mode 100644 examples/webenginewidgets/permissionbrowser/CMakeLists.txt create mode 100644 examples/webenginewidgets/permissionbrowser/Info.cmake.macos.plist create mode 100644 examples/webenginewidgets/permissionbrowser/doc/images/permissionbrowser-example.png create mode 100644 examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc create mode 100644 examples/webenginewidgets/permissionbrowser/main.cpp create mode 100644 examples/webenginewidgets/permissionbrowser/mainwindow.cpp create mode 100644 examples/webenginewidgets/permissionbrowser/mainwindow.h create mode 100644 examples/webenginewidgets/permissionbrowser/mainwindow.ui create mode 100644 examples/webenginewidgets/permissionbrowser/permissionbrowser.exe.manifest create mode 100644 examples/webenginewidgets/permissionbrowser/permissionbrowser.qrc create mode 100644 examples/webenginewidgets/permissionbrowser/permissiondialog.ui create mode 100644 examples/webenginewidgets/permissionbrowser/permissionwidget.ui create mode 100644 examples/webenginewidgets/permissionbrowser/resources/3rdparty/COPYING create mode 100644 examples/webenginewidgets/permissionbrowser/resources/3rdparty/go-next.png create mode 100644 examples/webenginewidgets/permissionbrowser/resources/3rdparty/go-previous.png create mode 100644 examples/webenginewidgets/permissionbrowser/resources/3rdparty/qt_attribution.json create mode 100644 examples/webenginewidgets/permissionbrowser/resources/3rdparty/view-refresh.png create mode 100644 examples/webenginewidgets/permissionbrowser/resources/AppLogoColor.png create mode 100644 examples/webenginewidgets/permissionbrowser/resources/landing.html diff --git a/examples/webenginewidgets/CMakeLists.txt b/examples/webenginewidgets/CMakeLists.txt index 3ce666d7293..ebe34d668fa 100644 --- a/examples/webenginewidgets/CMakeLists.txt +++ b/examples/webenginewidgets/CMakeLists.txt @@ -3,6 +3,7 @@ qt_internal_add_example(contentmanipulation) qt_internal_add_example(cookiebrowser) +qt_internal_add_example(permissionbrowser) qt_internal_add_example(notifications) qt_internal_add_example(simplebrowser) qt_internal_add_example(push-notifications) diff --git a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt new file mode 100644 index 00000000000..0a92691ba1f --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt @@ -0,0 +1,84 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.5) +project(permissionbrowser LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/permissionbrowser") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui WebEngineWidgets) + +qt_add_executable(permissionbrowser + permissiondialog.ui + permissionwidget.ui + main.cpp + mainwindow.cpp mainwindow.h mainwindow.ui +) + +if(WIN32) + set_property( + TARGET permissionbrowser + APPEND PROPERTY + SOURCES permissionbrowser.exe.manifest) +endif() + +set_target_properties(permissionbrowser PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.examples.webenginewidgets.permissionbrowser" +) + +target_link_libraries(permissionbrowser PUBLIC + Qt::Core + Qt::Gui + Qt::WebEngineWidgets +) + +# Resources: +set(permissionbrowser_resource_files + "resources/3rdparty/view-refresh.png" + "resources/3rdparty/go-next.png" + "resources/3rdparty/go-previous.png" + "resources/AppLogoColor.png" + "resources/landing.html" +) + +qt_add_resources(permissionbrowser "permissionbrowser" + PREFIX + "/" + BASE + "resources" + FILES + ${permissionbrowser_resource_files} +) + +if (APPLE) + set_target_properties(permissionbrowser PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.cmake.macos.plist" + ) + + if (NOT CMAKE_GENERATOR STREQUAL "Xcode") + # Need to sign application for location permissions to work + if(QT_FEATURE_debug_and_release) + set(exe_path "${CMAKE_CURRENT_BINARY_DIR}/$/") + else() + unset(exe_path) + endif() + add_custom_command(TARGET permissionbrowser + POST_BUILD COMMAND codesign --force -s - ${exe_path}permissionbrowser.app + ) + endif() +endif() + +install(TARGETS permissionbrowser + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/webenginewidgets/permissionbrowser/Info.cmake.macos.plist b/examples/webenginewidgets/permissionbrowser/Info.cmake.macos.plist new file mode 100644 index 00000000000..48ddaadc650 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/Info.cmake.macos.plist @@ -0,0 +1,36 @@ + + + + + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + LSMinimumSystemVersion + ${CMAKE_OSX_DEPLOYMENT_TARGET} + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleDevelopmentRegion + English + NSSupportsAutomaticGraphicsSwitching + + NSLocationUsageDescription + Permission Browser would like to give web sites access to your location for demo purposes. + NSMicrophoneUsageDescription + Permission Browser would like to give web sites access to your computer's microphone for demo purposes. + NSCameraUsageDescription + Permission Browser would like to give web sites access to your computer's camera for demo purposes. + + diff --git a/examples/webenginewidgets/permissionbrowser/doc/images/permissionbrowser-example.png b/examples/webenginewidgets/permissionbrowser/doc/images/permissionbrowser-example.png new file mode 100644 index 0000000000000000000000000000000000000000..56ea60025ded508dcc93f2bfecf9ae08b4f84d1b GIT binary patch literal 50311 zcmbTdWl&sQ(>96+cXtU8fywb#9ENW-4-r{0zhV7rlnLA#M8R1+2Gk>E8VLVWUL&92w;X zD81u1`a5mty}*skcWGfHs||j;zsT6oXp1ntK3QwN-7DvJ-Fz1k z9&YjXPu{}4tT`#ssu)o$< z;>5HWiUFrw^f{-zJ^0e@JY*ZPD@cM!Z-M#WsEs==6E8;Xk+xB%} zgvff0h1Z$A2{+%2FryUn6YVzyvclmoNI_|-k^$RyWV2Z#&n%Dd`;%~)-al(BC$Rp> z<~bjw-)k`&D(Y~0O2RCl%WYe`gd}*kg}XBaeo)>W>$}N7HZopvif+=Do6V zK6z<6Sr6QIN1Fq)lIm(+cVvAZg_yCm&+a(YJ9}DT6kkEJ;v1)Mj0uAktGrvsbDm;T zE5EgiO%?VMNJB|n7Q{=#_qFNVvL|%;YI+D#&}bBc1Qi*J;0#~iZma(3E<+tUKD!r3 zaetJda(!Dpa($p??Xq^aT4l7luNLm|_PV%Gu=9v+W7yl^$Xm;I<5xN7T|t+rkBQF) zIVNSdGX!smzX??CyQ_P9n0P^l_nUjM{yVKEL%s2IcM?@|oH9Y^UfW1prcZEt-0eos zu{XrSI;VZ7)Z)w*MZ{17!)&rx&FL=x$WCandEO5y>jINsAAP21(fdNErziCD>ccGL z&4}^CI9hi}L7X87h=&F~@{b1Yq0?HP&f?^CHy2^&M)1b@`2m14 z76DQ`o!-guq1zN_`H(BtaP08>;X9dyNPp+Vxc% zXQ$&fAt{h@he^s!7mb?TzeYO*E@vq>#%sV0JW!oyczcSMj5|TKk@Lo#qI|0f+=Be` z$PI6VO7rACA8^LrAxriSF78orD?D%uV&Cr~2b39|6;Y zK|~;xhR$8x%LExRI-;GtyG&bfd(8Iol5P8XF zN{lyS{*fRk?ArUxlIO;n8;P2dZd#82fev?%rlG(M*CY65DFPS1v?29COPRy!6ntuA zbNk_k@m3n{-(SxIHg%Xyy?RB3iZY0S=);g}{1jDK04)f1e%{P+#tw)b^=i+BNNXe4 zf!Rj=xlZ~ARCZf|WnP;c5r1NV2f4tqujBsInc#|UKBQpMhq)8Egw)06|>v2Gs~M3lw{w%9kF;MA(> zRhr-<4#yRj0KE4-7q$z2EwSJS>P-*JF7DYhMEP4lRn$^gJBC0!!bHN@{mAKe>N{>- z#B62t>UM_H#EcNieW{YtCg~SBMCwK{AFz>}yOCx$;c^&(y;ge?GE29}o0zby=#!ltD84ekzG{4<=F>u^s z`&`<|HOW;43UpJ7@z!auE7r#5Mcu#7St>=Z5cn&!{Y&lxP2uM8(Q@&FUHk}^<*H*e z0y^>0!4P9opjpJ&`o*$Q7zY-(ZJPW1)%($J|AZW`DpI-b2EA{V2 z@=dY9{TDEfXKC^AN~FO{(nLg|2Cm>-4Lob+_CV z3rBoYN47r{kNfpQcqdU$W;wQmNabYp%ZxSSBb+z178nOW&V72PQv2|?cb6s^)2W`@ z-$21FUsfo8%Xz5{9#Y17S2eQHOLiYWE~v*@)SO`}FY{oX%1@AZOZC!teJqpthF=(Dtj*a;FJgqDb;-G%4(Y9wykm1XW z;fV+Sl+JIHnR|4l&XYJ^jn%X3qvY?w+xwE5aGq0%yy#O z^-l;z%5~qNBXP%k)|8d)?|tevm0~H7J5mq{G-=(vWiYp~w?B{(0q&SwJ{-#+1og)< zf0EV8{ERnanKJaO!|F!BwpHd316hC%&NzDznDkBS5XR0t20p0T=>>#fZ|T_sG~LuI z?%6G+uQ%esRXp&b6Qf6pd{Df_U(VP2&1L86PGC?d1P1Utvh~Lw+)5wUaj#SeFnf2M z6p@-4&B^}!(aRGwdQ+$&@Sq@#&`Aa@8&xcfsBTz-nJ}+2rDw{HFY&O+)cVq!b#lBg zm{)F`1{74if)Dglt{~#mz3~o3**!egd;!^S-zcq4JFY$Q z99cp1r&3<_1y&hk-+wJ!v}RD^_qi06pJx`Lx8<(&trV|{I&`@Egr4AnfA8*i8r%}6 z78x1PJv_!q`pyYr^7=AshfWPRbPnGer3jXR*;p@LHpOK7E1lL0rVh#nm}H@UET`0_e?ts?%1x|1coPmNTtw|yGqX!@!RSGUgk-tp}!6~)}*fj>D2AHA~9qY zqb*(y?aP;_Usi#4*1@1Z7`!IOhl~iO$sEw)3rzI04ucIEaoLcm%MF-T{8>99 zc*{+tyIka$-+x#A7&}AQLEpf^p)&nB^FJ-W`=zjOvJlE6LU?Mgu}F{~522^V6cUN_ zpFV^?<&pjcdK#E!%mM#)eG$S(B>Qhy($}e&jQ{q7>^U!NTldt`iqe~-N36bG<~wx!|!upBQz`W-_9Mo+RU=rli#TH z|JfjD5E`pv=n|TK76TECjJV%8hLwpdE29l^aSJv)t$CC8W>Etkc7O}ACMLQWfF5f( zwI*SjhI2ptIi&@^58FI`&&-T)he>>oBlyo#_`j0c|L0*~{r7QRj9s5@xZGaY3cc+H zJnoxP*q)Ndq_YC=X<9g?fMvwh!QLYtU%$UO2RQCL?#223+C^xK?w@6j%6c?&*Olrc{RFRV{<8Z`e?rPtf<+uXM8hBPO8yOm;=UJVX z*A^Mzzt1B3*>{tMMf7Sg?5cPy-zg+-L02cPKx8!QQAtb6W%MJ1 zjGP8Yy6sIZ^1AcdW^0OXxrrFd{S2F(lN#N`ng6E<1yt&At=0TxI%d=|VDs4JBu@BIT`n=;MY-yeI;ZlF+fC(4b-$#( z(uA<0ScdgL?bQ|s$wQzwq3L_6OGQgfkXBb(7XLG<1%-x^(%8!d7u+@!7Pj9%M?UQ^ zZ>%B0Ohz-p64O1>_%LBlJIKj!GwJMwiG8JQ<7|rB@D%3Tk}7rp5TO>gh@%i z9CCngVPIPkkb95k=j^-d%IVmC<8!}WYfH%%TUp&0bIVjkNfV{kc`vad{sq?;rfmuv zO*!30+?c%Z-zR)ozRyTvEdr$sy(>~xxbI~EOrQSz`E!aq=>095rjv3C%bcdsS1Xs> zgKR+uUPmhBJHTQ`S#^_&y!@-wAxO@2i3dLL9^4=S;q-X`W8yi&%nk!lMQg64g&g9~ z4|QK@sD|OXOT7nqFe?x-B;YKfY!JvdwG37YT=oZUFkm4>_<&SOq<^=dG!tq zSR8pUS}zNnau&pW+3|b}fs;S#ExvoLc0&~Z8*Mu59o3!&Ti2RAVc(1tq;?4(!V)#Z z5R-oT-tIXQ3F39gU+QXf1C$PA&oY&68{D5$lXi7I^Go2i{eKOF1 z`>bNA&PCQ7jRoKHb*`{D+wKUv(T(zRkeu7Tt)C~{;8mu~S24F@7N1*KfarGTpBeHn zq8+vT%kmzZN(7P_#fARkQSgVLZ7O=kt(Z^PoRqnmI&$Bi4_haiHtbhQaD$%g(!)C! z`z?mIPi8G7L<7!e7Dk5&a;V8UA{elV?tZ<+oS>{HIP4zw4lT(@=lXdaDCn~N<&@2# zr|F^VBCY#|2hWB%*I`O*DcOVd2ro{hh-GTN%J>ZOm*2tu`l$9-&cU^xe6!1%Zkc|xSc zxLSnn&-UJ(5nEGXa#DKK%5v-}o6skLlnGBOn(gxo^L%fkmTyZU^TW0vxVdM3zebS59( zHg*bj%gH;sgRD+YB4Woz@3BmTbT;;rsWV0IbTY+ZjeY?C9Dw9(z;`Gp5F*4ta`(X5 zc@IbAt-Zz@ZF<0?2+Mq{vPi|P;VgEL-|X6fD9KbILSXSv!X?;7jROsKDtcpJ4~Rb= z`vuK@mobzRe#AX8AUbx$18DsmY|>@zR6TGCLg?T+l#K&$FX&DcZFTTzwL6BFv42FE z&T^5H4`A2Yb0{~+d~A#VD6M0lgRj!jf4i%jxe*X2iKLvoR~-}gsE^)x9F!DtO;**N zzx4y>GW*O`K3Wgh%&08tVpcdWDqtlKZwQsKi>oaGmn{v1W+E%WP?;y^uenqg`mTz5 zU{OEj%?(%zeXDFf;94*ybd-T?8_Ik8B?Vzz%&QRFQ&!D_ai|6XdpjJ$i~{M$)}A?Iah>iUDeNC zNO4*WR3xN=zsa<}d2dG_K(xbu_BD@^AMhe9jyA}Q<)<@MCD8b6dC7+yY9d}ZtzbiU zD-{;{hIW838j~UDM1zHpL5gGmzHuzt)P`pUHK{b7j`|s9ZoF_fm=2Uk9(~{_LWolL zKu7}NdM>I9JWLgpTJ07+d4W>)iSA=q@TDC za_DP?v9LCw7)b5krEtCVTTl?)DT1Q@y5im=sHPC;skCah!fH#ytcyYAnCFb`3Ch@H z82u18UXjvN`#LMmo5t9?%C6Not26oWoEK*gveu(fyZ4w&+6b7w9$`W>Wh84Y%9~p9 z`&VYb>FruiVYjKMjYGn)1>nkdn(ct*+DqKh`G`ugT4(xXNqi^Br*?9m!-WpJygN=>s%{HtGSyr(ABtIv1>%l|6gn&i(sd zPw~u6sza|!`mfG8rDb7&$FT+><+U^l4{p!UL&EhW;(-*gy9er;)`{*vImv5&7=Csd zJc*!^k%WCR1aV+NL5oGKD7P=E7{R_r$AnHm;`}jasNLATCT$Ndp?}{yL*SOpeK98- z8RWC^X-dbilFrQ}fdJ`xyY0N$c~<~_uO!7239>rj{f>r7;xs$>4mSqQ5oQPy84WiH zXG+nZ;tYP9Iir+&$6!LDXEchT+ZYWqw6E4Wk9-thJ8^ft#@;d4nuulzloarHB>zh# ziL73fb5?n4C)m3q@9{hibQ%*T^*IzhVYJuZ@dm`RE{sm>-o?|lG2C4Z?&`khOED$D zIP)_HtT|`LrPz(f%Iv?(s`O;owi;km@X#$0Vh{~*FsDXcvX=A2^{l-Al53i=okIz8^zBK91t04dI;grs29}J&hNnBfGHH$uw}uA#PSo?k ztGEoU(!!WDJds4+D|+=dMl@fE8}e6>IatS*Q@|3^$JQc7y3H@2DVDny$2IAk3lH0U zSDij0b)#t-6~{_UYt|3XHk$-c+PF!~Bw1V(_Bi}#10S+Hdgm^7L{k)G`_Mn-qAoqg zHnpvTocvP~veWsiz0@Oql$&NN-BkNBraxHV!@9TtLKj?KL=j=F_I$Qcf{=W#<{e<) zXZPX)3Ma1Bk8I40eS0Q(8oZzvM0a3$`Cvb_p#2(W9B7O~0-8y<*E{aCd|%1gE9q8e zx*$oKe#eDLjGTb^4`wpFy?y3oeV%fCRABeVLl3R5Crm75$SeZ$+uhftCfaD=5HP$E zucrk9CvpK0$S@GmQy6j+z-FK6j=MXvzNp4 zE<`m$xU#aT$?mdxAdVq!vbc>rpue|wwe7g`)29_GEySWilj*fXWAk-4Xo48MfA!bj z@d6DUYq<0E%)Ec=? z;H;%CX6>wfolRZ|;qLyEttzZBXVpF9p@sWss)H4r5RS)q%K6@FppmNWT;h9)%niwG zNd8Ln&}%K7s=V(1AUR5A)D^h%>H6EsR~;+@bF<1@yvBjQv|L6fV6oqjTaa)`Vg%7FhefN?!Y~T{<((|Yd_jDB0klsi{jm5EDhDHr51Hx@m#p`CP z^2HJyTe|c`Z|K57%LhIY1n+javN7Lw5aWb4!=pDW z@pF&&7JO|S9cKjkI~;l=h!&b2$OZ@a4-Qf&J=RFW2pFmyoHirYDE-$ALV)MitNSu} zhvmVPK4&s~?S=F#VR+*+=kL|8eQC2;gC94TlJH2 zCA6A086xefS`_SjL2EzJ4O_n`aqrTn@h6DH{Z4-bq1Y+BcQ8W`efZHZXLT>^k^L%q zT7TPRH;Yg_Rup^KwU6*wHJzcxe4YGG_cE6kU{h%84&E zy8s+vnUdZgf2C%MxfT7Qh#JTP?|f&FWJ7%%u%ykBSQhSO#ehr-_&;H?Tmoip7n4&n z@b#(depTC%_+zqMM*UNk#UtTT;>rIn*Mc1LNXq1|OfSnL`Fb)v0cK|A|G(tH z?)ktoZ5^F*{-;5xqt`b!rgaCduVo*{?;ChV{21pvHjQFkmVXEzpO8nA2xDe2fra1i z+WCocF*7p*@SwLgH3=Jb`cYBv82$-6`s)~j^e^jEqWH)OQH!pvt?8qzK9UYk=s#Vh z+x)R|K%cp|v9Zx$2uT?4U)BhlNgyCmDZp)Klpl-m$L1Xy6k^sBX7;Eh07vN4{-4?l z%%Oi$-{>+o(gOd(Jkfn?MAjuSb&fwS@RPa2`5%@^E`kmfpXcGm|GypohoZ`7Oo~;V zo?iG=c9BQ=Ykev|JHjArVr4;FHepsJYc^MEK%MMmPH5FqPmy~m-M?FT5%CW?J0uEo z1EY%VC+7`7?(Bq_xux-F?54g*1T%L1y`bf|4wN~xk;oRtc;NR~ut|FCBH-Ad)+_L@m6AzvJdjDuQizhBo@jZA`4 zX|&2jY&p|Z#H3PwSqVR9As1`wm3%;_JF=UvQyracdxo@f#cl1on4GrY*lH&QK5Xq+ zX)qGmc1x6udz<6o>(DAnK($JVD4QomyFITr-99(gT)e!Q=i_%M_%g2wD4H6twdG75 zbng>z8kqY95H4c!FGp`%04i+q9|c+2Nlu{TQltJW(^oHgxeX#V7hKybANt8?t$mP1dvD4uH})4SWoaG2o2% zi{o@whOkqS8HfZ4)uKYXfaJf$+bDoQ;onQ(S`?0V+A2$5ybjLbO~|e^hq1MBiCmZO zFq*$1J-B0L{fDs(N_`nqQPp2X`>ewDrFu*o7Wrfyz(By9o1{@^uxV<`Cj^bwEmwGc zyX{q7{nkhJyM@lT4`;mdoIz|jj^8rAwlQ$jlFjYu3CyiE{qFV9DRHZOiXfSDzn9xq zS9ck+%<=J__s!N0Zm4!DqFe7a57f~ulnycuG>?+XqO8`N&g^#l-KaNX18bBYNyyoq z<;Jz{ug-m(*;T6YC+Nx=3Q(ORHB~~2e6;W z343w=Oq8qC=PCaLE~h_s_r|)?E-9N?5Pn!n$)L7>U;oq0Ck9Ro0&C%fzvX?Xm|0M# zVePuz=N7)yuXJd(-mPIb8DOSx=+#yf_(o@NliHL!os)xJf3y^p-78!{_D*|IH{A7D z6;)j9>RX|kMmF1d$6A!*-opg-7 zS$T}xOYj~-f&Vb^8gVsoNcn+6=DnB>k32Bu6Z>X}{l&q-LEjBYk0iHEDd6aesO#S; zF8?9wQG>J4|Lgz%FQ|RXNA?L%La$>SyKGrzN%RiVuPNhLWVLPT~?{Uyy);9J2JFag>Q~Tk2saVpn@WLY6 zK7$!kC2it-MOE3)d>FY>;~()C4_IqJT(7@{QO~6m{k&R1G7OXzi_LDfOY%RSJ|x-6 z-%gWqdk2A~(`cB~(`2|2kDs`R4MVxR!o1T`iKUQnnr1_09w-v?<1f>_7g9rQCtc>PXM;1A4TYjob{twN@|4g(uNLx z{dis){?jZi39IOzR1Ai;>?IK&AeDM|@bEk#rJz4)c=}fYA}^itpkIM$l>0@(WWs+Y z{#KHz1gKzHd*}BvOv`a+8R>3=M*XTX{Ra|7%-=}Bl!?e^CPd*4An2d7`5N8KIxykg zyZ0I!ValYPI)(kuT24rHp$pL!i}J6i$-*mCt!hRwb#U%9a%mMoI5{C4^;6AxObk{@ z-Fh@Z_atHxIKQSv|A{zia5BW*0gI;_1Jgf1{r`mLYUQP|T92Vh?dVV}YC-+i>BJ9L zMCunc21FIJmkn1-Y8mAYB<_I+qI~0JY@`e@&8>Q~clwoVq)spnbmn;%(^qvSI^Vw@ zuyj?%5xdA#bibTzXG?V8>PfWHTWwoaYv9_OQ|5CuSH&)3IvxE^6Dk`vME$}+P;^?fBo;qzyX^mSQxf7e~!RpON_af}`tZ&3e@Tl?k5#bA}=Rs9iqDx@|0 z%ddhru^>+igTN+i=ws<4#eBY%8fH4^-eeT|Jl9Fu`kyfcm9PI|T74gL_-oWwlS zP_MC=V`Topv7sRA!;%XZGpoZyk41`L|4RLfW5^c^-?N8>0N3-TUhDdMPn9KUSQ_U+ ziCB5EogZj>%Re38(HZC&Y4+Nj?W{>BvV0CF`WS!bY6NN}FaJmR_hy_GKCP%TrTrTd zoK|XN?)3q8<@{;VK?SB?{+OWzzRyw8%WBrfH8+!l8TS%i(=H^VM`3~wm;(m=wMKo> zw|GYsm$U%D!d)ZIk4HwRZgHq}4KIH&`R7`bH9xbD@+>$l)Ep$N+1l{4{9qg;0E}d_ z7|__v(hZ6(mX9ynZh8LoFxg_-L1-?%kil9)qh;=4{PT}kt;rzp#<_P)ex16mUPJ|r zRlG*@W!#o|%oXZF*c*rPrR+{qkS2sDa*X!%{A6T=J&{ZoSU;gdQ^tA>ciK z$4P^p6FEsV+kVh@^Nw(5^1=n#)tWoNh&GmWhwNZw3f^(zqiXW<^{}tE?wQYB_H9A$ zokqb*9M5^Vg6wz9_Kyh-3yBJm%6+%suQm4`ad0C240ZT>?9bBs9_(v>`nW{>g-GTX zm*b#@1zok1&9l87557dQJI@(ibx8nC+ss=!0uc?SaN!%#9#K))tpgc0y;>j2DSdk7 zOQ&Fmu=MLDTDytQKg&=6BbDo^(!{W!(rt}N8Wq0nT7`Dzpurn(TUC*TweYvPUidL_ zwYN$;Tisi+?c{y|>bVPD%(_H1?| z$$ed_eSE`M%pf?Z(5=SQmsC56tVdh|dyRWt@P_k2uryLR@DT4NV*2XA`Bl<36Av(W z(KEX89!J;M0hD7K4U_Y$OO}*;c0)f<)nX?VtH~oG1<+`pt=?f;%ku+2Y)V`7BusA~ zTcngUT)wD}a`5u2dZ;2gv8omAe1CYI2~|-|(iN0YY6~aPIeIhi#<6_YPNGpwQ$qci z^3QWTnZ>jr3jAYW7k?A5t5|&P(%wF&LcCgWUn}|+eYUiwax~~IhIkLxppW5wDp>(u zHIMAD;MO6%1SOS7>9Si-Tzg^+I)haNV--;wMaIuer;N;M0*C|lx2fi}KiDpQmo1`G zTsbN{L6+xseR{e%ddxwahNAR5Z#Lf6e%O$%5Rh4@U}Bij8Oe(m?bLINFYWIjk?Rw1 zk0IV+)Ic-(xLHY6lSJCH&01sYV~3ht9>8K1c3sP@__HAXdS9nz?5IQa%gz9kpRJ-t zel}V_^PYFyz7i70S<_98R7zQlL{k)Ooxjc3ncb_cs4s3SpQ~2A%{XT3QRlIsHGN-$ zI=y^)=h;N1x%$Jxdrv8qkmlvq1>cJ5*S7(QWvR&{m0S*wp4(@GkrWvuLzc|fW% zaI}aO`S~xF^`*^@71MzrD(%F!B-yC?$6~S?MSX)+(abpXdWvS&9C2d*;A{W+dHDUW z>|xKWPr<0%%r;VI3ujkKNG?`i8C1GaxJ~28Veb>Om#`?HT5;S77Oi2fx)eKYtO~dZ zScfv~8TFs@o$KIYwsw+1mkYpx2)jIVO3CV^FspyPA|i4!A5`0qPPoB!Y?EQL&vV5Qe4R1xbr(GM!l z7vbt|D);2aCv2T!)`2|=ylt6;Wh#O?21$RPMr@YFPJ14PUqrr4q}hS@yK>Fjl;!(s z<&$IjH2GBDbZHHPwJ4P6$2TpvKd^851En~R%0=EIr~0+89J?*D zM(g7{$yU{0$z#+lryut+b$i{u?!nLn&z4|8TOY(Of`v5N$9fdaUgwuB{~=qy$MN9u zlmU5vfRw-fHLq+x_qqGC3F|Ba`Ooc&K8@%DvLYCCGCW+}!XF~RXZ4oo>(mZf0@k3{ z+(T61+H^tc1%OC#Mix-=j`S%{5*PsL0s^dE0ksW?~6XL0SWO`)LGBSxamhNY#=T+Wc)(lKd zVtLtIZ2`NNife#RCErb5c=d1@Liquj7;@;xKAaZkC-1PoMKk1scbE}WM9NS}hPRyJ zRk4|`xQBo@H5!24_z@>*1#Qp2;p~fnbBi}x^eS5Y-$-3Y1S{RS-s6#NOqp!P0ys0uZX!X%- zLlU`F0CR?2R=1hdhCFl4o2^%;p6P-o6LART-N*P;=z2|B z8gwG>qp?y?;>$a{Ez_H;myB7i8hZdfGR0l_0Mx%f`S$=qFEt%G_b)n*k9Phr)B$`9 z+*mqafSDQ#Xnu#E=y?x9N-{Ws1sAo0ZAI7T~$iLp{$KX(93)%I0HlIHv#~n#_y??46 z(a^!`bkw#QDx|(t)Jp2{#LE1Zz&CVZAwnCe7KL;=$2sVXV~^5{hqeB!lUj#*WijAj z$R+ir`2dZJm}>F&11ge>r&sc}xO%%eTmFVX?ON`20`Sh&{>uIiilu0k=6eYslJ%s< z9U>kxKEAF@F(i9}Mz!~iK(9W%k%hoI3UbroP5ZeA@gv;#k%FPBbzxzcvXHrCrm7g! zq{1Vz2|>prNxuqlbrxe=S2wn8-{(HqP2{`#e%c`@mUgPImiCHXk><94B)Bb8#);=! zOsa5h73!|!2;TIPA`mRFnke}g@_?la|JFjKgjd#7q5<;rLW}(%9RY-k;l_nn^}i(T zFtgLKD{|8q)OB!E`rXa;^&6E78~z{=SlxL)vevGpvShSkk9U zcwP97aDtv`({4L8FcmH{iRAiO2(z(r$#%0Ju>uq7Q&>#g?YFn<%{Nt}dVWuDRc)jD z1Fq}Njb|4*k6uw8s8Nad_(Hh{4gZe!7IeoR3`mOCoWI0RrkS#lz;kZTQ)pYq8a=ye1cPv(nOl zE#@0xiuv1?me0Ld&z58&wV$^D@q6MM^tmTq<&GERAgMiEis3>y!5jL5olBW``+`TR zf+uBo=;0DC^#~MyR^zxd7|(bu#AtnwV?^i(@~@q;L}aYZGs}pEm~6S=wd(%rX6p3( zojKAI-Ca=79oFB!vdi*>NMD5Dc2Xl}XU`RThHcq-6`upz4$G%8noioZ%}lI_lE+Sn zMS6_uJ86b!fg>)=n!4@2=g6V*ND# z3I(dSh*R7c{k`B+K7j1^*7^(?q0v?&+mh+~ByvOsZ6OOSkP+xEq55!0qPx+%#Y-tHK8*Ts1D>8l*fbwh(BK_NJp&QtQCi^YMX1 zS508PLa=P2)mLh_9j|IkRl2uXbusNbch|{eG)q3Kp0j6W(gMesAqO#M`~{_6TP-)Y zpFRX>p6kWAWl=5{N-N~&M^_=aZ)ph`RV6&_Q=X3IOJsnvN@l&H?MQg&i{mK8Ve~Q* z58W6=0AAGVVUoAk`TpP;iRKKEvdqH7B)jv>IPs`R5?0Z^U1&OHcV-D7Ss| zv(BMeTlb4DMzJYV|Eo5T8Mt1hb(muZYNEX1TBs*kpZ7PaQM)tVD#VQiR#Z-e;)^|H@k`u-t8KeRI0gk| z1P#y_z119KlfVpX)|?5DLckv_@9KoODFK9Yta51OJt6i;NBY=Tx1@MwJ9uY!l2kSFIUPX0)=d_Ht>r*BXE>hU}1z*^Gh!Jm_$RL@TRD)RJG9l9#RLan8- zSdrv9JeAvtdJNYzWWDlvhalcfDx#SVAH2_jQa`V-W1%q!{L=yO+}dc-Wyv8lCHB|B z-Y#)jVy#-E11#}s4C?DdaP52;cA46^If$j6J>M^&=ji?HL`Q!0J*>3=@VjugB88JT zNNQ2=h&4N6`1P6!T#~tpXoPNAS;W$;V|nTv9#}vxL_jOLXP?7URSk4|cDTo#dLF@9 z$pa?CZVb3r0Ae93x?1m%5|viw)U6*c)4d!0Yl-gDc@&yj|E&)!#f zmt&~zt=Qi*VP6%_zks+&6N}$4UXAY5(8rbRQ_LxHz&E-FX~{IDy5I;lSw?<1&uk0U_;ce9iADdzV;VI%s( z?Ej9UeX6tgW<3R4{mN<DQx9Q z{;^e@7k&k}cv-ZsC!d8cmAByZ9aD|1r=+WE%{$^HGVmpR7SdXa=Mf6+zlJF97i#(bcGHkuD95PAJNw(Q_1MHYA zzF)UX9tb^m|C*juNl%g*6-~90-M|nzrKr7&JiCtj<9fUy&()o{NU{NWOF?!!=Y=x6*RtSI3CH<S)h+14_l2R}s)tCY+AA+hSxN z{l(eGfcCrPGY^=m%6C*PrxHacY0kxC9I(&DP%iopns_lg{IhUYrtTZfh!;O39|1ew zy5Lop-<*tFmi*FTcH9wHKZ*(^noz&=yMORRor=w!3<$ulc z=(@W%QlD3uS+nK$#TkPv=k_(Gl6K}rG=FwBBB57DGBhy!GAY)G$l!lA4;h^<(^T~N zGB`b7JNI&N0ZcY<&#-5I)PuH9kuQ`(XTC$;IVeW)^c0M3d;+o3sDufcnP8ufKy6 z<;Pi%&pZ1TPIQjabAFH+Iq}0SWkc>g2Tq*^=75{Dk2XbM=JYqbIl3BeU;A7+!}8x2 zdM|vONnb(^)Ym86dGQE1o+sNAM#DgMOdgP8nNKUtU{?xj#%>nm z@#V2Rrz~ha{F~I=u|dgeH3nGRefIDj*TTkW#E~J?io4`?nRwIjrRpoKC9(RH zqQyq(Bt|w;9wr<&?R!j~jd%TZWHvo(ad|Aj@7gCn2r}ZUKEpb`*q8D2)rks; zsjnyJHIxsGXU!6h=l>^KMP29e(lkXWO} z^l5tW@%2moP^;qx&;c`%2IA#orn2RQ+PoFE!j>fGOZBKjw+$kQrZy2F@?jONXoUhv z&|%Ho`#?VP|A)J`jH>Ew`$g$)>28p&g@mM(G}7H6jY>C&bO_QNf^;sB?h*l!?(Xh} zJs0|a-sjn4pZDx@_88~GS)Un;x#qm*eP7qFE@P(>tbv3u%>idsWi~_RNiYm57;pZG z)t@ljlVo{^55qjx5>u_XKQLKKcgndnI%KEC9AjJDBT%V%?~E5RsLfIfm?t>jk!pC8 zac&hHm}jI8l`BL+RJ~1$fOt&8KLYZ=cKp2VRv0BjzLX2yjFjw5ClhkNL`xPFO2ooG zF8~N;ZWt{Jx>2VW?Exrzpn&m|$SEBvn8Q$OVlbnxE+}boLLH23_O_0dsPdg8f2)gN z?KitI+c~D%EjiZO@+rnBd5%Ni3PJg%zmjUHY=n~%ZAS6u*3ba0AjTN|?3@jyTdL(o zFL>HMt;W4I-7YZ%h8Xfl$NU-1nkPQh@-Ds_=~S`Sr_O<}4TNym}FzGl3)fsHj^+VNfPr&;I z8r7WW@9QQzOp3Uc>@xD1CwovcXX$eMdj4?4@CC8M#+*gdnuotS8}?Y!J? z{q&ptA5KQaP528N_1izdoZBB7C2;#X@)gr(Tp<3W?M#3MTs_+!wJtI}8F&(wA+T$A z&r<*>!`7awrKXQ1LO$?%86frQ2^VCB++>I>7H6zove^80F0|%+IJwnn7QYY}l7AFK z|6kbM{>`}cf9#^8wcQyjv;)M8nsEaOM4&%uN6mFbhM@^S$If@ zsAa2Qq;{Yiwr;V zbt@CTs*qzxlzg;zDSt@1pTsq7dyn84o;6cYkLX7 zOp!DYxe&EtS(KLR1(~Gjdy<)%mbUCzn6-tCwogQ+9I|jlapc7+<+5ExwYgI-vS4^|(OEmC+UA7Z@$4Kz$4OxB~7e$Gx9Yb2Tq< zed*~Bs+N`20o)<#Rh~*5^-CP5YE9!y>D!7OHqh`}v>u5f6(v_QDqmyLoGxD{)YH$- z!6}RSnvr5P#AIsJh}-T@KSaeb^*ho9ETUr@;a)h03TsXoYLbNL0MKdrq9m!lXd^{Ph|1CNveb4=7x_A|aXDzL3V&RTN41Gcfgtuk{VrxjjepNe z0$V=C%X&X8~PRQ!2J1fic~&q z;*y`r33{SQ1=g_9iqE$9Q!kf(I=z%qM;e~X7?4w8Y?MOkPQJ z!zEV!S2bb-!p`Y(Fr$|oZuW)zfk98rH^j@W!I(V05I{+h}%o?y$ZH>qNqYf|U?S#kP!#9N6 zj3|8QTD)YZ=US)!(p*b&f>jI*#{CIWW~~b$wY5^X`Q$+$Q=AoYu;>S{{T;wIO0Q7>OIk^r&1qKj{*D(ma-lgcJ`7s4BKvA%li{9Hgs za`n(dV$9nad?g;Ks7DLyL)4dAe9}uDDbi7Fvz0^`%M!eeiNi6TS>SuulmC8_v zeAnGqqMM%(oT%`3Z?jDD3yM(FbuHRA~5#U3VXAyA7hoy>K7?HJFw(;_;-$M`-1fpcP3hfGS`l_5@&l|lMV6FcsJqPianvY$DsCQZjHGQFa4TgThdVxxdJ0HCBU0^SXzCKjtEy}~) z&Z=d#7Kq!@;3r`1J8=NZhPrD!yii|fy!C!4z=}0%Qc@u;2Y%>Hd^2f_Dm48IExmNY z7WGd**vGGo1xp+XkNZ>zze+jf!uMom{&1FLd?9;X9`@m4$U0T_Y8s>%`@dvNH zRJP7sy*%w)k<|QH)(-0=e1^$!IS~SIQ7XUwswj1H^3g#KxlI!RsWoqspUPvPApKUh zK%0N|)-njX6xnYi&nWqAvbzwd<>xqDyY{N+gbbtp1`E_lVch-qC?#E@0a<+oGT#2= zhl5~7tG#w!Y&dg=(b-2=YjGBnhjCq5HM%Bi~zK&2M|Ym)4efj|HDA#H^0!cN4Sz6Q*zI;b%1d%TI~b zV;6TiHTON8#$cRzjRFe4|H8vj|Vc#6;1*{BrUD2F= zcFGlQ++>k)6OBXx1y)?Z1JC0#Nhz`@*TFGM%4EP>L}AM@`7vfd@EDT)D!Ax*?ArNL zH6cX}wJf8pk2Z@&qsAtBu$mD)%55V)-Xp)JZoNL+{0%uWzZZ^ooIfpnht4dNQa{qO z=&|Qa`4J)bN1GJYZlUd_O^0R3YO|aIPssf@l^PzwIG9j&3mVCE<#FBJ?8{wtFFjc4 zV!n*P^{G;e*HIp$KKJ;cdDHbnc@j?Xg%{n^Qgw>R^Fu)W6~bsWZnQdqLOUB#dmd|m zPBB~O#shnlv+=*iAk;ifIu|Bep z$tgpLUwx?Azdcts7-RQfZeD9B`9;d!G z$n@x$eoYMk1gmlSF(87^to49t#NnogHA1>MS_kj*+kwhuY-d~cwOnQ4X;D(o>Ed-L3bf)3S~ag}Vpuc9p+aRDku! zVZJSF@8Mx4Cj{x$>?itsC$+p^~Op-Qe)kk=rT`vZ{60I#E~3*N=C`oHKPnnu2|4gt@~g1dGp~p<@et8TV9kS%LQE7yI%gJsu^UG)-q|N zt5B~sj%UdhF_yNF=M4kb6ES`$kzOm-SZg*TFf4bH@$L#cS2Cv>DqR(-Yz^JTez^5o z>)}^Eia@`1_>!G3M!rh=)7J#=ouzKmq=prv^aD4^*v(3by`1Dmc|vCcAG}KEn85F8 zrnN^VlG^l0!ng$V-S--1^Z20<(d_*a4sK>-=iO#l1wVu0tWxKYyoBYprE!9Bx%5cq z#>bD;u#e!Kmn1AQ-X=o4A_VB30eI5+bkxooDEYMVVsq%9kzPbpKK(@)loiPkchyt+7-8SlzQG+Kt0ZC?24L#LdaO1+gzzb+4RC*gyk&x2z|3r&G z_usqU*RG*xO>>K2!*l-eScC}B&aMJ-n#tf6dmJOi_TO$32$VSsy%K)9(g7HJQ{3dh z^#dPtlk9XPz9t0YxJ0Ywi`^olX6^`~bx1V>IrH#lLj4*wvP(-#?~im6PWf*kSPbw9 zL{3Hc-%llR0is6g#>dACUq41rh>#a3WooFB6_=H1m_ojbhp^vr_ZG1I!9cn%)dlBu zS9)yt460Y3jLx=3kT5ZOffSMPxnJ)A^A*pF7pp&$xgohFDYLhC*9Paf&z^Pum0F_# zy(euyZ5xn}0TGs_iTIKyvgyB(6OV2}03tF(ZETn!$t9Nkeh2h0fCUNiri6re$OFNV z{SdEA&<7mR*iCjDxIP{1lLk2Azc&)ne!cfYC1CsZJl1Rw$z2}?{huax%(UuEaLfkA zEq0Oy>sIy&w}E`;zoJ|Mb#C&lOJQw>vp;C3>Ch#9(5X|CFk zLcP-mv&WL}$pXXaVOXOsREf$4?B)oN{cbRZ{ZKYHx_7A9Js32{$%0!rRP>}IIzR_ z5SKKvmxL>$ygzH<5dTrl=U}P+<6ps%|Knc?ql-ndAb?>ubH1*h^-psy<2`SDqinDC z6|mCWel=*Ea{!F&U_&Q){8SZqLxehre|=KB+4pVe1@$F8c7IFJQgPcnE8l^YZ>(G7 zzntqUc))&X??Hu0{RD(Lqm`|S&)s8bVml0k>z~#V%J~<+@hd+)1}*k_uGlTMLoipe`$V0Yoi7OX5$7~so^|Fr_) zddOacEnSggOUXW&Ty)d?vym(`zvYPzO4*i%1WESb0w9_RMw(rJNIa@+0=4j<4D}hb zT`S&{4Qb{qXK0oV9KUWecs~(@R|933Fm}7LAnk`w>RKZb=@#i!x#o;(v$)3E@A%Vy z#!R;n1L@oX+M#$?9aj4}rDdh;k1GL+%v0|shJ}m$RX4_@@$3uK<6#MRf)GF7)FN!7 z^suBUny9zwiDpyui%4K zRdV{?pCbhV+%{R-BrsqtZH>e_F|yq!oAj+JfX9a3m$wPj%^-xoH^EM=mZN)KR4FIl znfzrNgZ(hH&f8On97X4urHO|;E9nsRU0}sqGUOs-b4!(ba$Dwzacc~Dy)(J4gGB-^ zFf{F-x0R80dw-O`w9>l#0B3inO)*}==Ibgbv(ta=Vi5YKAsPy7Xeoz)y~Zxj8?|ls zWzvJ6URzve_ZKY5K50$;!?u<0yz*bPj=C51g4QH2O3qa}_> zQLhE_Vp*r6NcUn-C$yKg-bDIET}*z)0i3_R?3f+XJYoqqf;HCnRqUT;T)^yRr+zx) zmVwcKE_TIy(O^>ri&Onx237yY&GVx-y_zRkW3y)osuGF587Ef8qg}Jy?Sr z${4WSxa#Wbr>Fc^0Ma<;wHUBHQ|GkHCG6b%$3|`85F@m^SUoxCl(u*8Lq+<2^kpop z#8`4t5+NjC%9@F9uI>UVmig!FpoJFzQuYC~agq3hDBkh_puhXC>+9>Qvr(mS(pdZY zb^NuB4eQC7(KsdH!k&5%A%8(VZt|AgBIumCO1)xWn^%t{H7ys+zw zDg?II5@9=h4(l;S;2gS~zSMDj1`P|mY9+{Rw4$CTDHREDz^SQX7_&cU&fvTd;C=nl ziyk_p;pxb7JI=ws`w@H8=8VQ}*6iIlJTODbH`*UQ0!Fy7%>kWf=cZ?zVw7Gc)t@6SdiVRsv$FYzZ=IXG*7aRion6XCj$U zY{(GWxVvOJ}n5Tz85bIe5y4&-#+~nfQYdIK78MvOarKl zw1;OPJHlYZhjV5?2x4I3z(d9nKSx4$?O^|omsQJ(7OTd5BL$w}xW~7ZJT>au>jDwe zQ8GDY`Ul;2!8Wrx+bxw!s?Q%YA0>yl?Jh&+>fGi9Q)6Ou5$rV4e+>y@r)Kd~#w(2mITxh_6FnphSS(u(USIf7UWQ!aASY@ik{HM?m*Iii)Y!Ec>x-wv<# zzd3I3Obj!XgZHTgJoqrU*0CsgCuFe`&mZ)?PzSt0~MJuxp8ty|v89 z9|Q`OR@N#=c@}aWR*fP_@*WwA=t=Mh-4%h_WE5z85WUALz^Dpc;_XJ-klXV zi@yZqH{Y5`T!(Q3uO4_z{$kN|^G2HjM9gQjJlM?>53H z6g4?>(LPX2i{O+f>3vh@dhXDet23&pn!J#VyM5c?TfXpKgAIjUv}Wq4_xoM?fxkk)lfoW=5@eVj+sM&JlLN-+AI z;i|mqj6x}AE%R>LV)1u?#c_G*yLj#x-l9hmFw(n45$ng>Wx`&H4mL2q1hrZ9rFvz&H%TG!X?KJBb!;zec#pNmk!X8#<2^F^R2}NK;pmUlA^EGs8XH$=q0<_bf?rPoT9Hp8WWnHz z8)qRkfZAP)|Ou^j#1n$yWDtjXcFD9)Y4m+!LZvr~onmi^UYE!U8ed&NR&Ce9S@@w+yv8%5)U?#`7UP&xf0FL7X;>$ zUP4CJD9ZIhB;A-6)ZNtz5Bkq_3}J^_;MIEl0l5)}Q-UW2f=92vl*ubP!M$t7SZ~x4 z#hq(YL+;xev$0zEeLT<6?RM&KEE&OQCPe|fPPYVJq{740xq>u%CpFy zul6^?u~*7N4YZx%Ng=eo67v?7LpprXk`BVah_>i*xV8@1JD05a;saEvcgvoFVHvyP zlGC(To8EX!ct$cza4qXNLA%Y3@cefACE07WULu;nOAm_u>t~-&A|A$|?%g!A7kngk zcSTz?1j_}c$HaJ@LMGzKbOvE6F-rp_&cFDPyoo6sitC4d+TdF_&HAu_=t*iOCKOIi zPAb8^)98?pUuDviD2=xVjk7yDUYg%7E&k;V{-YW>*c5r>H}Ke|1C2|s(ZC!szA74- zZPoPc$=@}Uk`LZJEAJ)uM004l&QJL*biEem_Hey9u4eQ(`cSTe>QWIUR37FUIL&ho z!k>7$IFYbu3X!t>rd^2A0ELBXi%igkb_C4C z;5^ss)8?Jm^h^P{Qlh>wN@Q2sOa~Y-v`-0s=Q(EzI?(aLw&D#bWHHn&-J8i2%QU9n zFLm{l!x4svyyCC>W)(ga=E^5URkUp@k`6D0ewkvrLetYwAQ>PrlG``j08vfN&vR?@o1F&!Hs5mT_76F9yxFngn6Z3s*v#`-+%T0(cT^sh1vyu0)Ay4fzU#(2$z z9Fv+_tZ$=K)d|Wm>WYF14M8Ya+G63r7?5?PV!;1a(PLVuK_iNA4Mf4Deu@Om$kK0^ zXY9Jm7dVJ-E9k~tT$`w|e=xEK@+4=|M9h}%RVg>pD+#IS+2=0!g`3yY2peHWJk435 zg<>48&+zBYD)l<$*#tvB=btNjd(+Ts8nCkMXkKk8F7;4rR|A3Gn}CZ)>+*DDGHgF{ zvey5SVb$X}VY?T`ne@b2V!vN;tL64U5Hzj|WG_N9=NCOMEOR8UGH{vLKNf2_Nc@(b z7^JAV&j3UlmG#U$?ATlS!)72^Sy_oXIdNLs*o>2&;F6GpM?|3QW8-Ed;bs|i=K*?| zC2Tb%^ccG9#&=6VFo6LMbd}m-LJ7Tf<-9Jns2z=l;cHD}$)*hbE#XpMzf-~j_&tPS zs72B)RGk=KS%su$2rU8L(dIM4yHum-id_DVXHB|qa`Zd=`ob5K;F4fH;tBbzI&0!R zYd}q>4A{R~`(fx|nqs0cn$9P5InBeivme$rfHaeqgbDv*P z{84Kho$M~o6&e9ud$GGFM77Z)KHQ6RRuc_{9cFm@99Uh2=|0lbL#uPip9u>i2Oi*S z>h<4y&~`YXFo1>O#NWHTL}>@%e_ zaZpwLVrW%$q3$;0#dp&alpTNaUPhKQPWV}>az#o_TlM>#v_9wK?I#*J1QkAO``gg% zmR7edvjiV&Dao^^H9xJrq;!Fdwc3pPa0L#L5)zKzy+3=| zasPu{FLJ~%RS>m_c=9k3!Twrpf0*a--o|l9(c6HG+A;FNBS(}9=EiQc(szMJK9wGU zA5qH82h8-+fJ?Hk>HapDiN>6>F$+ ztU{UxH#prqx=Sxi$j!L@ZM(kF5d*=M*n&jmr+@h{dx)6OJL!d3pYJ8Xt=;ykY=SZ0lqBhJ0HUTd(A>pO~xa;<3Z6ZBKi!E3=p z=$9M9=bSDfmuA6ral2b7Psn0WRVX*7P(FTHf)Ju{9NksV63Fq=lB|F693eRCEwPbz z9d=}7&(ZT*6DoW6Wp8jz;~8z|C(JQ3O|N_DmjW9qcgHrMc?E`W^8Mz#9=m9h`3C2k zqb<942;`vrNg<~EhTOm`&=*c4h&PIQN4o09hu7M!D7OvZ^GvLJ)vxY>3_90lFbMRl%(>>b_bNF5&BLW(%qj2pSp1pekjZ8+bR7#L{DNMH?#fojkN`0(co^Q!@#Cb&82BDA8-B7;nk;>4Mm2U?}g@g=Ek~;Z?Az=f;$eRp0UUKGrt15H@(v0OjyzXOB zLi4RDiymFzfzws@g{u*sO`iqgz@hSP7}R1tS^Yt@Jap4&x)$3d)x+$~B-vHBvq=Kd zfrIvuX;W?rdlPs6_=n{ohORSJ-nn9hfz`@T@36^1gD54#*RVb}mw@D}ft(AYUW5IBWtGZdr#0i^S zSqdP5I~r`mSQkg&{HAfJCDha^DW{Zq*iH}3hjAVdbxD(k%e+v|zI*rmsmSyg?hYq_ z;NBp~*d}rSzfQ?|4cGU^Q?u}aRSOCGrAT%GwAs~l_`VbeyO)0W8&DB*cZWFM&|)QN zWJ|yS=0zucz=?Fk{@gKA?Ze!sd!I9^qX$pkyylY-S^1D95nXy3Jq3aTuN5+_%tlSp z+vW+C-XSA4m!aNoduONX-JbcjTBmSea32!PmI&t{ zu5uyAzEGXVWH_!vufjjOIp8uBDd*9=7=ACwTL{lkorFAgi%-S>m z-k0GXlr-cyhdIvsRq-O1)9}6T#GkjEY;bV!DGi4DEl~Q+I3x3j&1h#4z6@}0zG)^t zc?{qI88SCJ@B}!5=cE||8EhVNG)G@d#32X2@NXS+!RJkv*jLH=(9T-sZKZ(t5TIi@ z8X$Na!g3#scgXjQ@P2DebA?f;XjC(N8a*HD#6bH8tEs84AUVRlS#y&wAH+4m>8Cb3wWswbiid*0nv_svR{H z@wko!46lCfmc}q!_ZCJCG%0bqG;cfJO&M}d90jjh@s0A>2)q1RU)~7EugCE{gM_gmwSb5@t6A5bQZVkYc>;TIp8}eTB{KmRwD~o*Oq-~ zrj0m+La7c73@4>9_aciP%fytvS-nQ8TblhQIigN>SkPQnrUdzEW8MI^)dQ62zkdJD ziT~K!)AMPMa`+Lz=VqSxX|#+X7?m9sZ{JqsgdXOM=<7x{d=V*PlSrufy{PSqmU^sm zj}N3jOzX~vS<0h;Lw&}UJwkq_`^!e~c7JoaMlajs+}&I+C4K64zHHrd(NwTQdq z08G_fBdn(*1^M8>Xe!dxY++hSgHIKTgD;Z$57q!Bwd|tof6~+}JPr8y+@hP|$rx1JB}ak6ggK(yPIt8k>g^Vl0fPW|SC5o#jh?R2Pz?ycx0X)d?NF;CBj z-F%w+O`uC;QgIC4yEMIp*Ym(7Cv9=`rh>+ z@9iLVle6qpYR_A;$4JlKt)Rs%EXOqbqcUH_?}sYQtk-srSB&<>yaMshpuL-rC|$2m zYSvHU_?`!RXeMqg>0r;#^_XE1Z9qp>Zr(hMN#7@mrabdzYl(Qac~o0_;K925xxgCJ zYLH6tU?dfB59***)Akh|LeG3$fiu>Ytw6QD>f*$})j z>EWzN)Zwdr<=)%3<;A;CwB^VW!G98t1_Sn2uPj~(oB)-n$@-6Y>o70vMi@^0>;6f9f6}JG{6uN>V~%2^a(b8CG=%j5|PahUhuNLPLq< z{}E?~eB=Jhu>rGqfC&v&F>&|EC8pI+j2bnyIgqP#GJ+x9@73wKWpeZn|VDFFshcra};Z%Wpug8U40mM-cr+#`n zde*K%5{?YC@AJW6#62xs@nraaXl6!Hg|3`Mi`E)ycm}mB7Dv zyCN?i%^!l2snTkY(&|!5hKNyur)n~!qxviW{4Od__MV{BnXTGJ9cs;sIiDI~diLio zru|`Jx;XF5B_v{Qn{8*E3e$k z4Jc7hMDF0aTT?!6RanX2sB@B9&--r-UqiY8bXhKBqiUn4DE|RtwjZi4*NO=L3j2R+ zc&8s7(!ky`PSIAGSbYX%sIa?J;hR}F-{vh<*vhi~;#vCxFW%N+A=Ye25S@f4Dewk~ zu8i7Q37*2cl*_BV&y&@nNWyHCt{^^l#GYZ}HCf~~nV(HGt;;2{D>tW-Wj(B|Ht{84 z9{-pPSpML@y~S#O=!Nf_*Z#Ue0{AO!adK1>C;?3^uKpcN5N3$cEs#_&cWQHIZG%qS z-6xsW%T4w0RJ*{6T zQ#HiUrvU!G5trI#MeG<4U%35#?Bj1E>5EPqWp@n)l24M<>!0cR`uZexBA2Z#ltTP` zR^OEz&tc-kfZqzQ^$MYpfGuNFtoWD!#$&@DCz5@Jgawhk ztUskE$Zo9fb5l280S7FPR`-1LmnoDzR+Z6DDRn9aHth;JU;X~~m4pbU?}eSKC?=2J zGMj1_78iEX^N%h9YPU$CDGemE|AmlH*&EKRNeyXM-&$P2Rt9cqrF*P2+H9=p zDf-D?Z0Ux(^bpTuXbW)I#Xc>5F4#ZvvMt^aXv=v zu&bKLtqNv;#YwqKC(}F^T-1 z1E~VNWo%$#B0OJ)Z-9+v{D+A^&(6bu5j>CxT24%wI0GalBFokCP~V7JmoA;o6%s#)lj0xBkcj=@i64=vJ4zKhzFK^c|s85^jmatQQYqvoxT)tcXYuljlhr!OnmCOoTLF~Bbc+Bnf~4bed99OCr^(a zs^lhd8U^-`R9oB^VUr+y6U9ip-~mNV!StTaOdiYBCGnl@@dCP6uW;CjJ*Sn`yAmvG8tR$nF%=$keBV^ z$_QFp_&CKt>XSB!7os)6@XMKNv1- zN^NpB(Mm4?zjn<{e?<)3mkH>N5fYYz(i3AcoH(Hp)0J6-qbY>8d$LN`rW{iCIf7-x zG#7jN1Iy@r>U5XW(PnL2Xdx+|gVedr*nONrqDa4%Z|y}?JgLl6U_QIjQoYt?B(2Ta zdj&d3#2Au>+m@?3qlbTfS{3t6zd^!GC|{p{s=BJOy{Wv9GejfzO?#MlSMx#yuXMIc zDF}U~nX5U!h=;=bU0ybFhur_qrH}^zdRyDjP$r~m z{4WwC>F&)5#5eNc=cL?tI%$PS%Evv;bi4)ZbD3<7ll03XcuA#H9Qc*DL3roH!5F*)SCz<~m=kh`lo$PMnETu?rY#M9-)ucOz22vGe&*trXa zzMWIfX%1pcz%W}Oy9-x|+|NIww`mGafiC_SYQeOeq z_hG{aMed2=--aq+USidZ-FFJ9;I@D?G`3dnP5)xo#=2{QBBt;&TE7p)-D4$C%I143-A@{M%#R5)e0g-xcaEoC zdk-6o81X=^Rlk>33Mu34ccLI`r^CXIY!l5KI<}q<>!0|`Nr@MVPNuizH+T-CsXut_ zdL-glZ1UfFTQP!7EIQ;%pNrjQJaLOKx;HDNT{m7R&?;7OVh*aR&xnbM)4=NDPBEM8 zaVg%(a9g2JN^nRo%xVr_9;pld82_HVUQ#&o=y>iRsBX0#-gl}cv@>oM++xQegi=W; zt@KUB@PDC*_fSIBkypQxzV_f*4K@)1&9K(7OB=r~+x50(oD?9C*VdVMIF5nrc+lPd zF72#r1OEBGAf_$*9n<00-v>BYWhwAyOum6@#>++4&1EH3tHP*e?6=8rxtyonj#Dl( zF~sXk*@r?aN%oq#WcBm+Q;nUmwM6TnAT74rSISJjFA!}Oj!G6GoI9?JnWxvi_WjMT zNd*`*IxXU13uuY4+W=~8O7QN>U$5r&3(F+LymO1U+n&Vbl<>%PMI-)L@qW0f!}sd! z_&IaAr=9uFic%heNn$*JoynKJhax!|&Cnb9Op6r9q7mlw#z9ZaJ+RYxor5`B(<2kT z6@BdYPN+v*m|0%QJa) z@L%z`pdgCvCJiDfE3hRMUuG=6U`dKI_1H7&L@*Q4@GEjymp~<6s4{sdKG)d~D5{%i z%qVAvF_$j(8uI0LDb|k7Z3&G1&^pXO`W&-<=5X=_uu@Wn1` zUK;fco{m&VPRko@}J!CN|Lbdp-&H_iS--TogNQ;*mYt$m~5t7j@-0-d@42 zjnh$j)}}Dvnsrg#I#0syUR=**gx@LLcyzN*t302yDf;N0>azYPtY8qa>pJ;X!f~w7 z^eBlvjssy}Q1qfi-qx*L%t2~o&2N?D*g*}y1oLLJBoMN90^-?L79NY4s# z)l7=!H|>b2R}~4a=$D%l;MR-7`2-3c|0r*<_pM#!_FdjWe(=6Z-PbTvz)?e{ZBoc) zYz)mSLdwu_#Mt$fReD)k`sha|5Dh$MVHT1_tm2f!4s#xWn4azXVptjl$U$<=E%M@i zSI#Q&i7&B&lZdg2mmqbZxWY48R#E0;B*b(hgxlr08>3EIBbm+14T9m+EW>9CIAIvL zl(}EAP8p=b_t{0=1JE0pyC3Y8i~lI0RWeck^4mLOdAW?-lzckSAj_mY1nC#;RyeGvipXGs7?4Oz!*^1we3Q zpZ^P6xT+0Y*azF#-rDE-3M6ZHZ$4Z*t|nxU-8Gyk+|(zsy-M4x%GesT!*+M3m>}o# zgUxSmvC7erns5JudZ1g=$*qDJNV`GK@;9_;gbZo5>QIEo27>Q_-a$sj6kC>Vaz#*hb{6V6wzw(1+H-kF|;z9UGGN;VY1oaduP?pwq`K&z|gVj4@RZ3 zSbg;HE-X4V6S=S3C0ME`{B(l?Zo337Bu!oe15lrIX5#Yby!NG{CqiXb-1iw~YPR!? z2{P1u`bZ_fsOk-S#CH>gl$vl=fJC}11;0zzKd4NmK{K8O+_5}Yp8WC?DW4ghud^3^ zDq4qJ#n{}L@!L=x!*_-gEw4YKb+}S}^(wO#$HrV;w;yDRC2*;t=$||;>^_;%x!4&1 zS}7noz<}z{(1MHg8IjMv5^b%JL0k%mwr%X`-bh`Pg0ny_R{qc|NrAYHJLWMSdT4*}*4 z6CDflJX6?>Kp!r!fWieq?-ajEZ0F6Rc#0p2R(ed9W*z@_U+9wN>2L z0$&TvE5B4*%Fei*`-r67ZtKerF=ben$W7O~Lls5$lW^KmrTC$w^2&3_|dh?;zG9ip-&)i|R z*i=mv+;~M*^*0~PTD%@>5F$O>4V}s5A!_mr6waR|iyLdbz=rq+-_!|3`Jt8{9V`6H zt$KeA6YHcbAVv#@?cYy@J#(ReRs`IN;u@td;(Lls9c!(z+HX3{RFS=0$C@Hfbl5lP z0xNB%>Uzo~$f7AZThsGgUvxxTG*ggBXx3$M_g&n@I1)K4SiG zXVZ4ugLn3L9R1&mNihREKaB|xBKOvW%o9j1o0w^24A!n*p^+qbe5#4go8K>tthf2KS#Lr{6vL(8eV4_N4>LFS{=)|^ zGDlvqZ@{F9;7bb>+!cBCN6b4M@M(U#`c^qWMU*V<;r=R@MkV(o^8J<`RtWZO8_14F z6rGxPU7QC7vJ}wYbNk%6r3riMC^*aeBtiCE$RvWbr%42>z0t+b4;xMdt6%gP93M{G z9Hc2;*tTLt)qAlCt7vxrGsUQVxdn_Eqi3whbk+itv$@5bb*&Hs3hg4p1QNu?o%4&f zxU|t3M@B-(39za>O(uZ%4-G#W5I&$)Ho*KZ;|Q+F827F@*m-puN@C3PA4&?v4B*#& zpb*z+5Pe7MqR~h>O+LB+W|Kco8E` z`xy)k7+iuNrvhDb@&9xxpm7mV&UOX=Ggs%Y0ciHjJS|}mWQKZUfPeC zf}@HaDh?_z(2GL5`cFN=SWy}M7gx{u_ZiB_u@Y^s?>H^ddLo?ANraWd^U5DXqQIeA{F^yu3xr zWJU?nT$EZLa3g$=nDATPb_<@6X38jYd-e#8{Ds`J?b|YmkN#m4exzPj8vkr=YmC(L z2~MF)WAVVP^E$S{=2$F5oD^XayD@ZKBA6`1gHf06y=g~?=#TC$nDzB{ver=QmuPEt zlWtYKH`<>8KdIVqftn!*Mi}H5f(Cimz@#i}Kvz~5@V=F;6s!`3R}Rb3XZL(^d*(Ps3FvO`sq9Ch#2o02?1`7|N#U+_ zOj`&eCi?)v8$ajCT=UIM#%4i!>#lPdF~0R8yDio($w0Fn;-C6hk{-GziYy#(5<=GK z)j{K-xC_ujm3IOwH&;JV^ch^JA3*M>l*+`lm!QZt*QFA)pA(Fp=fnDrPriWBWu+8u zz{@PMfY+#$U+hUwdQf{V%cQ=frwwyQYCrl_NrAw|T@{7IXW!YEi=)-NJ^GyKAu`j1 zS;Da#{=n6wUQhF`ZoFEmjcj1#s!TniFCTi}2K9Sp;M9i7DyamA$S%8y=eridE?!xJ zrXu)#F71;cRg<;n4j>q_3SahzlOF{`lhYQ-ad0bWnXo=~dxx96bGx7SAg?(J@pfuW zO3_UP^0u{$XxJ5grlrrv=!oS72PZLBVm`|w^^MIdUU3B+cPbm0zN|}tqkJ0GM3S<0 zJwOayrSY+e&7Yo60JZ6WU@99vFY@Xvo(FqtVMQf?HFQZp7rt?_d!_d#$r0!Fu@v{M zNNQQp>|&_&8t;Q$tA;Fvpjd=&w#aP@;L&+Ot$C;YEB|~_+w!XD&7qAiHIMHweSiav zKL`&&=toC9|Zlhj#~N*Yzg`Ox+JuJ-|Q01*PNAzLUG~ zKnp+oR$?zbqF?gHaW(mruN?o96xL%$u!`T01(_ic&|2C+vPh(<+azpovT$H(wI9?p z%O&?y+oDaI>l!E$lcIQ7Wqc`aGjBOf4za|Vd07oDyFaM5!aeYZ&g4>uWMCENd%lw1 zH1hcEM|kp}FnI8D63iIHw$6?XD7src3PL3|-~2)Tpz} zM|d#B*b2MO^A=k+%KY$)&W&nqQR%ba?{gEx4!4#_e<~4Ubw=rlln*#p$^`N$sj5OY zr5v$BGj=Axf;?0zW0-I<8^hvbxxQB`<{(mBhGy>*-!HZEZ0bKVFjI+6!g3K<8)4}mWK`x9@-wkUN%Gt5j zhPLJu@4dV?U)B<#if~0-0K9-meF~xa3V-0i!oI2fRELv9Uw!q!^N;;nbnT~?(1bOx(o~ul zr2tfzYz6BLD+P-k3)V0GM{{2tRn@z#z3B!4=~M(1L_)fyrAtA&q`Nx=r39qArCYi| zT1wo&rc*&;(+wN$+Tc0ockVsoj&tw0-x%NehdmZ6<{N9y=bdxD&$KsvBvm|yRX^ab zkGir}e6{}FkpVR}{74H?LxWra-L{(xlJ2ZsalJWq@#VClvr)SZAK`kUL9aZR`5sFu zwfZ-fv`&q+eDsy|UoYt_?4wH4vqqyjEz*9}$&Kspbj`pyTsWsl6x0X#AL^S0>z90} zq%|j}o$c64UnQGZ?EBb=LN9VTzAL?Ak-nx7)4D$hS-_fA+bujf<|k`NYd9(F z5!ZIUYRieGyrT)E3!P)_yy|PZr@dd~P|5_-KcgEJ#^qo0#We;p2YzwCn)PjLWj8+X z*O?~EF8QplBpYG{DS!Qb+iZ#IO7pm$HdE8UhX zWqUIENmMZ^N}qJNP0dnEy)VMUk#PFr5B_r_=>_%x0}uC&JZJfr0cFhPhYz(iIJNp_YOxie_No9 z+7Q$-W-77Lq(cNuDzAavYJ*<~rO;>yNjlqDi2ai42)xEiPg+{asr)84gn%Rl7nha8 zX*4(pbMC_7LDn}50J>U2LN}&uXnfU=az`mtvaD;c!q2JTox`bk>6-5Fx;<^9kCT7K z2|lgZzLf~d<}Q0Jcvq&|Bkg$#fjJDz+^Ko(NG51C&Jx$);kv$VlwI#uEQzhaKt2NJ zUL>^Zx~WKpn+c`A+rN6FLkoYwYs{7kpg1vNGWyi2F!bD#^sKt< zSHBgD5108zO%4p$vB&0us0l0sq62juTV05G(|km{N*OOnlK!6hS+fS(Mba-;yfBHs zNl-FwNdz)xh{p>13LINAGo%~zrvppaFRYx*0yI`HTE{wAGK*o!YwdnGit|OICF01b zsLKBM2(Y@1DPWgWB|^Kk24wLsHIAQb5d#u-zE?mh)Tpum(%MyiW7Gj|hH;*Y77GxA zQ8cW+!>(Jf-xP5=L`9Ah&E{bx347>1KTs)kb~1(1U3=6GDX8243}Q7hHg@>gkIyC9 zDc=@#0DE+6_cvYcc5CXec;SA{cX?EZS`p9;)UCZP=i!BKaQiz{KI8X?a(H3?Li8m)4Vi<>agq z9xH-AI5S%&`B9|oKT0r^aSt;%VlP$8-hZk9upW=g!n*f2 zQ_AVt?i%yh99ahJFZ1XTLy?2-kD5mkIBJA19(l{xkZ*-C{ba4nQKhKwAVB%pXo#uW z-LCRHf%eyHn-@1{KXA9g=MMXG%|JNevyxcNq{<@lqham9 zm8jJ5A15io&w5ilUM6MnpQe6F3Z-u^k!aT7A?M@?S=3wl5;8h@A_G`u62O(d6B&gOD7xUM}?(98}2GVmmAeyS)$gF(* zBXYX|BT0=9rOquf=h{dpj99wUp#kLa1f$=#)hxh%1#GnF^1fdge9!p33w8RVZ^lV! zLG;?>J=f&5BSctgQD0NoF&v_1mie3EM2;cz?XP2hNaA;lroQ_O@RRk6!%DF!zNi{_ zjmBe!q_mO+w@`_vl4dC02eUl(W5P>)V^DW#84rKX?f3PpboQU10s04Kmn~5*=nJ znlX8aSp`FbVn&}yL**qVjX7#;{Dqh)D28nIl%}Fjl>>-H1t9HoNR4<}-61GyP{`oC+>Tc|5=vB&aS|8J8@1Y4@fA9`nvT}x32PI( z(imo@Xi}##^7y)E(#t;|a@P91V&CD%VlCrAYQ5XN450#cW zb?MBxra^M)+Do&P`4lwg!aS6S85yEUdAZJ*bkEozIJ5s@SLcDf^qn@0L4ENs3o|%O z_w9iLdwz#=67!Sqd#~e*dv`jb-C!&@c+%gTaK|;EUD?K5mBZ-LUCW52ezjP68$#-@ z-ux_furKME&=IxI&=n^u7FJo!;E4H@B{lCo{k@G9SwBbhQ|r_eKrdU(VE9d(LixNb z1<1UEA1~;DJ=_X;6b2#>`n0|q6`zOz)%Ny}vNe?`EJVASXF~FO$J%Z{Zp$G}LMRSq zgP#&P5C%nLzg`8mewb|S4)9d-pLd*$bH1ghk|mxw&6fFG&fImusX_jA-;+9qVYCy~ zLHAAvJ$6U709X@$+0}G722$clpFwAaBIln?f~C4|Qo|;~7fUu9Omt2XZqDSp=}lI@ ze-yj_^kWyP{=f&lW$N)@{a;Ey9w01V3>;HAP!7sj+MDa5e(b&fg+WYDv5nX0t{X9l zJCo7RO3_hXNg2=t2Thmvw_Q_cXf7`C=JW==!6;Vnp(LOglX9NLQvT^}ol&0GS;)N@ z^d;|Q|J-8%WckjkV8RLEOC@+Tu0_%(m)XMMD*|LXk9PSr*G$2~=rakR48alR+G44x zk2^Y-)-d*;*P^~iLbva@{z&weF!xo|@v@A^W4wb0ZmK@93uWo!-jnF5gjK@KJ#Xk} zpLCg8^5}m+i3)+He-B?y6@J+wVSCU-yX?)nmV{PbrL)CDN_r zP%LYAXfbo^#})^*TAz1WJ=Vf4dH^IJ+|U~U@%CJzYi zOM-+^)u?%>L4{WChPb^U9XhD%y=>oNg6LDF}hEukIPOYlNgirM?mwTi4 zys&y}HD(dsT8_b+umtSNp*lnT4W>sSRQ*n5u^APu>KY$W667a}vfbiG!;I5gB(OGd z&NqzjoqW^j%_`|&S)1WwihiV zFInqo-DdIQ%8pv(O-*T^-#C_|WDU$a8`7TJV*=$kTepwLK&;1)$LWP(oLe zI&FQLNy^FBZUtqT7|mvb_)+IG!u<25Kr!4meIC}f@EW;3twZTh$U&lOdIpz1QEZo0 z_sM((89a`QKW0GukPDGtkzpxNqiRoqdBMV3VwKRXIC*|-!1vK7nIVQHr)(dHdct%0B2xl2dt>g1uW;RtqtRDZcSE2p_nZGUe%C7{8t1LN_=tl?wU|YDn=V^3>H#f%XWOer$Z;4P%dP3s-W6ucQk-9oz zUcZMldfxkz(5j-0pDljpiGC_-w{P@e{7r~ptAHdtm8G!@`5?XDSMf{!4fICO{MSNt zOWfojq<`sr_9($IsHxgZr}LN4r2kIyaQe4J^3)202`$3C^MuJ z&(ci`8xT#-Q?)B4S#u_pHZ7g@zUq53!}fpURDMe0*&Atj2-QZu-mHsV0|_6gjxe<2zS$u+O~LF9i?vZ-z%*u6ISgqcQZ{ z*ol;7+g-x;zWMnB#P z{bZQ;lJ}`sCOA>QJ-*b=dv_gkYPID&Vxy(6@%RG5c{IQi3q4=b;J?AkoIN*0THLHk zpZxjbFnqgUqY<{E}q5PVjjo1Umv>99Q_20hPO(-hfQmGl!eZGCZVwe0=J-K_F12fTeXL zs6fqkOxT5o>ME3#cm7ay{zq+l^6SM+%GyQP$7@*B1t*LLlEyO0bDc}U#)e3NW5$=Gr@ihM==X$Tgg{l_u4LNot0_NhU5nDrmt`rK{`f^z?MwzV?EGKHVX+>YbTdD_bf+d;^{dW!k0Z7sWoF`g%;hVxc#5KK#m_ z=nrPIM{gwBFQPe*Dpb3WxPz&;6Byf%xC)pBij#Hh5bR;{emf&rOCDMoO4`b!n-Pdg zNA;DYZf!8@Uc&340mSrQeqQhJ`65r}GV?aupt#L4Va(TwKdL*^p=_-re$p34$}hB0 zUB!V|obLrVlZh0YiQ4U2+m)CQIYcVgbF-+xnguT3>A0qpKL+YlHiDm@p3mZ}B9pIZ zfFCnVaG4BK8I=%Q1{Y@!m(JaJZs4r#($(V-@#pWQ^_39~W!1h5zGGhvZFx3x-pi|; zBgGc`GSztD0)$E-C=|K__9MK{CXOP1ufrP^c+ZI#6dCb)QGa7_fpLch>o<5)ts{Sr zWcO3#b*S6pj+=>_E45wafR(rMCco{2@x3`JBbG6HymtLylBS-`!2;#i+W4)y-IRzg z>x{3{+zMYzHe7qpEu(obTr)2bd-m=X$fG#wtfb;uvA26j{O(`|!klvmjA$_cu?`xt$;6lIk+@X4~N1MvK?! z>70O~0JSyU;S!(EVStmo$LQb){ZgqCba#NYwY**=p5K&XaQS$=JJ_c6;)-Ng8%fm( z^FA}**pfhz2liYjQaGs?f^{qzwZRu8ph^C%>JTva(7>UpMmmFvib_jM>r38OqpBoW z+$^O1+9jROsW-v?Wc!WJ&E;Z!-Xo`oFA#)1yd4A(lkVgDUotVRY-}d3u3A`ry$0wn zKzq$bJ0;Wd+?El;`0ySBfiNH3yZ!4Qbr1daM~5`^IVFO~)iU03sFJtXsPJW}?yCN7 z%VDJN`JnzLv;KLQZuP)NeAFeSAv{pl4|Zt~NRWIsoo*=_4ROJ1SEzNrmqPXtfop^x z3L-))5a;zg82F<14h{JB3(%249l0vC0q{4e^B^LC_ROt$?sZTi+`jq@{q`Rqkav*i z?Fo>u813B;n*S;$@GSVTM2C!c`(qCucpm)tzj};}u9DJdU{8;v_ESY^>EMKf1nZ(o z&8Ma!z-zLI--|uCEUEAQIjRir}hAqI~2p>Km z9d!GJz$Hs=vpC3~ zs!2c5xa33X4;O`tR;(#Ti1YyH8XS31|9Y}^)~bT3@+ys>_V2E z=?hu+(sQMOEi^TrM$ez@?^`tQEc<*EAZnH#I@$K|oLwx7-WYF-T^wi~xulYoN>z2i z)@EHi1}Qt-_Er{ya}@TIw4|}OJn{1zK!%59FD?aogsk|+h=piiXNjwidO)X|qD_~# znezVFPdCL94MR7dX96`*4>oG1r5$y;OtZ2@X9M@aBNv7W(~h1riUMDwlScTYeHwJB zVFjF|Gzyar35M0VI$Inj8HpBlY%3T9KU=9mO!&8rRA(NW8>x(+kkBQF7ZX&QTmz1ZQ(CzLbAlJ3wXm=_;uU7rI(wvpbhGBAu?- zX0bwSllfAL|LLgkoU41C*X%DBx^fBLnDcRA2tRARf{LyJ3VI9Fpm5 z!&f$gV4~3HEA$zj$XYq={3iBHRJpEovj9fcz-!)hRPwp|H#%FO@u#BWHzQYX55+zT~w*S>ir2JqJKmtV%V>jJK6twnx{&%b3(W-2|olzB`o zFB}lnxVo!GhBIs7g>k{dc>KKU$w=xc(wbJ{gX#P%p^7Ad;1{l_sQ#8Jck0n$j5r)T zHkO^2N3YE^H1`;oi^|RNo1W|dYcZFIh@D(xJdoGJl$3nJ7|4I~z4ARUp+DTGSrUSQ z>MD{hE$iy)xH;f@#DD&WpQUnugbt528Hfqtw%ZK)OxmJE2qJCU20$PtWO2A+Rwn*{ z3h1)V@4#>1sHDGb+rO!N_AW$$d*bp4^k}BW$3Mdvb=unWTwGjSSwQM_Xn54-#>V0$ zB_%tm#n3k4Pw>rNA- zPZ)q^OY%x?EPw*a8+cTqmOM6kR>Jm#P=qM_(V%}%CA$a-3E>fwkl0l5{*%!HRJOm? zea!dU1z-ONAKiMp#b^Aal^OvcV6@=J zH&YG-dA6mU`Q|oUMAEe@1u6f5Fg8fuk3ZHgZWtR)Q&+c^o|NJFSDi#zaoXG4l(`R& zW_Oc8(?iFF-HinQS?$J`ZGC<=JYvaRtHWRPtQjNku17(IIt=Lc%Z26Xyg78zF>;Ua zzxP4c4qCISs}r4nNJrmwF~}ctA}@B4uUz8i+g8`Eaz`CLCn=3>v$#mn+jnPixcI!5 zo~>X`sfT2Gr}&+0(+`hixX6yARA)RuHXA1I5}7G-`u9l%2G0;d<372{^XFd=T zpS)3I#BLA=sfuGt3C^}0Z?8uWKS1C3hy?8P7s?smIha}DO@%r!TbXz|6?Qeed9&@{ zU+f@B@=Ugm^-Qa#c`dzwu6O@-Cbt({_CJG((N)b4*y?7DZF0n_C9q zTZ}6nn5kYPk+i4p69?2VlQ^sNxpaT-p6T=m9&_E8d~$h=Bx+8nPYLsRR*JdP+@Qb*LL?gI;_{<0VL za(rhLiKL#(Y_^T;Kk)09^ZgF_lXaikC7jliFJ-3(Wa%D!wJgngrhG!3w6Q2~t;p3u zg?MlBa5`#je#BXaXM+n#z{ti%0r=$Vkh^s7oOGFRfDaJ_8gJl>NRMKod>K*36Jv3f z;?8A7DvAr34?OJ6IGE#Uzj8n}g2(;muI+KFQ%k+do&-qYe29DK@Q++UL7@&gx2kHa z^;!IfyWY)wnauM%bT;(Zi2eBz@8`Chg-f2iWfejh8Q;@1Q%r1}$I?&wlEIpbg)4!v zC*Ip80UdNTEiK!^FyHN}KJQF2gOQt#03SUOR0~vhWagAR};db8pX-#d|6-ueGHBWa)QW^V@2@sOXKm zeDqQfs;iHxFd~Bg;`S?A|7>75L832`cekQ~a>?JC`hs44yluJiC$gwaZw)`kY3Kul zCu-!l(KsN3^;^viKtk#NtbhJ3==-mlPaNK}%?QXa{_xNi_Fp@|2hKr&weCwPvBB1kMZj43-bz@*X6 zdStSY*0#@CwezruTVT*)L(`SU)mGjoTlm$=6O);ih3v7yuh9+#scqHy<@}dE3)PSv zMHC|C-KyaQA2&1Q&@&wEgZ_p{FDlL#7R1i`-S|{|MhPJVeXQmu+gPp?vXZpGV1WwJ z=gIka3eU`Cy3}0bmz`htwfwT=a(Sgv5Wdg|rh-y9(7#LPw))x_*5^r-ne^#h5o7PX z<7og`Zo==?dk+!d z;$fPY7oJ!2tCxqPypT;xm2}@-@D|IAwKI{Ea5ChPv5cgr_<`o?DtN@x>pH_nKFYbN z)^XEMZ@K&957@pA!P~gRm;3t;=6zbThELOyE+jU zs^ND0_e9^9KCd@;%!FXtud?WB^Oo8(5qx)1P5dE_HZlVWAXBw}$*7buOs@JpFE-IM zK3aM2o!a`3muBH2xAxnAbjV`c+mzqq=Fm`bG>T6fyWlzRqjc_#Z6v}UOO3<0rzRDq zKZx4EqKB^>npr0BcwjMhqYCqaHP5jY1zt;@A2p#Y3HY=$Jw3KF2eNtFa zfa;*KEZ#(565vd^diDN76~cQ{JLEGb1}LB51~5ZC+Pd?_+jlr>P2{!HXbd3y*3BBO zp4scTCpccgkquACy!K9eaUJ-tNFq12EPsnic+v|6i#A81<+#FJYH384$J??YzTUdQ zU=?IDyydQ@>s3hI`HlYZ-9*1(x7gfZ?1gy>^JZ&+Tg3{VyU)04uJ<|%TM8t*ZhJHt zQ(!O~aLeO(@i)B1M6N%V;804{eLvC{8}JDx6uYq`jKQPyt(73v;>46Dbl8fA$8}*k zHxa6dC;vFQZ6VSd@}u8njwLcSgR#T;VwGp!sTDs_K&hka5XpT;UnZM7N9^h2eTwzW zXNQT7KqIWBI({40q6ue|8m$pG*wdfy%c?^ZX#20ohS!h2zazPitD|0=LUT7HcnTX6 zp;?zf^#M-__cq-H@nl&E+#?|kynSStvo>oOR+dTcE~yS5pjAh~ zS3y2WS+b@l9Sn!}MKZ_}KJ99)3GBS?b6Ce9RX0&ir4m0(-^)S;A0ov))~8TG7*h6M zm6aIbo%aaFK;Eb{;}vzVZE;cH_Y`A{l!YuDsFC`M!oTgSZ=b*Rbz%06nzepl&350@ z;h>tMO3Waa6V5Yq`w082pzD_Kk@^ystqXgu>caKLl#fwY(QWf^0AiZEcm6r*S7dPg zY`)$^5V$JCIf_PIa5vV&jAq9QA@-7Y-MR01FsggY|9&O9%4yBv%{+;O^?yvSh=!tRkdCYQ`Z#m5;LEH=>a`|y^4o>NUb1b3 zd|yn_UeWXsLL79V)yvY-@=KoVBwUYhS?TeeLFawm8W~G$%e67Ej8N`2L7Hpx(WaoFaFsLk;^Mp;!Eb=iN;C`uHHm#6 zSg!Fq|Nf-AB~ouY@Aw=cAu%x=Sa#g`gNOj#+c5&Sf=>U(o~-}n>g$!henmn8F&7Vy z)y*}`wd|&}tZW15DJ?y{Nq}Zcx4HHoeSf!z^Z=T`CVy{fsWZ^h-2D5uZ(%!&?RNEN zQH`h(5fK3FfVw#XmX9eVdzNj-qbFR>^R*C*8O6rJ8KUe%~3_1X;=tG6fHgul)5fn@GcR1ib zGbxm_5yDB1**J}r9nio(kL%VB9?N)^W2|G{dLXasBeuLQlzz2CgyN#n+V>iYY4&QJ zCN6|$S{2s`ZGvQTd@AjU2?_y69TeH@CVDn3(pNUSEpVo4KF2b78B|h|debUqYZ}z} zcXX<)apxycaWW=P{gTN%5WztIj(LM|YrZexex|#u<0O6Are+1FQ{z|yb0$k5kvg7N1Mv_(r3miGZWnd%v3R9JX4tj8x>(xYhUu zby^%}XfJRh8d}glT5B#P$G^5iJG~L5Z>uWk&DiKy_L$UsQsMIVJT|>O_+U7O`q`&% zh-^34x!|2<#b&kHRx-qs!w?0iTfzqZXsnJK=?hEPWyWrv$&Lt2cl31V3*YzykCy%Y z)R7CnFYB=}#@fBUs>d2!9OXa$P-HKQr~1vDhjrjl2j>cNN%j>9D9* zGdt^YZA}D+;?+GmWxohQ47{-xs8?k4IMD4;_|{$xtw~73^{X3#okk=-eLuAO9yLRi zZ3Tyxcb(YItqwML#AkhA`~32aV|m4Vl$TGsqUVi>72CD5V|w+JNOBh++{Y)Bk4nNF zNTprFxPHDasF=ZRNCIE6SEn35O;l{UakB38-i-+>-ZZ}bjF*s{$hVyMp-6;^W^6>* z{SSnSvIY?QbDO~%pJ%ZV)OZM9cN{Ggd?4DSV74mt_RIi*H==kNFPm;HtoR|)XNFCu z%ptpAaH!t|Dtf+Fnqn&sZ&D)$fzrmS*|7`?fuGjQ?*s}u37b+jvqq`L&&`=C4JjY9 zm3CGSk3=k)awHvw&$*WG$~yj*IHP%AuI&&*7&#xJ&y7E$i0@K+8%9{29tBrwt zC2*JGZ2T!N-%OB@v!t1#&iL2mN^pd9<1OOMsymKy|Iyi;j_V>Cs`Gr#gOO-kn4v(+ z7Vc?0TV4kJ8o@VcI7DtK>CfV3Tuyxs|M_C{3bd)^Ff(H^>&fV+UEf8?x>v3^jcb3} zU$(-5J9O%-y+JB>dI@+NGx|vecNq0IVRM=Vs0_G|r;=xOJgVP$v23#sS}XNB)R_~W z^heY?+bmapEs_z1ywsJ&qvA~!5ZzOzip60o?y`jJV~sSae|W)uS^VHmU(e>-G9}5b zMk!db2^R~WQh5Ss?^qs@_qdpWv+$+bu8#8lk=jYAr=o|uf!GLU^XT|R`uD=Y=V+gU zl4&~1W0Dy=&ikH=_~&202T!`C*Ij?L*a|Bs(_8c6P8SkNHeeSnT^?h+ANdHpG+I>K zkd3hBwZrS3D!dz6G|ENO@jB*mY^fsVl0DqQ&+~CND<|Jn>ETWbaxX$p;6TACyPKl_ zID7qcMq1whm_blXG5Gqcimn_ERftT5VBA(_$%vhE@43AY*Y?s-yx_5=*PQ6T2yd`C z83VRR6v|Pw-viL0|08nLwOt)|F@^dZ+t5*R-AVD_w2;M0&{b|fK(VokN>KH07CU}W zu+dL4l#q3+))`SLQBm(A^2o+4U2*fr`&G+&Z5;@mVxL~>B6EJ^bo~Ho|C>={jBjv{ z-~0C{+DxV6URr-5CMLHQvA^PGyg9Y&p1*X_RyF@j#uO!Y?j6LVH|uLn;+LvAwnVzs zp&;ty-La^k%G3q~Ch`~84)hPre!7m?b;o~S{`%yqXPiB(Ohf#3_5o3+am`FK z*Q+o}f=>sAIKiaE%FWwBzB|ai4DmN1+%)5iiw~F7D`(SxWouxql{iU`Z7mEShEHqQ z7)HWDTHJd+L=dTffV3#o;PwPaQ~~g3s)>sSvUIXRy8hxgtn)hEDJm)&NH73gl1+bc zG}?H0O#58GfDD;);pZJ`Hvvd!HEnG>dWo`Kx8bnISO6@LDXOS&>+9y>;n@Pp*#IVa zuE}L^7@6&b|J~Z#i%S}G+W~QKf7JHJR?I&xU=ZlvkC+u|;ZX}#0+Fi==-=GD#R(oF zZt&J1h#qsCayTi?V%>cNwZJagiScn0IgoNIzz|gX<%^MA^PkvH0tRwvMa352a4|sz z70RwH9G|U50rAIS-4n5YG1vaPP}-5DwY78N#f2x3&x9OI-2v4dFACHd@c>M-y=eJc};`Cb3zTth8?@_Mp z`$gD}n{Au{Fqg{i9#tIZA>f~k*CCH<{sAdT9z=-D=5y23)HEdOe-2T%wy;o9Q;Vhc z+O9e(K~Zz@pYQO~_iuN=6D=BwA_Wyn&9zsis^0h{Yapk*L>M+&LuSLfPy^~wY#!Yp Y>=i^cRRn}Az-4+VsVGq{X7KJm0OQuJIsgCw literal 0 HcmV?d00001 diff --git a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc new file mode 100644 index 00000000000..a266ec62a2a --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc @@ -0,0 +1,221 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example webenginewidgets/permissionbrowser + \examplecategory {Web Technologies} + \title WebEngine Widgets Permission Browser Example + \ingroup webengine-widgetexamples + \brief Demonstrates how to handle website permission requests, and manage + existing permissions. + + \image permissionbrowser-example.png + + Permission Browser demonstrates how to use the \l{QWebEnginePermission} class + to manage website permissions. The example includes code for handling incoming + permission requests, as well as modifying already existing permissions. Also + demonstrated are the effects of the different permission persistence policies + defined within the \l{QWebEngineProfile} class. + + \include examples-run.qdocinc + + \section1 Class Definitions + + \section2 MainWindow + + The \c MainWindow class inherits \l QMainWindow. Inside, we declare a convenience + pointer to the \l QVBoxLayout which will lay out the widgets used to manipulate + individual permissions, as well as another convenience pointer to the widget + displaying the currently pending permission request. We also declare a + \l QWebEngineView, which will be used to display the actual webpage contents. + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.h + \skipto class MainWindow : + \printuntil /^\}/ + + The rest of the layout for the application is defined inside mainwindow.ui, + and was created using Qt Creator's Design mode. \c MainWindow is a child class + of Ui_MainWindow, which is a C++ class generated at compile time from the + definitions found inside mainwindow.ui. + + \section2 PermissionWidget and PermissionDialog + + The \c PermissionWidget class defines a widget corresponding to a single + \l QWebEnginePermission instance. For convenience, the \l QWebEnginePermission + object is stored within. The widget itself has controls for granting, denying, + or deleting the permission; all of this is defined inside \c PermissionWidget.ui. + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.h + \skipto class PermissionWidget : + \printuntil /^\}/ + + When clicking the "New" button in the main window's UI, a pop-up window will + appear, allowing the user to pre-grant permission to a known origin. That + pop-up is defined by the \c PermissionDialog class: + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.h + \skipto class PermissionDialog : + \printuntil /^\}/ + + \section1 Handling incoming permission requests + + Whenever a website uses an API that might compromise the user's privacy, the + browser is expected to show them a prompt asking to either grant or deny permission. + The PermissionBrowser example has a dedicated section at the bottom right, which + gets populated with a \c PermissionWidget whenever that happens. + + The \c PermissionWidget displays the permission's origin, the requested + \l QWebEnginePermission::Feature, as well as the current status of that permission. + It also has buttons for granting and denying the permission. Since the permission status + is (by default) remembered, the delete button allows the user to remove the permission + from the underlying storage. + + To achieve all this, we first connect QWebEnginePage's \c permissionRequested signal + to \c MainWindow's \c handlePermissionRequested slot: + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto connect(m_webview->page(), + \printline connect(m_webview->page(), + + The signal handler is relatively simple: it attempts to create a \c PermissionWidget + instance for the provided QWebEnginePermission object, and if it succeeds it + plugs that widget into the QFrame designated for pending permissions. We also + subscribe to \c PermissionWidget's \c permissionModified signal so that we can later move + the \c PermissionWidget from the bottom right to the list of existing widgets above. + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto void MainWindow::handlePermissionRequested + \printuntil /^\}/ + + We only create a new \c PermissionWidget if we don't already have an existing one: + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto PermissionWidget *MainWindow::create PermissionWidget + \printuntil /^\}/ + + \target PermissionWidgetConstructor + \section1 Modifying a permission and displaying it to the user + + The QWebEnginePermission interface provides the \l {QWebEnginePermission::grant}{grant}() + and {QWebEnginePermission::deny}{deny}() functions, which are all that's needed to + change the status of a permission. If the application needs to forget about a permission, + we use the {QWebEnginePermission::reset}{reset}() function. + + Inside the \c PermissionWidget constructor, we hook those function up to the buttons' + \c clicked signal, so that we can execute the relevant functionality on the + QWebEnginePermission object. + + Whenever a button is pressed, we emit the \c permissionModified signal, which + \c MainWindow uses to know when it needs to move the widget from the bottom-right + to the list of existing permissions. We also make sure to call \c updateState(), which + handles visual updates to the widget. When the delete button is pressed, we also make + sure mark the widget for deletion, since we only want to display existing permissions to + the user. + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto PermissionWidget::PermissionWidget + \printuntil /^\}/ + + The \c updateState() function displays the data supplied by QWebEnginePermission + to the user. It also makes sure that, when a permission is in the + \l QWebEnginePermission::Invalid state, the buttons for granting or denying it + are disabled. + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto void PermissionWidget::updateState() + \printuntil /^\}/ + + When a pending permission is granted or denied, we want to move the associated + widget to the list above, which contains all currently existing permissions. + We do this in the MainWindow::handlePermissionModified slot. + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto void MainWindow::handlePermissionModified + \printuntil /^\}/ + + Notably, we only do this in cases where we know the permission is remembered. + This is not true for transient \c Features, + which require a permission prompt be shown to the user every time they're needed. + We also exclude permissions with a \l QWebEnginePermission::Ask state, which + indicates that the permission was \l {QWebEnginePermission::reset}{reset}(), + and we don't add anything to the list of existing permissions when + \l QWebEngineProfile::persistentPermissionsPolicy is set to + \c NoPersistentPermissions. + + \note Check the \l QWebEnginePermission::Feature documentation to see which + \c Features are transient. + + \section1 Displaying and modifying existing permissions + + By default, permissions are stored to disk and retrieved again on application + startup. To get a list of all existing website permissions, we call + \l QWebEngineProfile::listPermissions(): + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto void MainWindow::loadStoredPermissions() + \printuntil /^\}/ + + For every permission in the list, we simply construct a new \c PermissionWidget, and + add it to the list on the right-hand side of the screen. Existing permissions + are modified \l {PermissionWidgetConstructor}{using the exact same API as pending ones}. + + \section1 Pre-granting permissions + + Certain permissions may be granted in advance, provided the origin and Feature type + are known. Clicking on the "New" button in the top right will create a pop-up + dialog that allows you to do just that. The dialog is implemented by the + \c PermissionDialog class: + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto PermissionDialog::PermissionDialog + \printuntil /^\}/ + + We populate the \l QComboBox using the QMetaEnum type associated with + \l QWebEnginePermission::Feature. We make sure to filter out transient + features, since pre-granting these is not supported. + + We display the dialog and add show the resulting \c PermissionWidget + in the UI inside the \c MainWindow::handleNewClicked slot. The new + permission is handled the same way we would if a website requested it: + by calling \c handlePermissionRequested(). + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto void MainWindow::handleNewClicked() + \printuntil /^\}/ + + \section1 Changing the permission persistence policy + + By default, permissions are stored to disk for every named QWebEngineProfile, + and in memory for every unnamed/off-the-record one. Normally, this setting + won't be changed at runtime, but this example explores the effects + of each option. + + \list + \li \l QWebEngineProfile::PersistentPermissionsOnDisk is the default, and it ensures + that any permissions that have been granted in the current application run will be + loaded back up at next startup. A permission onlycneeds to be granted once, and + subsequent uses of the API that triggered the request will automatically be granted, + until the application calls QWebEnginePermission::reset(). + li \l QWebEngineProfile::PersistentPermissionsInMemory Has the same behavior as above, + except that permissions will be destroyed at application exit, and not committed + to disk. + li \l QWebEngineProfile::NoPersistentPermissions makes sure permissions are never + remembered, and all act as if they're transient. Thus, every time a web API needs + a permission, a new prompt will be shown to the user. This option is intended for + backwards compatibility and applications which implement their own permission storage. + \endlist + + To ensure the user will be shown previously existing permissions, we need to call + \l QWebEngineProfile::listPermissions(): + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto void MainWindow::loadStoredPermissions() + \printuntil /^\}/ + + This is done one time at startup, as well as whenever the user changes the policy + from the \l QComboBox from the top right. + + \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp + \skipto void MainWindow::handlePolicyComboBoxIndexChanged + \printuntil /^\}/ +*/ diff --git a/examples/webenginewidgets/permissionbrowser/main.cpp b/examples/webenginewidgets/permissionbrowser/main.cpp new file mode 100644 index 00000000000..c1e2c25660e --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/main.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "mainwindow.h" +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("QtExamples"); + QApplication app(argc, argv); + app.setWindowIcon(QIcon(QString(u":AppLogoColor.png"))); + MainWindow window(QUrl("qrc:/landing.html")); + window.resize(1024, 768); + window.show(); + return app.exec(); +} diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp new file mode 100644 index 00000000000..2fe3c3b1706 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp @@ -0,0 +1,270 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "mainwindow.h" +#include +#include +#include +#include +#include + +PermissionDialog::PermissionDialog(const QWebEngineProfile *profile, QWidget *parent) + : QDialog(parent) + , m_profile(profile) + , m_permission(nullptr) +{ + setupUi(this); + + auto metaEnum = QMetaEnum::fromType(); + Q_ASSERT(metaEnum.value(QWebEnginePermission::Unsupported) == 0); + for (int i = 1; i < metaEnum.keyCount(); ++i) { + QWebEnginePermission::Feature feature = QWebEnginePermission::Feature(metaEnum.value(i)); + if (!QWebEnginePermission::isTransient(feature)) + m_featureComboBox->addItem(metaEnum.valueToKey(feature), QVariant(feature)); + } +} + +PermissionDialog::~PermissionDialog() +{ + delete m_permission; +} + +QWebEnginePermission PermissionDialog::permission() +{ + return m_profile->getPermission(QUrl(m_originLineEdit->text()), + QWebEnginePermission::Feature(m_featureComboBox->itemData(m_featureComboBox->currentIndex()).toInt())); +} + +PermissionWidget::PermissionWidget(const QWebEnginePermission &permission, QWidget *parent) + : QWidget(parent) + , m_permission(permission) +{ + setupUi(this); + connect(m_deleteButton, &QPushButton::clicked, [this]() { + m_permission.reset(); + emit permissionModified(this); + deleteLater(); + }); + + connect(m_grantButton, &QPushButton::clicked, [this]() { + m_permission.grant(); + updateState(); + emit permissionModified(this); + }); + + connect(m_denyButton, &QPushButton::clicked, [this]() { + m_permission.deny(); + updateState(); + emit permissionModified(this); + }); + + updateState(); +} + +void PermissionWidget::updateState() +{ + switch (m_permission.state()) { + case QWebEnginePermission::Invalid: + m_stateLabel->setText("Invalid"); + m_grantButton->setEnabled(false); + m_denyButton->setEnabled(false); + break; + case QWebEnginePermission::Ask: + m_stateLabel->setText("Waiting for response"); + break; + case QWebEnginePermission::Granted: + m_stateLabel->setText("Granted"); + break; + case QWebEnginePermission::Denied: + m_stateLabel->setText("Denied"); + break; + } + + m_typeLabel->setText(QMetaEnum::fromType().valueToKey(m_permission.feature())); + m_originLabel->setText(m_permission.origin().toDisplayString()); +} + +MainWindow::MainWindow(const QUrl &url) + : QMainWindow() + , m_layout(new QVBoxLayout) + , m_profile(new QWebEngineProfile("permissionbrowser")) + , m_webview(new QWebEngineView(m_profile, this)) + , m_pendingWidget(nullptr) +{ + setupUi(this); + m_urlLineEdit->setText(url.toString()); + + m_layout->addItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + m_layout->setContentsMargins(0, 0, 0, 0); + m_layout->setSpacing(0); + + QWidget *w = new QWidget(); + w->setLayout(m_layout); + + m_storedScrollArea->setWidget(w); + m_storedScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + (new QVBoxLayout(m_pendingFrame))->setContentsMargins(0, 0, 0, 0); + + loadStoredPermissions(); + + connect(m_deleteAllButton, &QPushButton::clicked, this, &MainWindow::handleDeleteAllClicked); + connect(m_newButton, &QPushButton::clicked, this, &MainWindow::handleNewClicked); + connect(m_refreshButton, &QPushButton::clicked, this, &MainWindow::handleRefreshClicked); + connect(m_backButton, &QPushButton::clicked, this, &MainWindow::handleBackClicked); + connect(m_forwardButton, &QPushButton::clicked, this, &MainWindow::handleForwardClicked); + connect(m_policyComboBox, &QComboBox::currentIndexChanged, this, &MainWindow::handlePolicyComboBoxIndexChanged); + connect(m_webview, &QWebEngineView::urlChanged, this, &MainWindow::handleUrlChanged); + connect(m_webview->page(), &QWebEnginePage::permissionRequested, this, &MainWindow::handlePermissionRequested); + + m_profile->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); + m_profile->settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, true); + + m_frame->layout()->addWidget(m_webview); + static_cast(m_frame->layout())->setStretchFactor(m_webview, 1); + m_webview->load(url); +} + +MainWindow::~MainWindow() +{ + delete m_webview; + delete m_profile; +} + +void MainWindow::handlePermissionRequested(QWebEnginePermission permission) +{ + PermissionWidget *widget = createPermissionWidget(permission); + if (widget) { + m_pendingFrame->layout()->addWidget(widget); + connect(widget, &PermissionWidget::permissionModified, this, &MainWindow::handlePermissionModified); + + if (m_pendingWidget) + m_pendingWidget->deleteLater(); + + m_pendingWidget = widget; + } +} + +void MainWindow::handlePermissionModified(PermissionWidget *widget) +{ + if (!m_pendingWidget || m_pendingWidget != widget) + return; + + m_pendingFrame->layout()->removeWidget(widget); + m_pendingWidget = nullptr; + + if (QWebEnginePermission::isTransient(widget->m_permission.feature()) + || widget->m_permission.state() == QWebEnginePermission::Ask + || m_profile->persistentPermissionsPolicy() == QWebEngineProfile::NoPersistentPermissions) { + + widget->deleteLater(); + return; + } + + m_layout->insertWidget(0, widget); +} + +void MainWindow::handleUrlChanged(const QUrl &url) +{ + m_urlLineEdit->setText(url.toString()); +} + +void MainWindow::handleDeleteAllClicked() +{ + for (int i = m_layout->count() - 1; i >= 0; i--) { + PermissionWidget *widget = qobject_cast(m_layout->itemAt(i)->widget()); + if (!widget) + continue; + + widget->m_permission.reset(); + widget->deleteLater(); + } +} + +void MainWindow::handleNewClicked() +{ + PermissionDialog dialog(m_profile); + if (dialog.exec() == QDialog::Accepted) { + handlePermissionRequested(dialog.permission()); + } +} + +void MainWindow::handleRefreshClicked() +{ + m_webview->load(QUrl::fromUserInput(m_urlLineEdit->text())); +} + +void MainWindow::handleBackClicked() +{ + m_webview->triggerPageAction(QWebEnginePage::Back); +} + +void MainWindow::handleForwardClicked() +{ + m_webview->triggerPageAction(QWebEnginePage::Forward); +} + +void MainWindow::handlePolicyComboBoxIndexChanged(int index) +{ + QWebEngineProfile::PersistentPermissionsPolicy policy; + switch (index) { + case 0: + policy = QWebEngineProfile::PersistentPermissionsOnDisk; + break; + case 1: + policy = QWebEngineProfile::PersistentPermissionsInMemory; + break; + case 2: + policy = QWebEngineProfile::NoPersistentPermissions; + break; + } + + if (policy == m_profile->persistentPermissionsPolicy()) + return; + + for (int i = m_layout->count() - 1; i >= 0; i--) { + PermissionWidget *widget = qobject_cast(m_layout->itemAt(i)->widget()); + if (!widget) + continue; + + widget->deleteLater(); + } + + m_profile->setPersistentPermissionsPolicy(policy); + loadStoredPermissions(); +} + +bool MainWindow::containsPermission(const QWebEnginePermission &permission) +{ + for (const auto *w: std::as_const(m_storedScrollArea->widget()->children())) { + const PermissionWidget *widget = qobject_cast(w); + if (!widget) + continue; + const QWebEnginePermission &widgetPermission = widget->m_permission; + if (widgetPermission == permission) + return true; + } + + if (m_pendingWidget && m_pendingWidget->m_permission == permission) + return true; + + return false; +} + +PermissionWidget *MainWindow::createPermissionWidget(const QWebEnginePermission &permission) +{ + if (containsPermission(permission)) + return nullptr; + + return new PermissionWidget(permission, this); +} + +void MainWindow::loadStoredPermissions() +{ + QList permissionsList = m_profile->listPermissions(); + for (QWebEnginePermission &permission : permissionsList) { + PermissionWidget *widget = createPermissionWidget(permission); + if (widget) + m_layout->insertWidget(0, widget); + } +} diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.h b/examples/webenginewidgets/permissionbrowser/mainwindow.h new file mode 100644 index 00000000000..8f7a0945035 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.h @@ -0,0 +1,74 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "ui_mainwindow.h" +#include "ui_permissiondialog.h" +#include "ui_permissionwidget.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QWebEngineView; +class QWebEngineProfile; +class QLineEdit; +QT_END_NAMESPACE + +class PermissionDialog : public QDialog, public Ui_PermissionDialog +{ + Q_OBJECT +public: + PermissionDialog(const QWebEngineProfile *profile, QWidget *parent = nullptr); + ~PermissionDialog(); + QWebEnginePermission permission(); + +private: + const QWebEngineProfile *m_profile; + QWebEnginePermission *m_permission; +}; + +class PermissionWidget : public QWidget, public Ui_PermissionWidget +{ + Q_OBJECT +public: + PermissionWidget(const QWebEnginePermission &permission, QWidget *parent = nullptr); + + QWebEnginePermission m_permission; + +signals: + void permissionModified(PermissionWidget *widget); + +private: + void updateState(); +}; + +class MainWindow : public QMainWindow, public Ui_MainWindow +{ + Q_OBJECT +public: + explicit MainWindow(const QUrl &url); + ~MainWindow(); + +private slots: + void handlePermissionRequested(QWebEnginePermission permission); + void handleUrlChanged(const QUrl &url); + + void handlePermissionModified(PermissionWidget *widget); + void handleDeleteAllClicked(); + void handleNewClicked(); + void handleRefreshClicked(); + void handleBackClicked(); + void handleForwardClicked(); + void handlePolicyComboBoxIndexChanged(int index); + +private: + bool containsPermission(const QWebEnginePermission &permission); + PermissionWidget *createPermissionWidget(const QWebEnginePermission &permission); + void loadStoredPermissions(); + + QVBoxLayout *m_layout; + QWebEngineProfile *m_profile; + QWebEngineView *m_webview; + PermissionWidget *m_pendingWidget; +}; diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.ui b/examples/webenginewidgets/permissionbrowser/mainwindow.ui new file mode 100644 index 00000000000..4496b8c0782 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.ui @@ -0,0 +1,356 @@ + + + MainWindow + + + + 0 + 0 + 1600 + 900 + + + + Permission Browser + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + :3rdparty/go-previous.png:3rdparty/go-previous.png + + + + + + + + + + + :3rdparty/go-next.png:3rdparty/go-next.png + + + + + + + + + + + :3rdparty/view-refresh.png:3rdparty/view-refresh.png + + + + + + + + + + + + + + + + + 336 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Permissions: + + + + + + + Qt::Horizontal + + + + 87 + 20 + + + + + + + + New + + + + + + + Delete All + + + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Persistence policy: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + 0 + + + QComboBox::AdjustToContents + + + + Persist on disk + + + + + Persist in memory + + + + + Do not persist + + + + + + + + + + + + 0 + 10 + + + + Qt::Horizontal + + + + + + + Stored permissions + + + + + + + + 320 + 0 + + + + + 320 + 16777215 + + + + QFrame::StyledPanel + + + 2 + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + true + + + + + + + + 0 + 10 + + + + Qt::Horizontal + + + + + + + Pending permission + + + + + + + + 0 + 104 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 2 + + + + + + + + + + + + + + + + m_urlLineEdit + returnPressed() + m_refreshButton + click() + + + 509 + 28 + + + 1024 + 27 + + + + + diff --git a/examples/webenginewidgets/permissionbrowser/permissionbrowser.exe.manifest b/examples/webenginewidgets/permissionbrowser/permissionbrowser.exe.manifest new file mode 100644 index 00000000000..acc40177692 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/permissionbrowser.exe.manifest @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/examples/webenginewidgets/permissionbrowser/permissionbrowser.qrc b/examples/webenginewidgets/permissionbrowser/permissionbrowser.qrc new file mode 100644 index 00000000000..80a7d20f254 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/permissionbrowser.qrc @@ -0,0 +1,7 @@ + + + resources/3rdparty/view-refresh.png + resources/3rdparty/go-next.png + resources/3rdparty/go-previous.png + + diff --git a/examples/webenginewidgets/permissionbrowser/permissiondialog.ui b/examples/webenginewidgets/permissionbrowser/permissiondialog.ui new file mode 100644 index 00000000000..a98432131a1 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/permissiondialog.ui @@ -0,0 +1,117 @@ + + + PermissionDialog + + + + 0 + 0 + 400 + 110 + + + + Permission + + + + + + Origin + + + + + + + false + + + + + + + Feature + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + Add + + + + + + + Cancel + + + + + + + + + + + + m_originLineEdit + m_addButton + m_cancelButton + + + + + m_cancelButton + clicked() + PermissionDialog + reject() + + + 349 + 89 + + + 334 + 67 + + + + + m_addButton + clicked() + PermissionDialog + accept() + + + 264 + 88 + + + 218 + 68 + + + + + diff --git a/examples/webenginewidgets/permissionbrowser/permissionwidget.ui b/examples/webenginewidgets/permissionbrowser/permissionwidget.ui new file mode 100644 index 00000000000..0a09da5d3f0 --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/permissionwidget.ui @@ -0,0 +1,119 @@ + + + PermissionWidget + + + + 0 + 0 + 300 + 104 + + + + + 0 + 0 + + + + + 300 + 0 + + + + + 310 + 16777215 + + + + Form + + + + + + QLayout::SetDefaultConstraint + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 10 + + + + + Origin: + + + + + + + Empty + + + + + + + Type: + + + + + + + Empty + + + + + + + State: + + + + + + + Empty + + + + + + + + + + + Grant + + + + + + + Deny + + + + + + + Delete + + + + + + + + + + diff --git a/examples/webenginewidgets/permissionbrowser/resources/3rdparty/COPYING b/examples/webenginewidgets/permissionbrowser/resources/3rdparty/COPYING new file mode 100644 index 00000000000..220881da67d --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/resources/3rdparty/COPYING @@ -0,0 +1 @@ +The icons in this repository are herefore released into the Public Domain. diff --git a/examples/webenginewidgets/permissionbrowser/resources/3rdparty/go-next.png b/examples/webenginewidgets/permissionbrowser/resources/3rdparty/go-next.png new file mode 100644 index 0000000000000000000000000000000000000000..a68e2db77531cb15a2cddd62f567f030513b60fa GIT binary patch literal 1219 zcmV;!1U&nRP)Fd(Ls*Wa_5Q6f;u`ihh?a=O`)@EeXr|Ly9sZ zC=5b3BMHKwqR9S{L?bMO)t&cFZZhGEqz3tp@_}5zJx)hL7Fu!o|&;^gZF(;OA_T|6Jgd0l0 zQ!YoFtGH)szVrIL_irC&WgjdkwrAWh0$K+ogE&WzfXLJ-$IL-MSSuAOasO zUW;WpNF+iC1OlQMW=di6=cym@wTspYgC;v`G*d=DNO?_Zvij)GJxLkNulYHuasf`17F3`RqsJv{BAO(1|N{Zb&|wbRsAkC0$F63Z4?wm{kfX$hnR>7?EXgTQEmj=+Th zBftpm9{&V+vB_-Nv97bV{o?A%Rl$m@5$HA-(h^83jJCiEqm%*>-f0XN9VuV{gDqk_ zJn32dxHjLHZRkvNbiP@=T5SSMUj#(@e?q4Adnv=Gj=;NA5Fr7B(czN=!<<~E-TXZD zC+mWWnzFXmMzi41W>rh-@Kfm|G6~3Z1zvn$MHf({f{-csg-rFk?97+=fs0nDnqy)U zxi|M|D);X84j!qkJM~Af@JtP7!@A)lU)~*iYJmV)yXBJ}E_Ju!B`dHTfewf7*6jP3 z6w7D(FQv(b(+xY1Y*fqITZpIEC1dx^Bwzqt^+hlo7y>w`BrDJ-@t5M)`FKpTs@ zMm|o=9Y;y&2KV28F0QHlMy&(|e#QnLmxOBGD zl>D?laqd`h>9HTwt}s7xmA3A42uTCJLYcHe7Jw~=FfC^x`}gk)cK!ZqOXEKM%E@wd zA_Lq{i&uOx^+dn`UI-Wg2jRUI(I5$o@}aDv+&yq)@4@;V{-UPC{FgyAiZ1kgEcfSQ z(!K&5WI>UAAuo5F-*oR-4&_N(%y0 z5>0!N*ydiwAf#TXK|#&u+I8MN-n)D6dFaLezuUdn zt@c3g_Jtq6Kj+W+{l4e-bPh~m3X{a*Mpa+k;JJzJmy_@&-_4*5MM?B?En1DCl4OLCdP2wL~vvkw^MfWcAl~faU4&#hKb))y# zbnn)-H&(y1@ZriOetXwRtkaVsFy;tE8`Sz)GiQIa^~L5gZ+fMZirm! zX(y4oiggBS4aRAtkTk#c3D#L02J37n1{Z2$4ez$RIW(>a)NGH;cfuTAyKLi}MU_wZ z9bG3#X8LfroMGz>vA@2>SdFn79cp8LEuYP}Ar=UgG=Tt*hHHWA>f% zMBC*b$(nTd*Ws`r92SGc;H1W)aW2rqF)Z5E>^93kF=VQpA&j5w_d2v}>Yg$IL~1bsu- z(Ix`~&Xo`W861O|9{MwJ`m@)`*i_I74x9yR9acN6aTx9Jh>+H)v87<{c~fzYv%5at zzjO1mOJ6Ee(&x;z7^NjX(gQ;pEz%$jQVE0eKqI`+;L&rJi zLF$6qDTsJM)JJMV3CL3|x^3PPmK?K(TW=(~?p|8;O6hOi2Z^WuMCCbISxMj(d^M~U}#=vBJDZBI{MqIT6&Ya^XQzjA)?mw<#9)WLfnH2<5K ze2i%nyO5m&Z0|LOPJC##WjA(i{$ik|Va=-g$nE9jobEq_P$rk-zU@?5)7sQNni*_7dh2=V#2i?Mte=T z5x!mgjJqHe2QR12tca+xvPTv?qe@gMM`K607_;veow%4pHY8WjhNIPh3k}#j(SUdE zXWc$C)X O0000", + "Steven Garrity ", + "Lapo Calamandrei ", + "Ryan Collier ", + "Rodney Dawes ", + "Andreas Nilsson ", + "Tuomas Kuosmanen ", + "Garrett LeSage ", + "Jakub Steiner "] +} diff --git a/examples/webenginewidgets/permissionbrowser/resources/3rdparty/view-refresh.png b/examples/webenginewidgets/permissionbrowser/resources/3rdparty/view-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..cab4d02c756502f922bbff34df34c0056406bd96 GIT binary patch literal 1364 zcmV-a1*`grP)b zm1#^AXBfx-?>jR)yR%CSkD4Z}F=^Tmf|{770@hEqO%szQ{n9is zHEGgX6eKmafTT2OwXsKHJW8z!1VLK`LOl=`0dax7=XjrfU?CiS@JlE8XOfv`e)F4W zo|%^s5&n;jKTAy&;^&>EBHBBo`5EO|sKj&=J z5_Cb3Xb}|nqocOcn7QVqeWz0dr@u@KTRZD39?SzX23GoBb3MSyUw(0^ZDmff>~gB$ zoI%$O1VRQLJess_^m+m#;{k~=9QJeN3zwvG=)Bz$Vg)gg)ls`=U>nzH zUSF+63=0$fFk&_?ZmD@ zc?Mck^<7DVOM82J@iOh}mUc1b4RX!_VG$97nd)|hN(wTZg)gK^L_o+OY+avgFUrrb z_dk3R^J-BR>*^ggbs>p)FV8M3)z7(9XZ@K@nhF@qVOPSI5Z_;`t>7V!6wio%`?=P> zA3pu2HQ3fOOioq8(0B+>0w&hyr!z(7uq*-D9-a>d!)pV>lgu3#<6WMedPCPuFCab# zfSWZH-uC*6wktK|<%Vu;{QXK_`-vYrg7FTH%p?t$ZjC~bI4mJpWT7z$sG36^%FIZv zjn(W8V7$*Fn|I;FwAEE~>4te|Dxga-4h2KwAqW6=g~PIlDMA(iFxz8Gh+v}2@nwv| z{_|(`Ig88U z%-%Ny0HAWkqWLbWYDiTyjEIJ7LTO$Sn$F*e42=4Y zwjJNqu+UBx&J;-%$5e;!r^&ELn(+IpY_e?4oS!pp)0T!Qkdf#F1JK<+Mx3!##qTsP zUG&@%p0g~mVbT}eef!?vhrU2Kn{nKoz45Fth%o?ba^f&J9>kEBT0b&DOv1B6Yh(lH4dhQNwwkZ<1V>QD&5vpGVo|a|^hIHgFiABV;(0R{` zR|+$w;{0^28<*3^uZbcVE|zw(r3W-b^98;e$VZ)-gBS*1HciDJ$>!YH7P5%l`C5O zT5zU1RmBKKOo<2(5#OJqeXYj^t~PZ82t^YlqTmdet=@g?&6^GTF9WaxQ0GL6Mv|Ov zB_X3AA?O|U21fh50QBfwN1{+4fCv%MqNRy3Ce4A(LT%lQu} WXFoWq$46lk&aZQNe#WIfPi$A zq98?j5xwC%=R4>AxZj=Unb~`Le${ zUpLghG~pW-A2o9yBeb)RKLU#cs5+q?kU$MjgbUITiEs+^8bm4p07L?A#^yfeI@)rM zXirhZm5ykDCkBrO02Gu1FbGEvqz}*m>Eeb`WJxJph#CYcn}t8 z6r^kH806t7>%^n11XKu+!xMNSeGtF^&-*BExd26;zj)>F{VOqu2l$tYkB1`9zl<{1 z(Fa1&SR_zVR7%8AOiCIkEh`F^l$Mr|76yuofh9p=5D-L6L>wX~Atomw4*d7QgP#rS zm%ytB(&x4g~V|_ZRhth@!DBAh4{gEJ#coBrYz3*AVdzMEM{BL{Q$h z{$_w7y&bV`7#}w@3V6kca6tR|DDvPf{nrvaG5?`OdH>r@c!z-k5Eu|xRP1U=e=F+f z{Qs(+p8wJI_Ax~M*WUk=*xNV|g9I5Oz0tl{M||L%Z(U7=k%MB92p=@o7>&OFw-@zY z(LQKzS2P9)h5qF=pnwj-(G7Ja6#NUNqa&w*^7cWX9FZC@MIJnlsGFOUoT@Y!A`OFy zL1e{bz+g2=RWSYv5m%Q|msFRMl$87%3qw2ldLmIie`B5giv|B9_9`JfG5DEbNUWP5 z(n%eQ_5}X5a5=Ysv<0g6k9_~eI{l+9Q1ySrg7C(GuEP7j!u_`hpF>yO|0FMd@SpTY zqVPG7#V0pWK}Hk+z^JDIQ#B5l{gFrElWvk3hThgn)g&+D<)v5Q{XtJpV&ODHLr>h& z@1;8@jw*1>kLf~5IBHF7O2D;*?zu4)GEG8eOPHRjsmIU;soYTQ4EvGD%j;xUZWw%N za)2^GjIaC=GRd%9tY{k!{1qX$it{Es=psV&*xZHkPwiC}ZK)V{0>vlj>qFvw4>ZW%Xj88vRaN&%Wbk5d(- z=vEv(4(F4~`k9lYHVndq@cbs`+2oY%qgIK zk6P_qSlUI`_IzwVY&%*x@+ zi||v0gMAUi&$YkQ>9RIt1?`O`KhOT*zX(L)`ij;XDTwGeVIj*)9wk@qr`sq zuqq|@m~U5&61V*^*kj}?^Zjh2wxkw>LO9ume{#xr#pQ+!>@dy<&g4GwRsEhr99J#= z-tBk=zxb|5Y!yNYr8^_rd$P;-ye$vzc zgVNh*4-s{Ra9>IJ_^h)Y38~=DwfP=rLC-j8uPH_(&gR+l(#gm1?=A0i8NG~J(+afL ziEWB<(ra`Z-@_a;_)5hsGKwn9U;lXPj#{FEiT}=Sle~np=p*y|-c@jG{g8LuH~RT> z(>d|=7uii>gnFET&$#&n4VjjAgnvf_S5|1J^+neiC|ffhoAR!#WX92UL1_ZS`OB{u zNLCFPlPEE9-!RAkDbO9!N1c&u-D8os`w)MZc27U>Q7BxU8vvBKIkrkTNHdT@9q&X2q8(cbTw(T;&BN7 zH78M>Qj~NL*~FKS%M{^$aN0_=cKfbh#9+iv>$YXLMwr0IC^&x_G^U#QcDGuJ5&xg9cPI$C|D+HnDP6vTiDRJXYMDINQ~pYX~c#Lny{&f_a4V@ak1?>DEnQFb{~8yZa?u>_hP$K5|S7nGW=_feL) zPp8q9#NH2&J5p_WfKz%=X1HQr#B0L(X!KHWK2MQZV(4Y*<_5-U+4Ym3jP*~mnx?1O zvE&R7rDkJTadrKEPT}hxN%cxI;i5*J+0V|z1kv2CcYO?2C<)~XH#)i(6gk6Q4@>nt z8LGlDk&h5Yv3P;2#LqA}u54tdi~X)u#$wQ4^XcJxhXYAsFLo!uksDkpJi9pm7qq2R z!x6I0P%Hu$TDT@i1SmfMC$>Uz-V&drPCA4?n*Q_+gr@(K<++I-WUzX*E8 zN-uB)?RG#KOxrl+lBs!N!w}{4(`Ouhpx@<3x<);F_Z8>Uv?BJ|6$Rw72k)hn90#&v z4fhdSXC}-0GB=3^603jk?RR-P+ff#fS(I4{!Tg=r!}93@Gnx`rIUeZceWJK8`1BW^wGZkHfC4q zbuets_4PH-$>>wa$74zl1Td_xMn66sxI|5#d2*2F8UxEw zXq=FvNvnqrSBm)nMWZjJLP|2Z$*Y-*`e*`fALOVtQ`9A=xLsi+b_ zBxU~#on}btuVJlMO~fOG#8ag&vP+rdnxs$iS>hsz6`H|T)CGly z6QI~40=Lwjjg$6@7wts)_sYH#&!dV=4FAYeW1GDbZmLAOnf>}LPt$JU0{)DxJ7`e!VrOYaXbO6aq8h!`Z*y+z`lej`r#ctT71bI^6T6s<~s>vQbP+#A&nrF!1<+KgEbg9F6KLEJsb^E6TZi?Kqwmx@`&$7yiwl}^jayGsY zQSoabxX$HXT>6?YQ1=F4qOT(#U-*79A=b??m>*1)lD@O{YGQJ$Iz?W0 ziO}_ZcL?=a8SOwaMj>LPfV2tE?@H0_K&SJ&i1djVps60jJHCaYAxrFQC zq(zW(mTV$&-%M73wX2MF;|_jHY%W`io8v6dYUo#G-s*je8sVB8&B~8ux=M|Y1d(U# z@el8mO)c@=L>1?IQqdnJGeZ(Injy%j8TlXO#m2zCxRtz`a(I1E9nSftpV>SKM1h- zFOt%;41L|-ecNCLs4stT`0lW6V?4M%BzMn^VUhy>e1;;q#Gd#}tPhD-{dLs&*$2rH72bdbkGVhjlfHUO zPx=KiRk}xzH!DepESK(NOEPVw9oy1g)@2+=XegH)K~AyK&QUB4Uw`M*>49P?4=jSJ z9uK=(DXtk^D)+%`HNy5@t$*swUfxk^I|u3?pC7+yHn%=WC#U~prM?|_@O#>sl!~5n zM3jv5eG)=vkCJ%Afvdd4J$S`B(P;0IjRcgfwS$ZH7VVL!ej(PsAY#Uj#VxG4;YhfJQwwj0Ls)}~;%Use_jbzC87%25xGJzO{H}>Yd zRonCq2Xr?dQD$;?-`uE&B<+2h;#!%QNJ_O*<(Zq|JZ)+q_`Q9=6{;nAxAhmKQZ;J& z!7#F#nGZ@T$h_|F*t_~O7*5~ih|Bh1ogmRdhR~RaO3H*Vk7ihd$&f$IyCGfUL_;nHEN+vFL_9D50gUx>2TQB9qA~g`}s_9N2i-&I zmX1Z{ccZ5I*QJyeS3oNF>}p&PN}NwZn44f6JWmO?_~#1Ju8Pdc3BVZ%ksD-pvzp*q zt&%Oiv_$BO%4CChOv$tM%nndHtn`wWu^ISM#hMiy_G@2m-gIRr7Gf*wpxnn5~m}N1j4LfONle5O*dtr2d`V(d_qK zB-zCgM^&`OAjm;!YAsV>GZVh&+QuK;5y%bY+?1v_i?LA1{JEne9LFkrOF8iMx3eAt zvH`k}r28|2tkSOQ;mx{aPNK*Hjf%K0D1 z)}Y#gEu!Hu72CaR8%h_@neYcLcVNIf+>e<9r|T#TY=&)u7jrJ>B=cAW)eCehmeq9$-nQOX4uuA%KUFy!{gK8uZ4`Ff=PLU*cUGxCQfsbDHjw9_}G3_Qd zma^<_B=S^-P!DFf605+#0e8ON9wvSEKuyzs@m+12y-TICfX#}cZBDIy&$BOaQS7SQ zaB89=uxmOTyjNXJ#sfM#IBNX5tGfd^FN42>%ojgOo@e1N>uwZh+cgcEw;25Nf=m7S z^U|gozszq+`!ikmQb*+4&YaSNp7Yp`%^JhEE~`tM#IE_jN$iLH3@7(y%xgkiZYwIL z*(LM^7t!kHcCtR!IQe43W)wH{P*%$OtnycbUeQrIp+@CPvw_(I!eNcr~hQS6<`H?ORRK zcov;Pd{V5e)fqomwvtW#H8M)zvBDzZgV|f=T@IMo1AefXa2Ew8Qx zS}h8h{D}hXd4~c(?KP%Vr0#p+f5fQ1OGo4l!9%iK1 zTBl7gNy~Qlqki^Qz)mhehgvr^%)?+|-MQ;~)>J4I8=>^{$_|jE%GCY#!w`s| zt4?(aHi1!r|50$k*g3je*ZjLUz!zXv{?IsU@zpn&HLwM!An@VCD`R^2(^mJn1;RM0 fEX>*;;+udTxg@9kSPIXppY9rJy0GfI_7VRBJJS%C literal 0 HcmV?d00001 diff --git a/examples/webenginewidgets/permissionbrowser/resources/landing.html b/examples/webenginewidgets/permissionbrowser/resources/landing.html new file mode 100644 index 00000000000..5d921671fcb --- /dev/null +++ b/examples/webenginewidgets/permissionbrowser/resources/landing.html @@ -0,0 +1,88 @@ + + + + + Permissions example page + + + +

Permission Browser Example

+
+

Clipboard

+
+ + +
+
+ + +
+
+
+

Notifications

+
+ +
+
+
+

Local fonts

+ + +
+ + From 3fad66045a4482945d223916097b80fbc917b81b Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Fri, 24 May 2024 09:56:05 +0200 Subject: [PATCH 007/341] Ensure Chromium features are propagated to child processes With the 118 update, the fallback code path that passed Chromium feature flags via the command line was completely removed in favor of a shared memory model. Correctly initializing this requires having a FieldTrialList instance alive somewhere, but some fixups when integrating 118 rendered that code path unreachable. As a result, Chromium features were never getting sent to the render process, and were only visible on the main WebEngine process. This change adds a FieldTrialList instance inside WebEngineContext, which allows the FeaturesList class to work correctly, and thus correctly propagate features to the render process. Pick-to: 6.7 Change-Id: I6d07ea4a7c87db83e526ea62ca4d86526463ad1a Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 1e0c7155877a4cf81c6a3c5d26b02c939b0dd049) Reviewed-by: Qt Cherry-pick Bot --- src/core/web_engine_context.cpp | 5 +++++ src/core/web_engine_context.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index faf9bd54229..e38d8af8917 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -11,6 +11,7 @@ #include "base/functional/bind.h" #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/metrics/field_trial.h" #include "base/power_monitor/power_monitor.h" #include "base/power_monitor/power_monitor_device_source.h" #include "base/run_loop.h" @@ -970,6 +971,10 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitchASCII(switches::kUseAdapterLuid, luid.toStdString()); } #endif + // We need the FieldTrialList to make sure Chromium features are provided to child processes + if (!base::FieldTrialList::GetInstance()) { + m_fieldTrialList.reset(new base::FieldTrialList()); + } initializeFeatureList(parsedCommandLine, enableFeatures, disableFeatures); diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 50b080db100..faed5866180 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -16,6 +16,7 @@ namespace base { class RunLoop; class CommandLine; +class FieldTrialList; } namespace content { @@ -102,6 +103,7 @@ class WebEngineContext : public base::RefCounted { std::unique_ptr m_defaultProfileAdapter; std::unique_ptr m_devtoolsServer; QList m_profileAdapters; + std::unique_ptr m_fieldTrialList; #if QT_CONFIG(accessibility) std::unique_ptr m_accessibilityActivationObserver; #endif From 012b99c60ecf1398442f72697115eff17bb910ec Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Mon, 3 Jun 2024 12:23:33 +0200 Subject: [PATCH 008/341] Remove anonymus namespace from QWebEngineLoadingInfo header Fix code checker warning. Change-Id: I3f3fb2c6a3c08679dde2515066f7423d890b5a8e Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 6a02b2fc67f1fdffd28472008b76db8d291d6f9a) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineloadinginfo.h | 4 ---- src/core/net/custom_url_loader_factory.cpp | 9 ++++----- src/core/web_contents_delegate_qt.cpp | 8 ++++++++ src/core/web_contents_delegate_qt.h | 1 + 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/core/api/qwebengineloadinginfo.h b/src/core/api/qwebengineloadinginfo.h index e50718d7cae..48d14601ab6 100644 --- a/src/core/api/qwebengineloadinginfo.h +++ b/src/core/api/qwebengineloadinginfo.h @@ -12,9 +12,6 @@ #include namespace QtWebEngineCore { -namespace { -class CustomURLLoader; -} class WebContentsAdapter; class WebContentsDelegateQt; } @@ -78,7 +75,6 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo friend class QQuickWebEngineViewPrivate; friend class QtWebEngineCore::WebContentsAdapter; friend class QtWebEngineCore::WebContentsDelegateQt; - friend class QtWebEngineCore::CustomURLLoader; }; QT_END_NAMESPACE diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp index 954253b54de..b91a1289bda 100644 --- a/src/core/net/custom_url_loader_factory.cpp +++ b/src/core/net/custom_url_loader_factory.cpp @@ -28,6 +28,7 @@ #include "qwebengineloadinginfo.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" +#include "web_contents_delegate_qt.h" #include "web_contents_view_qt.h" #include @@ -358,10 +359,9 @@ class CustomURLLoader : public network::mojom::URLLoader void notifySuccess() override { if (m_webContents) { - WebContentsAdapterClient *client = WebContentsViewQt::from(static_cast(m_webContents)->GetView())->client(); - QWebEngineLoadingInfo info(toQt(m_request.url), QWebEngineLoadingInfo::LoadSucceededStatus); - client->loadFinished(std::move(info)); - client->updateNavigationActions(); + WebContentsDelegateQt *delegate = + static_cast(m_webContents->GetDelegate()); + delegate->emitLoadSucceeded(toQt(m_request.url)); } } void notifyReadyRead() override @@ -534,4 +534,3 @@ mojo::PendingRemote CreateCustomURLLoaderFacto } } // namespace QtWebEngineCore - diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index e16f5d769a2..70ee07cbb18 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -479,6 +479,14 @@ void WebContentsDelegateQt::DidStopLoading() m_loadingInfo.clear(); } +void WebContentsDelegateQt::emitLoadSucceeded(const QUrl &url) +{ + // Used by CustomURLLoader to emit LoadSucceeded bypassing the inner state of this delegate + m_viewClient->loadFinished( + QWebEngineLoadingInfo(url, QWebEngineLoadingInfo::LoadSucceededStatus)); + m_viewClient->updateNavigationActions(); +} + void WebContentsDelegateQt::didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription) { m_viewClient->iconChanged(QUrl()); diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 88056c3ca36..df9b5e3e802 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -132,6 +132,7 @@ class WebContentsDelegateQt : public content::WebContentsDelegate content::RenderFrameHost *render_frame_host, bool is_full_page) override; + void emitLoadSucceeded(const QUrl &url); void didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription); void overrideWebPreferences(content::WebContents *, blink::web_pref::WebPreferences*); void allowCertificateError(const QSharedPointer &); From d442e295f4d74d40f243c191adbea7cf75b8bf45 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 30 Jan 2024 14:39:23 +0100 Subject: [PATCH 009/341] Adaptations for Chromium 120 Change-Id: I487d2c6cf56fdda5fb95e6b2715e7dbc42527c2d Reviewed-by: Michal Klocek (cherry picked from commit bbf7a2e7c387f9618e31addcbeb38fd859819cf5) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineurlscheme.cpp | 2 +- src/core/autofill_client_qt.cpp | 15 +++----------- src/core/autofill_client_qt.h | 6 ++---- src/core/browser_accessibility_qt.cpp | 2 +- src/core/clipboard_qt.cpp | 7 +++++-- .../native_skia_output_device_vulkan.cpp | 2 +- src/core/configure/BUILD.root.gn.in | 10 ++++------ ...sponse_interceptor_url_loader_throttle.cpp | 18 ++++++++--------- .../proxying_restricted_cookie_manager_qt.cpp | 7 +++++-- .../proxying_restricted_cookie_manager_qt.h | 2 ++ src/core/net/webui_controller_factory_qt.cpp | 2 +- src/core/ozone/gl_share_context_qt.h | 2 +- src/core/platform_notification_service_qt.cpp | 20 +++++++++++++++++++ src/core/platform_notification_service_qt.h | 2 ++ src/core/pref_service_adapter.cpp | 3 +-- .../printing/print_view_manager_base_qt.cpp | 1 - src/core/profile_adapter.cpp | 1 - .../renderer/content_renderer_client_qt.cpp | 11 +++++----- .../extensions_renderer_client_qt.cpp | 2 +- .../extensions/resource_request_policy_qt.cpp | 2 +- .../extensions/resource_request_policy_qt.h | 2 +- src/core/type_conversion.h | 4 ++-- src/core/web_contents_adapter.cpp | 8 ++++++-- src/core/web_contents_view_qt.cpp | 6 ++++-- src/core/web_contents_view_qt.h | 8 ++++++-- src/core/web_engine_context.cpp | 3 --- tools/scripts/version_resolver.py | 4 ++-- 27 files changed, 86 insertions(+), 66 deletions(-) diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp index 3093c2b8edd..be56a304801 100644 --- a/src/core/api/qwebengineurlscheme.cpp +++ b/src/core/api/qwebengineurlscheme.cpp @@ -372,7 +372,7 @@ void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme) */ QWebEngineUrlScheme QWebEngineUrlScheme::schemeByName(const QByteArray &name) { - base::StringPiece namePiece{ name.data(), static_cast(name.size()) }; + std::string_view namePiece{ name.data(), static_cast(name.size()) }; if (const url::CustomScheme *cs = url::CustomScheme::FindScheme(namePiece)) return QWebEngineUrlScheme(new QWebEngineUrlSchemePrivate(*cs)); return QWebEngineUrlScheme(); diff --git a/src/core/autofill_client_qt.cpp b/src/core/autofill_client_qt.cpp index 3bdc62e199c..44a242d5c6b 100644 --- a/src/core/autofill_client_qt.cpp +++ b/src/core/autofill_client_qt.cpp @@ -70,12 +70,10 @@ void AutofillClientQt::ShowAutofillPopup(const autofill::AutofillClient::PopupOp autoSelectFirstSuggestion); } -void AutofillClientQt::UpdateAutofillPopupDataListValues(const std::vector &values, - const std::vector &labels) +void AutofillClientQt::UpdateAutofillPopupDataListValues( + base::span datalist) { - Q_UNUSED(labels); - - if (values.empty()) + if (datalist.empty()) HideAutofillPopup(autofill::PopupHidingReason::kNoSuggestions); } @@ -130,13 +128,6 @@ scoped_refptr AutofillClientQt::GetURLLoaderFac return nullptr; } -void AutofillClientQt::PropagateAutofillPredictionsDeprecated(autofill::AutofillDriver *, - const std::vector &) -{ - // For testing purposes only. - NOTIMPLEMENTED(); -} - WebContentsAdapterClient *AutofillClientQt::adapterClient() { return WebContentsViewQt::from( diff --git a/src/core/autofill_client_qt.h b/src/core/autofill_client_qt.h index cd38de462e6..b14a486e14f 100644 --- a/src/core/autofill_client_qt.h +++ b/src/core/autofill_client_qt.h @@ -46,8 +46,8 @@ class AutofillClientQt : public autofill::ContentAutofillClient, void ShowAutofillPopup(const autofill::AutofillClient::PopupOpenArgs &open_args, base::WeakPtr delegate) override; - void UpdateAutofillPopupDataListValues(const std::vector &values, - const std::vector &labels) override; + void UpdateAutofillPopupDataListValues( + base::span datalist) override; void PinPopupView() override; PopupOpenArgs GetReopenPopupArgs( autofill::AutofillSuggestionTriggerSource trigger_source) const override; @@ -58,8 +58,6 @@ class AutofillClientQt : public autofill::ContentAutofillClient, void HideAutofillPopup(autofill::PopupHidingReason reason) override; bool IsAutocompleteEnabled() const override; bool IsPasswordManagerEnabled() override; - void PropagateAutofillPredictionsDeprecated(autofill::AutofillDriver *, - const std::vector &) override; bool IsOffTheRecord() override; scoped_refptr GetURLLoaderFactory() override; diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index de3347df36d..ff3d21fb74a 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -617,7 +617,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const return QAccessible::ComboBox; case ax::mojom::Role::kPortal: return QAccessible::Button; - case ax::mojom::Role::kPre: + case ax::mojom::Role::kPreDeprecated: return QAccessible::Section; case ax::mojom::Role::kProgressIndicator: return QAccessible::ProgressBar; diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 3f49c6e3c26..774ba8954b9 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -234,7 +234,8 @@ void ClipboardQt::ReadAvailableTypes(ui::ClipboardBuffer type, if (mimeData->hasFormat(QString::fromLatin1(ui::kMimeTypeWebCustomData))) { const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData)); - ui::ReadCustomDataTypes(customData.constData(), customData.size(), types); + const base::span custom_data(customData.constData(), (unsigned long)customData.size()); + ui::ReadCustomDataTypes(base::as_bytes(custom_data), types); } } @@ -342,7 +343,9 @@ void ClipboardQt::ReadCustomData(ui::ClipboardBuffer clipboard_type, const std:: if (!mimeData) return; const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData)); - ui::ReadCustomDataForType(customData.constData(), customData.size(), type, result); + const base::span custom_data(customData.constData(), (unsigned long)customData.size()); + if (auto maybe_result = ui::ReadCustomDataForType(base::as_bytes(custom_data), type)) + *result = *std::move(maybe_result); } void ClipboardQt::ReadBookmark(const ui::DataTransferEndpoint *data_dst, std::u16string *title, std::string *url) const diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index f51eba98521..50768a2ef4b 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -201,7 +201,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te importedImageCreateInfo.pNext = &externalMemoryImageCreateInfo; importedImageCreateInfo.flags = 0; importedImageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - importedImageCreateInfo.format = gpu::ToVkFormat(m_frontBuffer->sharedImageFormat()); + importedImageCreateInfo.format = gpu::ToVkFormatSinglePlanar(m_frontBuffer->sharedImageFormat()); importedImageCreateInfo.extent.width = static_cast(size().width()); importedImageCreateInfo.extent.height = static_cast(size().height()); importedImageCreateInfo.extent.depth = 1; diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in index 986db502629..698fb16cba0 100644 --- a/src/core/configure/BUILD.root.gn.in +++ b/src/core/configure/BUILD.root.gn.in @@ -349,10 +349,10 @@ source_set("qtwebengine_sources") { "//chrome/browser/tab_contents/web_contents_collection.h", "//chrome/browser/ui/webui/device_log_ui.cc", "//chrome/browser/ui/webui/device_log_ui.h", - "//chrome/browser/ui/webui/devtools_ui.cc", - "//chrome/browser/ui/webui/devtools_ui.h", - "//chrome/browser/ui/webui/devtools_ui_data_source.cc", - "//chrome/browser/ui/webui/devtools_ui_data_source.h", + "//chrome/browser/ui/webui/devtools/devtools_ui.cc", + "//chrome/browser/ui/webui/devtools/devtools_ui.h", + "//chrome/browser/ui/webui/devtools/devtools_ui_data_source.cc", + "//chrome/browser/ui/webui/devtools/devtools_ui_data_source.h", "//chrome/browser/ui/webui/net_internals/net_internals_ui.cc", "//chrome/browser/ui/webui/net_internals/net_internals_ui.h", "//chrome/browser/ui/webui/user_actions/user_actions_ui.cc", @@ -364,8 +364,6 @@ source_set("qtwebengine_sources") { "//chrome/common/chrome_switches.cc", "//chrome/common/chrome_switches.h", "//chrome/common/pref_names.h", - "//chrome/common/url_constants.cc", - "//chrome/common/url_constants.h", "//chrome/common/webui_url_constants.cc", "//chrome/common/webui_url_constants.h", "//components/embedder_support/user_agent_utils.cc", diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp index 159fa28ca97..a99c68367e9 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -30,6 +30,9 @@ #include namespace { + +constexpr uint32_t kFullPageMimeHandlerDataPipeSize = 512U; + void ClearAllButFrameAncestors(network::mojom::URLResponseHead *response_head) { response_head->headers->RemoveHeader("Content-Security-Policy"); @@ -123,9 +126,7 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL MimeTypesHandler::ReportUsedHandler(extension_id); - std::string view_id = base::Uuid::GenerateRandomV4().AsLowercaseString(); - // The string passed down to the original client with the response body. - std::string payload = view_id; + const std::string stream_id = base::Uuid::GenerateRandomV4().AsLowercaseString(); mojo::PendingRemote dummy_new_loader; std::ignore = dummy_new_loader.InitWithNewPipeAndPassReceiver(); @@ -134,19 +135,18 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL new_client.BindNewPipeAndPassReceiver(); - uint32_t data_pipe_size = 64U; // Provide the MimeHandlerView code a chance to override the payload. This is // the case where the resource is handled by frame-based MimeHandlerView. - *defer = extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( - m_frame_tree_node_id, response_url, response_head->mime_type, view_id, - &payload, &data_pipe_size, + const std::string payload = extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( + m_frame_tree_node_id, response_url, response_head->mime_type, stream_id, base::BindOnce( &PluginResponseInterceptorURLLoaderThrottle::ResumeLoad, weak_factory_.GetWeakPtr())); + *defer = true; mojo::ScopedDataPipeProducerHandle producer_handle; mojo::ScopedDataPipeConsumerHandle consumer_handle; - CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(data_pipe_size, producer_handle, consumer_handle)); + CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(kFullPageMimeHandlerDataPipeSize, producer_handle, consumer_handle)); uint32_t len = static_cast(payload.size()); CHECK_EQ(MOJO_RESULT_OK, @@ -189,7 +189,7 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL FROM_HERE, base::BindOnce( &extensions::StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent, - extension_id, view_id, embedded, m_frame_tree_node_id, + extension_id, stream_id, embedded, m_frame_tree_node_id, std::move(transferrable_loader), response_url)); } diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp index d4d5cc4ab3c..29e6de968f5 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.cpp +++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp @@ -67,13 +67,14 @@ void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, bool has_storage_access, network::mojom::CookieManagerGetOptionsPtr options, + bool is_ad_tagged, GetAllForUrlCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, has_storage_access, - std::move(options), std::move(callback)); + std::move(options), is_ad_tagged, std::move(callback)); } else { std::move(callback).Run(std::vector()); } @@ -121,7 +122,7 @@ void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url, underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, has_storage_access, cookie, std::move(callback)); } else { - std::move(callback).Run(false, false); // FIXME: is true, true in aw_proxying_restricted_cookie_manager.cc though.. + std::move(callback).Run(); } } @@ -129,6 +130,7 @@ void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, bool has_storage_access, bool get_version_shared_memory, + bool is_ad_tagged, GetCookiesStringCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -136,6 +138,7 @@ void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, if (allowCookies(url, site_for_cookies)) { underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, top_frame_origin, has_storage_access, get_version_shared_memory, + is_ad_tagged, std::move(callback)); } else { std::move(callback).Run(network::mojom::kInvalidCookieVersion, base::ReadOnlySharedMemoryRegion(), ""); diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.h b/src/core/net/proxying_restricted_cookie_manager_qt.h index faf0545c31b..ba30a448e9f 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.h +++ b/src/core/net/proxying_restricted_cookie_manager_qt.h @@ -29,6 +29,7 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki const url::Origin &top_frame_origin, bool has_storage_access, network::mojom::CookieManagerGetOptionsPtr options, + bool is_ad_tagged, GetAllForUrlCallback callback) override; void SetCanonicalCookie(const net::CanonicalCookie& cookie, @@ -54,6 +55,7 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, bool has_storage_access, bool get_version_shared_memory, + bool is_ad_tagged, GetCookiesStringCallback callback) override; void CookiesEnabledFor(const GURL &url, const net::SiteForCookies &site_for_cookies, diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp index ed35a3e36fe..d38576b8261 100644 --- a/src/core/net/webui_controller_factory_qt.cpp +++ b/src/core/net/webui_controller_factory_qt.cpp @@ -15,7 +15,7 @@ #include "chrome/browser/accessibility/accessibility_ui.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/device_log_ui.h" -#include "chrome/browser/ui/webui/devtools_ui.h" +#include "chrome/browser/ui/webui/devtools/devtools_ui.h" #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h" #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h" #include "chrome/common/url_constants.h" diff --git a/src/core/ozone/gl_share_context_qt.h b/src/core/ozone/gl_share_context_qt.h index 89be0042118..1144d738464 100644 --- a/src/core/ozone/gl_share_context_qt.h +++ b/src/core/ozone/gl_share_context_qt.h @@ -21,7 +21,7 @@ class QtShareGLContext : public gl::GLContext void *GetHandle() override { return m_handle; } unsigned int CheckStickyGraphicsResetStatusImpl() override; // We don't care about the rest, this context shouldn't be used except for its handle. - bool Initialize(gl::GLSurface *, const gl::GLContextAttribs &) override + bool InitializeImpl(gl::GLSurface *, const gl::GLContextAttribs &) override { Q_UNREACHABLE(); return false; diff --git a/src/core/platform_notification_service_qt.cpp b/src/core/platform_notification_service_qt.cpp index 182a5ad849f..2c0a39a67c1 100644 --- a/src/core/platform_notification_service_qt.cpp +++ b/src/core/platform_notification_service_qt.cpp @@ -8,6 +8,8 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_event_dispatcher.h" #include "ui/message_center/public/cpp/notification_delegate.h" +#include "url/gurl.h" +#include "url/origin.h" #include "profile_adapter.h" #include "profile_adapter_client.h" @@ -153,6 +155,24 @@ void PlatformNotificationServiceQt::GetDisplayedNotifications(DisplayedNotificat std::move(callback).Run(std::move(movableStdStringSet), true /* supports_synchronization */); } +void PlatformNotificationServiceQt::GetDisplayedNotificationsForOrigin(const GURL &url, DisplayedNotificationsCallback callback) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + ProfileQt *profile = static_cast(browser_context); + + const url::Origin origin = url::Origin::Create(url); + std::set movableStdStringSet; + auto it = profile->profileAdapter()->persistentNotifications().constBegin(); + const auto end = profile->profileAdapter()->persistentNotifications().constEnd(); + while (it != end) { + if (it.value()->isShown() && origin.IsSameOriginWith(toGurl(https://github.com/it.value()->origin()))) + movableStdStringSet.insert(it.key().toStdString()); + ++it; + } + + std::move(callback).Run(std::move(movableStdStringSet), true /* supports_synchronization */); +} + int64_t PlatformNotificationServiceQt::ReadNextPersistentNotificationId() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); diff --git a/src/core/platform_notification_service_qt.h b/src/core/platform_notification_service_qt.h index bf8fcca04fa..1435f79e984 100644 --- a/src/core/platform_notification_service_qt.h +++ b/src/core/platform_notification_service_qt.h @@ -56,6 +56,8 @@ class PlatformNotificationServiceQt : public content::PlatformNotificationServic // Records a given notification to UKM. void RecordNotificationUkmEvent(const content::NotificationDatabaseData&) override { } + void GetDisplayedNotificationsForOrigin(const GURL&, DisplayedNotificationsCallback callback) override; + content::BrowserContext *browser_context; }; diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index 544a84de1f1..ae7cf102bc4 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -87,8 +87,7 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) registry->RegisterIntegerPref(prefs::kNotificationNextPersistentId, 10000); registry->RegisterDictionaryPref(prefs::kPushMessagingAppIdentifierMap); registry->RegisterListPref(prefs::kAccountInfo); - registry->RegisterStringPref(prefs::kGoogleServicesLastUsername, - std::string()); + registry->RegisterStringPref(prefs::kGoogleServicesLastSyncingUsername, std::string()); registry->RegisterStringPref(prefs::kGoogleServicesAccountId, std::string()); registry->RegisterBooleanPref(prefs::kGoogleServicesConsentedToSync, false); registry->RegisterBooleanPref(prefs::kAutologinEnabled, true); diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp index b2b8e34fc3e..a691bc2b64b 100644 --- a/src/core/printing/print_view_manager_base_qt.cpp +++ b/src/core/printing/print_view_manager_base_qt.cpp @@ -17,7 +17,6 @@ #include "base/task/thread_pool.h" #include "base/timer/timer.h" #include "base/values.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/printing/print_job.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/printer_query.h" diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index c0906003acb..7d6f5cda0ba 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -6,7 +6,6 @@ #include "base/files/file_util.h" #include "base/task/cancelable_task_tracker.h" #include "base/threading/thread_restrictions.h" -#include "base/time/time_to_iso8601.h" #include "components/embedder_support/user_agent_utils.h" #include "components/favicon/core/favicon_service.h" #include "components/history/content/browser/history_database_helper.h" diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index cc127e55fc2..b82c0fb0355 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -196,13 +196,12 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_fr ExtensionsRendererClientQt::GetInstance()->RenderFrameCreated(render_frame, render_frame_observer->registry()); #endif - autofill::PasswordAutofillAgent *password_autofill_agent = - new autofill::PasswordAutofillAgent(render_frame, associated_interfaces); - autofill::PasswordGenerationAgent *password_generation_agent = - new autofill::PasswordGenerationAgent(render_frame, password_autofill_agent, - associated_interfaces); + auto password_autofill_agent = + std::make_unique(render_frame, associated_interfaces); + auto password_generation_agent = + std::make_unique(render_frame, password_autofill_agent.get(), associated_interfaces); - new autofill::AutofillAgent(render_frame, password_autofill_agent, password_generation_agent, + new autofill::AutofillAgent(render_frame, std::move(password_autofill_agent), std::move(password_generation_agent), associated_interfaces); } diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp index b36ed9e8b45..f201e645795 100644 --- a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp +++ b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp @@ -149,7 +149,7 @@ void ExtensionsRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame, if (url.ProtocolIs(extensions::kExtensionScheme) && !resource_request_policy_->CanRequestResource(url, frame, transition_type, - base::OptionalFromPtr(initiator_origin))) { + initiator_origin)) { *new_url = GURL(chrome::kExtensionInvalidRequestURL); } } diff --git a/src/core/renderer/extensions/resource_request_policy_qt.cpp b/src/core/renderer/extensions/resource_request_policy_qt.cpp index a61e533107a..2e4eea771de 100644 --- a/src/core/renderer/extensions/resource_request_policy_qt.cpp +++ b/src/core/renderer/extensions/resource_request_policy_qt.cpp @@ -51,7 +51,7 @@ void ResourceRequestPolicyQt::OnExtensionUnloaded(const ExtensionId &extension_i bool ResourceRequestPolicyQt::CanRequestResource(const GURL &resource_url, blink::WebLocalFrame *frame, ui::PageTransition transition_type, - const absl::optional& initiator_origin) + const url::Origin *initiator_origin) { CHECK(resource_url.SchemeIs(kExtensionScheme)); diff --git a/src/core/renderer/extensions/resource_request_policy_qt.h b/src/core/renderer/extensions/resource_request_policy_qt.h index ec108519fa5..6807f509137 100644 --- a/src/core/renderer/extensions/resource_request_policy_qt.h +++ b/src/core/renderer/extensions/resource_request_policy_qt.h @@ -39,7 +39,7 @@ class ResourceRequestPolicyQt bool CanRequestResource(const GURL &resource_url, blink::WebLocalFrame *frame, ui::PageTransition transition_type, - const absl::optional &initiator_origin); + const url::Origin *initiator_origin); private: Dispatcher *m_dispatcher; diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 0da8a6931b6..688ea014d34 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -209,11 +209,11 @@ QIcon toQIcon(const std::vector &bitmaps); inline QDateTime toQt(base::Time time) { - return QDateTime::fromMSecsSinceEpoch(time.ToJavaTime()); + return QDateTime::fromMSecsSinceEpoch(time.InMillisecondsSinceUnixEpoch()); } inline base::Time toTime(const QDateTime &dateTime) { - return base::Time::FromJavaTime(dateTime.toMSecsSinceEpoch()); + return base::Time::FromMillisecondsSinceUnixEpoch(dateTime.toMSecsSinceEpoch()); } inline QNetworkCookie toQt(const net::CanonicalCookie & cookie) diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 7d9e119e94a..e73eca7f37f 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1736,8 +1736,12 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat if (mimeData->hasText()) dropData->text = toOptionalString16(mimeData->text()); if (mimeData->hasFormat(QLatin1String(ui::kMimeTypeWebCustomData))) { - QByteArray customData = mimeData->data(QLatin1String(ui::kMimeTypeWebCustomData)); - ui::ReadCustomDataIntoMap(customData.constData(), customData.length(), &dropData->custom_data); + const QByteArray customData = mimeData->data(QLatin1String(ui::kMimeTypeWebCustomData)); + const base::span custom_data(customData.constData(), (long unsigned)customData.length()); + if (auto maybe_data = ui::ReadCustomDataIntoMap(base::as_bytes(custom_data))) + dropData->custom_data = *std::move(maybe_data); + else + dropData->custom_data.clear(); } } diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 023f9e99f29..50d964de7fc 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -227,6 +227,7 @@ static Qt::DropActions toQtDropActions(blink::DragOperationsMask ops) } void WebContentsViewQt::StartDragging(const content::DropData &drop_data, + const url::Origin& source_origin, blink::DragOperationsMask allowed_ops, const gfx::ImageSkia &image, const gfx::Vector2d &image_offset, @@ -256,10 +257,11 @@ void WebContentsViewQt::StartDragging(const content::DropData &drop_data, #endif // QT_CONFIG(draganddrop) } -void WebContentsViewQt::UpdateDragCursor(ui::mojom::DragOperation dragOperation) +void WebContentsViewQt::UpdateDragOperation(ui::mojom::DragOperation dragOperation, bool isDrag) { #if QT_CONFIG(draganddrop) - m_client->webContentsAdapter()->updateDragAction(int(dragOperation)); + if (isDrag) + m_client->webContentsAdapter()->updateDragAction(int(dragOperation)); #endif // QT_CONFIG(draganddrop) } diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index 8754250e641..78041a1506d 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -80,13 +80,17 @@ class WebContentsViewQt #endif // content::RenderViewHostDelegateView overrides: - void StartDragging(const content::DropData& drop_data, blink::DragOperationsMask allowed_ops, + void StartDragging(const content::DropData& drop_data, + const url::Origin& source_origin, + blink::DragOperationsMask allowed_ops, const gfx::ImageSkia& image, const gfx::Vector2d& image_offset, const gfx::Rect& drag_obj_rect, const blink::mojom::DragEventSourceInfo &event_info, content::RenderWidgetHostImpl *source_rwh) override; - void UpdateDragCursor(ui::mojom::DragOperation dragOperation) override; + void UpdateDragOperation(ui::mojom::DragOperation dragOperation, bool document_is_handling_drag) override; + + void TransferDragSecurityInfo(content::WebContentsView *) override {} void ShowContextMenu(content::RenderFrameHost &, const content::ContextMenuParams ¶ms) override; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index e38d8af8917..e860e96b44d 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -903,9 +903,6 @@ WebEngineContext::WebEngineContext() enableFeatures.push_back(features::kNetworkServiceInProcess.name); enableFeatures.push_back(features::kTracingServiceInProcess.name); - // When enabled, event.movement is calculated in blink instead of in browser. - disableFeatures.push_back(features::kConsolidatedMovementXY.name); - // Avoid crashing when websites tries using this feature (since 83) disableFeatures.push_back(features::kInstalledApp.name); diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index a29ee34e8f4..707524ef35d 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -43,8 +43,8 @@ def get_recursedeps(self): return self.local_scope["recursedeps"] -chromium_version = '118.0.5993.220' -chromium_branch = '5993' +chromium_version = '120.0.6099.272' +chromium_branch = '6099' ninja_version = 'v1.8.2' json_url = 'http://omahaproxy.appspot.com/all.json' From f22d613e27b993e2baba78e0461f0c708c362c47 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Fri, 1 Mar 2024 20:27:18 +0100 Subject: [PATCH 010/341] Adaptations for Chromium 122 Includes following patches: * 340b36c Bind SpellCheckHost to a RenderFrameHost * f154285 Fix chrome://ukm webui after 122 update * 3e67d86 Adapt datalist test to new Chromium behavior after 122 adaptations * 76b532e Fix test failures in tst_accessibility * 8a9ecf5 Adapt IME test to new Chromium behavior after 122 adaptations * d65cd90 Fix to resolve the DCHECK failure during download operation * e956d1d Ensure DelegatedFrameHost's frame sink ID is registered Done-With: Anu Aliyas, Kaloyan Chehlarski, Martin Negyokru, Peter Varga Change-Id: Ic5e8c0457c1633af18a8e11785041ab423e9362e Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit d868597035a206e57384bc2974db65bf817803a5) Reviewed-by: Qt Cherry-pick Bot --- src/core/CMakeLists.txt | 5 ++ src/core/api/CMakeLists.txt | 6 +- src/core/api/qwebengineurlrequestinfo.cpp | 1 + src/core/api/qwebengineurlrequestinfo.h | 3 +- src/core/autofill_client_qt.cpp | 6 -- src/core/autofill_client_qt.h | 7 +- src/core/autofill_popup_controller.cpp | 6 +- src/core/browser_message_filter_qt.cpp | 2 + src/core/browser_message_filter_qt.h | 4 +- src/core/clipboard_qt.cpp | 16 ++-- src/core/clipboard_qt.h | 7 +- .../extensions/extensions_api_provider_qt.cpp | 2 +- .../extensions/extensions_api_provider_qt.h | 2 +- .../compositor/display_skia_output_device.cpp | 2 +- .../native_skia_output_device_vulkan.cpp | 12 +-- src/core/configure/BUILD.root.gn.in | 15 +++- src/core/content_browser_client_qt.cpp | 77 +++++++++++-------- src/core/content_browser_client_qt.h | 33 ++++---- src/core/desktop_screen_qt.cpp | 7 +- src/core/download_manager_delegate_qt.cpp | 57 +++++++------- src/core/download_manager_delegate_qt.h | 4 +- .../extensions/extension_host_delegate_qt.cpp | 7 +- .../extensions/extension_host_delegate_qt.h | 2 +- .../extensions_browser_client_qt.cpp | 7 +- .../extensions/extensions_browser_client_qt.h | 4 + .../extensions/file_system_delegate_qt.cpp | 31 ++------ src/core/extensions/file_system_delegate_qt.h | 17 ++-- src/core/favicon_service_factory_qt.cpp | 2 +- src/core/favicon_service_factory_qt.h | 2 +- src/core/file_picker_controller.cpp | 4 +- ...file_system_access_permission_context_qt.h | 2 + src/core/media_capture_devices_dispatcher.cpp | 30 +++++++- ...sponse_interceptor_url_loader_throttle.cpp | 24 +++--- src/core/net/proxy_config_service_qt.cpp | 1 - .../net/proxying_url_loader_factory_qt.cpp | 1 + src/core/net/ssl_host_state_delegate_qt.cpp | 4 +- src/core/net/ssl_host_state_delegate_qt.h | 6 +- .../net/system_network_context_manager.cpp | 5 +- src/core/net/webui_controller_factory_qt.cpp | 2 +- src/core/ozone/gl_share_context_qt.cpp | 5 ++ src/core/ozone/gl_share_context_qt.h | 1 + src/core/ozone/gl_surface_qt.cpp | 9 +-- src/core/ozone/ozone_platform_qt.cpp | 9 +-- src/core/ozone/surface_factory_qt.cpp | 16 ++-- src/core/permission_manager_qt.cpp | 14 ++-- src/core/permission_manager_qt.h | 13 ++-- src/core/profile_adapter.cpp | 19 +++-- src/core/profile_io_data_qt.cpp | 33 +++----- src/core/profile_io_data_qt.h | 6 -- src/core/profile_qt.cpp | 5 -- src/core/profile_qt.h | 1 - src/core/render_widget_host_view_qt.cpp | 7 +- src/core/render_widget_host_view_qt.h | 3 +- .../renderer/content_renderer_client_qt.cpp | 27 ++++--- .../renderer/content_renderer_client_qt.h | 2 +- .../renderer/content_settings_observer_qt.cpp | 7 +- .../renderer/content_settings_observer_qt.h | 3 + .../extensions_renderer_client_qt.cpp | 5 +- .../loadable_plugin_placeholder_qt.cpp | 10 +-- .../renderer/render_frame_observer_qt.cpp | 2 +- src/core/renderer/render_frame_observer_qt.h | 2 +- .../renderer/user_resource_controller.cpp | 5 +- .../qwebengine_convert_dict/CMakeLists.txt | 3 + src/core/web_contents_delegate_qt.cpp | 4 +- src/core/web_contents_delegate_qt.h | 4 +- src/core/web_engine_context.cpp | 2 +- .../auto/quick/qmltests/data/tst_datalist.qml | 14 +++- .../accessibility/tst_accessibility.cpp | 19 +++-- .../qwebengineview/tst_qwebengineview.cpp | 23 +++--- 69 files changed, 378 insertions(+), 320 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8ba77607b79..a359cc57f91 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -350,6 +350,8 @@ foreach(arch ${archs}) use_static_angle=true use_perfetto_client_library=false trial_comparison_cert_verifier_supported=false + enable_extensions_legacy_ipc=true + enable_bound_session_credentials=false ) extend_gn_list(gnArgArg ARGS use_v8_context_snapshot v8_use_external_startup_data @@ -577,6 +579,7 @@ target_include_directories(WebEngineCore PRIVATE ${buildDir}/$/${arch}/gen ${buildDir}/$/${arch}/gen/third_party/perfetto ${buildDir}/$/${arch}/gen/third_party/perfetto/build_config + ${buildDir}/$/${arch}/gen/base/allocator/partition_allocator/src ) set(stamps QtWebEngineCore.stamp) @@ -632,7 +635,9 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING) target_include_directories(${dict_target_name} PRIVATE ../3rdparty/chromium ../3rdparty/chromium/third_party/boringssl/src/include + ../3rdparty/chromium/base/allocator/partition_allocator/src ${buildDir}/$/${arch}/gen + ${buildDir}/$/${arch}/gen/base/allocator/partition_allocator/src ) add_gn_build_artifacts_to_target( CMAKE_TARGET ${dict_target_name} diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt index e14d0cd5c18..2a06baec664 100644 --- a/src/core/api/CMakeLists.txt +++ b/src/core/api/CMakeLists.txt @@ -51,6 +51,7 @@ qt_internal_add_module(WebEngineCore ../../3rdparty/chromium/third_party/abseil-cpp ../../3rdparty/chromium/third_party/perfetto/include ../../3rdparty/chromium/third_party/boringssl/src/include + ../../3rdparty/chromium/base/allocator/partition_allocator/src LIBRARIES Qt::CorePrivate Qt::GuiPrivate @@ -67,10 +68,13 @@ qt_internal_add_module(WebEngineCore set_target_properties(WebEngineCore PROPERTIES QTWEBENGINEPROCESS_NAME ${qtWebEngineProcessName}) set_target_properties(WebEngineCore PROPERTIES CXX_STANDARD 20) - # Chromium included headers are not clean qt_skip_warnings_are_errors(WebEngineCore) +if(MSVC AND NOT CLANG) + target_compile_options(WebEngineCore PRIVATE "/Zc:preprocessor") +endif() + if(CLANG OR GCC) target_compile_options(WebEngineCore PRIVATE "-Wno-unused-parameter" diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp index 152cf4dd09e..b323b5ec3b3 100644 --- a/src/core/api/qwebengineurlrequestinfo.cpp +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -161,6 +161,7 @@ QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPriva \value ResourceTypeNavigationPreloadSubFrame A sub-frame service worker navigation preload request. (Added in Qt 5.14) \value ResourceTypeWebSocket A WebSocket request. (Added in Qt 6.4) \value ResourceTypeUnknown Unknown request type. + \value ResourceTypeJson A JSON module. (Added in Qt 6.9) \note For forward compatibility all values not matched should be treated as unknown, not just \c ResourceTypeUnknown. diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h index 33efcbedafe..b8a02d07a82 100644 --- a/src/core/api/qwebengineurlrequestinfo.h +++ b/src/core/api/qwebengineurlrequestinfo.h @@ -47,8 +47,9 @@ class Q_WEBENGINECORE_EXPORT QWebEngineUrlRequestInfo ResourceTypePluginResource, // A resource requested by a plugin ResourceTypeNavigationPreloadMainFrame = 19, // A main-frame service worker navigation preload request ResourceTypeNavigationPreloadSubFrame, // A sub-frame service worker navigation preload request + ResourceTypeJson, // a JSON module (import ... with { type: "json" }) #ifndef Q_QDOC - ResourceTypeLast = ResourceTypeNavigationPreloadSubFrame, + ResourceTypeLast = ResourceTypeJson, #endif ResourceTypeWebSocket = 254, ResourceTypeUnknown = 255 diff --git a/src/core/autofill_client_qt.cpp b/src/core/autofill_client_qt.cpp index 44a242d5c6b..15162e9e926 100644 --- a/src/core/autofill_client_qt.cpp +++ b/src/core/autofill_client_qt.cpp @@ -97,12 +97,6 @@ std::vector AutofillClientQt::GetPopupSuggestions() const return {}; } -void AutofillClientQt::UpdatePopup(const std::vector &, autofill::PopupType, autofill::AutofillSuggestionTriggerSource) -{ - // Called by password_manager component only. - NOTIMPLEMENTED(); -} - void AutofillClientQt::HideAutofillPopup(autofill::PopupHidingReason) { adapterClient()->hideAutofillPopup(); diff --git a/src/core/autofill_client_qt.h b/src/core/autofill_client_qt.h index b14a486e14f..4f10882d24c 100644 --- a/src/core/autofill_client_qt.h +++ b/src/core/autofill_client_qt.h @@ -19,6 +19,7 @@ #include #include "base/memory/weak_ptr.h" +#include "base/containers/span.h" #include "components/autofill/content/browser/content_autofill_client.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -52,9 +53,9 @@ class AutofillClientQt : public autofill::ContentAutofillClient, PopupOpenArgs GetReopenPopupArgs( autofill::AutofillSuggestionTriggerSource trigger_source) const override; std::vector GetPopupSuggestions() const override; - void UpdatePopup(const std::vector& suggestions, - autofill::PopupType popup_type, - autofill::AutofillSuggestionTriggerSource trigger_source) override; + void UpdatePopup(const std::vector &suggestions, + autofill::FillingProduct main_filling_product, + autofill::AutofillSuggestionTriggerSource trigger_source) override{}; void HideAutofillPopup(autofill::PopupHidingReason reason) override; bool IsAutocompleteEnabled() const override; bool IsPasswordManagerEnabled() override; diff --git a/src/core/autofill_popup_controller.cpp b/src/core/autofill_popup_controller.cpp index a6baf5fc29f..a4ce0b7f885 100644 --- a/src/core/autofill_popup_controller.cpp +++ b/src/core/autofill_popup_controller.cpp @@ -9,6 +9,8 @@ namespace QtWebEngineCore { +using SuggestionPosition = autofill::AutofillPopupDelegate::SuggestionPosition; + AutofillPopupController::AutofillPopupController(AutofillPopupControllerPrivate *dd) { Q_ASSERT(dd); @@ -26,7 +28,7 @@ void AutofillPopupController::setCurrentIndex(const QModelIndex &index) if (m_currentIndex.isValid()) { const autofill::Suggestion &suggestion = d->suggestions[m_currentIndex.row()]; - d->delegate->DidSelectSuggestion(suggestion, autofill::AutofillSuggestionTriggerSource::kFormControlElementClicked); + d->delegate->DidSelectSuggestion(suggestion); } Q_EMIT currentIndexChanged(index); @@ -79,7 +81,7 @@ void AutofillPopupController::acceptSuggestion() const int index = m_currentIndex.row(); const autofill::Suggestion &suggestion = d->suggestions[index]; - d->delegate->DidAcceptSuggestion(suggestion, index, autofill::AutofillSuggestionTriggerSource::kFormControlElementClicked); + d->delegate->DidAcceptSuggestion(suggestion, SuggestionPosition{ .row = index }); } void AutofillPopupController::notifyPopupShown() diff --git a/src/core/browser_message_filter_qt.cpp b/src/core/browser_message_filter_qt.cpp index e8fcb994ab1..8708fc8306d 100644 --- a/src/core/browser_message_filter_qt.cpp +++ b/src/core/browser_message_filter_qt.cpp @@ -19,6 +19,7 @@ BrowserMessageFilterQt::BrowserMessageFilterQt(int /*render_process_id*/, Profil { } +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) bool BrowserMessageFilterQt::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(BrowserMessageFilterQt, message) @@ -31,6 +32,7 @@ bool BrowserMessageFilterQt::OnMessageReceived(const IPC::Message& message) IPC_END_MESSAGE_MAP() return true; } +#endif void BrowserMessageFilterQt::OnAllowStorageAccess(int /*render_frame_id*/, const GURL &origin_url, diff --git a/src/core/browser_message_filter_qt.h b/src/core/browser_message_filter_qt.h index 0f5721c824f..c19d2f352e9 100644 --- a/src/core/browser_message_filter_qt.h +++ b/src/core/browser_message_filter_qt.h @@ -5,6 +5,7 @@ #define BROWSER_MESSAGE_FILTER_QT_H #include "base/functional/callback.h" +#include "content/common/buildflags.h" #include "content/public/browser/browser_message_filter.h" class GURL; @@ -20,8 +21,9 @@ class BrowserMessageFilterQt : public content::BrowserMessageFilter BrowserMessageFilterQt(int render_process_id, Profile *profile); private: +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) bool OnMessageReceived(const IPC::Message& message) override; - +#endif void OnAllowStorageAccess(int render_frame_id, const GURL &origin_url, diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 774ba8954b9..1140164ae98 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -9,10 +9,12 @@ #include "clipboard_change_observer.h" #include "type_conversion.h" +#include "base/containers/map_util.h" #include "base/logging.h" #include "base/strings/utf_offset_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/types/variant_util.h" +#include "base/types/optional_util.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/base/clipboard/clipboard.h" @@ -128,8 +130,10 @@ void ClipboardQt::WriteText(base::StringPiece text) getUncommittedData()->setText(toQString(text)); } -void ClipboardQt::WriteHTML(base::StringPiece markup, absl::optional source_url) +void ClipboardQt::WriteHTML(base::StringPiece markup, absl::optional source_url, + ui::ClipboardContentType /*content_type*/) { + QString markup_string = toQString(markup); #if defined (Q_OS_MACOS) // We need to prepend the charset on macOS to prevent garbled Unicode characters @@ -390,10 +394,9 @@ const ui::ClipboardSequenceNumberToken &ClipboardQt::GetSequenceNumber(ui::Clipb : clipboardChangeObserver()->getSelectionSequenceNumber(); } -const ui::DataTransferEndpoint *ClipboardQt::GetSource(ui::ClipboardBuffer buffer) const +absl::optional ClipboardQt::GetSource(ui::ClipboardBuffer buffer) const { - auto it = m_dataSrc.find(buffer); - return it == m_dataSrc.end() ? nullptr : it->second.get(); + return base::OptionalFromPtr(base::FindPtrOrNull(m_dataSrc, buffer)); } void ClipboardQt::ReadFilenames(ui::ClipboardBuffer buffer, @@ -423,11 +426,6 @@ void ClipboardQt::WriteFilenames(std::vector filenames) getUncommittedData()->setUrls(urls); } -void ClipboardQt::WriteUnsanitizedHTML(base::StringPiece markup, absl::optional source_url) -{ - WriteHTML(std::move(markup), std::move(source_url)); -} - #if defined(USE_OZONE) bool ClipboardQt::IsSelectionBufferAvailable() const { diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h index 22f24cfe5ac..62dc2fbe6a3 100644 --- a/src/core/clipboard_qt.h +++ b/src/core/clipboard_qt.h @@ -36,7 +36,8 @@ class ClipboardQt : public ui::Clipboard std::vector GetStandardFormats(ui::ClipboardBuffer buffer, const ui::DataTransferEndpoint *data_dst) const override; - const ui::DataTransferEndpoint *GetSource(ui::ClipboardBuffer buffer) const override; + absl::optional GetSource(ui::ClipboardBuffer buffer) const override; + void ReadFilenames(ui::ClipboardBuffer buffer, const ui::DataTransferEndpoint *data_dst, std::vector *result) const override; @@ -48,7 +49,8 @@ class ClipboardQt : public ui::Clipboard std::unique_ptr data_src) override; void WriteText(base::StringPiece text) override; - void WriteHTML(base::StringPiece markup, absl::optional source_url) override; + void WriteHTML(base::StringPiece markup, absl::optional source_url, + ui::ClipboardContentType content_type) override; void WriteRTF(base::StringPiece rtf) override; void WriteBookmark(base::StringPiece title, base::StringPiece url) override; void WriteWebSmartPaste() override; @@ -56,7 +58,6 @@ class ClipboardQt : public ui::Clipboard void WriteData(const ui::ClipboardFormatType &format, base::span data) override; void WriteSvg(base::StringPiece markup) override; void WriteFilenames(std::vector filenames) override; - void WriteUnsanitizedHTML(base::StringPiece markup, absl::optional source_url) override; base::flat_map> m_dataSrc; }; diff --git a/src/core/common/extensions/extensions_api_provider_qt.cpp b/src/core/common/extensions/extensions_api_provider_qt.cpp index 1c8e89747a5..5a0f6d89169 100644 --- a/src/core/common/extensions/extensions_api_provider_qt.cpp +++ b/src/core/common/extensions/extensions_api_provider_qt.cpp @@ -57,7 +57,7 @@ bool ExtensionsAPIProviderQt::IsAPISchemaGenerated(const std::string &name) api::QtWebEngineGeneratedSchemas::IsGenerated(name); } -base::StringPiece ExtensionsAPIProviderQt::GetAPISchema(const std::string &name) +std::string_view ExtensionsAPIProviderQt::GetAPISchema(const std::string &name) { if (!api::GeneratedSchemas::Get(name).empty()) return api::GeneratedSchemas::Get(name); diff --git a/src/core/common/extensions/extensions_api_provider_qt.h b/src/core/common/extensions/extensions_api_provider_qt.h index 34e8bdd9f6b..b5e67aabf4c 100644 --- a/src/core/common/extensions/extensions_api_provider_qt.h +++ b/src/core/common/extensions/extensions_api_provider_qt.h @@ -18,7 +18,7 @@ class ExtensionsAPIProviderQt : public ExtensionsAPIProvider void AddPermissionFeatures(FeatureProvider* provider) override; bool IsAPISchemaGenerated(const std::string& name) override; - base::StringPiece GetAPISchema(const std::string& name) override; + std::string_view GetAPISchema(const std::string &name) override; // Adds feature definitions to the given |provider| of the specified type. void AddManifestFeatures(FeatureProvider* provider) override { } diff --git a/src/core/compositor/display_skia_output_device.cpp b/src/core/compositor/display_skia_output_device.cpp index 0ca466fe82a..ab891f81400 100644 --- a/src/core/compositor/display_skia_output_device.cpp +++ b/src/core/compositor/display_skia_output_device.cpp @@ -31,7 +31,7 @@ class DisplaySkiaOutputDevice::Buffer m_texture = m_parent->m_contextState->gr_context()->createBackendTexture( m_shape.imageInfo.width(), m_shape.imageInfo.height(), colorType, - GrMipMapped::kNo, GrRenderable::kYes); + skgpu::Mipmapped::kNo, GrRenderable::kYes); DCHECK(m_texture.isValid()); DCHECK(m_texture.backend() == GrBackendApi::kOpenGL); diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index 50768a2ef4b..b775276f665 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -4,6 +4,7 @@ #include "native_skia_output_device_vulkan.h" #include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h" +#include "ui/base/ozone_buildflags.h" #include #include @@ -11,17 +12,17 @@ #include #if defined(USE_OZONE) -#include "ui/ozone/buildflags.h" -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) // We need to define USE_VULKAN_XCB for proper vulkan function pointers. // Avoiding it may lead to call wrong vulkan functions. // This is originally defined in chromium/gpu/vulkan/BUILD.gn. #define USE_VULKAN_XCB -#endif // BUILDFLAG(OZONE_PLATFORM_X11) +#endif // BUILDFLAG(IS_OZONE_X11) #include "gpu/vulkan/vulkan_function_pointers.h" - #include "components/viz/common/gpu/vulkan_context_provider.h" #include "gpu/vulkan/vulkan_device_queue.h" +#include "third_party/skia/include/gpu/vk/GrVkTypes.h" +#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h" #endif // defined(USE_OZONE) namespace QtWebEngineCore { @@ -84,7 +85,8 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te return nullptr; } - backendTexture.getVkImageInfo(&vkImageInfo); + GrBackendTextures::GetVkImageInfo(backendTexture, &vkImageInfo); + if (vkImageInfo.fAlloc.fMemory == VK_NULL_HANDLE) { qWarning("VULKAN: Unable to access Vulkan memory."); return nullptr; diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in index 698fb16cba0..1fbbadf2671 100644 --- a/src/core/configure/BUILD.root.gn.in +++ b/src/core/configure/BUILD.root.gn.in @@ -92,6 +92,8 @@ config("cpp20_config") { # Chromium is built with C++20 if (is_win) { cflags_cc = [ "/std:c++20" ] + } else if(is_gcc) { + cflags_cc = [ "-std=gnu++20" ] } else { cflags_cc = [ "-std=c++20" ] } @@ -207,6 +209,8 @@ source_set("qtwebengine_spellcheck_sources") { sources = [ "//chrome/browser/spellchecker/spell_check_host_chrome_impl.cc", "//chrome/browser/spellchecker/spell_check_host_chrome_impl.h", + "//chrome/browser/spellchecker/spell_check_initialization_host_impl.cc", + "//chrome/browser/spellchecker/spell_check_initialization_host_impl.h", "//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc", "//chrome/browser/spellchecker/spellcheck_custom_dictionary.h", "//chrome/browser/spellchecker/spellcheck_factory.cc", @@ -278,6 +282,7 @@ source_set("qtwebengine_sources") { "//components/performance_manager", "//components/permissions:permissions_common", "//components/plugins/renderer/", + "//components/compose:buildflags", "//content/browser/resources/quota:resources", "//extensions/buildflags:buildflags", "//pdf:buildflags", @@ -347,8 +352,8 @@ source_set("qtwebengine_sources") { "//chrome/browser/tab_contents/form_interaction_tab_helper.h", "//chrome/browser/tab_contents/web_contents_collection.cc", "//chrome/browser/tab_contents/web_contents_collection.h", - "//chrome/browser/ui/webui/device_log_ui.cc", - "//chrome/browser/ui/webui/device_log_ui.h", + "//chrome/browser/ui/webui/device_log/device_log_ui.cc", + "//chrome/browser/ui/webui/device_log/device_log_ui.h", "//chrome/browser/ui/webui/devtools/devtools_ui.cc", "//chrome/browser/ui/webui/devtools/devtools_ui.h", "//chrome/browser/ui/webui/devtools/devtools_ui_data_source.cc", @@ -364,6 +369,7 @@ source_set("qtwebengine_sources") { "//chrome/common/chrome_switches.cc", "//chrome/common/chrome_switches.h", "//chrome/common/pref_names.h", + "//chrome/common/url_constants.h", "//chrome/common/webui_url_constants.cc", "//chrome/common/webui_url_constants.h", "//components/embedder_support/user_agent_utils.cc", @@ -556,6 +562,7 @@ group("qtwebengine_resources") { "//chrome/browser:resources", "//chrome/browser/resources:component_extension_resources", "//chrome/common:resources", + "//chrome/browser/resources/device_log:resources", "//components/resources:components_resources", ":qtwebengine_repack_resources", ":qtwebengine_repack_resources_100", @@ -571,9 +578,11 @@ repack("qtwebengine_repack_resources") { "$root_gen_dir/chrome/accessibility_resources.pak", "$root_gen_dir/chrome/common_resources.pak", "$root_gen_dir/chrome/dev_ui_browser_resources.pak", + "$root_gen_dir/chrome/device_log_resources.pak", "$root_gen_dir/chrome/net_internals_resources.pak", "$root_gen_dir/components/components_resources.pak", "$root_gen_dir/components/dev_ui_components_resources.pak", + "$root_gen_dir/components/ukm_resources.pak", "$root_gen_dir/content/attribution_internals_resources.pak", "$root_gen_dir/content/browser/resources/media/media_internals_resources.pak", "$root_gen_dir/content/browser/tracing/tracing_resources.pak", @@ -597,8 +606,10 @@ repack("qtwebengine_repack_resources") { "//chrome/browser/resources/accessibility:resources", "//chrome/browser/resources/net_internals:resources", "//chrome/common:resources_grit", + "//chrome/browser/resources/device_log:resources_grit", "//components/resources:components_resources_grit", "//components/resources:dev_ui_components_resources_grit", + "//components/ukm/debug:resources", "//content/browser/resources/attribution_reporting:resources", "//content/browser/resources/gpu:resources", "//content/browser/resources/histograms:resources_grit", diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index f57cf545572..6fec6a1e87b 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -95,6 +95,7 @@ #if QT_CONFIG(webengine_spellchecker) #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" +#include "chrome/browser/spellchecker/spell_check_initialization_host_impl.h" #include "chrome/browser/spellchecker/spellcheck_factory.h" #include "chrome/browser/spellchecker/spellcheck_service.h" #include "components/spellcheck/browser/pref_names.h" @@ -228,7 +229,7 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost #endif #if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) - WebRtcLoggingController::AttachToRenderProcessHost(host, WebEngineContext::current()->webRtcLogUploader()); + WebRtcLoggingController::AttachToRenderProcessHost(host); #endif // Allow requesting custom schemes. @@ -240,12 +241,13 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost // FIXME: Add a settings variable to enable/disable the file scheme. policy->GrantRequestScheme(id, url::kFileScheme); profileAdapter->userResourceController()->renderProcessStartedWithHost(host); +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) host->AddFilter(new BrowserMessageFilterQt(id, profile)); #if BUILDFLAG(ENABLE_EXTENSIONS) host->AddFilter(new extensions::ExtensionMessageFilter(id, profile)); host->AddFilter(new extensions::MessagingAPIMessageFilter(id, profile)); #endif //ENABLE_EXTENSIONS - +#endif // CONTENT_ENABLE_LEGACY_IPC bool is_incognito_process = profile->IsOffTheRecord(); mojo::AssociatedRemote renderer_configuration; host->GetChannel()->GetRemoteAssociatedInterface(&renderer_configuration); @@ -390,8 +392,9 @@ void ContentBrowserClientQt::BindHostReceiverForRenderer(content::RenderProcessH mojo::GenericPendingReceiver receiver) { #if QT_CONFIG(webengine_spellchecker) - if (auto host_receiver = receiver.As()) { - SpellCheckHostChromeImpl::Create(render_process_host->GetID(), std::move(host_receiver)); + if (auto host_receiver = receiver.As()) { + SpellCheckInitializationHostImpl::Create(render_process_host->GetID(), + std::move(host_receiver)); return; } #endif @@ -434,6 +437,15 @@ void ContentBrowserClientQt::RegisterBrowserInterfaceBindersForFrame( mojo::BinderMapWithContext *map) { map->Add(base::BindRepeating(&BindNetworkHintsHandler)); +#if QT_CONFIG(webengine_spellchecker) + map->Add(base::BindRepeating( + [](content::RenderFrameHost *frame_host, + mojo::PendingReceiver receiver) { + SpellCheckHostChromeImpl::Create(frame_host->GetProcess()->GetID(), + std::move(receiver)); + })); +#endif + #if BUILDFLAG(ENABLE_EXTENSIONS) map->Add(base::BindRepeating(&BindMimeHandlerService)); map->Add(base::BindRepeating(&BindBeforeUnloadControl)); @@ -460,13 +472,9 @@ void ContentBrowserClientQt::ExposeInterfacesToRenderer(service_manager::BinderR { if (auto *manager = performance_manager::PerformanceManagerRegistry::GetInstance()) manager->CreateProcessNodeAndExposeInterfacesToRendererProcess(registry, render_process_host); -#if BUILDFLAG(ENABLE_EXTENSIONS) - associated_registry->AddInterface( - base::BindRepeating(&extensions::EventRouter::BindForRenderer, render_process_host->GetID())); - associated_registry->AddInterface( - base::BindRepeating(&extensions::ExtensionsGuestView::CreateForComponents, render_process_host->GetID())); - associated_registry->AddInterface( - base::BindRepeating(&extensions::ExtensionsGuestView::CreateForExtensions, render_process_host->GetID())); +#if BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC) + associated_registry->AddInterface(base::BindRepeating( + &extensions::EventRouter::BindForRenderer, render_process_host->GetID())); #else Q_UNUSED(associated_registry); #endif @@ -502,12 +510,13 @@ void ContentBrowserClientQt::RegisterAssociatedInterfaceBindersForRenderFrameHos extensions::ExtensionWebContentsObserverQt::BindLocalFrameHost(std::move(receiver), render_frame_host); }, &rfh)); #endif - associated_registry.AddInterface( - base::BindRepeating( - [](content::RenderFrameHost *render_frame_host, - mojo::PendingAssociatedReceiver receiver) { - autofill::ContentAutofillDriverFactory::BindAutofillDriver(std::move(receiver), render_frame_host); - }, &rfh)); + associated_registry.AddInterface(base::BindRepeating( + [](content::RenderFrameHost *render_frame_host, + mojo::PendingAssociatedReceiver receiver) { + autofill::ContentAutofillDriverFactory::BindAutofillDriver(render_frame_host, + std::move(receiver)); + }, + &rfh)); #if BUILDFLAG(ENABLE_PDF) associated_registry.AddInterface( base::BindRepeating( @@ -517,6 +526,12 @@ void ContentBrowserClientQt::RegisterAssociatedInterfaceBindersForRenderFrameHos }, &rfh)); #endif // BUILDFLAG(ENABLE_PDF) ContentBrowserClient::RegisterAssociatedInterfaceBindersForRenderFrameHost(rfh, associated_registry); +#if BUILDFLAG(ENABLE_EXTENSIONS) + associated_registry.AddInterface(base::BindRepeating( + &extensions::ExtensionsGuestView::CreateForComponents, rfh.GetGlobalId())); + associated_registry.AddInterface(base::BindRepeating( + &extensions::ExtensionsGuestView::CreateForExtensions, rfh.GetGlobalId())); +#endif } bool ContentBrowserClientQt::CanCreateWindow( @@ -764,7 +779,8 @@ std::vector> ContentBrowserClientQt::CreateURLLoaderThrottles( const network::ResourceRequest &request, content::BrowserContext *browser_context, const base::RepeatingCallback & /*wc_getter*/, - content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id) + content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id, + absl::optional navigation_id) { std::vector> result; result.push_back(std::make_unique( @@ -883,13 +899,10 @@ bool ContentBrowserClientQt::HasErrorPage(int httpStatusCode, content::WebConten } std::unique_ptr ContentBrowserClientQt::CreateLoginDelegate( - const net::AuthChallengeInfo &authInfo, - content::WebContents *web_contents, - const content::GlobalRequestID & /*request_id*/, - bool /*is_main_frame*/, - const GURL &url, - scoped_refptr /*response_headers*/, - bool first_auth_attempt, + const net::AuthChallengeInfo &authInfo, content::WebContents *web_contents, + content::BrowserContext *browser_context, const content::GlobalRequestID & /*request_id*/, + bool /*is_main_frame*/, const GURL &url, + scoped_refptr /*response_headers*/, bool first_auth_attempt, LoginAuthRequiredCallback auth_required_callback) { auto loginDelegate = std::make_unique(authInfo, web_contents, url, first_auth_attempt, std::move(auth_required_callback)); @@ -1029,9 +1042,8 @@ std::vector ContentBrowserClientQt::GetNetworkContextsParentDire toFilePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) }; } -void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, - ukm::SourceIdObj ukm_source_id, - NonNetworkURLLoaderFactoryMap *factories) +void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories( + int frame_tree_node_id, NonNetworkURLLoaderFactoryMap *factories) { content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); Profile *profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); @@ -1041,10 +1053,9 @@ void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories(int factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter, web_contents)); #if BUILDFLAG(ENABLE_EXTENSIONS) - factories->emplace( - extensions::kExtensionScheme, - extensions::CreateExtensionNavigationURLLoaderFactory(profile, ukm_source_id, - !!extensions::WebViewGuest::FromWebContents(web_contents))); + factories->emplace(extensions::kExtensionScheme, + extensions::CreateExtensionNavigationURLLoaderFactory( + profile, !!extensions::WebViewGuest::FromWebContents(web_contents))); #endif } @@ -1309,7 +1320,7 @@ void ContentBrowserClientQt::CreateWebSocket( std::move(factory).Run(to_url, std::move(headers), std::move(handshake_client), mojo::NullRemote(), mojo::NullRemote()); } -void ContentBrowserClientQt::SiteInstanceGotProcess(content::SiteInstance *site_instance) +void ContentBrowserClientQt::SiteInstanceGotProcessAndSite(content::SiteInstance *site_instance) { #if BUILDFLAG(ENABLE_EXTENSIONS) content::BrowserContext *context = site_instance->GetBrowserContext(); diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index 7d8e9802898..b40c2a343cb 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -150,15 +150,13 @@ class ContentBrowserClientQt : public content::ContentBrowserClient void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) override; #endif - std::unique_ptr CreateLoginDelegate( - const net::AuthChallengeInfo &auth_info, - content::WebContents *web_contents, - const content::GlobalRequestID& request_id, - bool is_request_for_main_frame, - const GURL &url, - scoped_refptr response_headers, - bool first_auth_attempt, - LoginAuthRequiredCallback auth_required_callback) override; + std::unique_ptr + CreateLoginDelegate(const net::AuthChallengeInfo &auth_info, content::WebContents *web_contents, + content::BrowserContext *browser_context, + const content::GlobalRequestID &request_id, bool is_request_for_main_frame, + const GURL &url, scoped_refptr response_headers, + bool first_auth_attempt, + LoginAuthRequiredCallback auth_required_callback) override; bool HandleExternalProtocol( const GURL &url, @@ -174,10 +172,12 @@ class ContentBrowserClientQt : public content::ContentBrowserClient content::RenderFrameHost *initiator_document, mojo::PendingRemote *out_factory) override; - std::vector> CreateURLLoaderThrottles( - const network::ResourceRequest &request, content::BrowserContext *browser_context, - const base::RepeatingCallback &wc_getter, - content::NavigationUIData *navigation_ui_data, int frame_tree_node_id) override; + std::vector> + CreateURLLoaderThrottles(const network::ResourceRequest &request, + content::BrowserContext *browser_context, + const base::RepeatingCallback &wc_getter, + content::NavigationUIData *navigation_ui_data, int frame_tree_node_id, + absl::optional navigation_id) override; std::vector> CreateThrottlesForNavigation( content::NavigationHandle *navigation_handle) override; @@ -214,9 +214,8 @@ class ContentBrowserClientQt : public content::ContentBrowserClient cert_verifier::mojom::CertVerifierCreationParams *cert_verifier_creation_params) override; std::vector GetNetworkContextsParentDirectory() override; - void RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, - ukm::SourceIdObj ukm_source_id, - NonNetworkURLLoaderFactoryMap *factories) override; + void RegisterNonNetworkNavigationURLLoaderFactories( + int frame_tree_node_id, NonNetworkURLLoaderFactoryMap *factories) override; void RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, const absl::optional& request_initiator_origin, NonNetworkURLLoaderFactoryMap *factories) override; @@ -224,7 +223,7 @@ class ContentBrowserClientQt : public content::ContentBrowserClient NonNetworkURLLoaderFactoryMap* factories) override; void RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(content::BrowserContext* browser_context, NonNetworkURLLoaderFactoryMap* factories) override; - void SiteInstanceGotProcess(content::SiteInstance *site_instance) override; + void SiteInstanceGotProcessAndSite(content::SiteInstance *site_instance) override; base::flat_set GetPluginMimeTypesWithExternalHandlers(content::BrowserContext *browser_context) override; std::unique_ptr GetWebContentsViewDelegate(content::WebContents *web_contents) override; diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp index fb68f7b092f..2b45e91d11d 100644 --- a/src/core/desktop_screen_qt.cpp +++ b/src/core/desktop_screen_qt.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "desktop_screen_qt.h" - +#include "ui/base/ozone_buildflags.h" #include "ui/display/display.h" #include "type_conversion.h" @@ -10,14 +10,11 @@ #include #include -#if defined(USE_OZONE) -#include "ui/ozone/buildflags.h" -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE_X11) #define USE_XSCREENSAVER #include "ui/base/x/x11_screensaver.h" #include "ui/base/x/x11_util.h" #endif -#endif #include diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index c0fd0d3eeed..7ccd063ffda 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -47,16 +47,13 @@ download::DownloadItem *DownloadManagerDelegateQt::findDownloadById(quint32 down return dlm->GetDownload(downloadId); } -void DownloadManagerDelegateQt::cancelDownload(content::DownloadTargetCallback callback) +void DownloadManagerDelegateQt::cancelDownload(download::DownloadTargetCallback callback) { - std::move(callback).Run(base::FilePath(), - download::DownloadItem::TARGET_DISPOSITION_PROMPT, - download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - download::DownloadItem::UNKNOWN, - base::FilePath(), - base::FilePath(), - std::string(), - download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); + download::DownloadTargetInfo target_info; + target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_PROMPT; + target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; + target_info.interrupt_reason = download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED; + std::move(callback).Run(std::move(target_info)); } bool DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) @@ -87,7 +84,7 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId) } bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *item, - content::DownloadTargetCallback *callback) + download::DownloadTargetCallback *callback) { m_currentId = item->GetId(); @@ -95,13 +92,15 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * // 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. if (!item->GetForcedFilePath().empty()) { - std::move(*callback).Run(item->GetForcedFilePath(), download::DownloadItem::TARGET_DISPOSITION_PROMPT, - download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - download::DownloadItem::VALIDATED, - item->GetForcedFilePath(), - item->GetFileNameToReportUser(), - item->GetMimeType(), - download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); + download::DownloadTargetInfo target_info; + target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_PROMPT; + target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; + target_info.insecure_download_status = download::DownloadItem::VALIDATED; + target_info.mime_type = item->GetMimeType(); + target_info.display_name = item->GetFileNameToReportUser(); + target_info.target_path = item->GetForcedFilePath(); + target_info.intermediate_path = item->GetForcedFilePath(); + std::move(*callback).Run(std::move(target_info)); return true; } @@ -211,14 +210,17 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * } base::FilePath filePathForCallback(toFilePathString(suggestedFile.absoluteFilePath())); - std::move(*callback).Run(filePathForCallback, - download::DownloadItem::TARGET_DISPOSITION_OVERWRITE, - download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - download::DownloadItem::VALIDATED, - filePathForCallback.AddExtension(toFilePathString("download")), - base::FilePath(), - item->GetMimeType(), - download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); + download::DownloadTargetInfo target_info; + target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE; + target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; + target_info.insecure_download_status = download::DownloadItem::VALIDATED; + target_info.mime_type = item->GetMimeType(); + target_info.intermediate_path = + filePathForCallback.AddExtension(toFilePathString("download")); + target_info.display_name = base::FilePath(); + target_info.target_path = filePathForCallback; + target_info.interrupt_reason = download::DOWNLOAD_INTERRUPT_REASON_NONE; + std::move(*callback).Run(std::move(target_info)); } else cancelDownload(std::move(*callback)); @@ -306,7 +308,10 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content if (!info.accepted) return; - std::move(callback).Run(toFilePath(info.path), static_cast(info.savePageFormat), + content::SavePackagePathPickedParams params; + params.file_path = toFilePath(info.path); + params.save_type = static_cast(info.savePageFormat); + std::move(callback).Run(std::move(params), base::BindOnce(&DownloadManagerDelegateQt::savePackageDownloadCreated, m_weakPtrFactory.GetWeakPtr())); } diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index cc6d49764f6..e7dfad29dcf 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -35,7 +35,7 @@ class DownloadManagerDelegateQt void GetNextId(content::DownloadIdCallback callback) override; bool DetermineDownloadTarget(download::DownloadItem *item, - content::DownloadTargetCallback *callback) override; + download::DownloadTargetCallback *callback) override; void GetSaveDir(content::BrowserContext* browser_context, base::FilePath* website_save_dir, @@ -56,7 +56,7 @@ class DownloadManagerDelegateQt void OnDownloadDestroyed(download::DownloadItem *download) override; private: - void cancelDownload(content::DownloadTargetCallback callback); + void cancelDownload(download::DownloadTargetCallback callback); download::DownloadItem *findDownloadById(quint32 downloadId); void savePackageDownloadCreated(download::DownloadItem *download); ProfileAdapter *m_profileAdapter; diff --git a/src/core/extensions/extension_host_delegate_qt.cpp b/src/core/extensions/extension_host_delegate_qt.cpp index aa408a544d9..16133a598f8 100644 --- a/src/core/extensions/extension_host_delegate_qt.cpp +++ b/src/core/extensions/extension_host_delegate_qt.cpp @@ -86,10 +86,9 @@ void ExtensionHostDelegateQt::ProcessMediaAccessRequest(content::WebContents *we }); } -bool ExtensionHostDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *render_frame_host, - const GURL &security_origin, - blink::mojom::MediaStreamType type, - const Extension *extension) +bool ExtensionHostDelegateQt::CheckMediaAccessPermission( + content::RenderFrameHost *render_frame_host, const url::Origin &security_origin, + blink::mojom::MediaStreamType type, const Extension *extension) { Q_UNUSED(render_frame_host); Q_UNUSED(security_origin); diff --git a/src/core/extensions/extension_host_delegate_qt.h b/src/core/extensions/extension_host_delegate_qt.h index 1c2688933ea..38b5d4a2fd1 100644 --- a/src/core/extensions/extension_host_delegate_qt.h +++ b/src/core/extensions/extension_host_delegate_qt.h @@ -27,7 +27,7 @@ class ExtensionHostDelegateQt : public ExtensionHostDelegate content::MediaResponseCallback callback, const Extension *extension) override; bool CheckMediaAccessPermission(content::RenderFrameHost *render_frame_host, - const GURL &security_origin, + const url::Origin &security_origin, blink::mojom::MediaStreamType type, const Extension *extension) override; content::PictureInPictureResult EnterPictureInPicture(content::WebContents *web_contents) override; diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp index 19fc6c808b5..36151cee562 100644 --- a/src/core/extensions/extensions_browser_client_qt.cpp +++ b/src/core/extensions/extensions_browser_client_qt.cpp @@ -542,5 +542,10 @@ media_device_salt::MediaDeviceSaltService *ExtensionsBrowserClientQt::GetMediaDe // Not needed for QWE return nullptr; } - +mojo::PendingRemote +ExtensionsBrowserClientQt::GetControlledFrameEmbedderURLLoader( + int frame_tree_node_id, content::BrowserContext *browser_context) +{ + return mojo::PendingRemote(); +} } // namespace extensions diff --git a/src/core/extensions/extensions_browser_client_qt.h b/src/core/extensions/extensions_browser_client_qt.h index bcc8f142b26..34a84631106 100644 --- a/src/core/extensions/extensions_browser_client_qt.h +++ b/src/core/extensions/extensions_browser_client_qt.h @@ -108,6 +108,10 @@ class ExtensionsBrowserClientQt : public ExtensionsBrowserClient media_device_salt::MediaDeviceSaltService *GetMediaDeviceSaltService(content::BrowserContext *context) override; + mojo::PendingRemote + GetControlledFrameEmbedderURLLoader(int frame_tree_node_id, + content::BrowserContext *browser_context) override; + private: // Support for extension APIs. std::unique_ptr api_client_; diff --git a/src/core/extensions/file_system_delegate_qt.cpp b/src/core/extensions/file_system_delegate_qt.cpp index 7c1c5bbd843..6c5b3391913 100644 --- a/src/core/extensions/file_system_delegate_qt.cpp +++ b/src/core/extensions/file_system_delegate_qt.cpp @@ -41,36 +41,21 @@ FileEntryPickerQt::FileEntryPickerQt( FileEntryPickerQt::~FileEntryPickerQt() = default; -void FileEntryPickerQt::FileSelected(const base::FilePath &path, - int index, - void *params) +void FileEntryPickerQt::FileSelected(const ui::SelectedFileInfo &file, int index, void *params) { - MultiFilesSelected({path}, params); + MultiFilesSelected({ file }, params); } -void FileEntryPickerQt::FileSelectedWithExtraInfo(const ui::SelectedFileInfo& file, - int index, - void *params) -{ - FileSelected(file.file_path, index, params); -} - -void FileEntryPickerQt::MultiFilesSelected(const std::vector& files, - void* params) +void FileEntryPickerQt::MultiFilesSelected(const std::vector &files, + void *params) { Q_UNUSED(params); - std::move(m_filesSelectedCallback).Run(files); - delete this; -} - -void FileEntryPickerQt::MultiFilesSelectedWithExtraInfo( - const std::vector &files, - void *params) -{ std::vector paths; - for (const auto& file : files) + for (const auto &file : files) { paths.push_back(file.file_path); - MultiFilesSelected(paths, params); + } + std::move(m_filesSelectedCallback).Run(paths); + delete this; } void FileEntryPickerQt::FileSelectionCanceled(void *params) diff --git a/src/core/extensions/file_system_delegate_qt.h b/src/core/extensions/file_system_delegate_qt.h index 1e9d87c38fa..01b56fa569d 100644 --- a/src/core/extensions/file_system_delegate_qt.h +++ b/src/core/extensions/file_system_delegate_qt.h @@ -19,6 +19,10 @@ namespace content { class BrowserContext; } // namespace content +namespace ui { +struct SelectedFileInfo; +} + namespace extensions { class FileEntryPickerQt : public ui::SelectFileDialog::Listener { @@ -38,17 +42,8 @@ class FileEntryPickerQt : public ui::SelectFileDialog::Listener { ~FileEntryPickerQt() override; // ui::SelectFileDialog::Listener implementation. - void FileSelected(const base::FilePath &path, - int index, - void *params) override; - void FileSelectedWithExtraInfo(const ui::SelectedFileInfo &file, - int index, - void *params) override; - void MultiFilesSelected(const std::vector &files, - void *params) override; - void MultiFilesSelectedWithExtraInfo( - const std::vector &files, - void *params) override; + void FileSelected(const ui::SelectedFileInfo &file, int index, void *params) override; + void MultiFilesSelected(const std::vector &files, void *params) override; void FileSelectionCanceled(void *params) override; FileSystemDelegate::FilesSelectedCallback m_filesSelectedCallback; diff --git a/src/core/favicon_service_factory_qt.cpp b/src/core/favicon_service_factory_qt.cpp index dd2a1979acb..1ed33d559e2 100644 --- a/src/core/favicon_service_factory_qt.cpp +++ b/src/core/favicon_service_factory_qt.cpp @@ -46,7 +46,7 @@ std::unique_ptr HistoryClientQt::CreateBackendCli return nullptr; } -void HistoryClientQt::UpdateBookmarkLastUsedTime(const base::Uuid &, base::Time /*time*/) +void HistoryClientQt::UpdateBookmarkLastUsedTime(int64_t /*bookmark_node_id*/, base::Time /*time*/) { } diff --git a/src/core/favicon_service_factory_qt.h b/src/core/favicon_service_factory_qt.h index 55d5f3b3306..0c3bfd7b56a 100644 --- a/src/core/favicon_service_factory_qt.h +++ b/src/core/favicon_service_factory_qt.h @@ -51,7 +51,7 @@ class HistoryClientQt : public history::HistoryClient history::CanAddURLCallback GetThreadSafeCanAddURLCallback() const override; void NotifyProfileError(sql::InitStatus init_status, const std::string &diagnostics) override; std::unique_ptr CreateBackendClient() override; - void UpdateBookmarkLastUsedTime(const base::Uuid &, base::Time) override; + void UpdateBookmarkLastUsedTime(int64_t bookmark_node_id, base::Time time) override; }; class HistoryServiceFactoryQt : public BrowserContextKeyedServiceFactory diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 9b452135865..9f97892966a 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -9,6 +9,7 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/file_select_listener.h" #include "ui/shell_dialogs/select_file_dialog.h" +#include "ui/shell_dialogs/selected_file_info.h" #include #include @@ -214,7 +215,8 @@ void FilePickerController::filesSelectedInChooser(const QStringList &filesList) if (files.empty()) d_ptr->fileSystemAccessDialogListener->FileSelectionCanceled(nullptr); else - d_ptr->fileSystemAccessDialogListener->MultiFilesSelected(files, nullptr); + d_ptr->fileSystemAccessDialogListener->MultiFilesSelected( + ui::FilePathListToSelectedFileInfoList(files), nullptr); } } diff --git a/src/core/file_system_access/file_system_access_permission_context_qt.h b/src/core/file_system_access/file_system_access_permission_context_qt.h index 06fbfae3f0e..b569c81c020 100644 --- a/src/core/file_system_access/file_system_access_permission_context_qt.h +++ b/src/core/file_system_access/file_system_access_permission_context_qt.h @@ -53,6 +53,8 @@ class FileSystemAccessPermissionContextQt : public content::FileSystemAccessPerm base::FilePath GetWellKnownDirectoryPath(blink::mojom::WellKnownDirectory directory, const url::Origin &origin) override; std::u16string GetPickerTitle(const blink::mojom::FilePickerOptionsPtr &) override; void NotifyEntryMoved(const url::Origin &, const base::FilePath &, const base::FilePath &) override; + void OnFileCreatedFromShowSaveFilePicker(const GURL &file_picker_binding_context, + const storage::FileSystemURL &url) override{}; void NavigatedAwayFromOrigin(const url::Origin &origin); content::BrowserContext *profile() const { return m_profile; } diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 6dc45c4429b..73885b6f203 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -13,11 +13,13 @@ #include "web_engine_settings.h" #include "base/strings/strcat.h" +#include "blink/public/common/page/page_zoom.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/desktop_streams_registry.h" +#include "content/public/browser/host_zoom_map.h" #include "content/public/browser/media_capture_devices.h" #include "content/public/browser/render_process_host.h" #include "media/audio/audio_device_description.h" @@ -107,6 +109,27 @@ media::mojom::CaptureHandlePtr CreateCaptureHandle(content::WebContents *capture return result; } +absl::optional GetZoomLevel(content::WebContents *capturer, + const content::DesktopMediaID &captured_id) +{ + content::RenderFrameHost *const captured_rfh = + content::RenderFrameHost::FromID(captured_id.web_contents_id.render_process_id, + captured_id.web_contents_id.main_render_frame_id); + if (!captured_rfh || !captured_rfh->IsActive()) { + return absl::nullopt; + } + + content::WebContents *const captured_wc = + content::WebContents::FromRenderFrameHost(captured_rfh); + if (!captured_wc) { + return absl::nullopt; + } + + double zoom_level = + blink::PageZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(captured_wc)); + return std::round(100 * zoom_level); +} + // Based on chrome/browser/media/webrtc/desktop_capture_devices_util.cc: media::mojom::DisplayMediaInformationPtr DesktopMediaIDToDisplayMediaInformation(content::WebContents *capturer, const url::Origin &capturer_origin, @@ -122,6 +145,7 @@ media::mojom::DisplayMediaInformationPtr DesktopMediaIDToDisplayMediaInformation #endif // defined(USE_AURA) media::mojom::CaptureHandlePtr capture_handle; + int zoom_level = 100; switch (media_id.type) { case content::DesktopMediaID::TYPE_SCREEN: display_surface = media::mojom::DisplayCaptureSurfaceType::MONITOR; @@ -137,12 +161,16 @@ media::mojom::DisplayMediaInformationPtr DesktopMediaIDToDisplayMediaInformation display_surface = media::mojom::DisplayCaptureSurfaceType::BROWSER; cursor = media::mojom::CursorCaptureType::MOTION; capture_handle = CreateCaptureHandle(capturer, capturer_origin, media_id); + if (base::FeatureList::IsEnabled(features::kCapturedSurfaceControlKillswitch)) { + zoom_level = GetZoomLevel(capturer, media_id).value_or(zoom_level); + } break; case content::DesktopMediaID::TYPE_NONE: break; } - return media::mojom::DisplayMediaInformation::New(display_surface, logical_surface, cursor, std::move(capture_handle)); + return media::mojom::DisplayMediaInformation::New(display_surface, logical_surface, cursor, + std::move(capture_handle), zoom_level); } diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp index a99c68367e9..319d3a56633 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -124,8 +124,6 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL if (extension_id == extension_misc::kPdfExtensionId && response_head->headers) ClearAllButFrameAncestors(response_head); - MimeTypesHandler::ReportUsedHandler(extension_id); - const std::string stream_id = base::Uuid::GenerateRandomV4().AsLowercaseString(); mojo::PendingRemote dummy_new_loader; @@ -134,14 +132,15 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL mojo::PendingReceiver new_client_receiver = new_client.BindNewPipeAndPassReceiver(); - + const std::string internal_id = base::UnguessableToken::Create().ToString(); // Provide the MimeHandlerView code a chance to override the payload. This is // the case where the resource is handled by frame-based MimeHandlerView. - const std::string payload = extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( - m_frame_tree_node_id, response_url, response_head->mime_type, stream_id, - base::BindOnce( - &PluginResponseInterceptorURLLoaderThrottle::ResumeLoad, - weak_factory_.GetWeakPtr())); + const std::string payload = + extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( + m_frame_tree_node_id, response_url, response_head->mime_type, stream_id, + internal_id, + base::BindOnce(&PluginResponseInterceptorURLLoaderThrottle::ResumeLoad, + weak_factory_.GetWeakPtr())); *defer = true; mojo::ScopedDataPipeProducerHandle producer_handle; @@ -186,11 +185,10 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL bool embedded = m_request_destination != network::mojom::RequestDestination::kDocument; content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce( - &extensions::StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent, - extension_id, stream_id, embedded, m_frame_tree_node_id, - std::move(transferrable_loader), response_url)); + FROM_HERE, + base::BindOnce(&extensions::StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent, + extension_id, stream_id, embedded, m_frame_tree_node_id, + std::move(transferrable_loader), response_url, internal_id)); } void PluginResponseInterceptorURLLoaderThrottle::ResumeLoad() diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp index fcce08550a9..d74ec699df8 100644 --- a/src/core/net/proxy_config_service_qt.cpp +++ b/src/core/net/proxy_config_service_qt.cpp @@ -27,7 +27,6 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt return net::ProxyServer::FromSchemeHostAndPort(net::ProxyServer::SCHEME_HTTP, host, port); case QNetworkProxy::NoProxy: case QNetworkProxy::DefaultProxy: - return net::ProxyServer(net::ProxyServer::SCHEME_DIRECT, net::HostPortPair()); default: return net::ProxyServer(net::ProxyServer::SCHEME_INVALID, net::HostPortPair()); } diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp index 3a83ed7ea74..220f44023f6 100644 --- a/src/core/net/proxying_url_loader_factory_qt.cpp +++ b/src/core/net/proxying_url_loader_factory_qt.cpp @@ -65,6 +65,7 @@ ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeCspReport, blink::mojom ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePluginResource, blink::mojom::ResourceType::kPluginResource) ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame, blink::mojom::ResourceType::kNavigationPreloadMainFrame) ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame, blink::mojom::ResourceType::kNavigationPreloadSubFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeJson, blink::mojom::ResourceType::kJson) ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeLast, blink::mojom::ResourceType::kMaxValue) extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); diff --git a/src/core/net/ssl_host_state_delegate_qt.cpp b/src/core/net/ssl_host_state_delegate_qt.cpp index 41967f14efc..809a95c8dc4 100644 --- a/src/core/net/ssl_host_state_delegate_qt.cpp +++ b/src/core/net/ssl_host_state_delegate_qt.cpp @@ -127,9 +127,9 @@ void SSLHostStateDelegateQt::SetHttpsEnforcementForHost(const std::string &host, // Intentional no-op see aw_ssl_host_state_delegate } -bool SSLHostStateDelegateQt::IsHttpsEnforcedForHost(const std::string &host, content::StoragePartition *storage_partition) +bool SSLHostStateDelegateQt::IsHttpsEnforcedForUrl(const GURL &url, + content::StoragePartition *storage_partition) { - // Intentional no-op return false; } diff --git a/src/core/net/ssl_host_state_delegate_qt.h b/src/core/net/ssl_host_state_delegate_qt.h index 0b3d7974c2c..f210f028a18 100644 --- a/src/core/net/ssl_host_state_delegate_qt.h +++ b/src/core/net/ssl_host_state_delegate_qt.h @@ -39,11 +39,13 @@ class SSLHostStateDelegateQt : public content::SSLHostStateDelegate bool DidHostRunInsecureContent(const std::string &host, int child_id, InsecureContentType content_type) override; void AllowHttpForHost(const std::string &host, content::StoragePartition *web_contents) override; bool IsHttpAllowedForHost(const std::string &host, content::StoragePartition *web_contents) override; - void SetHttpsEnforcementForHost(const std::string &host, bool enforce, content::StoragePartition *storage_partition) override; - bool IsHttpsEnforcedForHost(const std::string &host, content::StoragePartition *web_contents) override; + void SetHttpsEnforcementForHost(const std::string &host, bool enforce, + content::StoragePartition *storage_partition) override; void RevokeUserAllowExceptions(const std::string &host) override; bool HasAllowException(const std::string &host, content::StoragePartition *web_contents) override; bool HasAllowExceptionForAnyHost(content::StoragePartition *storage_partition) override; + bool IsHttpsEnforcedForUrl(const GURL &url, + content::StoragePartition *storage_partition) override; private: std::map m_certPolicyforHost; diff --git a/src/core/net/system_network_context_manager.cpp b/src/core/net/system_network_context_manager.cpp index 439d1066c29..78098529da5 100644 --- a/src/core/net/system_network_context_manager.cpp +++ b/src/core/net/system_network_context_manager.cpp @@ -236,10 +236,7 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(network::mojom::Networ log_list_mojo.push_back(std::move(log_info)); } - network_service->UpdateCtLogList( - std::move(log_list_mojo), - certificate_transparency::GetLogListTimestamp(), - base::DoNothing()); + network_service->UpdateCtLogList(std::move(log_list_mojo), base::DoNothing()); // The system NetworkContext is created first network_service_network_context_.reset(); diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp index d38576b8261..2acd05cae7a 100644 --- a/src/core/net/webui_controller_factory_qt.cpp +++ b/src/core/net/webui_controller_factory_qt.cpp @@ -14,7 +14,7 @@ #include "build/build_config.h" #include "chrome/browser/accessibility/accessibility_ui.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/device_log_ui.h" +#include "chrome/browser/ui/webui/device_log/device_log_ui.h" #include "chrome/browser/ui/webui/devtools/devtools_ui.h" #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h" #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h" diff --git a/src/core/ozone/gl_share_context_qt.cpp b/src/core/ozone/gl_share_context_qt.cpp index b1c5e201f10..f2078b59785 100644 --- a/src/core/ozone/gl_share_context_qt.cpp +++ b/src/core/ozone/gl_share_context_qt.cpp @@ -43,6 +43,11 @@ QtShareGLContext::QtShareGLContext(QOpenGLContext *context) #endif // QT_CONFIG(opengl) } +QtShareGLContext::~QtShareGLContext() +{ + OnContextWillDestroy(); +} + unsigned int QtShareGLContext::CheckStickyGraphicsResetStatusImpl() { #if QT_CONFIG(opengl) diff --git a/src/core/ozone/gl_share_context_qt.h b/src/core/ozone/gl_share_context_qt.h index 1144d738464..6b0546a72ea 100644 --- a/src/core/ozone/gl_share_context_qt.h +++ b/src/core/ozone/gl_share_context_qt.h @@ -18,6 +18,7 @@ class QtShareGLContext : public gl::GLContext public: QtShareGLContext(QOpenGLContext *qtContext); + ~QtShareGLContext() override; void *GetHandle() override { return m_handle; } unsigned int CheckStickyGraphicsResetStatusImpl() override; // We don't care about the rest, this context shouldn't be used except for its handle. diff --git a/src/core/ozone/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp index 0cbe75cbd3e..cebeb8b67f2 100644 --- a/src/core/ozone/gl_surface_qt.cpp +++ b/src/core/ozone/gl_surface_qt.cpp @@ -128,15 +128,14 @@ bool usingSoftwareDynamicGL() #endif // QT_CONFIG(opengl) } -scoped_refptr -CreateOffscreenGLSurfaceWithFormat(GLDisplay *display, const gfx::Size& size, GLSurfaceFormat format) +scoped_refptr CreateOffscreenGLSurface(GLDisplay *display, const gfx::Size &size) { scoped_refptr surface; switch (GetGLImplementation()) { case kGLImplementationDesktopGLCoreProfile: case kGLImplementationDesktopGL: { surface = new GLSurfaceWGLQt(size); - if (surface->Initialize(format)) + if (surface->Initialize(GLSurfaceFormat())) return surface; break; } @@ -144,8 +143,8 @@ CreateOffscreenGLSurfaceWithFormat(GLDisplay *display, const gfx::Size& size, GL case kGLImplementationEGLGLES2: { GLDisplayEGL *display_egl = display->GetAs(); if (display_egl->IsEGLSurfacelessContextSupported() && size.width() == 0 && size.height() == 0) - return InitializeGLSurfaceWithFormat(new SurfacelessEGL(display_egl, size), format); - return InitializeGLSurfaceWithFormat(new PbufferGLSurfaceEGL(display_egl, size), format); + return InitializeGLSurface(new SurfacelessEGL(display_egl, size)); + return InitializeGLSurface(new PbufferGLSurfaceEGL(display_egl, size)); } default: break; diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp index 623cf43cfb8..6384ea2dbda 100644 --- a/src/core/ozone/ozone_platform_qt.cpp +++ b/src/core/ozone/ozone_platform_qt.cpp @@ -38,7 +38,7 @@ #include #endif // BUILDFLAG(USE_XKBCOMMON) -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) #include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" #include "ui/ozone/platform/x11/gl_egl_utility_x11.h" @@ -113,9 +113,6 @@ const ui::OzonePlatform::PlatformProperties &OzonePlatformQt::GetPlatformPropert if (!initialized) { DCHECK(m_supportsNativePixmaps); properties->fetch_buffer_formats_for_gmb_on_gpu = m_supportsNativePixmaps.value(); -#if BUILDFLAG(USE_VAAPI) - properties->supports_vaapi = m_supportsNativePixmaps.value(); -#endif initialized = true; } @@ -238,7 +235,7 @@ void OzonePlatformQt::InitializeGPU(const ui::OzonePlatform::InitParams ¶ms) { surface_factory_ozone_.reset(new QtWebEngineCore::SurfaceFactoryQt()); -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) if (params.enable_native_gpu_memory_buffers) { base::ThreadPool::PostTask(FROM_HERE, base::BindOnce([]() @@ -263,7 +260,7 @@ bool OzonePlatformQt::IsNativePixmapConfigSupported(gfx::BufferFormat format, gf PlatformGLEGLUtility *OzonePlatformQt::GetPlatformGLEGLUtility() { if (!gl_egl_utility_) { -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) if (GetQtXDisplay()) gl_egl_utility_ = std::make_unique(); else diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index 2d311a02a26..1bfa49c6006 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -9,16 +9,16 @@ #include "ozone/gl_ozone_egl_qt.h" #include "media/gpu/buildflags.h" +#include "ui/base/ozone_buildflags.h" #include "ui/gfx/linux/drm_util_linux.h" #include "ui/gfx/linux/gbm_buffer.h" #include "ui/gfx/linux/native_pixmap_dmabuf.h" #include "ui/gl/egl_util.h" -#include "ui/ozone/buildflags.h" #include #include -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) #include "ozone/gl_ozone_glx_qt.h" #include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" @@ -32,7 +32,7 @@ namespace QtWebEngineCore { SurfaceFactoryQt::SurfaceFactoryQt() { -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) { m_impl = { gl::GLImplementationParts(gl::kGLImplementationDesktopGL), gl::GLImplementationParts(gl::kGLImplementationDisabled) }; @@ -73,7 +73,7 @@ SurfaceFactoryQt::CreateVulkanImplementation(bool /*allow_protected_memory*/, bool SurfaceFactoryQt::CanCreateNativePixmapForFormat(gfx::BufferFormat format) { -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) return ui::GpuMemoryBufferSupportX11::GetInstance()->CanCreateNativePixmapForFormat(format); #endif @@ -101,7 +101,7 @@ scoped_refptr SurfaceFactoryQt::CreateNativePixmap( gfx::NativePixmapHandle handle; -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) { auto gbmBuffer = ui::GpuMemoryBufferSupportX11::GetInstance()->CreateBuffer(format, size, usage); @@ -165,7 +165,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( #if QT_CONFIG(opengl) gfx::NativePixmapHandle bufferHandle; -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) { auto gbmBuffer = ui::GpuMemoryBufferSupportX11::GetInstance()->CreateBufferFromHandle( size, format, std::move(handle)); @@ -250,10 +250,10 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( bool SurfaceFactoryQt::SupportsNativePixmaps() { #if QT_CONFIG(opengl) -#if BUILDFLAG(OZONE_PLATFORM_X11) +#if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) return ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device(); -#endif // BUILDFLAG(OZONE_PLATFORM_X11) +#endif // BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getEglPlatformInterface()) return EGLHelper::instance()->isDmaBufSupported(); diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 63189c1d7a0..2c1c0d3d670 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -494,12 +494,11 @@ void PermissionManagerQt::ResetPermission( updater.Get().Remove(requesting_origin.spec()); } -content::PermissionControllerDelegate::SubscriptionId PermissionManagerQt::SubscribePermissionStatusChange( - blink::PermissionType permission, - content::RenderProcessHost * /*render_process_host*/, - content::RenderFrameHost * /* render_frame_host */, - const GURL& requesting_origin, - base::RepeatingCallback callback) +content::PermissionControllerDelegate::SubscriptionId +PermissionManagerQt::SubscribeToPermissionStatusChange( + blink::PermissionType permission, content::RenderProcessHost * /*render_process_host*/, + content::RenderFrameHost * /* render_frame_host */, const GURL &requesting_origin, + base::RepeatingCallback callback) { auto subscriber_id = subscription_id_generator_.GenerateNextId(); m_subscribers.insert( { subscriber_id, @@ -507,7 +506,8 @@ content::PermissionControllerDelegate::SubscriptionId PermissionManagerQt::Subsc return subscriber_id; } -void PermissionManagerQt::UnsubscribePermissionStatusChange(content::PermissionControllerDelegate::SubscriptionId subscription_id) +void PermissionManagerQt::UnsubscribeFromPermissionStatusChange( + content::PermissionControllerDelegate::SubscriptionId subscription_id) { if (!m_subscribers.erase(subscription_id)) LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id; diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index ebab613d616..6a4df2efa80 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -57,14 +57,13 @@ class PermissionManagerQt : public content::PermissionControllerDelegate const content::PermissionRequestDescription &request_description, base::OnceCallback &)> callback) override; - content::PermissionControllerDelegate::SubscriptionId SubscribePermissionStatusChange( - blink::PermissionType permission, - content::RenderProcessHost* render_process_host, - content::RenderFrameHost* render_frame_host, - const GURL& requesting_origin, - const base::RepeatingCallback callback) override; + content::PermissionControllerDelegate::SubscriptionId SubscribeToPermissionStatusChange( + blink::PermissionType permission, content::RenderProcessHost *render_process_host, + content::RenderFrameHost *render_frame_host, const GURL &requesting_origin, + const base::RepeatingCallback callback) override; - void UnsubscribePermissionStatusChange(content::PermissionControllerDelegate::SubscriptionId subscription_id) override; + void UnsubscribeFromPermissionStatusChange( + content::PermissionControllerDelegate::SubscriptionId subscription_id) override; private: struct Request { diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 7d6f5cda0ba..1f006295322 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -333,9 +333,9 @@ void ProfileAdapter::setHttpUserAgent(const QString &userAgent) } m_profile->ForEachLoadedStoragePartition( - base::BindRepeating([](const std::string &user_agent, content::StoragePartition *storage_partition) { - storage_partition->GetNetworkContext()->SetUserAgent(user_agent); - }, stdUserAgent)); + [stdUserAgent](content::StoragePartition *storage_partition) { + storage_partition->GetNetworkContext()->SetUserAgent(stdUserAgent); + }); } ProfileAdapter::HttpCacheType ProfileAdapter::httpCacheType() const @@ -490,10 +490,9 @@ const QList ProfileAdapter::customUrlSchemes() const void ProfileAdapter::updateCustomUrlSchemeHandlers() { - m_profile->ForEachLoadedStoragePartition( - base::BindRepeating([](content::StoragePartition *storage_partition) { - storage_partition->ResetURLLoaderFactories(); - })); + m_profile->ForEachLoadedStoragePartition([](content::StoragePartition *storage_partition) { + storage_partition->ResetURLLoaderFactories(); + }); } void ProfileAdapter::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) @@ -624,9 +623,9 @@ void ProfileAdapter::setHttpAcceptLanguage(const QString &httpAcceptLanguage) } m_profile->ForEachLoadedStoragePartition( - base::BindRepeating([](std::string accept_language, content::StoragePartition *storage_partition) { - storage_partition->GetNetworkContext()->SetAcceptLanguage(accept_language); - }, http_accept_language)); + [http_accept_language](content::StoragePartition *storage_partition) { + storage_partition->GetNetworkContext()->SetAcceptLanguage(http_accept_language); + }); } QVariant ProfileAdapter::clientHint(ClientHint clientHint) const diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp index 859aff8d4fa..31a85a534c1 100644 --- a/src/core/profile_io_data_qt.cpp +++ b/src/core/profile_io_data_qt.cpp @@ -37,8 +37,6 @@ ProfileIODataQt::~ProfileIODataQt() { if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::IO)) DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - m_resourceContext.reset(); } QPointer ProfileIODataQt::profileAdapter() @@ -69,11 +67,6 @@ void ProfileIODataQt::shutdownOnUIThread() } } -content::ResourceContext *ProfileIODataQt::resourceContext() -{ - return m_resourceContext.get(); -} - #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ExtensionSystemQt* ProfileIODataQt::GetExtensionSystem() { @@ -91,7 +84,6 @@ void ProfileIODataQt::initializeOnUIThread() { m_profileAdapter = m_profile->profileAdapter(); DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - m_resourceContext.reset(new content::ResourceContext()); m_cookieDelegate = new CookieMonsterDelegateQt(); m_cookieDelegate->setClient(m_profile->profileAdapter()->cookieStore()); m_proxyConfigMonitor.reset(new ProxyConfigMonitor(m_profile->GetPrefs())); @@ -152,15 +144,12 @@ void ProfileIODataQt::resetNetworkContext() Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); Q_ASSERT(m_clearHttpCacheState != Removing); setFullConfiguration(); - m_profile->ForEachLoadedStoragePartition( - base::BindRepeating([](ProfileIODataQt *profileData, - content::StoragePartition *storage) { - storage->SetNetworkContextCreatedObserver(profileData); - - auto storage_impl = static_cast(storage); - storage_impl->ResetURLLoaderFactories(); - storage_impl->ResetNetworkContext(); - }, this)); + m_profile->ForEachLoadedStoragePartition([this](content::StoragePartition *storage) { + storage->SetNetworkContextCreatedObserver(this); + auto storage_impl = static_cast(storage); + storage_impl->ResetURLLoaderFactories(); + storage_impl->ResetNetworkContext(); + }); } void ProfileIODataQt::OnNetworkContextCreated(content::StoragePartition *storage) @@ -174,12 +163,10 @@ void ProfileIODataQt::OnNetworkContextCreated(content::StoragePartition *storage bool pendingReset = false; m_profile->ForEachLoadedStoragePartition( - base::BindRepeating([](bool *pendingReset, - ProfileIODataQt *profileData, - content::StoragePartition *storage) { - if (storage->GetNetworkContextCreatedObserver() == profileData) - *pendingReset = true; - }, &pendingReset, this)); + [&pendingReset, this](content::StoragePartition *storage) { + if (storage->GetNetworkContextCreatedObserver() == this) + pendingReset = true; + }); if (pendingReset) return; diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h index 0d032e4dcfc..a871307d70f 100644 --- a/src/core/profile_io_data_qt.h +++ b/src/core/profile_io_data_qt.h @@ -20,10 +20,6 @@ namespace mojom { class CertVerifierCreationParams; }} -namespace content { -class ResourceContext; -} - namespace extensions { class ExtensionSystemQt; } @@ -66,7 +62,6 @@ class ProfileIODataQt : public content::StoragePartition::NetworkContextCreatedO virtual ~ProfileIODataQt(); QPointer profileAdapter(); - content::ResourceContext *resourceContext(); #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ExtensionSystemQt* GetExtensionSystem(); #endif // BUILDFLAG(ENABLE_EXTENSIONS) @@ -104,7 +99,6 @@ class ProfileIODataQt : public content::StoragePartition::NetworkContextCreatedO void removeBrowsingDataRemoverObserver(); ProfileQt *m_profile; - std::unique_ptr m_resourceContext; scoped_refptr m_cookieDelegate; QPointer m_profileAdapter; // never dereferenced in IO thread and it is passed by qpointer ProfileAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy; diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index d8a6c191cb2..c54e8485b49 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -116,11 +116,6 @@ bool ProfileQt::IsOffTheRecord() return m_profileAdapter->isOffTheRecord(); } -content::ResourceContext *ProfileQt::GetResourceContext() -{ - return m_profileIOData->resourceContext(); -} - content::DownloadManagerDelegate *ProfileQt::GetDownloadManagerDelegate() { return m_profileAdapter->downloadManagerDelegate(); diff --git a/src/core/profile_qt.h b/src/core/profile_qt.h index 4865632559e..a267efbc91b 100644 --- a/src/core/profile_qt.h +++ b/src/core/profile_qt.h @@ -40,7 +40,6 @@ class ProfileQt : public Profile base::FilePath GetPath() override; bool IsOffTheRecord() override; - content::ResourceContext *GetResourceContext() override; content::DownloadManagerDelegate *GetDownloadManagerDelegate() override; content::BrowserPluginGuestManager *GetGuestManager() override; storage::SpecialStoragePolicy *GetSpecialStoragePolicy() override; diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 81817442ae1..98d0471c1d2 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -21,7 +21,6 @@ #include "content/browser/renderer_host/frame_tree.h" #include "content/browser/renderer_host/frame_tree_node.h" #include "content/browser/renderer_host/cursor_manager.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -29,6 +28,7 @@ #include "content/browser/renderer_host/ui_events_helper.h" #include "content/common/content_switches_internal.h" #include "content/common/cursors/webcursor.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/public/browser/web_contents.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/cursor/cursor.h" @@ -160,6 +160,8 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget &m_delegatedFrameHostClient, true /* should_register_frame_sink_id */)); + m_delegatedFrameHost->SetIsFrameSinkIdOwner(true); + content::ImageTransportFactory *imageTransportFactory = content::ImageTransportFactory::GetInstance(); ui::ContextFactory *contextFactory = imageTransportFactory->GetContextFactory(); m_uiCompositor.reset(new FlingingCompositor( @@ -916,8 +918,7 @@ void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &even } void RenderWidgetHostViewQt::GestureEventAck(const blink::WebGestureEvent &event, - blink::mojom::InputEventResultState ack_result, - blink::mojom::ScrollResultDataPtr scroll_result_data) + blink::mojom::InputEventResultState ack_result) { // Forward unhandled scroll events back as wheel events if (event.GetType() != blink::WebInputEvent::Type::kGestureScrollUpdate) diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 43cff430bc8..49c1125fc26 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -95,8 +95,7 @@ class RenderWidgetHostViewQt void WheelEventAck(const blink::WebMouseWheelEvent &event, blink::mojom::InputEventResultState ack_result) override; void GestureEventAck(const blink::WebGestureEvent &event, - blink::mojom::InputEventResultState ack_result, - blink::mojom::ScrollResultDataPtr scroll_result_data) override; + blink::mojom::InputEventResultState ack_result) override; content::MouseWheelPhaseHandler *GetMouseWheelPhaseHandler() override; viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata) override; void OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata); diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index b82c0fb0355..0622fc27e13 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -11,7 +11,6 @@ #include "web_engine_library_info.h" #include "base/task/sequenced_task_runner.h" -#include "components/autofill/content/renderer/autofill_agent.h" #include "components/autofill/content/renderer/password_autofill_agent.h" #include "components/autofill/content/renderer/password_generation_agent.h" #include "components/cdm/renderer/external_clear_key_key_system_info.h" @@ -37,6 +36,7 @@ #include "third_party/blink/public/platform/web_url_error.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" +#include "ui/base/webui/web_ui_util.h" #if QT_CONFIG(webengine_spellchecker) #include "components/spellcheck/renderer/spellcheck.h" @@ -178,7 +178,7 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_fr new QtWebEngineCore::ContentSettingsObserverQt(render_frame); #if QT_CONFIG(webengine_spellchecker) - new SpellCheckProvider(render_frame, m_spellCheck.data(), this); + new SpellCheckProvider(render_frame, m_spellCheck.data()); #endif #if QT_CONFIG(webengine_printing_and_pdf) new printing::PrintRenderFrameHelper(render_frame, base::WrapUnique(new PrintWebViewHelperDelegateQt())); @@ -188,9 +188,8 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_fr #if BUILDFLAG(ENABLE_EXTENSIONS) associated_interfaces->AddInterface( - base::BindRepeating( - &extensions::MimeHandlerViewContainerManager::BindReceiver, - render_frame->GetRoutingID())); + base::BindRepeating(&extensions::MimeHandlerViewContainerManager::BindReceiver, + base::Unretained(render_frame))); auto registry = std::make_unique(); ExtensionsRendererClientQt::GetInstance()->RenderFrameCreated(render_frame, render_frame_observer->registry()); @@ -201,8 +200,12 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_fr auto password_generation_agent = std::make_unique(render_frame, password_autofill_agent.get(), associated_interfaces); - new autofill::AutofillAgent(render_frame, std::move(password_autofill_agent), std::move(password_generation_agent), - associated_interfaces); + new autofill::AutofillAgent( + render_frame, + { autofill::AutofillAgent::UsesKeyboardAccessoryForSuggestions(false), + autofill::AutofillAgent::ExtractAllDatalists(false) }, + std::move(password_autofill_agent), std::move(password_generation_agent), + associated_interfaces); } void ContentRendererClientQt::WebViewCreated(blink::WebView *web_view, @@ -302,13 +305,13 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF if (template_html.empty()) NOTREACHED() << "unable to load template. ID: " << resourceId; else // "t" is the id of the templates root node. - *errorHtml = webui::GetTemplatesHtml(template_html, errorPageState.strings, "t"); + *errorHtml = webui::GetLocalizedHtml(template_html, errorPageState.strings); } } -uint64_t ContentRendererClientQt::VisitedLinkHash(const char *canonicalUrl, size_t length) +uint64_t ContentRendererClientQt::VisitedLinkHash(std::string_view canonicalUrl) { - return m_visitedLinkReader->ComputeURLFingerprint(canonicalUrl, length); + return m_visitedLinkReader->ComputeURLFingerprint(canonicalUrl); } bool ContentRendererClientQt::IsLinkVisited(uint64_t linkHash) @@ -354,8 +357,8 @@ void AppendParams(const std::vector &addition values[existing_size + i] = blink::WebString::FromUTF16(additional_params[i].value); } - existing_names->Swap(names); - existing_values->Swap(values); + existing_names->swap(names); + existing_values->swap(values); } #endif // BUILDFLAG(ENABLE_PLUGINS) diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h index b2231f00acd..8151c9710fe 100644 --- a/src/core/renderer/content_renderer_client_qt.h +++ b/src/core/renderer/content_renderer_client_qt.h @@ -66,7 +66,7 @@ class ContentRendererClientQt int http_status, content::mojom::AlternativeErrorPageOverrideInfoPtr alternative_error_page_info, std::string *error_html) override; - uint64_t VisitedLinkHash(const char *canonical_url, size_t length) override; + uint64_t VisitedLinkHash(std::string_view canonical_url) override; bool IsLinkVisited(uint64_t linkHash) override; std::unique_ptr CreatePrescientNetworking(content::RenderFrame *render_frame) override; void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override; diff --git a/src/core/renderer/content_settings_observer_qt.cpp b/src/core/renderer/content_settings_observer_qt.cpp index 3e3c159f516..c78f53d8a84 100644 --- a/src/core/renderer/content_settings_observer_qt.cpp +++ b/src/core/renderer/content_settings_observer_qt.cpp @@ -39,6 +39,7 @@ ContentSettingsObserverQt::ContentSettingsObserverQt(content::RenderFrame *rende ContentSettingsObserverQt::~ContentSettingsObserverQt() {} +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message &message) { bool handled = true; @@ -49,6 +50,7 @@ bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message &message) return handled; } +#endif void ContentSettingsObserverQt::DidCommitProvisionalLoad(ui::PageTransition /*transition*/) { @@ -83,11 +85,12 @@ void ContentSettingsObserverQt::AllowStorageAccess(StorageType storage_type, // Verify there are no duplicate insertions. DCHECK(inserted); - +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) Send(new QtWebEngineHostMsg_RequestStorageAccessAsync(routing_id(), m_currentRequestId, url::Origin(frame->GetSecurityOrigin()).GetURL(), url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), int(storage_type))); +#endif } bool ContentSettingsObserverQt::AllowStorageAccessSync(StorageType storage_type) @@ -105,9 +108,11 @@ bool ContentSettingsObserverQt::AllowStorageAccessSync(StorageType storage_type) } bool result = false; +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) Send(new QtWebEngineHostMsg_AllowStorageAccess(routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), int(storage_type), &result)); +#endif if (sameOrigin) m_cachedStoragePermissions[key] = result; return result; diff --git a/src/core/renderer/content_settings_observer_qt.h b/src/core/renderer/content_settings_observer_qt.h index 415d0b6b739..f843c61ee38 100644 --- a/src/core/renderer/content_settings_observer_qt.h +++ b/src/core/renderer/content_settings_observer_qt.h @@ -9,6 +9,7 @@ #define CONTENT_SETTINGS_OBSERVER_QT_H #include "base/containers/flat_map.h" +#include "content/common/buildflags.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" #include "third_party/blink/public/platform/web_content_settings_client.h" @@ -33,7 +34,9 @@ class ContentSettingsObserverQt private: // RenderFrameObserver implementation: +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) bool OnMessageReceived(const IPC::Message &message) override; +#endif void DidCommitProvisionalLoad(ui::PageTransition transition) override; void OnDestruct() override; diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp index f201e645795..9db6bbe3627 100644 --- a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp +++ b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp @@ -31,6 +31,7 @@ #include "extensions/renderer/extensions_render_frame_observer.h" #include "extensions/renderer/renderer_extension_registry.h" #include "extensions/renderer/script_context.h" +#include "extensions/renderer/extensions_renderer_api_provider.h" #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/web/web_plugin_params.h" @@ -108,7 +109,9 @@ void ExtensionsRendererClientQt::RenderThreadStarted() { content::RenderThread *thread = content::RenderThread::Get(); if (!extension_dispatcher_) - extension_dispatcher_.reset(new extensions::Dispatcher(std::make_unique())); + extension_dispatcher_.reset(new extensions::Dispatcher( + std::make_unique(), + std::vector>())); extension_dispatcher_->OnRenderThreadStarted(thread); permissions_policy_delegate_.reset(new RendererPermissionsPolicyDelegateQt(extension_dispatcher_.get())); resource_request_policy_.reset(new extensions::ResourceRequestPolicyQt(extension_dispatcher_.get())); diff --git a/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp index 06fd4f71f96..4d25be12a27 100644 --- a/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp +++ b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp @@ -22,11 +22,11 @@ namespace QtWebEngineCore { // static gin::WrapperInfo LoadablePluginPlaceholderQt::kWrapperInfo = {gin::kEmbedderNativeGin}; -LoadablePluginPlaceholderQt::LoadablePluginPlaceholderQt(content::RenderFrame* render_frame, - const blink::WebPluginParams& params, - const std::string& html_data, - const std::u16string& title) - : plugins::LoadablePluginPlaceholder(render_frame, params, html_data) +LoadablePluginPlaceholderQt::LoadablePluginPlaceholderQt(content::RenderFrame *render_frame, + const blink::WebPluginParams ¶ms, + const std::string &html_data, + const std::u16string &title) + : plugins::LoadablePluginPlaceholder(render_frame, params) {} LoadablePluginPlaceholderQt::~LoadablePluginPlaceholderQt() diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index e6489eefbb2..03fb0d9e881 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -51,7 +51,7 @@ bool RenderFrameObserverQt::OnAssociatedInterfaceRequestForFrame(const std::stri return m_associated_interfaces.TryBindInterface(interface_name, handle); } -void RenderFrameObserverQt::WillDetach() +void RenderFrameObserverQt::WillDetach(blink::DetachReason reason) { m_isFrameDetached = true; } diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h index 8cab3bd9a6c..c3a1dd8ba1f 100644 --- a/src/core/renderer/render_frame_observer_qt.h +++ b/src/core/renderer/render_frame_observer_qt.h @@ -34,7 +34,7 @@ class RenderFrameObserverQt const std::string &interface_name, mojo::ScopedInterfaceEndpointHandle *handle) override; void OnDestruct() override; - void WillDetach() override; + void WillDetach(blink::DetachReason detach_reason) override; bool isFrameDetached() const; diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index eff304981c5..82579ea7d79 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -110,7 +110,7 @@ class UserResourceController::RenderFrameObserverHelper void DidCommitProvisionalLoad(ui::PageTransition transition) override; void DidDispatchDOMContentLoadedEvent() override; void DidFinishLoad() override; - void WillDetach() override; + void WillDetach(blink::DetachReason detach_reason) override; void OnDestruct() override; void AddScript(const QtWebEngineCore::UserScriptData &data) override; void RemoveScript(const QtWebEngineCore::UserScriptData &data) override; @@ -231,7 +231,8 @@ void UserResourceController::RenderFrameObserverHelper::DidFinishLoad() QtWebEngineCore::UserScriptData::AfterLoad)); } -void UserResourceController::RenderFrameObserverHelper::WillDetach() +void UserResourceController::RenderFrameObserverHelper::WillDetach( + blink::DetachReason detach_reason) { m_runner.reset(); } diff --git a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt index 5e8a1de143e..fcc11bdcb8c 100644 --- a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt +++ b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt @@ -11,6 +11,9 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING) INCLUDE_DIRECTORIES ../../../3rdparty/chromium/third_party/abseil-cpp ) + if(MSVC AND NOT CLANG) + target_compile_options(${dict_target_name} PRIVATE "/Zc:preprocessor") + endif() if(COMMAND qt_internal_return_unless_building_tools) qt_internal_return_unless_building_tools() endif() diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 70ee07cbb18..c2cd6981ab3 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -794,7 +794,9 @@ void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool pr m_viewClient->windowCloseRejected(); } -bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *, const GURL& security_origin, blink::mojom::MediaStreamType type) +bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *, + const url::Origin &security_origin, + blink::mojom::MediaStreamType type) { switch (type) { case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE: diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index df9b5e3e802..899d46cd0c6 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -106,7 +106,9 @@ class WebContentsDelegateQt : public content::WebContentsDelegate void UpdateTargetURL(content::WebContents* source, const GURL& url) override; void RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) override; void BeforeUnloadFired(content::WebContents* tab, bool proceed, bool* proceed_to_fire_unload) override; - bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host, const GURL& security_origin, blink::mojom::MediaStreamType type) override; + bool CheckMediaAccessPermission(content::RenderFrameHost *render_frame_host, + const url::Origin &security_origin, + blink::mojom::MediaStreamType type) override; void RegisterProtocolHandler(content::RenderFrameHost* frame_host, const std::string& protocol, const GURL& url, bool user_gesture) override; void UnregisterProtocolHandler(content::RenderFrameHost* frame_host, const std::string& protocol, const GURL& url, bool user_gesture) override; bool TakeFocus(content::WebContents *source, bool reverse) override; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index e860e96b44d..50821fa984e 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -837,7 +837,7 @@ static void initializeFeatureList(base::CommandLine *commandLine, std::vectorAppendSwitchASCII(switches::kEnableFeatures, enableFeaturesString); commandLine->AppendSwitchASCII(switches::kDisableFeatures, disableFeaturesString); - base::FeatureList::InitializeInstance(enableFeaturesString, disableFeaturesString); + base::FeatureList::InitInstance(enableFeaturesString, disableFeaturesString); } WebEngineContext::WebEngineContext() diff --git a/tests/auto/quick/qmltests/data/tst_datalist.qml b/tests/auto/quick/qmltests/data/tst_datalist.qml index f739639b2b3..1e5a7ad6b86 100644 --- a/tests/auto/quick/qmltests/data/tst_datalist.qml +++ b/tests/auto/quick/qmltests/data/tst_datalist.qml @@ -105,10 +105,13 @@ TestWebEngineView { keyClick(Qt.Key_Escape); tryVerify(function() { return listView() == null; }); - // Key Down should open the popup and select the first suggestion. + // The first Key Down opens the popup. keyClick(Qt.Key_Down); tryVerify(function() { return listView() != null; }); - compare(listView().currentIndex, 0); + + // The second Key Down selects the first suggestion. + keyClick(Qt.Key_Down); + tryCompare(listView(), "currentIndex", 0); verify(listView().currentItem); } @@ -120,10 +123,13 @@ TestWebEngineView { // Make sure there is no open popup yet. verify(!listView()); - // Key Down should open the popup and select the first suggestion. + // The first Key Down opens the popup. keyClick(Qt.Key_Down); tryVerify(function() { return listView() != null; }); - compare(listView().currentIndex, 0); + + // The second Key Down selects the first suggestion. + keyClick(Qt.Key_Down); + tryCompare(listView(), "currentIndex", 0); // Test keyboard navigation in list. keyClick(Qt.Key_Up); diff --git a/tests/auto/widgets/accessibility/tst_accessibility.cpp b/tests/auto/widgets/accessibility/tst_accessibility.cpp index 1579b61e2fe..0a65e7a9566 100644 --- a/tests/auto/widgets/accessibility/tst_accessibility.cpp +++ b/tests/auto/widgets/accessibility/tst_accessibility.cpp @@ -94,13 +94,13 @@ void tst_Accessibility::noPage() void tst_Accessibility::hierarchy() { QWebEngineView webView; + QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); webView.setHtml("" \ "Hello world" \ "" \ ""); webView.show(); - QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); - QVERIFY(spyFinished.wait()); + QTRY_VERIFY(spyFinished.size()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); QVERIFY(view); @@ -581,28 +581,27 @@ void tst_Accessibility::crossTreeParent() webView.show(); QVERIFY(spyFinished.wait()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); - QAccessibleInterface *document = view->child(0); - QCOMPARE(document->role(), QAccessible::WebDocument); - QTRY_COMPARE(document->childCount(), 1); - QAccessibleInterface *p = document->child(0); + QCOMPARE(view->child(0)->role(), QAccessible::WebDocument); + QTRY_COMPARE(view->child(0)->childCount(), 1); + QAccessibleInterface *p = view->child(0)->child(0); QVERIFY(p); - QCOMPARE(p->parent(), document); + QCOMPARE(p->parent(), view->child(0)); p = p->child(0); QVERIFY(p); QCOMPARE(p->role(), QAccessible::WebDocument); - QCOMPARE(p->parent()->parent(), document); + QCOMPARE(p->parent()->parent(), view->child(0)); QTRY_COMPARE(p->childCount(), 1); p = p->child(0); QVERIFY(p); QAccessibleInterface *subdocument = p; QCOMPARE(p->role(), QAccessible::WebDocument); - QCOMPARE(p->parent()->parent()->parent(), document); + QCOMPARE(p->parent()->parent()->parent(), view->child(0)); p = p->child(0); QVERIFY(p); QVERIFY(p->object()); QCOMPARE(p->role(), QAccessible::Paragraph); QCOMPARE(p->parent(), subdocument); - QCOMPARE(p->parent()->parent()->parent()->parent(), document); + QCOMPARE(p->parent()->parent()->parent()->parent(), view->child(0)); QCOMPARE(p->parent()->parent()->parent()->parent()->parent(), view); QCOMPARE(p->object()->objectName(), QStringLiteral("my_id")); } diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index f4ed06e147d..03acd69feb6 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -2947,8 +2947,8 @@ void tst_QWebEngineView::imeJSInputEvents() QTRY_COMPARE(logLines().size(), 4); QCOMPARE(logLines()[0], QStringLiteral("[object CompositionEvent] compositionstart ")); - QCOMPARE(logLines()[1], QStringLiteral("[object InputEvent] beforeinput preedit")); - QCOMPARE(logLines()[2], QStringLiteral("[object CompositionEvent] compositionupdate preedit")); + QCOMPARE(logLines()[1], QStringLiteral("[object CompositionEvent] compositionupdate preedit")); + QCOMPARE(logLines()[2], QStringLiteral("[object InputEvent] beforeinput preedit")); QCOMPARE(logLines()[3], QStringLiteral("[object InputEvent] input preedit")); { @@ -2960,8 +2960,8 @@ void tst_QWebEngineView::imeJSInputEvents() } QTRY_COMPARE(logLines().size(), 9); - QCOMPARE(logLines()[4], QStringLiteral("[object InputEvent] beforeinput commit")); - QCOMPARE(logLines()[5], QStringLiteral("[object CompositionEvent] compositionupdate commit")); + QCOMPARE(logLines()[4], QStringLiteral("[object CompositionEvent] compositionupdate commit")); + QCOMPARE(logLines()[5], QStringLiteral("[object InputEvent] beforeinput commit")); QCOMPARE(logLines()[6], QStringLiteral("[object TextEvent] textInput commit")); QCOMPARE(logLines()[7], QStringLiteral("[object InputEvent] input commit")); QCOMPARE(logLines()[8], QStringLiteral("[object CompositionEvent] compositionend commit")); @@ -2979,8 +2979,8 @@ void tst_QWebEngineView::imeJSInputEvents() QTRY_COMPARE(logLines().size(), 4); QCOMPARE(logLines()[0], QStringLiteral("[object CompositionEvent] compositionstart ")); - QCOMPARE(logLines()[1], QStringLiteral("[object InputEvent] beforeinput preedit")); - QCOMPARE(logLines()[2], QStringLiteral("[object CompositionEvent] compositionupdate preedit")); + QCOMPARE(logLines()[1], QStringLiteral("[object CompositionEvent] compositionupdate preedit")); + QCOMPARE(logLines()[2], QStringLiteral("[object InputEvent] beforeinput preedit")); QCOMPARE(logLines()[3], QStringLiteral("[object InputEvent] input preedit")); { @@ -2991,8 +2991,8 @@ void tst_QWebEngineView::imeJSInputEvents() } QTRY_COMPARE(logLines().size(), 9); - QCOMPARE(logLines()[4], QStringLiteral("[object InputEvent] beforeinput ")); - QCOMPARE(logLines()[5], QStringLiteral("[object CompositionEvent] compositionupdate ")); + QCOMPARE(logLines()[4], QStringLiteral("[object CompositionEvent] compositionupdate ")); + QCOMPARE(logLines()[5], QStringLiteral("[object InputEvent] beforeinput ")); QCOMPARE(logLines()[6], QStringLiteral("[object TextEvent] textInput ")); QCOMPARE(logLines()[7], QStringLiteral("[object InputEvent] input null")); QCOMPARE(logLines()[8], QStringLiteral("[object CompositionEvent] compositionend ")); @@ -3894,10 +3894,13 @@ void tst_QWebEngineView::datalist() QTest::keyClick(view.windowHandle(), Qt::Key_Escape); QTRY_VERIFY(!listView()); - // Key Down should open the popup and select the first suggestion. + // The first Key Down opens the popup. QTest::keyClick(view.windowHandle(), Qt::Key_Down); QTRY_VERIFY(listView()); - QCOMPARE(listView()->currentIndex().row(), 0); + + // The second Key Down selects the first suggestion. + QTest::keyClick(view.windowHandle(), Qt::Key_Down); + QTRY_COMPARE(listView()->currentIndex().row(), 0); // Test keyboard navigation in list. QTest::keyClick(view.windowHandle(), Qt::Key_Up); From 999dca5dc80ad3fe63d2f1052d18a27a018718bb Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 4 Jun 2024 09:46:44 +0200 Subject: [PATCH 011/341] Update Chromium for 122-based Blacklist dynamicFrame faliling test. Task-number: QTBUG-126049 Change-Id: I1bc03ce1987ed033d10322f1984c03e272e334b8 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit e23488c5d24eb383d61d53a84803a2925536b8fd) Reviewed-by: Michal Klocek --- src/3rdparty | 2 +- tests/auto/widgets/qwebenginepage/BLACKLIST | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index f3033f5aa9b..6434c2d5827 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit f3033f5aa9be1e98096c55972166d0be6cb64920 +Subproject commit 6434c2d5827960f6a9ae839da3981b84965ac77e diff --git a/tests/auto/widgets/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST index 52def48d170..01d1ffe3d9b 100644 --- a/tests/auto/widgets/qwebenginepage/BLACKLIST +++ b/tests/auto/widgets/qwebenginepage/BLACKLIST @@ -13,3 +13,7 @@ macos [backgroundColor] macos + +[dynamicFrame] +ubuntu-22.04 + From f5f23448c17a34e497a6da818f26e72ef1b4c385 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Mon, 6 May 2024 12:52:38 +0200 Subject: [PATCH 012/341] Update snapshot filters and version for 122-based snapshot Change-Id: I4cafb01aa2bc4f6e3dad21550a01256f31daadca Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit f3170e5b5207a320493194b7ad165478c6ebd547) Reviewed-by: Qt Cherry-pick Bot --- tools/scripts/take_snapshot.py | 5 +++++ tools/scripts/version_resolver.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index e312dd64c7a..2e2d3991716 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -188,6 +188,10 @@ def isInChromiumBlacklist(file_path): and not file_path.startswith('third_party/node/node_modules/js-tokens/') and not file_path.startswith('third_party/node/node_modules/jsesc/') and not file_path.startswith('third_party/node/node_modules/jsonschema/') + and not file_path.startswith('third_party/node/node_modules/@lit/reactive-element/') + and not file_path.startswith('third_party/node/node_modules/lit-element/') + and not file_path.startswith('third_party/node/node_modules/lit-html/') + and not file_path.startswith('third_party/node/node_modules/lit/') and not file_path.startswith('third_party/node/node_modules/lodash.camelcase/') and not file_path.startswith('third_party/node/node_modules/lodash.sortby/') and not file_path.startswith('third_party/node/node_modules/minimatch/') @@ -271,6 +275,7 @@ def isInChromiumBlacklist(file_path): or '/fuzzer/' in file_path or '/fuzzers/' in file_path or '/fuzzing/' in file_path + and not file_path.endswith('internals_fuzzing.idl') )) or ('/test' in file_path and ('/testdata/' in file_path diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index 707524ef35d..9021d1e202e 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -43,8 +43,8 @@ def get_recursedeps(self): return self.local_scope["recursedeps"] -chromium_version = '120.0.6099.272' -chromium_branch = '6099' +chromium_version = '122.0.6261.72' +chromium_branch = '6261' ninja_version = 'v1.8.2' json_url = 'http://omahaproxy.appspot.com/all.json' From 1ec6b541830c62eb390862b42f0e8cab5ad3410e Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Fri, 17 May 2024 12:14:41 +0200 Subject: [PATCH 013/341] Revive push messaging It crashes due to missing preferences. This patch isolates push message related prefs and uses their 3rdparty registration functions where it's possible - hoping to reduce their maintenance time in the future. Correct a missing character in the docs. Pick-to: 6.7 Change-Id: Ia713bdb16edef8bc535624ba61a47c9f5d7c4155 Reviewed-by: Michal Klocek (cherry picked from commit b5954b3d3d46e8825ce99a9a958c561a34d369f9) Reviewed-by: Qt Cherry-pick Bot --- src/core/pref_service_adapter.cpp | 29 ++++++++++--------- .../doc/snippets/push-notifications/commands | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index ae7cf102bc4..d561cab4fbc 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -19,9 +19,12 @@ #include "components/prefs/pref_service_factory.h" #include "components/prefs/pref_registry_simple.h" #include "components/signin/internal/identity_manager/account_tracker_service.h" -#include "components/signin/public/base/signin_pref_names.h" +#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h" +#include "components/signin/internal/identity_manager/primary_account_manager.h" +#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h" #include "components/user_prefs/user_prefs.h" #include "components/proxy_config/pref_proxy_config_tracker_impl.h" +#include "chrome/browser/gcm/gcm_product_util.h" #include "chrome/common/pref_names.h" #include "extensions/buildflags/buildflags.h" #include "content/public/browser/browser_context.h" @@ -84,16 +87,20 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) #endif // QT_CONFIG(webengine_spellchecker) registry->RegisterBooleanPref(prefs::kShowInternalAccessibilityTree, false); registry->RegisterBooleanPref(prefs::kAccessibilityImageLabelsEnabled, false); + + // chrome/browser/notifications registry->RegisterIntegerPref(prefs::kNotificationNextPersistentId, 10000); + // chrome/browser/push_messaging registry->RegisterDictionaryPref(prefs::kPushMessagingAppIdentifierMap); - registry->RegisterListPref(prefs::kAccountInfo); - registry->RegisterStringPref(prefs::kGoogleServicesLastSyncingUsername, std::string()); - registry->RegisterStringPref(prefs::kGoogleServicesAccountId, std::string()); - registry->RegisterBooleanPref(prefs::kGoogleServicesConsentedToSync, false); - registry->RegisterBooleanPref(prefs::kAutologinEnabled, true); - registry->RegisterListPref(prefs::kReverseAutologinRejectedEmailList); - registry->RegisterBooleanPref(prefs::kSigninAllowed, true); - registry->RegisterBooleanPref(prefs::kSignedInWithCredentialProvider, false); + // chrome/browser/gcm + gcm::RegisterPrefs(registry.get()); + + // signin + PrimaryAccountManager::RegisterProfilePrefs(registry.get()); + ProfileOAuth2TokenService::RegisterProfilePrefs(registry.get()); + GaiaCookieManagerService::RegisterPrefs(registry.get()); + AccountTrackerService::RegisterPrefs(registry.get()); + #if defined(Q_OS_WIN) OSCrypt::RegisterLocalPrefs(registry.get()); #endif @@ -133,10 +140,6 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) registry->RegisterDictionaryPref(prefs::kDevToolsSyncedPreferencesSyncDisabled); registry->RegisterDictionaryPref(prefs::kDevToolsSyncedPreferencesSyncEnabled); - registry->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId, std::string()); - registry->RegisterStringPref(prefs::kGaiaCookieLastListAccountsData, std::string()); - registry->RegisterStringPref(prefs::kGCMProductCategoryForSubtypes, std::string()); - { base::ScopedAllowBlocking allowBlock; m_prefService = factory.Create(registry); diff --git a/src/webenginewidgets/doc/snippets/push-notifications/commands b/src/webenginewidgets/doc/snippets/push-notifications/commands index aee9761c10f..077538e2e55 100644 --- a/src/webenginewidgets/doc/snippets/push-notifications/commands +++ b/src/webenginewidgets/doc/snippets/push-notifications/commands @@ -11,7 +11,7 @@ npm install web-push express //! [1] //! [2] -./node_odules/.bin/web-push generate-vapid-keys +./node_modules/.bin/web-push generate-vapid-keys //! [2] //! [3] From 5583321d089d299f10452027e2e243507bf64a5e Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 11 Jun 2024 16:32:45 +0200 Subject: [PATCH 014/341] Update Chromium MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule src/3rdparty 6434c2d5..b953fab5: * Fix crash when cleaning up indexed database, debug MSVC * Fix MSVC debug mode assertion in Viz * ANGLE: Silence private data warnings when using Direct3D11 backing * Disable DCHECK failure instrumentation in PendingTask destructor Change-Id: Ibce1d5dde11c3a6f2ff3a35a187d289c134ab919 Reviewed-by: Michael BrĂ¼ning (cherry picked from commit 413eef173b24d6070b7bdf5131caa50ef839cd8d) --- src/3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index 6434c2d5827..b953fab5b59 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 6434c2d5827960f6a9ae839da3981b84965ac77e +Subproject commit b953fab5b599be589a978c79735c62c35dad28b5 From 8912f84dc19f90c88f55b64f2840e2f86a087151 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Wed, 22 May 2024 16:55:24 +0200 Subject: [PATCH 015/341] Report an error if system icu is enabled outside Linux and Android The default value for the GN argument icu_use_data_file is true. If it is true, it will try to load the external ICU data, and if the external data file is not present, it will result in a runtime error. system icu option only valid for linux and android. Added code to report configure failure when using QT_FEATURE_webengine_system_icu=ON for unsupported platforms Fixes: QTBUG-125452 Pick-to: 6.7 6.6 Change-Id: I4db6edbd6e45fa216df27843084e21f993492f0e Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 7e6f28e544c3887245809b019392b26da6bb693e) Reviewed-by: Qt Cherry-pick Bot --- configure.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.cmake b/configure.cmake index 2d826e6ddc8..dedd11cff8b 100644 --- a/configure.cmake +++ b/configure.cmake @@ -315,7 +315,7 @@ qt_feature("webengine-system-re2" PRIVATE qt_feature("webengine-system-icu" PRIVATE LABEL "icu" AUTODETECT FALSE - CONDITION ICU_FOUND + CONDITION UNIX AND NOT APPLE AND ICU_FOUND ) qt_feature("webengine-system-libwebp" PRIVATE LABEL "libwebp, libwebpmux and libwebpdemux" From be07b12340af3ebd61d8b87755f5e9731276f1db Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Wed, 15 May 2024 11:46:36 +0200 Subject: [PATCH 016/341] Remove trial_comparison_cert_verifier_supported from GN argument list The specified argument was removed as part of chromium change https://chromium-review.googlesource.com/c/chromium/src/+/4834506 and it is no longer need for 122 based chromium. Change-Id: Ia20d7486f1e106b781d301ba83ce83248b7a1206 Reviewed-by: Michal Klocek (cherry picked from commit 95e69c58cfa6264568c00112f3ae5c1f00a66b24) Reviewed-by: Qt Cherry-pick Bot --- src/core/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a359cc57f91..d43188813db 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -349,7 +349,6 @@ foreach(arch ${archs}) devtools_skip_typecheck=false use_static_angle=true use_perfetto_client_library=false - trial_comparison_cert_verifier_supported=false enable_extensions_legacy_ipc=true enable_bound_session_credentials=false ) From 3439cacdbf76cbd52fd5328aef126ba51914f5a7 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Sat, 15 Jun 2024 21:38:15 +0000 Subject: [PATCH 017/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I94e76e11ff50c0d62c289dab505e302a25cbdb74 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 37198aaddc8..6703bb2ca2b 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: b241e3f8bc951dfbac152bbf58532170ed910756 + ref: d021fd7cb13491ad30e52fd6ebbdb655860bf045 required: true ../qtpositioning: - ref: edda8a2bba1e447ba08f977f8156d45f19cb0b72 + ref: 49731b3ba22a38ab3a433fdb83f087896fb8d315 required: false ../qttools: - ref: f7d623d562d55b75eef0a43e1045a5da8d7609fc + ref: 407ff594b7b4be74731f3e3a5b265b8f073d517a required: false ../qtwebchannel: - ref: 779185f6fa8e33bc183332c7e89b908904dea591 + ref: e432e4c05cc94d1e35b74b832c71109340b75a3d required: false From c6f0efbda04a53342030817d141122461baaea00 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Thu, 11 Apr 2024 14:41:53 +0200 Subject: [PATCH 018/341] Add V8 version to chrome://qt Insert the required V8_VERSION_STRING among the template replacements. Task-number: QTBUG-123500 Change-Id: I8310427300d20c5885ddbc2a5e39d8ec6bf31a26 Reviewed-by: Michal Klocek (cherry picked from commit 97a8fd263c01d2091cbcc7a5aaa685ec708ebb84) Reviewed-by: Qt Cherry-pick Bot --- src/core/net/version_ui_qt.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/net/version_ui_qt.cpp b/src/core/net/version_ui_qt.cpp index 61a89596a2d..a49dea62aaa 100644 --- a/src/core/net/version_ui_qt.cpp +++ b/src/core/net/version_ui_qt.cpp @@ -9,12 +9,14 @@ #include "chrome/browser/profiles/profile.h" #include "qtwebengine/grit/qt_webengine_resources.h" #include "services/network/public/cpp/content_security_policy/content_security_policy.h" +#include "v8/include/v8-version-string.h" namespace { const char kQtWebEngineVersion[] = "qtwebengine_version"; const char kQtWebEngineChromiumVersion[] = "qtwebengine_chromium_version"; const char kQtWebEngineChromiumSecurityPatchVersion[] = "qtwebengine_chromium_security_patch_version"; +const char kQtWebEngineChromiumV8Version[] = "qtwebengine_chromium_v8_version"; const char kCommandLine[] = "command_line"; const char kQtVersionCSS[] = "qt_version.css"; const char kQtLogo[] = "images/qt.png"; @@ -23,7 +25,6 @@ const char kQtWebEngineLogo[] = "images/qtwebengine.png"; VersionUIQt::VersionUIQt(content::WebUI *web_ui) : content::WebUIController(web_ui) { - Profile *profile = Profile::FromWebUI(web_ui); content::WebUIDataSource *html_source = content::WebUIDataSource::CreateAndAdd(profile, chrome::kChromeUIVersionQtHost); @@ -39,6 +40,7 @@ VersionUIQt::VersionUIQt(content::WebUI *web_ui) : content::WebUIController(web_ html_source->AddString(kQtWebEngineChromiumVersion, qWebEngineChromiumVersion()); html_source->AddString(kQtWebEngineChromiumSecurityPatchVersion, qWebEngineChromiumSecurityPatchVersion()); + html_source->AddString(kQtWebEngineChromiumV8Version, V8_VERSION_STRING); #if BUILDFLAG(IS_WIN) html_source->AddString( kCommandLine, From 70a07884c0868ad9972d5de61d41b0e1a2663426 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 12 Jun 2024 15:18:07 +0200 Subject: [PATCH 019/341] Fix build with no extensions Match cmake file and fix linker issue: "undefined symbol: PDFDocumentHelperClientQt" Change-Id: Ie9ac1f8e0137b482a666349a4254419dab773d10 Reviewed-by: Szabolcs David (cherry picked from commit a8e4c357253d655fe00f8d5dd78cc1ab89261a1d) Reviewed-by: Qt Cherry-pick Bot --- src/core/content_browser_client_qt.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 6fec6a1e87b..c32bb3411b4 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -148,12 +148,11 @@ #include "components/pdf/browser/pdf_navigation_throttle.h" #include "components/pdf/browser/pdf_url_loader_request_interceptor.h" #include "components/pdf/browser/pdf_document_helper.h" - -#include "printing/pdf_document_helper_client_qt.h" #endif #if BUILDFLAG(ENABLE_PDF) && BUILDFLAG(ENABLE_EXTENSIONS) #include "extensions/pdf_iframe_navigation_throttle_qt.h" +#include "printing/pdf_document_helper_client_qt.h" #endif #include @@ -517,7 +516,7 @@ void ContentBrowserClientQt::RegisterAssociatedInterfaceBindersForRenderFrameHos std::move(receiver)); }, &rfh)); -#if BUILDFLAG(ENABLE_PDF) +#if BUILDFLAG(ENABLE_PDF) && BUILDFLAG(ENABLE_EXTENSIONS) associated_registry.AddInterface( base::BindRepeating( [](content::RenderFrameHost *render_frame_host, From 234b0a434d0d8ff0c0a3d62eb44b4969154af9b2 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Tue, 11 Jun 2024 14:57:32 +0200 Subject: [PATCH 020/341] Clarify the OTR nature of default QQuickWebEngineProfiles Since the default profile is OTR now, this behavior needs more mention in the documentation. Task-number: QTBUG-126085 Change-Id: I26b5f05cc8c76982bc97deaecd0df835c8ad82fb Reviewed-by: Peter Varga (cherry picked from commit 6716aacd51e09fdf5e9eb01663a0115adce33567) Reviewed-by: Qt Cherry-pick Bot --- .../api/qquickwebengineprofile.cpp | 19 +++++++++++++++++-- .../tst_qquickwebengineview.cpp | 3 ++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index d3373d0b9b7..0246eb64549 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -365,7 +365,7 @@ QQuickWebEngineScriptCollection *QQuickWebEngineProfilePrivate::getUserScripts() whether a profile is off-the-record. Each web engine view has an associated profile. Views that do not have a specific profile set - share a common default one. + share a common one, which is off-the-record by default. */ /*! @@ -404,7 +404,12 @@ QQuickWebEngineScriptCollection *QQuickWebEngineProfilePrivate::getUserScripts() */ /*! - Constructs a new profile with the parent \a parent. + Constructs a new off-the-record profile with the parent \a parent. + + An off-the-record profile leaves no record on the local machine, and has no + persistent data or cache. Thus, the HTTP cache can only be in memory and the + cookies can only be non-persistent. Trying to change these settings will + have no effect. */ QQuickWebEngineProfile::QQuickWebEngineProfile(QObject *parent) : QObject(parent), @@ -478,6 +483,11 @@ void QQuickWebEngineProfile::setStorageName(const QString &name) Whether the web engine profile is \e off-the-record. An off-the-record profile forces cookies, the HTTP cache, and other normally persistent data to be stored only in memory. Profile is off-the-record by default. + + Changing a profile from \e off-the-record to disk-based behavior also requires setting a + proper storageName. + + \sa storageName() */ @@ -487,6 +497,11 @@ void QQuickWebEngineProfile::setStorageName(const QString &name) Whether the web engine profile is \e off-the-record. An off-the-record profile forces cookies, the HTTP cache, and other normally persistent data to be stored only in memory. Profile is off-the-record by default. + + Changing a profile from \e off-the-record to disk-based behavior also requires setting a + proper storageName. + + \sa setStorageName() */ bool QQuickWebEngineProfile::isOffTheRecord() const diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index dbfa1cb3350..cc514f87379 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -99,7 +99,8 @@ private Q_SLOTS: tst_QQuickWebEngineView::tst_QQuickWebEngineView() { QtWebEngineQuick::initialize(); - QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); + + QVERIFY(QQuickWebEngineProfile::defaultProfile()->isOffTheRecord()); m_testSourceDirPath = QDir(QT_TESTCASE_SOURCEDIR).canonicalPath(); if (!m_testSourceDirPath.endsWith(QLatin1Char('/'))) From 33b9eece53f4d185b8a4360fb7a8a47fb606aded Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Fri, 14 Jun 2024 07:53:50 +0200 Subject: [PATCH 021/341] Update Chromium MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule src/3rdparty b953fab5..e2c58970: * Merge "Merge remote-tracking branch 'origin/upstream-master' into HEAD" into 122-based * Merge remote-tracking branch 'origin/upstream-master' into HEAD * FIXUP: Fix QtWebEngine build on Windows * [Backport] IWYU: missing include for std::memcpy usage in bdict_reader.cc * Remove use of dawn_version_file * FIXUP: Fix enable_extensions=false builds * Fix missing include * FIXUP: [Backport] CVE-2024-3914: Use after free in V8 * BASELINE: Update Chromium to 122.0.6261.171 * [Backport] Don't define CRYPTO_addc_* and CRYPTO_subc_* in C++ * FIXUP: Add rsp target writer * [Backport] CVE-2024-4671: Use after free in Visuals * [Backport] CVE-2024-4558: Use after free in ANGLE * [Backport] CVE-2024-4368: Use after free in Dawn * [Backport] CVE-2024-4331: Use after free in Picture In Picture * [Backport] CVE-2024-3845: Inappropriate implementation in Network (2/2) * [Backport] CVE-2024-3845: Inappropriate implementation in Network (1/2) * [Backport] Security bug 327698060 * [Backport] CVE-2024-3914: Use after free in V8 (2/2) * [Backport] CVE-2024-3914: Use after free in V8 (1/2) * [Backport] Security bug 323898565 * [Backport] CVE-2024-4058: Type Confusion in ANGLE * [Backport] Security bug 40940917 * [Backport] CVE-2024-3837: Use after free in QUIC * [Backport] CVE-2024-3839: Out of bounds read in Fonts * [Backport] Security bug 326521449 * [Backport] CVE-2024-3515: Use after free in Dawn * [Backport] CVE-2024-3516: Heap buffer overflow in ANGLE * [Backport] CVE-2024-3157: Out of bounds write in Compositing * [Backport] Security bug 326349405 * [Backport] CVE-2024-3159: Out of bounds memory access in V8 * [Backport] CVE-2024-3156: Inappropriate implementation in V8. * [Backport] Security bug 327183408 * [Backport] Security bug 329674887 (2/2) * [Backport] Security bug 329674887 (1/2) * [Backport] CVE-2024-2887: Type Confusion in WebAssembly * [Backport] CVE-2024-2885: Use after free in Dawn * [Backport] Security bug 41495984 * [Backport] Security bug 40066823 * [Backport] CVE-2024-2627: Use after free in Canvas * [Backport] CVE-2024-2626: Out of bounds read in Swiftshader (2/2) * [Backport] CVE-2024-2626: Out of bounds read in Swiftshader (1/2) * [Backport] CVE-2024-2625: Object lifecycle issue in V8 Change-Id: Iea06fef7a54ee4377309251950847ec2ba5fb01c Reviewed-by: Michael BrĂ¼ning (cherry picked from commit d2d13b886431ad0760ad2fcda363f16c1d26e93c) Reviewed-by: Qt Cherry-pick Bot --- CHROMIUM_VERSION | 4 ++-- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 8bdc0df63b6..39028d6d975 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ -Based on Chromium version: 118.0.5993.220 -Patched with security patches up to Chromium version: 122.0.6261.128 +Based on Chromium version: 122.0.6261.171 +Patched with security patches up to Chromium version: 124.0.6367.202 diff --git a/src/3rdparty b/src/3rdparty index b953fab5b59..e2c589700c3 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit b953fab5b599be589a978c79735c62c35dad28b5 +Subproject commit e2c589700c312d35a503a15c30ea6432d77cbca2 diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 50821fa984e..f969b0e8b9e 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1218,7 +1218,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "122.0.6261.128"; // FIXME: Remember to update + return "124.0.6367.202"; // FIXME: Remember to update } QT_END_NAMESPACE From e0a8072f164c20e19e761224bb13707e3cc147a3 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 10 Jun 2024 12:50:15 +0200 Subject: [PATCH 022/341] Make ImageAnimationPolicy a scoped enum Change-Id: I2c03c6d56d18f37e60b287c337c67718178fbb2b Reviewed-by: Peter Varga (cherry picked from commit edcdccfa232f995f5fc738fc2655f21a30d24f46) Reviewed-by: Qt Cherry-pick Bot --- .../quicknanobrowser/BrowserWindow.qml | 14 +++++++------- .../simplebrowser/webview.cpp | 12 ++++++------ src/core/api/qwebenginesettings.cpp | 2 +- src/core/api/qwebenginesettings.h | 10 +++++----- src/core/doc/src/qwebenginesettings_lgpl.qdoc | 14 +++++++------- src/core/web_engine_settings.cpp | 16 +++++++++------- .../api/qquickwebenginesettings.cpp | 19 ++++++++++--------- .../api/qquickwebenginesettings_p.h | 8 ++++---- tests/auto/quick/publicapi/tst_publicapi.cpp | 6 +++--- 9 files changed, 52 insertions(+), 49 deletions(-) diff --git a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml index 2c5b3d86e75..d040667d32f 100644 --- a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml +++ b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml @@ -44,7 +44,7 @@ ApplicationWindow { property alias webRTCPublicInterfacesOnly : webRTCPublicInterfacesOnly.checked property alias devToolsEnabled: devToolsEnabled.checked property alias pdfViewerEnabled: pdfViewerEnabled.checked - property int imageAnimationPolicy: WebEngineSettings.AllowImageAnimation + property int imageAnimationPolicy: WebEngineSettings.ImageAnimationPolicy.Allow } Action { @@ -377,9 +377,9 @@ ApplicationWindow { text: "Disable All Image Animation" checkable: true autoExclusive: true - checked: WebEngine.settings.imageAnimationPolicy === WebEngineSettings.DisallowImageAnimation + checked: WebEngine.settings.imageAnimationPolicy === WebEngineSettings.ImageAnimationPolicy.Disallow onTriggered: { - appSettings.imageAnimationPolicy = WebEngineSettings.DisallowImageAnimation + appSettings.imageAnimationPolicy = WebEngineSettings.ImageAnimationPolicy.Disallow } } @@ -388,9 +388,9 @@ ApplicationWindow { text: "Allow All Animated Images" checkable: true autoExclusive: true - checked: WebEngine.settings.imageAnimationPolicy === WebEngineSettings.AllowImageAnimation + checked: WebEngine.settings.imageAnimationPolicy === WebEngineSettings.ImageAnimationPolicy.Allow onTriggered : { - appSettings.imageAnimationPolicy = WebEngineSettings.AllowImageAnimation + appSettings.imageAnimationPolicy = WebEngineSettings.ImageAnimationPolicy.Allow } } @@ -399,9 +399,9 @@ ApplicationWindow { text: "Animate Image Once" checkable: true autoExclusive: true - checked: WebEngine.settings.imageAnimationPolicy === WebEngineSettings.AnimateImageOnce + checked: WebEngine.settings.imageAnimationPolicy === WebEngineSettings.ImageAnimationPolicy.AnimateOnce onTriggered : { - appSettings.imageAnimationPolicy = WebEngineSettings.AnimateImageOnce + appSettings.imageAnimationPolicy = WebEngineSettings.ImageAnimationPolicy.AnimateOnce } } } diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp index 3dcfc0c47c5..40a1508b4ef 100644 --- a/examples/webenginewidgets/simplebrowser/webview.cpp +++ b/examples/webenginewidgets/simplebrowser/webview.cpp @@ -227,29 +227,29 @@ void WebView::contextMenuEvent(QContextMenuEvent *event) disableImageAnimation->setCheckable(true); m_imageAnimationGroup->addAction(disableImageAnimation); connect(disableImageAnimation, &QAction::triggered, [this]() { - handleImageAnimationPolicyChange(QWebEngineSettings::DisallowImageAnimation); + handleImageAnimationPolicyChange(QWebEngineSettings::ImageAnimationPolicy::Disallow); }); QAction *allowImageAnimationOnce = editImageAnimation->addAction(tr("Allow animated images, but only once")); allowImageAnimationOnce->setCheckable(true); m_imageAnimationGroup->addAction(allowImageAnimationOnce); connect(allowImageAnimationOnce, &QAction::triggered, - [this]() { handleImageAnimationPolicyChange(QWebEngineSettings::AnimateImageOnce); }); + [this]() { handleImageAnimationPolicyChange(QWebEngineSettings::ImageAnimationPolicy::AnimateOnce); }); QAction *allowImageAnimation = editImageAnimation->addAction(tr("Allow all animated images")); allowImageAnimation->setCheckable(true); m_imageAnimationGroup->addAction(allowImageAnimation); connect(allowImageAnimation, &QAction::triggered, [this]() { - handleImageAnimationPolicyChange(QWebEngineSettings::AllowImageAnimation); + handleImageAnimationPolicyChange(QWebEngineSettings::ImageAnimationPolicy::Allow); }); switch (page()->settings()->imageAnimationPolicy()) { - case QWebEngineSettings::AllowImageAnimation: + case QWebEngineSettings::ImageAnimationPolicy::Allow: allowImageAnimation->setChecked(true); break; - case QWebEngineSettings::AnimateImageOnce: + case QWebEngineSettings::ImageAnimationPolicy::AnimateOnce: allowImageAnimationOnce->setChecked(true); break; - case QWebEngineSettings::DisallowImageAnimation: + case QWebEngineSettings::ImageAnimationPolicy::Disallow: disableImageAnimation->setChecked(true); break; default: diff --git a/src/core/api/qwebenginesettings.cpp b/src/core/api/qwebenginesettings.cpp index f19d8efe57f..a7ae80cd126 100644 --- a/src/core/api/qwebenginesettings.cpp +++ b/src/core/api/qwebenginesettings.cpp @@ -115,7 +115,7 @@ QWebEngineSettings::ImageAnimationPolicy QWebEngineSettings::imageAnimationPolic void QWebEngineSettings::resetImageAnimationPolicy() { - d_ptr->setImageAnimationPolicy(QWebEngineSettings::InheritedImageAnimationPolicy); + d_ptr->setImageAnimationPolicy(QWebEngineSettings::ImageAnimationPolicy::Inherited); } QT_END_NAMESPACE diff --git a/src/core/api/qwebenginesettings.h b/src/core/api/qwebenginesettings.h index 7f89f1ea631..f6b5dfe4d11 100644 --- a/src/core/api/qwebenginesettings.h +++ b/src/core/api/qwebenginesettings.h @@ -78,11 +78,11 @@ class Q_WEBENGINECORE_EXPORT QWebEngineSettings AllowAllUnknownUrlSchemes }; - enum ImageAnimationPolicy { - InheritedImageAnimationPolicy = 0, - AllowImageAnimation, - AnimateImageOnce, - DisallowImageAnimation + enum class ImageAnimationPolicy : uint8_t { + Inherited = 0, + Allow, + AnimateOnce, + Disallow, }; public: diff --git a/src/core/doc/src/qwebenginesettings_lgpl.qdoc b/src/core/doc/src/qwebenginesettings_lgpl.qdoc index cd7ff8e8c0d..dbe9c1d349f 100644 --- a/src/core/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/core/doc/src/qwebenginesettings_lgpl.qdoc @@ -208,13 +208,13 @@ This enum describes how an image animation should be handled when the image frames are rendered for animation. - \value AllowImageAnimation + \value Allow Allows image animation when the image frames are rendered. - \value AnimateImageOnce + \value AnimateOnce Animate the image once when the image frames are rendered. - \value DisallowImageAnimation + \value Disallow Disallows image animation when the image frames are rendered. - \omitvalue InheritedImageAnimationPolicy + \omitvalue Inherited \sa imageAnimationPolicy setImageAnimationPolicy resetImageAnimationPolicy */ @@ -312,7 +312,7 @@ \fn QWebEngineSettings::ImageAnimationPolicy QWebEngineSettings::imageAnimationPolicy() const \since Qt 6.8 Returns the currently selected policy for handling image animation when the image frames are rendered. - Default is \l{QWebEngineSettings::AllowImageAnimation}. + Default is \l{QWebEngineSettings::ImageAnimationPolicy::Allow}. \sa setImageAnimationPolicy resetImageAnimationPolicy */ @@ -320,13 +320,13 @@ \fn void QWebEngineSettings::setImageAnimationPolicy(QWebEngineSettings::ImageAnimationPolicy policy) \since Qt 6.8 Sets the policy for handling image animation when the image frames are rendered to \a policy. - Default is \l{QWebEngineSettings::AllowImageAnimation}. + Default is \l{QWebEngineSettings::ImageAnimationPolicy::Allow}. \sa imageAnimationPolicy resetImageAnimationPolicy */ /*! \fn void QWebEngineSettings::resetImageAnimationPolicy() - \since Qt 6.7 + \since Qt 6.8 Removes the policy for handling image animation. \sa imageAnimationPolicy setImageAnimationPolicy */ diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index e302998f085..452ba639330 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -60,12 +60,14 @@ blink::mojom::ImageAnimationPolicy toBlinkImageAnimationPolicy(QWebEngineSettings::ImageAnimationPolicy policy) { switch (policy) { - case QWebEngineSettings::AllowImageAnimation: + case QWebEngineSettings::ImageAnimationPolicy::Allow: return blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAllowed; - case QWebEngineSettings::AnimateImageOnce: + case QWebEngineSettings::ImageAnimationPolicy::AnimateOnce: return blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAnimateOnce; - case QWebEngineSettings::DisallowImageAnimation: + case QWebEngineSettings::ImageAnimationPolicy::Disallow: return blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyNoAnimation; + case QWebEngineSettings::ImageAnimationPolicy::Inherited: + break; } return blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAllowed; } @@ -74,7 +76,7 @@ WebEngineSettings::WebEngineSettings(WebEngineSettings *_parentSettings) : m_adapter(nullptr) , parentSettings(_parentSettings) , m_unknownUrlSchemePolicy(QWebEngineSettings::InheritedUnknownUrlSchemePolicy) - , m_imageAnimationPolicy(QWebEngineSettings::InheritedImageAnimationPolicy) + , m_imageAnimationPolicy(QWebEngineSettings::ImageAnimationPolicy::Inherited) { if (parentSettings) parentSettings->childSettings.insert(this); @@ -217,13 +219,13 @@ void WebEngineSettings::setImageAnimationPolicy(QWebEngineSettings::ImageAnimati QWebEngineSettings::ImageAnimationPolicy WebEngineSettings::imageAnimationPolicy() const { - if (m_imageAnimationPolicy != QWebEngineSettings::InheritedImageAnimationPolicy) + if (m_imageAnimationPolicy != QWebEngineSettings::ImageAnimationPolicy::Inherited) return m_imageAnimationPolicy; if (parentSettings) return parentSettings->imageAnimationPolicy(); - return QWebEngineSettings::AllowImageAnimation; + return QWebEngineSettings::ImageAnimationPolicy::Allow; } QWebEngineSettings::UnknownUrlSchemePolicy WebEngineSettings::unknownUrlSchemePolicy() const @@ -333,7 +335,7 @@ void WebEngineSettings::initDefaults() m_defaultEncoding = QStringLiteral("ISO-8859-1"); m_unknownUrlSchemePolicy = QWebEngineSettings::InheritedUnknownUrlSchemePolicy; - m_imageAnimationPolicy = QWebEngineSettings::InheritedImageAnimationPolicy; + m_imageAnimationPolicy = QWebEngineSettings::ImageAnimationPolicy::Inherited; } void WebEngineSettings::scheduleApply() diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp index 5dc093a4472..4a66605d6da 100644 --- a/src/webenginequick/api/qquickwebenginesettings.cpp +++ b/src/webenginequick/api/qquickwebenginesettings.cpp @@ -496,11 +496,12 @@ QString QQuickWebEngineSettings::defaultTextEncoding() const return d_ptr->defaultTextEncoding(); } -ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::AllowImageAnimation, - QWebEngineSettings::AllowImageAnimation) -ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::AnimateImageOnce, QWebEngineSettings::AnimateImageOnce) -ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::DisallowImageAnimation, - QWebEngineSettings::DisallowImageAnimation) +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::ImageAnimationPolicy::Allow, + QWebEngineSettings::ImageAnimationPolicy::Allow) +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::ImageAnimationPolicy::AnimateOnce, + QWebEngineSettings::ImageAnimationPolicy::AnimateOnce) +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::ImageAnimationPolicy::Disallow, + QWebEngineSettings::ImageAnimationPolicy::Disallow) /*! \qmlproperty enumeration WebEngineSettings::imageAnimationPolicy \since QtWebEngine 6.8 @@ -508,14 +509,14 @@ ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::DisallowImageAnimation, Specifies how an image animation should be handled when the image frames are rendered for animation. - \value WebEngineSettings.AllowImageAnimation + \value WebEngineSettings.ImageAnimationPolicy.Allow Allows all image animations when the image frames are rendered. - \value WebEngineSettings.AnimateImageOnce + \value WebEngineSettings.ImageAnimationPolicy.AnimateOnce Animate the image once when the image frames are rendered. - \value WebEngineSettings.DisallowImageAnimation + \value WebEngineSettings.ImageAnimationPolicy.Disallow Disallows all image animations when the image frames are rendered. - Default value is \c {WebEngineSettings.AllowImageAnimation}. + Default value is \c {WebEngineSettings.ImageAnimationPolicy.Allow}. */ QQuickWebEngineSettings::ImageAnimationPolicy QQuickWebEngineSettings::imageAnimationPolicy() const { diff --git a/src/webenginequick/api/qquickwebenginesettings_p.h b/src/webenginequick/api/qquickwebenginesettings_p.h index ed3c778845f..3320c45d884 100644 --- a/src/webenginequick/api/qquickwebenginesettings_p.h +++ b/src/webenginequick/api/qquickwebenginesettings_p.h @@ -74,10 +74,10 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject { Q_ENUM(UnknownUrlSchemePolicy) - enum ImageAnimationPolicy { - AllowImageAnimation = 1, - AnimateImageOnce, - DisallowImageAnimation + enum class ImageAnimationPolicy : uint8_t { + Allow = 1, + AnimateOnce, + Disallow, }; Q_ENUM(ImageAnimationPolicy) diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index e6605dc4103..0046de78453 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -923,9 +923,9 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineWebAuthPinRequest.error --> QWebEngineWebAuthUxRequest::PinEntryError" << "QWebEngineWebAuthPinRequest.minPinLength --> int" << "QWebEngineWebAuthPinRequest.remainingAttempts --> int" - << "QQuickWebEngineSettings.AllowImageAnimation --> ImageAnimationPolicy" - << "QQuickWebEngineSettings.AnimateImageOnce --> ImageAnimationPolicy" - << "QQuickWebEngineSettings.DisallowImageAnimation --> ImageAnimationPolicy" + << "QQuickWebEngineSettings.ImageAnimationPolicy.Allow --> ImageAnimationPolicy" + << "QQuickWebEngineSettings.ImageAnimationPolicy.AnimateOnce --> ImageAnimationPolicy" + << "QQuickWebEngineSettings.ImageAnimationPolicy.Disallow --> ImageAnimationPolicy" << "QQuickWebEngineSettings.imageAnimationPolicy --> QQuickWebEngineSettings::ImageAnimationPolicy" << "QQuickWebEngineSettings.imageAnimationPolicyChanged() --> void" << "QWebEngineFrame.htmlName --> QString" From 34d5d5c59f10f454a1dd0d72d41cf52d9b4f7416 Mon Sep 17 00:00:00 2001 From: Martin Negyokru Date: Mon, 10 Jun 2024 15:12:31 +0200 Subject: [PATCH 023/341] Fix warnings after 122 update Fix [-Wswitch] warnings. Test the newly added accessibility role. Change-Id: Ieea34a759dd630a0b60eac2cd74d1420916a5b85 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit b400e36004b8af8ece0d65495e05302120ddd2cb) Reviewed-by: Qt Cherry-pick Bot --- src/core/browser_accessibility_qt.cpp | 1 + src/core/permission_manager_qt.cpp | 3 +++ src/core/type_conversion.cpp | 1 + tests/auto/widgets/accessibility/tst_accessibility.cpp | 1 + 4 files changed, 6 insertions(+) diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index ff3d21fb74a..60e5390e3d0 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -408,6 +408,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const case ax::mojom::Role::kDirectory: return QAccessible::List; case ax::mojom::Role::kDisclosureTriangle: + case ax::mojom::Role::kDisclosureTriangleGrouped: return QAccessible::Button; case ax::mojom::Role::kGenericContainer: return QAccessible::Section; diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 2c1c0d3d670..95f79bb118d 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -69,6 +69,9 @@ static QWebEnginePermission::Feature toQt(blink::PermissionType type) case blink::PermissionType::VR: case blink::PermissionType::STORAGE_ACCESS_GRANT: case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS: + case blink::PermissionType::CAPTURED_SURFACE_CONTROL: + case blink::PermissionType::SMART_CARD: + case blink::PermissionType::WEB_PRINTING: case blink::PermissionType::NUM: LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast(type); break; diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index 2d4fb323dc4..0a3c2489c45 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -32,6 +32,7 @@ QImage toQImage(const SkBitmap &bitmap) case kR16G16_float_SkColorType: case kR16G16_unorm_SkColorType: case kR8_unorm_SkColorType: + case kRGBA_10x6_SkColorType: qWarning("Unknown or unsupported skia image format"); break; case kAlpha_8_SkColorType: diff --git a/tests/auto/widgets/accessibility/tst_accessibility.cpp b/tests/auto/widgets/accessibility/tst_accessibility.cpp index 0a65e7a9566..200f9a5fb3e 100644 --- a/tests/auto/widgets/accessibility/tst_accessibility.cpp +++ b/tests/auto/widgets/accessibility/tst_accessibility.cpp @@ -378,6 +378,7 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kDialog") << QString("
") << 0 << QAccessible::Dialog; //QTest::newRow("ax::mojom::Role::kDirectory") << QString("
    ") << 0 << QAccessible::List; // FIXME: Aria role 'directory' should work QTest::newRow("ax::mojom::Role::kDisclosureTriangle") << QString("
    a
    ") << 1 << QAccessible::Button; + QTest::newRow("ax::mojom::Role::kDisclosureTriangleGroup") << QString("
    a
    ") << 1 << QAccessible::Button; QTest::newRow("ax::mojom::Role::kGenericContainer") << QString("
    a
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocCover") << QString("
    ") << 0 << QAccessible::Graphic; QTest::newRow("ax::mojom::Role::kDocBackLink") << QString("
    ") << 0 << QAccessible::Link; From 72fcd240a5de9a10c3d7fc12896ea23b9f5addb9 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 18 Jun 2024 14:37:05 +0200 Subject: [PATCH 024/341] Remove ninja project from sync scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id861858b413b880ed7f69bb0485b672d2d218d5a Reviewed-by: Michael BrĂ¼ning (cherry picked from commit 1e8d0c5cad19ec6a5e31ce36e71edb80df971932) Reviewed-by: Qt Cherry-pick Bot --- tools/scripts/init-repository.py | 14 -------------- tools/scripts/take_snapshot.py | 16 ---------------- tools/scripts/version_resolver.py | 4 ---- 3 files changed, 34 deletions(-) diff --git a/tools/scripts/init-repository.py b/tools/scripts/init-repository.py index e6ec0c44053..0b973ebd6eb 100755 --- a/tools/scripts/init-repository.py +++ b/tools/scripts/init-repository.py @@ -16,7 +16,6 @@ import version_resolver as resolver chromium_src = os.environ.get('CHROMIUM_SRC_DIR') -ninja_src = os.path.join(qtwebengine_root, 'src/3rdparty_upstream/ninja') gn_src = os.path.join(qtwebengine_root, 'src/3rdparty_upstream/gn') use_external_chromium = False @@ -39,7 +38,6 @@ chromium_src = os.path.join(qtwebengine_root, 'src/3rdparty_upstream/chromium') if args.snapshot or not chromium_src: chromium_src = os.path.join(qtwebengine_root, 'src/3rdparty/chromium') - ninja_src = os.path.join(qtwebengine_root, 'src/3rdparty/ninja') gn_src = os.path.join(qtwebengine_root, 'src/3rdparty/gn') args.snapshot = True print('CHROMIUM_SRC_DIR not set, using Chromium in' + chromium_src) @@ -63,27 +61,16 @@ def updateLastChange(): def initUpstreamSubmodules(): gn_url = 'https://gn.googlesource.com/gn' - ninja_url = 'https://github.com/martine/ninja.git' chromium_url = 'https://chromium.googlesource.com/chromium/src.git' - ninja_shasum = 'refs/tags/' + resolver.currentNinjaVersion() chromium_ref = 'refs/tags/' + resolver.currentVersion() os.chdir(qtwebengine_root) current_submodules = subprocess.check_output(['git', 'submodule']).decode() if not 'src/3rdparty_upstream/gn' in current_submodules: subprocess.call(['git', 'submodule', 'add', gn_url, 'src/3rdparty_upstream/gn']) - if not 'src/3rdparty_upstream/ninja' in current_submodules: - subprocess.call(['git', 'submodule', 'add', ninja_url, 'src/3rdparty_upstream/ninja']) if not use_external_chromium and not 'src/3rdparty_upstream/chromium' in current_submodules: subprocess.call(['git', 'submodule', 'add', chromium_url, 'src/3rdparty_upstream/chromium']) - ninjaSubmodule = GitSubmodule.Submodule() - ninjaSubmodule.path = 'src/3rdparty_upstream/ninja' - ninjaSubmodule.ref = ninja_shasum - ninjaSubmodule.url = ninja_url - ninjaSubmodule.os = 'all' - ninjaSubmodule.initialize() - gnSubmodule = GitSubmodule.Submodule() gnSubmodule.path = 'src/3rdparty_upstream/gn' gnSubmodule.ref = 'master' @@ -103,7 +90,6 @@ def initUpstreamSubmodules(): # Unstage repositories so we do not accidentally commit them. subprocess.call(['git', 'reset', '-q', 'HEAD', 'src/3rdparty_upstream/gn']) - subprocess.call(['git', 'reset', '-q', 'HEAD', 'src/3rdparty_upstream/ninja']) subprocess.call(['git', 'reset', '-q', 'HEAD', 'src/3rdparty_upstream/chromium']) def initSnapshot(): diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index 2e2d3991716..70ce7e5bf49 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -382,21 +382,6 @@ def exportGn(): copyFile(f, os.path.join(third_party_gn, f)) print("") -def exportNinja(): - third_party_upstream_ninja = os.path.join(third_party_upstream, 'ninja') - third_party_ninja = os.path.join(third_party, 'ninja') - os.makedirs(third_party_ninja); - print('exporting contents of:' + third_party_upstream_ninja) - os.chdir(third_party_upstream_ninja) - files = listFilesInCurrentRepository() - print('copying files to ' + third_party_ninja) - for i in range(len(files)): - printProgress(i+1, len(files)) - f = files[i].decode() - if not isInGitBlacklist(f): - copyFile(f, os.path.join(third_party_ninja, f)) - print("") - def exportChromium(): third_party_upstream_chromium = os.path.join(third_party_upstream, 'chromium') third_party_chromium = os.path.join(third_party, 'chromium') @@ -461,7 +446,6 @@ def exportChromium(): clearDirectory(third_party) exportGn() -exportNinja() exportChromium() print('done.') diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index 9021d1e202e..c8923c0f9bc 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -45,7 +45,6 @@ def get_recursedeps(self): chromium_version = '122.0.6261.72' chromium_branch = '6261' -ninja_version = 'v1.8.2' json_url = 'http://omahaproxy.appspot.com/all.json' @@ -72,9 +71,6 @@ def get_recursedeps(self): def currentVersion(): return chromium_version -def currentNinjaVersion(): - return ninja_version - def readReleaseChannels(): response = urllib2.urlopen(json_url) raw_json = response.read().strip() From 08cf629f6349b8462fabc0f90d3014140159caa0 Mon Sep 17 00:00:00 2001 From: Martin Negyokru Date: Wed, 8 May 2024 09:41:56 +0200 Subject: [PATCH 025/341] Handle single file selection in fileChooser There are some components (eg. devtools) that implement their own SelectFileDialog::Listener. They expect 'FileSelected' calls for single file selections. Fixes an issue with devtools_file_helper after 122 update. Change-Id: Iffb5515b9b040dde2e3634b1daddd9e5056d13ca Reviewed-by: Michal Klocek (cherry picked from commit 24805532be9d5d8962c90f0dd9ad0d666cb03c7a) Reviewed-by: Qt Cherry-pick Bot --- src/core/file_picker_controller.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 9f97892966a..fb124df7bb8 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -214,6 +214,9 @@ void FilePickerController::filesSelectedInChooser(const QStringList &filesList) if (files.empty()) d_ptr->fileSystemAccessDialogListener->FileSelectionCanceled(nullptr); + else if (files.size() == 1) + d_ptr->fileSystemAccessDialogListener->FileSelected( + ui::SelectedFileInfo(files[0]), 0, nullptr); else d_ptr->fileSystemAccessDialogListener->MultiFilesSelected( ui::FilePathListToSelectedFileInfoList(files), nullptr); From 67367b7b231d2d22358cb87d1e744e391d6f05d3 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 18 Jun 2024 15:29:17 +0200 Subject: [PATCH 026/341] Update resovler version to 122.0.6261.171 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7428e3782b700846c8565a91f8ed0b1f3d0d5362 Reviewed-by: Michael BrĂ¼ning (cherry picked from commit 390054d7f7176846ff69758a1991a5162ab1d653) Reviewed-by: Qt Cherry-pick Bot --- tools/scripts/version_resolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index c8923c0f9bc..ad71f06e281 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -43,7 +43,7 @@ def get_recursedeps(self): return self.local_scope["recursedeps"] -chromium_version = '122.0.6261.72' +chromium_version = '122.0.6261.171' chromium_branch = '6261' json_url = 'http://omahaproxy.appspot.com/all.json' From 42643386f4d733366b17b5b8d103af49d44d77be Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 13 Jun 2024 08:35:57 +0200 Subject: [PATCH 027/341] Remove unused WebRtcLogUploader It is not referenced by the WebRtcLoggingController after the 122-based adaptations. See, https://crrev.com/c/5021200 Change-Id: Ifd03c5af09575abb37832ad663f61dc0aacfbf3e Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 260b930ac3480dae8204a292dabd7bb98edffbef) Reviewed-by: Qt Cherry-pick Bot --- src/core/web_engine_context.cpp | 22 ---------------------- src/core/web_engine_context.h | 7 ------- 2 files changed, 29 deletions(-) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index f969b0e8b9e..74453d1992e 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -20,9 +20,6 @@ #include "base/task/thread_pool/thread_pool_instance.h" #include "base/threading/thread_restrictions.h" #include "cc/base/switches.h" -#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) -#include "chrome/browser/media/webrtc/webrtc_log_uploader.h" -#endif #include "chrome/common/chrome_switches.h" #include "content/common/process_visibility_tracker.h" #include "content/gpu/gpu_child_thread.h" @@ -658,11 +655,6 @@ void WebEngineContext::destroy() if (m_devtoolsServer) m_devtoolsServer->stop(); -#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) - if (m_webrtcLogUploader) - m_webrtcLogUploader->Shutdown(); -#endif - // Normally the GPU thread is shut down when the GpuProcessHost is destroyed // on IO thread (triggered by ~BrowserMainRunner). But by that time the UI // task runner is not working anymore so we need to do this earlier. @@ -710,10 +702,6 @@ void WebEngineContext::destroy() // Drop the false reference. m_handle->Release(); - -#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) - m_webrtcLogUploader.reset(); -#endif } WebEngineContext::~WebEngineContext() @@ -1109,16 +1097,6 @@ printing::PrintJobManager* WebEngineContext::getPrintJobManager() } #endif -#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) -WebRtcLogUploader *WebEngineContext::webRtcLogUploader() -{ - if (!m_webrtcLogUploader) - m_webrtcLogUploader = std::make_unique(); - return m_webrtcLogUploader.get(); -} -#endif - - base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, bool &enableGLSoftwareRendering) { diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index faed5866180..7a36fd00187 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -48,7 +48,6 @@ struct SandboxInterfaceInfo; #endif QT_FORWARD_DECLARE_CLASS(QObject) -class WebRtcLogUploader; namespace QtWebEngineCore { @@ -74,9 +73,6 @@ class WebEngineContext : public base::RefCounted { QObject *globalQObject(); #if QT_CONFIG(webengine_printing_and_pdf) printing::PrintJobManager* getPrintJobManager(); -#endif -#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) - WebRtcLogUploader *webRtcLogUploader(); #endif void destroyProfileAdapter(); void addProfileAdapter(ProfileAdapter *profileAdapter); @@ -110,9 +106,6 @@ class WebEngineContext : public base::RefCounted { #if QT_CONFIG(webengine_printing_and_pdf) std::unique_ptr m_printJobManager; -#endif -#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) - std::unique_ptr m_webrtcLogUploader; #endif static scoped_refptr m_handle; static bool m_destroyed; From 8242ec532e2575579d5ac5797cb8dd422f37d5c9 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 13 Jun 2024 09:35:57 +0200 Subject: [PATCH 028/341] Remove some leftover forward declarations and includes after Chromium update Change-Id: I0ad59891ccede8e6690fab1f132f43b434f61600 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 200b6245651545fa2f4ff510687689b6d8bf0ee0) Reviewed-by: Qt Cherry-pick Bot --- src/core/autofill_client_qt.h | 1 - src/core/content_browser_client_qt.cpp | 13 +++++-------- src/core/content_browser_client_qt.h | 7 ------- src/core/profile_qt.cpp | 1 - src/core/profile_qt.h | 4 ---- 5 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/core/autofill_client_qt.h b/src/core/autofill_client_qt.h index 4f10882d24c..59b728cc7e6 100644 --- a/src/core/autofill_client_qt.h +++ b/src/core/autofill_client_qt.h @@ -22,7 +22,6 @@ #include "base/containers/span.h" #include "components/autofill/content/browser/content_autofill_client.h" #include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" #include diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index c32bb3411b4..341c4629588 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -16,7 +16,6 @@ #include "components/performance_manager/embedder/performance_manager_registry.h" #include "components/performance_manager/public/performance_manager.h" #include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_main_runner.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/client_certificate_delegate.h" @@ -25,15 +24,12 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" #include "content/public/browser/shared_cors_origin_access_list.h" #include "content/public/browser/url_loader_request_interceptor.h" #include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_contents_view_delegate.h" #include "content/public/browser/web_ui_url_loader_factory.h" #include "content/public/common/content_switches.h" -#include "content/public/common/main_function_params.h" #include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" #include "extensions/buildflags/buildflags.h" @@ -57,7 +53,6 @@ #include "profile_adapter.h" #include "browser_main_parts_qt.h" -#include "browser_message_filter_qt.h" #include "certificate_error_controller.h" #include "client_cert_select_controller.h" #include "custom_handlers/protocol_handler_registry_factory.h" @@ -70,7 +65,6 @@ #include "net/proxying_restricted_cookie_manager_qt.h" #include "net/proxying_url_loader_factory_qt.h" #include "net/system_network_context_manager.h" -#include "platform_notification_service_qt.h" #include "profile_qt.h" #include "profile_io_data_qt.h" #include "renderer_host/user_resource_controller_host.h" @@ -80,7 +74,6 @@ #include "web_contents_adapter.h" #include "web_contents_delegate_qt.h" #include "web_contents_view_qt.h" -#include "web_engine_context.h" #include "web_engine_library_info.h" #include "web_engine_settings.h" #include "authenticator_request_client_delegate_qt.h" @@ -88,6 +81,10 @@ #include "api/qwebenginecookiestore_p.h" #include "api/qwebengineurlrequestinfo_p.h" +#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) +#include "browser_message_filter_qt.h" +#endif + #if QT_CONFIG(webengine_geolocation) #include "base/memory/ptr_util.h" #include "location_provider_qt.h" @@ -190,7 +187,7 @@ bool IsHandledProtocol(base::StringPiece scheme) return true; return false; } -} +} // namespace url namespace QtWebEngineCore { diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index b40c2a343cb..333b08ea22d 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -10,17 +10,10 @@ namespace content { class BrowserContext; class BrowserMainParts; - -#if QT_CONFIG(webengine_pepper_plugins) -class BrowserPpapiHost; -#endif - class DevToolsManagerDelegate; class RenderFrameHost; class RenderProcessHost; -class ResourceContext; class WebContents; -struct MainFunctionParams; struct Referrer; } // namespace content diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index c54e8485b49..ffb1297a5cf 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -15,7 +15,6 @@ #include "qtwebenginecoreglobal_p.h" #include "type_conversion.h" #include "web_engine_library_info.h" -#include "web_engine_context.h" #include "base/base_paths.h" #include "base/files/file_util.h" diff --git a/src/core/profile_qt.h b/src/core/profile_qt.h index a267efbc91b..5394182e4e1 100644 --- a/src/core/profile_qt.h +++ b/src/core/profile_qt.h @@ -11,10 +11,6 @@ class PrefService; -namespace content { -class ResourceContext; -} - namespace extensions { class ExtensionSystemQt; } From 324b3d9d29936dfbefea574ec825c1852bcd1898 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Thu, 13 Jun 2024 16:48:19 +0200 Subject: [PATCH 029/341] Stabilize tst_QWebEngineProfile::permissionPersistence For some reason, the server used to load pages sometimes refuses to stop(). This change adds a TRY_VERIFY to ensure it stops correctly. Change-Id: I05c57e22ca5debbc7f02e48cbed40a30ce3ae43f Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 6ec047b73d030ff5dca171c02fd6027632825c82) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 6245a6c7a23..3cd400fdc64 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -1099,7 +1099,7 @@ void tst_QWebEngineProfile::permissionPersistence() storageDir.remove("permissions.json"); } - QVERIFY(server.stop()); + QTRY_VERIFY(server.stop()); } void tst_QWebEngineProfile::getPermission_data() From 4b7f183dc5adc73388e776d90422c19628cd0eee Mon Sep 17 00:00:00 2001 From: Martin Negyokru Date: Tue, 11 Jun 2024 10:31:48 +0200 Subject: [PATCH 030/341] Fix QWEPermission related warnings Fix compiler warnings that are related to QWebEnginePermission. Change-Id: Icac1352e4934f73a205b85896b6f83171b759dd3 Reviewed-by: Kaloyan Chehlarski Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit f4090baa2d1d7f6c4c963ac8034d7a24836f0e6c) Reviewed-by: Qt Cherry-pick Bot --- examples/webenginewidgets/push-notifications/main.cpp | 2 +- src/core/api/qwebenginepage.cpp | 8 ++++++-- src/core/api/qwebenginepermission.cpp | 2 ++ src/core/permission_manager_qt.cpp | 3 ++- src/core/web_contents_adapter.cpp | 2 ++ 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/examples/webenginewidgets/push-notifications/main.cpp b/examples/webenginewidgets/push-notifications/main.cpp index 950ebfc9f14..2a52ea39e0e 100644 --- a/examples/webenginewidgets/push-notifications/main.cpp +++ b/examples/webenginewidgets/push-notifications/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) QObject::connect(view.page(), &QWebEnginePage::permissionRequested, [&](QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePage::Notifications) + if (permission.feature() != QWebEnginePermission::Notifications) return; permission.grant(); diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index f0260fd0d31..d7e56c0a1dd 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -1857,8 +1857,8 @@ QT_WARNING_DISABLE_DEPRECATED void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy) { Q_D(QWebEnginePage); - QWebEnginePermission::Feature f; - QWebEnginePermission::State s; + QWebEnginePermission::Feature f = QWebEnginePermission::Feature::Unsupported; + QWebEnginePermission::State s = QWebEnginePermission::State::Invalid; switch (feature) { case QWebEnginePage::Notifications: @@ -1891,6 +1891,8 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine case QWebEnginePage::LocalFontsAccess: f = QWebEnginePermission::LocalFontsAccess; break; + default: + Q_UNREACHABLE(); } switch (policy) { @@ -1903,6 +1905,8 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine case QWebEnginePage::PermissionGrantedByUser: s = QWebEnginePermission::Granted; break; + default: + Q_UNREACHABLE(); } d->adapter->setFeaturePermission(securityOrigin, f, s); diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp index d898b8c7e59..61e76ee4a0d 100644 --- a/src/core/api/qwebenginepermission.cpp +++ b/src/core/api/qwebenginepermission.cpp @@ -300,6 +300,8 @@ bool QWebEnginePermission::isTransient(QWebEnginePermission::Feature feature) case QWebEnginePermission::Unsupported: return false; } + + Q_UNREACHABLE_RETURN(false); } QT_END_NAMESPACE diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 95f79bb118d..1f826e7124d 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -98,6 +98,7 @@ static blink::PermissionType toBlink(QWebEnginePermission::Feature feature) case QWebEnginePermission::LocalFontsAccess: return blink::PermissionType::LOCAL_FONTS; case QWebEnginePermission::MediaAudioVideoCapture: + case QWebEnginePermission::MouseLock: case QWebEnginePermission::Unsupported: LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast(feature); return blink::PermissionType::NUM; @@ -173,8 +174,8 @@ static blink::mojom::PermissionStatus getStatusFromSettings(blink::PermissionTyp PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) : m_requestIdCount(0) - , m_persistence(true) , m_profileAdapter(profileAdapter) + , m_persistence(true) { PrefServiceFactory factory; factory.set_async(false); diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index e73eca7f37f..ed169b161e5 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1423,6 +1423,7 @@ void WebContentsAdapter::setFeaturePermission(const QUrl &origin, QWebEnginePerm CHECK_INITIALIZED(); if (feature == QWebEnginePermission::MouseLock) { switch (state) { + case QWebEnginePermission::Invalid: case QWebEnginePermission::Ask: // Do nothing break; @@ -1445,6 +1446,7 @@ void WebContentsAdapter::setFeaturePermission(const QUrl &origin, QWebEnginePerm WebContentsAdapterClient::MediaDesktopAudioCapture); switch (state) { + case QWebEnginePermission::Invalid: case QWebEnginePermission::Ask: // Do nothing return; From c6fa99b96028817d657a793e9f0cc8220b778078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20K=C3=B6hne?= Date: Mon, 24 Jun 2024 13:55:25 +0200 Subject: [PATCH 031/341] Replace urn:dje license identifier with SPDX compatible one We aim for using only valid SPDX expressions in LicenseId fields. But SPDX does not contain a generic 'Public Domain' license, which is why we were going for urn.dje licenses originally. Anyhow, best practice is to use custom LicenseRef- licenses in this case. Task-number: QTBUG-126403 Pick-to: 6.7 Change-Id: I1d050ae42603168c6a4c9d44eeb7fdd6767af060 Reviewed-by: Lucie Gerard (cherry picked from commit 8e22839aa06bed928e37bf9172ee7b31fc2b7ee1) Reviewed-by: Qt Cherry-pick Bot --- LICENSES/LicenseRef-Tango-Icons-Public-Domain.txt | 1 + .../quicknanobrowser/icons/3rdparty/qt_attribution.json | 3 +-- .../permissionbrowser/resources/3rdparty/qt_attribution.json | 3 +-- .../simplebrowser/data/3rdparty/qt_attribution.json | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) create mode 100644 LICENSES/LicenseRef-Tango-Icons-Public-Domain.txt diff --git a/LICENSES/LicenseRef-Tango-Icons-Public-Domain.txt b/LICENSES/LicenseRef-Tango-Icons-Public-Domain.txt new file mode 100644 index 00000000000..220881da67d --- /dev/null +++ b/LICENSES/LicenseRef-Tango-Icons-Public-Domain.txt @@ -0,0 +1 @@ +The icons in this repository are herefore released into the Public Domain. diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json b/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json index d8d85d6f153..48dbde66037 100644 --- a/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json +++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json @@ -9,9 +9,8 @@ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library", "Version": "0.8.90", "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz", - "LicenseId": "urn:dje:license:public-domain", + "LicenseId": "LicenseRef-Tango-Icons-Public-Domain", "License": "Public Domain", - "LicenseFile": "COPYING", "Copyright": ["Ulisse Perusin ", "Steven Garrity ", "Lapo Calamandrei ", diff --git a/examples/webenginewidgets/permissionbrowser/resources/3rdparty/qt_attribution.json b/examples/webenginewidgets/permissionbrowser/resources/3rdparty/qt_attribution.json index e11663d5e41..63fe372c21c 100644 --- a/examples/webenginewidgets/permissionbrowser/resources/3rdparty/qt_attribution.json +++ b/examples/webenginewidgets/permissionbrowser/resources/3rdparty/qt_attribution.json @@ -9,9 +9,8 @@ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library", "Version": "0.8.90", "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz", - "LicenseId": "urn:dje:license:public-domain", + "LicenseId": "LicenseRef-Tango-Icons-Public-Domain", "License": "Public Domain", - "LicenseFile": "COPYING", "Copyright": ["Ulisse Perusin ", "Steven Garrity ", "Lapo Calamandrei ", diff --git a/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json b/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json index fbc96416ee1..301e933eb8e 100644 --- a/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json +++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json @@ -9,9 +9,8 @@ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library", "Version": "0.8.90", "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz", - "LicenseId": "urn:dje:license:public-domain", + "LicenseId": "LicenseRef-Tango-Icons-Public-Domain", "License": "Public Domain", - "LicenseFile": "COPYING", "Copyright": ["Ulisse Perusin ", "Steven Garrity ", "Lapo Calamandrei ", From d08874c52183c470cbd62dfeb26c9d18c0795de2 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Wed, 19 Jun 2024 16:01:49 +0200 Subject: [PATCH 032/341] Fix deprecation of QWebEngineUrlRequestJob::NoError after API review Change-Id: I6919c441053f4378d1785bfa97067ef58c0240e1 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 63224bc040533663963a2a81fedb0ef203383698) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineurlrequestjob.cpp | 2 +- src/core/api/qwebengineurlrequestjob.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp index 5ad22f3441d..b969b2369e1 100644 --- a/src/core/api/qwebengineurlrequestjob.cpp +++ b/src/core/api/qwebengineurlrequestjob.cpp @@ -32,7 +32,7 @@ QT_BEGIN_NAMESPACE This enum type holds the type of the error that occurred: \value NoError - The request was successful. (Deprecated since Qt 6.7) + The request was successful. (Deprecated since Qt 6.8) \value UrlNotFound The requested URL was not found. \value UrlInvalid diff --git a/src/core/api/qwebengineurlrequestjob.h b/src/core/api/qwebengineurlrequestjob.h index 858c03e6eb3..8448efdefd3 100644 --- a/src/core/api/qwebengineurlrequestjob.h +++ b/src/core/api/qwebengineurlrequestjob.h @@ -26,11 +26,11 @@ class Q_WEBENGINECORE_EXPORT QWebEngineUrlRequestJob : public QObject ~QWebEngineUrlRequestJob(); enum Error { -#if QT_DEPRECATED_SINCE(6, 7) +#if QT_DEPRECATED_SINCE(6, 8) NoError Q_DECL_ENUMERATOR_DEPRECATED_X( "This attribute has no effect.") = 0, #endif - UrlNotFound, + UrlNotFound = 1, UrlInvalid, RequestAborted, RequestDenied, From 661a06bf3eed90d000eeb2116cc37681b4a7736e Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 20 Jun 2024 14:42:44 +0200 Subject: [PATCH 033/341] Remove leftover EGL context initialization methods Their usage was removed by caf5f383a Fix building on Windows and macOS with chromium EGL Change-Id: I1e707a6976a1acd28081964cea6571dde6ea7979 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 21ab3a899a9dcd6100d677c169b725d632e41028) Reviewed-by: Qt Cherry-pick Bot --- src/core/ozone/gl_context_qt.cpp | 17 ----------------- src/core/ozone/gl_context_qt.h | 3 --- 2 files changed, 20 deletions(-) diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index 2e358c0fbb0..634e2aa0f64 100644 --- a/src/core/ozone/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -75,23 +75,6 @@ void GLContextHelper::destroy() contextHelper = nullptr; } -bool GLContextHelper::initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs) -{ - return context->Initialize(surface, attribs); -} - -bool GLContextHelper::initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs) -{ - bool ret = false; - Qt::ConnectionType connType = (QThread::currentThread() == qApp->thread()) ? Qt::DirectConnection : Qt::BlockingQueuedConnection; - QMetaObject::invokeMethod(contextHelper, "initializeContextOnBrowserThread", connType, - Q_RETURN_ARG(bool, ret), - Q_ARG(gl::GLContext*, context), - Q_ARG(gl::GLSurface*, surface), - Q_ARG(gl::GLContextAttribs, attribs)); - return ret; -} - void* GLContextHelper::getEGLConfig() { QByteArray resource = QByteArrayLiteral("eglconfig"); diff --git a/src/core/ozone/gl_context_qt.h b/src/core/ozone/gl_context_qt.h index 41c6a5f0c9b..1607284331b 100644 --- a/src/core/ozone/gl_context_qt.h +++ b/src/core/ozone/gl_context_qt.h @@ -28,7 +28,6 @@ class GLContextHelper : public QObject { public: static void initialize(); static void destroy(); - static bool initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); static void* getEGLConfig(); static void* getGlXConfig(); @@ -42,8 +41,6 @@ class GLContextHelper : public QObject { static void *getEglPlatformInterface(); private: - Q_INVOKABLE bool initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); - static GLContextHelper* contextHelper; bool m_robustness = false; }; From d46f4a69a62ffc440ebd6d52ae9eabe440827910 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 20 Jun 2024 14:08:58 +0200 Subject: [PATCH 034/341] Initialize extension settings for EGL This fixes vaapi for EGL backend. b_EGL_MESA_image_dma_buf_export setting has to be initialized because vaapi uses the EGL_MESA_image_dma_buf_export extension. Also override the extension settings with our own capability check results. If EGL_EXT_create_context_robustness extension is not overridden it may cause EGL_BAD_MATCH error when creating EGL context. Change-Id: I29d4b2203f14131ffd1781f8b24c1e4e5752ffe7 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit e01cdda43c2c93dda47da5f2a447f41417d5d36e) Reviewed-by: Qt Cherry-pick Bot --- src/core/ozone/gl_surface_egl_qt.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/core/ozone/gl_surface_egl_qt.cpp b/src/core/ozone/gl_surface_egl_qt.cpp index a0c120ac61c..cc588453d16 100644 --- a/src/core/ozone/gl_surface_egl_qt.cpp +++ b/src/core/ozone/gl_surface_egl_qt.cpp @@ -14,7 +14,7 @@ #include "ui/gl/gl_display_manager.h" #include "ui/gl/init/gl_factory.h" -#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN) +#if defined(USE_OZONE) using ui::GetLastEGLErrorString; @@ -47,6 +47,21 @@ gl::GLDisplay *GLSurfaceEGLQt::InitializeOneOff(gl::GpuPreference preference) return nullptr; } + egl_display->ext->InitializeExtensionSettings(egl_display->GetDisplay()); + if (egl_display->ext->b_EGL_EXT_create_context_robustness) { + egl_display->ext->b_EGL_EXT_create_context_robustness = + GLContextHelper::isCreateContextRobustnessSupported(); + } + + if (egl_display->ext->b_EGL_EXT_image_dma_buf_import + || egl_display->ext->b_EGL_EXT_image_dma_buf_import_modifiers + || egl_display->ext->b_EGL_MESA_image_dma_buf_export) { + const bool dmaBufSupported = EGLHelper::instance()->isDmaBufSupported(); + egl_display->ext->b_EGL_EXT_image_dma_buf_import = dmaBufSupported; + egl_display->ext->b_EGL_EXT_image_dma_buf_import_modifiers = dmaBufSupported; + egl_display->ext->b_EGL_MESA_image_dma_buf_export = dmaBufSupported; + } + g_config = GLContextHelper::getEGLConfig(); if (!g_config) { LOG(ERROR) << "GLContextHelper::getEGLConfig() failed."; @@ -195,4 +210,4 @@ void* GLSurfacelessQtEGL::GetShareHandle() } } // namespace gl -#endif // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN) +#endif // defined(USE_OZONE) From 7338266ed2fc40941deef18f3c5c04d27699f695 Mon Sep 17 00:00:00 2001 From: Alexei Cazacov Date: Fri, 7 Jun 2024 08:40:25 +0300 Subject: [PATCH 035/341] Docs: fix the QML docs for the PdfSelection::text property The QML docs described the "string" property, but the actual property name is "text". Add a selectAll() shortcut to the withdoc.qml manual test while we're at it, for easier checking of behavior. Fixes: QTBUG-126138 Pick-to: 6.7 6.5 6.2 Change-Id: Ieab6188661d4e9b1c1f4dc4faaf355b94bdc3f4c Reviewed-by: Shawn Rutledge (cherry picked from commit 1caa4fd26b25d97507e916780e34e70720ceb0b2) Reviewed-by: Qt Cherry-pick Bot --- src/pdfquick/qquickpdfselection.cpp | 7 ++++--- tests/manual/quick/pdf/withdoc.qml | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pdfquick/qquickpdfselection.cpp b/src/pdfquick/qquickpdfselection.cpp index 4776cb8b4ed..5a9aa0025e6 100644 --- a/src/pdfquick/qquickpdfselection.cpp +++ b/src/pdfquick/qquickpdfselection.cpp @@ -470,9 +470,10 @@ void QQuickPdfSelection::setHold(bool hold) } /*! - \qmlproperty string PdfSelection::string + \qmlproperty string PdfSelection::text - The string found. + The text that was found in the rectangular area between \l from and \l to, + or all text on the \l page if selectAll() was called. */ QString QQuickPdfSelection::text() const { @@ -483,7 +484,7 @@ QString QQuickPdfSelection::text() const /*! \qmlmethod void PdfSelection::copyToClipboard() - Copies plain text from the \l string property to the system clipboard. + Copies plain text from the \l text property to the system clipboard. */ void QQuickPdfSelection::copyToClipboard() const { diff --git a/tests/manual/quick/pdf/withdoc.qml b/tests/manual/quick/pdf/withdoc.qml index 0a2a8663087..c388e041edd 100644 --- a/tests/manual/quick/pdf/withdoc.qml +++ b/tests/manual/quick/pdf/withdoc.qml @@ -125,6 +125,10 @@ Window { image.sourceSize.height = image.implicitHeight / image.zoomFactor } } + Shortcut { + sequence: StandardKey.SelectAll + onActivated: selection.selectAll() + } Shortcut { sequence: "Ctrl+0" onActivated: image.sourceSize = undefined From f8e0ab645e76be0bc50888c67a501e47a8a46be0 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 27 Jun 2024 06:11:25 +0000 Subject: [PATCH 036/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I0f123e24e09b74071580b22e5587e95f34994aad Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 6703bb2ca2b..a4a9f46a3b7 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: d021fd7cb13491ad30e52fd6ebbdb655860bf045 + ref: 8206b9b4b159c9a0244ff4f92d4c3bb8fad13c1c required: true ../qtpositioning: - ref: 49731b3ba22a38ab3a433fdb83f087896fb8d315 + ref: 5a12dc643d425e96d19f6a543f7c6c51a01aa857 required: false ../qttools: - ref: 407ff594b7b4be74731f3e3a5b265b8f073d517a + ref: df2a2fc4c6b32ad6203a6c90222dd9051c2f1ba5 required: false ../qtwebchannel: - ref: e432e4c05cc94d1e35b74b832c71109340b75a3d + ref: 4579fb731a4954633e4398477896bbf6968c34bc required: false From a955c950752680bc7c015d2101a67c4ccaeca42a Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Tue, 25 Jun 2024 16:09:07 +0200 Subject: [PATCH 037/341] Additions to QWebEngineClientHints (post API review) - Make this class accessible from QML - Mark properties as FINAL - Change fullVersionList to QVariantMap to support it in QML - Access ProfileAdapter through QPointer instead of raw pointer to make it safer Change-Id: Ib242059378aaf6fd2c5f176ba26ed6f94e2afd76 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit d745868c586fb6469e8bd5ee6134ce3b4a83c40a) Reviewed-by: Qt Cherry-pick Bot --- .../quicknanobrowser/ApplicationRoot.qml | 6 ++ src/core/api/qwebengineclienthints.cpp | 63 ++++++++++++++++--- src/core/api/qwebengineclienthints.h | 47 ++++++++------ .../api/qquickwebengineprofile.h | 1 + tests/auto/quick/publicapi/tst_publicapi.cpp | 14 +++++ .../qwebenginepage/tst_qwebenginepage.cpp | 11 ++-- 6 files changed, 108 insertions(+), 34 deletions(-) diff --git a/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml b/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml index 55c41440976..5a27d46df95 100644 --- a/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml +++ b/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml @@ -10,6 +10,12 @@ QtObject { property QtObject defaultProfile: WebEngineProfile { storageName: "Profile" offTheRecord: false + + Component.onCompleted: { + let fullVersionList = defaultProfile.clientHints.fullVersionList; + fullVersionList["QuickNanoBrowser"] = "1.0"; + defaultProfile.clientHints.fullVersionList = fullVersionList; + } } property QtObject otrProfile: WebEngineProfile { diff --git a/src/core/api/qwebengineclienthints.cpp b/src/core/api/qwebengineclienthints.cpp index 907d4ae76d8..ced25b4c91c 100644 --- a/src/core/api/qwebengineclienthints.cpp +++ b/src/core/api/qwebengineclienthints.cpp @@ -6,6 +6,7 @@ #include "profile_adapter.h" #include +#include QT_BEGIN_NAMESPACE @@ -35,11 +36,15 @@ QT_BEGIN_NAMESPACE \sa QWebEngineProfile::clientHints(), QQuickWebEngineProfile::clientHints() */ +/*! \internal + */ QWebEngineClientHints::QWebEngineClientHints(QtWebEngineCore::ProfileAdapter *profileAdapter) : m_profileAdapter(profileAdapter) { } +/*! \internal + */ QWebEngineClientHints::~QWebEngineClientHints() { } @@ -50,6 +55,8 @@ QWebEngineClientHints::~QWebEngineClientHints() */ QString QWebEngineClientHints::arch() const { + if (!m_profileAdapter) + return QString(); return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAArchitecture).toString(); } @@ -61,6 +68,8 @@ QString QWebEngineClientHints::arch() const */ QString QWebEngineClientHints::platform() const { + if (!m_profileAdapter) + return QString(); return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAPlatform).toString(); } @@ -70,6 +79,8 @@ QString QWebEngineClientHints::platform() const */ QString QWebEngineClientHints::model() const { + if (!m_profileAdapter) + return QString(); return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAModel).toString(); } @@ -81,6 +92,8 @@ QString QWebEngineClientHints::model() const */ bool QWebEngineClientHints::isMobile() const { + if (!m_profileAdapter) + return false; return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAMobile).toBool(); } @@ -90,6 +103,8 @@ bool QWebEngineClientHints::isMobile() const */ QString QWebEngineClientHints::fullVersion() const { + if (!m_profileAdapter) + return QString(); return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAFullVersion).toString(); } @@ -99,6 +114,8 @@ QString QWebEngineClientHints::fullVersion() const */ QString QWebEngineClientHints::platformVersion() const { + if (!m_profileAdapter) + return QString(); return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAPlatformVersion).toString(); } @@ -108,6 +125,8 @@ QString QWebEngineClientHints::platformVersion() const */ QString QWebEngineClientHints::bitness() const { + if (!m_profileAdapter) + return QString(); return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UABitness).toString(); } @@ -115,15 +134,17 @@ QString QWebEngineClientHints::bitness() const \property QWebEngineClientHints::fullVersionList The value of the \c{Sec-CH-UA-Full-Version-List} HTTP header and \c{fullVersionList} member of NavigatorUAData in JavaScript. - It holds brand name and version number pairs in a QHash. The provided values will be automatically extended by the currently used version + It holds brand name and version number pairs in a QVariantMap. The provided values will be automatically extended by the currently used version of Chromium and a semi-random brand. */ -QHash QWebEngineClientHints::fullVersionList() const +QVariantMap QWebEngineClientHints::fullVersionList() const { - QHash ret; + QVariantMap ret; + if (!m_profileAdapter) + return ret; QJsonObject fullVersionList = m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAFullVersionList).toJsonObject(); for (const QString &key : fullVersionList.keys()) - ret.insert(key, fullVersionList.value(key).toString()); + ret.insert(key, fullVersionList.value(key).toVariant()); return ret; } @@ -133,54 +154,74 @@ QHash QWebEngineClientHints::fullVersionList() const */ bool QWebEngineClientHints::isWow64() const { + if (!m_profileAdapter) + return false; return m_profileAdapter->clientHint(QtWebEngineCore::ProfileAdapter::UAWOW64).toBool(); } void QWebEngineClientHints::setArch(const QString &arch) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAArchitecture, QVariant(arch)); } void QWebEngineClientHints::setPlatform(const QString &platform) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAPlatform, QVariant(platform)); } void QWebEngineClientHints::setModel(const QString &model) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAModel, QVariant(model)); } -void QWebEngineClientHints::setIsMobile(const bool mobile) +void QWebEngineClientHints::setIsMobile(bool mobile) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAMobile, QVariant(mobile)); } void QWebEngineClientHints::setFullVersion(const QString &fullVerson) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAFullVersion, QVariant(fullVerson)); } void QWebEngineClientHints::setPlatformVersion(const QString &platformVersion) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAPlatformVersion, QVariant(platformVersion)); } void QWebEngineClientHints::setBitness(const QString &bitness) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UABitness, QVariant(bitness)); } -void QWebEngineClientHints::setFullVersionList(const QHash &fullVersionList) +void QWebEngineClientHints::setFullVersionList(const QVariantMap &fullVersionList) { + if (!m_profileAdapter) + return; QJsonObject jsonObject; for (auto i = fullVersionList.cbegin(), end = fullVersionList.cend(); i != end; ++i) - jsonObject.insert(i.key(), QJsonValue(i.value())); + jsonObject.insert(i.key(), QJsonValue(i.value().toString())); m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAFullVersionList, QVariant(jsonObject)); } -void QWebEngineClientHints::setIsWow64(const bool wow64) +void QWebEngineClientHints::setIsWow64(bool wow64) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHint(QtWebEngineCore::ProfileAdapter::UAWOW64, QVariant(wow64)); } @@ -192,11 +233,15 @@ void QWebEngineClientHints::setIsWow64(const bool wow64) */ bool QWebEngineClientHints::isAllClientHintsEnabled() { + if (!m_profileAdapter) + return true; return m_profileAdapter->clientHintsEnabled(); } void QWebEngineClientHints::setAllClientHintsEnabled(bool enabled) { + if (!m_profileAdapter) + return; m_profileAdapter->setClientHintsEnabled(enabled); } @@ -205,6 +250,8 @@ void QWebEngineClientHints::setAllClientHintsEnabled(bool enabled) */ void QWebEngineClientHints::resetAll() { + if (!m_profileAdapter) + return; m_profileAdapter->resetClientHints(); } diff --git a/src/core/api/qwebengineclienthints.h b/src/core/api/qwebengineclienthints.h index 8956b5cb629..efaebb99e94 100644 --- a/src/core/api/qwebengineclienthints.h +++ b/src/core/api/qwebengineclienthints.h @@ -7,7 +7,9 @@ #include #include -#include +#include +#include +#include namespace QtWebEngineCore { class ProfileAdapter; @@ -15,22 +17,26 @@ class ProfileAdapter; QT_BEGIN_NAMESPACE -class Q_WEBENGINECORE_EXPORT QWebEngineClientHints +class Q_WEBENGINECORE_EXPORT QWebEngineClientHints : public QObject { - Q_GADGET - Q_PROPERTY(QString arch READ arch WRITE setArch) - Q_PROPERTY(QString platform READ platform WRITE setPlatform) - Q_PROPERTY(QString model READ model WRITE setModel) - Q_PROPERTY(bool mobile READ isMobile WRITE setIsMobile) - Q_PROPERTY(QString fullVersion READ fullVersion WRITE setFullVersion) - Q_PROPERTY(QString platformVersion READ platformVersion WRITE setPlatformVersion) - Q_PROPERTY(QString bitness READ bitness WRITE setBitness) - Q_PROPERTY(QHash fullVersionList READ fullVersionList WRITE setFullVersionList) - Q_PROPERTY(bool wow64 READ isWow64 WRITE setIsWow64) - - Q_PROPERTY(bool isAllClientHintsEnabled READ isAllClientHintsEnabled WRITE setAllClientHintsEnabled) + Q_OBJECT + Q_PROPERTY(QString arch READ arch WRITE setArch FINAL) + Q_PROPERTY(QString platform READ platform WRITE setPlatform FINAL) + Q_PROPERTY(QString model READ model WRITE setModel FINAL) + Q_PROPERTY(bool mobile READ isMobile WRITE setIsMobile FINAL) + Q_PROPERTY(QString fullVersion READ fullVersion WRITE setFullVersion FINAL) + Q_PROPERTY(QString platformVersion READ platformVersion WRITE setPlatformVersion FINAL) + Q_PROPERTY(QString bitness READ bitness WRITE setBitness FINAL) + Q_PROPERTY(QVariantMap fullVersionList READ fullVersionList WRITE setFullVersionList FINAL) + Q_PROPERTY(bool wow64 READ isWow64 WRITE setIsWow64 FINAL) + + Q_PROPERTY(bool isAllClientHintsEnabled READ isAllClientHintsEnabled WRITE setAllClientHintsEnabled FINAL) public: + QML_NAMED_ELEMENT(WebEngineClientHints) + QML_UNCREATABLE("") + QML_ADDED_IN_VERSION(6, 8) + ~QWebEngineClientHints(); QString arch() const; @@ -40,31 +46,32 @@ class Q_WEBENGINECORE_EXPORT QWebEngineClientHints QString fullVersion() const; QString platformVersion() const; QString bitness() const; - QHash fullVersionList() const; + QVariantMap fullVersionList() const; bool isWow64() const; void setArch(const QString &); void setPlatform(const QString &); void setModel(const QString &); - void setIsMobile(const bool); + void setIsMobile(bool); void setFullVersion(const QString &); void setPlatformVersion(const QString &); void setBitness(const QString &); - void setFullVersionList(const QHash &); - void setIsWow64(const bool); + void setFullVersionList(const QVariantMap &); + void setIsWow64(bool); bool isAllClientHintsEnabled(); void setAllClientHintsEnabled(bool enabled); - void resetAll(); + Q_INVOKABLE void resetAll(); private: explicit QWebEngineClientHints(QtWebEngineCore::ProfileAdapter *profileAdapter); + Q_DISABLE_COPY(QWebEngineClientHints) friend class QWebEngineProfilePrivate; friend class QQuickWebEngineProfilePrivate; - QtWebEngineCore::ProfileAdapter *m_profileAdapter; + QPointer m_profileAdapter; }; QT_END_NAMESPACE diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h index 186a11d7bc4..f5b7ce8e7e0 100644 --- a/src/webenginequick/api/qquickwebengineprofile.h +++ b/src/webenginequick/api/qquickwebengineprofile.h @@ -41,6 +41,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject { Q_PROPERTY(QQuickWebEngineScriptCollection *userScripts READ userScripts) Q_PROPERTY(QString downloadPath READ downloadPath WRITE setDownloadPath NOTIFY downloadPathChanged FINAL REVISION(1,5)) Q_PROPERTY(bool isPushServiceEnabled READ isPushServiceEnabled WRITE setPushServiceEnabled NOTIFY pushServiceEnabledChanged FINAL REVISION(6,5)) + Q_PROPERTY(QWebEngineClientHints *clientHints READ clientHints FINAL REVISION(6,8)) QML_NAMED_ELEMENT(WebEngineProfile) QML_ADDED_IN_VERSION(1, 1) QML_EXTRA_VERSION(2, 0) diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 0046de78453..45501cd6099 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,7 @@ static const QList typesToCheck = QList knownEnumNames = QList() @@ -144,6 +146,17 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineCertificateError.overridable --> bool" << "QWebEngineCertificateError.rejectCertificate() --> void" << "QWebEngineCertificateError.url --> QUrl" + << "QWebEngineClientHints.arch --> QString" + << "QWebEngineClientHints.platform --> QString" + << "QWebEngineClientHints.model --> QString" + << "QWebEngineClientHints.mobile --> bool" + << "QWebEngineClientHints.fullVersion --> QString" + << "QWebEngineClientHints.platformVersion --> QString" + << "QWebEngineClientHints.bitness --> QString" + << "QWebEngineClientHints.fullVersionList --> QVariantMap" + << "QWebEngineClientHints.wow64 --> bool" + << "QWebEngineClientHints.isAllClientHintsEnabled --> bool" + << "QWebEngineClientHints.resetAll() --> void" << "QQuickWebEngineClientCertificateOption.issuer --> QString" << "QQuickWebEngineClientCertificateOption.subject --> QString" << "QQuickWebEngineClientCertificateOption.effectiveDate --> QDateTime" @@ -395,6 +408,7 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineProfile.cachePathChanged() --> void" << "QQuickWebEngineProfile.clearHttpCache() --> void" << "QQuickWebEngineProfile.clearHttpCacheCompleted() --> void" + << "QQuickWebEngineProfile.clientHints --> QWebEngineClientHints*" << "QQuickWebEngineProfile.downloadFinished(QQuickWebEngineDownloadRequest*) --> void" << "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadRequest*) --> void" << "QQuickWebEngineProfile.downloadPath --> QString" diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index e7f2ce1cd7a..5af1e9ff9ff 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -5434,11 +5434,11 @@ void tst_QWebEnginePage::clientHints_data() QTest::addColumn("platformVersion"); QTest::addColumn("bitness"); QTest::addColumn("isWOW64"); - QTest::addColumn>("fullVersionList"); + QTest::addColumn("fullVersionList"); - QTest::newRow("Modify values") << true << "Abc" << "AmigaOS" << "Ultra" << true << "1.99" << "3" << "x64" << true << QHash({{"APITest", "1.0.0"}, {"App", "5.0"}}); - QTest::newRow("Empty values") << true << "" << "" << "" << false << "" << "" << "" << false << QHash(); - QTest::newRow("Disable headers") << false << "" << "" << "" << false << "" << "" << "" << false << QHash(); + QTest::newRow("Modify values") << true << "Abc" << "AmigaOS" << "Ultra" << true << "1.99" << "3" << "x64" << true << QVariantMap({{"APITest", "1.0.0"}, {"App", "5.0"}}); + QTest::newRow("Empty values") << true << "" << "" << "" << false << "" << "" << "" << false << QVariantMap(); + QTest::newRow("Disable headers") << false << "" << "" << "" << false << "" << "" << "" << false << QVariantMap(); } void tst_QWebEnginePage::clientHints() @@ -5452,8 +5452,7 @@ void tst_QWebEnginePage::clientHints() QFETCH(QString, platformVersion); QFETCH(QString, bitness); QFETCH(bool, isWOW64); - typedef QHash brandVersionPairs; - QFETCH(brandVersionPairs, fullVersionList); + QFETCH(QVariantMap, fullVersionList); QWebEnginePage page; QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); From 2d053c4fd0a58500090434c4c6ffa818035d6ec0 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Fri, 21 Jun 2024 15:45:28 +0200 Subject: [PATCH 038/341] Use QAnyStringView instead of QString cr Change-Id: I54f1cd3784ef2fb3e9547281592db9217f819966 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit c258d265a5d56f7c4684487a27322d8aeebe95fa) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginepage.cpp | 4 ++-- src/core/api/qwebenginepage.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index d7e56c0a1dd..a5c06f29ce8 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -2574,10 +2574,10 @@ QWebEngineFrame QWebEnginePage::mainFrame() Returns the frame with the given \a name. If there are multiple frames with the same name, which one is returned is arbitrary. If no frame was found, returns \c std::nullopt. */ -std::optional QWebEnginePage::findFrameByName(const QString &name) +std::optional QWebEnginePage::findFrameByName(QAnyStringView name) { Q_D(QWebEnginePage); - if (auto maybeId = d->adapter->findFrameIdByName(name)) { + if (auto maybeId = d->adapter->findFrameIdByName(name.toString())) { return QWebEngineFrame(d, *maybeId); } return {}; diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h index cca7c55e7a8..61c9bd990c1 100644 --- a/src/core/api/qwebenginepage.h +++ b/src/core/api/qwebenginepage.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -324,7 +325,7 @@ QT_WARNING_POP void setVisible(bool visible); QWebEngineFrame mainFrame(); - std::optional findFrameByName(const QString &name); + std::optional findFrameByName(QAnyStringView name); void acceptAsNewWindow(QWebEngineNewWindowRequest &request); From bcfb37c93850ae4bfc189d6d48835f4467e90159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucie=20G=C3=A9rard?= Date: Thu, 28 Mar 2024 15:35:21 +0100 Subject: [PATCH 039/341] Correct license for test files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to QUIP-18 [1], all test files should be LicenseRef-Qt-Commercial OR GPL-3.0-only [1]: https://contribute.qt-project.org/quips/18 Pick-to: 6.7 Task-number: QTBUG-121787 Change-Id: I7ba480e5d9b9095ad6686c8b1c857f35caf17d04 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Kai Köhne (cherry picked from commit a2d4c8a183e763b097e16f52172092cdb627b731) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/core/certificateerror/tst_certificateerror.cpp | 2 +- tests/auto/core/devtools/tst_devtools.cpp | 2 +- .../auto/core/getdomainandregistry/tst_getdomainandregistry.cpp | 2 +- tests/auto/core/origins/tst_origins.cpp | 2 +- tests/auto/core/qtversion/tst_qtversion.cpp | 2 +- .../tst_qwebengineclientcertificatestore.cpp | 2 +- .../core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp | 2 +- .../qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp | 2 +- .../core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp | 2 +- .../tst_qwebengineurlrequestinterceptor.cpp | 2 +- .../qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp | 2 +- tests/auto/core/webenginedriver/browser/main.cpp | 2 +- tests/auto/core/webenginedriver/tst_webenginedriver.cpp | 2 +- tests/auto/httpserver/httpreqrep.cpp | 2 +- tests/auto/httpserver/httpreqrep.h | 2 +- tests/auto/httpserver/httpserver.cpp | 2 +- tests/auto/httpserver/httpserver.h | 2 +- tests/auto/httpserver/httpsserver.h | 2 +- tests/auto/httpserver/proxy_server.cpp | 2 +- tests/auto/httpserver/proxy_server.h | 2 +- tests/auto/pdf/qpdfbookmarkmodel/tst_qpdfbookmarkmodel.cpp | 2 +- tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp | 2 +- tests/auto/pdf/qpdfpagenavigator/tst_qpdfpagenavigator.cpp | 2 +- tests/auto/pdf/qpdfpagerenderer/tst_qpdfpagerenderer.cpp | 2 +- tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp | 2 +- tests/auto/pdfquick/multipageview/tst_multipageview.cpp | 2 +- tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp | 2 +- tests/auto/pdfquick/shared/util.cpp | 2 +- tests/auto/pdfquick/shared/util.h | 2 +- tests/auto/quick/dialogs/WebView.qml | 2 +- tests/auto/quick/dialogs/testhandler.cpp | 2 +- tests/auto/quick/dialogs/testhandler.h | 2 +- tests/auto/quick/dialogs/tst_dialogs.cpp | 2 +- tests/auto/quick/inspectorserver/tst_inspectorserver.cpp | 2 +- tests/auto/quick/publicapi/tst_publicapi.cpp | 2 +- tests/auto/quick/qmltests/data/TestWebEngineView.qml | 2 +- tests/auto/quick/qmltests/data/titleupdate.js | 2 +- tests/auto/quick/qmltests/data/tst_action.qml | 2 +- tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml | 2 +- tests/auto/quick/qmltests/data/tst_audioMuted.qml | 2 +- tests/auto/quick/qmltests/data/tst_basicProfiles.qml | 2 +- tests/auto/quick/qmltests/data/tst_certificateError.qml | 2 +- tests/auto/quick/qmltests/data/tst_contextMenu.qml | 2 +- tests/auto/quick/qmltests/data/tst_datalist.qml | 2 +- tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml | 2 +- tests/auto/quick/qmltests/data/tst_download.qml | 2 +- tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml | 2 +- tests/auto/quick/qmltests/data/tst_favicon.qml | 2 +- tests/auto/quick/qmltests/data/tst_faviconDatabase.qml | 2 +- tests/auto/quick/qmltests/data/tst_filePicker.qml | 2 +- tests/auto/quick/qmltests/data/tst_filesystem.qml | 2 +- tests/auto/quick/qmltests/data/tst_findText.qml | 2 +- tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml | 2 +- tests/auto/quick/qmltests/data/tst_geopermission.qml | 2 +- tests/auto/quick/qmltests/data/tst_getUserMedia.qml | 2 +- tests/auto/quick/qmltests/data/tst_inputMethod.qml | 2 +- tests/auto/quick/qmltests/data/tst_inputTextDirection.qml | 2 +- tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml | 2 +- tests/auto/quick/qmltests/data/tst_keyboardEvents.qml | 2 +- tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml | 2 +- tests/auto/quick/qmltests/data/tst_linkHovered.qml | 2 +- tests/auto/quick/qmltests/data/tst_loadFail.qml | 2 +- tests/auto/quick/qmltests/data/tst_loadHtml.qml | 2 +- tests/auto/quick/qmltests/data/tst_loadProgress.qml | 2 +- tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml | 2 +- tests/auto/quick/qmltests/data/tst_loadUrl.qml | 2 +- tests/auto/quick/qmltests/data/tst_mouseClick.qml | 2 +- tests/auto/quick/qmltests/data/tst_mouseMove.qml | 2 +- tests/auto/quick/qmltests/data/tst_navigationHistory.qml | 2 +- tests/auto/quick/qmltests/data/tst_navigationRequested.qml | 2 +- tests/auto/quick/qmltests/data/tst_newViewRequest.qml | 2 +- tests/auto/quick/qmltests/data/tst_notification.qml | 2 +- tests/auto/quick/qmltests/data/tst_properties.qml | 2 +- tests/auto/quick/qmltests/data/tst_runJavaScript.qml | 2 +- tests/auto/quick/qmltests/data/tst_scrollPosition.qml | 2 +- tests/auto/quick/qmltests/data/tst_settings.qml | 2 +- tests/auto/quick/qmltests/data/tst_titleChanged.qml | 2 +- .../quick/qmltests/data/tst_unhandledKeyEventPropagation.qml | 2 +- tests/auto/quick/qmltests/data/tst_userScriptCollection.qml | 2 +- tests/auto/quick/qmltests/data/tst_userScripts.qml | 2 +- tests/auto/quick/qmltests/data/tst_viewSource.qml | 2 +- tests/auto/quick/qmltests/data/tst_webchannel.qml | 2 +- .../QtWebEngine/ControlsDelegates/AlertDialog.qml | 2 +- .../QtWebEngine/ControlsDelegates/ConfirmDialog.qml | 2 +- .../QtWebEngine/ControlsDelegates/DirectoryPicker.qml | 2 +- .../mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml | 2 +- .../mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml | 2 +- .../mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml | 2 +- .../QtWebEngine/ControlsDelegates/PromptDialog.qml | 2 +- .../qmltests/mock-delegates/TestParams/FilePickerParams.qml | 2 +- .../quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml | 2 +- .../quick/qmltests/mock-delegates/TestParams/MenuParams.qml | 2 +- tests/auto/quick/qmltests/tst_qmltests.cpp | 2 +- .../tst_qquickwebenginedefaultsurfaceformat.cpp | 2 +- .../auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp | 2 +- .../tst_qquickwebengineviewgraphics.cpp | 2 +- tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp | 2 +- tests/auto/quick/uidelegates/tst_uidelegates.cpp | 2 +- tests/auto/util/qt_webengine_quicktest.h | 2 +- tests/auto/util/quickutil.h | 2 +- tests/auto/util/testwindow.h | 2 +- tests/auto/util/util.h | 2 +- tests/auto/util/widgetutil.h | 2 +- .../widgets/defaultsurfaceformat/tst_defaultsurfaceformat.cpp | 2 +- tests/auto/widgets/favicon/tst_favicon.cpp | 2 +- tests/auto/widgets/loadsignals/tst_loadsignals.cpp | 2 +- tests/auto/widgets/offscreen/tst_offscreen.cpp | 2 +- tests/auto/widgets/printing/tst_printing.cpp | 2 +- tests/auto/widgets/proxy/tst_proxy.cpp | 2 +- tests/auto/widgets/proxypac/proxyserver.cpp | 2 +- tests/auto/widgets/proxypac/proxyserver.h | 2 +- tests/auto/widgets/proxypac/tst_proxypac.cpp | 2 +- tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp | 2 +- .../qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp | 2 +- tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp | 2 +- tests/auto/widgets/schemes/tst_schemes.cpp | 2 +- tests/auto/widgets/shutdown/tst_shutdown.cpp | 2 +- tests/auto/widgets/spellchecking/tst_spellchecking.cpp | 2 +- tests/auto/widgets/touchinput/tst_touchinput.cpp | 2 +- tests/manual/quick/geopermission/main.cpp | 2 +- tests/manual/quick/geopermission/tst_geopermission.qml | 2 +- tests/manual/quick/pdf/bookmarks-list.qml | 2 +- tests/manual/quick/pdf/bookmarks.qml | 2 +- tests/manual/quick/pdf/gridview.qml | 2 +- tests/manual/quick/pdf/listview.qml | 2 +- tests/manual/quick/pdf/multipleDocuments.qml | 2 +- tests/manual/quick/pdf/pdfPageView.qml | 2 +- tests/manual/quick/pdf/pessimizedListView.qml | 2 +- tests/manual/quick/pdf/simplest.qml | 2 +- tests/manual/quick/pdf/underscoredLinks.qml | 2 +- tests/manual/quick/pdf/withdoc.qml | 2 +- tests/manual/quick/touchbrowser/AddressBar.qml | 2 +- tests/manual/quick/touchbrowser/MockTouchPoint.qml | 2 +- tests/manual/quick/touchbrowser/main.cpp | 2 +- tests/manual/quick/touchbrowser/main.qml | 2 +- tests/manual/touchmocking/touchmockingapplication.cpp | 2 +- tests/manual/touchmocking/touchmockingapplication.h | 2 +- tests/manual/touchmocking/utils.h | 2 +- tests/manual/widgets/geolocation/main.cpp | 2 +- tests/manual/widgets/inputmethods/colorpicker.cpp | 2 +- tests/manual/widgets/inputmethods/colorpicker.h | 2 +- tests/manual/widgets/inputmethods/controlview.cpp | 2 +- tests/manual/widgets/inputmethods/controlview.h | 2 +- tests/manual/widgets/inputmethods/main.cpp | 2 +- tests/manual/widgets/inputmethods/referenceview.cpp | 2 +- tests/manual/widgets/inputmethods/referenceview.h | 2 +- tests/manual/widgets/inputmethods/testview.cpp | 2 +- tests/manual/widgets/inputmethods/testview.h | 2 +- tests/manual/widgets/inputmethods/webview.cpp | 2 +- tests/manual/widgets/inputmethods/webview.h | 2 +- tests/manual/widgets/touchbrowser/main.cpp | 2 +- tests/manual/widgets/webgl/main.cpp | 2 +- tests/manual/widgets/webrtc/main.cpp | 2 +- 153 files changed, 153 insertions(+), 153 deletions(-) diff --git a/tests/auto/core/certificateerror/tst_certificateerror.cpp b/tests/auto/core/certificateerror/tst_certificateerror.cpp index 61201e250bf..252e1544d64 100644 --- a/tests/auto/core/certificateerror/tst_certificateerror.cpp +++ b/tests/auto/core/certificateerror/tst_certificateerror.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/devtools/tst_devtools.cpp b/tests/auto/core/devtools/tst_devtools.cpp index 57a2b83a357..7284f0d51e5 100644 --- a/tests/auto/core/devtools/tst_devtools.cpp +++ b/tests/auto/core/devtools/tst_devtools.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/core/getdomainandregistry/tst_getdomainandregistry.cpp b/tests/auto/core/getdomainandregistry/tst_getdomainandregistry.cpp index e9e0bf105d0..f5b8910e8d2 100644 --- a/tests/auto/core/getdomainandregistry/tst_getdomainandregistry.cpp +++ b/tests/auto/core/getdomainandregistry/tst_getdomainandregistry.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/origins/tst_origins.cpp b/tests/auto/core/origins/tst_origins.cpp index 81385701f74..06af1123e2a 100644 --- a/tests/auto/core/origins/tst_origins.cpp +++ b/tests/auto/core/origins/tst_origins.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include "httpserver.h" diff --git a/tests/auto/core/qtversion/tst_qtversion.cpp b/tests/auto/core/qtversion/tst_qtversion.cpp index 44c2d4e5c90..66df04412c4 100644 --- a/tests/auto/core/qtversion/tst_qtversion.cpp +++ b/tests/auto/core/qtversion/tst_qtversion.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp index 7d82a56405f..d203ab130b3 100644 --- a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp +++ b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp index 3fff2cd459c..a75002ae51c 100644 --- a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp +++ b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp index 5b6b64778d2..3e46a823e2a 100644 --- a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp +++ b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp b/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp index ccae7436bdd..010932ea093 100644 --- a/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp +++ b/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index 7cea14c0cc9..c84de3599f8 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses diff --git a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp index d92aad5c4bd..acddfb0e021 100644 --- a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp +++ b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/webenginedriver/browser/main.cpp b/tests/auto/core/webenginedriver/browser/main.cpp index 4b8f3513fe2..b43b06f2e59 100644 --- a/tests/auto/core/webenginedriver/browser/main.cpp +++ b/tests/auto/core/webenginedriver/browser/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/core/webenginedriver/tst_webenginedriver.cpp b/tests/auto/core/webenginedriver/tst_webenginedriver.cpp index cd3098b25cb..66e14e68307 100644 --- a/tests/auto/core/webenginedriver/tst_webenginedriver.cpp +++ b/tests/auto/core/webenginedriver/tst_webenginedriver.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/httpserver/httpreqrep.cpp b/tests/auto/httpserver/httpreqrep.cpp index 8b338ce4eb5..65a1df36559 100644 --- a/tests/auto/httpserver/httpreqrep.cpp +++ b/tests/auto/httpserver/httpreqrep.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "httpreqrep.h" HttpReqRep::HttpReqRep(QTcpSocket *socket, QObject *parent) diff --git a/tests/auto/httpserver/httpreqrep.h b/tests/auto/httpserver/httpreqrep.h index 774c08eb126..2b90b774b16 100644 --- a/tests/auto/httpserver/httpreqrep.h +++ b/tests/auto/httpserver/httpreqrep.h @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef HTTPREQREP_H #define HTTPREQREP_H diff --git a/tests/auto/httpserver/httpserver.cpp b/tests/auto/httpserver/httpserver.cpp index e08af77e773..8a1d8e6f685 100644 --- a/tests/auto/httpserver/httpserver.cpp +++ b/tests/auto/httpserver/httpserver.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "httpserver.h" #include diff --git a/tests/auto/httpserver/httpserver.h b/tests/auto/httpserver/httpserver.h index 201eef4c6f5..a1c2e3791f0 100644 --- a/tests/auto/httpserver/httpserver.h +++ b/tests/auto/httpserver/httpserver.h @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef HTTPSERVER_H #define HTTPSERVER_H diff --git a/tests/auto/httpserver/httpsserver.h b/tests/auto/httpserver/httpsserver.h index d029851aa8d..237314965db 100644 --- a/tests/auto/httpserver/httpsserver.h +++ b/tests/auto/httpserver/httpsserver.h @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef HTTPSSERVER_H #define HTTPSSERVER_H diff --git a/tests/auto/httpserver/proxy_server.cpp b/tests/auto/httpserver/proxy_server.cpp index 3384153118d..e47214ee43f 100644 --- a/tests/auto/httpserver/proxy_server.cpp +++ b/tests/auto/httpserver/proxy_server.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "proxy_server.h" #include diff --git a/tests/auto/httpserver/proxy_server.h b/tests/auto/httpserver/proxy_server.h index 6be0c4e1ab1..8f7cd4cc6c2 100644 --- a/tests/auto/httpserver/proxy_server.h +++ b/tests/auto/httpserver/proxy_server.h @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef PROXY_SERVER_H #define PROXY_SERVER_H diff --git a/tests/auto/pdf/qpdfbookmarkmodel/tst_qpdfbookmarkmodel.cpp b/tests/auto/pdf/qpdfbookmarkmodel/tst_qpdfbookmarkmodel.cpp index a1804e17954..7c9216534ae 100644 --- a/tests/auto/pdf/qpdfbookmarkmodel/tst_qpdfbookmarkmodel.cpp +++ b/tests/auto/pdf/qpdfbookmarkmodel/tst_qpdfbookmarkmodel.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp index d222bff0cd2..45d1d5a7b01 100644 --- a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp +++ b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/pdf/qpdfpagenavigator/tst_qpdfpagenavigator.cpp b/tests/auto/pdf/qpdfpagenavigator/tst_qpdfpagenavigator.cpp index 327a9f36a57..4044757660e 100644 --- a/tests/auto/pdf/qpdfpagenavigator/tst_qpdfpagenavigator.cpp +++ b/tests/auto/pdf/qpdfpagenavigator/tst_qpdfpagenavigator.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/pdf/qpdfpagerenderer/tst_qpdfpagerenderer.cpp b/tests/auto/pdf/qpdfpagerenderer/tst_qpdfpagerenderer.cpp index 39d32df0b72..ca14338cc14 100644 --- a/tests/auto/pdf/qpdfpagerenderer/tst_qpdfpagerenderer.cpp +++ b/tests/auto/pdf/qpdfpagerenderer/tst_qpdfpagerenderer.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp b/tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp index cf71b148e04..f5e946d1945 100644 --- a/tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp +++ b/tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/pdfquick/multipageview/tst_multipageview.cpp b/tests/auto/pdfquick/multipageview/tst_multipageview.cpp index c5e0b30dbba..71c09077c36 100644 --- a/tests/auto/pdfquick/multipageview/tst_multipageview.cpp +++ b/tests/auto/pdfquick/multipageview/tst_multipageview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp b/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp index d2c9c8709f6..3f98025fa71 100644 --- a/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp +++ b/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/pdfquick/shared/util.cpp b/tests/auto/pdfquick/shared/util.cpp index c540ebfa66e..1bf9b45b764 100644 --- a/tests/auto/pdfquick/shared/util.cpp +++ b/tests/auto/pdfquick/shared/util.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "util.h" #include diff --git a/tests/auto/pdfquick/shared/util.h b/tests/auto/pdfquick/shared/util.h index 9ceb711afe8..2788e6104a6 100644 --- a/tests/auto/pdfquick/shared/util.h +++ b/tests/auto/pdfquick/shared/util.h @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QUICK_VISUAL_TEST_UTIL_H #define QUICK_VISUAL_TEST_UTIL_H diff --git a/tests/auto/quick/dialogs/WebView.qml b/tests/auto/quick/dialogs/WebView.qml index 45fafb42d1c..6db0e5777b6 100644 --- a/tests/auto/quick/dialogs/WebView.qml +++ b/tests/auto/quick/dialogs/WebView.qml @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtWebEngine diff --git a/tests/auto/quick/dialogs/testhandler.cpp b/tests/auto/quick/dialogs/testhandler.cpp index f4585263075..0596626f1fa 100644 --- a/tests/auto/quick/dialogs/testhandler.cpp +++ b/tests/auto/quick/dialogs/testhandler.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testhandler.h" diff --git a/tests/auto/quick/dialogs/testhandler.h b/tests/auto/quick/dialogs/testhandler.h index c72e8184119..fef41d075f3 100644 --- a/tests/auto/quick/dialogs/testhandler.h +++ b/tests/auto/quick/dialogs/testhandler.h @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef TESTHANDLER_H #define TESTHANDLER_H diff --git a/tests/auto/quick/dialogs/tst_dialogs.cpp b/tests/auto/quick/dialogs/tst_dialogs.cpp index 2b861efa62a..6f54019c7ff 100644 --- a/tests/auto/quick/dialogs/tst_dialogs.cpp +++ b/tests/auto/quick/dialogs/tst_dialogs.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testhandler.h" #include diff --git a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp index a9638bee471..32683ad1df5 100644 --- a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp +++ b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 45501cd6099..f27515c51c3 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml index 415985471d8..aefeb9af56d 100644 --- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml +++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/titleupdate.js b/tests/auto/quick/qmltests/data/titleupdate.js index 720e836761f..94bfd90dfd9 100644 --- a/tests/auto/quick/qmltests/data/titleupdate.js +++ b/tests/auto/quick/qmltests/data/titleupdate.js @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only function updateTitle() { diff --git a/tests/auto/quick/qmltests/data/tst_action.qml b/tests/auto/quick/qmltests/data/tst_action.qml index 9e49c2dbfe1..52891197dbb 100644 --- a/tests/auto/quick/qmltests/data/tst_action.qml +++ b/tests/auto/quick/qmltests/data/tst_action.qml @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml index 77968f6b637..d9ca1e8e66f 100644 --- a/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml +++ b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_audioMuted.qml b/tests/auto/quick/qmltests/data/tst_audioMuted.qml index 85f813f0c28..11527f8480c 100644 --- a/tests/auto/quick/qmltests/data/tst_audioMuted.qml +++ b/tests/auto/quick/qmltests/data/tst_audioMuted.qml @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_basicProfiles.qml b/tests/auto/quick/qmltests/data/tst_basicProfiles.qml index 97a25cdd87e..11d631344b9 100644 --- a/tests/auto/quick/qmltests/data/tst_basicProfiles.qml +++ b/tests/auto/quick/qmltests/data/tst_basicProfiles.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_certificateError.qml b/tests/auto/quick/qmltests/data/tst_certificateError.qml index 220ef9ac832..6c8e680e046 100644 --- a/tests/auto/quick/qmltests/data/tst_certificateError.qml +++ b/tests/auto/quick/qmltests/data/tst_certificateError.qml @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_contextMenu.qml b/tests/auto/quick/qmltests/data/tst_contextMenu.qml index 58e27b8ba6d..9a34d3f339f 100644 --- a/tests/auto/quick/qmltests/data/tst_contextMenu.qml +++ b/tests/auto/quick/qmltests/data/tst_contextMenu.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_datalist.qml b/tests/auto/quick/qmltests/data/tst_datalist.qml index 1e5a7ad6b86..9e4d766ef42 100644 --- a/tests/auto/quick/qmltests/data/tst_datalist.qml +++ b/tests/auto/quick/qmltests/data/tst_datalist.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml b/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml index 6cb2841ec8c..5e2dd19c255 100644 --- a/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml +++ b/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_download.qml b/tests/auto/quick/qmltests/data/tst_download.qml index 61a363c3972..a0cb8970b48 100644 --- a/tests/auto/quick/qmltests/data/tst_download.qml +++ b/tests/auto/quick/qmltests/data/tst_download.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml b/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml index c22bd44c285..35332b4e42a 100644 --- a/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml +++ b/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index 15f116e5db3..fcc24dfb7de 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml index 28439061920..c1679000107 100644 --- a/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml +++ b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_filePicker.qml b/tests/auto/quick/qmltests/data/tst_filePicker.qml index a7b59b2e9bb..8c769a04291 100644 --- a/tests/auto/quick/qmltests/data/tst_filePicker.qml +++ b/tests/auto/quick/qmltests/data/tst_filePicker.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_filesystem.qml b/tests/auto/quick/qmltests/data/tst_filesystem.qml index fa0da4457b9..5ed05b419dd 100644 --- a/tests/auto/quick/qmltests/data/tst_filesystem.qml +++ b/tests/auto/quick/qmltests/data/tst_filesystem.qml @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml index 597cff73e97..bd2bfbb480b 100644 --- a/tests/auto/quick/qmltests/data/tst_findText.qml +++ b/tests/auto/quick/qmltests/data/tst_findText.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml index f070e4bc5ed..b440e572099 100644 --- a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml +++ b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_geopermission.qml b/tests/auto/quick/qmltests/data/tst_geopermission.qml index e425a82c742..1eb68749738 100644 --- a/tests/auto/quick/qmltests/data/tst_geopermission.qml +++ b/tests/auto/quick/qmltests/data/tst_geopermission.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml index 9a876778b37..fbc863a45f6 100644 --- a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml +++ b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_inputMethod.qml b/tests/auto/quick/qmltests/data/tst_inputMethod.qml index cf79e8a4d89..d8ed8e55e90 100644 --- a/tests/auto/quick/qmltests/data/tst_inputMethod.qml +++ b/tests/auto/quick/qmltests/data/tst_inputMethod.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_inputTextDirection.qml b/tests/auto/quick/qmltests/data/tst_inputTextDirection.qml index 2141db4c80a..52675983a6b 100644 --- a/tests/auto/quick/qmltests/data/tst_inputTextDirection.qml +++ b/tests/auto/quick/qmltests/data/tst_inputTextDirection.qml @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml index 6e91b2e7742..49ba5ae471c 100644 --- a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml +++ b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml @@ -1,5 +1,5 @@ // Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml index 0f69a7e81a7..6a67b698316 100644 --- a/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml +++ b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml index d0bc75619b4..33be0329a2e 100644 --- a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml +++ b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_linkHovered.qml b/tests/auto/quick/qmltests/data/tst_linkHovered.qml index a11bd2450bd..593beb7356a 100644 --- a/tests/auto/quick/qmltests/data/tst_linkHovered.qml +++ b/tests/auto/quick/qmltests/data/tst_linkHovered.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_loadFail.qml b/tests/auto/quick/qmltests/data/tst_loadFail.qml index 8e9224bbf92..b6d3419f7c6 100644 --- a/tests/auto/quick/qmltests/data/tst_loadFail.qml +++ b/tests/auto/quick/qmltests/data/tst_loadFail.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_loadHtml.qml b/tests/auto/quick/qmltests/data/tst_loadHtml.qml index 8f94cd4a27d..db2035842e9 100644 --- a/tests/auto/quick/qmltests/data/tst_loadHtml.qml +++ b/tests/auto/quick/qmltests/data/tst_loadHtml.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_loadProgress.qml b/tests/auto/quick/qmltests/data/tst_loadProgress.qml index 2c06a02070f..30995d276ad 100644 --- a/tests/auto/quick/qmltests/data/tst_loadProgress.qml +++ b/tests/auto/quick/qmltests/data/tst_loadProgress.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml index c0eb5932b91..d6e6e108aaa 100644 --- a/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml +++ b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml index 25a62c8787c..757343703c5 100644 --- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml +++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_mouseClick.qml b/tests/auto/quick/qmltests/data/tst_mouseClick.qml index c0c6a696798..cc06416c171 100644 --- a/tests/auto/quick/qmltests/data/tst_mouseClick.qml +++ b/tests/auto/quick/qmltests/data/tst_mouseClick.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_mouseMove.qml b/tests/auto/quick/qmltests/data/tst_mouseMove.qml index 5ded24c57c5..6ee58fcb030 100644 --- a/tests/auto/quick/qmltests/data/tst_mouseMove.qml +++ b/tests/auto/quick/qmltests/data/tst_mouseMove.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml index 2ea76c3872a..54d2ffd4bcc 100644 --- a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml +++ b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml index 31c0cf44e31..785cfa27abd 100644 --- a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml +++ b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml index 68350d10737..67142677144 100644 --- a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml +++ b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_notification.qml b/tests/auto/quick/qmltests/data/tst_notification.qml index 5defbff4b6f..4f064af3d3c 100644 --- a/tests/auto/quick/qmltests/data/tst_notification.qml +++ b/tests/auto/quick/qmltests/data/tst_notification.qml @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_properties.qml b/tests/auto/quick/qmltests/data/tst_properties.qml index 13d40ed116d..e3d6ed6254f 100644 --- a/tests/auto/quick/qmltests/data/tst_properties.qml +++ b/tests/auto/quick/qmltests/data/tst_properties.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml index f16cd9c419f..542a3aac697 100644 --- a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml +++ b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_scrollPosition.qml b/tests/auto/quick/qmltests/data/tst_scrollPosition.qml index cc7d15e4c77..e90f879139d 100644 --- a/tests/auto/quick/qmltests/data/tst_scrollPosition.qml +++ b/tests/auto/quick/qmltests/data/tst_scrollPosition.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_settings.qml b/tests/auto/quick/qmltests/data/tst_settings.qml index f47674aa7fa..4cd0bf6a7a2 100644 --- a/tests/auto/quick/qmltests/data/tst_settings.qml +++ b/tests/auto/quick/qmltests/data/tst_settings.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_titleChanged.qml b/tests/auto/quick/qmltests/data/tst_titleChanged.qml index 66a7c115f79..16dafa5932d 100644 --- a/tests/auto/quick/qmltests/data/tst_titleChanged.qml +++ b/tests/auto/quick/qmltests/data/tst_titleChanged.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml index 76363fa7113..75d0d38d9ac 100644 --- a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml +++ b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_userScriptCollection.qml b/tests/auto/quick/qmltests/data/tst_userScriptCollection.qml index 94c9937715e..fbf4f083332 100644 --- a/tests/auto/quick/qmltests/data/tst_userScriptCollection.qml +++ b/tests/auto/quick/qmltests/data/tst_userScriptCollection.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml index 30704f47b4f..a64de389d8e 100644 --- a/tests/auto/quick/qmltests/data/tst_userScripts.qml +++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml index d4449f7de55..a79de3e3a2d 100644 --- a/tests/auto/quick/qmltests/data/tst_viewSource.qml +++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/data/tst_webchannel.qml b/tests/auto/quick/qmltests/data/tst_webchannel.qml index 780b559341b..0000a212557 100644 --- a/tests/auto/quick/qmltests/data/tst_webchannel.qml +++ b/tests/auto/quick/qmltests/data/tst_webchannel.qml @@ -1,5 +1,5 @@ // Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/AlertDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/AlertDialog.qml index 7d7efda0c0c..424c3fdb26a 100644 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/AlertDialog.qml +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/AlertDialog.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only // Both dialogs are basically expected to behave in the same way from an API point of view ConfirmDialog { } diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/ConfirmDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/ConfirmDialog.qml index 6125d0b9862..db7c2d05aa0 100644 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/ConfirmDialog.qml +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/ConfirmDialog.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQml import QtTest diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/DirectoryPicker.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/DirectoryPicker.qml index 71da28843fc..da423e44128 100644 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/DirectoryPicker.qml +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/DirectoryPicker.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import "../../TestParams" diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml index 247088bcba6..6dac9973e17 100644 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import "../../TestParams" diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml index cd7ed48211c..35e3b274f94 100644 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQml import "../../TestParams" diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml index 67dab1bba40..8d3a2df5153 100644 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQml diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/PromptDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/PromptDialog.qml index 81a63d91843..62e48906751 100644 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/PromptDialog.qml +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/PromptDialog.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQml import QtTest diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml b/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml index 67d67dc4039..342933365d6 100644 --- a/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml +++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only pragma Singleton import QtQuick diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml b/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml index 1033b509efc..4f983119721 100644 --- a/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml +++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only pragma Singleton import QtQml diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/MenuParams.qml b/tests/auto/quick/qmltests/mock-delegates/TestParams/MenuParams.qml index d8a01764c90..8b6bcb28587 100644 --- a/tests/auto/quick/qmltests/mock-delegates/TestParams/MenuParams.qml +++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/MenuParams.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only pragma Singleton import QtQml diff --git a/tests/auto/quick/qmltests/tst_qmltests.cpp b/tests/auto/quick/qmltests/tst_qmltests.cpp index 9e928157e9f..01a657e8b44 100644 --- a/tests/auto/quick/qmltests/tst_qmltests.cpp +++ b/tests/auto/quick/qmltests/tst_qmltests.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp index b4c95d67126..64c1cfaa4ec 100644 --- a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp +++ b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testwindow.h" #include "quickutil.h" diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index cc514f87379..abe5e1f3da5 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses diff --git a/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp b/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp index 3644ac48187..b7cc8e7deb7 100644 --- a/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp +++ b/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp b/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp index cf5c187c35c..1cf62e80086 100644 --- a/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp +++ b/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qtwebenginequickglobal.h" #include diff --git a/tests/auto/quick/uidelegates/tst_uidelegates.cpp b/tests/auto/quick/uidelegates/tst_uidelegates.cpp index fb8734f83a7..1c3024d949f 100644 --- a/tests/auto/quick/uidelegates/tst_uidelegates.cpp +++ b/tests/auto/quick/uidelegates/tst_uidelegates.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testwindow.h" #include "quickutil.h" diff --git a/tests/auto/util/qt_webengine_quicktest.h b/tests/auto/util/qt_webengine_quicktest.h index bd98693de1f..4d68f90f0e8 100644 --- a/tests/auto/util/qt_webengine_quicktest.h +++ b/tests/auto/util/qt_webengine_quicktest.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QT_WEBENGINE_QUICKTEST_H #define QT_WEBENGINE_QUICKTEST_H diff --git a/tests/auto/util/quickutil.h b/tests/auto/util/quickutil.h index 687cb94dc85..c3542478f18 100644 --- a/tests/auto/util/quickutil.h +++ b/tests/auto/util/quickutil.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef UTIL_H #define UTIL_H diff --git a/tests/auto/util/testwindow.h b/tests/auto/util/testwindow.h index f9ffd381afd..dfce32b43fd 100644 --- a/tests/auto/util/testwindow.h +++ b/tests/auto/util/testwindow.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef TESTWINDOW_H #define TESTWINDOW_H diff --git a/tests/auto/util/util.h b/tests/auto/util/util.h index 5533eed80a8..eab5fa91359 100644 --- a/tests/auto/util/util.h +++ b/tests/auto/util/util.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only // Functions and macros that really need to be in QTestLib diff --git a/tests/auto/util/widgetutil.h b/tests/auto/util/widgetutil.h index 67d09ee4f43..b673a811f88 100644 --- a/tests/auto/util/widgetutil.h +++ b/tests/auto/util/widgetutil.h @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only // Functions and macros that really need to be in QTestLib diff --git a/tests/auto/widgets/defaultsurfaceformat/tst_defaultsurfaceformat.cpp b/tests/auto/widgets/defaultsurfaceformat/tst_defaultsurfaceformat.cpp index c53f6f5b324..3fdba71c2f0 100644 --- a/tests/auto/widgets/defaultsurfaceformat/tst_defaultsurfaceformat.cpp +++ b/tests/auto/widgets/defaultsurfaceformat/tst_defaultsurfaceformat.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/widgets/favicon/tst_favicon.cpp b/tests/auto/widgets/favicon/tst_favicon.cpp index c70aa1182a4..e4b5619a6fd 100644 --- a/tests/auto/widgets/favicon/tst_favicon.cpp +++ b/tests/auto/widgets/favicon/tst_favicon.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/widgets/loadsignals/tst_loadsignals.cpp b/tests/auto/widgets/loadsignals/tst_loadsignals.cpp index 6140b3766bd..b465f985823 100644 --- a/tests/auto/widgets/loadsignals/tst_loadsignals.cpp +++ b/tests/auto/widgets/loadsignals/tst_loadsignals.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/widgets/offscreen/tst_offscreen.cpp b/tests/auto/widgets/offscreen/tst_offscreen.cpp index 553dc653bc9..258178dd746 100644 --- a/tests/auto/widgets/offscreen/tst_offscreen.cpp +++ b/tests/auto/widgets/offscreen/tst_offscreen.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/widgets/printing/tst_printing.cpp b/tests/auto/widgets/printing/tst_printing.cpp index 605fb57b5c7..c9f6e8cfa92 100644 --- a/tests/auto/widgets/printing/tst_printing.cpp +++ b/tests/auto/widgets/printing/tst_printing.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/widgets/proxy/tst_proxy.cpp b/tests/auto/widgets/proxy/tst_proxy.cpp index 3dc72618c9b..c16b8cf5aac 100644 --- a/tests/auto/widgets/proxy/tst_proxy.cpp +++ b/tests/auto/widgets/proxy/tst_proxy.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "proxy_server.h" #include diff --git a/tests/auto/widgets/proxypac/proxyserver.cpp b/tests/auto/widgets/proxypac/proxyserver.cpp index f7a85974784..a7bbd6934f0 100644 --- a/tests/auto/widgets/proxypac/proxyserver.cpp +++ b/tests/auto/widgets/proxypac/proxyserver.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "proxyserver.h" #include diff --git a/tests/auto/widgets/proxypac/proxyserver.h b/tests/auto/widgets/proxypac/proxyserver.h index c95856da954..4d622175ec1 100644 --- a/tests/auto/widgets/proxypac/proxyserver.h +++ b/tests/auto/widgets/proxypac/proxyserver.h @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef PROXY_SERVER_H #define PROXY_SERVER_H diff --git a/tests/auto/widgets/proxypac/tst_proxypac.cpp b/tests/auto/widgets/proxypac/tst_proxypac.cpp index 43ccbf028a3..19654d1a963 100644 --- a/tests/auto/widgets/proxypac/tst_proxypac.cpp +++ b/tests/auto/widgets/proxypac/tst_proxypac.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "proxy_server.h" #include diff --git a/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp b/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp index 9453ae9b845..904d0849361 100644 --- a/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp +++ b/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp index c81a27b3aaf..a47bdbcc4d3 100644 --- a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp +++ b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 3cd400fdc64..5303d99fc6c 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/widgets/schemes/tst_schemes.cpp b/tests/auto/widgets/schemes/tst_schemes.cpp index 188c112e415..19bab06dafe 100644 --- a/tests/auto/widgets/schemes/tst_schemes.cpp +++ b/tests/auto/widgets/schemes/tst_schemes.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/widgets/shutdown/tst_shutdown.cpp b/tests/auto/widgets/shutdown/tst_shutdown.cpp index c2b31bb808f..88cbc6aa734 100644 --- a/tests/auto/widgets/shutdown/tst_shutdown.cpp +++ b/tests/auto/widgets/shutdown/tst_shutdown.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/auto/widgets/spellchecking/tst_spellchecking.cpp b/tests/auto/widgets/spellchecking/tst_spellchecking.cpp index c643a56bacb..f5525c9f151 100644 --- a/tests/auto/widgets/spellchecking/tst_spellchecking.cpp +++ b/tests/auto/widgets/spellchecking/tst_spellchecking.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/auto/widgets/touchinput/tst_touchinput.cpp b/tests/auto/widgets/touchinput/tst_touchinput.cpp index 42178558ccc..abc56a8e6cc 100644 --- a/tests/auto/widgets/touchinput/tst_touchinput.cpp +++ b/tests/auto/widgets/touchinput/tst_touchinput.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/manual/quick/geopermission/main.cpp b/tests/manual/quick/geopermission/main.cpp index e0ff6f3e7f3..b0e9a7eda9d 100644 --- a/tests/manual/quick/geopermission/main.cpp +++ b/tests/manual/quick/geopermission/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include diff --git a/tests/manual/quick/geopermission/tst_geopermission.qml b/tests/manual/quick/geopermission/tst_geopermission.qml index ace48d464d4..6d6f4de8bc8 100644 --- a/tests/manual/quick/geopermission/tst_geopermission.qml +++ b/tests/manual/quick/geopermission/tst_geopermission.qml @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtTest diff --git a/tests/manual/quick/pdf/bookmarks-list.qml b/tests/manual/quick/pdf/bookmarks-list.qml index 2be0d68484b..e0af43054e0 100644 --- a/tests/manual/quick/pdf/bookmarks-list.qml +++ b/tests/manual/quick/pdf/bookmarks-list.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import QtQuick.Dialogs diff --git a/tests/manual/quick/pdf/bookmarks.qml b/tests/manual/quick/pdf/bookmarks.qml index e12629b31ca..86ae4e34761 100644 --- a/tests/manual/quick/pdf/bookmarks.qml +++ b/tests/manual/quick/pdf/bookmarks.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import QtQuick.Dialogs diff --git a/tests/manual/quick/pdf/gridview.qml b/tests/manual/quick/pdf/gridview.qml index 773e72388db..69b85470d42 100644 --- a/tests/manual/quick/pdf/gridview.qml +++ b/tests/manual/quick/pdf/gridview.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Pdf diff --git a/tests/manual/quick/pdf/listview.qml b/tests/manual/quick/pdf/listview.qml index d01be9e86e3..1c997fdce7e 100644 --- a/tests/manual/quick/pdf/listview.qml +++ b/tests/manual/quick/pdf/listview.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Pdf diff --git a/tests/manual/quick/pdf/multipleDocuments.qml b/tests/manual/quick/pdf/multipleDocuments.qml index 055808ab60d..7826c9a8f84 100644 --- a/tests/manual/quick/pdf/multipleDocuments.qml +++ b/tests/manual/quick/pdf/multipleDocuments.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import QtQuick.Dialogs diff --git a/tests/manual/quick/pdf/pdfPageView.qml b/tests/manual/quick/pdf/pdfPageView.qml index 22c0d5ac238..edf3aa05bf9 100644 --- a/tests/manual/quick/pdf/pdfPageView.qml +++ b/tests/manual/quick/pdf/pdfPageView.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import QtQuick.Dialogs diff --git a/tests/manual/quick/pdf/pessimizedListView.qml b/tests/manual/quick/pdf/pessimizedListView.qml index 1b514668e62..6e1083fd3b2 100644 --- a/tests/manual/quick/pdf/pessimizedListView.qml +++ b/tests/manual/quick/pdf/pessimizedListView.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import QtQuick.Dialogs diff --git a/tests/manual/quick/pdf/simplest.qml b/tests/manual/quick/pdf/simplest.qml index 3f39bb21341..0736f38aee6 100644 --- a/tests/manual/quick/pdf/simplest.qml +++ b/tests/manual/quick/pdf/simplest.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick Image { diff --git a/tests/manual/quick/pdf/underscoredLinks.qml b/tests/manual/quick/pdf/underscoredLinks.qml index 514008ca26b..f23d9a5a1fc 100644 --- a/tests/manual/quick/pdf/underscoredLinks.qml +++ b/tests/manual/quick/pdf/underscoredLinks.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import QtQuick.Dialogs diff --git a/tests/manual/quick/pdf/withdoc.qml b/tests/manual/quick/pdf/withdoc.qml index c388e041edd..bcd1a9b5843 100644 --- a/tests/manual/quick/pdf/withdoc.qml +++ b/tests/manual/quick/pdf/withdoc.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls import QtQuick.Dialogs diff --git a/tests/manual/quick/touchbrowser/AddressBar.qml b/tests/manual/quick/touchbrowser/AddressBar.qml index 42188c94eac..36a83d87289 100644 --- a/tests/manual/quick/touchbrowser/AddressBar.qml +++ b/tests/manual/quick/touchbrowser/AddressBar.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/manual/quick/touchbrowser/MockTouchPoint.qml b/tests/manual/quick/touchbrowser/MockTouchPoint.qml index 895e12e70a6..8583d934fc3 100644 --- a/tests/manual/quick/touchbrowser/MockTouchPoint.qml +++ b/tests/manual/quick/touchbrowser/MockTouchPoint.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick Item { diff --git a/tests/manual/quick/touchbrowser/main.cpp b/tests/manual/quick/touchbrowser/main.cpp index 1f4d7d86900..7db3f40a169 100644 --- a/tests/manual/quick/touchbrowser/main.cpp +++ b/tests/manual/quick/touchbrowser/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "touchmockingapplication.h" #include "utils.h" diff --git a/tests/manual/quick/touchbrowser/main.qml b/tests/manual/quick/touchbrowser/main.qml index 83ede7d75b9..ed60b36e53e 100644 --- a/tests/manual/quick/touchbrowser/main.qml +++ b/tests/manual/quick/touchbrowser/main.qml @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Layouts diff --git a/tests/manual/touchmocking/touchmockingapplication.cpp b/tests/manual/touchmocking/touchmockingapplication.cpp index feedae5cd69..d1536466296 100644 --- a/tests/manual/touchmocking/touchmockingapplication.cpp +++ b/tests/manual/touchmocking/touchmockingapplication.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "touchmockingapplication.h" diff --git a/tests/manual/touchmocking/touchmockingapplication.h b/tests/manual/touchmocking/touchmockingapplication.h index 4f6e744fc65..e42159451af 100644 --- a/tests/manual/touchmocking/touchmockingapplication.h +++ b/tests/manual/touchmocking/touchmockingapplication.h @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef TOUCHMOCKINGAPPLICATION_H #define TOUCHMOCKINGAPPLICATION_H diff --git a/tests/manual/touchmocking/utils.h b/tests/manual/touchmocking/utils.h index 12d493d3f03..2e6fb1b0571 100644 --- a/tests/manual/touchmocking/utils.h +++ b/tests/manual/touchmocking/utils.h @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef UTILS_H #define UTILS_H diff --git a/tests/manual/widgets/geolocation/main.cpp b/tests/manual/widgets/geolocation/main.cpp index 1f4cefe54e4..9e471650b01 100644 --- a/tests/manual/widgets/geolocation/main.cpp +++ b/tests/manual/widgets/geolocation/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/manual/widgets/inputmethods/colorpicker.cpp b/tests/manual/widgets/inputmethods/colorpicker.cpp index cc0840bcd6c..6ea8e808607 100644 --- a/tests/manual/widgets/inputmethods/colorpicker.cpp +++ b/tests/manual/widgets/inputmethods/colorpicker.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "colorpicker.h" diff --git a/tests/manual/widgets/inputmethods/colorpicker.h b/tests/manual/widgets/inputmethods/colorpicker.h index 0b6b3257a5c..719aa93eb20 100644 --- a/tests/manual/widgets/inputmethods/colorpicker.h +++ b/tests/manual/widgets/inputmethods/colorpicker.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef COLORPICKER_H #define COLORPICKER_H diff --git a/tests/manual/widgets/inputmethods/controlview.cpp b/tests/manual/widgets/inputmethods/controlview.cpp index 86bf8cca967..85d7cfa0fe5 100644 --- a/tests/manual/widgets/inputmethods/controlview.cpp +++ b/tests/manual/widgets/inputmethods/controlview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "controlview.h" diff --git a/tests/manual/widgets/inputmethods/controlview.h b/tests/manual/widgets/inputmethods/controlview.h index caa08593ffd..c686adbec57 100644 --- a/tests/manual/widgets/inputmethods/controlview.h +++ b/tests/manual/widgets/inputmethods/controlview.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef CONTROLVIEW_H #define CONTROLVIEW_H diff --git a/tests/manual/widgets/inputmethods/main.cpp b/tests/manual/widgets/inputmethods/main.cpp index 2378e95aea7..4bba9f78208 100644 --- a/tests/manual/widgets/inputmethods/main.cpp +++ b/tests/manual/widgets/inputmethods/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/manual/widgets/inputmethods/referenceview.cpp b/tests/manual/widgets/inputmethods/referenceview.cpp index 27e784fbcd2..24957eaa954 100644 --- a/tests/manual/widgets/inputmethods/referenceview.cpp +++ b/tests/manual/widgets/inputmethods/referenceview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "referenceview.h" diff --git a/tests/manual/widgets/inputmethods/referenceview.h b/tests/manual/widgets/inputmethods/referenceview.h index d943a93d01c..62c43faeb5e 100644 --- a/tests/manual/widgets/inputmethods/referenceview.h +++ b/tests/manual/widgets/inputmethods/referenceview.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef REFERENCEVIEW_H #define REFERENCEVIEW_H diff --git a/tests/manual/widgets/inputmethods/testview.cpp b/tests/manual/widgets/inputmethods/testview.cpp index d57b22cc59c..e0e84d72b2a 100644 --- a/tests/manual/widgets/inputmethods/testview.cpp +++ b/tests/manual/widgets/inputmethods/testview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testview.h" diff --git a/tests/manual/widgets/inputmethods/testview.h b/tests/manual/widgets/inputmethods/testview.h index b99e60d75f3..5ba894bf3d9 100644 --- a/tests/manual/widgets/inputmethods/testview.h +++ b/tests/manual/widgets/inputmethods/testview.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef TESTVIEW_H #define TESTVIEW_H diff --git a/tests/manual/widgets/inputmethods/webview.cpp b/tests/manual/widgets/inputmethods/webview.cpp index 915d73a7f8f..febd05049cf 100644 --- a/tests/manual/widgets/inputmethods/webview.cpp +++ b/tests/manual/widgets/inputmethods/webview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "webview.h" #include diff --git a/tests/manual/widgets/inputmethods/webview.h b/tests/manual/widgets/inputmethods/webview.h index a46dcb2f625..ec5a295d1ed 100644 --- a/tests/manual/widgets/inputmethods/webview.h +++ b/tests/manual/widgets/inputmethods/webview.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef WEBVIEW_H #define WEBVIEW_H diff --git a/tests/manual/widgets/touchbrowser/main.cpp b/tests/manual/widgets/touchbrowser/main.cpp index 18baf79e89f..0aa3e791797 100644 --- a/tests/manual/widgets/touchbrowser/main.cpp +++ b/tests/manual/widgets/touchbrowser/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "touchmockingapplication.h" #include "utils.h" diff --git a/tests/manual/widgets/webgl/main.cpp b/tests/manual/widgets/webgl/main.cpp index 7037c34dba1..e9b4c285afc 100644 --- a/tests/manual/widgets/webgl/main.cpp +++ b/tests/manual/widgets/webgl/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include diff --git a/tests/manual/widgets/webrtc/main.cpp b/tests/manual/widgets/webrtc/main.cpp index b5718159c8b..c1742445a4c 100644 --- a/tests/manual/widgets/webrtc/main.cpp +++ b/tests/manual/widgets/webrtc/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include From 1eb8f906a5bb0cb3ed12ff8d65d595ac46b1fced Mon Sep 17 00:00:00 2001 From: Martin Negyokru Date: Fri, 21 Jun 2024 08:59:48 +0200 Subject: [PATCH 040/341] Ensure deferred deletion of WebEngineQuickWidget In some cases the event loop exits before WebEngineQuickWidget::deletLater is called. In this scenario the object will not be deleted. Fixes: QTBUG-126401 Pick-to: 6.7 6.6 Change-Id: I9de8640c6f8d3b0f04665bce664f8b91523ddb69 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Anu Aliyas (cherry picked from commit a9357c72535b5e99f75b03af560badbb90dfa6f1) Reviewed-by: Qt Cherry-pick Bot --- src/webenginewidgets/api/qwebengineview.cpp | 5 +++++ .../widgets/qwebengineview/tst_qwebengineview.cpp | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index ebb818cbd71..9dab3a45b22 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -141,6 +141,11 @@ class WebEngineQuickWidget : public QQuickWidget, public WidgetDelegate void Destroy() override { deleteLater(); + + // The event loop may be exited at this point. + // Ensure deferred deletion in this scenario. + if (QThread::currentThread()->loopLevel() == 0) + QCoreApplication::sendPostedEvents(this, QEvent::DeferredDelete); } bool ActiveFocusOnPress() override diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 03acd69feb6..3b481402e7e 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -189,6 +189,7 @@ private Q_SLOTS: void datalist(); void longKeyEventText(); void pageWithPaintListeners(); + void deferredDelete(); }; // This will be called before the first test function is executed. @@ -4006,5 +4007,19 @@ void tst_QWebEngineView::longKeyEventText() QTRY_VERIFY(consoleMessageSpy.size()); } +void tst_QWebEngineView::deferredDelete() +{ + { + QWebEngineView view; + QSignalSpy loadFinishedSpy(view.page(), &QWebEnginePage::loadFinished); + view.load(QUrl("chrome://qt")); + view.show(); + QTRY_VERIFY(loadFinishedSpy.size()); + QCOMPARE(QApplication::allWidgets().size(), 2); // QWebEngineView and WebEngineQuickWidget + } + + QCOMPARE(QApplication::allWidgets().size(), 0); +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" From 0b9a2c616ec824557f6bfb4c432750fd4dcd4af7 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 28 Jun 2024 19:04:04 +0000 Subject: [PATCH 041/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I53e55c11a577d389d6b8e2e91b44ca857027e258 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index a4a9f46a3b7..a2e94f244e2 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 8206b9b4b159c9a0244ff4f92d4c3bb8fad13c1c + ref: f67b8f68a951fdd5fd21ce95cf0be0668397d3f8 required: true ../qtpositioning: - ref: 5a12dc643d425e96d19f6a543f7c6c51a01aa857 + ref: a94950c0e9df7cd8bdeeff38e8826b6ee522eee8 required: false ../qttools: - ref: df2a2fc4c6b32ad6203a6c90222dd9051c2f1ba5 + ref: 71e84ea044451757f6590df211c18372661717c0 required: false ../qtwebchannel: - ref: 4579fb731a4954633e4398477896bbf6968c34bc + ref: 57aa7f5ae976f7bb4efebce011fcd0f8153bb158 required: false From eb4412f900262a564529adc6b20e1c4b443b2cda Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Fri, 28 Jun 2024 12:23:24 +0200 Subject: [PATCH 042/341] Doc: Increase warninglimit for doc builds to 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Technically the Qt WebEngine documentation builds without warnings, but testing in CI two warnings are observed: warning: Already generated qtwebengine-3rdparty-inspector-protocol.html for this project warning: Already generated qtwebengine-3rdparty-lit.html for this project These pages come from a qtattributionsscanner-generated source file, codeattributions.qdoc. The warnings do not affect the generated output. Increase the documentation warning limit temporarily to let integrations pass. Task-number: QTBUG-126546 Change-Id: I450c4ef4a03abdbf5ccbeab865468b302c92ee90 Reviewed-by: Topi Reiniö (cherry picked from commit 33f30724f0e3e50abf559a14340ded85d35480ca) Reviewed-by: Qt Cherry-pick Bot --- src/core/doc/qtwebengine.qdocconf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf index 6b78f13f8ce..89136314743 100644 --- a/src/core/doc/qtwebengine.qdocconf +++ b/src/core/doc/qtwebengine.qdocconf @@ -93,4 +93,4 @@ navigation.qmltypespage = "Qt WebEngine QML Types" macro.QWE = "Qt \\WebEngine" # Enforce zero documentation warnings -warninglimit = 0 +warninglimit = 2 From 537cbfb72459f0017a16eb7234f95bf9d82f72b7 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 26 Jun 2024 11:08:59 +0200 Subject: [PATCH 043/341] Fix QString and QChar deprecation warnings in web_engine_context.cpp Change-Id: Iba85d76a11a61ea36b05ee2069959f68dd5d9fc1 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 86ac0c32fe9a6bc25054840a08c4343d22e1d817) Reviewed-by: Qt Cherry-pick Bot --- src/core/web_engine_context.cpp | 113 ++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 49 deletions(-) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 74453d1992e..bf6a06ae5af 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -178,27 +178,27 @@ class GPUInfo if (it != vendorIdMap.end()) return it->second; - qWarning() << "Unknown Vendor ID:" << QString("0x%1").arg(vendorId, 0, 16); + qWarning() << "Unknown Vendor ID:" << QStringLiteral("0x%1").arg(vendorId, 0, 16); return Unknown; } - static Vendor deviceNameToVendor(QString deviceName) + static Vendor deviceNameToVendor(const QString &deviceName) { // TODO: Test and add more vendors to the list. - if (deviceName.contains(QLatin1String("AMD"), Qt::CaseInsensitive)) + if (deviceName.contains(QLatin1StringView("AMD"), Qt::CaseInsensitive)) return AMD; - if (deviceName.contains(QLatin1String("Intel"), Qt::CaseInsensitive)) + if (deviceName.contains(QLatin1StringView("Intel"), Qt::CaseInsensitive)) return Intel; - if (deviceName.contains(QLatin1String("Nvidia"), Qt::CaseInsensitive)) + if (deviceName.contains(QLatin1StringView("Nvidia"), Qt::CaseInsensitive)) return Nvidia; #if defined(USE_OZONE) - if (deviceName.contains(QLatin1String("Mesa llvmpipe"))) + if (deviceName.contains(QLatin1StringView("Mesa llvmpipe"))) return Mesa; #endif #if defined(Q_OS_MACOS) - if (deviceName.contains(QLatin1String("Apple"))) + if (deviceName.contains(QLatin1StringView("Apple"))) return Apple; #endif @@ -259,8 +259,8 @@ class GPUInfo const QRhiD3D11NativeHandles *handles = static_cast(d3d11Rhi->nativeHandles()); Q_ASSERT(handles); - m_adapterLuid = - QString("%1,%2").arg(handles->adapterLuidHigh).arg(handles->adapterLuidLow); + m_adapterLuid = QString::number(handles->adapterLuidHigh) % QLatin1Char(',') + % QString::number(handles->adapterLuidLow); } } #elif defined(Q_OS_MACOS) @@ -269,7 +269,7 @@ class GPUInfo QScopedPointer metalRhi( QRhi::create(QRhi::Metal, ¶ms, QRhi::Flags(), nullptr)); if (metalRhi) - m_vendor = deviceNameToVendor(metalRhi->driverInfo().deviceName); + m_vendor = deviceNameToVendor(QLatin1StringView(metalRhi->driverInfo().deviceName)); } #endif @@ -280,7 +280,7 @@ class GPUInfo QScopedPointer glRhi( QRhi::create(QRhi::OpenGLES2, ¶ms, QRhi::Flags(), nullptr)); if (glRhi) - m_vendor = deviceNameToVendor(glRhi->driverInfo().deviceName); + m_vendor = deviceNameToVendor(QLatin1StringView(glRhi->driverInfo().deviceName)); } #endif @@ -327,7 +327,7 @@ static bool usingSupportedSGBackend() QString device = QQuickWindow::sceneGraphBackend(); for (int index = 0; index < args.count(); ++index) { - if (args.at(index).startsWith(QLatin1String("--device="))) { + if (args.at(index).startsWith(QLatin1StringView("--device="))) { device = args.at(index).mid(9); break; } @@ -338,7 +338,7 @@ static bool usingSupportedSGBackend() if (device.isEmpty()) device = qEnvironmentVariable("QMLSCENE_DEVICE"); - return device.isEmpty() || device == QLatin1String("rhi"); + return device.isEmpty() || device == QLatin1StringView("rhi"); } #if QT_CONFIG(opengl) @@ -358,7 +358,7 @@ bool usingSoftwareDynamicGL() wchar_t path[MAX_PATH]; DWORD size = GetModuleFileName(handle, path, MAX_PATH); QFileInfo openGLModule(QString::fromWCharArray(path, size)); - return openGLModule.fileName().contains(QLatin1String("opengl32sw"),Qt::CaseInsensitive); + return openGLModule.fileName().contains(QLatin1StringView("opengl32sw"), Qt::CaseInsensitive); #else return false; #endif @@ -471,27 +471,41 @@ static void logContext(const std::string &glType, base::CommandLine *cmd) { if (Q_UNLIKELY(webEngineContextLog().isDebugEnabled())) { QStringList log; - log << "\n"; - - log << "Chromium GL Backend:" << glType.c_str() << "\n"; - log << "Chromium ANGLE Backend:" << getAngleType(glType, cmd).c_str() << "\n"; - log << "Chromium Vulkan Backend:" << getVulkanType(cmd).c_str() << "\n"; - log << "\n"; - - log << "QSG RHI Backend:" << QSGRhiSupport::instance()->rhiBackendName() << "\n"; - log << "QSG RHI Backend Supported:" << (usingSupportedSGBackend() ? "yes" : "no") << "\n"; - log << "GPU Vendor:" << GPUInfo::vendorToString(GPUInfo::instance()->vendor()).c_str(); - log << "\n"; + log << QLatin1StringView("\n"); + + log << QLatin1StringView("Chromium GL Backend: " + glType) << QLatin1StringView("\n"); + log << QLatin1StringView("Chromium ANGLE Backend: " + getAngleType(glType, cmd)) + << QLatin1StringView("\n"); + log << QLatin1StringView("Chromium Vulkan Backend: " + getVulkanType(cmd)) + << QLatin1StringView("\n"); + log << QLatin1StringView("\n"); + + log << QLatin1StringView("QSG RHI Backend:") << QSGRhiSupport::instance()->rhiBackendName() + << QLatin1StringView("\n"); + log << QLatin1StringView("QSG RHI Backend Supported:") + << QLatin1StringView(usingSupportedSGBackend() ? "yes" : "no") + << QLatin1StringView("\n"); + log << QLatin1StringView("GPU Vendor: " + + GPUInfo::vendorToString(GPUInfo::instance()->vendor())) + << QLatin1StringView("\n"); + log << QLatin1StringView("\n"); #if QT_CONFIG(opengl) #if defined(USE_OZONE) - log << "Using GLX:" << (GLContextHelper::getGlxPlatformInterface() ? "yes" : "no") << "\n"; - log << "Using EGL:" << (GLContextHelper::getEglPlatformInterface() ? "yes" : "no") << "\n"; + log << QLatin1StringView("Using GLX:") + << QLatin1StringView(GLContextHelper::getGlxPlatformInterface() ? "yes" : "no") + << QLatin1StringView("\n"); + log << QLatin1StringView("Using EGL:") + << QLatin1StringView(GLContextHelper::getEglPlatformInterface() ? "yes" : "no") + << QLatin1StringView("\n"); #endif - log << "Using Shared GL:" << (qt_gl_global_share_context() ? "yes" : "no") << "\n"; + log << QLatin1StringView("Using Shared GL:") + << QLatin1StringView(qt_gl_global_share_context() ? "yes" : "no") + << QLatin1StringView("\n"); if (qt_gl_global_share_context()) { - log << "Using Software Dynamic GL:" << (usingSoftwareDynamicGL() ? "yes" : "no") - << "\n"; + log << QLatin1StringView("Using Software Dynamic GL:") + << QLatin1StringView(usingSoftwareDynamicGL() ? "yes" : "no") + << QLatin1StringView("\n"); const QSurfaceFormat sharedFormat = qt_gl_global_share_context() ? qt_gl_global_share_context()->format() @@ -501,23 +515,23 @@ static void logContext(const std::string &glType, base::CommandLine *cmd) sharedFormat.profile()); const auto type = QMetaEnum::fromType().valueToKey( sharedFormat.renderableType()); - log << "Surface Type:" << type << "\n"; - log << "Surface Profile:" << profile << "\n"; - log << "Surface Version:" - << QString("%1.%2") + log << QLatin1StringView("Surface Type:") << QLatin1StringView(type) + << QLatin1StringView("\n"); + log << QLatin1StringView("Surface Profile:") << QLatin1StringView(profile) + << QLatin1StringView("\n"); + log << QStringLiteral("Surface Version: %1.%2\n") .arg(sharedFormat.majorVersion()) - .arg(sharedFormat.minorVersion()) - << "\n"; + .arg(sharedFormat.minorVersion()); } - log << "\n"; + log << QLatin1StringView("\n"); #endif // QT_CONFIG(opengl) - log << "Init Parameters:\n"; + log << QLatin1StringView("Init Parameters:\n"); const base::CommandLine::SwitchMap switchMap = cmd->GetSwitches(); for (const auto &pair : switchMap) - log << " * " << toQt(pair.first) << toQt(pair.second) << "\n"; + log << QStringLiteral(" * %1 %2\n").arg(toQt(pair.first)).arg(toQt(pair.second)); - qCDebug(webEngineContextLog) << qPrintable(log.join(" ")); + qCDebug(webEngineContextLog) << qPrintable(log.join(QLatin1Char(' '))); } } @@ -527,13 +541,14 @@ static void setupProxyPac(base::CommandLine *commandLine) { if (commandLine->HasSwitch(switches::kProxyPacUrl)) { QUrl pac_url(https://github.com/toQt(commandLine-%3EGetSwitchValueASCII(switches::kProxyPacUrl))); - if (pac_url.isValid() && (pac_url.isLocalFile() || - !pac_url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive))) { + if (pac_url.isValid() + && (pac_url.isLocalFile() + || !pac_url.scheme().compare(QLatin1StringView("qrc"), Qt::CaseInsensitive))) { QFile file; if (pac_url.isLocalFile()) file.setFileName(pac_url.toLocalFile()); else - file.setFileName(pac_url.path().prepend(QChar(':'))); + file.setFileName(pac_url.path().prepend(QLatin1Char(':'))); if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { QByteArray ba = file.readAll(); commandLine->RemoveSwitch(switches::kProxyPacUrl); @@ -562,16 +577,16 @@ static QStringList parseEnvCommandLine(const QString &cmdLine) for (const QChar c : cmdLine) { switch (state) { case Parse: - if (c == '"') { + if (c == QLatin1Char('"')) { state = Quoted; - } else if (c != ' ' ) { + } else if (c != QLatin1Char(' ')) { arg += c; state = Unquoted; } // skips spaces break; case Quoted: - if (c == '"') { + if (c == QLatin1Char('"')) { DCHECK(!arg.isEmpty()); state = Unquoted; } else { @@ -580,10 +595,10 @@ static QStringList parseEnvCommandLine(const QString &cmdLine) } break; case Unquoted: - if (c == '"') { + if (c == QLatin1Char('"')) { // skips quotes state = Quoted; - } else if (c == ' ') { + } else if (c == QLatin1Char(' ')) { arguments.append(arg); arg.clear(); state = Parse; @@ -1110,7 +1125,7 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, } base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); - int index = appArgs.indexOf(QRegularExpression(QLatin1String("--webEngineArgs"), + int index = appArgs.indexOf(QRegularExpression(QLatin1StringView("--webEngineArgs"), QRegularExpression::CaseInsensitiveOption)); if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) { appArgs = appArgs.mid(0, 1); // Take application name and drop the rest From d8d0aeb17e892b049d8b876c9dc911f7e48afe0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20K=C3=B6hne?= Date: Tue, 25 Jun 2024 08:36:57 +0200 Subject: [PATCH 044/341] Replace urn:dje license identifier II Amends 8e22839aa0 Task-number: QTBUG-126403 Pick-to: 6.7 Change-Id: I1560e5af29d2e94657a83e98bb649729b4a67cd2 Reviewed-by: Lucie Gerard (cherry picked from commit 994986fb96044551b5c43523a3589e989c2b2294) Reviewed-by: Qt Cherry-pick Bot --- .../cookiebrowser/3rdparty/qt_attribution.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json b/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json index 35d9cf0d7ad..64ba15e00ef 100644 --- a/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json +++ b/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json @@ -9,9 +9,8 @@ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library", "Version": "0.8.90", "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz", - "LicenseId": "urn:dje:license:public-domain", + "LicenseId": "LicenseRef-Tango-Icons-Public-Domain", "License": "Public Domain", - "LicenseFile": "COPYING", "Copyright": ["Ulisse Perusin ", "Steven Garrity ", "Lapo Calamandrei ", From 55942cfb6b2306234c8278a70413ec827180ad08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucie=20G=C3=A9rard?= Date: Fri, 5 Apr 2024 11:52:48 +0200 Subject: [PATCH 045/341] Correct license for documentation file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to QUIP-18 [1], all documentation files should be LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only [1]: https://contribute.qt-project.org/quips/18 Pick-to: 6.7 Task-number: QTBUG-121787 Change-Id: Ibf7b2738d62e5f2075183d2f0376774583595a55 Reviewed-by: Kai Köhne (cherry picked from commit 86e97f65b6afc495ddf46f4b39eac47646e83b0a) Reviewed-by: Qt Cherry-pick Bot --- src/pdf/qpdfdocumentrenderoptions.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pdf/qpdfdocumentrenderoptions.qdoc b/src/pdf/qpdfdocumentrenderoptions.qdoc index ad8e7bfdb88..253f3e37adb 100644 --- a/src/pdf/qpdfdocumentrenderoptions.qdoc +++ b/src/pdf/qpdfdocumentrenderoptions.qdoc @@ -1,5 +1,5 @@ // Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only #include "qpdfdocumentrenderoptions.h" From 49e95e4bda8a0c6e5e3d91b8cbfdb53dc4cbed90 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Thu, 27 Jun 2024 10:18:09 +0200 Subject: [PATCH 046/341] QWebEngineFrame: export symbols individually Per API review comment, we should export members individually when the class is not polymorphic. Change-Id: I1d338606b9d1105aa817fb47ceac4683882bd360 Reviewed-by: Michal Klocek (cherry picked from commit f6dc5265fbf6d46319adada99d3881bad266ba4d) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineframe.h | 50 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/core/api/qwebengineframe.h b/src/core/api/qwebengineframe.h index b6953cdd21f..85b02407a4d 100644 --- a/src/core/api/qwebengineframe.h +++ b/src/core/api/qwebengineframe.h @@ -19,9 +19,9 @@ class WebContentsAdapterClient; QT_BEGIN_NAMESPACE -class Q_WEBENGINECORE_EXPORT QWebEngineFrame +class QWebEngineFrame { - Q_GADGET + Q_GADGET_EXPORT(Q_WEBENGINECORE_EXPORT) Q_PROPERTY(bool isValid READ isValid FINAL) Q_PROPERTY(QString name READ name FINAL) @@ -34,26 +34,29 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFrame QML_VALUE_TYPE(webEngineFrame) QML_ADDED_IN_VERSION(6, 8) - bool isValid() const; - QString name() const; - QString htmlName() const; - QList children() const; - QUrl url() const; - QSizeF size() const; - bool isMainFrame() const; - - void runJavaScript(const QString &script, - const std::function &callback); - void runJavaScript(const QString &script, quint32 worldId, - const std::function &callback); - Q_INVOKABLE void runJavaScript(const QString &script, quint32 worldId = 0); - Q_INVOKABLE void runJavaScript(const QString &script, const QJSValue &callback); - Q_INVOKABLE void runJavaScript(const QString &script, quint32 worldId, - const QJSValue &callback); - - Q_INVOKABLE void printToPdf(const QString &filePath); - void printToPdf(const std::function &callback); - Q_INVOKABLE void printToPdf(const QJSValue &callback); + Q_WEBENGINECORE_EXPORT bool isValid() const; + Q_WEBENGINECORE_EXPORT QString name() const; + Q_WEBENGINECORE_EXPORT QString htmlName() const; + Q_WEBENGINECORE_EXPORT QList children() const; + Q_WEBENGINECORE_EXPORT QUrl url() const; + Q_WEBENGINECORE_EXPORT QSizeF size() const; + Q_WEBENGINECORE_EXPORT bool isMainFrame() const; + + Q_WEBENGINECORE_EXPORT void + runJavaScript(const QString &script, const std::function &callback); + Q_WEBENGINECORE_EXPORT void + runJavaScript(const QString &script, quint32 worldId, + const std::function &callback); + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void runJavaScript(const QString &script, + quint32 worldId = 0); + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void runJavaScript(const QString &script, + const QJSValue &callback); + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void runJavaScript(const QString &script, quint32 worldId, + const QJSValue &callback); + + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void printToPdf(const QString &filePath); + Q_WEBENGINECORE_EXPORT void printToPdf(const std::function &callback); + Q_WEBENGINECORE_EXPORT Q_INVOKABLE void printToPdf(const QJSValue &callback); friend inline bool comparesEqual(const QWebEngineFrame &lhs, const QWebEngineFrame &rhs) noexcept @@ -69,7 +72,8 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFrame friend class QQuickWebEngineView; friend class QQuickWebEngineViewPrivate; - QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *page, quint64 id); + Q_WEBENGINECORE_EXPORT QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *page, + quint64 id); QtWebEngineCore::WebContentsAdapterClient *m_adapterClient; quint64 m_id; From 75d1aa2dd1adb19e8a16de8ff84eae0529cbbb68 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Wed, 17 Apr 2024 13:03:22 +0200 Subject: [PATCH 047/341] Implement MotionEvent::GetSourceDeviceId Without this many errors are printed during tst_touchpoint Change-Id: I9742fe50b1e915d52e1ff7a9b1e48511ca8bdcc6 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 841aa01aaf83c63ffd83bafe7509c17b6d36d467) Reviewed-by: Qt Cherry-pick Bot --- src/core/render_widget_host_view_qt_delegate_client.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp index 3e8cad6693a..02ad9b039e0 100644 --- a/src/core/render_widget_host_view_qt_delegate_client.cpp +++ b/src/core/render_widget_host_view_qt_delegate_client.cpp @@ -88,6 +88,11 @@ class MotionEventQt : public ui::MotionEvent Action GetAction() const override { return action; } int GetActionIndex() const override { return index; } size_t GetPointerCount() const override { return touchPoints.size(); } + int32_t GetSourceDeviceId(size_t pointer_index) const override + { + return static_cast( + touchPoints[pointer_index].second.device()->uniqueId().numericId()); + } int GetPointerId(size_t pointer_index) const override { return touchPoints[pointer_index].first; From 05136d3d63f49b32dbe7ed2caa23519024478375 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Wed, 19 Jun 2024 10:37:45 +0100 Subject: [PATCH 048/341] Use device pixel ratio of the window rather than the screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Window device pixel ratio can differ from the screen depending on the platform. The window is the more authorative source with new events in Qt to support that. In Chromium the rendering is still based off a screen factor, but each view will have a completely independent set of screen variables, so we can adjust the screen to match our current view. Chromium itself also alters the screen scale factor on a per window basis for their own native Wayland backend or if recording a window. Fixes: QTBUG-113574 Change-Id: I12231c826525a9d7b5e30eed10324f65fbf8c16f Reviewed-by: Moss Heim Reviewed-by: Morten Johan Sørvig Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 21a9add47def34322b799683e1e1daff88dc4a06) Reviewed-by: Qt Cherry-pick Bot --- src/core/render_widget_host_view_qt.cpp | 5 +++++ src/core/render_widget_host_view_qt_delegate_item.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 98d0471c1d2..4405de46c56 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -876,6 +876,11 @@ bool RenderWidgetHostViewQt::updateScreenInfo() return false; display::ScreenInfos newScreenInfos = screenInfosFromQtForUpdate(window->screen()); + + // We always want to use the scale from our current window + // This screen information is stored on a per-view basis + auto &screen = newScreenInfos.mutable_current(); + screen.device_scale_factor = window->devicePixelRatio(); if (screen_infos_ == newScreenInfos) return false; diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp index 23e5bc93594..a9f872220ad 100644 --- a/src/core/render_widget_host_view_qt_delegate_item.cpp +++ b/src/core/render_widget_host_view_qt_delegate_item.cpp @@ -345,6 +345,8 @@ void RenderWidgetHostViewQtDelegateItem::itemChange(ItemChange change, const Ite if (!m_isPopup) onHide(); } + } else if (change == QQuickItem::ItemDevicePixelRatioHasChanged) { + m_client->visualPropertiesChanged(); } } From f27fa91cf0fd102de148edec9ac54ea2b0fb69cf Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Wed, 3 Jul 2024 01:14:49 +0000 Subject: [PATCH 049/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ia42e2f8e5b8701475184c6a109762a3b19f5ae9d Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index a2e94f244e2..d9a5ed195c7 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: f67b8f68a951fdd5fd21ce95cf0be0668397d3f8 + ref: df193621ede18ee1166281435750fc1980b3bc1f required: true ../qtpositioning: - ref: a94950c0e9df7cd8bdeeff38e8826b6ee522eee8 + ref: 31a8040367a3d79f1970799d283acb1be8e4f23b required: false ../qttools: - ref: 71e84ea044451757f6590df211c18372661717c0 + ref: a5a69456bf87773b671aca85373085a948408ff9 required: false ../qtwebchannel: - ref: 57aa7f5ae976f7bb4efebce011fcd0f8153bb158 + ref: abad90db61a76dc0e1faaa2034837a8612bcdd83 required: false From 9603e7f5aee70ebfa2ef96e35b809e43b79f070b Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Wed, 8 May 2024 14:20:37 +0200 Subject: [PATCH 050/341] Add missing dependencies to webengine devtools source set Missing dependencies are added to resolve the dependencies issues encountered when compiling with Ninja 1.12.0 Fixes: QTBUG-125035 Pick-to: 6.7 Change-Id: Ia089f407852efdeb837c6fc348e9d1fbb43a0da7 Reviewed-by: Michal Klocek (cherry picked from commit 35f49e787dd5894c0f890855b1ac2f0d7c24421d) Reviewed-by: Qt Cherry-pick Bot --- src/core/configure/BUILD.root.gn.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in index 1fbbadf2671..0e913f1d44b 100644 --- a/src/core/configure/BUILD.root.gn.in +++ b/src/core/configure/BUILD.root.gn.in @@ -237,6 +237,7 @@ source_set("qtwebengine_spellcheck_sources") { source_set("devtools_sources") { configs += [ ":cpp20_config" ] deps = [ + "//chrome/app:generated_resources", "//components/zoom", "//third_party/blink/public/mojom:mojom_platform", ] From 129e37d823cc6a89ca0de04a12f72b4e2fad47f0 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Thu, 20 Jun 2024 16:35:13 +0200 Subject: [PATCH 051/341] QWebEnginePermission: Post-API review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit contains fixes for the issues found during the API review of the new permissions API. In particular: - All new enums are now scoped - Replaced isTransient with its opposite, isPersistent - Renamed Feature to PermissionType - Made origin() return a non-const QUrl - Renamed PersistentPermissionsPolicy members to be more concise - Fixed a couple of bugs in the implementation - Updated documentation Change-Id: Idf84e1c9ba3ae803ef4686e1caa7f3e6c198c87d Reviewed-by: Michal Klocek (cherry picked from commit 85ff9e35fdec602f71c66e9c93eefd2c6d911512) Reviewed-by: Michael BrĂ¼ning --- .../quicknanobrowser/BrowserWindow.qml | 31 +-- examples/webenginewidgets/maps/mainwindow.cpp | 2 +- .../webenginewidgets/notifications/main.cpp | 2 +- .../doc/src/permissionbrowser.qdoc | 32 ++-- .../permissionbrowser/mainwindow.cpp | 38 ++-- .../permissionbrowser/permissiondialog.ui | 4 +- .../push-notifications/main.cpp | 2 +- .../simplebrowser/webview.cpp | 28 +-- src/core/api/qwebenginepage.cpp | 100 +++++----- src/core/api/qwebenginepage.h | 49 ++--- src/core/api/qwebenginepage_p.h | 4 +- src/core/api/qwebenginepermission.cpp | 171 +++++++++-------- src/core/api/qwebenginepermission.h | 34 +++- src/core/api/qwebenginepermission_p.h | 4 +- src/core/api/qwebengineprofile.cpp | 68 +++---- src/core/api/qwebengineprofile.h | 16 +- src/core/doc/src/qtwebengine-features.qdoc | 6 +- src/core/permission_manager_qt.cpp | 178 +++++++++--------- src/core/permission_manager_qt.h | 12 +- src/core/profile_adapter.cpp | 27 +-- src/core/profile_adapter.h | 15 +- src/core/web_contents_adapter.cpp | 51 ++--- src/core/web_contents_adapter.h | 4 +- src/core/web_contents_adapter_client.h | 4 +- src/core/web_contents_delegate_qt.cpp | 10 +- src/core/web_contents_delegate_qt.h | 2 +- .../api/qquickwebengineprofile.cpp | 97 +++++----- .../api/qquickwebengineprofile.h | 16 +- .../api/qquickwebenginesettings.cpp | 4 +- .../api/qquickwebengineview.cpp | 91 ++++----- .../api/qquickwebengineview_p.h | 32 +--- .../api/qquickwebengineview_p_p.h | 4 +- .../doc/src/webengine_permission.qdoc | 87 +++++---- .../doc/src/webengineview_lgpl.qdoc | 6 +- tests/auto/quick/publicapi/tst_publicapi.cpp | 50 ++--- .../quick/qmltests/data/tst_geopermission.qml | 10 +- .../quick/qmltests/data/tst_getUserMedia.qml | 14 +- .../quick/qmltests/data/tst_notification.qml | 9 +- .../qwebenginepage/tst_qwebenginepage.cpp | 143 +++++++------- .../tst_qwebengineprofile.cpp | 95 +++++----- .../quick/geopermission/tst_geopermission.qml | 2 +- 41 files changed, 781 insertions(+), 773 deletions(-) diff --git a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml index d040667d32f..02f5564aca2 100644 --- a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml +++ b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml @@ -748,53 +748,54 @@ ApplicationWindow { contentItem: Item { Label { id: mainTextForPermissionDialog - text: permissionDialog.questionForFeature() } } onAccepted: permission.grant() onRejected: permission.deny() onVisibleChanged: { - if (visible) + if (visible) { + mainTextForPermissionDialog.text = questionForPermissionType(); width = contentWidth + 20; + } } - function questionForFeature() { + function questionForPermissionType() { var question = "Allow " + permission.origin + " to " - switch (permission.feature) { - case WebEnginePermission.Geolocation: + switch (permission.permissionType) { + case WebEnginePermission.PermissionType.Geolocation: question += "access your location information?"; break; - case WebEnginePermission.MediaAudioCapture: + case WebEnginePermission.PermissionType.MediaAudioCapture: question += "access your microphone?"; break; - case WebEnginePermission.MediaVideoCapture: + case WebEnginePermission.PermissionType.MediaVideoCapture: question += "access your webcam?"; break; - case WebEnginePermission.MediaAudioVideoCapture: + case WebEnginePermission.PermissionType.MediaAudioVideoCapture: question += "access your microphone and webcam?"; break; - case WebEnginePermission.MouseLock: + case WebEnginePermission.PermissionType.MouseLock: question += "lock your mouse cursor?"; break; - case WebEnginePermission.DesktopVideoCapture: + case WebEnginePermission.PermissionType.DesktopVideoCapture: question += "capture video of your desktop?"; break; - case WebEnginePermission.DesktopAudioVideoCapture: + case WebEnginePermission.PermissionType.DesktopAudioVideoCapture: question += "capture audio and video of your desktop?"; break; - case WebEnginePermission.Notifications: + case WebEnginePermission.PermissionType.Notifications: question += "show notification on your desktop?"; break; - case WebEnginePermission.ClipboardReadWrite: + case WebEnginePermission.PermissionType.ClipboardReadWrite: question += "read from and write to your clipboard?"; break; - case WebEnginePermission.LocalFontsAccess: + case WebEnginePermission.PermissionType.LocalFontsAccess: question += "access the fonts stored on your machine?"; break; default: - question += "access unknown or unsupported feature [" + permission.feature + "] ?"; + question += "access unknown or unsupported permission type [" + permission.permissionType + "] ?"; break; } diff --git a/examples/webenginewidgets/maps/mainwindow.cpp b/examples/webenginewidgets/maps/mainwindow.cpp index ca98ca2630f..07b8d8ab3da 100644 --- a/examples/webenginewidgets/maps/mainwindow.cpp +++ b/examples/webenginewidgets/maps/mainwindow.cpp @@ -15,7 +15,7 @@ MainWindow::MainWindow(QWidget *parent) connect(page, &QWebEnginePage::permissionRequested, [this, page](QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePermission::Geolocation) + if (permission.permissionType() != QWebEnginePermission::PermissionType::Geolocation) return; QMessageBox msgBox(this); diff --git a/examples/webenginewidgets/notifications/main.cpp b/examples/webenginewidgets/notifications/main.cpp index df9ebff73c8..e01dd03bc5f 100644 --- a/examples/webenginewidgets/notifications/main.cpp +++ b/examples/webenginewidgets/notifications/main.cpp @@ -35,7 +35,7 @@ int main(int argc, char *argv[]) QObject::connect(view.page(), &QWebEnginePage::permissionRequested, [&] (QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePermission::Notifications) + if (permission.permissionType() != QWebEnginePermission::PermissionType::Notifications) return; permission.grant(); }); diff --git a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc index a266ec62a2a..3715d63cd94 100644 --- a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc +++ b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc @@ -65,7 +65,7 @@ gets populated with a \c PermissionWidget whenever that happens. The \c PermissionWidget displays the permission's origin, the requested - \l QWebEnginePermission::Feature, as well as the current status of that permission. + \l QWebEnginePermission::PermissionType, as well as the current status of that permission. It also has buttons for granting and denying the permission. Since the permission status is (by default) remembered, the delete button allows the user to remove the permission from the underlying storage. @@ -133,23 +133,23 @@ \skipto void MainWindow::handlePermissionModified \printuntil /^\}/ - Notably, we only do this in cases where we know the permission is remembered. - This is not true for transient \c Features, - which require a permission prompt be shown to the user every time they're needed. + Notably, we only do this in cases where we know the permission is remembered; + some \c PermissionTypes are non-persistent, which means they require + a permission prompt be shown to the user every time they're used. We also exclude permissions with a \l QWebEnginePermission::Ask state, which indicates that the permission was \l {QWebEnginePermission::reset}{reset}(), and we don't add anything to the list of existing permissions when \l QWebEngineProfile::persistentPermissionsPolicy is set to - \c NoPersistentPermissions. + \c AskEveryTime. - \note Check the \l QWebEnginePermission::Feature documentation to see which - \c Features are transient. + \note Check the \l QWebEnginePermission::PermissionType documentation to see which + \c PermissionTypes are persistent. \section1 Displaying and modifying existing permissions By default, permissions are stored to disk and retrieved again on application startup. To get a list of all existing website permissions, we call - \l QWebEngineProfile::listPermissions(): + \l QWebEngineProfile::listAllPermissions(): \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp \skipto void MainWindow::loadStoredPermissions() @@ -161,7 +161,7 @@ \section1 Pre-granting permissions - Certain permissions may be granted in advance, provided the origin and Feature type + Certain permissions may be granted in advance, provided the origin and permission type are known. Clicking on the "New" button in the top right will create a pop-up dialog that allows you to do just that. The dialog is implemented by the \c PermissionDialog class: @@ -171,8 +171,8 @@ \printuntil /^\}/ We populate the \l QComboBox using the QMetaEnum type associated with - \l QWebEnginePermission::Feature. We make sure to filter out transient - features, since pre-granting these is not supported. + \l QWebEnginePermission::PermissionType. We make sure to filter out non-persistent + permission types, since pre-granting these is not supported. We display the dialog and add show the resulting \c PermissionWidget in the UI inside the \c MainWindow::handleNewClicked slot. The new @@ -191,22 +191,22 @@ of each option. \list - \li \l QWebEngineProfile::PersistentPermissionsOnDisk is the default, and it ensures + \li \l QWebEngineProfile::StoreOnDisk is the default, and it ensures that any permissions that have been granted in the current application run will be loaded back up at next startup. A permission onlycneeds to be granted once, and subsequent uses of the API that triggered the request will automatically be granted, until the application calls QWebEnginePermission::reset(). - li \l QWebEngineProfile::PersistentPermissionsInMemory Has the same behavior as above, + li \l QWebEngineProfile::StoreInMemory Has the same behavior as above, except that permissions will be destroyed at application exit, and not committed to disk. - li \l QWebEngineProfile::NoPersistentPermissions makes sure permissions are never - remembered, and all act as if they're transient. Thus, every time a web API needs + li \l QWebEngineProfile::AskEveryTime makes sure permissions are never + remembered, and all act as if they're non-persistent. Thus, every time a web API needs a permission, a new prompt will be shown to the user. This option is intended for backwards compatibility and applications which implement their own permission storage. \endlist To ensure the user will be shown previously existing permissions, we need to call - \l QWebEngineProfile::listPermissions(): + \l QWebEngineProfile::listAllPermissions(): \quotefromfile webenginewidgets/permissionbrowser/mainwindow.cpp \skipto void MainWindow::loadStoredPermissions() diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp index 2fe3c3b1706..8fd811e8383 100644 --- a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp @@ -15,12 +15,12 @@ PermissionDialog::PermissionDialog(const QWebEngineProfile *profile, QWidget *pa { setupUi(this); - auto metaEnum = QMetaEnum::fromType(); - Q_ASSERT(metaEnum.value(QWebEnginePermission::Unsupported) == 0); + auto metaEnum = QMetaEnum::fromType(); + Q_ASSERT(metaEnum.value((quint8)QWebEnginePermission::PermissionType::Unsupported) == 0); for (int i = 1; i < metaEnum.keyCount(); ++i) { - QWebEnginePermission::Feature feature = QWebEnginePermission::Feature(metaEnum.value(i)); - if (!QWebEnginePermission::isTransient(feature)) - m_featureComboBox->addItem(metaEnum.valueToKey(feature), QVariant(feature)); + QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i)); + if (QWebEnginePermission::isPersistent(permissionType)) + m_permissionTypeComboBox->addItem(metaEnum.valueToKey((quint8)permissionType), QVariant::fromValue(permissionType)); } } @@ -31,8 +31,8 @@ PermissionDialog::~PermissionDialog() QWebEnginePermission PermissionDialog::permission() { - return m_profile->getPermission(QUrl(m_originLineEdit->text()), - QWebEnginePermission::Feature(m_featureComboBox->itemData(m_featureComboBox->currentIndex()).toInt())); + return m_profile->queryPermission(QUrl(m_originLineEdit->text()), + QWebEnginePermission::PermissionType(m_permissionTypeComboBox->itemData(m_permissionTypeComboBox->currentIndex()).toInt())); } PermissionWidget::PermissionWidget(const QWebEnginePermission &permission, QWidget *parent) @@ -64,23 +64,23 @@ PermissionWidget::PermissionWidget(const QWebEnginePermission &permission, QWidg void PermissionWidget::updateState() { switch (m_permission.state()) { - case QWebEnginePermission::Invalid: + case QWebEnginePermission::State::Invalid: m_stateLabel->setText("Invalid"); m_grantButton->setEnabled(false); m_denyButton->setEnabled(false); break; - case QWebEnginePermission::Ask: + case QWebEnginePermission::State::Ask: m_stateLabel->setText("Waiting for response"); break; - case QWebEnginePermission::Granted: + case QWebEnginePermission::State::Granted: m_stateLabel->setText("Granted"); break; - case QWebEnginePermission::Denied: + case QWebEnginePermission::State::Denied: m_stateLabel->setText("Denied"); break; } - m_typeLabel->setText(QMetaEnum::fromType().valueToKey(m_permission.feature())); + m_typeLabel->setText(QMetaEnum::fromType().valueToKey((quint8)m_permission.permissionType())); m_originLabel->setText(m_permission.origin().toDisplayString()); } @@ -153,9 +153,9 @@ void MainWindow::handlePermissionModified(PermissionWidget *widget) m_pendingFrame->layout()->removeWidget(widget); m_pendingWidget = nullptr; - if (QWebEnginePermission::isTransient(widget->m_permission.feature()) - || widget->m_permission.state() == QWebEnginePermission::Ask - || m_profile->persistentPermissionsPolicy() == QWebEngineProfile::NoPersistentPermissions) { + if (!QWebEnginePermission::isPersistent(widget->m_permission.permissionType()) + || widget->m_permission.state() == QWebEnginePermission::State::Ask + || m_profile->persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime) { widget->deleteLater(); return; @@ -209,13 +209,13 @@ void MainWindow::handlePolicyComboBoxIndexChanged(int index) QWebEngineProfile::PersistentPermissionsPolicy policy; switch (index) { case 0: - policy = QWebEngineProfile::PersistentPermissionsOnDisk; + policy = QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime; break; case 1: - policy = QWebEngineProfile::PersistentPermissionsInMemory; + policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory; break; case 2: - policy = QWebEngineProfile::NoPersistentPermissions; + policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk; break; } @@ -261,7 +261,7 @@ PermissionWidget *MainWindow::createPermissionWidget(const QWebEnginePermission void MainWindow::loadStoredPermissions() { - QList permissionsList = m_profile->listPermissions(); + QList permissionsList = m_profile->listAllPermissions(); for (QWebEnginePermission &permission : permissionsList) { PermissionWidget *widget = createPermissionWidget(permission); if (widget) diff --git a/examples/webenginewidgets/permissionbrowser/permissiondialog.ui b/examples/webenginewidgets/permissionbrowser/permissiondialog.ui index a98432131a1..430df2d58b4 100644 --- a/examples/webenginewidgets/permissionbrowser/permissiondialog.ui +++ b/examples/webenginewidgets/permissionbrowser/permissiondialog.ui @@ -31,7 +31,7 @@ - Feature + Permission type @@ -70,7 +70,7 @@ - + diff --git a/examples/webenginewidgets/push-notifications/main.cpp b/examples/webenginewidgets/push-notifications/main.cpp index 2a52ea39e0e..16465317dfc 100644 --- a/examples/webenginewidgets/push-notifications/main.cpp +++ b/examples/webenginewidgets/push-notifications/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) QObject::connect(view.page(), &QWebEnginePage::permissionRequested, [&](QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePermission::Notifications) + if (permission.permissionType() != QWebEnginePermission::PermissionType::Notifications) return; permission.grant(); diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp index 40a1508b4ef..e7538f948ca 100644 --- a/examples/webenginewidgets/simplebrowser/webview.cpp +++ b/examples/webenginewidgets/simplebrowser/webview.cpp @@ -71,27 +71,31 @@ WebView::~WebView() m_imageAnimationGroup = nullptr; } -inline QString questionForFeature(QWebEnginePermission::Feature feature) +inline QString questionForPermissionType(QWebEnginePermission::PermissionType permissionType) { - switch (feature) { - case QWebEnginePermission::Geolocation: + switch (permissionType) { + case QWebEnginePermission::PermissionType::Geolocation: return QObject::tr("Allow %1 to access your location information?"); - case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::PermissionType::MediaAudioCapture: return QObject::tr("Allow %1 to access your microphone?"); - case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::PermissionType::MediaVideoCapture: return QObject::tr("Allow %1 to access your webcam?"); - case QWebEnginePermission::MediaAudioVideoCapture: + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: return QObject::tr("Allow %1 to access your microphone and webcam?"); - case QWebEnginePermission::MouseLock: + case QWebEnginePermission::PermissionType::MouseLock: return QObject::tr("Allow %1 to lock your mouse cursor?"); - case QWebEnginePermission::DesktopVideoCapture: + case QWebEnginePermission::PermissionType::DesktopVideoCapture: return QObject::tr("Allow %1 to capture video of your desktop?"); - case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: return QObject::tr("Allow %1 to capture audio and video of your desktop?"); - case QWebEnginePermission::Notifications: + case QWebEnginePermission::PermissionType::Notifications: return QObject::tr("Allow %1 to show notification on your desktop?"); - case QWebEnginePermission::ClipboardReadWrite: + case QWebEnginePermission::PermissionType::ClipboardReadWrite: return QObject::tr("Allow %1 to read from and write to the clipboard?"); + case QWebEnginePermission::PermissionType::LocalFontsAccess: + return QObject::tr("Allow %1 to access fonts stored on this machine?"); + case QWebEnginePermission::PermissionType::Unsupported: + break; } return QString(); } @@ -312,7 +316,7 @@ void WebView::handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticato void WebView::handlePermissionRequested(QWebEnginePermission permission) { QString title = tr("Permission Request"); - QString question = questionForFeature(permission.feature()).arg(permission.origin().host()); + QString question = questionForPermissionType(permission.permissionType()).arg(permission.origin().host()); if (!question.isEmpty() && QMessageBox::question(window(), title, question) == QMessageBox::Yes) permission.grant(); else diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index a5c06f29ce8..433de26b072 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -590,22 +590,22 @@ void QWebEnginePagePrivate::showColorDialog(QSharedPointerpermissionRequested(createFeaturePermissionObject(securityOrigin, feature)); + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType)); #if QT_DEPRECATED_SINCE(6, 8) QT_WARNING_PUSH @@ -633,30 +633,30 @@ void QWebEnginePagePrivate::runMediaAccessPermissionRequest(const QUrl &security #if QT_DEPRECATED_SINCE(6, 8) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED -static QWebEnginePage::Feature toDeprecatedFeature(QWebEnginePermission::Feature feature) +static QWebEnginePage::Feature toDeprecatedFeature(QWebEnginePermission::PermissionType permissionType) { - switch (feature) { - case QWebEnginePermission::Feature::Notifications: + switch (permissionType) { + case QWebEnginePermission::PermissionType::Notifications: return QWebEnginePage::Notifications; - case QWebEnginePermission::Feature::Geolocation: + case QWebEnginePermission::PermissionType::Geolocation: return QWebEnginePage::Geolocation; - case QWebEnginePermission::Feature::ClipboardReadWrite: + case QWebEnginePermission::PermissionType::ClipboardReadWrite: return QWebEnginePage::ClipboardReadWrite; - case QWebEnginePermission::Feature::LocalFontsAccess: + case QWebEnginePermission::PermissionType::LocalFontsAccess: return QWebEnginePage::LocalFontsAccess; - case QWebEnginePermission::Feature::MediaAudioCapture: + case QWebEnginePermission::PermissionType::MediaAudioCapture: return QWebEnginePage::MediaAudioCapture; - case QWebEnginePermission::Feature::MediaVideoCapture: + case QWebEnginePermission::PermissionType::MediaVideoCapture: return QWebEnginePage::MediaVideoCapture; - case QWebEnginePermission::Feature::MediaAudioVideoCapture: + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: return QWebEnginePage::MediaAudioVideoCapture; - case QWebEnginePermission::Feature::DesktopVideoCapture: + case QWebEnginePermission::PermissionType::DesktopVideoCapture: return QWebEnginePage::DesktopVideoCapture; - case QWebEnginePermission::Feature::DesktopAudioVideoCapture: + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: return QWebEnginePage::DesktopAudioVideoCapture; - case QWebEnginePermission::Feature::MouseLock: + case QWebEnginePermission::PermissionType::MouseLock: return QWebEnginePage::MouseLock; - case QWebEnginePermission::Feature::Unsupported: + case QWebEnginePermission::PermissionType::Unsupported: break; } @@ -666,38 +666,28 @@ static QWebEnginePage::Feature toDeprecatedFeature(QWebEnginePermission::Feature QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) -void QWebEnginePagePrivate::runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &securityOrigin) +void QWebEnginePagePrivate::runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin) { Q_Q(QWebEnginePage); - switch (feature) { - case QWebEnginePermission::Notifications: - case QWebEnginePermission::Geolocation: - case QWebEnginePermission::ClipboardReadWrite: - case QWebEnginePermission::LocalFontsAccess: - Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, feature)); + + if (QWebEnginePermission::isPersistent(permissionType)) { + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType)); #if QT_DEPRECATED_SINCE(6, 8) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(feature)); + Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(permissionType)); QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) return; - case QWebEnginePermission::MouseLock: - case QWebEnginePermission::MediaAudioCapture: - case QWebEnginePermission::MediaVideoCapture: - case QWebEnginePermission::MediaAudioVideoCapture: - case QWebEnginePermission::DesktopAudioVideoCapture: - case QWebEnginePermission::DesktopVideoCapture: - case QWebEnginePermission::Unsupported: - Q_UNREACHABLE(); - return; } + + Q_UNREACHABLE(); } void QWebEnginePagePrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin) { Q_Q(QWebEnginePage); - Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, QWebEnginePermission::MouseLock)); + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, QWebEnginePermission::PermissionType::MouseLock)); #if QT_DEPRECATED_SINCE(6, 8) QT_WARNING_PUSH @@ -893,9 +883,9 @@ void QWebEnginePagePrivate::showWebAuthDialog(QWebEngineWebAuthUxRequest *reques Q_EMIT q->webAuthUxRequested(request); } -QWebEnginePermission QWebEnginePagePrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) +QWebEnginePermission QWebEnginePagePrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType feature) { - auto *returnPrivate = new QWebEnginePermissionPrivate{securityOrigin, feature, adapter, profileAdapter()}; + auto *returnPrivate = new QWebEnginePermissionPrivate(securityOrigin, feature, adapter, profileAdapter()); return QWebEnginePermission(returnPrivate); } @@ -1857,39 +1847,39 @@ QT_WARNING_DISABLE_DEPRECATED void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy) { Q_D(QWebEnginePage); - QWebEnginePermission::Feature f = QWebEnginePermission::Feature::Unsupported; + QWebEnginePermission::PermissionType f = QWebEnginePermission::PermissionType::Unsupported; QWebEnginePermission::State s = QWebEnginePermission::State::Invalid; switch (feature) { case QWebEnginePage::Notifications: - f = QWebEnginePermission::Notifications; + f = QWebEnginePermission::PermissionType::Notifications; break; case QWebEnginePage::Geolocation: - f = QWebEnginePermission::Geolocation; + f = QWebEnginePermission::PermissionType::Geolocation; break; case QWebEnginePage::MediaAudioCapture: - f = QWebEnginePermission::MediaAudioCapture; + f = QWebEnginePermission::PermissionType::MediaAudioCapture; break; case QWebEnginePage::MediaVideoCapture: - f = QWebEnginePermission::MediaVideoCapture; + f = QWebEnginePermission::PermissionType::MediaVideoCapture; break; case QWebEnginePage::MediaAudioVideoCapture: - f = QWebEnginePermission::MediaAudioVideoCapture; + f = QWebEnginePermission::PermissionType::MediaAudioVideoCapture; break; case QWebEnginePage::MouseLock: - f = QWebEnginePermission::MouseLock; + f = QWebEnginePermission::PermissionType::MouseLock; break; case QWebEnginePage::DesktopVideoCapture: - f = QWebEnginePermission::DesktopVideoCapture; + f = QWebEnginePermission::PermissionType::DesktopVideoCapture; break; case QWebEnginePage::DesktopAudioVideoCapture: - f = QWebEnginePermission::DesktopAudioVideoCapture; + f = QWebEnginePermission::PermissionType::DesktopAudioVideoCapture; break; case QWebEnginePage::ClipboardReadWrite: - f = QWebEnginePermission::ClipboardReadWrite; + f = QWebEnginePermission::PermissionType::ClipboardReadWrite; break; case QWebEnginePage::LocalFontsAccess: - f = QWebEnginePermission::LocalFontsAccess; + f = QWebEnginePermission::PermissionType::LocalFontsAccess; break; default: Q_UNREACHABLE(); @@ -1897,19 +1887,19 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine switch (policy) { case QWebEnginePage::PermissionUnknown: - s = QWebEnginePermission::Ask; + s = QWebEnginePermission::State::Ask; break; case QWebEnginePage::PermissionDeniedByUser: - s = QWebEnginePermission::Denied; + s = QWebEnginePermission::State::Denied; break; case QWebEnginePage::PermissionGrantedByUser: - s = QWebEnginePermission::Granted; + s = QWebEnginePermission::State::Granted; break; default: Q_UNREACHABLE(); } - d->adapter->setFeaturePermission(securityOrigin, f, s); + d->adapter->setPermission(securityOrigin, f, s); } QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h index 61c9bd990c1..8b36826725c 100644 --- a/src/core/api/qwebenginepage.h +++ b/src/core/api/qwebenginepage.h @@ -150,17 +150,12 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject Q_ENUM(WebWindowType) #if QT_DEPRECATED_SINCE(6, 8) -QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - enum QT_DEPRECATED_VERSION_X_6_8( - "QWebEnginePage::PermissionPolicy has been deprecated. " - "The updated permissions API uses QWebEnginePermission::State.") - PermissionPolicy { - PermissionUnknown, - PermissionGrantedByUser, - PermissionDeniedByUser + enum PermissionPolicy { + PermissionUnknown Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::State::Ask instead"), + PermissionGrantedByUser Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::State::Granted instead"), + PermissionDeniedByUser Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::State::Denied instead") }; Q_ENUM(PermissionPolicy) -QT_WARNING_POP #endif // must match WebContentsAdapterClient::NavigationType @@ -176,24 +171,19 @@ QT_WARNING_POP Q_ENUM(NavigationType) #if QT_DEPRECATED_SINCE(6, 8) -QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - enum QT_DEPRECATED_VERSION_X_6_8( - "QWebEnginePage::Feature has been deprecated. " - "The updated permissions API uses QWebEnginePermission::Feature.") - Feature { - Notifications = 0, - Geolocation = 1, - MediaAudioCapture = 2, - MediaVideoCapture, - MediaAudioVideoCapture, - MouseLock, - DesktopVideoCapture, - DesktopAudioVideoCapture, - ClipboardReadWrite, - LocalFontsAccess, + enum Feature { + Notifications Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::Notifications instead") = 0, + Geolocation Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::Geolocation instead") = 1, + MediaAudioCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaAudioCapture instead") = 2, + MediaVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaVideoCapture instead"), + MediaAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaAudioVideoCapture instead"), + MouseLock Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MouseLock instead"), + DesktopVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::DesktopVideoCapture instead"), + DesktopAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::DesktopAudioVideoCapture instead"), + ClipboardReadWrite Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::ClipboardReadWrite instead"), + LocalFontsAccess Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::LocalFontsAccess instead"), }; Q_ENUM(Feature) -QT_WARNING_POP #endif // Ex-QWebFrame enum @@ -253,10 +243,8 @@ QT_WARNING_POP void findText(const QString &subString, FindFlags options = {}, const std::function &resultCallback = std::function()); #if QT_DEPRECATED_SINCE(6, 8) -QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QT_DEPRECATED_VERSION_X_6_8("Setting permissions through QWebEnginePage has been deprecated. Please use QWebEnginePermission instead.") void setFeaturePermission(const QUrl &securityOrigin, Feature feature, PermissionPolicy policy); -QT_WARNING_POP #endif bool isLoading() const; @@ -341,17 +329,10 @@ QT_WARNING_POP void windowCloseRequested(); #if QT_DEPRECATED_SINCE(6, 8) -#if !defined(Q_MOC_RUN) -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED -#endif // !defined(Q_MOC_RUN) QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated; please use permissionRequested instead.") void featurePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature); QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated, and no longer functions.") void featurePermissionRequestCanceled(const QUrl &securityOrigin, QWebEnginePage::Feature feature); -#if !defined(Q_MOC_RUN) -QT_WARNING_POP -#endif // !defined(Q_MOC_RUN) #endif // QT_DEPRECATED_SINCE(6, 8) void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h index 77d3dd8c247..5e81a0cf91c 100644 --- a/src/core/api/qwebenginepage_p.h +++ b/src/core/api/qwebenginepage_p.h @@ -148,7 +148,7 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePagePrivate : public QtWebEngineCore::Web QSharedPointer) override; void releaseProfile() override; void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override; - void runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &securityOrigin) override; + void runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin) override; void runMouseLockPermissionRequest(const QUrl &securityOrigin) override; void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) override; void runFileSystemAccessRequest(QWebEngineFileSystemAccessRequest) override; @@ -180,7 +180,7 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePagePrivate : public QtWebEngineCore::Web const QRect &bounds, bool autoselectFirstSuggestion) override; void hideAutofillPopup() override; void showWebAuthDialog(QWebEngineWebAuthUxRequest *controller) override; - QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) override; + QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) override; QtWebEngineCore::ProfileAdapter *profileAdapter() override; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp index 61e76ee4a0d..a6860b5ddff 100644 --- a/src/core/api/qwebenginepermission.cpp +++ b/src/core/api/qwebenginepermission.cpp @@ -10,17 +10,19 @@ QT_BEGIN_NAMESPACE QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QWebEnginePermissionPrivate) +/*! \internal */ QWebEnginePermissionPrivate::QWebEnginePermissionPrivate() : QSharedData() - , feature(QWebEnginePermission::Unsupported) + , permissionType(QWebEnginePermission::PermissionType::Unsupported) { } -QWebEnginePermissionPrivate::QWebEnginePermissionPrivate(const QUrl &origin_, QWebEnginePermission::Feature feature_, +/*! \internal */ +QWebEnginePermissionPrivate::QWebEnginePermissionPrivate(const QUrl &origin_, QWebEnginePermission::PermissionType permissionType_, QSharedPointer webContentsAdapter_, QtWebEngineCore::ProfileAdapter *profileAdapter_) : QSharedData() , origin(origin_) - , feature(feature_) + , permissionType(permissionType_) , webContentsAdapter(webContentsAdapter_) , profileAdapter(profileAdapter_) { @@ -35,32 +37,39 @@ QWebEnginePermissionPrivate::QWebEnginePermissionPrivate(const QUrl &origin_, QW The typical usage pattern is as follows: \list 1 - \li A website requests a specific feature, triggering the QWebEnginePage::permissionRequested() signal; + \li A website requests a specific permission, triggering the QWebEnginePage::permissionRequested() signal; \li The signal handler triggers a prompt asking the user whether they want to grant the permission; \li When the user has made their decision, the application calls \l grant() or \l deny(); \endlist - Alternatively, an application interested in modifying already granted permissions may use QWebEngineProfile::listPermissions() - to get a list of existing permissions associated with a profile, or QWebEngineProfile::getPermission() to get + Alternatively, an application interested in modifying already granted permissions may use QWebEngineProfile::listAllPermissions() + to get a list of existing permissions associated with a profile, or QWebEngineProfile::queryPermission() to get a QWebEnginePermission object for a specific permission. The \l origin() property can be used to query which origin the QWebEnginePermission is associated with, while the - \l feature() property describes the associated feature. A website origin is the combination of its scheme, hostname, - and port. Permissions are granted on a per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} - requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. + \l permissionType() property describes the type of the requested permission. A website origin is the combination of + its scheme, hostname, and port. Permissions are granted on a per-origin basis; thus, if the web page + \c{https://www.example.com:12345/some/page.html} requests a permission, it will be granted to the origin + \c{https://www.example.com:12345/}. + + \l QWebEnginePermission::PermissionType describes all the permission types Qt WebEngine supports. Only some permission types + are remembered between browsing sessions; they are \e persistent. Non-persistent permissions query the user every time a + website requests them, and cannot be granted in advance. You can check whether a permission type is persistent at runtime + using the static method QWebEnginePermission::isPersistent(). + + Persistent permissions are stored inside the active QWebEngineProfile, and their lifetime depends on the value of + QWebEngineProfile::persistentPermissionsPolicy(). By default, named profiles store their permissions on disk, whereas + off-the-record ones store them in memory (and destroy them when the profile is destroyed). A stored permission will not + query the user the next time a website requests it; instead it will be automatically granted or denied, depending on + the resolution the user picked initially. To erase a stored permission, call \l reset() on it. - \l QWebEnginePermission::Feature describes all the feature types Qt WebEngine supports. Some Features are transient; - in practice, this means that they are never remembered, and a website that uses them will trigger a permission - prompt every time the Feature is needed. Transient Features cannot be granted in advance. + A non-persistent permission, on the other hand, is only usable until the related QWebEnginePage performs a navigation to + a different URL, or is destroyed. - The usability lifetime of a QWebEnginePermission is tied either to its associated QWebEnginePage - (for transient feature types), or QWebEngineProfile (for permanent feature types). A transient permission is one which - needs to be explicitly granted or denied every time it's needed (e.g. webcam/screen sharing permission), whereas a permanent - one might be stored inside the current profile, depending on the value of QWebEngineProfile::persistentPermissionsPolicy(). You can check whether a QWebEnginePermission is in a valid state using its \l isValid() property. For invalid objects, calls to \l grant(), \l deny(), or \l reset() will do nothing, while calls to \l state() will always return QWebEnginePermission::Invalid. - \sa QWebEnginePage::permissionRequested(), QWebEngineProfile::getPermission(), QWebEngineProfile::listPermissions() + \sa QWebEnginePage::permissionRequested(), QWebEngineProfile::queryPermission(), QWebEngineProfile::listAllPermissions() */ /*! \fn QWebEnginePermission::QWebEnginePermission() @@ -100,10 +109,10 @@ bool QWebEnginePermission::comparesEqual(const QWebEnginePermission &other) cons if (this == &other) return true; - if (d_ptr->feature != other.d_ptr->feature || d_ptr->origin != other.d_ptr->origin) + if (d_ptr->permissionType != other.d_ptr->permissionType || d_ptr->origin != other.d_ptr->origin) return false; - if (isTransient(d_ptr->feature)) { + if (!isPersistent(d_ptr->permissionType)) { if (d_ptr->webContentsAdapter != other.d_ptr->webContentsAdapter) return false; } else { @@ -129,49 +138,49 @@ bool QWebEnginePermission::comparesEqual(const QWebEnginePermission &other) cons per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. */ -const QUrl QWebEnginePermission::origin() const +QUrl QWebEnginePermission::origin() const { return d_ptr->origin; } /*! - \enum QWebEnginePermission::Feature - - This enum type holds the type of the requested feature: - - \value MediaAudioCapture Access to a microphone, or another audio source. This feature is transient. - \value MediaVideoCapture Access to a webcam, or another video source. This feature is transient. - \value MediaAudioVideoCapture Combination of \l MediaAudioCapture and \l MediaVideoCapture. This feature is transient. - \value DesktopVideoCapture Access to the contents of the user's screen. This feature is transient. - \value DesktopAudioVideoCapture Access to the contents of the user's screen, and application audio. This feature is transient. - \value MouseLock Locks the pointer inside an element on the web page. This feature is transient. - \value Notifications Allows the website to send notifications to the user. - \value Geolocation Access to the user's physical location. - \value ClipboardReadWrite Access to the user's clipboard. - \value LocalFontsAccess Access to the fonts installed on the user's machine. Only available on desktops. - \value Unsupported An unsupported feature type. - - \note Transient feature types are ones that will never be remembered by the underlying storage, and will trigger - a permission request every time a website tries to use them. Transient Features can only be denied/granted - as they're needed; any attempts to pre-grant a transient Feature will fail. + \enum QWebEnginePermission::PermissionType + + This enum type holds the type of the requested permission type: + + \value MediaAudioCapture Access to a microphone, or another audio source. This permission is \e not persistent. + \value MediaVideoCapture Access to a webcam, or another video source. This permission is \e not persistent. + \value MediaAudioVideoCapture Combination of \l MediaAudioCapture and \l MediaVideoCapture. This permission is \e not persistent. + \value DesktopVideoCapture Access to the contents of the user's screen. This permission is \e not persistent. + \value DesktopAudioVideoCapture Access to the contents of the user's screen, and application audio. This permission is \e not persistent. + \value MouseLock Locks the pointer inside an element on the web page. This permission is \e not persistent. + \value Notifications Allows the website to send notifications to the user. This permission is persistent. + \value Geolocation Access to the user's physical location. This permission is persistent. + \value ClipboardReadWrite Access to the user's clipboard. This permission is persistent. + \value LocalFontsAccess Access to the fonts installed on the user's machine. Only available on desktops. This permission is persistent. + \value Unsupported An unsupported permission type. + + \note Non-persistent permission types are ones that will never be remembered by the underlying storage, and will trigger + a permission request every time a website tries to use them. They can only be denied/granted as they're needed; + any attempts to pre-grant a non-persistent permission will fail. */ /*! - \property QWebEnginePermission::feature - \brief The feature type associated with this permission. + \property QWebEnginePermission::permissionType + \brief The permission type associated with this permission. */ -QWebEnginePermission::Feature QWebEnginePermission::feature() const +QWebEnginePermission::PermissionType QWebEnginePermission::permissionType() const { - return d_ptr->feature; + return d_ptr->permissionType; } /*! \enum QWebEnginePermission::State - This enum type holds the current state of the requested feature: + This enum type holds the current state of the requested permission: \value Invalid Object is in an invalid state, and any attempts to modify the described permission will fail. - \value Ask Either the permission has not been requested before, or the feature() is transient. + \value Ask Either the permission has not been requested before, or the permissionType() is not persistent. \value Granted Permission has already been granted. \value Denied Permission has already been denied. */ @@ -180,24 +189,24 @@ QWebEnginePermission::Feature QWebEnginePermission::feature() const \property QWebEnginePermission::state \brief The current state of the permission. - If a permission for the specified \l feature() and \l origin() has already been granted or denied, + If a permission for the specified \l permissionType() and \l origin() has already been granted or denied, the return value is QWebEnginePermission::Granted, or QWebEnginePermission::Denied, respectively. - When this is the first time the permission is requested, or if the \l feature() is transient, + When this is the first time the permission is requested, or if the \l permissionType() is non-persistent, the return value is QWebEnginePermission::Ask. If the object is in an invalid state, the returned value is QWebEnginePermission::Invalid. - \sa isValid(), isTransient() + \sa isValid(), isPersistent() */ QWebEnginePermission::State QWebEnginePermission::state() const { if (!isValid()) - return Invalid; + return State::Invalid; if (d_ptr->webContentsAdapter) - return d_ptr->webContentsAdapter.toStrongRef()->getPermissionState(origin(), feature()); + return d_ptr->webContentsAdapter.toStrongRef()->getPermissionState(origin(), permissionType()); if (d_ptr->profileAdapter) - return d_ptr->profileAdapter->getPermissionState(origin(), feature()); + return d_ptr->profileAdapter->getPermissionState(origin(), permissionType()); Q_UNREACHABLE(); - return Ask; + return State::Ask; } /*! @@ -206,19 +215,19 @@ QWebEnginePermission::State QWebEnginePermission::state() const An invalid QWebEnginePermission is either: \list - \li One whose \l feature() is unsupported; - \li One whose \l feature() is transient, and the associated page/view has been destroyed; - \li One whose \l feature() is permanent, but the associated profile has been destroyed; + \li One whose \l permissionType() is unsupported; + \li One whose \l permissionType() is non-persistent, and the user has navigated away from the web page that triggered the request; + \li One whose \l permissionType() is persistent, but the associated profile has been destroyed; \li One whose \l origin() is invalid. \endlist - \sa isTransient() + \sa isPersistent() */ bool QWebEnginePermission::isValid() const { - if (feature() == Unsupported) + if (permissionType() == PermissionType::Unsupported) return false; - if (isTransient(feature()) && !d_ptr->webContentsAdapter) + if (!isPersistent(permissionType()) && !d_ptr->webContentsAdapter) return false; if (!d_ptr->profileAdapter) return false; @@ -228,7 +237,7 @@ bool QWebEnginePermission::isValid() const } /*! - Allows the associated origin to access the requested feature. Does nothing when \l isValid() evaluates to false. + Allows the associated origin to access the requested permissionType. Does nothing when \l isValid() evaluates to false. \sa deny(), reset(), isValid() */ @@ -237,13 +246,13 @@ void QWebEnginePermission::grant() const if (!isValid()) return; if (d_ptr->webContentsAdapter) - d_ptr->webContentsAdapter.toStrongRef()->setFeaturePermission(origin(), feature(), Granted); + d_ptr->webContentsAdapter.toStrongRef()->setPermission(origin(), permissionType(), State::Granted); else if (d_ptr->profileAdapter) - d_ptr->profileAdapter->setPermission(origin(), feature(), Granted); + d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Granted); } /*! - Stops the associated origin from accessing the requested feature. Does nothing when \l isValid() evaluates to false. + Stops the associated origin from accessing the requested permissionType. Does nothing when \l isValid() evaluates to false. \sa grant(), reset(), isValid() */ @@ -252,9 +261,9 @@ void QWebEnginePermission::deny() const if (!isValid()) return; if (d_ptr->webContentsAdapter) - d_ptr->webContentsAdapter.toStrongRef()->setFeaturePermission(origin(), feature(), Denied); + d_ptr->webContentsAdapter.toStrongRef()->setPermission(origin(), permissionType(), State::Denied); else if (d_ptr->profileAdapter) - d_ptr->profileAdapter->setPermission(origin(), feature(), Denied); + d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Denied); } /*! @@ -273,31 +282,31 @@ void QWebEnginePermission::reset() const if (!isValid()) return; if (d_ptr->webContentsAdapter) - d_ptr->webContentsAdapter.toStrongRef()->setFeaturePermission(origin(), feature(), Ask); + d_ptr->webContentsAdapter.toStrongRef()->setPermission(origin(), permissionType(), State::Ask); else if (d_ptr->profileAdapter) - d_ptr->profileAdapter->setPermission(origin(), feature(), Ask); + d_ptr->profileAdapter->setPermission(origin(), permissionType(), State::Ask); } /*! - Returns whether \a feature is transient, meaning that a permission will be requested - every time the associated functionality is used by a web page. + Returns whether a \a permissionType is \e persistent, meaning that a permission's state will be remembered + and the user will not be queried the next time the website requests the same permission. */ -bool QWebEnginePermission::isTransient(QWebEnginePermission::Feature feature) +bool QWebEnginePermission::isPersistent(QWebEnginePermission::PermissionType permissionType) { - switch (feature) { - case QWebEnginePermission::MediaAudioCapture: - case QWebEnginePermission::MediaVideoCapture: - case QWebEnginePermission::MediaAudioVideoCapture: - case QWebEnginePermission::DesktopVideoCapture: - case QWebEnginePermission::DesktopAudioVideoCapture: - case QWebEnginePermission::MouseLock: + switch (permissionType) { + case QWebEnginePermission::PermissionType::Notifications: + case QWebEnginePermission::PermissionType::Geolocation: + case QWebEnginePermission::PermissionType::ClipboardReadWrite: + case QWebEnginePermission::PermissionType::LocalFontsAccess: return true; - case QWebEnginePermission::Notifications: - case QWebEnginePermission::Geolocation: - case QWebEnginePermission::ClipboardReadWrite: - case QWebEnginePermission::LocalFontsAccess: + case QWebEnginePermission::PermissionType::MediaAudioCapture: + case QWebEnginePermission::PermissionType::MediaVideoCapture: + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: + case QWebEnginePermission::PermissionType::DesktopVideoCapture: + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: + case QWebEnginePermission::PermissionType::MouseLock: return false; - case QWebEnginePermission::Unsupported: + case QWebEnginePermission::PermissionType::Unsupported: return false; } diff --git a/src/core/api/qwebenginepermission.h b/src/core/api/qwebenginepermission.h index 09db8ce363d..440bf788b71 100644 --- a/src/core/api/qwebenginepermission.h +++ b/src/core/api/qwebenginepermission.h @@ -9,8 +9,17 @@ #include #include +namespace QtWebEngineCore { +class PermissionManagerQt; +} // namespace + QT_BEGIN_NAMESPACE +class QWebEnginePagePrivate; +class QWebEngineProfile; +class QQuickWebEngineViewPrivate; +class QQuickWebEngineProfile; + struct QWebEnginePermissionPrivate; QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QWebEnginePermissionPrivate, Q_WEBENGINECORE_EXPORT) @@ -19,7 +28,7 @@ class QWebEnginePermission { Q_GADGET_EXPORT(Q_WEBENGINECORE_EXPORT) Q_PROPERTY(QUrl origin READ origin CONSTANT FINAL) - Q_PROPERTY(Feature feature READ feature CONSTANT FINAL) + Q_PROPERTY(PermissionType permissionType READ permissionType CONSTANT FINAL) Q_PROPERTY(State state READ state CONSTANT FINAL) Q_PROPERTY(bool isValid READ isValid CONSTANT FINAL) Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") @@ -28,14 +37,13 @@ class QWebEnginePermission Q_WEBENGINECORE_EXPORT QWebEnginePermission(); Q_WEBENGINECORE_EXPORT QWebEnginePermission(const QWebEnginePermission &other); - Q_WEBENGINECORE_EXPORT QWebEnginePermission(QWebEnginePermissionPrivate *pvt); Q_WEBENGINECORE_EXPORT ~QWebEnginePermission(); Q_WEBENGINECORE_EXPORT QWebEnginePermission &operator=(const QWebEnginePermission &other); QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QWebEnginePermission) void swap(QWebEnginePermission &other) noexcept { d_ptr.swap(other.d_ptr); } - enum Feature : quint8 { + enum class PermissionType : quint8 { Unsupported, MediaAudioCapture, MediaVideoCapture, @@ -48,18 +56,18 @@ class QWebEnginePermission ClipboardReadWrite, LocalFontsAccess, }; - Q_ENUM(Feature) + Q_ENUM(PermissionType) - enum State : quint8 { + enum class State : quint8 { Invalid, Ask, Granted, - Denied + Denied, }; Q_ENUM(State) - Q_WEBENGINECORE_EXPORT const QUrl origin() const; - Q_WEBENGINECORE_EXPORT Feature feature() const; + Q_WEBENGINECORE_EXPORT QUrl origin() const; + Q_WEBENGINECORE_EXPORT PermissionType permissionType() const; Q_WEBENGINECORE_EXPORT State state() const; Q_WEBENGINECORE_EXPORT bool isValid() const; @@ -67,7 +75,7 @@ class QWebEnginePermission Q_WEBENGINECORE_EXPORT Q_INVOKABLE void deny() const; Q_WEBENGINECORE_EXPORT Q_INVOKABLE void reset() const; - Q_WEBENGINECORE_EXPORT Q_INVOKABLE static bool isTransient(QWebEnginePermission::Feature feature); + Q_WEBENGINECORE_EXPORT Q_INVOKABLE static bool isPersistent(QWebEnginePermission::PermissionType permissionType); private: inline friend bool operator==(const QWebEnginePermission &lhs, const QWebEnginePermission &rhs) @@ -78,6 +86,14 @@ class QWebEnginePermission Q_WEBENGINECORE_EXPORT bool comparesEqual(const QWebEnginePermission &other) const; protected: + friend class QWebEnginePagePrivate; + friend class QWebEngineProfile; + friend class QQuickWebEngineViewPrivate; + friend class QQuickWebEngineProfile; + friend class QtWebEngineCore::PermissionManagerQt; + + Q_WEBENGINECORE_EXPORT QWebEnginePermission(QWebEnginePermissionPrivate *pvt); + QExplicitlySharedDataPointer d_ptr; }; diff --git a/src/core/api/qwebenginepermission_p.h b/src/core/api/qwebenginepermission_p.h index 94c89887391..fe4dc62f81a 100644 --- a/src/core/api/qwebenginepermission_p.h +++ b/src/core/api/qwebenginepermission_p.h @@ -31,11 +31,11 @@ QT_BEGIN_NAMESPACE struct QWebEnginePermissionPrivate : public QSharedData { Q_WEBENGINECORE_EXPORT QWebEnginePermissionPrivate(); - Q_WEBENGINECORE_EXPORT QWebEnginePermissionPrivate(const QUrl &, QWebEnginePermission::Feature, + Q_WEBENGINECORE_EXPORT QWebEnginePermissionPrivate(const QUrl &, QWebEnginePermission::PermissionType, QSharedPointer, QtWebEngineCore::ProfileAdapter *); QUrl origin; - QWebEnginePermission::Feature feature; + QWebEnginePermission::PermissionType permissionType; QWeakPointer webContentsAdapter; QPointer profileAdapter; diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index 5d7bb5559b2..b238d32a5d9 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -113,18 +113,18 @@ using QtWebEngineCore::ProfileAdapter; This enum describes the policy for permission persistence: - \value NoPersistentPermissions + \value AskEveryTime The application will ask for permissions every time they're needed, regardless of whether they've been granted before or not. This is intended for backwards compatibility with existing applications, and otherwise not recommended. - \value PersistentPermissionsInMemory + \value StoreInMemory A request will be made only the first time a permission is needed. Any subsequent requests will be automatically granted or denied, depending on the initial user choice. This carries over to all pages that use the same QWebEngineProfile instance, until the application is shut down. This is the setting applied if \c off-the-record is set or no persistent data path is available. - \value PersistentPermissionsOnDisk - Works the same way as \c PersistentPermissionsInMemory, but the permissions are saved to + \value StoreOnDisk + Works the same way as \c StoreInMemory, but the permissions are saved to and restored from disk. This is the default setting. */ @@ -597,9 +597,9 @@ void QWebEngineProfile::setPersistentCookiesPolicy(QWebEngineProfile::Persistent Returns the current policy for persistent permissions. Off-the-record profiles are not allowed to save data to the disk, so they can only return - PersistentPermissionsInMemory or NoPersistentPermissions. + \c StoreInMemory or \c AskEveryTime. - \sa setPersistentPermissionsPolicy() + \sa QWebEngineProfile::PersistentPermissionsPolicy, setPersistentPermissionsPolicy() */ QWebEngineProfile::PersistentPermissionsPolicy QWebEngineProfile::persistentPermissionsPolicy() const { @@ -610,7 +610,7 @@ QWebEngineProfile::PersistentPermissionsPolicy QWebEngineProfile::persistentPerm /*! Sets the policy for persistent permissions to \a newPersistentPermissionsPolicy. - \sa persistentPermissionsPolicy() + \sa QWebEngineProfile::PersistentPermissionsPolicy, persistentPermissionsPolicy() */ void QWebEngineProfile::setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy newPersistentPermissionsPolicy) { @@ -979,44 +979,45 @@ void QWebEngineProfile::requestIconForIconURL(const QUrl &url, int desiredSizeIn /*! * Returns a QWebEnginePermission object corresponding to a single permission for the provided \a securityOrigin and - * \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + * \a permissionType. The object may be used to query for the current state of the permission, or to change it. It is not required * for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is * known to use it. * - * \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + * \note This may only be used for persistent permission types. Calling it with a non-persistent type will return an invalid object. * \since 6.8 - * \sa listPermissions(), QWebEnginePermission::Feature + * \sa listAllPermissions(), listPermissionsForOrigin(), listPermissionsForPermissionType(), QWebEnginePermission::PermissionType */ -QWebEnginePermission QWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const +QWebEnginePermission QWebEngineProfile::queryPermission(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) const { Q_D(const QWebEngineProfile); - if (feature == QWebEnginePermission::Unsupported) { + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) { qWarning("Attempting to get unsupported permission. Returned object will be in an invalid state."); return QWebEnginePermission(new QWebEnginePermissionPrivate()); } - if (QWebEnginePermission::isTransient(feature)) { - qWarning() << "Attempting to get permission for feature" << feature << ". Returned object will be in an invalid state."; + if (!QWebEnginePermission::isPersistent(permissionType)) { + qWarning() << "Attempting to get permission for permission type" << permissionType << ". Returned object will be in an invalid state."; return QWebEnginePermission(new QWebEnginePermissionPrivate()); } - auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, feature, nullptr, d->profileAdapter()); + auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, permissionType, nullptr, d->profileAdapter()); return QWebEnginePermission(pvt); } /*! * Returns a QList of QWebEnginePermission objects, each one representing a single permission currently * present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, - * except for those of a transient feature type. + * provided they are of a \e persistent type. * + * \note When persistentPermissionPolicy() is set to \c AskEveryTime, this will return an empty list. * \since 6.8 - * \sa getPermission(), QWebEnginePermission::Feature + * \sa queryPermission(), QWebEnginePermission::PermissionType, QWebEnginePermission::isPersistent() */ -QList QWebEngineProfile::listPermissions() const +QList QWebEngineProfile::listAllPermissions() const { Q_D(const QWebEngineProfile); - if (persistentPermissionsPolicy() == NoPersistentPermissions) + if (persistentPermissionsPolicy() == PersistentPermissionsPolicy::AskEveryTime) return QList(); return d->profileAdapter()->listPermissions(); } @@ -1024,46 +1025,49 @@ QList QWebEngineProfile::listPermissions() const /*! * Returns a QList of QWebEnginePermission objects, each one representing a single permission currently * present in the permissions store. The returned list contains all previously granted/denied permissions associated with a - * specific \a securityOrigin for this profile, except for those of a transient feature type. + * specific \a securityOrigin for this profile, provided they are of a \e persistent type. * * \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its * origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html * is the same as passing just https://www.example.com/. + * \note When persistentPermissionPolicy() is set to \c AskEveryTime, this will return an empty list. * \since 6.8 - * \sa getPermission(), QWebEnginePermission::Feature + * \sa queryPermission(), QWebEnginePermission::PermissionType, QWebEnginePermission::isPersistent() */ -QList QWebEngineProfile::listPermissions(const QUrl &securityOrigin) const +QList QWebEngineProfile::listPermissionsForOrigin(const QUrl &securityOrigin) const { Q_D(const QWebEngineProfile); - if (persistentPermissionsPolicy() == NoPersistentPermissions) + if (persistentPermissionsPolicy() == PersistentPermissionsPolicy::AskEveryTime) return QList(); return d->profileAdapter()->listPermissions(securityOrigin); } /*! * Returns a QList of QWebEnginePermission objects, each one representing a single permission currently - * present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature - * type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + * present in the permissions store. The returned list contains all previously granted/denied permissions of the provided + * \a permissionType. If the \permissionType is non-persistent, the list will be empty. + * + * \note When persistentPermissionPolicy() is set to \c AskEveryTime, this will return an empty list. * \since 6.8 - * \sa getPermission(), QWebEnginePermission::Feature + * \sa queryPermission(), QWebEnginePermission::PermissionType, QWebEnginePermission::isPersistent() */ -QList QWebEngineProfile::listPermissions(QWebEnginePermission::Feature feature) const +QList QWebEngineProfile::listPermissionsForPermissionType(QWebEnginePermission::PermissionType permissionType) const { Q_D(const QWebEngineProfile); - if (persistentPermissionsPolicy() == NoPersistentPermissions) + if (persistentPermissionsPolicy() == PersistentPermissionsPolicy::AskEveryTime) return QList(); - if (feature == QWebEnginePermission::Unsupported) { + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) { qWarning("Attempting to get permission list for an unsupported type. Returned list will be empty."); return QList(); } - if (QWebEnginePermission::isTransient(feature)) { - qWarning() << "Attempting to get permission list for feature" << feature << ". Returned list will be empty."; + if (!QWebEnginePermission::isPersistent(permissionType)) { + qWarning() << "Attempting to get permission list for permission type" << permissionType << ". Returned list will be empty."; return QList(); } - return d->profileAdapter()->listPermissions(QUrl(), feature); + return d->profileAdapter()->listPermissions(QUrl(), permissionType); } /*! diff --git a/src/core/api/qwebengineprofile.h b/src/core/api/qwebengineprofile.h index 573f39e7dd3..c83ffbe3343 100644 --- a/src/core/api/qwebengineprofile.h +++ b/src/core/api/qwebengineprofile.h @@ -50,10 +50,10 @@ class Q_WEBENGINECORE_EXPORT QWebEngineProfile : public QObject }; Q_ENUM(PersistentCookiesPolicy) - enum PersistentPermissionsPolicy : quint8 { - NoPersistentPermissions, - PersistentPermissionsInMemory, - PersistentPermissionsOnDisk, + enum class PersistentPermissionsPolicy : quint8 { + AskEveryTime = 0, + StoreInMemory, + StoreOnDisk, }; Q_ENUM(PersistentPermissionsPolicy) @@ -121,10 +121,10 @@ class Q_WEBENGINECORE_EXPORT QWebEngineProfile : public QObject void requestIconForPageURL(const QUrl &url, int desiredSizeInPixel, std::function iconAvailableCallback) const; void requestIconForIconURL(const QUrl &url, int desiredSizeInPixel, std::function iconAvailableCallback) const; - QWebEnginePermission getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const; - QList listPermissions() const; - QList listPermissions(const QUrl &securityOrigin) const; - QList listPermissions(QWebEnginePermission::Feature feature) const; + QWebEnginePermission queryPermission(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) const; + QList listAllPermissions() const; + QList listPermissionsForOrigin(const QUrl &securityOrigin) const; + QList listPermissionsForPermissionType(QWebEnginePermission::PermissionType permissionType) const; static QWebEngineProfile *defaultProfile(); diff --git a/src/core/doc/src/qtwebengine-features.qdoc b/src/core/doc/src/qtwebengine-features.qdoc index 9465d75a201..c7221677cd1 100644 --- a/src/core/doc/src/qtwebengine-features.qdoc +++ b/src/core/doc/src/qtwebengine-features.qdoc @@ -358,9 +358,9 @@ \QWE supports JavaScript Geolocation API with \l {Qt Positioning} as a backend. HTML5 geolocation is disabled by default. To explicitly allow it, the application - needs to listen to QWebEnginePage::featurePermissionRequested. Use QWebEnginePage::Geolocation - with a QWebEnginePage::setFeaturePermission() call or \l{WebEngineView::Feature} - with a \l{WebEngineView::grantFeaturePermission} {WebEngineView.grantFeaturePermission}() call + needs to listen to QWebEnginePage::permissionRequested. When a permission request + with a type of QWebEnginePermission::PermissionType::Geolocation is received, + you can call QWebEnginePermission::grant() on the received object to grant the required permission. If \QWE was built with Qt Positioning support then this feature can be diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 1f826e7124d..b9a327d51cb 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -28,30 +28,30 @@ namespace QtWebEngineCore { -static QWebEnginePermission::Feature toQt(blink::PermissionType type) +static QWebEnginePermission::PermissionType toQt(blink::PermissionType type) { switch (type) { case blink::PermissionType::GEOLOCATION: - return QWebEnginePermission::Geolocation; + return QWebEnginePermission::PermissionType::Geolocation; case blink::PermissionType::AUDIO_CAPTURE: - return QWebEnginePermission::MediaAudioCapture; + return QWebEnginePermission::PermissionType::MediaAudioCapture; case blink::PermissionType::VIDEO_CAPTURE: - return QWebEnginePermission::MediaVideoCapture; + return QWebEnginePermission::PermissionType::MediaVideoCapture; case blink::PermissionType::DISPLAY_CAPTURE: - return QWebEnginePermission::DesktopAudioVideoCapture; + return QWebEnginePermission::PermissionType::DesktopAudioVideoCapture; // We treat these both as read/write since we do not currently have a - // ClipboardSanitizedWrite feature. + // ClipboardSanitizedWrite permission type. case blink::PermissionType::CLIPBOARD_READ_WRITE: case blink::PermissionType::CLIPBOARD_SANITIZED_WRITE: - return QWebEnginePermission::ClipboardReadWrite; + return QWebEnginePermission::PermissionType::ClipboardReadWrite; case blink::PermissionType::NOTIFICATIONS: - return QWebEnginePermission::Notifications; + return QWebEnginePermission::PermissionType::Notifications; case blink::PermissionType::LOCAL_FONTS: - return QWebEnginePermission::LocalFontsAccess; + return QWebEnginePermission::PermissionType::LocalFontsAccess; case blink::PermissionType::ACCESSIBILITY_EVENTS: case blink::PermissionType::CAMERA_PAN_TILT_ZOOM: case blink::PermissionType::WINDOW_MANAGEMENT: - return QWebEnginePermission::Unsupported; + return QWebEnginePermission::PermissionType::Unsupported; case blink::PermissionType::MIDI_SYSEX: case blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER: case blink::PermissionType::MIDI: @@ -76,31 +76,31 @@ static QWebEnginePermission::Feature toQt(blink::PermissionType type) LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast(type); break; } - return QWebEnginePermission::Unsupported; + return QWebEnginePermission::PermissionType::Unsupported; } -static blink::PermissionType toBlink(QWebEnginePermission::Feature feature) +static blink::PermissionType toBlink(QWebEnginePermission::PermissionType permissionType) { - switch (feature) { - case QWebEnginePermission::Notifications: + switch (permissionType) { + case QWebEnginePermission::PermissionType::Notifications: return blink::PermissionType::NOTIFICATIONS; - case QWebEnginePermission::Geolocation: + case QWebEnginePermission::PermissionType::Geolocation: return blink::PermissionType::GEOLOCATION; - case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::PermissionType::MediaAudioCapture: return blink::PermissionType::AUDIO_CAPTURE; - case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::PermissionType::MediaVideoCapture: return blink::PermissionType::VIDEO_CAPTURE; - case QWebEnginePermission::DesktopVideoCapture: - case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::PermissionType::DesktopVideoCapture: + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: return blink::PermissionType::DISPLAY_CAPTURE; - case QWebEnginePermission::ClipboardReadWrite: + case QWebEnginePermission::PermissionType::ClipboardReadWrite: return blink::PermissionType::CLIPBOARD_READ_WRITE; - case QWebEnginePermission::LocalFontsAccess: + case QWebEnginePermission::PermissionType::LocalFontsAccess: return blink::PermissionType::LOCAL_FONTS; - case QWebEnginePermission::MediaAudioVideoCapture: - case QWebEnginePermission::MouseLock: - case QWebEnginePermission::Unsupported: - LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast(feature); + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: + case QWebEnginePermission::PermissionType::MouseLock: + case QWebEnginePermission::PermissionType::Unsupported: + LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast(permissionType); return blink::PermissionType::NUM; } @@ -111,46 +111,46 @@ static QWebEnginePermission::State toQt(blink::mojom::PermissionStatus state) { switch (state) { case blink::mojom::PermissionStatus::ASK: - return QWebEnginePermission::Ask; + return QWebEnginePermission::State::Ask; case blink::mojom::PermissionStatus::GRANTED: - return QWebEnginePermission::Granted; + return QWebEnginePermission::State::Granted; case blink::mojom::PermissionStatus::DENIED: - return QWebEnginePermission::Denied; + return QWebEnginePermission::State::Denied; } } static blink::mojom::PermissionStatus toBlink(QWebEnginePermission::State state) { switch (state) { - case QWebEnginePermission::Invalid: - case QWebEnginePermission::Ask: + case QWebEnginePermission::State::Invalid: + case QWebEnginePermission::State::Ask: return blink::mojom::PermissionStatus::ASK; - case QWebEnginePermission::Granted: + case QWebEnginePermission::State::Granted: return blink::mojom::PermissionStatus::GRANTED; - case QWebEnginePermission::Denied: + case QWebEnginePermission::State::Denied: return blink::mojom::PermissionStatus::DENIED; } } -std::string featureString(QWebEnginePermission::Feature feature) +std::string permissionTypeString(QWebEnginePermission::PermissionType permissionType) { - // This is separate from blink::featureString() for the sake of future-proofing; + // This is separate from blink::permissionTypeString() for the sake of future-proofing; // e.g. in case we add extra Features that do not correspond to a PermissionType, and // we need to store them. - switch (feature) { - case QWebEnginePermission::Notifications: + switch (permissionType) { + case QWebEnginePermission::PermissionType::Notifications: return "Notifications"; - case QWebEnginePermission::Geolocation: + case QWebEnginePermission::PermissionType::Geolocation: return "Geolocation"; - case QWebEnginePermission::ClipboardReadWrite: + case QWebEnginePermission::PermissionType::ClipboardReadWrite: return "ClipboardReadWrite"; - case QWebEnginePermission::LocalFontsAccess: + case QWebEnginePermission::PermissionType::LocalFontsAccess: return "LocalFontsAccess"; - case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::PermissionType::MediaAudioCapture: return "MediaAudioCapture"; - case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::PermissionType::MediaVideoCapture: return "MediaVideoCapture"; - case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: return "DesktopAudioVideoCapture"; default: Q_UNREACHABLE(); @@ -186,7 +186,7 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) auto prefRegistry = base::MakeRefCounted(); auto policy = profileAdapter->persistentPermissionsPolicy(); - if (!profileAdapter->isOffTheRecord() && policy == ProfileAdapter::PersistentPermissionsOnDisk && + if (!profileAdapter->isOffTheRecord() && policy == ProfileAdapter::PersistentPermissionsPolicy::StoreOnDisk && !userPrefStorePath.isEmpty() && profileAdapter->ensureDataPathExists()) { userPrefStorePath += QDir::separator(); userPrefStorePath += QStringLiteral("permissions.json"); @@ -195,22 +195,22 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) factory.set_user_prefs(new InMemoryPrefStore); } - m_featureTypes.push_back(QWebEnginePermission::Notifications); - m_featureTypes.push_back(QWebEnginePermission::Geolocation); - m_featureTypes.push_back(QWebEnginePermission::ClipboardReadWrite); - m_featureTypes.push_back(QWebEnginePermission::LocalFontsAccess); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::Notifications); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::Geolocation); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::ClipboardReadWrite); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::LocalFontsAccess); // Transient, but the implementation relies on them being written to storage - m_featureTypes.push_back(QWebEnginePermission::MediaAudioCapture); - m_featureTypes.push_back(QWebEnginePermission::MediaVideoCapture); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaAudioCapture); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaVideoCapture); // Register all preference types as keys prior to doing anything else - for (auto &type : m_featureTypes) { - prefRegistry->RegisterDictionaryPref(featureString(type)); + for (auto &type : m_permissionTypes) { + prefRegistry->RegisterDictionaryPref(permissionTypeString(type)); } PrefProxyConfigTrackerImpl::RegisterPrefs(prefRegistry.get()); - if (policy == ProfileAdapter::NoPersistentPermissions) + if (policy == ProfileAdapter::PersistentPermissionsPolicy::AskEveryTime) m_persistence = false; { @@ -224,22 +224,22 @@ PermissionManagerQt::~PermissionManagerQt() commit(); } -void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::Feature feature, QWebEnginePermission::State state) +void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state) { // Normalize the QUrl to Chromium origin form. const GURL gorigin = toG/service/https://github.com/url(url).DeprecatedGetOriginAsURL(); const QUrl origin = gorigin.is_empty() ? url : toQt(gorigin); if (origin.isEmpty()) return; - if (state == QWebEnginePermission::Ask) - ResetPermission(toBlink(feature), gorigin, gorigin); + if (state == QWebEnginePermission::State::Ask) + ResetPermission(toBlink(permissionType), gorigin, gorigin); else - setPermission(toBlink(feature), gorigin, state == QWebEnginePermission::Granted); + setPermission(toBlink(permissionType), gorigin, state == QWebEnginePermission::State::Granted); blink::mojom::PermissionStatus status = toBlink(state); - if (state != QWebEnginePermission::Ask) { + if (state != QWebEnginePermission::State::Ask) { auto it = m_requests.begin(); while (it != m_requests.end()) { - if (it->origin == origin && it->type == feature) { + if (it->origin == origin && it->type == permissionType) { std::move(it->callback).Run(status); it = m_requests.erase(it); } else @@ -247,12 +247,12 @@ void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::F } } - for (const auto &it: m_subscribers) { - if (it.second.origin == origin && it.second.type == feature) + for (const auto &it : m_subscribers) { + if (it.second.origin == origin && it.second.type == permissionType) it.second.callback.Run(status); } - if (state == QWebEnginePermission::Ask) + if (state == QWebEnginePermission::State::Ask) return; auto it = m_multiRequests.begin(); @@ -262,7 +262,7 @@ void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::F std::vector result; result.reserve(it->types.size()); for (blink::PermissionType permission : it->types) { - if (toQt(permission) == QWebEnginePermission::Unsupported) { + if (toQt(permission) == QWebEnginePermission::PermissionType::Unsupported) { result.push_back(blink::mojom::PermissionStatus::DENIED); continue; } @@ -276,7 +276,7 @@ void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::F result.push_back(permissionStatus); } else { - // Reached when the PersistentPermissionsPolicy is set to NoPersistentPermissions + // Reached when the PersistentPermissionsPolicy is set to AskEveryTime result.push_back(toBlink(state)); } } @@ -290,14 +290,14 @@ void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::F } } -QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature) +QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) { - return toQt(GetPermissionStatus(toBlink(feature), toGurl(https://github.com/origin), GURL())); + return toQt(GetPermissionStatus(toBlink(permissionType), toGurl(https://github.com/origin), GURL())); } -QList PermissionManagerQt::listPermissions(const QUrl &origin, QWebEnginePermission::Feature feature) +QList PermissionManagerQt::listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) { - Q_ASSERT(origin.isEmpty() || feature == QWebEnginePermission::Unsupported); + Q_ASSERT(origin.isEmpty() || permissionType == QWebEnginePermission::PermissionType::Unsupported); QList returnList; GURL gorigin = toGurl(https://github.com/origin).DeprecatedGetOriginAsURL(); std::string originSpec = gorigin.spec(); @@ -305,19 +305,19 @@ QList PermissionManagerQt::listPermissions(const QUrl &ori if (!origin.isEmpty() && !gorigin.is_valid()) return returnList; - std::vector types; - if (feature == QWebEnginePermission::Unsupported) - types = m_featureTypes; + std::vector types; + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) + types = m_permissionTypes; else - types.push_back(feature); + types.push_back(permissionType); for (auto &type : types) { // Transient types may end up in the permission store as an implementation detail, // but we do not want to expose them to callers. - if (QWebEnginePermission::isTransient(type)) + if (!QWebEnginePermission::isPersistent(type)) continue; - auto *pref = m_prefService->FindPreference(featureString(type)); + auto *pref = m_prefService->FindPreference(permissionTypeString(type)); if (!pref) continue; @@ -360,8 +360,8 @@ void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost std::vector result; result.reserve(requestDescription.permissions.size()); for (blink::PermissionType permission : requestDescription.permissions) { - const QWebEnginePermission::Feature feature = toQt(permission); - if (feature == QWebEnginePermission::Unsupported) { + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) { result.push_back(blink::mojom::PermissionStatus::DENIED); continue; } @@ -391,9 +391,9 @@ void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost auto requestOrigin = toQt(requestDescription.requesting_origin); m_multiRequests.push_back({ request_id, requestDescription.permissions, requestOrigin, std::move(callback) }); for (blink::PermissionType permission : requestDescription.permissions) { - const QWebEnginePermission::Feature feature = toQt(permission); - if (!QWebEnginePermission::isTransient(feature)) - contentsDelegate->requestFeaturePermission(feature, requestOrigin); + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (QWebEnginePermission::isPersistent(permissionType)) + contentsDelegate->requestFeaturePermission(permissionType, requestOrigin); } } @@ -409,12 +409,12 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus( const GURL& requesting_origin, const GURL& /*embedding_origin*/) { - const QWebEnginePermission::Feature feature = toQt(permission); - if (feature == QWebEnginePermission::Unsupported) + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) return blink::mojom::PermissionStatus::DENIED; permission = toBlink(toQt(permission)); // Filter out merged/unsupported permissions (e.g. clipboard) - auto *pref = m_prefService->FindPreference(featureString(toQt(permission))); + auto *pref = m_prefService->FindPreference(permissionTypeString(toQt(permission))); if (!pref) return blink::mojom::PermissionStatus::ASK; // Permission type not in database @@ -429,7 +429,7 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus( // it's checked whether the permission has been granted. By always returning ASK, we force the request to // come through every time. if (permission == blink::PermissionType::LOCAL_FONTS - && m_profileAdapter->persistentPermissionsPolicy() == ProfileAdapter::NoPersistentPermissions) + && m_profileAdapter->persistentPermissionsPolicy() == ProfileAdapter::PersistentPermissionsPolicy::AskEveryTime) return blink::mojom::PermissionStatus::ASK; if (requestedPermission.value()) @@ -490,11 +490,11 @@ void PermissionManagerQt::ResetPermission( const GURL& requesting_origin, const GURL& /*embedding_origin*/) { - const QWebEnginePermission::Feature feature = toQt(permission); - if (feature == QWebEnginePermission::Unsupported) + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) return; - ScopedDictPrefUpdate updater(m_prefService.get(), featureString(feature)); + ScopedDictPrefUpdate updater(m_prefService.get(), permissionTypeString(permissionType)); updater.Get().Remove(requesting_origin.spec()); } @@ -522,14 +522,14 @@ void PermissionManagerQt::setPermission( const GURL& requesting_origin, bool granted) { - const QWebEnginePermission::Feature feature = toQt(permission); - if (feature == QWebEnginePermission::Unsupported) + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) return; - if (!m_prefService->FindPreference(featureString(feature))) + if (!m_prefService->FindPreference(permissionTypeString(permissionType))) return; - ScopedDictPrefUpdate updater(m_prefService.get(), featureString(feature)); + ScopedDictPrefUpdate updater(m_prefService.get(), permissionTypeString(permissionType)); updater.Get().Set(requesting_origin.spec(), granted); } diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 6a4df2efa80..ea69243b5f1 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -22,9 +22,9 @@ class PermissionManagerQt : public content::PermissionControllerDelegate PermissionManagerQt(ProfileAdapter *adapter); ~PermissionManagerQt(); - void setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state); - QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature); - QList listPermissions(const QUrl &origin, QWebEnginePermission::Feature feature); + void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state); + QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType); + QList listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType); void commit(); @@ -68,7 +68,7 @@ class PermissionManagerQt : public content::PermissionControllerDelegate private: struct Request { int id; - QWebEnginePermission::Feature type; + QWebEnginePermission::PermissionType type; QUrl origin; base::OnceCallback callback; }; @@ -79,7 +79,7 @@ class PermissionManagerQt : public content::PermissionControllerDelegate base::OnceCallback&)> callback; }; struct Subscription { - QWebEnginePermission::Feature type; + QWebEnginePermission::PermissionType type; QUrl origin; base::RepeatingCallback callback; }; @@ -90,7 +90,7 @@ class PermissionManagerQt : public content::PermissionControllerDelegate std::vector m_requests; std::vector m_multiRequests; - std::vector m_featureTypes; + std::vector m_permissionTypes; std::map m_subscribers; content::PermissionControllerDelegate::SubscriptionId::Generator subscription_id_generator_; int m_requestIdCount; diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 1f006295322..031ee6dec87 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -63,7 +63,7 @@ ProfileAdapter::ProfileAdapter(const QString &storageName): , m_downloadPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) , m_httpCacheType(DiskHttpCache) , m_persistentCookiesPolicy(AllowPersistentCookies) - , m_persistentPermissionsPolicy(PersistentPermissionsOnDisk) + , m_persistentPermissionsPolicy(PersistentPermissionsPolicy::StoreOnDisk) , m_visitedLinksPolicy(TrackVisitedLinksOnDisk) , m_clientHintsEnabled(true) , m_pushServiceEnabled(false) @@ -265,6 +265,7 @@ void ProfileAdapter::setDataPath(const QString &path) return; m_dataPath = path; m_profile->setupPrefService(); + m_profile->setupPermissionsManager(); if (!m_profile->m_profileIOData->isClearHttpCacheInProgress()) m_profile->m_profileIOData->resetNetworkContext(); if (!m_offTheRecord && m_visitedLinksManager) @@ -377,10 +378,10 @@ void ProfileAdapter::setPersistentCookiesPolicy(ProfileAdapter::PersistentCookie ProfileAdapter::PersistentPermissionsPolicy ProfileAdapter::persistentPermissionsPolicy() const { - if (m_persistentPermissionsPolicy == NoPersistentPermissions) - return NoPersistentPermissions; + if (m_persistentPermissionsPolicy == PersistentPermissionsPolicy::AskEveryTime) + return PersistentPermissionsPolicy::AskEveryTime; if (isOffTheRecord() || m_name.isEmpty()) - return PersistentPermissionsInMemory; + return PersistentPermissionsPolicy::StoreInMemory; return m_persistentPermissionsPolicy; } @@ -567,25 +568,25 @@ UserResourceControllerHost *ProfileAdapter::userResourceController() return m_userResourceController.data(); } -void ProfileAdapter::setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state) +void ProfileAdapter::setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state) { - static_cast(profile()->GetPermissionControllerDelegate())->setPermission(origin, feature, state); + static_cast(profile()->GetPermissionControllerDelegate())->setPermission(origin, permissionType, state); } -QWebEnginePermission::State ProfileAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature) +QWebEnginePermission::State ProfileAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) { - if (persistentPermissionsPolicy() == ProfileAdapter::NoPersistentPermissions) - return QWebEnginePermission::Ask; + if (persistentPermissionsPolicy() == ProfileAdapter::PersistentPermissionsPolicy::AskEveryTime) + return QWebEnginePermission::State::Ask; - return static_cast(profile()->GetPermissionControllerDelegate())->getPermissionState(origin, feature); + return static_cast(profile()->GetPermissionControllerDelegate())->getPermissionState(origin, permissionType); } -QList ProfileAdapter::listPermissions(const QUrl &origin, QWebEnginePermission::Feature feature) +QList ProfileAdapter::listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) { - if (persistentPermissionsPolicy() == ProfileAdapter::NoPersistentPermissions) + if (persistentPermissionsPolicy() == ProfileAdapter::PersistentPermissionsPolicy::AskEveryTime) return QList(); - return static_cast(profile()->GetPermissionControllerDelegate())->listPermissions(origin, feature); + return static_cast(profile()->GetPermissionControllerDelegate())->listPermissions(origin, permissionType); } QString ProfileAdapter::httpAcceptLanguageWithoutQualities() const diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 6550e617696..d0194df99c7 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -128,10 +128,10 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject TrackVisitedLinksOnDisk, }; - enum PersistentPermissionsPolicy { - NoPersistentPermissions = 0, - PersistentPermissionsInMemory, - PersistentPermissionsOnDisk, + enum class PersistentPermissionsPolicy : quint8 { + AskEveryTime = 0, + StoreInMemory, + StoreOnDisk, }; enum ClientHint : uchar { @@ -172,9 +172,10 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject const QList customUrlSchemes() const; UserResourceControllerHost *userResourceController(); - void setPermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state); - QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature); - QList listPermissions(const QUrl &origin = QUrl(), QWebEnginePermission::Feature feature = QWebEnginePermission::Unsupported); + void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state); + QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType); + QList listPermissions(const QUrl &origin = QUrl(), + QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType::Unsupported); QString httpAcceptLanguageWithoutQualities() const; QString httpAcceptLanguage() const; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index ed169b161e5..a40f641c11b 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1411,26 +1411,27 @@ QSizeF WebContentsAdapter::lastContentsSize() const return QSizeF(); } -void WebContentsAdapter::setFeaturePermission(const QUrl &origin, QWebEnginePermission::Feature feature, QWebEnginePermission::State state) +void WebContentsAdapter::setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state) { - if (!QWebEnginePermission::isTransient(feature)) { + if (QWebEnginePermission::isPersistent(permissionType)) { // Do not check for initialization in this path so permissions can be set before first navigation Q_ASSERT(m_profileAdapter); - m_profileAdapter->setPermission(origin, feature, state); + m_profileAdapter->setPermission(origin, permissionType, state); return; } CHECK_INITIALIZED(); - if (feature == QWebEnginePermission::MouseLock) { + + if (permissionType == QWebEnginePermission::PermissionType::MouseLock) { switch (state) { - case QWebEnginePermission::Invalid: - case QWebEnginePermission::Ask: + case QWebEnginePermission::State::Invalid: + case QWebEnginePermission::State::Ask: // Do nothing break; - case QWebEnginePermission::Denied: + case QWebEnginePermission::State::Denied: grantMouseLockPermission(origin, false); break; - case QWebEnginePermission::Granted: + case QWebEnginePermission::State::Granted: grantMouseLockPermission(origin, true); break; } @@ -1446,33 +1447,33 @@ void WebContentsAdapter::setFeaturePermission(const QUrl &origin, QWebEnginePerm WebContentsAdapterClient::MediaDesktopAudioCapture); switch (state) { - case QWebEnginePermission::Invalid: - case QWebEnginePermission::Ask: + case QWebEnginePermission::State::Invalid: + case QWebEnginePermission::State::Ask: // Do nothing return; - case QWebEnginePermission::Denied: + case QWebEnginePermission::State::Denied: // Deny all media access grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaNone); return; - case QWebEnginePermission::Granted: + case QWebEnginePermission::State::Granted: // Enable only the requested capture type break; } - switch (feature) { - case QWebEnginePermission::MediaAudioVideoCapture: + switch (permissionType) { + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: grantMediaAccessPermission(origin, audioVideoCaptureFlags); break; - case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::PermissionType::MediaAudioCapture: grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaAudioCapture); break; - case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::PermissionType::MediaVideoCapture: grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaVideoCapture); break; - case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: grantMediaAccessPermission(origin, desktopAudioVideoCaptureFlags); break; - case QWebEnginePermission::DesktopVideoCapture: + case QWebEnginePermission::PermissionType::DesktopVideoCapture: grantMediaAccessPermission(origin, WebContentsAdapterClient::MediaDesktopVideoCapture); break; default: @@ -1481,13 +1482,13 @@ void WebContentsAdapter::setFeaturePermission(const QUrl &origin, QWebEnginePerm } } -QWebEnginePermission::State WebContentsAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::Feature feature) +QWebEnginePermission::State WebContentsAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) { - // For now, we just return Ask for transient Features - if (QWebEnginePermission::isTransient(feature)) - return QWebEnginePermission::Ask; + // For now, we just return Ask for transient (a.k.a non-persistent) PermissionTypes + if (!QWebEnginePermission::isPersistent(permissionType)) + return QWebEnginePermission::State::Ask; - return m_profileAdapter->getPermissionState(origin, feature); + return m_profileAdapter->getPermissionState(origin, permissionType); } void WebContentsAdapter::grantMediaAccessPermission(const QUrl &origin, WebContentsAdapterClient::MediaRequestFlags flags) @@ -1495,9 +1496,9 @@ void WebContentsAdapter::grantMediaAccessPermission(const QUrl &origin, WebConte CHECK_INITIALIZED(); // Let the permission manager remember the reply. if (flags & WebContentsAdapterClient::MediaAudioCapture) - m_profileAdapter->setPermission(origin, QWebEnginePermission::MediaAudioCapture, QWebEnginePermission::Granted); + m_profileAdapter->setPermission(origin, QWebEnginePermission::PermissionType::MediaAudioCapture, QWebEnginePermission::State::Granted); if (flags & WebContentsAdapterClient::MediaVideoCapture) - m_profileAdapter->setPermission(origin, QWebEnginePermission::MediaVideoCapture, QWebEnginePermission::Granted); + m_profileAdapter->setPermission(origin, QWebEnginePermission::PermissionType::MediaVideoCapture, QWebEnginePermission::State::Granted); MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), origin, flags); } diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 66736dd2151..41a296072ba 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -179,8 +179,8 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapter : public QEnableSharedFromThis) = 0; - virtual void runFeaturePermissionRequest(QWebEnginePermission::Feature, const QUrl &securityOrigin) = 0; + virtual void runFeaturePermissionRequest(QWebEnginePermission::PermissionType, const QUrl &securityOrigin) = 0; virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) = 0; virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) = 0; virtual void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) = 0; @@ -229,7 +229,7 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapterClient { virtual WebContentsAdapter* webContentsAdapter() = 0; virtual void releaseProfile() = 0; virtual void showWebAuthDialog(QWebEngineWebAuthUxRequest *request) = 0; - virtual QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) = 0; + virtual QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) = 0; }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index c2cd6981ab3..2eada9d3c86 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -741,9 +741,9 @@ void WebContentsDelegateQt::selectClientCert(const QSharedPointerselectClientCert(selectController); } -void WebContentsDelegateQt::requestFeaturePermission(QWebEnginePermission::Feature feature, const QUrl &requestingOrigin) +void WebContentsDelegateQt::requestFeaturePermission(QWebEnginePermission::PermissionType permissionType, const QUrl &requestingOrigin) { - m_viewClient->runFeaturePermissionRequest(feature, requestingOrigin); + m_viewClient->runFeaturePermissionRequest(permissionType, requestingOrigin); } extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); @@ -800,9 +800,11 @@ bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost { switch (type) { case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE: - return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::MediaAudioCapture); + return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::PermissionType::MediaAudioCapture) + == QWebEnginePermission::State::Granted; case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE: - return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::MediaVideoCapture); + return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::PermissionType::MediaVideoCapture) + == QWebEnginePermission::State::Granted; default: LOG(INFO) << "WebContentsDelegateQt::CheckMediaAccessPermission: " << "Unsupported media stream type checked " << type; diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 899d46cd0c6..8188b3dea9f 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -139,7 +139,7 @@ class WebContentsDelegateQt : public content::WebContentsDelegate void overrideWebPreferences(content::WebContents *, blink::web_pref::WebPreferences*); void allowCertificateError(const QSharedPointer &); void selectClientCert(const QSharedPointer &); - void requestFeaturePermission(QWebEnginePermission::Feature feature, const QUrl &requestingOrigin); + void requestFeaturePermission(QWebEnginePermission::PermissionType permissionType, const QUrl &requestingOrigin); void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture); FindTextHelper *findTextHelper(); diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index 0246eb64549..1979d18a0cd 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -102,17 +102,17 @@ QT_BEGIN_NAMESPACE This enum describes the policy for permission persistence: - \value NoPersistentPermissions + \value AskEveryTime The application will ask for permissions every time they're needed, regardless of whether they've been granted before or not. This is intended for backwards compatibility with existing applications, and otherwise not recommended. - \value PersistentPermissionsInMemory + \value StoreInMemory A request will be made only the first time a permission is needed. Any subsequent requests will be automatically granted or denied, depending on the initial user choice. This carries over to all pages that use the same QQuickWebEngineProfile instance, until the application is shut down. This is the setting applied if \c off-the-record is set or no persistent data path is available. - \value PersistentPermissionsOnDisk + \value StoreOnDisk Works the same way as \c PersistentPermissionsInMemory, but the permissions are saved to and restored from disk. This is the default setting. */ @@ -714,17 +714,17 @@ void QQuickWebEngineProfile::setPersistentCookiesPolicy(QQuickWebEngineProfile:: This enumeration describes the policy for permission persistence: - \value WebEngineProfile.NoPersistentPermissions + \value WebEngineProfile.AskEveryTime The application will ask for permissions every time they're needed, regardless of whether they've been granted before or not. This is intended for backwards compatibility with existing applications, and otherwise not recommended. - \value WebEngineProfile.PersistentPermissionsInMemory + \value WebEngineProfile.StoreInMemory A request will be made only the first time a permission is needed. Any subsequent requests will be automatically granted or denied, depending on the initial user choice. This carries over to all pages using the same QWebEngineProfile instance, until the application is shut down. This is the setting applied if \c off-the-record is set or no persistent data path is available. - \value WebEngineProfile.PersistentPermissionsOnDisk + \value WebEngineProfile.StoreOnDisk Works the same way as \c PersistentPermissionsInMemory, but the permissions are saved to and restored from disk. This is the default setting. */ @@ -1130,144 +1130,149 @@ QWebEngineClientHints *QQuickWebEngineProfile::clientHints() const } /*! - \fn QQuickWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const + \fn QQuickWebEngineProfile::queryPermission(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) const Returns a QWebEnginePermission object corresponding to a single permission for the provided \a securityOrigin and - \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + \a permissionType. The object may be used to query for the current state of the permission, or to change it. It is not required for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is known to use it. - \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + \note This may only be used for persistent permission types. Calling it with a non-persistent \a permissionType will return an invalid object. \since 6.8 - \sa listPermissions(), QWebEnginePermission::Feature + \sa listAllPermissions(), listPermissionsForOrigin(), listPermissionsForPermissionType(), QWebEnginePermission::PermissionType */ /*! - \qmlmethod void WebEngineProfile::getPermission(url securityOrigin, WebEnginePermission.Feature feature) const + \qmlmethod void WebEngineProfile::queryPermission(url securityOrigin, WebEnginePermission.PermissionType permissionType) const Returns a webEnginePermission object corresponding to a single permission for the provided \a securityOrigin and - \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + \a permissionType. The object may be used to query for the current state of the permission, or to change it. It is not required for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is known to use it. - \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + \note This may only be used for persistent permission types. Calling it with a non-persistent \a permissionType will return an invalid object. \since 6.8 - \sa listPermissions() + \sa listAllPermissions(), listPermissionsForOrigin(), listPermissionsForPermissionType() */ -QWebEnginePermission QQuickWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const +QWebEnginePermission QQuickWebEngineProfile::queryPermission(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) const { Q_D(const QQuickWebEngineProfile); - if (feature == QWebEnginePermission::Unsupported) { + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) { qWarning("Attempting to get unsupported permission. Returned object will be in an invalid state."); return QWebEnginePermission(new QWebEnginePermissionPrivate()); } - if (QWebEnginePermission::isTransient(feature)) { - qWarning() << "Attempting to get permission for feature" << feature << ". Returned object will be in an invalid state."; + if (!QWebEnginePermission::isPersistent(permissionType)) { + qWarning() << "Attempting to get permission for permission type" << permissionType << ". Returned object will be in an invalid state."; return QWebEnginePermission(new QWebEnginePermissionPrivate()); } - auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, feature, nullptr, d->profileAdapter()); + auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, permissionType, nullptr, d->profileAdapter()); return QWebEnginePermission(pvt); } /*! - \qmlmethod list WebEngineProfile::listPermissions() const + \qmlmethod list WebEngineProfile::listAllPermissions() const Returns a \l list of webEnginePermission objects, each one representing a single permission currently present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, - except for those of a transient feature type. + provided they are of a \e persistent type. + \note When the persistentPermissionPolicy property is set to \c AskEveryTime, this will return an empty list. \since 6.8 - \sa getPermission() + \sa queryPermission(), listPermissionsForOrigin(), listPermissionsForPermissionType(), webEnginePermission::isPersistent() */ /*! Returns a QList of QWebEnginePermission objects, each one representing a single permission currently present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, - except for those of a transient feature type. + provided they are of a \e persistent type. + \note When persistentPermissionPolicy() is set to \c AskEveryTime, this will return an empty list. \since 6.8 - \sa getPermission() + \sa queryPermission(), listPermissionsForOrigin(), listPermissionsForPermissionType(), QWebEnginePermission::isPersistent() */ -QList QQuickWebEngineProfile::listPermissions() const +QList QQuickWebEngineProfile::listAllPermissions() const { Q_D(const QQuickWebEngineProfile); - if (persistentPermissionsPolicy() == NoPersistentPermissions) + if (persistentPermissionsPolicy() == PersistentPermissionsPolicy::AskEveryTime) return QList(); return d->profileAdapter()->listPermissions(); } /*! - \qmlmethod list WebEngineProfile::listPermissions(url securityOrigin) const + \qmlmethod list WebEngineProfile::listPermissionsForOrigin(url securityOrigin) const Returns a \l list of webEnginePermission objects, each one representing a single permission currently present in the permissions store. The returned list contains all previously granted/denied permissions associated with a - specific \a securityOrigin for this profile, except for those of a transient feature type. + specific \a securityOrigin for this profile, provided they are of a \e persistent type. \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html is the same as passing just https://www.example.com/. + \note When persistentPermissionPolicy() is set to \c AskEveryTime, this will return an empty list. \since 6.8 - \sa getPermission() + \sa queryPermission(), listAllPermissions(), listPermissionsForPermissionType(), webEnginePermission::isPersistent() */ /*! Returns a QList of QWebEnginePermission objects, each one representing a single permission currently present in the permissions store. The returned list contains all previously granted/denied permissions associated with a - specific \a securityOrigin for this profile, except for those of a transient feature type. + specific \a securityOrigin for this profile, provided they are of a \e persistent type. \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html is the same as passing just https://www.example.com/. \since 6.8 - \sa getPermission() + \sa queryPermission(), listAllPermissions(), listPermissionsForPermissionType(), QWebEnginePermission::isPersistent() */ -QList QQuickWebEngineProfile::listPermissions(const QUrl &securityOrigin) const +QList QQuickWebEngineProfile::listPermissionsForOrigin(const QUrl &securityOrigin) const { Q_D(const QQuickWebEngineProfile); - if (persistentPermissionsPolicy() == NoPersistentPermissions) + if (persistentPermissionsPolicy() == PersistentPermissionsPolicy::AskEveryTime) return QList(); return d->profileAdapter()->listPermissions(securityOrigin); } /*! - \qmlmethod list WebEngineProfile::listPermissions(WebEnginePermission.Feature feature) const + \qmlmethod list WebEngineProfile::listPermissionsForPermissionType(WebEnginePermission.PermissionType permissionType) const Returns a \l list of webEnginePermission objects, each one representing a single permission currently - present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature - type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + present in the permissions store. The returned list contains all previously granted/denied permissions of the provided + \a permissionType. If the \permissionType is non-persistent, the list will be empty. + \note When persistentPermissionPolicy() is set to \c AskEveryTime, this will return an empty list. \since 6.8 - \sa getPermission() + \sa queryPermission(), listAllPermissions(), listPermissionsForOrigin(), webEnginePermission::isPersistent() */ /*! Returns a QList of QWebEnginePermission objects, each one representing a single permission currently - present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature - type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + present in the permissions store. The returned list contains all previously granted/denied permissions of the provided + \a permissionType. If the \permissionType is non-persistent, the list will be empty. + \note When persistentPermissionPolicy() is set to \c AskEveryTime, this will return an empty list. \since 6.8 - \sa getPermission(), QWebEnginePermission::Feature + \sa queryPermission(), listAllPermissions(), listPermissionsForOrigin(), QWebEnginePermission::PermissionType, QWebEnginePermission::isPersistent() */ -QList QQuickWebEngineProfile::listPermissions(QWebEnginePermission::Feature feature) const +QList QQuickWebEngineProfile::listPermissionsForPermissionType(QWebEnginePermission::PermissionType permissionType) const { Q_D(const QQuickWebEngineProfile); - if (persistentPermissionsPolicy() == NoPersistentPermissions) + if (persistentPermissionsPolicy() == PersistentPermissionsPolicy::AskEveryTime) return QList(); - if (feature == QWebEnginePermission::Unsupported) { + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) { qWarning("Attempting to get permission list for an unsupported type. Returned list will be empty."); return QList(); } - if (QWebEnginePermission::isTransient(feature)) { - qWarning() << "Attempting to get permission list for feature" << feature << ". Returned list will be empty."; + if (!QWebEnginePermission::isPersistent(permissionType)) { + qWarning() << "Attempting to get permission list for permission type" << permissionType << ". Returned list will be empty."; return QList(); } - return d->profileAdapter()->listPermissions(QUrl(), feature); + return d->profileAdapter()->listPermissions(QUrl(), permissionType); } void QQuickWebEngineProfile::ensureQmlContext(const QObject *object) diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h index f5b7ce8e7e0..27ce9d9fcec 100644 --- a/src/webenginequick/api/qquickwebengineprofile.h +++ b/src/webenginequick/api/qquickwebengineprofile.h @@ -64,10 +64,10 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject { }; Q_ENUM(PersistentCookiesPolicy) - enum PersistentPermissionsPolicy : quint8 { - NoPersistentPermissions, - PersistentPermissionsInMemory, - PersistentPermissionsOnDisk, + enum class PersistentPermissionsPolicy : quint8 { + AskEveryTime = 0, + StoreInMemory, + StoreOnDisk, }; Q_ENUM(PersistentPermissionsPolicy) @@ -129,10 +129,10 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject { QWebEngineClientCertificateStore *clientCertificateStore(); QWebEngineClientHints *clientHints() const; - Q_REVISION(6,8) Q_INVOKABLE QWebEnginePermission getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const; - Q_REVISION(6,8) Q_INVOKABLE QList listPermissions() const; - Q_REVISION(6,8) Q_INVOKABLE QList listPermissions(const QUrl &securityOrigin) const; - Q_REVISION(6,8) Q_INVOKABLE QList listPermissions(QWebEnginePermission::Feature feature) const; + Q_REVISION(6,8) Q_INVOKABLE QWebEnginePermission queryPermission(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) const; + Q_REVISION(6,8) Q_INVOKABLE QList listAllPermissions() const; + Q_REVISION(6,8) Q_INVOKABLE QList listPermissionsForOrigin(const QUrl &securityOrigin) const; + Q_REVISION(6,8) Q_INVOKABLE QList listPermissionsForPermissionType(QWebEnginePermission::PermissionType permissionType) const; static QQuickWebEngineProfile *defaultProfile(); diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp index 4a66605d6da..50fb5c3b0f8 100644 --- a/src/webenginequick/api/qquickwebenginesettings.cpp +++ b/src/webenginequick/api/qquickwebenginesettings.cpp @@ -79,7 +79,7 @@ bool QQuickWebEngineSettings::javascriptCanOpenWindows() const Since unrestricted clipboard access is a potential security concern, it is recommended that applications leave this disabled and instead respond to - \l{WebEnginePermission::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. + \l{webEnginePermission::permissionType}{ClipboardReadWrite} feature permission requests. Disabled by default. */ @@ -389,7 +389,7 @@ bool QQuickWebEngineSettings::webRTCPublicInterfacesOnly() const Since unrestricted clipboard access is a potential security concern, it is recommended that applications leave this disabled and instead respond to - \l{WebEnginePermission::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. + \l{webEnginePermission::permissionType}{ClipboardReadWrite} feature permission requests. Disabled by default. */ diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp index 852d00c7642..56b5963f61d 100644 --- a/src/webenginequick/api/qquickwebengineview.cpp +++ b/src/webenginequick/api/qquickwebengineview.cpp @@ -489,29 +489,29 @@ void QQuickWebEngineViewPrivate::selectClientCert( #if QT_DEPRECATED_SINCE(6, 8) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED -static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::Feature feature) +static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::PermissionType permissionType) { - switch (feature) { - case QWebEnginePermission::Feature::Notifications: + switch (permissionType) { + case QWebEnginePermission::PermissionType::Notifications: return QQuickWebEngineView::Notifications; - case QWebEnginePermission::Feature::Geolocation: + case QWebEnginePermission::PermissionType::Geolocation: return QQuickWebEngineView::Geolocation; - case QWebEnginePermission::Feature::ClipboardReadWrite: + case QWebEnginePermission::PermissionType::ClipboardReadWrite: return QQuickWebEngineView::ClipboardReadWrite; - case QWebEnginePermission::Feature::LocalFontsAccess: + case QWebEnginePermission::PermissionType::LocalFontsAccess: return QQuickWebEngineView::LocalFontsAccess; - case QWebEnginePermission::Feature::MediaAudioCapture: + case QWebEnginePermission::PermissionType::MediaAudioCapture: return QQuickWebEngineView::MediaAudioCapture; - case QWebEnginePermission::Feature::MediaVideoCapture: + case QWebEnginePermission::PermissionType::MediaVideoCapture: return QQuickWebEngineView::MediaVideoCapture; - case QWebEnginePermission::Feature::MediaAudioVideoCapture: + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: return QQuickWebEngineView::MediaAudioVideoCapture; - case QWebEnginePermission::Feature::DesktopVideoCapture: + case QWebEnginePermission::PermissionType::DesktopVideoCapture: return QQuickWebEngineView::DesktopVideoCapture; - case QWebEnginePermission::Feature::DesktopAudioVideoCapture: + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: return QQuickWebEngineView::DesktopAudioVideoCapture; - case QWebEnginePermission::Feature::MouseLock: - case QWebEnginePermission::Feature::Unsupported: + case QWebEnginePermission::PermissionType::MouseLock: + case QWebEnginePermission::PermissionType::Unsupported: break; } @@ -521,32 +521,22 @@ static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::Fe QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) -void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &url) +void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin) { Q_Q(QQuickWebEngineView); - switch (feature) { - case QWebEnginePermission::Notifications: - case QWebEnginePermission::Geolocation: - case QWebEnginePermission::ClipboardReadWrite: - case QWebEnginePermission::LocalFontsAccess: - Q_EMIT q->permissionRequested(createFeaturePermissionObject(url, feature)); + + if (QWebEnginePermission::isPersistent(permissionType)) { + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType)); #if QT_DEPRECATED_SINCE(6, 8) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - Q_EMIT q->featurePermissionRequested(url, toDeprecatedFeature(feature)); + Q_EMIT q->featurePermissionRequested(securityOrigin, toDeprecatedFeature(permissionType)); QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) return; - case QWebEnginePermission::MouseLock: - case QWebEnginePermission::MediaAudioCapture: - case QWebEnginePermission::MediaVideoCapture: - case QWebEnginePermission::MediaAudioVideoCapture: - case QWebEnginePermission::DesktopAudioVideoCapture: - case QWebEnginePermission::DesktopVideoCapture: - case QWebEnginePermission::Unsupported: - Q_UNREACHABLE(); - return; } + + Q_UNREACHABLE(); } void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer controller) @@ -824,19 +814,19 @@ void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &sec Q_Q(QQuickWebEngineView); if (!requestFlags) return; - QWebEnginePermission::Feature feature; + QWebEnginePermission::PermissionType permissionType; if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - feature = QWebEnginePermission::MediaAudioVideoCapture; + permissionType = QWebEnginePermission::PermissionType::MediaAudioVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) - feature = QWebEnginePermission::MediaAudioCapture; + permissionType = QWebEnginePermission::PermissionType::MediaAudioCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - feature = QWebEnginePermission::MediaVideoCapture; + permissionType = QWebEnginePermission::PermissionType::MediaVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) - feature = QWebEnginePermission::DesktopAudioVideoCapture; + permissionType = QWebEnginePermission::PermissionType::DesktopAudioVideoCapture; else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) - feature = QWebEnginePermission::DesktopVideoCapture; - Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, feature)); + permissionType = QWebEnginePermission::PermissionType::DesktopVideoCapture; + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, permissionType)); #if QT_DEPRECATED_SINCE(6, 8) QT_WARNING_PUSH @@ -1528,9 +1518,9 @@ void QQuickWebEngineViewPrivate::showWebAuthDialog(QWebEngineWebAuthUxRequest *r Q_EMIT q->webAuthUxRequested(request); } -QWebEnginePermission QQuickWebEngineViewPrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) +QWebEnginePermission QQuickWebEngineViewPrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) { - auto *returnPrivate = new QWebEnginePermissionPrivate(securityOrigin, feature, adapter, profileAdapter()); + auto *returnPrivate = new QWebEnginePermissionPrivate(securityOrigin, permissionType, adapter, profileAdapter()); return QWebEnginePermission(returnPrivate); } @@ -1834,41 +1824,42 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature, bool granted) { Q_D(QQuickWebEngineView); - QWebEnginePermission::Feature f; + QWebEnginePermission::PermissionType permissionType; switch (feature) { case QQuickWebEngineView::Notifications: - f = QWebEnginePermission::Notifications; + permissionType = QWebEnginePermission::PermissionType::Notifications; break; case QQuickWebEngineView::Geolocation: - f = QWebEnginePermission::Geolocation; + permissionType = QWebEnginePermission::PermissionType::Geolocation; break; case QQuickWebEngineView::MediaAudioCapture: - f = QWebEnginePermission::MediaAudioCapture; + permissionType = QWebEnginePermission::PermissionType::MediaAudioCapture; break; case QQuickWebEngineView::MediaVideoCapture: - f = QWebEnginePermission::MediaVideoCapture; + permissionType = QWebEnginePermission::PermissionType::MediaVideoCapture; break; case QQuickWebEngineView::MediaAudioVideoCapture: - f = QWebEnginePermission::MediaAudioVideoCapture; + permissionType = QWebEnginePermission::PermissionType::MediaAudioVideoCapture; break; case QQuickWebEngineView::DesktopVideoCapture: - f = QWebEnginePermission::DesktopVideoCapture; + permissionType = QWebEnginePermission::PermissionType::DesktopVideoCapture; break; case QQuickWebEngineView::DesktopAudioVideoCapture: - f = QWebEnginePermission::DesktopAudioVideoCapture; + permissionType = QWebEnginePermission::PermissionType::DesktopAudioVideoCapture; break; case QQuickWebEngineView::ClipboardReadWrite: - f = QWebEnginePermission::ClipboardReadWrite; + permissionType = QWebEnginePermission::PermissionType::ClipboardReadWrite; break; case QQuickWebEngineView::LocalFontsAccess: - f = QWebEnginePermission::LocalFontsAccess; + permissionType = QWebEnginePermission::PermissionType::LocalFontsAccess; break; default: Q_UNREACHABLE(); } - d->adapter->setFeaturePermission(securityOrigin, f, granted ? QWebEnginePermission::Granted : QWebEnginePermission::Denied); + d->adapter->setPermission(securityOrigin, permissionType, + granted ? QWebEnginePermission::State::Granted : QWebEnginePermission::State::Denied); } QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h index ea09dff9faf..d15b8e82cc4 100644 --- a/src/webenginequick/api/qquickwebengineview_p.h +++ b/src/webenginequick/api/qquickwebengineview_p.h @@ -168,23 +168,18 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QT_WARNING_POP #endif #if QT_DEPRECATED_SINCE(6, 8) -QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - enum QT_DEPRECATED_VERSION_X_6_8( - "WebEnginePage::Feature has been deprecated. " - "The updated permissions API uses WebEnginePermission::Feature.") - Feature { - MediaAudioCapture, - MediaVideoCapture, - MediaAudioVideoCapture, - Geolocation, - DesktopVideoCapture, - DesktopAudioVideoCapture, - Notifications, - ClipboardReadWrite, - LocalFontsAccess, + enum Feature { + MediaAudioCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaAudioCapture instead"), + MediaVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaVideoCapture instead"), + MediaAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaAudioVideoCapture instead"), + Geolocation Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::Geolocation instead"), + DesktopVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::DesktopVideoCapture instead"), + DesktopAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::DesktopAudioVideoCapture instead"), + Notifications Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::Notifications instead"), + ClipboardReadWrite Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::ClipboardReadWrite instead"), + LocalFontsAccess Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::LocalFontsAccess instead"), }; Q_ENUM(Feature) -QT_WARNING_POP #endif enum WebAction { @@ -497,15 +492,8 @@ public Q_SLOTS: Q_REVISION(1,1) void findText(const QString &subString, FindFlags options = { }, const QJSValue &callback = QJSValue()); Q_REVISION(1,1) void fullScreenCancelled(); #if QT_DEPRECATED_SINCE(6, 8) -#if !defined(Q_MOC_RUN) -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED -#endif // !defined(Q_MOC_RUN) QT_DEPRECATED_VERSION_X_6_8("Setting permissions through WebEngineView has been deprecated. Please use WebEnginePermission instead.") Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature, bool granted); -#if !defined(Q_MOC_RUN) -QT_WARNING_POP -#endif // !defined(Q_MOC_RUN) #endif // QT_DEPRECATED_SINCE(6, 8) Q_REVISION(1,2) void setActiveFocusOnPress(bool arg); Q_REVISION(1,2) void triggerWebAction(WebAction action); diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h index e61f32bcb09..d781575971b 100644 --- a/src/webenginequick/api/qquickwebengineview_p_p.h +++ b/src/webenginequick/api/qquickwebengineview_p_p.h @@ -114,7 +114,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineViewPrivate : public QtWebEngineCor void allowCertificateError(const QWebEngineCertificateError &error) override; void selectClientCert(const QSharedPointer &selectController) override; - void runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &securityOrigin) override; + void runFeaturePermissionRequest(QWebEnginePermission::PermissionType permissionType, const QUrl &securityOrigin) override; void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) override; void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) override; void updateScrollPosition(const QPointF &position) override; @@ -139,7 +139,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineViewPrivate : public QtWebEngineCor const QRect &bounds, bool autoselectFirstSuggestion) override; void hideAutofillPopup() override; void showWebAuthDialog(QWebEngineWebAuthUxRequest *request) override; - QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) override; + QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::PermissionType permissionType) override; void updateAction(QQuickWebEngineView::WebAction) const; bool adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); diff --git a/src/webenginequick/doc/src/webengine_permission.qdoc b/src/webenginequick/doc/src/webengine_permission.qdoc index f59f57fa07f..e36264240dd 100644 --- a/src/webenginequick/doc/src/webengine_permission.qdoc +++ b/src/webenginequick/doc/src/webengine_permission.qdoc @@ -15,26 +15,34 @@ \li When the user has made their decision, the application calls \l grant() or \l deny(); \endlist - Alternatively, an application interested in modifying already granted permissions may use WebEngineProfile::listPermissions() - to get a list of existing permissions associated with a profile, or WebEngineProfile::getPermission() to get + Alternatively, an application interested in modifying already granted permissions may use WebEngineProfile::listAllPermissions() + to get a list of existing permissions associated with a profile, or WebEngineProfile::queryPermission() to get a webEnginePermission object for a specific permission. The \l origin property can be used to query which origin the webEnginePermission is associated with, while the - \l feature property describes the associated feature. A website origin is the combination of its scheme, hostname, + \l permissionType property describes the associated feature. A website origin is the combination of its scheme, hostname, and port. Permissions are granted on a per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. - The usability lifetime of a webEnginePermission is tied either to its associated WebEngineView - (for transient feature types), or WebEngineProfile (for permanent feature types). A transient permission is one which - needs to be explicitly granted or denied every time it's needed (e.g. webcam/screen sharing permission), whereas a permanent - one might be stored inside the current profile, depending on the value of WebEngineProfile::persistentPermissionsPolicy. - You can check whether a webEnginePermission is in a valid state using its \l isValid() property. For invalid objects, calls to \l grant(), - \l deny(), or \l reset() will do nothing, and their \l state() will always be WebEnginePermission.Invalid. + The \l permissionType enumeration describes all the permission types Qt WebEngine supports. Only some permission types + are remembered between browsing sessions; they are \e persistent. Non-persistent permissions query the user every time a + website requests them, and cannot be granted in advance. You can check whether a permission type is persistent at runtime + using the static method WebEnginePermission::isPersistent(). - The feature types Qt WebEngine supports are described in \l feature. + Persistent permissions are stored inside the active WebEngineProfile, and their lifetime depends on the value of + WebEngineProfile::persistentPermissionsPolicy. By default, named profiles store their permissions on disk, whereas + off-the-record ones store them in memory (and destroy them when the profile is destroyed). A stored permission will not + query the user the next time a website requests it; instead it will be automatically granted or denied, depending on + the resolution the user picked initially. To erase a stored permission, call \l reset() on it. - \sa WebEngineView::permissionRequested, WebEngineProfile::getPermission(), - WebEngineProfile::listPermissions() + A non-persistent permission, on the other hand, is only usable until the related WebEngineView performs a navigation to + a different URL, or is destroyed. + + You can check whether a WebEnginePermission is in a valid state using its \l isValid property. For invalid objects, calls to \l grant(), + \l deny(), or \l reset() will do nothing, while calls to \l state will always return WebEnginePermission::Invalid. + + \sa WebEngineView::permissionRequested, WebEngineProfile::queryPermission(), + WebEngineProfile::listAllPermissions() */ /*! @@ -47,23 +55,24 @@ */ /*! - \qmlproperty enumeration webEnginePermission::feature - \brief The feature type associated with this permission. - - \value WebEnginePermission.MediaAudioCapture Access to a microphone, or another audio source. This feature is transient. - \value WebEnginePermission.MediaVideoCapture Access to a webcam, or another video source. This feature is transient. - \value WebEnginePermission.MediaAudioVideoCapture Combination of \l MediaAudioCapture and \l MediaVideoCapture. This feature is transient. - \value WebEnginePermission.DesktopVideoCapture Access to the contents of the user's screen. This feature is transient. - \value WebEnginePermission.DesktopAudioVideoCapture Access to the contents of the user's screen, and application audio. This feature is transient. - \value WebEnginePermission.MouseLock Locks the pointer inside an element on the web page. This feature is transient. - \value WebEnginePermission.Notifications Allows the website to send notifications to the user. - \value WebEnginePermission.Geolocation Access to the user's physical location. - \value WebEnginePermission.ClipboardReadWrite Access to the user's clipboard. - \value WebEnginePermission.LocalFontsAccess Access to the fonts installed on the user's machine. Only available on desktops. + \qmlproperty enumeration webEnginePermission::permissionType + \brief The permission type associated with this permission. + + \value WebEnginePermission.MediaAudioCapture Access to a microphone, or another audio source. This permission is \e not persistent. + \value WebEnginePermission.MediaVideoCapture Access to a webcam, or another video source. This permission is \e not persistent. + \value WebEnginePermission.MediaAudioVideoCapture Combination of \e MediaAudioCapture and \e MediaVideoCapture. This permission is \e not persistent. + \value WebEnginePermission.DesktopVideoCapture Access to the contents of the user's screen. This permission is \e not persistent. + \value WebEnginePermission.DesktopAudioVideoCapture Access to the contents of the user's screen, and application audio. This permission is \e not persistent. + \value WebEnginePermission.Notifications Allows the website to send notifications to the user. This permission is persistent. + \value WebEnginePermission.Geolocation Access to the user's physical location. This permission is persistent. + \value WebEnginePermission.ClipboardReadWrite Access to the user's clipboard. This permission is persistent. + \value WebEnginePermission.LocalFontsAccess Access to the fonts installed on the user's machine. Only available on desktops. This permission is persistent. \value WebEnginePermission.Unsupported An unsupported feature type. + \omitvalue WebEnginePermission.MouseLock - \note Transient feature types are ones that will never be remembered by the underlying storage, and will trigger - a permission request every time a website tries to use them. + \note Non-persistent permission types are ones that will never be remembered by the underlying storage, and will trigger + a permission request every time a website tries to use them. They can only be denied/granted as they're needed; + any attempts to pre-grant a non-persistent permission will fail. */ /*! @@ -71,17 +80,17 @@ \brief The current state of the permission. \value WebEnginePermission.Invalid Object is in an invalid state, and any attempts to modify the described permission will fail. - \value WebEnginePermission.Ask Either the permission has not been requested before, or the feature() is transient. + \value WebEnginePermission.Ask Either the permission has not been requested before, or the \l permissionType is not persistent. \value WebEnginePermission.Granted Permission has already been granted. \value WebEnginePermission.Denied Permission has already been denied. - If a permission for the specified \l feature and \l origin has already been granted or denied, + If a permission for the specified \l permissionType and \l origin has already been granted or denied, the return value is WebEnginePermission.Granted, or WebEnginePermission.Denied, respectively. - When this is the first time the permission is requested, or if the \l feature is transient, + When this is the first time the permission is requested, or if the \l permissionType is non-persistent, the return value is WebEnginePermission.Ask. If the object is in an invalid state, the returned value is WebEnginePermission.Invalid. - \sa isValid, isTransient + \sa isValid, isPersistent */ /*! @@ -90,19 +99,19 @@ An invalid webEnginePermission is either: \list - \li One whose \l feature is unsupported; - \li One whose \l feature is transient, and the associated page/view has been destroyed; - \li One whose \l feature is permanent, but the associated profile has been destroyed; + \li One whose \l permissionType is unsupported; + \li One whose \l permissionType is non-persistent, and the user has navigated away from the web page that triggered the request; + \li One whose \l permissionType is persistent, but the associated profile has been destroyed; \li One whose \l origin is invalid. \endlist - \sa isTransient + \sa isPersistent */ /*! \qmlmethod void webEnginePermission::grant() - Allows the associated origin to access the requested feature. Does nothing when \l isValid evaluates to false. + Allows the associated origin to access the requested per. Does nothing when \l isValid evaluates to false. \sa deny, reset, isValid */ @@ -130,8 +139,8 @@ */ /*! - \qmlmethod void webEnginePermission::isTransient(WebEnginePermission.Feature feature) + \qmlmethod void webEnginePermission::isPersistent(WebEnginePermission.PermissionType permissionType) - Returns whether \a feature is transient, meaning that a permission will be requested - every time the associated functionality is used by a web page. + Returns whether a \a permissionType is \e persistent, meaning that a permission's state will be remembered + and the user will not be queried the next time the website requests the same permission. */ diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc index f7b17fa7b62..ac90bb0183c 100644 --- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc +++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc @@ -513,9 +513,9 @@ \qmlsignal WebEngineView::permissionRequested(webEnginePermission permission) \since QtWebEngine 6.8 - This signal is emitted when a web site requests to make use of a feature (e.g. geolocation access, + This signal is emitted when a web site fires a permission request (e.g. geolocation access, permission to send notifications). The \a permission object can queried for the requesting URL - and the \c{WebEnginePermission.Feature} it's asking for, as well as to grant or deny permission. + and the \c{WebEnginePermission.PermissionType} it's asking for, as well as to grant or deny permission. */ /*! @@ -854,7 +854,7 @@ /*! \qmlproperty enumeration WebEngineView::Feature - \deprecated [6.8] Replaced by WebEnginePermission.Feature. + \deprecated [6.8] Replaced by WebEnginePermission.PermissionType. Describes the platform feature access categories that the user may be asked to grant or deny access to: diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index f27515c51c3..6abaac31567 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -86,7 +86,7 @@ static const QList typesToCheck = QList knownEnumNames = QList() << QWebEngineDownloadRequest::staticMetaObject.enumerator(QWebEngineDownloadRequest::staticMetaObject.indexOfEnumerator("SavePageFormat")) - << QWebEnginePermission::staticMetaObject.enumerator(QWebEnginePermission::staticMetaObject.indexOfEnumerator("Feature")) + << QWebEnginePermission::staticMetaObject.enumerator(QWebEnginePermission::staticMetaObject.indexOfEnumerator("PermissionType")) ; static const QStringList hardcodedTypes = QStringList() @@ -371,29 +371,29 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineNewWindowRequest.InNewDialog --> DestinationType" << "QWebEngineNewWindowRequest.InNewTab --> DestinationType" << "QWebEngineNewWindowRequest.InNewWindow --> DestinationType" - << "QWebEnginePermission.Unsupported --> Feature" - << "QWebEnginePermission.MediaAudioCapture --> Feature" - << "QWebEnginePermission.MediaVideoCapture --> Feature" - << "QWebEnginePermission.MediaAudioVideoCapture --> Feature" - << "QWebEnginePermission.DesktopVideoCapture --> Feature" - << "QWebEnginePermission.DesktopAudioVideoCapture --> Feature" - << "QWebEnginePermission.MouseLock --> Feature" - << "QWebEnginePermission.Notifications --> Feature" - << "QWebEnginePermission.Geolocation --> Feature" - << "QWebEnginePermission.ClipboardReadWrite --> Feature" - << "QWebEnginePermission.LocalFontsAccess --> Feature" - << "QWebEnginePermission.Invalid --> State" - << "QWebEnginePermission.Ask --> State" - << "QWebEnginePermission.Granted --> State" - << "QWebEnginePermission.Denied --> State" + << "QWebEnginePermission.PermissionType.Unsupported --> PermissionType" + << "QWebEnginePermission.PermissionType.MediaAudioCapture --> PermissionType" + << "QWebEnginePermission.PermissionType.MediaVideoCapture --> PermissionType" + << "QWebEnginePermission.PermissionType.MediaAudioVideoCapture --> PermissionType" + << "QWebEnginePermission.PermissionType.DesktopVideoCapture --> PermissionType" + << "QWebEnginePermission.PermissionType.DesktopAudioVideoCapture --> PermissionType" + << "QWebEnginePermission.PermissionType.MouseLock --> PermissionType" + << "QWebEnginePermission.PermissionType.Notifications --> PermissionType" + << "QWebEnginePermission.PermissionType.Geolocation --> PermissionType" + << "QWebEnginePermission.PermissionType.ClipboardReadWrite --> PermissionType" + << "QWebEnginePermission.PermissionType.LocalFontsAccess --> PermissionType" + << "QWebEnginePermission.State.Invalid --> State" + << "QWebEnginePermission.State.Ask --> State" + << "QWebEnginePermission.State.Granted --> State" + << "QWebEnginePermission.State.Denied --> State" << "QWebEnginePermission.origin --> QUrl" - << "QWebEnginePermission.feature --> QWebEnginePermission::Feature" + << "QWebEnginePermission.permissionType --> QWebEnginePermission::PermissionType" << "QWebEnginePermission.state --> QWebEnginePermission::State" << "QWebEnginePermission.isValid --> bool" << "QWebEnginePermission.grant() --> void" << "QWebEnginePermission.deny() --> void" << "QWebEnginePermission.reset() --> void" - << "QWebEnginePermission.isTransient(QWebEnginePermission::Feature) --> bool" + << "QWebEnginePermission.isPersistent(QWebEnginePermission::PermissionType) --> bool" << "QQuickWebEngineNewWindowRequest.openIn(QQuickWebEngineView*) --> void" << "QQuickWebEngineProfile.AllowPersistentCookies --> PersistentCookiesPolicy" << "QQuickWebEngineProfile.DiskHttpCache --> HttpCacheType" @@ -401,9 +401,9 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineProfile.MemoryHttpCache --> HttpCacheType" << "QQuickWebEngineProfile.NoCache --> HttpCacheType" << "QQuickWebEngineProfile.NoPersistentCookies --> PersistentCookiesPolicy" - << "QQuickWebEngineProfile.NoPersistentPermissions --> PersistentPermissionsPolicy" - << "QQuickWebEngineProfile.PersistentPermissionsInMemory --> PersistentPermissionsPolicy" - << "QQuickWebEngineProfile.PersistentPermissionsOnDisk --> PersistentPermissionsPolicy" + << "QQuickWebEngineProfile.PersistentPermissionsPolicy.AskEveryTime --> PersistentPermissionsPolicy" + << "QQuickWebEngineProfile.PersistentPermissionsPolicy.StoreInMemory --> PersistentPermissionsPolicy" + << "QQuickWebEngineProfile.PersistentPermissionsPolicy.StoreOnDisk --> PersistentPermissionsPolicy" << "QQuickWebEngineProfile.cachePath --> QString" << "QQuickWebEngineProfile.cachePathChanged() --> void" << "QQuickWebEngineProfile.clearHttpCache() --> void" @@ -413,10 +413,10 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadRequest*) --> void" << "QQuickWebEngineProfile.downloadPath --> QString" << "QQuickWebEngineProfile.downloadPathChanged() --> void" - << "QQuickWebEngineProfile.getPermission(QUrl,QWebEnginePermission::Feature) --> QWebEnginePermission" - << "QQuickWebEngineProfile.listPermissions() --> QList" - << "QQuickWebEngineProfile.listPermissions(QUrl) --> QList" - << "QQuickWebEngineProfile.listPermissions(QWebEnginePermission::Feature) --> QList" + << "QQuickWebEngineProfile.queryPermission(QUrl,QWebEnginePermission::PermissionType) --> QWebEnginePermission" + << "QQuickWebEngineProfile.listAllPermissions() --> QList" + << "QQuickWebEngineProfile.listPermissionsForOrigin(QUrl) --> QList" + << "QQuickWebEngineProfile.listPermissionsForPermissionType(QWebEnginePermission::PermissionType) --> QList" << "QQuickWebEngineProfile.persistentPermissionsPolicy --> QQuickWebEngineProfile::PersistentPermissionsPolicy" << "QQuickWebEngineProfile.persistentPermissionsPolicyChanged() --> void" << "QQuickWebEngineProfile.presentNotification(QWebEngineNotification*) --> void" diff --git a/tests/auto/quick/qmltests/data/tst_geopermission.qml b/tests/auto/quick/qmltests/data/tst_geopermission.qml index 1eb68749738..2957367edb1 100644 --- a/tests/auto/quick/qmltests/data/tst_geopermission.qml +++ b/tests/auto/quick/qmltests/data/tst_geopermission.qml @@ -13,7 +13,7 @@ TestWebEngineView { property bool deniedGeolocation: false property bool geoPermissionRequested: false - profile.persistentPermissionsPolicy: WebEngineProfile.NoPersistentPermissions + profile.persistentPermissionsPolicy: WebEngineProfile.PersistentPermissionsPolicy.AskEveryTime SignalSpy { id: permissionSpy @@ -22,7 +22,7 @@ TestWebEngineView { } onPermissionRequested: function(perm) { - if (perm.feature === WebEnginePermission.Geolocation) { + if (perm.permissionType === WebEnginePermission.PermissionType.Geolocation) { geoPermissionRequested = true if (deniedGeolocation) { perm.deny() @@ -63,17 +63,17 @@ TestWebEngineView { function test_geoPermissionRequest() { compare(permissionSpy.count, 0) webEngineView.url = Qt.resolvedUrl("geolocation.html") - permissionSpy.wait() + tryCompare(permissionSpy, "count", 1) verify(geoPermissionRequested) - compare(permissionSpy.count, 1) tryVerify(isHandled, 5000) verify(getErrorMessage() === "") } function test_deniedGeolocationByUser() { + compare(permissionSpy.count, 0) deniedGeolocation = true webEngineView.url = Qt.resolvedUrl("geolocation.html") - permissionSpy.wait() + tryCompare(permissionSpy, "count", 1) tryVerify(isHandled, 5000) compare(getErrorMessage(), "User denied Geolocation") } diff --git a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml index fbc863a45f6..371977ac737 100644 --- a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml +++ b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml @@ -11,7 +11,7 @@ TestWebEngineView { height: 400 settings.screenCaptureEnabled: true - profile.persistentPermissionsPolicy: WebEngineProfile.NoPersistentPermissions + profile.persistentPermissionsPolicy: WebEngineProfile.PersistentPermissionsPolicy.AskEveryTime TestCase { name: "GetUserMedia" @@ -22,17 +22,17 @@ TestWebEngineView { { tag: "device audio", constraints: { audio: true }, - feature: WebEnginePermission.MediaAudioCapture, + feature: WebEnginePermission.PermissionType.MediaAudioCapture, }, { tag: "device video", constraints: { video: true }, - feature: WebEnginePermission.MediaVideoCapture, + feature: WebEnginePermission.PermissionType.MediaVideoCapture, }, { tag: "device audio+video", constraints: { audio: true, video: true }, - feature: WebEnginePermission.MediaAudioVideoCapture, + feature: WebEnginePermission.PermissionType.MediaAudioVideoCapture, }, { tag: "desktop video", @@ -43,7 +43,7 @@ TestWebEngineView { } } }, - feature: WebEnginePermission.DesktopVideoCapture, + feature: WebEnginePermission.PermissionType.DesktopVideoCapture, }, { tag: "desktop audio+video", @@ -59,7 +59,7 @@ TestWebEngineView { } } }, - feature: WebEnginePermission.DesktopAudioVideoCapture, + feature: WebEnginePermission.PermissionType.DesktopAudioVideoCapture, } ] } @@ -123,7 +123,7 @@ TestWebEngineView { } function gotFeatureRequest(expectedFeature) { - return permissionObject && permissionObject.feature == expectedFeature + return permissionObject && permissionObject.permissionType == expectedFeature } function acceptPendingRequest() { diff --git a/tests/auto/quick/qmltests/data/tst_notification.qml b/tests/auto/quick/qmltests/data/tst_notification.qml index 4f064af3d3c..4795ac31d68 100644 --- a/tests/auto/quick/qmltests/data/tst_notification.qml +++ b/tests/auto/quick/qmltests/data/tst_notification.qml @@ -15,7 +15,7 @@ TestWebEngineView { property bool grantPermission: false property var permissionObject - profile.persistentPermissionsPolicy: WebEngineProfile.NoPersistentPermissions + profile.persistentPermissionsPolicy: WebEngineProfile.PersistentPermissionsPolicy.AskEveryTime signal consoleMessage(string message) @@ -26,7 +26,7 @@ TestWebEngineView { } onPermissionRequested: function(perm) { - if (perm.feature === WebEnginePermission.Notifications) { + if (perm.permissionType === WebEnginePermission.PermissionType.Notifications) { view.permissionRequested = true view.permissionObject = perm if (grantPermission) @@ -70,9 +70,8 @@ TestWebEngineView { tryCompare(result, 'permission', 'default') view.runJavaScript('requestPermission()') - spyRequest.wait() + tryCompare(spyRequest, "count", 1) verify(permissionRequested) - compare(spyRequest.count, 1) view.runJavaScript('getPermission()', function (permission) { result.permission = permission }) tryCompare(result, 'permission', data.permission) @@ -85,7 +84,7 @@ TestWebEngineView { view.waitForLoadSucceeded() view.runJavaScript('requestPermission()') - spyRequest.wait() + tryCompare(spyRequest, "count", 1) verify(permissionRequested) let title = 'Title', message = 'Message', notification = null diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 5af1e9ff9ff..dfb4fe5bf94 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -486,7 +486,7 @@ void tst_QWebEnginePage::geolocationRequestJS() QWebEngineView view; JSTestPage *newPage = new JSTestPage(&view); view.setPage(newPage); - newPage->profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); + newPage->profile()->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); newPage->setGeolocationPermission(allowed); connect(newPage, SIGNAL(permissionRequested(QWebEnginePermission)), @@ -1663,7 +1663,7 @@ Q_OBJECT connect(this, &QWebEnginePage::loadFinished, [this](bool success){ m_loadSucceeded = success; }); - profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); + profile()->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); // We need to load content from a resource in order for the securityOrigin to be valid. load(QUrl("qrc:///resources/content.html")); } @@ -1708,9 +1708,9 @@ Q_OBJECT m_gotRequest = false; } - bool gotFeatureRequest(QWebEnginePermission::Feature feature) + bool gotFeatureRequest(QWebEnginePermission::PermissionType permissionType) { - return m_gotRequest && m_permission && m_permission->feature() == feature; + return m_gotRequest && m_permission && m_permission->permissionType() == permissionType; } bool gotFeatureRequest() const @@ -1739,32 +1739,33 @@ private Q_SLOTS: void tst_QWebEnginePage::getUserMediaRequest_data() { QTest::addColumn("call"); - QTest::addColumn("feature"); + QTest::addColumn("permissionType"); QTest::addRow("device audio") - << "getUserMedia({audio: true})" << QWebEnginePermission::MediaAudioCapture; + << "getUserMedia({audio: true})" << QWebEnginePermission::PermissionType::MediaAudioCapture; QTest::addRow("device video") - << "getUserMedia({video: true})" << QWebEnginePermission::MediaVideoCapture; + << "getUserMedia({video: true})" << QWebEnginePermission::PermissionType::MediaVideoCapture; QTest::addRow("device audio+video") - << "getUserMedia({audio: true, video: true})" << QWebEnginePermission::MediaAudioVideoCapture; + << "getUserMedia({audio: true, video: true})" << QWebEnginePermission::PermissionType::MediaAudioVideoCapture; QTest::addRow("desktop video") << "getUserMedia({video: { mandatory: { chromeMediaSource: 'desktop' }}})" - << QWebEnginePermission::DesktopVideoCapture; + << QWebEnginePermission::PermissionType::DesktopVideoCapture; QTest::addRow("desktop audio+video") << "getUserMedia({audio: { mandatory: { chromeMediaSource: 'desktop' }}, video: { mandatory: { chromeMediaSource: 'desktop' }}})" - << QWebEnginePermission::DesktopAudioVideoCapture; + << QWebEnginePermission::PermissionType::DesktopAudioVideoCapture; QTest::addRow("display video") - << "getDisplayMedia()" << QWebEnginePermission::DesktopVideoCapture; + << "getDisplayMedia()" << QWebEnginePermission::PermissionType::DesktopVideoCapture; } void tst_QWebEnginePage::getUserMediaRequest() { QFETCH(QString, call); - QFETCH(QWebEnginePermission::Feature, feature); + QFETCH(QWebEnginePermission::PermissionType, permissionType); GetUserMediaTestPage page; QWebEngineView view; - if (feature == QWebEnginePermission::DesktopVideoCapture || feature == QWebEnginePermission::DesktopAudioVideoCapture) { + if (permissionType == QWebEnginePermission::PermissionType::DesktopVideoCapture + || permissionType == QWebEnginePermission::PermissionType::DesktopAudioVideoCapture) { // Desktop capture needs to be on a desktop. view.setPage(&page); view.resize(640, 480); @@ -1777,7 +1778,7 @@ void tst_QWebEnginePage::getUserMediaRequest() // 1. Rejecting request on C++ side should reject promise on JS side. page.jsGetMedia(call); - QTRY_VERIFY(page.gotFeatureRequest(feature)); + QTRY_VERIFY(page.gotFeatureRequest(permissionType)); page.rejectPendingRequest(); QTRY_VERIFY(!page.jsPromiseFulfilled() && page.jsPromiseRejected()); @@ -1787,13 +1788,13 @@ void tst_QWebEnginePage::getUserMediaRequest() // always be fulfilled, however in this case an error should be returned to // JS instead of leaving the Promise in limbo. page.jsGetMedia(call); - QTRY_VERIFY(page.gotFeatureRequest(feature)); + QTRY_VERIFY(page.gotFeatureRequest(permissionType)); page.acceptPendingRequest(); QTRY_VERIFY(page.jsPromiseFulfilled() || page.jsPromiseRejected()); - // 3. Media feature permissions are not remembered. + // 3. Media permissions are not remembered. page.jsGetMedia(call); - QTRY_VERIFY(page.gotFeatureRequest(feature)); + QTRY_VERIFY(page.gotFeatureRequest(permissionType)); page.acceptPendingRequest(); QTRY_VERIFY(page.jsPromiseFulfilled() || page.jsPromiseRejected()); } @@ -1834,7 +1835,7 @@ void tst_QWebEnginePage::getUserMediaRequestSettingDisabled() void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyPages() { const QString constraints = QStringLiteral("{video: { mandatory: { chromeMediaSource: 'desktop' }}}"); - const QWebEnginePermission::Feature feature = QWebEnginePermission::DesktopVideoCapture; + const QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType::DesktopVideoCapture; std::vector pages(10); // Desktop capture needs to be on a desktop @@ -1855,7 +1856,7 @@ void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyPages() for (GetUserMediaTestPage &page : pages) page.jsGetUserMedia(constraints); for (GetUserMediaTestPage &page : pages) - QTRY_VERIFY(page.gotFeatureRequest(feature)); + QTRY_VERIFY(page.gotFeatureRequest(permissionType)); for (GetUserMediaTestPage &page : pages) page.acceptPendingRequest(); for (GetUserMediaTestPage &page : pages) @@ -1867,7 +1868,7 @@ void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyPages() void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyRequests() { const QString constraints = QStringLiteral("{video: { mandatory: { chromeMediaSource: 'desktop' }}}"); - const QWebEnginePermission::Feature feature = QWebEnginePermission::DesktopVideoCapture; + const QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType::DesktopVideoCapture; GetUserMediaTestPage page; // Desktop capture needs to be on a desktop @@ -1881,7 +1882,7 @@ void tst_QWebEnginePage::getUserMediaRequestDesktopVideoManyRequests() page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); for (int i = 0; i != 100; ++i) { page.jsGetUserMedia(constraints); - QTRY_VERIFY(page.gotFeatureRequest(feature)); + QTRY_VERIFY(page.gotFeatureRequest(permissionType)); page.acceptPendingRequest(); QTRY_VERIFY(page.jsPromiseFulfilled() || page.jsPromiseRejected()); } @@ -3804,21 +3805,21 @@ struct NotificationPage : ConsolePage { connect(this, &QWebEnginePage::permissionRequested, [this] (QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePermission::Notifications) + if (permission.permissionType() != QWebEnginePermission::PermissionType::Notifications) return; if (spyRequest.wasCalled()) QFAIL("request executed twise!"); switch (policy) { - case QWebEnginePermission::Granted: + case QWebEnginePermission::State::Granted: permission.grant(); break; - case QWebEnginePermission::Denied: + case QWebEnginePermission::State::Denied: permission.deny(); break; - case QWebEnginePermission::Ask: + case QWebEnginePermission::State::Ask: permission.reset(); break; - default: + case QWebEnginePermission::State::Invalid: break; } spyRequest.ref()(permission.origin()); @@ -3843,10 +3844,10 @@ void tst_QWebEnginePage::notificationPermission_data() QTest::addColumn("setOnInit"); QTest::addColumn("policy"); QTest::addColumn("permission"); - QTest::newRow("denyOnInit") << true << QWebEnginePermission::Denied << "denied"; - QTest::newRow("deny") << false << QWebEnginePermission::Denied << "denied"; - QTest::newRow("grant") << false << QWebEnginePermission::Granted << "granted"; - QTest::newRow("grantOnInit") << true << QWebEnginePermission::Granted << "granted"; + QTest::newRow("denyOnInit") << true << QWebEnginePermission::State::Denied << "denied"; + QTest::newRow("deny") << false << QWebEnginePermission::State::Denied << "denied"; + QTest::newRow("grant") << false << QWebEnginePermission::State::Granted << "granted"; + QTest::newRow("grantOnInit") << true << QWebEnginePermission::State::Granted << "granted"; } void tst_QWebEnginePage::notificationPermission() @@ -3856,14 +3857,14 @@ void tst_QWebEnginePage::notificationPermission() QFETCH(QString, permission); QWebEngineProfile otr; - otr.setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); + otr.setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); QWebEnginePage page(&otr, nullptr); QUrl baseUrl("https://www.example.com/somepage.html"); bool permissionRequested = false, errorState = false; connect(&page, &QWebEnginePage::permissionRequested, &page, [&] (QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePermission::Notifications) + if (permission.permissionType() != QWebEnginePermission::PermissionType::Notifications) return; if (permissionRequested || permission.origin() != baseUrl.url(/service/qurl::RemoveFilename)) { qWarning() << "Unexpected case. Can't proceed." << setOnInit << permissionRequested << permission.origin(); @@ -3872,15 +3873,15 @@ void tst_QWebEnginePage::notificationPermission() } permissionRequested = true; - if (policy == QWebEnginePermission::Granted) + if (policy == QWebEnginePermission::State::Granted) permission.grant(); else permission.deny(); }); - QWebEnginePermission permissionObject = otr.getPermission(baseUrl, QWebEnginePermission::Notifications); + QWebEnginePermission permissionObject = otr.queryPermission(baseUrl, QWebEnginePermission::PermissionType::Notifications); if (setOnInit) { - if (policy == QWebEnginePermission::Granted) + if (policy == QWebEnginePermission::State::Granted) permissionObject.grant(); else permissionObject.deny(); @@ -3893,7 +3894,7 @@ void tst_QWebEnginePage::notificationPermission() QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), setOnInit ? permission : QLatin1String("default")); if (!setOnInit) { - if (policy == QWebEnginePermission::Granted) + if (policy == QWebEnginePermission::State::Granted) permissionObject.grant(); else permissionObject.deny(); @@ -3910,7 +3911,7 @@ void tst_QWebEnginePage::notificationPermission() void tst_QWebEnginePage::sendNotification() { - NotificationPage page(QWebEnginePermission::Granted); + NotificationPage page(QWebEnginePermission::State::Granted); QVERIFY(page.spyLoad.waitForResult()); page.resetPermission(); @@ -3976,7 +3977,7 @@ void tst_QWebEnginePage::clipboardReadWritePermissionInitialState() QFETCH(QString, permission); QWebEngineProfile otr; - otr.setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); + otr.setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); QWebEngineView view(&otr); QWebEnginePage &page = *view.page(); view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); @@ -4004,28 +4005,28 @@ void tst_QWebEnginePage::clipboardReadWritePermission_data() QTest::addColumn("finalPermission"); QTest::newRow("noAccessGrantGrant") - << false << QWebEnginePermission::Granted << "granted" - << QWebEnginePermission::Granted << "granted"; + << false << QWebEnginePermission::State::Granted << "granted" + << QWebEnginePermission::State::Granted << "granted"; QTest::newRow("noAccessGrantDeny") - << false << QWebEnginePermission::Granted << "granted" - << QWebEnginePermission::Denied << "denied"; + << false << QWebEnginePermission::State::Granted << "granted" + << QWebEnginePermission::State::Denied << "denied"; QTest::newRow("noAccessDenyGrant") - << false << QWebEnginePermission::Denied << "denied" - << QWebEnginePermission::Granted << "granted"; - QTest::newRow("noAccessDenyDeny") << false << QWebEnginePermission::Denied << "denied" - << QWebEnginePermission::Denied << "denied"; - QTest::newRow("noAccessAskGrant") << false << QWebEnginePermission::Ask << "prompt" - << QWebEnginePermission::Granted << "granted"; + << false << QWebEnginePermission::State::Denied << "denied" + << QWebEnginePermission::State::Granted << "granted"; + QTest::newRow("noAccessDenyDeny") << false << QWebEnginePermission::State::Denied << "denied" + << QWebEnginePermission::State::Denied << "denied"; + QTest::newRow("noAccessAskGrant") << false << QWebEnginePermission::State::Ask << "prompt" + << QWebEnginePermission::State::Granted << "granted"; // All policies are ignored and overridden by setting JsCanAccessClipboard and JsCanPaste to // true QTest::newRow("accessGrantGrant") - << true << QWebEnginePermission::Granted << "granted" - << QWebEnginePermission::Granted << "granted"; - QTest::newRow("accessDenyDeny") << true << QWebEnginePermission::Denied << "granted" - << QWebEnginePermission::Denied << "granted"; - QTest::newRow("accessAskAsk") << true << QWebEnginePermission::Ask << "granted" - << QWebEnginePermission::Ask << "granted"; + << true << QWebEnginePermission::State::Granted << "granted" + << QWebEnginePermission::State::Granted << "granted"; + QTest::newRow("accessDenyDeny") << true << QWebEnginePermission::State::Denied << "granted" + << QWebEnginePermission::State::Denied << "granted"; + QTest::newRow("accessAskAsk") << true << QWebEnginePermission::State::Ask << "granted" + << QWebEnginePermission::State::Ask << "granted"; } void tst_QWebEnginePage::clipboardReadWritePermission() @@ -4037,7 +4038,7 @@ void tst_QWebEnginePage::clipboardReadWritePermission() QFETCH(QString, finalPermission); QWebEngineProfile otr; - otr.setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); + otr.setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); QWebEngineView view(&otr); QWebEnginePage &page = *view.page(); view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); @@ -4053,7 +4054,7 @@ void tst_QWebEnginePage::clipboardReadWritePermission() // if JavascriptCanAccessClipboard is true, this never fires connect(&page, &QWebEnginePage::permissionRequested, &page, [&](QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePermission::ClipboardReadWrite) + if (permission.permissionType() != QWebEnginePermission::PermissionType::ClipboardReadWrite) return; if (permission.origin() != baseUrl.url(/service/qurl::RemoveFilename)) { qWarning() << "Unexpected case. Can't proceed." << permission.origin(); @@ -4062,13 +4063,13 @@ void tst_QWebEnginePage::clipboardReadWritePermission() } permissionRequestCount++; switch (requestPolicy) { - case QWebEnginePermission::Granted: + case QWebEnginePermission::State::Granted: permission.grant(); break; - case QWebEnginePermission::Denied: + case QWebEnginePermission::State::Denied: permission.deny(); break; - case QWebEnginePermission::Ask: + case QWebEnginePermission::State::Ask: permission.reset(); break; default: @@ -4076,18 +4077,18 @@ void tst_QWebEnginePage::clipboardReadWritePermission() } }); - QWebEnginePermission permissionObject = otr.getPermission(baseUrl, QWebEnginePermission::ClipboardReadWrite); + QWebEnginePermission permissionObject = otr.queryPermission(baseUrl, QWebEnginePermission::PermissionType::ClipboardReadWrite); switch (initialPolicy) { - case QWebEnginePermission::Granted: + case QWebEnginePermission::State::Granted: permissionObject.grant(); break; - case QWebEnginePermission::Denied: + case QWebEnginePermission::State::Denied: permissionObject.deny(); break; - case QWebEnginePermission::Ask: + case QWebEnginePermission::State::Ask: permissionObject.reset(); break; - default: + case QWebEnginePermission::State::Invalid: break; } @@ -4153,9 +4154,9 @@ void tst_QWebEnginePage::localFontAccessPermission_data() QTest::addColumn("ignore"); QTest::addColumn("shouldBeEmpty"); - QTest::newRow("ignore") << QWebEnginePermission::Denied << true << true; - QTest::newRow("setDeny") << QWebEnginePermission::Denied << false << true; - QTest::newRow("setGrant") << QWebEnginePermission::Granted << false << false; + QTest::newRow("ignore") << QWebEnginePermission::State::Denied << true << true; + QTest::newRow("setDeny") << QWebEnginePermission::State::Denied << false << true; + QTest::newRow("setGrant") << QWebEnginePermission::State::Granted << false << false; } void tst_QWebEnginePage::localFontAccessPermission() { @@ -4165,15 +4166,15 @@ void tst_QWebEnginePage::localFontAccessPermission() { QWebEngineView view; QWebEnginePage page(&view); - page.profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); + page.profile()->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); view.setPage(&page); connect(&page, &QWebEnginePage::permissionRequested, &page, [&] (QWebEnginePermission permission) { - if (permission.feature() != QWebEnginePermission::LocalFontsAccess) + if (permission.permissionType() != QWebEnginePermission::PermissionType::LocalFontsAccess) return; if (!ignore) { - if (policy == QWebEnginePermission::Granted) + if (policy == QWebEnginePermission::State::Granted) permission.grant(); else permission.deny(); @@ -5777,7 +5778,7 @@ void tst_QWebEnginePage::chooseDesktopMedia() QWebEnginePage page; QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); - page.profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); + page.profile()->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); bool desktopMediaRequested = false; bool permissionRequested = false; diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 5303d99fc6c..6c9af17271a 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -58,8 +58,8 @@ private Q_SLOTS: void badDeleteOrder(); void permissionPersistence_data(); void permissionPersistence(); - void getPermission_data(); - void getPermission(); + void queryPermission_data(); + void queryPermission(); void listPermissions(); void qtbug_71895(); // this should be the last test }; @@ -1025,10 +1025,10 @@ void tst_QWebEngineProfile::permissionPersistence_data() QTest::addColumn("policy"); QTest::addColumn("granted"); - QTest::newRow("noPersistenceNotificationsNoGrant") << QWebEngineProfile::NoPersistentPermissions << false; - QTest::newRow("noPersistenceNotificationsGrant") << QWebEngineProfile::NoPersistentPermissions << true; - QTest::newRow("memoryPersistenceNotificationsNoGrant") << QWebEngineProfile::PersistentPermissionsInMemory << false; - QTest::newRow("diskPersistenceNotificationsGrant") << QWebEngineProfile::PersistentPermissionsOnDisk << true; + QTest::newRow("noPersistenceNotificationsNoGrant") << QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime << false; + QTest::newRow("noPersistenceNotificationsGrant") << QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime << true; + QTest::newRow("memoryPersistenceNotificationsNoGrant") << QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory << false; + QTest::newRow("diskPersistenceNotificationsGrant") << QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk << true; } void tst_QWebEngineProfile::permissionPersistence() @@ -1055,7 +1055,7 @@ void tst_QWebEngineProfile::permissionPersistence() QVariant variant = granted ? "granted" : "denied"; QVariant defaultVariant = "default"; - QWebEnginePermission permissionObject = profile->getPermission(server.url("https://github.com/hedgehog.html"), QWebEnginePermission::Notifications); + QWebEnginePermission permissionObject = profile->queryPermission(server.url("https://github.com/hedgehog.html"), QWebEnginePermission::PermissionType::Notifications); if (granted) permissionObject.grant(); else @@ -1067,7 +1067,7 @@ void tst_QWebEngineProfile::permissionPersistence() loadSpy.reset(); bool expectSame = false; - if (policy == QWebEngineProfile::PersistentPermissionsOnDisk) { + if (policy == QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk) { expectSame = true; // File is written asynchronously, wait for it to be created @@ -1085,7 +1085,7 @@ void tst_QWebEngineProfile::permissionPersistence() expectSame ? variant : defaultVariant); // Re-acquire the permission, since deleting the Profile makes it invalid - permissionObject = profile->getPermission(server.url("https://github.com/hedgehog.html"), QWebEnginePermission::Notifications); + permissionObject = profile->queryPermission(server.url("https://github.com/hedgehog.html"), QWebEnginePermission::PermissionType::Notifications); permissionObject.reset(); QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), defaultVariant); @@ -1093,7 +1093,7 @@ void tst_QWebEngineProfile::permissionPersistence() profile.reset(); loadSpy.reset(); - if (policy == QWebEngineProfile::PersistentPermissionsOnDisk) { + if (policy == QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk) { // Wait for file to be written to before deleting QTest::qWait(1000); storageDir.remove("permissions.json"); @@ -1102,81 +1102,86 @@ void tst_QWebEngineProfile::permissionPersistence() QTRY_VERIFY(server.stop()); } -void tst_QWebEngineProfile::getPermission_data() +void tst_QWebEngineProfile::queryPermission_data() { - QTest::addColumn("feature"); + QTest::addColumn("permissionType"); QTest::addColumn("url"); QTest::addColumn("expectedValid"); - QTest::newRow("badUrl") << QWebEnginePermission::Notifications << QUrl(QStringLiteral("//:bad-url")) << false; - QTest::newRow("badFeature") << QWebEnginePermission::Unsupported << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << false; - QTest::newRow("transientFeature") << QWebEnginePermission::MouseLock << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << false; - QTest::newRow("good") << QWebEnginePermission::Notifications << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << true; + QTest::newRow("badUrl") + << QWebEnginePermission::PermissionType::Notifications << QUrl(QStringLiteral("//:bad-url")) << false; + QTest::newRow("badFeature") + << QWebEnginePermission::PermissionType::Unsupported << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << false; + QTest::newRow("transientFeature") + << QWebEnginePermission::PermissionType::MouseLock << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << false; + QTest::newRow("good") + << QWebEnginePermission::PermissionType::Notifications << QUrl(QStringLiteral("qrc:/resources/hedgehog.html")) << true; } -void tst_QWebEngineProfile::getPermission() +void tst_QWebEngineProfile::queryPermission() { - QFETCH(QWebEnginePermission::Feature, feature); + QFETCH(QWebEnginePermission::PermissionType, permissionType); QFETCH(QUrl, url); QFETCH(bool, expectedValid); QWebEngineProfile profile; // In-memory is the default for otr profiles - QVERIFY(profile.persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsInMemory); + QVERIFY(profile.persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory); - QWebEnginePermission permission = profile.getPermission(url, feature); + QWebEnginePermission permission = profile.queryPermission(url, permissionType); bool valid = permission.isValid(); QVERIFY(valid == expectedValid); if (!valid) - QVERIFY(permission.state() == QWebEnginePermission::Invalid); + QVERIFY(permission.state() == QWebEnginePermission::State::Invalid); // Verify that we can grant a valid permission, and we can't grant an invalid one... permission.grant(); - QVERIFY(permission.state() == (valid ? QWebEnginePermission::Granted : QWebEnginePermission::Invalid)); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Granted : QWebEnginePermission::State::Invalid)); // ...and that doing so twice doesn't mess up the state... permission.grant(); - QVERIFY(permission.state() == (valid ? QWebEnginePermission::Granted : QWebEnginePermission::Invalid)); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Granted : QWebEnginePermission::State::Invalid)); // ...and that the same thing applies to denying them... permission.deny(); - QVERIFY(permission.state() == (valid ? QWebEnginePermission::Denied : QWebEnginePermission::Invalid)); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Denied : QWebEnginePermission::State::Invalid)); permission.deny(); - QVERIFY(permission.state() == (valid ? QWebEnginePermission::Denied : QWebEnginePermission::Invalid)); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Denied : QWebEnginePermission::State::Invalid)); // ...and that resetting works permission.reset(); - QVERIFY(permission.state() == (valid ? QWebEnginePermission::Ask : QWebEnginePermission::Invalid)); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Ask : QWebEnginePermission::State::Invalid)); permission.reset(); - QVERIFY(permission.state() == (valid ? QWebEnginePermission::Ask : QWebEnginePermission::Invalid)); + QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Ask : QWebEnginePermission::State::Invalid)); } void tst_QWebEngineProfile::listPermissions() { QWebEngineProfile profile; // In-memory is the default for otr profiles - QVERIFY(profile.persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsInMemory); + QVERIFY(profile.persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory); QUrl commonUrl = QUrl(QStringLiteral("http://www.bing.com/maps")); - QWebEnginePermission::Feature commonFeature = QWebEnginePermission::Notifications; + QWebEnginePermission::PermissionType commonType = QWebEnginePermission::PermissionType::Notifications; // First, set several permissions at once - profile.getPermission(commonUrl, QWebEnginePermission::Geolocation).deny(); - profile.getPermission(commonUrl, QWebEnginePermission::Unsupported).grant(); // Invalid - profile.getPermission(commonUrl, commonFeature).grant(); - profile.getPermission(QUrl(QStringLiteral("http://www.google.com/translate")), commonFeature).grant(); + profile.queryPermission(commonUrl, QWebEnginePermission::PermissionType::Geolocation).deny(); + profile.queryPermission(commonUrl, QWebEnginePermission::PermissionType::Unsupported).grant(); // Invalid + profile.queryPermission(commonUrl, commonType).grant(); + profile.queryPermission(QUrl(QStringLiteral("http://www.google.com/translate")), commonType).grant(); - QList permissionsListAll = profile.listPermissions(); - QList permissionsListUrl = profile.listPermissions(commonUrl); - QList permissionsListFeature = profile.listPermissions(commonFeature); + QList permissionsListAll = profile.listAllPermissions(); + QList permissionsListUrl = profile.listPermissionsForOrigin(commonUrl); + QList permissionsListFeature = profile.listPermissionsForPermissionType(commonType); // Order of returned permissions is not guaranteed, so we must iterate until we find the one we need auto findInList = [](QList list, const QUrl &url, - QWebEnginePermission::Feature feature, QWebEnginePermission::State state) + QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state) { bool found = false; for (auto &permission : list) { - if (permission.origin().adjusted(QUrl::RemovePath) == url.adjusted(QUrl::RemovePath) && permission.feature() == feature && permission.state() == state) { + if (permission.origin().adjusted(QUrl::RemovePath) == url.adjusted(QUrl::RemovePath) + && permission.permissionType() == permissionType && permission.state() == state) { found = true; break; } @@ -1186,19 +1191,19 @@ void tst_QWebEngineProfile::listPermissions() // Check full list QVERIFY(permissionsListAll.size() == 3); - QVERIFY(findInList(permissionsListAll, commonUrl, QWebEnginePermission::Geolocation, QWebEnginePermission::Denied)); - QVERIFY(findInList(permissionsListAll, commonUrl, commonFeature, QWebEnginePermission::Granted)); - QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("http://www.google.com/")), commonFeature, QWebEnginePermission::Granted)); + QVERIFY(findInList(permissionsListAll, commonUrl, QWebEnginePermission::PermissionType::Geolocation, QWebEnginePermission::State::Denied)); + QVERIFY(findInList(permissionsListAll, commonUrl, commonType, QWebEnginePermission::State::Granted)); + QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("http://www.google.com/")), commonType, QWebEnginePermission::State::Granted)); // Check list filtered by URL QVERIFY(permissionsListUrl.size() == 2); - QVERIFY(findInList(permissionsListUrl, commonUrl, QWebEnginePermission::Geolocation, QWebEnginePermission::Denied)); - QVERIFY(findInList(permissionsListAll, commonUrl, commonFeature, QWebEnginePermission::Granted)); + QVERIFY(findInList(permissionsListUrl, commonUrl, QWebEnginePermission::PermissionType::Geolocation, QWebEnginePermission::State::Denied)); + QVERIFY(findInList(permissionsListAll, commonUrl, commonType, QWebEnginePermission::State::Granted)); // Check list filtered by feature QVERIFY(permissionsListFeature.size() == 2); - QVERIFY(findInList(permissionsListAll, commonUrl, commonFeature, QWebEnginePermission::Granted)); - QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("http://www.google.com/")), commonFeature, QWebEnginePermission::Granted)); + QVERIFY(findInList(permissionsListAll, commonUrl, commonType, QWebEnginePermission::State::Granted)); + QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("http://www.google.com/")), commonType, QWebEnginePermission::State::Granted)); } void tst_QWebEngineProfile::qtbug_71895() diff --git a/tests/manual/quick/geopermission/tst_geopermission.qml b/tests/manual/quick/geopermission/tst_geopermission.qml index 6d6f4de8bc8..ff9c79f1d06 100644 --- a/tests/manual/quick/geopermission/tst_geopermission.qml +++ b/tests/manual/quick/geopermission/tst_geopermission.qml @@ -14,7 +14,7 @@ WebEngineView { property bool geoPermissionRequested: false onPermissionRequested: function(perm) { - if (perm.feature === WebEnginePermission.Geolocation) { + if (perm.permissionType === WebEnginePermission.PermissionType.Geolocation) { geoPermissionRequested = true if (deniedGeolocation) { perm.deny() From 96c8ebd25c04e314fb6bec15b9f4d919675bae8a Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Mon, 1 Jul 2024 16:58:12 +0200 Subject: [PATCH 052/341] Allow pressing the print button of PDF viewer multiple times Chromium started to protect ongoing print jobs by a print_in_progress_ flag in PrintRenderFrameHelper. Now we have to properly close requested print previews before starting a new one. Fixes: QTBUG-125096 Change-Id: I83fec883d717756d97dc65e3b55363b0cac0fbef Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit ea2012c56952cd0378d13a4257eebade4e3c736d) Reviewed-by: Qt Cherry-pick Bot --- src/core/printing/print_view_manager_qt.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp index 42bade52bdd..41f2cd999a6 100644 --- a/src/core/printing/print_view_manager_qt.cpp +++ b/src/core/printing/print_view_manager_qt.cpp @@ -364,6 +364,11 @@ void PrintViewManagerQt::RequestPrintPreview(printing::mojom::RequestPrintPrevie content::WebContentsView *view = static_cast(web_contents()->GetOutermostWebContents())->GetView(); if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client()) client->printRequested(); + + content::GlobalRenderFrameHostId rfhId = GetCurrentTargetFrame()->GetGlobalId(); + auto *renderFrameHost = content::RenderFrameHost::FromID(rfhId); + if (renderFrameHost && renderFrameHost->IsRenderFrameLive()) + GetPrintRenderFrame(renderFrameHost)->OnPrintPreviewDialogClosed(); return; } From e4cd2608f2cae33b0e95031dbe0f71cd375dbf80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucie=20G=C3=A9rard?= Date: Tue, 2 Jul 2024 11:36:36 +0200 Subject: [PATCH 053/341] Correct license for examples file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example takes precedence over build system file type. According to QUIP-18 [1], all examples file should be LicenseRef-Qt-Commercial OR BSD-3-Clause [1]: https://contribute.qt-project.org/quips/18 Task-number: QTBUG-121787 Change-Id: Ifb33a2b284ef234648b50d2333e83f7015023405 Reviewed-by: Kai Köhne Reviewed-by: Kaloyan Chehlarski (cherry picked from commit d66b248444c6ee523594edd21d37db5300ff4423) Reviewed-by: Qt Cherry-pick Bot --- examples/webenginewidgets/permissionbrowser/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt index 0a92691ba1f..c4d8f9cd43e 100644 --- a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt +++ b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (C) 2024 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause cmake_minimum_required(VERSION 3.5) project(permissionbrowser LANGUAGES CXX) From 686eb71d22529f170715822af1c95c4cea3e9fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucie=20G=C3=A9rard?= Date: Thu, 4 Apr 2024 18:05:03 +0200 Subject: [PATCH 054/341] Correct license for module and plugin files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those files partially come from Chromium and are made available only under BSD-3-Clause Pick-to: 6.7 Task-number: QTBUG-121787 Change-Id: Iba17543d385f157a648959dcd2b46eaf0e43a7f1 Reviewed-by: Kai Köhne Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit e8f074f3c318b7ececb02e6ed5ba34a869327f40) Reviewed-by: Qt Cherry-pick Bot --- src/core/clipboard_util_win.cpp | 2 +- src/core/common/qt_messages.cpp | 2 +- src/core/common/qt_messages.h | 2 +- src/core/tools/qwebengine_convert_dict/main.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/clipboard_util_win.cpp b/src/core/clipboard_util_win.cpp index 601e4418026..2dbd173d3c8 100644 --- a/src/core/clipboard_util_win.cpp +++ b/src/core/clipboard_util_win.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2007, 2008 Apple Inc. All rights reserved. // Copyright (c) 2012 The Chromium Authors. All rights reserved. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: BSD-3-Clause #include diff --git a/src/core/common/qt_messages.cpp b/src/core/common/qt_messages.cpp index bc3a1560d3b..aaaddf83010 100644 --- a/src/core/common/qt_messages.cpp +++ b/src/core/common/qt_messages.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 The Chromium Authors. All rights reserved. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: BSD-3-Clause // Get basic type definitions. #define IPC_MESSAGE_IMPL diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index 17adcbb0da1..eaf3d03f23b 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -1,5 +1,5 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: BSD-3-Clause // Multiply-included file, no traditional include guard. diff --git a/src/core/tools/qwebengine_convert_dict/main.cpp b/src/core/tools/qwebengine_convert_dict/main.cpp index a82947ddc35..17dd3eec6aa 100644 --- a/src/core/tools/qwebengine_convert_dict/main.cpp +++ b/src/core/tools/qwebengine_convert_dict/main.cpp @@ -7,7 +7,7 @@ ** Modified work: ** Copyright (C) 2016 The Qt Company Ltd. ** -** SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +** SPDX-License-Identifier: BSD-3-Clause ** ** This tool converts Hunspell .aff/.dic pairs to a combined binary dictionary ** format (.bdic). This format is more compact, and can be more efficiently From b88e8bc197aa8b40575faf9b1f5ffe6922dc8fa5 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 8 Jul 2024 22:40:10 +0000 Subject: [PATCH 055/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ie6f8cd5ec7d035333dc312ccdddc679debeb7612 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index d9a5ed195c7..e87c805d4c0 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: df193621ede18ee1166281435750fc1980b3bc1f + ref: e9f904aaf2bc17d46709a6a32a6ee22a0eeaf909 required: true ../qtpositioning: - ref: 31a8040367a3d79f1970799d283acb1be8e4f23b + ref: fb6aa84a86ef5238bc78e1016045bf6ead024947 required: false ../qttools: - ref: a5a69456bf87773b671aca85373085a948408ff9 + ref: 81114e34cf4fd0438c0b7500dec5127e7acc5acc required: false ../qtwebchannel: - ref: abad90db61a76dc0e1faaa2034837a8612bcdd83 + ref: 1e1b3285624ad11e40765304900cfa2feb262988 required: false From 5313ab65edb681571175c03114b479a32474d3c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucie=20G=C3=A9rard?= Date: Thu, 4 Apr 2024 18:22:59 +0200 Subject: [PATCH 056/341] Add a licenseRule.json file for checking of SPDX license identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The license test in qtqa reads this file in order to check the validity of the license used. This file reproduce the QUIP-18 [1] rules, with some exceptions. Each entry in the file corresponds to a set of licensing rules. A set of licensing rules can depend on the file ending, registered in "file_pattern_ending". The last entry in the file has no "file_pattern_ending", it sets the rules for the files whose licensing does not depend on their ending. The license to be used depends on the location of the file within the Qt module repository. Let's call this "". The "" can also correspond to a file name, offering flexibility for exceptions to the rule. The "" are registered in "location". For each "" there is a "file type" entry and a "spdx" entry. The "spdx" entry gives the rule: the expected license tag(s) in SPDX format for the file ending (if applicable) and "". The "file type" informs on the QUIP-18 type the tested file corresponds to. It is purely informational for the reader. The set of rules are tested in order of appearance in the json file. For this reason, a more constraining ending (like "special.txt") needs to appear in a "file_pattern_ending" located before the "file_pattern_ending" of a less constraining ending (like ".txt"). Also, a file ending cannot be present in two "file_pattern_ending". "file_pattern_ending" and "spdx" should list strings. "" can be regular expressions. During the test the deeper "" are checked first. The order is which they appear in the json file does not matter. To test this file, run QT_MODULE_TO_TEST=../qtwebengine perl tests/prebuild/license/tst_licenses.pl [1]: https://contribute.qt-project.org/quips/18 Pick-to: 6.7 Task-number: QTBUG-121039 Change-Id: I4c6c5a78ca17e3afb20023e7339b1b6caf04be83 Reviewed-by: Kai Köhne (cherry picked from commit 5693d073d1478967362d8f81f29b7f57ba88da66) Reviewed-by: Qt Cherry-pick Bot --- licenseRule.json | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 licenseRule.json diff --git a/licenseRule.json b/licenseRule.json new file mode 100644 index 00000000000..5f78a7dc8c1 --- /dev/null +++ b/licenseRule.json @@ -0,0 +1,104 @@ +[ + { + "comment" : ["file_pattern_ending: strings matched against the end of a file name.", + "location keys: regular expression matched against the beginning of", + "the file path (relative to the git submodule root).", + "spdx: list of SPDX-License-Expression's allowed in the matching files.", + "-------------------------------------------------------", + "Files with the following endings are Build System licensed,", + "unless they are examples", + "Files with other endings can also be build system files" + ], + "file_pattern_ending" : ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", + "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", ".clang-format"], + "location" : { + "" : { + "comment" : "Default", + "file type" : "build system", + "spdx" : ["BSD-3-Clause"] + }, + "(.*)(examples/|snippets/)" : { + "comment" : "Example takes precedence", + "file type" : "examples and snippets", + "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + } + } + }, + { + "comments" : ["Files with the following endings are Tool licensed,", + "unless they are examples.", + "Files with other endings can also be tool files."], + "file_pattern_ending" : [".sh", ".py", ".pl", ".bat", ".ps1"], + "location" :{ + "" : { + "comment" : "Default", + "file type" : "tools and utils", + "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] + }, + "(.*)(examples/|snippets/)" : { + "comment" : "Example takes precedence", + "file type" : "examples and snippets", + "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + } + } + }, + { + "comment" : "Files with the following endings are Documentation licensed.", + "file_pattern_ending" : [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", ".txt", "README", "qt_attribution.json"], + "location" :{ + "" : { + "comment" : "", + "file type" : "documentation", + "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + } + } + }, + { + "comment" : ["All other files", + "The licensing is defined only by the file location in the Qt module repository.", + "NO key for this case!", + "This needs to be the last entry of the file."], + "location" : { + "" : { + "comment" : "Default", + "file type" : "module and plugin", + "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "src/" : { + "comment" : "Default", + "file type" : "module and plugin", + "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "tests/" : { + "comment" : "Default", + "file type" : "test", + "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"] + }, + "(.*)(examples/|snippets/)" : { + "comment" : "Default", + "file type" : "examples and snippets", + "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + }, + "src/host/config\\.tests/" : { + "comment" : "Default", + "file type" : "build system", + "spdx" : ["BSD-3-Clause"] + }, + "src/core/clipboard_util_win.cpp" : { + "comment" : "Partially from Chromium", + "file type" : "module and plugin", + "spdx" : ["BSD-3-Clause"] + }, + "src/core/common/qt_messages.*" : { + "comment" : "Partially from Chromium", + "file type" : "module and plugin", + "spdx" : ["BSD-3-Clause"] + }, + "src/core/tools/qwebengine_convert_dict/main.cpp" : { + "comment" : "Partially from Chromium", + "file type" : "module and plugin", + "spdx" : ["BSD-3-Clause"] + } + } + } +] From 83e85bebcb5257a29402b6d4f64925b63ac3d3a1 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Tue, 2 Jul 2024 10:43:22 +0200 Subject: [PATCH 057/341] Add more vendors to GPU detection This change expands the list of GPU vendors in the web engine context creation code. The original list was based on code inside Dawn, whereas this change adds entries from an equivalent list in ANGLE. This removes some startup warnings for a few more exotic system configurations (e.g. VMWare virtual machines). Fixes: QTBUG-126722 Pick-to: 6.7 Change-Id: I5548cc0677f80e02439e7c4cfc3ab1d680d10971 Reviewed-by: Peter Varga (cherry picked from commit 791ee8106f7a6c8f9c0bf13a46721df2a6cde651) Reviewed-by: Qt Cherry-pick Bot --- src/core/web_engine_context.cpp | 42 +++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index bf6a06ae5af..d1504a6851c 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -135,6 +135,8 @@ class GPUInfo public: enum Vendor { Unknown = -1, + + // PCI-SIG-registered vendors AMD, Apple, ARM, @@ -142,10 +144,20 @@ class GPUInfo ImgTec, Intel, Microsoft, - Mesa, Nvidia, Qualcomm, - Samsung + Samsung, + Broadcom, + VMWare, + VirtIO, + + // Khronos-registered vendors + Vivante, + VeriSilicon, + Kazan, + CodePlay, + Mesa, + PoCL, }; static GPUInfo *instance() @@ -157,7 +169,7 @@ class GPUInfo static Vendor vendorIdToVendor(quint64 vendorId) { // clang-format off - // Based on //third_party/dawn/src/dawn/gpu_info.json + // Based on //third_party/angle/src/gpu_info_util/SystemInfo.h static const std::map vendorIdMap = { {0x0, Unknown}, {0x1002, AMD}, @@ -166,11 +178,19 @@ class GPUInfo {0x1AE0, Google}, {0x1010, ImgTec}, {0x8086, Intel}, - {0x10005, Mesa}, {0x1414, Microsoft}, {0x10DE, Nvidia}, {0x5143, Qualcomm}, - {0x144D, Samsung} + {0x144D, Samsung}, + {0x14E4, Broadcom}, + {0x15AD, VMWare}, + {0x1AF4, VirtIO}, + {0x10001, Vivante}, + {0x10002, VeriSilicon}, + {0x10003, Kazan}, + {0x10004, CodePlay}, + {0x10005, Mesa}, + {0x10006, PoCL}, }; // clang-format on @@ -216,11 +236,19 @@ class GPUInfo {Google, "Google"}, {ImgTec, "Img Tec"}, {Intel, "Intel"}, - {Mesa, "Mesa"}, {Microsoft, "Microsoft"}, {Nvidia, "Nvidia"}, {Qualcomm, "Qualcomm"}, - {Samsung, "Samsung"} + {Samsung, "Samsung"}, + {Broadcom, "Broadcom"}, + {VMWare, "VMWare"}, + {VirtIO, "VirtIO"}, + {Vivante, "Vivante"}, + {VeriSilicon, "VeriSilicon"}, + {Kazan, "Kazan"}, + {CodePlay, "CodePlay"}, + {Mesa, "Mesa"}, + {PoCL, "PoCL"}, }; // clang-format on From 27455f47da86b635f2b940aa81084c8ab8a30283 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Tue, 9 Jul 2024 10:57:39 +0200 Subject: [PATCH 058/341] Write permissions and preferences to disk whenever they're modified Previously, permissions and user prefs would only get committed to disk when the application closed, and only if it did so with no errors. This could obviously lead to data loss when the application crashes, so this change adds calls to PrefService::SchedulePendingLossyWrites() whenever a permission or user pref is modified. This way, the data will be written to disk quickly after it's modified inside the PrefService. Change-Id: I8aa7c22f9a8b701f697f39132bf3e82ae3c66cc0 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 06507fd00502a1260c088302e36c5ffd355c805f) Reviewed-by: Qt Cherry-pick Bot --- src/core/permission_manager_qt.cpp | 2 ++ src/core/pref_service_adapter.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index b9a327d51cb..2792a07edf1 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -531,6 +531,8 @@ void PermissionManagerQt::setPermission( ScopedDictPrefUpdate updater(m_prefService.get(), permissionTypeString(permissionType)); updater.Get().Set(requesting_origin.spec(), granted); + + m_prefService->SchedulePendingLossyWrites(); } } // namespace QtWebEngineCore diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index d561cab4fbc..72eb850e7b9 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -150,6 +150,8 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) m_prefService->ClearPref(spellcheck::prefs::kSpellCheckEnable); m_prefService->ClearPref(spellcheck::prefs::kSpellCheckDictionaries); #endif // QT_CONFIG(webengine_spellchecker) + + m_prefService->SchedulePendingLossyWrites(); } void PrefServiceAdapter::commit() @@ -185,6 +187,7 @@ void PrefServiceAdapter::setSpellCheckLanguages(const QStringList &languages) for (const auto &language : languages) dictionaries.push_back(language.toStdString()); dictionaries_pref.SetValue(dictionaries); + m_prefService->SchedulePendingLossyWrites(); } QStringList PrefServiceAdapter::spellCheckLanguages() const @@ -201,6 +204,7 @@ QStringList PrefServiceAdapter::spellCheckLanguages() const void PrefServiceAdapter::setSpellCheckEnabled(bool enabled) { m_prefService->SetBoolean(spellcheck::prefs::kSpellCheckEnable, enabled); + m_prefService->SchedulePendingLossyWrites(); } bool PrefServiceAdapter::isSpellCheckEnabled() const From 26b166183e7c0d78396d8e26e06b149be6c86f23 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Mon, 1 Jul 2024 16:00:47 +0200 Subject: [PATCH 059/341] Update Chromium MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule src/3rdparty 28f666ec..95fda5a0: * Work around MSVC 17.10 bug * Modify .gitattributes to stop PDF file line ending changes * FIXUP: Silence most warnings * FIXUP: Fix vaapi support for QtWebEngine Change-Id: I0ce1df66cab625260b491bb86e3414a3b1313251 Reviewed-by: Michael BrĂ¼ning (cherry picked from commit 27b3312102ce9f2d72d63a26072159c700161655) --- src/3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index e2c589700c3..95fda5a0e06 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit e2c589700c312d35a503a15c30ea6432d77cbca2 +Subproject commit 95fda5a0e06d39e23be741dbd52bd8d6597ff86e From d698419f73f8f125f806b95cb3fb9c203122565d Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 12 Jul 2024 18:20:52 +0000 Subject: [PATCH 060/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I28ef77db8280c845a44454d4377564d63677ef65 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index e87c805d4c0..91fa28f2627 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: e9f904aaf2bc17d46709a6a32a6ee22a0eeaf909 + ref: 6b21cd12e3d20af2c374e5fbe4a8e3021a7addd3 required: true ../qtpositioning: - ref: fb6aa84a86ef5238bc78e1016045bf6ead024947 + ref: fde5b24156d54a646e5f19fca7a0ac3e01f9b175 required: false ../qttools: - ref: 81114e34cf4fd0438c0b7500dec5127e7acc5acc + ref: 0cabf7a4f3b7d9ee300d22613a7545a63a522d06 required: false ../qtwebchannel: - ref: 1e1b3285624ad11e40765304900cfa2feb262988 + ref: bc034a51e65392d03458b6068a3a121a3a60a3d2 required: false From d4435b47ada2d2f14e980c30d390b9a99dff80f5 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Tue, 9 Jul 2024 13:14:13 +0200 Subject: [PATCH 061/341] Remove usage of non-standard swprintf WebEngineLibraryInfo::isRemoteDrivePath usea an MSVC-only, non-standard version of swprintf which doesn't have a len argument, triggering a compiler warning. This change adds the len argument, which fixes the warning. Pick-to: 6.7 Change-Id: I7124e5e5260ed39e46f7df4dc4dfc39521d6374d Reviewed-by: Michal Klocek (cherry picked from commit f4b3399471112ae5f6df86c649df2c6e25c99410) Reviewed-by: Qt Cherry-pick Bot --- src/core/web_engine_library_info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index e7115389962..8b69bec3c92 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -429,7 +429,7 @@ std::string WebEngineLibraryInfo::getApplicationLocale() bool WebEngineLibraryInfo::isRemoteDrivePath(const QString &path) { WCHAR wDriveLetter[4] = { 0 }; - swprintf(wDriveLetter, L"%S", path.mid(0, 3).toStdString().c_str()); + swprintf(wDriveLetter, 4, L"%S", path.mid(0, 3).toStdString().c_str()); return GetDriveType(wDriveLetter) == DRIVE_REMOTE; } From 3036e77a156c6770716e95b196e0afcf00275cca Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 15 Jul 2024 17:21:23 +0000 Subject: [PATCH 062/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Icf45392574a50287277b986a8d886a27765767ba Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 91fa28f2627..740679e5b86 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 6b21cd12e3d20af2c374e5fbe4a8e3021a7addd3 + ref: 321c8a88eb575749cca8d5116b2a131c7932f74d required: true ../qtpositioning: - ref: fde5b24156d54a646e5f19fca7a0ac3e01f9b175 + ref: ea75bd6c9a1df3f91c718e7a6a20f582405bd913 required: false ../qttools: - ref: 0cabf7a4f3b7d9ee300d22613a7545a63a522d06 + ref: eedf2f68c5918074443b556183ab4068d7255d01 required: false ../qtwebchannel: - ref: bc034a51e65392d03458b6068a3a121a3a60a3d2 + ref: 40451b711429d04347cdd010b904699303d311a4 required: false From 63a801b7d3e8e3f92fe63d02d9bb5129ac7eb3ac Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Thu, 4 Jul 2024 13:32:01 +0200 Subject: [PATCH 063/341] QWebEngineFrame: hold weak ref to adapter This is a bit safer as it prevents crashes when the adapter/page is no longer around. This also adds a getter for the adapterClient on WebContentsAdapter. Change-Id: I50690fd7bf3e5fe60568c565ce0fff20a832351f Reviewed-by: Michal Klocek (cherry picked from commit aa7c32734ca0b05440d01ffd6b943ce435825947) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineframe.cpp | 50 +++++++++++++------ src/core/api/qwebengineframe.h | 11 ++-- src/core/api/qwebenginepage.cpp | 6 +-- src/core/web_contents_adapter.cpp | 5 ++ src/core/web_contents_adapter.h | 1 + .../api/qquickwebengineview.cpp | 6 +-- 6 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/core/api/qwebengineframe.cpp b/src/core/api/qwebengineframe.cpp index fa2cbb507b3..6eb628ffabf 100644 --- a/src/core/api/qwebengineframe.cpp +++ b/src/core/api/qwebengineframe.cpp @@ -13,6 +13,11 @@ QT_BEGIN_NAMESPACE +#define LOCK_ADAPTER(adapter_variable, return_value) \ + auto adapter = m_adapter.lock(); \ + if (!adapter) \ + return return_value + /*! \class QWebEngineFrame \brief The QWebEngineFrame class gives information about and control over a page frame. @@ -34,8 +39,9 @@ QT_BEGIN_NAMESPACE /*! \internal */ -QWebEngineFrame::QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *adapter, quint64 id) - : m_adapterClient(adapter), m_id(id) +QWebEngineFrame::QWebEngineFrame(QWeakPointer adapter, + quint64 id) + : m_adapter(std::move(adapter)), m_id(id) { } @@ -46,7 +52,8 @@ QWebEngineFrame::QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *adap */ bool QWebEngineFrame::isValid() const { - return m_adapterClient->webContentsAdapter()->hasFrame(m_id); + LOCK_ADAPTER(adapter, false); + return adapter->hasFrame(m_id); } /*! @@ -58,7 +65,8 @@ bool QWebEngineFrame::isValid() const */ QString QWebEngineFrame::name() const { - return m_adapterClient->webContentsAdapter()->frameName(m_id); + LOCK_ADAPTER(adapter, QString()); + return adapter->frameName(m_id); } /*! @@ -70,7 +78,8 @@ QString QWebEngineFrame::name() const */ QString QWebEngineFrame::htmlName() const { - return m_adapterClient->webContentsAdapter()->frameHtmlName(m_id); + LOCK_ADAPTER(adapter, QString()); + return adapter->frameHtmlName(m_id); } /*! @@ -80,9 +89,10 @@ QString QWebEngineFrame::htmlName() const */ QList QWebEngineFrame::children() const { + LOCK_ADAPTER(adapter, {}); QList result; - for (auto childId : m_adapterClient->webContentsAdapter()->frameChildren(m_id)) - result.push_back(QWebEngineFrame{ m_adapterClient, childId }); + for (auto childId : adapter->frameChildren(m_id)) + result.push_back(QWebEngineFrame{ m_adapter, childId }); return result; } @@ -93,7 +103,8 @@ QList QWebEngineFrame::children() const */ QUrl QWebEngineFrame::url() const { - return m_adapterClient->webContentsAdapter()->frameUrl(m_id); + LOCK_ADAPTER(adapter, QUrl()); + return adapter->frameUrl(m_id); } /*! @@ -103,7 +114,8 @@ QUrl QWebEngineFrame::url() const */ QSizeF QWebEngineFrame::size() const { - return m_adapterClient->webContentsAdapter()->frameSize(m_id); + LOCK_ADAPTER(adapter, QSizeF()); + return adapter->frameSize(m_id); } /*! @@ -111,7 +123,8 @@ QSizeF QWebEngineFrame::size() const */ bool QWebEngineFrame::isMainFrame() const { - return m_adapterClient->webContentsAdapter()->mainFrameId() == m_id; + LOCK_ADAPTER(adapter, false); + return adapter->mainFrameId() == m_id; } /*! \fn void QWebEngineFrame::runJavaScript(const QString &script, const std::function &callback) @@ -153,7 +166,8 @@ void QWebEngineFrame::runJavaScript(const QString &script, void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, const std::function &callback) { - m_adapterClient->runJavaScript(script, worldId, m_id, callback); + LOCK_ADAPTER(adapter, ); + adapter->runJavaScript(script, worldId, m_id, callback); } void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId) @@ -169,9 +183,10 @@ void QWebEngineFrame::runJavaScript(const QString &script, const QJSValue &callb void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, const QJSValue &callback) { + LOCK_ADAPTER(adapter, ); std::function wrappedCallback; if (!callback.isUndefined()) { - const QObject *holdingObject = m_adapterClient->holdingQObject(); + const QObject *holdingObject = adapter->adapterClient()->holdingQObject(); wrappedCallback = [holdingObject, callback](const QVariant &result) { if (auto engine = qmlEngine(holdingObject)) { QJSValueList args; @@ -203,8 +218,9 @@ void QWebEngineFrame::runJavaScript(const QString &script, quint32 worldId, */ void QWebEngineFrame::printToPdf(const QString &filePath) { + LOCK_ADAPTER(adapter, ); QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); - m_adapterClient->printToPdf(filePath, layout, QPageRanges(), m_id); + adapter->adapterClient()->printToPdf(filePath, layout, QPageRanges(), m_id); } /*! @@ -219,19 +235,21 @@ void QWebEngineFrame::printToPdf(const QString &filePath) */ void QWebEngineFrame::printToPdf(const std::function &callback) { + LOCK_ADAPTER(adapter, ); std::function wrappedCallback = [callback](QSharedPointer result) { if (callback) callback(result ? *result : QByteArray()); }; QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); - m_adapterClient->printToPdf(std::move(wrappedCallback), layout, QPageRanges(), m_id); + adapter->adapterClient()->printToPdf(std::move(wrappedCallback), layout, QPageRanges(), m_id); } void QWebEngineFrame::printToPdf(const QJSValue &callback) { + LOCK_ADAPTER(adapter, ); std::function)> wrappedCallback; if (!callback.isUndefined()) { - const QObject *holdingObject = m_adapterClient->holdingQObject(); + const QObject *holdingObject = adapter->adapterClient()->holdingQObject(); wrappedCallback = [holdingObject, callback](QSharedPointer result) { if (auto engine = qmlEngine(holdingObject)) { QJSValueList args; @@ -243,7 +261,7 @@ void QWebEngineFrame::printToPdf(const QJSValue &callback) }; } QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); - m_adapterClient->printToPdf(std::move(wrappedCallback), layout, QPageRanges(), m_id); + adapter->adapterClient()->printToPdf(std::move(wrappedCallback), layout, QPageRanges(), m_id); } /*! \fn bool QWebEngineFrame::operator==(const QWebEngineFrame &left, const QWebEngineFrame &right) noexcept diff --git a/src/core/api/qwebengineframe.h b/src/core/api/qwebengineframe.h index 85b02407a4d..02f442f4f47 100644 --- a/src/core/api/qwebengineframe.h +++ b/src/core/api/qwebengineframe.h @@ -12,9 +12,10 @@ #include #include #include +#include namespace QtWebEngineCore { -class WebContentsAdapterClient; +class WebContentsAdapter; } QT_BEGIN_NAMESPACE @@ -61,7 +62,7 @@ class QWebEngineFrame friend inline bool comparesEqual(const QWebEngineFrame &lhs, const QWebEngineFrame &rhs) noexcept { - return lhs.m_adapterClient == rhs.m_adapterClient && lhs.m_id == rhs.m_id; + return lhs.m_adapter == rhs.m_adapter && lhs.m_id == rhs.m_id; } Q_DECLARE_EQUALITY_COMPARABLE(QWebEngineFrame); @@ -72,10 +73,10 @@ class QWebEngineFrame friend class QQuickWebEngineView; friend class QQuickWebEngineViewPrivate; - Q_WEBENGINECORE_EXPORT QWebEngineFrame(QtWebEngineCore::WebContentsAdapterClient *page, - quint64 id); + Q_WEBENGINECORE_EXPORT + QWebEngineFrame(QWeakPointer adapter, quint64 id); - QtWebEngineCore::WebContentsAdapterClient *m_adapterClient; + QWeakPointer m_adapter; quint64 m_id; }; diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 433de26b072..c125b3aca47 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -1768,7 +1768,7 @@ void QWebEnginePagePrivate::printRequested() void QWebEnginePagePrivate::printRequestedByFrame(quint64 frameId) { Q_Q(QWebEnginePage); - QWebEngineFrame frame(this, frameId); + QWebEngineFrame frame(adapter, frameId); QTimer::singleShot(0, q, [q, frame]() { Q_EMIT q->printRequestedByFrame(frame); }); if (view) view->printRequestedByFrame(frame); @@ -2555,7 +2555,7 @@ void QWebEnginePage::setVisible(bool visible) QWebEngineFrame QWebEnginePage::mainFrame() { Q_D(QWebEnginePage); - return QWebEngineFrame(d, d->adapter->mainFrameId()); + return QWebEngineFrame(d->adapter, d->adapter->mainFrameId()); } /*! @@ -2568,7 +2568,7 @@ std::optional QWebEnginePage::findFrameByName(QAnyStringView na { Q_D(QWebEnginePage); if (auto maybeId = d->adapter->findFrameIdByName(name.toString())) { - return QWebEngineFrame(d, *maybeId); + return QWebEngineFrame(d->adapter, *maybeId); } return {}; } diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index a40f641c11b..c49331f1e76 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1561,6 +1561,11 @@ content::WebContents *WebContentsAdapter::guestWebContents() const return !innerWebContents.empty() ? innerWebContents[0] : nullptr; } +WebContentsAdapterClient *WebContentsAdapter::adapterClient() +{ + return m_adapterClient; +} + #if QT_CONFIG(webengine_webchannel) QWebChannel *WebContentsAdapter::webChannel() const { diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 41a296072ba..44ee7823dde 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -238,6 +238,7 @@ class Q_WEBENGINECORE_EXPORT WebContentsAdapter : public QEnableSharedFromThisprintRequestedByFrame(QWebEngineFrame(this, frameId)); + Q_EMIT q->printRequestedByFrame(QWebEngineFrame(this->adapter, frameId)); }); } @@ -2597,14 +2597,14 @@ QQmlComponent *QQuickWebEngineView::touchHandleDelegate() const QWebEngineFrame QQuickWebEngineView::mainFrame() { Q_D(QQuickWebEngineView); - return QWebEngineFrame(d, d->adapter->mainFrameId()); + return QWebEngineFrame(d->adapter, d->adapter->mainFrameId()); } QWebEngineFrame QQuickWebEngineView::findFrameByName(const QString &name) { Q_D(QQuickWebEngineView); auto maybeId = d->adapter->findFrameIdByName(name); - return QWebEngineFrame(d, maybeId.value_or(WebContentsAdapter::kInvalidFrameId)); + return QWebEngineFrame(d->adapter, maybeId.value_or(WebContentsAdapter::kInvalidFrameId)); } void QQuickWebEngineView::save(const QString &filePath, From 3339c5eeeb88994118971ccda8ae54a6d3f0c8b3 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Thu, 11 Jul 2024 10:55:36 +0200 Subject: [PATCH 064/341] Fix deprecations in QQuickWebEngineView Add a missing QT_MOC_COMPAT macro in grantFeaturePermission, and remove the leftover moc workaround macro magic in featurePermissionRequested. Found in API review. Change-Id: I480b22accd076abc7e30f12f9d65ee323c08839c Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 944a92d9da346f5a4059d928678412e4c8e066ff) Reviewed-by: Qt Cherry-pick Bot --- src/webenginequick/api/qquickwebengineview_p.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h index d15b8e82cc4..53f81f776ea 100644 --- a/src/webenginequick/api/qquickwebengineview_p.h +++ b/src/webenginequick/api/qquickwebengineview_p.h @@ -492,7 +492,7 @@ public Q_SLOTS: Q_REVISION(1,1) void findText(const QString &subString, FindFlags options = { }, const QJSValue &callback = QJSValue()); Q_REVISION(1,1) void fullScreenCancelled(); #if QT_DEPRECATED_SINCE(6, 8) - QT_DEPRECATED_VERSION_X_6_8("Setting permissions through WebEngineView has been deprecated. Please use WebEnginePermission instead.") + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("Setting permissions through WebEngineView has been deprecated. Please use WebEnginePermission instead.") Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature, bool granted); #endif // QT_DEPRECATED_SINCE(6, 8) Q_REVISION(1,2) void setActiveFocusOnPress(bool arg); @@ -521,17 +521,10 @@ private Q_SLOTS: Q_REVISION(1,1) void fullScreenRequested(const QWebEngineFullScreenRequest &request); Q_REVISION(1,1) void isFullScreenChanged(); #if QT_DEPRECATED_SINCE(6, 8) -#if !defined(Q_MOC_RUN) -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED -#endif // !defined(Q_MOC_RUN) QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated; please use permissionRequested instead.") Q_REVISION(1, 1) void featurePermissionRequested(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature); -#if !defined(Q_MOC_RUN) -QT_WARNING_POP -#endif // !defined(Q_MOC_RUN) #endif // QT_DEPRECATED_SINCE(6, 8) Q_REVISION(1,1) void zoomFactorChanged(qreal arg); Q_REVISION(1,1) void profileChanged(); From 523aeb9ced2b8ffd78453469e4d094a5b6fa2ce3 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Thu, 4 Jul 2024 09:42:12 +0200 Subject: [PATCH 065/341] QWebEnginePermission: fix the name of comparison helper Do not use comparesEqual() as a name of a 1-arg member function, as it is used in the C++20 comparison framework and should be a 2-arg hidden friend. Rename the exported member function to equals(), thus leaving the possibility to use the comparison helper macros later, if needed. Amends 00d7de830a43a84a431511a55525f04c21b8ba49. Found in Qt 6.8 API review. Change-Id: I0ed9bf9ee08418da2f489ed328aecee412486fd0 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit ba5199f362b2362bb9b9d8e05aad9ef0129c8e22) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginepermission.cpp | 2 +- src/core/api/qwebenginepermission.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp index a6860b5ddff..9cef4bf9684 100644 --- a/src/core/api/qwebenginepermission.cpp +++ b/src/core/api/qwebenginepermission.cpp @@ -104,7 +104,7 @@ QWebEnginePermission &QWebEnginePermission::operator=(const QWebEnginePermission return *this; } -bool QWebEnginePermission::comparesEqual(const QWebEnginePermission &other) const +bool QWebEnginePermission::equals(const QWebEnginePermission &other) const { if (this == &other) return true; diff --git a/src/core/api/qwebenginepermission.h b/src/core/api/qwebenginepermission.h index 440bf788b71..a6a767aeb9f 100644 --- a/src/core/api/qwebenginepermission.h +++ b/src/core/api/qwebenginepermission.h @@ -79,11 +79,11 @@ class QWebEnginePermission private: inline friend bool operator==(const QWebEnginePermission &lhs, const QWebEnginePermission &rhs) - { return lhs.comparesEqual(rhs); }; + { return lhs.equals(rhs); }; inline friend bool operator!=(const QWebEnginePermission &lhs, const QWebEnginePermission &rhs) - { return !lhs.comparesEqual(rhs); }; + { return !lhs.equals(rhs); }; - Q_WEBENGINECORE_EXPORT bool comparesEqual(const QWebEnginePermission &other) const; + Q_WEBENGINECORE_EXPORT bool equals(const QWebEnginePermission &other) const; protected: friend class QWebEnginePagePrivate; From bcb95b58086c9126dcc38fffe7dbd309f212f1f2 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 5 Jul 2024 10:53:00 +0200 Subject: [PATCH 066/341] Remove use_vaapi_x11 from GN argument list No longer available after 122-based update. See, https://crrev.com/c/3646633 Change-Id: I4698f186f315a0d105f9f01df413fc360a90d486 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 4ba69b273d33462fdf1984f574597668b02a53a0) Reviewed-by: Qt Cherry-pick Bot --- src/core/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d43188813db..c5ff65405ac 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -510,10 +510,6 @@ foreach(arch ${archs}) ARGS rtc_use_x11 CONDITION QT_FEATURE_webengine_ozone_x11 AND QT_FEATURE_webengine_webrtc ) - extend_gn_list(gnArgArg - ARGS use_vaapi_x11 - CONDITION QT_FEATURE_webengine_ozone_x11 AND QT_FEATURE_webengine_vaapi - ) if(QT_FEATURE_webengine_kerberos) list(APPEND gnArgArg From 133dbd5d2a8d36be811cf95a93e813b56c65bce3 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 3 Jul 2024 15:05:12 +0200 Subject: [PATCH 067/341] Fix restoring EGL context in EGLHelper In case of ANGLE, the gl::GLContext::MakeCurrent() makes the ANGLE context current and not the underlying native context. Use native eglMakeCurrent() instead. Change-Id: I84a0cb77478e906ad8926db8813b0c3386521bf3 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 55d0379824cc92cb850f656039c2d13275104b55) Reviewed-by: Qt Cherry-pick Bot --- src/core/ozone/gl_context_qt.cpp | 42 +++++++++++++++++++++++++------- src/core/ozone/gl_context_qt.h | 8 ++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index 634e2aa0f64..08729a78a12 100644 --- a/src/core/ozone/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -162,11 +162,16 @@ bool GLContextHelper::isCreateContextRobustnessSupported() class ScopedGLContext { public: - ScopedGLContext(QOffscreenSurface *surface) - : m_context(new QOpenGLContext()) - , m_previousContext(gl::GLContext::GetCurrent()) - , m_previousSurface(gl::GLSurface::GetCurrent()) + ScopedGLContext(QOffscreenSurface *surface) : m_context(new QOpenGLContext()) { + if (gl::GLContext::GetCurrent()) { + auto eglFun = EGLHelper::instance()->functions(); + m_previousEGLContext = eglFun->eglGetCurrentContext(); + m_previousEGLDrawSurface = eglFun->eglGetCurrentSurface(EGL_DRAW); + m_previousEGLReadSurface = eglFun->eglGetCurrentSurface(EGL_READ); + m_previousEGLDisplay = eglFun->eglGetCurrentDisplay(); + } + if (!m_context->create()) { qWarning("Failed to create OpenGL context."); return; @@ -186,8 +191,18 @@ class ScopedGLContext glFun->glDeleteTextures(m_textures.size(), m_textures.data()); } - if (m_previousContext) - m_previousContext->MakeCurrent(m_previousSurface); + if (m_previousEGLContext) { + // Make sure the scoped context is not current when restoring the previous + // EGL context otherwise the QOpenGLContext destructor resets the restored + // current context. + m_context->doneCurrent(); + + auto eglFun = EGLHelper::instance()->functions(); + eglFun->eglMakeCurrent(m_previousEGLDisplay, m_previousEGLDrawSurface, + m_previousEGLReadSurface, m_previousEGLContext); + if (eglFun->eglGetError() != EGL_SUCCESS) + qWarning("Failed to restore EGL context."); + } } bool isValid() const { return m_context->isValid() && (m_context->surface() != nullptr); } @@ -223,8 +238,10 @@ class ScopedGLContext private: QScopedPointer m_context; - gl::GLContext *m_previousContext; - gl::GLSurface *m_previousSurface; + EGLContext m_previousEGLContext = nullptr; + EGLSurface m_previousEGLDrawSurface = nullptr; + EGLSurface m_previousEGLReadSurface = nullptr; + EGLDisplay m_previousEGLDisplay = nullptr; std::vector m_textures; }; @@ -235,11 +252,18 @@ EGLHelper::EGLFunctions::EGLFunctions() eglCreateImage = reinterpret_cast(getProcAddress("eglCreateImage")); eglDestroyImage = reinterpret_cast(getProcAddress("eglDestroyImage")); - eglGetError = reinterpret_cast(getProcAddress("eglGetError")); eglExportDMABUFImageMESA = reinterpret_cast( getProcAddress("eglExportDMABUFImageMESA")); eglExportDMABUFImageQueryMESA = reinterpret_cast( getProcAddress("eglExportDMABUFImageQueryMESA")); + eglGetCurrentContext = + reinterpret_cast(getProcAddress("eglGetCurrentContext")); + eglGetCurrentDisplay = + reinterpret_cast(getProcAddress("eglGetCurrentDisplay")); + eglGetCurrentSurface = + reinterpret_cast(getProcAddress("eglGetCurrentSurface")); + eglGetError = reinterpret_cast(getProcAddress("eglGetError")); + eglMakeCurrent = reinterpret_cast(getProcAddress("eglMakeCurrent")); eglQueryString = reinterpret_cast(getProcAddress("eglQueryString")); } diff --git a/src/core/ozone/gl_context_qt.h b/src/core/ozone/gl_context_qt.h index 1607284331b..81c08a65073 100644 --- a/src/core/ozone/gl_context_qt.h +++ b/src/core/ozone/gl_context_qt.h @@ -50,7 +50,11 @@ class GLContextHelper : public QObject { #undef eglDestroyImage #undef eglExportDMABUFImageMESA #undef eglExportDMABUFImageQueryMESA +#undef eglGetCurrentContext +#undef eglGetCurrentDisplay +#undef eglGetCurrentSurface #undef eglGetError +#undef eglMakeCurrent #undef eglQueryString class EGLHelper @@ -64,7 +68,11 @@ class EGLHelper PFNEGLDESTROYIMAGEPROC eglDestroyImage; PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImageMESA; PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC eglExportDMABUFImageQueryMESA; + PFNEGLGETCURRENTCONTEXTPROC eglGetCurrentContext; + PFNEGLGETCURRENTDISPLAYPROC eglGetCurrentDisplay; + PFNEGLGETCURRENTSURFACEPROC eglGetCurrentSurface; PFNEGLGETERRORPROC eglGetError; + PFNEGLMAKECURRENTPROC eglMakeCurrent; PFNEGLQUERYSTRINGPROC eglQueryString; }; From df6e6d17f2e8958e722a7845c79513d96e42f81f Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 12 Jan 2024 12:46:08 +0100 Subject: [PATCH 068/341] Support ANGLE to EGL/GLX painting Enable it with: --webEngineArgs --use-gl=angle --use-angle=gl-egl Task-number: QTBUG-112281 Change-Id: I224bbcb486489450635010400053318f3ec04c97 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 32e16d24c556fcba380f10f5f1284dad7162e891) Reviewed-by: Qt Cherry-pick Bot --- src/core/CMakeLists.txt | 2 + .../compositor/native_skia_output_device.cpp | 7 +- .../native_skia_output_device_opengl.cpp | 236 +++++++++++++++++- src/core/ozone/gl_ozone_angle_qt.cpp | 119 +++++++++ src/core/ozone/gl_ozone_angle_qt.h | 41 +++ src/core/ozone/surface_factory_qt.cpp | 36 ++- src/core/ozone/surface_factory_qt.h | 3 +- 7 files changed, 425 insertions(+), 19 deletions(-) create mode 100644 src/core/ozone/gl_ozone_angle_qt.cpp create mode 100644 src/core/ozone/gl_ozone_angle_qt.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c5ff65405ac..24ccdacbbf4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -149,6 +149,7 @@ foreach(arch ${archs}) net/version_ui_qt.cpp net/version_ui_qt.h net/webui_controller_factory_qt.cpp net/webui_controller_factory_qt.h ozone/gl_context_qt.cpp ozone/gl_context_qt.h + ozone/gl_ozone_angle_qt.cpp ozone/gl_ozone_angle_qt.h ozone/gl_ozone_egl_qt.cpp ozone/gl_ozone_egl_qt.h ozone/gl_share_context_qt.cpp ozone/gl_share_context_qt.h ozone/gl_surface_egl_qt.cpp ozone/gl_surface_egl_qt.h @@ -427,6 +428,7 @@ foreach(arch ${archs}) if(LINUX) list(APPEND gnArgArg + angle_enable_gl=true use_gtk=false # GTK toolkit bindings use_qt=false # Qt5 toolkit bindings use_cups=false diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp index 708692df7d5..4420e8d59aa 100644 --- a/src/core/compositor/native_skia_output_device.cpp +++ b/src/core/compositor/native_skia_output_device.cpp @@ -222,9 +222,12 @@ NativeSkiaOutputDevice::Buffer::~Buffer() // found in the LICENSE file. bool NativeSkiaOutputDevice::Buffer::initialize() { - static const uint32_t kDefaultSharedImageUsage = gpu::SHARED_IMAGE_USAGE_SCANOUT - | gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE + uint32_t kDefaultSharedImageUsage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ + | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE | gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT; + if (m_parent->m_isNativeBufferSupported) + kDefaultSharedImageUsage |= gpu::SHARED_IMAGE_USAGE_SCANOUT; + auto mailbox = gpu::Mailbox::GenerateForSharedImage(); SkColorType skColorType = m_shape.imageInfo.colorType(); diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index 058573b9e55..c8430f0f7d6 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -1,6 +1,10 @@ // Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.Chromium file. + #include "native_skia_output_device_opengl.h" #include @@ -8,8 +12,107 @@ #include #include +#include "ui/base/ozone_buildflags.h" +#include "ui/gl/gl_implementation.h" + +#if defined(USE_OZONE) +#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" +#include "ui/gfx/linux/drm_util_linux.h" +#include "ui/gfx/linux/native_pixmap_dmabuf.h" + +#if BUILDFLAG(IS_OZONE_X11) +#include "base/posix/eintr_wrapper.h" +#include "ui/gfx/x/connection.h" +#include "ui/gfx/x/dri3.h" +#include "ui/gfx/x/future.h" +#include "ui/gfx/x/glx.h" +#include "ui/gfx/x/xproto.h" + +#include "ui/gl/gl_bindings.h" +#undef glBindTexture +#undef glDeleteTextures +#undef glGenTextures +#endif // BUILDFLAG(IS_OZONE_X11) + +// Keep it at the end. +#include "ozone/gl_context_qt.h" +#endif // defined(USE_OZONE) + namespace QtWebEngineCore { +#if BUILDFLAG(IS_OZONE_X11) +namespace { + +// Based on //ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc +x11::Pixmap XPixmapFromNativePixmap(const gfx::NativePixmap &nativePixmap) +{ + // Hard coded values for gfx::BufferFormat::BGRA_8888: + const uint8_t depth = 32; + const uint8_t bpp = 32; + + const int dmaBufFd = HANDLE_EINTR(dup(nativePixmap.GetDmaBufFd(0))); + if (dmaBufFd < 0) { + qWarning("Could not import the dma-buf as an XPixmap because the FD couldn't be dup()ed."); + return x11::Pixmap::None; + } + x11::RefCountedFD refCountedFD(dmaBufFd); + + uint32_t size = base::checked_cast(nativePixmap.GetDmaBufPlaneSize(0)); + uint16_t width = base::checked_cast(nativePixmap.GetBufferSize().width()); + uint16_t height = base::checked_cast(nativePixmap.GetBufferSize().height()); + uint16_t stride = base::checked_cast(nativePixmap.GetDmaBufPitch(0)); + + auto *connection = x11::Connection::Get(); + const x11::Pixmap pixmapId = connection->GenerateId(); + if (pixmapId == x11::Pixmap::None) { + qWarning("Could not import the dma-buf as an XPixmap because an ID couldn't be generated."); + return x11::Pixmap::None; + } + + auto response = connection->dri3() + .PixmapFromBuffer(pixmapId, connection->default_root(), size, width, + height, stride, depth, bpp, refCountedFD) + .Sync(); + + if (response.error) { + qWarning() << "Could not import the dma-buf as an XPixmap because " + "PixmapFromBuffer() failed; error: " + << response.error->ToString(); + return x11::Pixmap::None; + } + + return pixmapId; +} + +GLXFBConfig GetFBConfig(Display *display) +{ + // clang-format off + static const int configAttribs[] = { + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_BUFFER_SIZE, 32, + GLX_BIND_TO_TEXTURE_RGBA_EXT, 1, + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, + GLX_DOUBLEBUFFER, 0, + GLX_Y_INVERTED_EXT, GLX_DONT_CARE, + 0 + }; + // clang-format on + + int numConfigs = 0; + GLXFBConfig *configs = glXChooseFBConfig(display, /* screen */ 0, configAttribs, &numConfigs); + if (!configs || numConfigs < 1) + qFatal("GLX: Failed to find frame buffer configuration for pixmap."); + + return configs[0]; +} + +} // namespace +#endif // BUILDFLAG(IS_OZONE_X11) + NativeSkiaOutputDeviceOpenGL::NativeSkiaOutputDeviceOpenGL( scoped_refptr contextState, bool requiresAlpha, gpu::MemoryTracker *memoryTracker, viz::SkiaOutputSurfaceDependency *dependency, @@ -21,6 +124,11 @@ NativeSkiaOutputDeviceOpenGL::NativeSkiaOutputDeviceOpenGL( didSwapBufferCompleteCallback) { SkColorType skColorType = kRGBA_8888_SkColorType; +#if BUILDFLAG(IS_OZONE_X11) + if (GLContextHelper::getGlxPlatformInterface()) + skColorType = kBGRA_8888_SkColorType; +#endif // BUILDFLAG(IS_OZONE_X11) + capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRA_8888)] = skColorType; @@ -39,10 +147,43 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te return nullptr; #if defined(USE_OZONE) + Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kGL); + + GrGLTextureInfo glTextureInfo; scoped_refptr nativePixmap = m_frontBuffer->nativePixmap(); if (!nativePixmap) { - qWarning("No native pixmap."); - return nullptr; + if (m_isNativeBufferSupported) { + qWarning("No native pixmap."); + return nullptr; + } + + sk_sp skImage = m_frontBuffer->skImage(); + if (!skImage) { + qWarning("No SkImage."); + return nullptr; + } + + if (!skImage->isTextureBacked()) { + qWarning("SkImage is not backed by GPU texture."); + return nullptr; + } + + GrBackendTexture backendTexture; + bool success = SkImages::GetBackendTextureFromImage(skImage, &backendTexture, false); + if (!success || !backendTexture.isValid()) { + qWarning("Failed to retrieve backend texture from SkImage."); + return nullptr; + } + + if (backendTexture.backend() != GrBackendApi::kOpenGL) { + qWarning("Backend texture is not a OpenGL texture."); + return nullptr; + } + + if (!GrBackendTextures::GetGLTextureInfo(backendTexture, &glTextureInfo)) { + qWarning("Unable to access OpenGL texture."); + return nullptr; + } } #elif defined(Q_OS_WIN) auto overlayImage = m_frontBuffer->overlayImage(); @@ -62,8 +203,95 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te QSGTexture *texture = nullptr; #if defined(USE_OZONE) - // TODO(QTBUG-112281): Add ANGLE support to Linux. - QT_NOT_YET_IMPLEMENTED + QOpenGLContext *glContext = QOpenGLContext::currentContext(); + auto glFun = glContext->functions(); + GLuint glTexture = 0; + + if (nativePixmap) { +#if BUILDFLAG(IS_OZONE_X11) + if (GLContextHelper::getGlxPlatformInterface()) { + x11::Pixmap pixmapId = + XPixmapFromNativePixmap(*(gfx::NativePixmapDmaBuf *)nativePixmap.get()); + if (pixmapId == x11::Pixmap::None) + qFatal("GLX: Failed to import XPixmap."); + + // clang-format off + static const int pixmapAttribs[] = { + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, + GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, + 0 + }; + // clang-format on + + Display *display = static_cast(GLContextHelper::getXDisplay()); + GLXPixmap glxPixmap = glXCreatePixmap(display, GetFBConfig(display), + static_cast<::Pixmap>(pixmapId), pixmapAttribs); + + glFun->glGenTextures(1, &glTexture); + glFun->glBindTexture(GL_TEXTURE_2D, glTexture); + glXBindTexImageEXT(display, glxPixmap, GLX_FRONT_LEFT_EXT, nullptr); + glFun->glBindTexture(GL_TEXTURE_2D, 0); + + m_frontBuffer->textureCleanupCallback = [glFun, glTexture, display, glxPixmap]() { + glFun->glDeleteTextures(1, &glTexture); + glXDestroyGLXPixmap(display, glxPixmap); + }; + } +#endif // BUILDFLAG(IS_OZONE_X11) + + if (GLContextHelper::getEglPlatformInterface()) { + EGLHelper *eglHelper = EGLHelper::instance(); + auto *eglFun = eglHelper->functions(); + + const int dmaBufFd = HANDLE_EINTR(dup(nativePixmap->GetDmaBufFd(0))); + if (dmaBufFd < 0) { + qFatal("Could not import the dma-buf as an EGLImage because the FD couldn't be " + "dup()ed."); + } + base::ScopedFD scopedFd(dmaBufFd); + + int drmFormat = ui::GetFourCCFormatFromBufferFormat(nativePixmap->GetBufferFormat()); + uint64_t modifier = nativePixmap->GetBufferFormatModifier(); + + // clang-format off + EGLAttrib const attributeList[] = { + EGL_WIDTH, size().width(), + EGL_HEIGHT, size().height(), + EGL_LINUX_DRM_FOURCC_EXT, drmFormat, + EGL_DMA_BUF_PLANE0_FD_EXT, scopedFd.get(), + EGL_DMA_BUF_PLANE0_OFFSET_EXT, nativePixmap->GetDmaBufOffset(0), + EGL_DMA_BUF_PLANE0_PITCH_EXT, nativePixmap->GetDmaBufPitch(0), + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, modifier & 0xffffffff, + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, modifier >> 32, + EGL_NONE + }; + // clang-format on + EGLImage eglImage = eglFun->eglCreateImage(GLContextHelper::getEGLDisplay(), + EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, + (EGLClientBuffer)NULL, attributeList); + Q_ASSERT(eglImage != EGL_NO_IMAGE_KHR); + + static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC imageTargetTexture = + (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)glContext->getProcAddress( + "glEGLImageTargetTexture2DOES"); + + glFun->glGenTextures(1, &glTexture); + glFun->glBindTexture(GL_TEXTURE_2D, glTexture); + imageTargetTexture(GL_TEXTURE_2D, eglImage); + glFun->glBindTexture(GL_TEXTURE_2D, 0); + + m_frontBuffer->textureCleanupCallback = [glFun, eglFun, glTexture, eglImage]() { + glFun->glDeleteTextures(1, &glTexture); + eglFun->eglDestroyImage(GLContextHelper::getEGLDisplay(), eglImage); + }; + } + } else { + // TODO: Import texture into Qt's context. + qWarning("ANGLE is not yet supported without NativePixmap."); + glTexture = glTextureInfo.fID; + } + + texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts); #elif defined(Q_OS_WIN) // TODO: Add WGL support over ANGLE. QT_NOT_YET_IMPLEMENTED diff --git a/src/core/ozone/gl_ozone_angle_qt.cpp b/src/core/ozone/gl_ozone_angle_qt.cpp new file mode 100644 index 00000000000..66692ed09a6 --- /dev/null +++ b/src/core/ozone/gl_ozone_angle_qt.cpp @@ -0,0 +1,119 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#if defined(USE_OZONE) +#include "gl_context_qt.h" +#include "gl_ozone_angle_qt.h" +#include "gl_surface_egl_qt.h" + +#include "ui/base/ozone_buildflags.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_display.h" +#include "ui/gl/gl_surface.h" +#include "ui/gl/gl_utils.h" +#include "ui/ozone/common/native_pixmap_egl_binding.h" + +#if BUILDFLAG(IS_OZONE_X11) +#include "ui/gl/gl_glx_api_implementation.h" +#endif + +extern "C" { +typedef void (*__eglMustCastToProperFunctionPointerType)(void); +extern __eglMustCastToProperFunctionPointerType EGL_GetProcAddress(const char *procname); +} + +namespace ui { + +bool GLOzoneANGLEQt::LoadGLES2Bindings(const gl::GLImplementationParts & /*implementation*/) +{ + gl::SetGLGetProcAddressProc(&EGL_GetProcAddress); + return true; +} + +bool GLOzoneANGLEQt::InitializeStaticGLBindings(const gl::GLImplementationParts &implementation) +{ + bool res = GLOzoneEGL::InitializeStaticGLBindings(implementation); + +#if BUILDFLAG(IS_OZONE_X11) + if (GLContextHelper::getGlxPlatformInterface()) { + gl::SetGLGetProcAddressProc(reinterpret_cast( + GLContextHelper::getGlXGetProcAddress())); + gl::InitializeStaticGLBindingsGLX(); + gl::SetGLGetProcAddressProc(&EGL_GetProcAddress); + } +#endif + + return res; +} + +bool GLOzoneANGLEQt::InitializeExtensionSettingsOneOffPlatform(gl::GLDisplay *display) +{ + bool res = GLOzoneEGL::InitializeExtensionSettingsOneOffPlatform( + static_cast(display)); + +#if BUILDFLAG(IS_OZONE_X11) + if (GLContextHelper::getGlxPlatformInterface()) { + gl::SetGLGetProcAddressProc(reinterpret_cast( + GLContextHelper::getGlXGetProcAddress())); + std::string extensions = + glXQueryExtensionsString((struct _XDisplay *)GLContextHelper::getXDisplay(), 0); + gl::g_driver_glx.InitializeExtensionBindings(extensions.c_str()); + gl::SetGLGetProcAddressProc(&EGL_GetProcAddress); + } +#endif + + return res; +} + +scoped_refptr GLOzoneANGLEQt::CreateViewGLSurface(gl::GLDisplay *display, + gfx::AcceleratedWidget window) +{ + Q_UNUSED(display); + Q_UNUSED(window); + return nullptr; +} + +// based on GLOzoneEGLX11::CreateOffscreenGLSurface() (x11_surface_factory.cc) +scoped_refptr GLOzoneANGLEQt::CreateOffscreenGLSurface(gl::GLDisplay *display, + const gfx::Size &size) +{ + gl::GLDisplayEGL *eglDisplay = display->GetAs(); + + if (eglDisplay->IsEGLSurfacelessContextSupported() && size.width() == 0 && size.height() == 0) + return InitializeGLSurface(new gl::SurfacelessEGL(eglDisplay, size)); + + return InitializeGLSurface(new gl::PbufferGLSurfaceEGL(eglDisplay, size)); +} + +gl::EGLDisplayPlatform GLOzoneANGLEQt::GetNativeDisplay() +{ +#if BUILDFLAG(IS_OZONE_X11) + void *xdisplay = GLContextHelper::getXDisplay(); + if (xdisplay) + return gl::EGLDisplayPlatform(reinterpret_cast(xdisplay)); +#endif + + if (gl::g_driver_egl.client_ext.b_EGL_MESA_platform_surfaceless) + return gl::EGLDisplayPlatform(EGL_DEFAULT_DISPLAY, EGL_PLATFORM_SURFACELESS_MESA); + + return gl::EGLDisplayPlatform(EGL_DEFAULT_DISPLAY); +} + +bool GLOzoneANGLEQt::CanImportNativePixmap() +{ + return gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_EXT_image_dma_buf_import; +} + +std::unique_ptr +GLOzoneANGLEQt::ImportNativePixmap(scoped_refptr pixmap, + gfx::BufferFormat plane_format, gfx::BufferPlane plane, + gfx::Size plane_size, const gfx::ColorSpace &color_space, + GLenum target, GLuint texture_id) +{ + return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, color_space, + target, texture_id); +} + +} // namespace ui + +#endif // defined(USE_OZONE) diff --git a/src/core/ozone/gl_ozone_angle_qt.h b/src/core/ozone/gl_ozone_angle_qt.h new file mode 100644 index 00000000000..bba276fc09b --- /dev/null +++ b/src/core/ozone/gl_ozone_angle_qt.h @@ -0,0 +1,41 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef GL_OZONE_ANGLE_QT_H +#define GL_OZONE_ANGLE_QT_H + +#if defined(USE_OZONE) +#include "ui/ozone/common/gl_ozone_egl.h" + +namespace ui { + +class GLOzoneANGLEQt : public GLOzoneEGL +{ +public: + bool InitializeStaticGLBindings(const gl::GLImplementationParts &implementation) override; + bool InitializeExtensionSettingsOneOffPlatform(gl::GLDisplay *display) override; + scoped_refptr CreateViewGLSurface(gl::GLDisplay *display, + gfx::AcceleratedWidget window) override; + scoped_refptr CreateOffscreenGLSurface(gl::GLDisplay *display, + const gfx::Size &size) override; + bool CanImportNativePixmap() override; + std::unique_ptr + ImportNativePixmap(scoped_refptr pixmap, gfx::BufferFormat plane_format, + gfx::BufferPlane plane, gfx::Size plane_size, + const gfx::ColorSpace &color_space, GLenum target, + GLuint texture_id) override; + +protected: + // Returns native platform display handle. This is used to obtain the EGL + // display connection for the native display. + gl::EGLDisplayPlatform GetNativeDisplay() override; + + // Sets up GL bindings for the native surface. + bool LoadGLES2Bindings(const gl::GLImplementationParts &implementation) override; +}; + +} // namespace ui + +#endif // defined(USE_OZONE) + +#endif // GL_OZONE_ANGLE_QT_H diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index 1bfa49c6006..726c2c0465f 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -6,7 +6,9 @@ #include "qtwebenginecoreglobal_p.h" #include "ozone/gl_context_qt.h" +#include "ozone/gl_ozone_angle_qt.h" #include "ozone/gl_ozone_egl_qt.h" +#include "qtwebenginecoreglobal_p.h" #include "media/gpu/buildflags.h" #include "ui/base/ozone_buildflags.h" @@ -34,30 +36,42 @@ SurfaceFactoryQt::SurfaceFactoryQt() { #if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) { - m_impl = { gl::GLImplementationParts(gl::kGLImplementationDesktopGL), - gl::GLImplementationParts(gl::kGLImplementationDisabled) }; - m_ozone.reset(new ui::GLOzoneGLXQt()); + m_impls.push_back({ gl::GLImplementationParts(gl::kGLImplementationDesktopGL), + std::make_unique() }); } else #endif if (GLContextHelper::getEglPlatformInterface()) { - m_impl = { gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), - gl::GLImplementationParts(gl::kGLImplementationDesktopGL), - gl::GLImplementationParts(gl::kGLImplementationDisabled) }; - m_ozone.reset(new ui::GLOzoneEGLQt()); - } else { - m_impl = { gl::GLImplementationParts(gl::kGLImplementationDisabled) }; + m_impls.push_back({ gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), + std::make_unique() }); + m_impls.push_back({ gl::GLImplementationParts(gl::kGLImplementationDesktopGL), + std::make_unique() }); } + + m_impls.push_back({ gl::GLImplementationParts(gl::kGLImplementationEGLANGLE), + std::make_unique() }); + m_impls.push_back({ gl::GLImplementationParts(gl::kGLImplementationDisabled), nullptr }); } std::vector SurfaceFactoryQt::GetAllowedGLImplementations() { - return m_impl; + std::vector allowed; + for (const auto &impl : m_impls) + allowed.push_back(impl.first); + + return allowed; } ui::GLOzone *SurfaceFactoryQt::GetGLOzone(const gl::GLImplementationParts &implementation) { - return m_ozone.get(); + for (const auto &impl : m_impls) { + if (impl.first.gl == implementation.gl) + return impl.second.get(); + } + + qFatal() << "GLOzone not found for" << gl::GetGLImplementationGLName(implementation); + return nullptr; } + #if BUILDFLAG(ENABLE_VULKAN) std::unique_ptr SurfaceFactoryQt::CreateVulkanImplementation(bool /*allow_protected_memory*/, diff --git a/src/core/ozone/surface_factory_qt.h b/src/core/ozone/surface_factory_qt.h index d69467a26ab..557bda09148 100644 --- a/src/core/ozone/surface_factory_qt.h +++ b/src/core/ozone/surface_factory_qt.h @@ -43,8 +43,7 @@ class SurfaceFactoryQt : public ui::SurfaceFactoryOzone static bool SupportsNativePixmaps(); private: - std::vector m_impl; - std::unique_ptr m_ozone; + std::vector>> m_impls; }; } // namespace QtWebEngineCore From 048c5bee84a38e50c5731077ca4350052a0ca79b Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 16 Apr 2024 12:58:20 +0200 Subject: [PATCH 069/341] Disable ANGLE without NativePixmap support Fallback to Vulkan rendering instead. This is a workaround for rendering with Nvidia when ANGLE is enabled in Chromium and Qt RHI is backed by OpenGL. Task-number: QTBUG-112281 Change-Id: I0ab8915875d7f8781aa267a30b584c7c4c751819 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 8ce04357b4ce39b8c4c2243991eae70f78f9b61b) Reviewed-by: Qt Cherry-pick Bot --- src/core/compositor/display_overrides.cpp | 8 +- .../native_skia_output_device_opengl.cpp | 104 ++++++++++++++++-- src/core/web_engine_context.cpp | 20 ++++ 3 files changed, 118 insertions(+), 14 deletions(-) diff --git a/src/core/compositor/display_overrides.cpp b/src/core/compositor/display_overrides.cpp index ebaa96dbb56..feb3dafa148 100644 --- a/src/core/compositor/display_overrides.cpp +++ b/src/core/compositor/display_overrides.cpp @@ -43,9 +43,11 @@ viz::SkiaOutputSurfaceImplOnGpu::CreateOutputDevice() if (graphicsApi == QSGRendererInterface::OpenGL) { if (gl::GetGLImplementation() != gl::kGLImplementationEGLANGLE) { #if !defined(Q_OS_MACOS) - return std::make_unique( - context_state_, renderer_settings_.requires_alpha_channel, - shared_gpu_deps_->memory_tracker(), GetDidSwapBuffersCompleteCallback()); + if (context_state_->gr_context_type() == gpu::GrContextType::kGL) { + return std::make_unique( + context_state_, renderer_settings_.requires_alpha_channel, + shared_gpu_deps_->memory_tracker(), GetDidSwapBuffersCompleteCallback()); + } #else qFatal("macOS only supports ANGLE."); #endif // !defined(Q_OS_MACOS) diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index c8430f0f7d6..07c68ffff65 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -30,10 +30,29 @@ #include "ui/gl/gl_bindings.h" #undef glBindTexture +#undef glCreateMemoryObjectsEXT +#undef glDeleteMemoryObjectsEXT #undef glDeleteTextures #undef glGenTextures +#undef glGetError +#undef glImportMemoryFdEXT +#undef glTextureStorageMem2DEXT #endif // BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(ENABLE_VULKAN) +#if BUILDFLAG(IS_OZONE_X11) +// We need to define USE_VULKAN_XCB for proper vulkan function pointers. +// Avoiding it may lead to call wrong vulkan functions. +// This is originally defined in chromium/gpu/vulkan/BUILD.gn. +#define USE_VULKAN_XCB +#endif // BUILDFLAG(IS_OZONE_X11) +#include "components/viz/common/gpu/vulkan_context_provider.h" +#include "gpu/vulkan/vulkan_device_queue.h" +#include "gpu/vulkan/vulkan_function_pointers.h" +#include "third_party/skia/include/gpu/vk/GrVkTypes.h" +#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h" +#endif // BUILDFLAG(ENABLE_VULKAN) + // Keep it at the end. #include "ozone/gl_context_qt.h" #endif // defined(USE_OZONE) @@ -125,8 +144,10 @@ NativeSkiaOutputDeviceOpenGL::NativeSkiaOutputDeviceOpenGL( { SkColorType skColorType = kRGBA_8888_SkColorType; #if BUILDFLAG(IS_OZONE_X11) - if (GLContextHelper::getGlxPlatformInterface()) + if (GLContextHelper::getGlxPlatformInterface() + && m_contextState->gr_context_type() == gpu::GrContextType::kGL) { skColorType = kBGRA_8888_SkColorType; + } #endif // BUILDFLAG(IS_OZONE_X11) capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; @@ -147,10 +168,9 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te return nullptr; #if defined(USE_OZONE) - Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kGL); - - GrGLTextureInfo glTextureInfo; scoped_refptr nativePixmap = m_frontBuffer->nativePixmap(); +#if BUILDFLAG(ENABLE_VULKAN) + GrVkImageInfo vkImageInfo; if (!nativePixmap) { if (m_isNativeBufferSupported) { qWarning("No native pixmap."); @@ -175,16 +195,23 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te return nullptr; } - if (backendTexture.backend() != GrBackendApi::kOpenGL) { - qWarning("Backend texture is not a OpenGL texture."); + if (backendTexture.backend() != GrBackendApi::kVulkan) { + qWarning("Backend texture is not a Vulkan texture."); return nullptr; } - if (!GrBackendTextures::GetGLTextureInfo(backendTexture, &glTextureInfo)) { - qWarning("Unable to access OpenGL texture."); + GrBackendTextures::GetVkImageInfo(backendTexture, &vkImageInfo); + if (vkImageInfo.fAlloc.fMemory == VK_NULL_HANDLE) { + qWarning("Unable to access Vulkan memory."); return nullptr; } } +#else + if (!nativePixmap) { + qWarning("No native pixmap."); + return nullptr; + } +#endif // BUILDFLAG(ENABLE_VULKAN) #elif defined(Q_OS_WIN) auto overlayImage = m_frontBuffer->overlayImage(); if (!overlayImage) { @@ -208,6 +235,8 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te GLuint glTexture = 0; if (nativePixmap) { + Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kGL); + #if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) { x11::Pixmap pixmapId = @@ -286,12 +315,65 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te }; } } else { - // TODO: Import texture into Qt's context. - qWarning("ANGLE is not yet supported without NativePixmap."); - glTexture = glTextureInfo.fID; +#if BUILDFLAG(ENABLE_VULKAN) + Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kVulkan); + + gpu::VulkanFunctionPointers *vfp = gpu::GetVulkanFunctionPointers(); + gpu::VulkanDeviceQueue *vulkanDeviceQueue = + m_contextState->vk_context_provider()->GetDeviceQueue(); + VkDevice vulkanDevice = vulkanDeviceQueue->GetVulkanDevice(); + + VkDeviceMemory importedImageMemory = vkImageInfo.fAlloc.fMemory; + VkDeviceSize importedImageSize = vkImageInfo.fAlloc.fSize; + + VkMemoryGetFdInfoKHR exportInfo = { VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR }; + exportInfo.pNext = nullptr; + exportInfo.memory = importedImageMemory; + exportInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + + int fd = -1; + if (vfp->vkGetMemoryFdKHR(vulkanDevice, &exportInfo, &fd) != VK_SUCCESS) + qFatal("VULKAN: Unable to extract file descriptor out of external VkImage."); + + static PFNGLCREATEMEMORYOBJECTSEXTPROC glCreateMemoryObjectsEXT = + (PFNGLCREATEMEMORYOBJECTSEXTPROC)glContext->getProcAddress( + "glCreateMemoryObjectsEXT"); + static PFNGLIMPORTMEMORYFDEXTPROC glImportMemoryFdEXT = + (PFNGLIMPORTMEMORYFDEXTPROC)glContext->getProcAddress("glImportMemoryFdEXT"); + static PFNGLTEXTURESTORAGEMEM2DEXTPROC glTextureStorageMem2DEXT = + (PFNGLTEXTURESTORAGEMEM2DEXTPROC)glContext->getProcAddress( + "glTextureStorageMem2DEXT"); + + GLuint glMemoryObject; + glFun->glGenTextures(1, &glTexture); + glFun->glBindTexture(GL_TEXTURE_2D, glTexture); + glCreateMemoryObjectsEXT(1, &glMemoryObject); + glImportMemoryFdEXT(glMemoryObject, importedImageSize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); + glTextureStorageMem2DEXT(glTexture, 1, GL_RGBA8_OES, size().width(), size().height(), + glMemoryObject, 0); + glFun->glBindTexture(GL_TEXTURE_2D, 0); + + m_frontBuffer->textureCleanupCallback = [glTexture, glMemoryObject]() { + QOpenGLContext *glContext = QOpenGLContext::currentContext(); + if (!glContext) + return; + auto glFun = glContext->functions(); + Q_ASSERT(glFun->glGetError() == GL_NO_ERROR); + + static PFNGLDELETEMEMORYOBJECTSEXTPROC glDeleteMemoryObjectsEXT = + (PFNGLDELETEMEMORYOBJECTSEXTPROC)glContext->getProcAddress( + "glDeleteMemoryObjectsEXT"); + + glDeleteMemoryObjectsEXT(1, &glMemoryObject); + glFun->glDeleteTextures(1, &glTexture); + }; +#else + Q_UNREACHABLE(); +#endif // BUILDFLAG(ENABLE_VULKAN) } texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts); + Q_ASSERT(glFun->glGetError() == GL_NO_ERROR); #elif defined(Q_OS_WIN) // TODO: Add WGL support over ANGLE. QT_NOT_YET_IMPLEMENTED diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index d1504a6851c..5c06a0879ed 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -962,6 +962,26 @@ WebEngineContext::WebEngineContext() } #if QT_CONFIG(webengine_vulkan) + if (QQuickWindow::graphicsApi() == QSGRendererInterface::OpenGL) { + // FIXME: We assume that ANGLE is explicitly enabled on Linux. + // Make sure to reimplement fallback if ANGLE becomes the default. + bool usingANGLE = false; + if (parsedCommandLine->HasSwitch(switches::kUseGL)) + usingANGLE = (parsedCommandLine->GetSwitchValueASCII(switches::kUseGL) + == gl::kGLImplementationANGLEName); + if (usingANGLE && GPUInfo::instance()->vendor() == GPUInfo::Nvidia) { + qWarning("Disable ANGLE because GBM is not supported with the current configuration. " + "Fallback to Vulkan rendering in Chromium."); + parsedCommandLine->RemoveSwitch(switches::kUseANGLE); + parsedCommandLine->RemoveSwitch(switches::kUseGL); + parsedCommandLine->AppendSwitchASCII(switches::kUseGL, + gl::kGLImplementationDesktopName); + parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan, + switches::kVulkanImplementationNameNative); + enableFeatures.push_back(features::kVulkan.name); + } + } + if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) { enableFeatures.push_back(features::kVulkan.name); parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan, From 28feb6efd7a803c76bb58e46e83527354ef0d3b5 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Thu, 11 Jul 2024 10:59:20 +0200 Subject: [PATCH 070/341] Add line breaks to public header files Adding deprecation warnings resulted in lines deemed too long. This change wraps those lines. Found in API review. Change-Id: I3e1f8647c046e2a6042cc8201424b803d4f95d23 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit e7f17dc5a7e43b481e1e78d9f1f76409bedc0d77) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginepage.h | 48 ++++++++++++------- .../api/qquickwebengineview_p.h | 6 ++- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h index 8b36826725c..ada0af9dab9 100644 --- a/src/core/api/qwebenginepage.h +++ b/src/core/api/qwebenginepage.h @@ -151,9 +151,12 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject #if QT_DEPRECATED_SINCE(6, 8) enum PermissionPolicy { - PermissionUnknown Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::State::Ask instead"), - PermissionGrantedByUser Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::State::Granted instead"), - PermissionDeniedByUser Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::State::Denied instead") + PermissionUnknown Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::State::Ask instead"), + PermissionGrantedByUser Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::State::Granted instead"), + PermissionDeniedByUser Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::State::Denied instead") }; Q_ENUM(PermissionPolicy) #endif @@ -172,16 +175,26 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject #if QT_DEPRECATED_SINCE(6, 8) enum Feature { - Notifications Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::Notifications instead") = 0, - Geolocation Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::Geolocation instead") = 1, - MediaAudioCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaAudioCapture instead") = 2, - MediaVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaVideoCapture instead"), - MediaAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MediaAudioVideoCapture instead"), - MouseLock Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::MouseLock instead"), - DesktopVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::DesktopVideoCapture instead"), - DesktopAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::DesktopAudioVideoCapture instead"), - ClipboardReadWrite Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::ClipboardReadWrite instead"), - LocalFontsAccess Q_DECL_ENUMERATOR_DEPRECATED_X("Use QWebEnginePermission::PermissionType::LocalFontsAccess instead"), + Notifications Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::Notifications instead") = 0, + Geolocation Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::Geolocation instead") = 1, + MediaAudioCapture Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::MediaAudioCapture instead") = 2, + MediaVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::MediaVideoCapture instead"), + MediaAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::MediaAudioVideoCapture instead"), + MouseLock Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::MouseLock instead"), + DesktopVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::DesktopVideoCapture instead"), + DesktopAudioVideoCapture Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::DesktopAudioVideoCapture instead"), + ClipboardReadWrite Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::ClipboardReadWrite instead"), + LocalFontsAccess Q_DECL_ENUMERATOR_DEPRECATED_X( + "Use QWebEnginePermission::PermissionType::LocalFontsAccess instead"), }; Q_ENUM(Feature) #endif @@ -243,7 +256,8 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject void findText(const QString &subString, FindFlags options = {}, const std::function &resultCallback = std::function()); #if QT_DEPRECATED_SINCE(6, 8) - QT_DEPRECATED_VERSION_X_6_8("Setting permissions through QWebEnginePage has been deprecated. Please use QWebEnginePermission instead.") + QT_DEPRECATED_VERSION_X_6_8( + "Setting permissions through QWebEnginePage has been deprecated. Please use QWebEnginePermission instead.") void setFeaturePermission(const QUrl &securityOrigin, Feature feature, PermissionPolicy policy); #endif @@ -329,9 +343,11 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject void windowCloseRequested(); #if QT_DEPRECATED_SINCE(6, 8) - QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated; please use permissionRequested instead.") + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8( + "The signal has been deprecated; please use permissionRequested instead.") void featurePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature); - QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated, and no longer functions.") + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8( + "The signal has been deprecated, and no longer functions.") void featurePermissionRequestCanceled(const QUrl &securityOrigin, QWebEnginePage::Feature feature); #endif // QT_DEPRECATED_SINCE(6, 8) diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h index 53f81f776ea..95635d19c9b 100644 --- a/src/webenginequick/api/qquickwebengineview_p.h +++ b/src/webenginequick/api/qquickwebengineview_p.h @@ -492,7 +492,8 @@ public Q_SLOTS: Q_REVISION(1,1) void findText(const QString &subString, FindFlags options = { }, const QJSValue &callback = QJSValue()); Q_REVISION(1,1) void fullScreenCancelled(); #if QT_DEPRECATED_SINCE(6, 8) - QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("Setting permissions through WebEngineView has been deprecated. Please use WebEnginePermission instead.") + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8( + "Setting permissions through WebEngineView has been deprecated. Please use WebEnginePermission instead.") Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature, bool granted); #endif // QT_DEPRECATED_SINCE(6, 8) Q_REVISION(1,2) void setActiveFocusOnPress(bool arg); @@ -521,7 +522,8 @@ private Q_SLOTS: Q_REVISION(1,1) void fullScreenRequested(const QWebEngineFullScreenRequest &request); Q_REVISION(1,1) void isFullScreenChanged(); #if QT_DEPRECATED_SINCE(6, 8) - QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated; please use permissionRequested instead.") + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8( + "The signal has been deprecated; please use permissionRequested instead.") Q_REVISION(1, 1) void featurePermissionRequested(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature); From 64732c2327d19213edfaaf0be90e28673ea6b00b Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Thu, 11 Jul 2024 13:45:56 +0200 Subject: [PATCH 071/341] QWebEnginePermission: Add move constructor and nullptr checks A move assignment existed for the class, but not a move constructor. Since both of those can leave a QWebEnginePermission object in a state where the d_ptr is null, this change also adds checks to ensure using a moved-from object won't crash the application. Found in API review. Change-Id: I977927c18094d06ea63840bb80c88b50c4b19b73 Reviewed-by: Michal Klocek Reviewed-by: Moss Heim (cherry picked from commit 2a84d23c69b0db9a8b050f8e6667972ce337c611) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginepermission.cpp | 14 ++++++++++++-- src/core/api/qwebenginepermission.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp index 9cef4bf9684..0cee6506b8a 100644 --- a/src/core/api/qwebenginepermission.cpp +++ b/src/core/api/qwebenginepermission.cpp @@ -93,6 +93,11 @@ QWebEnginePermission::QWebEnginePermission(const QWebEnginePermission &other) { } +QWebEnginePermission::QWebEnginePermission(QWebEnginePermission &&other) + : d_ptr(std::move(other.d_ptr)) +{ +} + QWebEnginePermission::~QWebEnginePermission() = default; QWebEnginePermission &QWebEnginePermission::operator=(const QWebEnginePermission &other) @@ -109,6 +114,9 @@ bool QWebEnginePermission::equals(const QWebEnginePermission &other) const if (this == &other) return true; + if (!d_ptr || !other.d_ptr) + return false; + if (d_ptr->permissionType != other.d_ptr->permissionType || d_ptr->origin != other.d_ptr->origin) return false; @@ -140,7 +148,7 @@ bool QWebEnginePermission::equals(const QWebEnginePermission &other) const */ QUrl QWebEnginePermission::origin() const { - return d_ptr->origin; + return d_ptr ? d_ptr->origin : QUrl(); } /*! @@ -171,7 +179,7 @@ QUrl QWebEnginePermission::origin() const */ QWebEnginePermission::PermissionType QWebEnginePermission::permissionType() const { - return d_ptr->permissionType; + return d_ptr ? d_ptr->permissionType : PermissionType::Unsupported; } /*! @@ -225,6 +233,8 @@ QWebEnginePermission::State QWebEnginePermission::state() const */ bool QWebEnginePermission::isValid() const { + if (!d_ptr) + return false; if (permissionType() == PermissionType::Unsupported) return false; if (!isPersistent(permissionType()) && !d_ptr->webContentsAdapter) diff --git a/src/core/api/qwebenginepermission.h b/src/core/api/qwebenginepermission.h index a6a767aeb9f..bb74e6a2052 100644 --- a/src/core/api/qwebenginepermission.h +++ b/src/core/api/qwebenginepermission.h @@ -37,6 +37,7 @@ class QWebEnginePermission Q_WEBENGINECORE_EXPORT QWebEnginePermission(); Q_WEBENGINECORE_EXPORT QWebEnginePermission(const QWebEnginePermission &other); + Q_WEBENGINECORE_EXPORT QWebEnginePermission(QWebEnginePermission &&other); Q_WEBENGINECORE_EXPORT ~QWebEnginePermission(); Q_WEBENGINECORE_EXPORT QWebEnginePermission &operator=(const QWebEnginePermission &other); From 2f1add47bbad80a404a7488f0646b17b31a56b20 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Wed, 20 Mar 2024 13:05:29 +0100 Subject: [PATCH 072/341] Fix typos in comments & docs POINTER instead of ACTION in enum value names Correct type and name for WebEngineScript::runsOnSubFrames Correct return type for WebEngineScriptCollection::contains \sa notes in docs: insert and remove should point to each other, as should find and contains. This is closer to documentation for QList, QMap, etc. Change-Id: I1ac31fb53bd3fa53463f37e1bb4b6ef3b8fba65b Reviewed-by: Michal Klocek (cherry picked from commit 2f5e631d2870208f054b613cac0cba761903f833) Reviewed-by: Allan Sandfeld Jensen --- src/core/render_widget_host_view_qt_delegate_client.cpp | 4 ++-- .../api/qquickwebenginescriptcollection.cpp | 8 ++++---- src/webenginequick/doc/src/webenginescript.qdoc | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp index 02ad9b039e0..ad4da26fcb7 100644 --- a/src/core/render_widget_host_view_qt_delegate_client.cpp +++ b/src/core/render_widget_host_view_qt_delegate_client.cpp @@ -76,8 +76,8 @@ class MotionEventQt : public ui::MotionEvent , flags(flagsFromModifiers(modifiers)) , index(index) { - // index is only valid for ACTION_DOWN and ACTION_UP and should correspond to the point causing it - // see blink_event_util.cc:ToWebTouchPointState for details + // index is only valid for POINTER_DOWN and POINTER_UP and should correspond to the point + // causing it see blink_event_util.cc:ToWebTouchPointState for details Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1) || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == QEventPoint::Pressed) || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == QEventPoint::Released), diff --git a/src/webenginequick/api/qquickwebenginescriptcollection.cpp b/src/webenginequick/api/qquickwebenginescriptcollection.cpp index a58d9783219..00ddb78e5db 100644 --- a/src/webenginequick/api/qquickwebenginescriptcollection.cpp +++ b/src/webenginequick/api/qquickwebenginescriptcollection.cpp @@ -117,7 +117,7 @@ QQuickWebEngineScriptCollection::QQuickWebEngineScriptCollection(QQuickWebEngine QQuickWebEngineScriptCollection::~QQuickWebEngineScriptCollection() { } /*! - \qmlmethod void WebEngineScriptCollection::contains(WebEngineScript script) + \qmlmethod bool WebEngineScriptCollection::contains(WebEngineScript script) \since QtWebEngine 6.2 Checks if the specified \a script is in the collection. \sa find() @@ -132,7 +132,7 @@ bool QQuickWebEngineScriptCollection::contains(const QWebEngineScript &value) co \qmlmethod list WebEngineScriptCollection::find(string name) \since QtWebEngine 6.2 Returns a list of all user script objects with the given \a name. - \sa find() + \sa contains() */ QList QQuickWebEngineScriptCollection::find(const QString &name) const { @@ -143,7 +143,7 @@ QList QQuickWebEngineScriptCollection::find(const QString &nam \qmlmethod void WebEngineScriptCollection::insert(WebEngineScript script) \since QtWebEngine 6.2 Inserts a single \a script into the collection. - \sa find() + \sa remove() */ void QQuickWebEngineScriptCollection::insert(const QWebEngineScript &s) { @@ -154,7 +154,7 @@ void QQuickWebEngineScriptCollection::insert(const QWebEngineScript &s) \qmlmethod void WebEngineScriptCollection::insert(list list) \since QtWebEngine 6.2 Inserts a \a list of WebEngineScript values into the user script collection. - \sa find() + \sa remove() */ void QQuickWebEngineScriptCollection::insert(const QList &list) { diff --git a/src/webenginequick/doc/src/webenginescript.qdoc b/src/webenginequick/doc/src/webenginescript.qdoc index 9708ffbf814..493873f891e 100644 --- a/src/webenginequick/doc/src/webenginescript.qdoc +++ b/src/webenginequick/doc/src/webenginescript.qdoc @@ -90,7 +90,7 @@ */ /*! - \qmlproperty int WebEngineScript::runOnSubframes + \qmlproperty bool WebEngineScript::runsOnSubFrames Set this property to \c true if the script is executed on every frame in the page, or \c false if it is only ran for the main frame. From a56bd1740e5ba837b46cd8328e63acd1179216ba Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 18 Jul 2024 16:24:43 +0000 Subject: [PATCH 073/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ia9deb535356b28a21479a48ba5720ec6e06b34bf Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 740679e5b86..6bfba13bee6 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 321c8a88eb575749cca8d5116b2a131c7932f74d + ref: 49909e8b8a4fcbeb7c8e57c052ce2b4574e621d5 required: true ../qtpositioning: - ref: ea75bd6c9a1df3f91c718e7a6a20f582405bd913 + ref: ae72e98b7ec0a16ab16b169eeda04ab245dfc65c required: false ../qttools: - ref: eedf2f68c5918074443b556183ab4068d7255d01 + ref: 3f5bef070a824e2afa6269ac2803f54790de2948 required: false ../qtwebchannel: - ref: 40451b711429d04347cdd010b904699303d311a4 + ref: 47d44416816aacaeae2c4d33d15fabe42b830160 required: false From 152894283800a27f6e6a6b3d0937f13ef4b396a3 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Mon, 13 May 2024 11:00:50 +0200 Subject: [PATCH 074/341] Use host paths when finding and running GN Suggested patch from F S Matches similar usage in qtbase/src/corelib/Qt6AndroidMacros.cmake, for example. Fixes: QTBUG-124172 Change-Id: Icac1e4511019e4d3ef9e80e6351490beab0f1ce7 Reviewed-by: Michal Klocek (cherry picked from commit 0249011d7f0f6d9606afd8387f3f387acb44a441) Reviewed-by: Qt Cherry-pick Bot --- cmake/FindGn.cmake | 4 ++-- cmake/Functions.cmake | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/FindGn.cmake b/cmake/FindGn.cmake index fd03b7346d0..f30edcd3649 100644 --- a/cmake/FindGn.cmake +++ b/cmake/FindGn.cmake @@ -6,11 +6,11 @@ if(NOT DEFINED WEBENGINE_ROOT_BUILD_DIR) endif() find_program(Gn_EXECUTABLE NAMES gn PATHS "${WEBENGINE_ROOT_BUILD_DIR}/install/bin" NO_DEFAULT_PATH) if(NOT QT_HOST_PATH STREQUAL "") - find_program(Gn_EXECUTABLE NAMES gn PATHS ${QT_HOST_PATH}/${INSTALL_LIBEXECDIR} NO_DEFAULT_PATH) + find_program(Gn_EXECUTABLE NAMES gn PATHS ${QT_HOST_PATH}/${QT6_HOST_INFO_LIBEXECDIR} NO_DEFAULT_PATH) # note: mingw installs with INSTALL_LIBEXECDIR = bin, # however android on windows has INSTALL_LIBEXECDIR = libexec, # so cover this case also - find_program(Gn_EXECUTABLE NAMES gn PATHS ${QT_HOST_PATH}/${INSTALL_BINDIR} NO_DEFAULT_PATH) + find_program(Gn_EXECUTABLE NAMES gn PATHS ${QT_HOST_PATH}/${QT6_HOST_INFO_BINDIR} NO_DEFAULT_PATH) endif() find_program(Gn_EXECUTABLE NAMES gn) diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 6cc8a401ea3..412d1eb3bbc 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -1266,8 +1266,8 @@ function(add_gn_command) -DSOURCE_DIR=${CMAKE_CURRENT_LIST_DIR} -DMODULE=${arg_MODULE} -DQT_HOST_PATH=${QT_HOST_PATH} - -DINSTALL_LIBEXECDIR=${INSTALL_LIBEXECDIR} - -DINSTALL_BINDIR=${INSTALL_BINDIR} + -DQT6_HOST_INFO_LIBEXECDIR=${QT6_HOST_INFO_LIBEXECDIR} + -DQT6_HOST_INFO_BINDIR=${QT6_HOST_INFO_BINDIR} -DPython3_EXECUTABLE=${Python3_EXECUTABLE} -DGN_THREADS=$ENV{QTWEBENGINE_GN_THREADS} -DQT_ALLOW_SYMLINK_IN_PATHS=${QT_ALLOW_SYMLINK_IN_PATHS} From d8cb9ae856e4fb03bc1f1dc0b7c65d4bc5187faa Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Fri, 21 Jun 2024 16:13:54 +0200 Subject: [PATCH 075/341] Partially stabilize QML favicon tests It seems that the pattern... 1. trigger action 2. start wait()-ing on a signal spy 3. continue after the signal is received ...is somewhat cursed in QML, since the signal may trigger inbetween steps 1 and 2, which will cause the wait() to never return true. This change removes that pattern from the favicon tests, which will hopefully reduce the tests' flakiness. Pick-to: 6.7 Change-Id: I65cd3b8c8ae5fc855138eec94821eb932d999c3b Reviewed-by: Peter Varga (cherry picked from commit 7cdcdb10915455c8ccb7f470158de0cc2fe66223) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/quick/qmltests/data/tst_favicon.qml | 18 ++++++------------ .../qmltests/data/tst_faviconDatabase.qml | 4 +--- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index fcc24dfb7de..d4b5c805366 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -68,8 +68,7 @@ TestWebEngineView { webEngineView.url = url verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() - compare(iconChangedSpy.count, 1) + tryCompare(iconChangedSpy, "count", 1) tryCompare(favicon, "status", Image.Ready) compare(favicon.width, 32) @@ -91,8 +90,7 @@ TestWebEngineView { webEngineView.url = url verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() - compare(iconChangedSpy.count, 1) + tryCompare(iconChangedSpy, "count", 1) tryCompare(favicon, "status", Image.Ready) compare(favicon.width, 32) @@ -298,8 +296,7 @@ TestWebEngineView { webEngineView.url = url verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() - compare(iconChangedSpy.count, 1) + tryCompare(iconChangedSpy, "count", 1) iconUrl = removeFaviconProviderPrefix(webEngineView.icon) // Touch icon is ignored @@ -352,10 +349,9 @@ TestWebEngineView { webEngineView.url = url verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() + tryCompare(iconChangedSpy, "count", 1) iconUrl = removeFaviconProviderPrefix(webEngineView.icon) compare(iconUrl, Qt.resolvedUrl("icons/qt144.png")) - compare(iconChangedSpy.count, 1) tryCompare(favicon, "status", Image.Ready) compare(favicon.width, 144) compare(favicon.height, 144) @@ -376,8 +372,7 @@ TestWebEngineView { webEngineView.url = url verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() - compare(iconChangedSpy.count, 1) + tryCompare(iconChangedSpy, "count", 1) tryCompare(favicon, "status", Image.Ready) compare(favicon.width, 32) compare(favicon.height, 32) @@ -517,8 +512,7 @@ TestWebEngineView { webEngineView.url = row.url verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() - compare(iconChangedSpy.count, 1) + tryCompare(iconChangedSpy, "count", 1) var iconUrl = removeFaviconProviderPrefix(webEngineView.icon) compare(iconUrl, row.expectedIconUrl) diff --git a/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml index c1679000107..22250852048 100644 --- a/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml +++ b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml @@ -101,8 +101,7 @@ TestWebEngineView { webEngineView.url = Qt.resolvedUrl("favicon.html"); // favicon.png -> 165 verify(webEngineView.waitForLoadSucceeded()); - iconChangedSpy.wait(); - compare(iconChangedSpy.count, 1); + tryCompare(iconChangedSpy, "count", 1); var previousIcon = webEngineView.icon; iconChangedSpy.clear(); @@ -213,4 +212,3 @@ TestWebEngineView { } } } - From f375deab83f3bbeb891492d7d10aca3a824f723e Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Thu, 18 Jul 2024 11:35:59 +0200 Subject: [PATCH 076/341] Fix narrowing conversions -Wc++11-narrowing under some GL versions and clang 18 Change-Id: I86433dd8da36aeb24a6cb79d630b7984906ae556 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit f916ff7d41ff4e065eaa6cfa943516046121d843) Reviewed-by: Qt Cherry-pick Bot --- src/core/compositor/native_skia_output_device_opengl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index 07c68ffff65..137bc3e2113 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -116,7 +116,7 @@ GLXFBConfig GetFBConfig(Display *display) GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, GLX_DOUBLEBUFFER, 0, - GLX_Y_INVERTED_EXT, GLX_DONT_CARE, + GLX_Y_INVERTED_EXT, static_cast(GLX_DONT_CARE), 0 }; // clang-format on @@ -288,10 +288,10 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te EGL_HEIGHT, size().height(), EGL_LINUX_DRM_FOURCC_EXT, drmFormat, EGL_DMA_BUF_PLANE0_FD_EXT, scopedFd.get(), - EGL_DMA_BUF_PLANE0_OFFSET_EXT, nativePixmap->GetDmaBufOffset(0), + EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast(nativePixmap->GetDmaBufOffset(0)), EGL_DMA_BUF_PLANE0_PITCH_EXT, nativePixmap->GetDmaBufPitch(0), - EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, modifier & 0xffffffff, - EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, modifier >> 32, + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, static_cast(modifier & 0xffffffff), + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, static_cast(modifier >> 32), EGL_NONE }; // clang-format on From f9d8018eb5fb9707ea5eeb006464d2a9f17446ee Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Mon, 22 Jul 2024 14:18:50 +0200 Subject: [PATCH 077/341] Add BUILD_ONLY_GN option Simply wrap gn build call so it can be used in form of: qt-configrue-module path/to/qtwebengine -- -DBUILD_ONLY_GN=TRUE Drop all config sanity checks. Fixes: QTBUG-113636 Change-Id: I2763bc1304032b36917288431770229c0e8890fb Reviewed-by: Alexey Edelev (cherry picked from commit 4bb470c40dd96e9d8e9e117460f0145a52c8f133) Reviewed-by: Qt Cherry-pick Bot --- CMakeLists.txt | 6 ++++++ cmake/Functions.cmake | 33 +++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 11 +---------- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d4638139cb..7388dd55bd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,12 @@ include(cmake/Functions.cmake) project(QtWebEngineDummy) find_package(Qt6 6.5 CONFIG REQUIRED COMPONENTS BuildInternals Core) +# Sepcial case of just doing gn build +if(DEFINED BUILD_ONLY_GN) + qt_webengine_build_and_install_gn() + return() +endif() + project(QtWebEngine VERSION ${Qt6Core_VERSION} DESCRIPTION "QtWebEngine and QtPdf modules" diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 412d1eb3bbc..03eafadb420 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -1405,3 +1405,36 @@ function(add_code_attributions_target) ) add_custom_target(${arg_TARGET} DEPENDS ${arg_OUTPUT}) endfunction() + +macro(qt_webengine_build_and_install_gn) + set(suppress_warning "${BUILD_ONLY_GN} ${QT_INTERNAL_CALLED_FROM_CONFIGURE}") + qt_internal_project_setup() + qt_webengine_externalproject_add(gn + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/src/gn + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/gn + INSTALL_DIR ${PROJECT_BINARY_DIR}/install + ) + qt_internal_set_cmake_build_type() + get_install_config(install_config) + qt_install( + PROGRAMS "${PROJECT_BINARY_DIR}/install/bin/gn${CMAKE_EXECUTABLE_SUFFIX}" + CONFIGURATIONS ${install_config} + RUNTIME DESTINATION "${INSTALL_LIBEXECDIR}" + ) + unset(suppress_warning) + unset(install_config) +endmacro() + +macro(qt_webengine_externalproject_add) + externalproject_add(${ARGN} + PREFIX gn + USES_TERMINAL_BUILD TRUE + CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_INSTALL_PREFIX:PATH= + -DCMAKE_PREFIX_PATH:PATH= + -DWEBENGINE_ROOT_BUILD_DIR=${PROJECT_BINARY_DIR} + -DQT_ALLOW_SYMLINK_IN_PATHS=${QT_ALLOW_SYMLINK_IN_PATHS} + ) +endmacro() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0084697f21f..eb36e70539d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -129,20 +129,11 @@ if(CMAKE_CROSSCOMPILING AND NOT Gn_FOUND) endif() if(NOT Gn_FOUND) - externalproject_add(gn + qt_webengine_externalproject_add(gn SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/gn BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/gn INSTALL_DIR ${installDir} - PREFIX gn - USES_TERMINAL_BUILD TRUE EXCLUDE_FROM_ALL TRUE - CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release - -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DCMAKE_INSTALL_PREFIX:PATH= - -DCMAKE_PREFIX_PATH:PATH= - -DWEBENGINE_ROOT_BUILD_DIR=${PROJECT_BINARY_DIR} - -DQT_ALLOW_SYMLINK_IN_PATHS=${QT_ALLOW_SYMLINK_IN_PATHS} ) if(QT_FEATURE_qtwebengine_core_build) add_dependencies(run_core_GnReady gn) From 37966380b3d231a359e34acd29957e5377d60bff Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Mon, 22 Jul 2024 16:23:23 +0200 Subject: [PATCH 078/341] Fix whitespace in webrtc manual test Change-Id: I6aeaff890cb8c3ef4e362ab81cde50470083d39e Reviewed-by: Anu Aliyas (cherry picked from commit 1e3232e398c68b4b24a3bd00856a4538dee8e67c) Reviewed-by: Qt Cherry-pick Bot --- tests/manual/widgets/webrtc/main.cpp | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/manual/widgets/webrtc/main.cpp b/tests/manual/widgets/webrtc/main.cpp index c1742445a4c..7eecf0735a0 100644 --- a/tests/manual/widgets/webrtc/main.cpp +++ b/tests/manual/widgets/webrtc/main.cpp @@ -52,27 +52,27 @@ void Page::handlePermissionRequest(QWebEnginePermission permission) void Page::handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request) { - Ui::MediaPickerDialog mediaPickerDialog; - QDialog dialog; - dialog.setModal(true); - mediaPickerDialog.setupUi(&dialog); - - auto *screensView = mediaPickerDialog.screensView; - auto *windowsView = mediaPickerDialog.windowsView; - auto *screensModel = request.screensModel(); - auto *windowsModel = request.windowsModel(); - - screensView->setModel(screensModel); - windowsView->setModel(windowsModel); - - if (dialog.exec() == QDialog::Accepted) { - if (mediaPickerDialog.tabWidget->currentIndex() == 0) - request.selectWindow(windowsView->selectionModel()->selectedIndexes().first()); - else - request.selectScreen(screensView->selectionModel()->selectedIndexes().first()); - } else { - request.cancel(); - } + Ui::MediaPickerDialog mediaPickerDialog; + QDialog dialog; + dialog.setModal(true); + mediaPickerDialog.setupUi(&dialog); + + auto *screensView = mediaPickerDialog.screensView; + auto *windowsView = mediaPickerDialog.windowsView; + auto *screensModel = request.screensModel(); + auto *windowsModel = request.windowsModel(); + + screensView->setModel(screensModel); + windowsView->setModel(windowsModel); + + if (dialog.exec() == QDialog::Accepted) { + if (mediaPickerDialog.tabWidget->currentIndex() == 0) + request.selectWindow(windowsView->selectionModel()->selectedIndexes().first()); + else + request.selectScreen(screensView->selectionModel()->selectedIndexes().first()); + } else { + request.cancel(); + } } int main(int argc, char *argv[]) From e23a577e15e72fc57b3972f8311ee43988429cf6 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Thu, 18 Jul 2024 11:31:37 +0200 Subject: [PATCH 079/341] Find text: Start new search when toggling case sensitivity Only toggling case sensitivity, without changing the text that's being looked up, would keep the helper in "find next" state, which in turn would keep otherwise invalid matches highlighted on screen. This change ensures that a new text search is initiated in cases like this. Fixes: QTBUG-127318 Pick-to: 6.7 Change-Id: I95b410b123dc09851f5aaefc8470f0656a88bb0d Reviewed-by: Anu Aliyas (cherry picked from commit 7f47a253ba7bce2d76f41079c34bc9468ec142aa) Reviewed-by: Qt Cherry-pick Bot --- src/core/find_text_helper.cpp | 4 +++- src/core/find_text_helper.h | 1 + .../auto/quick/qmltests/data/tst_findText.qml | 21 +++++++++++++++++++ .../qwebenginepage/tst_qwebenginepage.cpp | 17 +++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/core/find_text_helper.cpp b/src/core/find_text_helper.cpp index 5dc12fab7db..cc52e65c14a 100644 --- a/src/core/find_text_helper.cpp +++ b/src/core/find_text_helper.cpp @@ -19,6 +19,7 @@ FindTextHelper::FindTextHelper(content::WebContents *webContents, WebContentsAda , m_viewClient(viewClient) , m_currentFindRequestId(m_findRequestIdCounter++) , m_lastCompletedFindRequestId(m_currentFindRequestId) + , m_previousCaseSensitively(false) { } @@ -64,7 +65,7 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, { Q_ASSERT(!findText.isEmpty()); - const bool findNext = !m_previousFindText.isEmpty() && findText == m_previousFindText; + const bool findNext = !m_previousFindText.isEmpty() && findText == m_previousFindText && caseSensitively == m_previousCaseSensitively; if (isFindTextInProgress()) { // There are cases where the render process will overwrite a previous request // with the new search and we'll have a dangling callback, leaving the application @@ -83,6 +84,7 @@ void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, options->match_case = caseSensitively; options->new_session = !findNext; m_previousFindText = findText; + m_previousCaseSensitively = caseSensitively; m_currentFindRequestId = m_findRequestIdCounter++; m_webContents->Find(m_currentFindRequestId, toString16(findText), std::move(options), /*skip_delay=*/true); diff --git a/src/core/find_text_helper.h b/src/core/find_text_helper.h index 6d2e48b632a..fa3ea08d33d 100644 --- a/src/core/find_text_helper.h +++ b/src/core/find_text_helper.h @@ -61,6 +61,7 @@ class Q_WEBENGINECORE_EXPORT FindTextHelper { int m_lastCompletedFindRequestId; QString m_previousFindText; + bool m_previousCaseSensitively; QMap m_quickCallbacks; QMap> m_widgetCallbacks; diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml index bd2bfbb480b..8bf50d9138e 100644 --- a/tests/auto/quick/qmltests/data/tst_findText.qml +++ b/tests/auto/quick/qmltests/data/tst_findText.qml @@ -105,6 +105,27 @@ TestWebEngineView { compare(findTextSpy.signalArguments[0][0].activeMatch, 1) } + function test_toggleCaseSensitivity() { + var findFlags = 0 + webEngineView.url = Qt.resolvedUrl("test1.html") + verify(webEngineView.waitForLoadSucceeded()) + + webEngineView.clear() + webEngineView.findText("heLLo", findFlags, webEngineView.findTextCallback) + tryCompare(webEngineView, "matchCount", 1) + verify(!findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1) + compare(findTextSpy.signalArguments[0][0].activeMatch, 1) + + findTextSpy.clear() + webEngineView.clear() + findFlags = WebEngineView.FindCaseSensitively + webEngineView.findText("heLLo", findFlags, webEngineView.findTextCallback) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0) + } + function test_findTextManyMatches() { var findFlags = 0 webEngineView.url = Qt.resolvedUrl("test4.html") diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index dfb4fe5bf94..090c7dde0f1 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -1199,6 +1199,23 @@ void tst_QWebEnginePage::findText() QTRY_VERIFY(m_view->selectedText().isEmpty()); } + // Toggling case sensitivity without changing the text that's being looked up + // will clear previously found text + { + auto *callbackSpy = new CallbackSpy(); + QSignalSpy signalSpy(m_view->page(), &QWebEnginePage::findTextFinished); + m_view->findText("FOO", {}, callbackSpy->ref()); + QVERIFY(callbackSpy->waitForResult().numberOfMatches() > 0); + QTRY_COMPARE(signalSpy.size(), 1); + delete callbackSpy; + callbackSpy = new CallbackSpy(); + m_view->findText("FOO", QWebEnginePage::FindCaseSensitively, callbackSpy->ref()); + QVERIFY(callbackSpy->waitForResult().numberOfMatches() == 0); + QVERIFY(callbackSpy->wasCalled()); + QTRY_COMPARE(signalSpy.size(), 2); + delete callbackSpy; + } + // Select whole page contents again. m_view->page()->triggerAction(QWebEnginePage::SelectAll); QTRY_COMPARE(m_view->hasSelection(), true); From c1369837ac825567eabe9cf5ff818c4656942bb0 Mon Sep 17 00:00:00 2001 From: Martin Negyokru Date: Wed, 10 Jul 2024 16:21:58 +0200 Subject: [PATCH 080/341] Bump the minimum FFmpeg version to 6.1 Change-Id: Ie406728d6c52de5ea6d033072998c0ee627aeee6 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 6f18a71b15f1a9f3f1a9bdd5b230e63813bae2d4) --- configure.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure.cmake b/configure.cmake index dedd11cff8b..9fff6c3d507 100644 --- a/configure.cmake +++ b/configure.cmake @@ -52,7 +52,10 @@ if(PkgConfig_FOUND) pkg_check_modules(LCMS2 lcms2) pkg_check_modules(FREETYPE freetype2 IMPORTED_TARGET) pkg_check_modules(LIBXML2 libxml-2.0 libxslt IMPORTED_TARGET) - pkg_check_modules(FFMPEG libavcodec libavformat libavutil IMPORTED_TARGET) + pkg_check_modules(FFMPEG libavcodec>=60.31.102 + libavformat>=60.16.100 + libavutil>=58.29.100 + IMPORTED_TARGET) pkg_check_modules(OPUS opus>=1.3.1) pkg_check_modules(VPX vpx>=1.10.0 IMPORTED_TARGET) pkg_check_modules(LIBPCI libpci) From bed6a834b3a95538417bc61bdcdabf52da26c372 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 5 Jul 2024 14:19:57 +0200 Subject: [PATCH 081/341] Fix compiler warnings in tests and examples Change-Id: If371441d9b0d93fbd7a3e3e37e4f3780ddb52eb0 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit da4b139b97e47764a6d4aa1752e996d8bd41ae00) --- examples/pdfwidgets/pdfviewer/mainwindow.cpp | 7 ++-- .../tst_qwebengineglobalsettings.cpp | 2 -- .../pdfpageimage/tst_pdfpageimage.cpp | 6 ++-- .../tst_qquickwebengineview.cpp | 28 ++++++++-------- .../qwebenginepage/tst_qwebenginepage.cpp | 32 +++++++++++-------- tests/manual/widgets/webgl/main.cpp | 5 +-- 6 files changed, 43 insertions(+), 37 deletions(-) diff --git a/examples/pdfwidgets/pdfviewer/mainwindow.cpp b/examples/pdfwidgets/pdfviewer/mainwindow.cpp index ce19359fc58..25c2cbaab99 100644 --- a/examples/pdfwidgets/pdfviewer/mainwindow.cpp +++ b/examples/pdfwidgets/pdfviewer/mainwindow.cpp @@ -19,6 +19,8 @@ #include #include +using namespace Qt::StringLiterals; + const qreal zoomMultiplier = qSqrt(2.0); Q_LOGGING_CATEGORY(lcExample, "qt.examples.pdfviewer") @@ -115,8 +117,9 @@ void MainWindow::pageSelected(int page) const auto documentTitle = m_document->metaData(QPdfDocument::MetaDataField::Title).toString(); setWindowTitle(!documentTitle.isEmpty() ? documentTitle : QStringLiteral("PDF Viewer")); setWindowTitle(tr("%1: page %2 (%3 of %4)") - .arg(documentTitle.isEmpty() ? u"PDF Viewer"_qs : documentTitle, - m_pageSelector->currentPageLabel(), QString::number(page + 1), QString::number(m_document->pageCount()))); + .arg(documentTitle.isEmpty() ? u"PDF Viewer"_s : documentTitle, + m_pageSelector->currentPageLabel(), QString::number(page + 1), + QString::number(m_document->pageCount()))); } void MainWindow::searchResultSelected(const QModelIndex ¤t, const QModelIndex &previous) diff --git a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp index 3e46a823e2a..c7e9df51a7f 100644 --- a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp +++ b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp @@ -32,8 +32,6 @@ private Q_SLOTS: void dnsOverHttps(); }; -Q_LOGGING_CATEGORY(lc, "qt.webengine.tests") - void tst_QWebEngineGlobalSettings::dnsOverHttps_data() { QTest::addColumn("dnsMode"); diff --git a/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp b/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp index 3f98025fa71..c8ad4bdaa8b 100644 --- a/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp +++ b/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp @@ -11,10 +11,12 @@ using namespace Qt::StringLiterals; -Q_LOGGING_CATEGORY(lcTests, "qt.pdf.tests") - // #define DEBUG_WRITE_OUTPUT +#ifdef DEBUG_WRITE_OUTPUT +Q_LOGGING_CATEGORY(lcTests, "qt.pdf.tests") +#endif + class tst_PdfPageImage : public QQuickDataTest { Q_OBJECT diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index abe5e1f3da5..2a96061fbce 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -800,7 +800,7 @@ void tst_QQuickWebEngineView::setZoomFactor() view->setZoomFactor(2.5); QCOMPARE(view->zoomFactor(), 2.5); - const QUrl url1 = urlFromTestPath("html/basic_page.html"), url2 = urlFromTestPath("html/basic_page2.html"); + const QUrl url1 = urlFromTestPath("html/basic_page.html"); view->setUrl(url1); QVERIFY(waitForLoadSucceeded(view)); @@ -817,20 +817,22 @@ void tst_QQuickWebEngineView::setZoomFactor() view2->setParentItem(m_window->contentItem()); // try loading different url and check new values after load - for (auto &&p : { - qMakePair(view, 2.5), // navigating away to different url should keep zoom - qMakePair(view2.get(), 1.0), // same url navigation in diffent page shouldn't be affected - }) { - auto &&view = p.first; auto zoomFactor = p.second; - view->setUrl(url2); - QVERIFY(waitForLoadSucceeded(view)); - QCOMPARE(view->zoomFactor(), zoomFactor); - } + const QUrl url2 = urlFromTestPath("html/basic_page2.html"); + + // navigating away to different url should keep zoom + view->setUrl(url2); + QVERIFY(waitForLoadSucceeded(view)); + QCOMPARE(view->zoomFactor(), 2.5); + + // same url navigation in different view shouldn't be affected + view2->setUrl(url2); + QVERIFY(waitForLoadSucceeded(view2.get())); + QCOMPARE(view2->zoomFactor(), 1.0); - // should have no influence on first page + // should have no influence on first view view2->setZoomFactor(3.5); - for (auto &&p : { qMakePair(view, 2.5), qMakePair(view2.get(), 3.5), }) - QCOMPARE(p.first->zoomFactor(), p.second); + QCOMPARE(view->zoomFactor(), 2.5); + QCOMPARE(view2->zoomFactor(), 3.5); } void tst_QQuickWebEngineView::printToPdf() diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 090c7dde0f1..24a2e348be8 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -3252,13 +3252,13 @@ void tst_QWebEnginePage::toPlainTextLoadFinishedRace() void tst_QWebEnginePage::setZoomFactor() { - TestBasePage page, page2; + TestBasePage page; QCOMPARE(page.zoomFactor(), 1.0); page.setZoomFactor(2.5); QCOMPARE(page.zoomFactor(), 2.5); - const QUrl url1("qrc:/resources/test1.html"), url2(QUrl("qrc:/resources/test2.html")); + const QUrl url1("qrc:/resources/test1.html"); page.load(url1); QTRY_COMPARE(page.loadSpy.size(), 1); @@ -3272,22 +3272,26 @@ void tst_QWebEnginePage::setZoomFactor() QCOMPARE(page.zoomFactor(), 2.5); // try loading different url and check new values after load + const QUrl url2(QUrl("qrc:/resources/test2.html")); + + // navigating away to different url should keep zoom page.loadSpy.clear(); - for (auto &&p : { - qMakePair(&page, 2.5), // navigating away to different url should keep zoom - qMakePair(&page2, 1.0), // same url navigation in diffent page shouldn't be affected - }) { - auto &&page = *p.first; auto zoomFactor = p.second; - page.load(url2); - QTRY_COMPARE(page.loadSpy.size(), 1); - QVERIFY(page.loadSpy.last().first().toBool()); - QCOMPARE(page.zoomFactor(), zoomFactor); - } + page.load(url2); + QTRY_COMPARE(page.loadSpy.size(), 1); + QVERIFY(page.loadSpy.last().first().toBool()); + QCOMPARE(page.zoomFactor(), 2.5); + + // same url navigation in different page shouldn't be affected + TestBasePage page2; + page2.load(url2); + QTRY_COMPARE(page2.loadSpy.size(), 1); + QVERIFY(page2.loadSpy.last().first().toBool()); + QCOMPARE(page2.zoomFactor(), 1.0); // should have no influence on first page page2.setZoomFactor(3.5); - for (auto &&p : { qMakePair(&page, 2.5), qMakePair(&page2, 3.5), }) - QCOMPARE(p.first->zoomFactor(), p.second); + QCOMPARE(page.zoomFactor(), 2.5); + QCOMPARE(page2.zoomFactor(), 3.5); } void tst_QWebEnginePage::mouseButtonTranslation() diff --git a/tests/manual/widgets/webgl/main.cpp b/tests/manual/widgets/webgl/main.cpp index e9b4c285afc..cca1dbb160a 100644 --- a/tests/manual/widgets/webgl/main.cpp +++ b/tests/manual/widgets/webgl/main.cpp @@ -24,7 +24,7 @@ class MainWindow : public QMainWindow Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); - QSize sizeHint() const; + QSize sizeHint() const override; private: QWebEngineView *view = nullptr; @@ -103,9 +103,6 @@ int main(int argc, char *argv[]) const QString gles3 = QStringLiteral("gles3"); // ANGLE on Windows. const QString softwareGL = QStringLiteral("software"); - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - QString glType = qEnvironmentVariable("QTWEBENGINE_GL_TYPE"); if (glType.isEmpty()) { if (isWindows()) From f540fe3b3a871f54eb05b720b5b8b751305c28dc Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Tue, 23 Jul 2024 12:25:25 +0200 Subject: [PATCH 082/341] cmake: Quote list element with escaped quotes While technically correct cmake syntax, this breaks syntax highlighting in neovim and gerrit and also just looks a bit odd. Change-Id: Ia8a62ad9ad139bf3091b46949786579666dc9417 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit a7ad4591a92258ad46252808ddd458acdc1f3a80) Reviewed-by: Qt Cherry-pick Bot --- cmake/Functions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 03eafadb420..f87fd5de316 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -872,7 +872,7 @@ macro(append_build_type_setup) if(QT_FEATURE_webengine_jumbo_build) list(APPEND gnArgArg jumbo_file_merge_limit=${QT_FEATURE_webengine_jumbo_file_merge_limit}) if(QT_FEATURE_webengine_jumbo_file_merge_limit LESS_EQUAL 8) - list(APPEND gnArgArg jumbo_build_excluded=[\"browser\"]) + list(APPEND gnArgArg "jumbo_build_excluded=[\"browser\"]") endif() endif() From 2ec2daad25156072bbee401420771c0fdb063e81 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 25 Jul 2024 09:28:24 +0000 Subject: [PATCH 083/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Iae5fd9fef4a48b6589b95d3fbcbfd05407c3025c Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 6bfba13bee6..f55af2592f4 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 49909e8b8a4fcbeb7c8e57c052ce2b4574e621d5 + ref: 97a77aa53435bae6e8b3de6c0c1af0631f6e9e8a required: true ../qtpositioning: - ref: ae72e98b7ec0a16ab16b169eeda04ab245dfc65c + ref: 498f49315d2a82881141df179c3456e3cf7bf24e required: false ../qttools: - ref: 3f5bef070a824e2afa6269ac2803f54790de2948 + ref: d5c328f71aff66f88133715abeffeb66bee6127b required: false ../qtwebchannel: - ref: 47d44416816aacaeae2c4d33d15fabe42b830160 + ref: 4e9162619e853c40693a0cd16d0a500a92da278f required: false From 2692773d3fe801f2855fa49e88c62a101a1307ea Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Fri, 26 Jul 2024 13:23:28 +0200 Subject: [PATCH 084/341] Permission browser example: Use QLatin1StringView Removes ambiguous conversion of string types. Fixes: QTBUG-127544 Change-Id: I53d444b641c4b5190c1e391d9df21ccd7076ef13 Reviewed-by: Anu Aliyas (cherry picked from commit c8b34851faf4eb5116cf01ca810565d02b21e2a2) Reviewed-by: Qt Cherry-pick Bot --- examples/webenginewidgets/permissionbrowser/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webenginewidgets/permissionbrowser/main.cpp b/examples/webenginewidgets/permissionbrowser/main.cpp index c1e2c25660e..5efc8c6f96a 100644 --- a/examples/webenginewidgets/permissionbrowser/main.cpp +++ b/examples/webenginewidgets/permissionbrowser/main.cpp @@ -10,7 +10,7 @@ int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName("QtExamples"); QApplication app(argc, argv); - app.setWindowIcon(QIcon(QString(u":AppLogoColor.png"))); + app.setWindowIcon(QIcon(QString(QLatin1StringView(":AppLogoColor.png")))); MainWindow window(QUrl("qrc:/landing.html")); window.resize(1024, 768); window.show(); From bd8bcff50124dd61e765834de9ffe5d671bd65fd Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 17 Jul 2024 14:17:34 +0200 Subject: [PATCH 085/341] Do not warn needlessly about missing dictionaries directory Dictionaries are only required if spellchecking is enabled, therefore make sure we print out the warning in the right time. Do not enable spellchecker if dictionary directory is not present. This change amends d86ddb74877342d82c36cb9f47cccb53bf339e23 Fixes: QTBUG-124110 Pick-to: 6.7 Change-Id: I49fb191d40c81252e1a17835988621fa2e01ff79 Reviewed-by: Anu Aliyas (cherry picked from commit 47a076e58301ba51f0aa428145939a77fe657501) Reviewed-by: Qt Cherry-pick Bot --- src/core/pref_service_adapter.cpp | 8 ++++++-- src/core/web_engine_library_info.cpp | 26 +++++++++++++++++++------- src/core/web_engine_library_info.h | 2 +- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index 72eb850e7b9..2512c3c44f3 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -6,7 +6,9 @@ #include "profile_adapter.h" #include "type_conversion.h" #include "web_engine_context.h" +#include "web_engine_library_info.h" +#include "base/base_paths.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/prefs/chrome_command_line_pref_store.h" #include "content/public/browser/browser_thread.h" @@ -203,8 +205,10 @@ QStringList PrefServiceAdapter::spellCheckLanguages() const void PrefServiceAdapter::setSpellCheckEnabled(bool enabled) { - m_prefService->SetBoolean(spellcheck::prefs::kSpellCheckEnable, enabled); - m_prefService->SchedulePendingLossyWrites(); + if (!WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES, true).empty()) { + m_prefService->SetBoolean(spellcheck::prefs::kSpellCheckEnable, enabled); + m_prefService->SchedulePendingLossyWrites(); + } } bool PrefServiceAdapter::isSpellCheckEnabled() const diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index 8b69bec3c92..b6b8fc76340 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -241,9 +241,10 @@ QString localesPath() } #if QT_CONFIG(webengine_spellchecker) -QString dictionariesPath() +QString dictionariesPath(bool showWarnings) { static QString potentialDictionariesPath; + static QStringList warningMessage; static bool initialized = false; QStringList candidatePaths; if (!initialized) { @@ -284,14 +285,25 @@ QString dictionariesPath() break; } } - if (potentialDictionariesPath.isEmpty()) { - // return path for error message - potentialDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator() - % QLatin1String("qtwebengine_dictionaries"); + warningMessage.append(QStringLiteral( + "The following paths were searched for Qt WebEngine dictionaries:")); + for (const QString &candidate : std::as_const(candidatePaths)) + warningMessage.append(QStringLiteral(" ") % candidate); + warningMessage.append(QStringLiteral("but could not find it.")); + if (fromEnv.isEmpty()) { + warningMessage.append( + QStringLiteral("You may override the default search path by using " + "QTWEBENGINE_DICTIONARIES_PATH environment variable.")); + } + warningMessage.append(QStringLiteral("Spellchecking can not be enabled.")); } } + if (showWarnings && !warningMessage.isEmpty()) { + qWarning("%s", qPrintable(warningMessage.join('\n'))); + } + return potentialDictionariesPath; } #endif // QT_CONFIG(webengine_spellchecker) @@ -346,7 +358,7 @@ QString resourcesPath() } } // namespace -base::FilePath WebEngineLibraryInfo::getPath(int key) +base::FilePath WebEngineLibraryInfo::getPath(int key, bool showWarnings) { QString directory; switch (key) { @@ -382,7 +394,7 @@ base::FilePath WebEngineLibraryInfo::getPath(int key) return toFilePath(localesPath()); #if QT_CONFIG(webengine_spellchecker) case base::DIR_APP_DICTIONARIES: - return toFilePath(dictionariesPath()); + return toFilePath(dictionariesPath(showWarnings)); #endif case base::DIR_ASSETS: return toFilePath(resourcesPath()); diff --git a/src/core/web_engine_library_info.h b/src/core/web_engine_library_info.h index b7503f2df0a..a675172af48 100644 --- a/src/core/web_engine_library_info.h +++ b/src/core/web_engine_library_info.h @@ -18,7 +18,7 @@ enum { class WebEngineLibraryInfo { public: - static base::FilePath getPath(int key); + static base::FilePath getPath(int key, bool showWarnings = false); // Called by localized_error in our custom chrome layer static std::u16string getApplicationName(); static std::string getResolvedLocale(); From 76b5ab01a93c64f8644b2e0bf2c6f0ead939c05e Mon Sep 17 00:00:00 2001 From: Martin Negyokru Date: Wed, 28 Feb 2024 15:01:44 +0100 Subject: [PATCH 086/341] Workaround for setCursor issue with embedded views QQuickItem::setCursor maps the cursor position to the window while the Item's position is mapped to the View. If the View is moved inside its container, the offset is ignored on the Item. Ergo View.pos != Item.pos breaking hittesting of setCursor. Fix this by forwarding Item::setCursor calls to the View. It is safe since the Item shares its coordinate system with chromium and works as a proxy to the View. Fixes: QTBUG-111927 Fixes: QTBUG-123889 Fixes: QTBUG-115929 Pick-to: 6.7 6.6 Change-Id: Idee5ba043774952b554874ce654279cb5029ef1d Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 5043f4ddff206d2ffcb4684fb791ec689c2538f0) Reviewed-by: Qt Cherry-pick Bot --- ...nder_widget_host_view_qt_delegate_item.cpp | 2 + ...render_widget_host_view_qt_delegate_item.h | 1 + src/webenginewidgets/api/qwebengineview.cpp | 5 ++ tests/auto/widgets/qwebengineview/BLACKLIST | 3 + .../qwebengineview/tst_qwebengineview.cpp | 61 +++++++++++++++++++ 5 files changed, 72 insertions(+) diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp index a9f872220ad..aafa7556aa8 100644 --- a/src/core/render_widget_host_view_qt_delegate_item.cpp +++ b/src/core/render_widget_host_view_qt_delegate_item.cpp @@ -126,6 +126,8 @@ void RenderWidgetHostViewQtDelegateItem::readyToSwap() void RenderWidgetHostViewQtDelegateItem::updateCursor(const QCursor &cursor) { + if (m_widgetDelegate) + m_widgetDelegate->SetCursor(cursor); setCursor(cursor); } diff --git a/src/core/render_widget_host_view_qt_delegate_item.h b/src/core/render_widget_host_view_qt_delegate_item.h index 0da6b494834..65fbeeb175e 100644 --- a/src/core/render_widget_host_view_qt_delegate_item.h +++ b/src/core/render_widget_host_view_qt_delegate_item.h @@ -35,6 +35,7 @@ class WidgetDelegate virtual void Destroy() = 0; virtual void Resize(int, int) { } virtual QWindow *Window() { return nullptr; } + virtual void SetCursor(const QCursor &) { } virtual void unhandledWheelEvent(QWheelEvent *) { } }; diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 9dab3a45b22..0ef881b5ae7 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -199,6 +199,11 @@ class WebEngineQuickWidget : public QQuickWidget, public WidgetDelegate qApp->notify(parentWidget, ev); } } + void SetCursor(const QCursor &cursor) override + { + if (auto parentWidget = QQuickWidget::parentWidget()) + parentWidget->setCursor(cursor); + } protected: void closeEvent(QCloseEvent *event) override diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST index 26f2da4bbe8..f9ad091840f 100644 --- a/tests/auto/widgets/qwebengineview/BLACKLIST +++ b/tests/auto/widgets/qwebengineview/BLACKLIST @@ -10,3 +10,6 @@ windows [horizontalScrollbarTest] macos rhel # flaky + +[setCursorOnEmbeddedView] +macos # QTest::mousemove is not reliable diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 3b481402e7e..2eec0901a69 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -190,6 +190,7 @@ private Q_SLOTS: void longKeyEventText(); void pageWithPaintListeners(); void deferredDelete(); + void setCursorOnEmbeddedView(); }; // This will be called before the first test function is executed. @@ -4021,5 +4022,65 @@ void tst_QWebEngineView::deferredDelete() QCOMPARE(QApplication::allWidgets().size(), 0); } +// QTBUG-111927 +void tst_QWebEngineView::setCursorOnEmbeddedView() +{ + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: Can't manipulate the mouse cursor in auto test."); + + const QString html(QStringLiteral("" + "Pointer" + "" + "")); + QWidget parentWidget; + QWebEngineView view(&parentWidget); + PageWithPaintListeners page; + view.setPage(&page); + + // Move the view to it's parent rightBottom corner + parentWidget.resize(600, 600); + view.resize(150, 150); + view.move(450, 450); + + QSignalSpy firstPaintSpy(&page, &PageWithPaintListeners::largestContentfulPaint); + view.setHtml(html); + parentWidget.show(); + view.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&parentWidget)); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QTRY_VERIFY(firstPaintSpy.size()); + + const QPoint step = QPoint(25, 25); + QPoint cursorPos = view.pos() - step; + + // Single QTest::mouseMove may not move the cursor on macOS. + for (int i = 0; i < 5; i++) { + QTest::mouseMove(&parentWidget, cursorPos); + cursorPos += step; + } + + QQuickWidget *webEngineQuickWidget = qobject_cast(view.focusProxy()); + QVERIFY(webEngineQuickWidget); + QTRY_COMPARE(webEngineQuickWidget->hasFocus(), true); + + QQuickItem *root = webEngineQuickWidget->rootObject(); + // The root item should not has focus, otherwise it would handle mouse events + // instead of the RenderWidgetHostViewQtDelegateItem. + QVERIFY(!root->hasFocus()); + + QCOMPARE(root->childItems().size(), 1); + QQuickItem *renderWidgetHostViewQtDelegateItem = root->childItems().at(0); + QVERIFY(renderWidgetHostViewQtDelegateItem); + QTRY_COMPARE(renderWidgetHostViewQtDelegateItem->hasFocus(), true); + + QTRY_COMPARE(renderWidgetHostViewQtDelegateItem->cursor().shape(), Qt::PointingHandCursor); + QTRY_COMPARE(view.cursor().shape(), Qt::PointingHandCursor); +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" From 5258b46bab75d62e048f3d931c73434d7006053f Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 29 Jul 2024 13:39:44 +0000 Subject: [PATCH 087/341] Doc: Fix link to Qt Widgets Designer 'Qt Designer' has been renamed to 'Qt Widgets Designer'. Change-Id: Iebb09d61b0b600acee71a17e0cb80855e68ad0be Reviewed-by: Leena Miettinen (cherry picked from commit ac70cdbec9caa10baa88b598e1409baf8afb44c0) Reviewed-by: Qt Cherry-pick Bot --- examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc b/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc index b56958a9f28..6fb0fe65f19 100644 --- a/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc +++ b/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc @@ -15,11 +15,12 @@ \e {PDF Viewer} demonstrates how to use the QPdfView class to render PDF documents and the QPdfPageNavigator class to navigate them. - Qt Creator and the integrated Qt Designer were used to create the example - UI and to connect it to the code. This affects the code, which might be - somewhat different to what you would typically write by hand. - For more information about using Qt Designer, see \l{Qt Designer Manual} - and \l{Qt Creator: Creating a Qt Widget Based Application}. + Qt Creator and the integrated Qt Widgets Designer were used to create the + example UI and to connect it to the code. This affects the code, which + might be somewhat different to what you would typically write by hand. + For more information about using Qt Widgets Designer, see + \l{Qt Widgets Designer Manual} and + \l{Qt Creator: Creating a Qt Widget Based Application}. \include examples-run.qdocinc From 68c386f613304dafb5fd12122d90b80287ce19f7 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Wed, 17 Jul 2024 17:34:58 +0200 Subject: [PATCH 088/341] CMake: Mark WebEngineCore and Pdf SBOM as incomplete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The build system doesn't know about all the Chromium dependencies to automatically add them to the generated SBOM, so mark those modules as containing incomplete information regarding 3rd party dependencies. Task-number: QTBUG-122899 Change-Id: I9475e02a0633e0f6eaa86e1d7d2335e949c7dc97 Reviewed-by: Kai Köhne Reviewed-by: Alexey Edelev (cherry picked from commit 5ae7396128a16cc177c024779dddf1373d7e584a) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/CMakeLists.txt | 1 + src/pdf/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt index 2a06baec664..916c219d0a3 100644 --- a/src/core/api/CMakeLists.txt +++ b/src/core/api/CMakeLists.txt @@ -64,6 +64,7 @@ qt_internal_add_module(WebEngineCore EXTRA_CMAKE_FILES "${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}WebEngineCoreDeploySupport.cmake" NO_GENERATE_CPP_EXPORTS + SBOM_INCOMPLETE_3RD_PARTY_DEPENDENCIES ) set_target_properties(WebEngineCore PROPERTIES QTWEBENGINEPROCESS_NAME ${qtWebEngineProcessName}) diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt index 41018e7da3b..eeb84a8e1c7 100644 --- a/src/pdf/CMakeLists.txt +++ b/src/pdf/CMakeLists.txt @@ -38,6 +38,7 @@ qt_internal_add_module(Pdf PUBLIC_LIBRARIES Qt::Core Qt::Gui + SBOM_INCOMPLETE_3RD_PARTY_DEPENDENCIES ) add_subdirectory(plugins/imageformats/pdf) From 26e2dcfd6d4bdfcd1e8e2ff71db135cb1b588051 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Wed, 31 Jul 2024 14:56:23 +0000 Subject: [PATCH 089/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I287e2c816340602449a8cca59c648b397b1a7da9 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index f55af2592f4..57bcc2da1bf 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 97a77aa53435bae6e8b3de6c0c1af0631f6e9e8a + ref: 523cca30bb6e0aaa1e3f7ebd26328613b893c174 required: true ../qtpositioning: - ref: 498f49315d2a82881141df179c3456e3cf7bf24e + ref: 62b231fd7081a4211d5aff7908c0b83f1dcc79fd required: false ../qttools: - ref: d5c328f71aff66f88133715abeffeb66bee6127b + ref: 912881b3dac1b2ec0b9444f64836fc1a3d703805 required: false ../qtwebchannel: - ref: 4e9162619e853c40693a0cd16d0a500a92da278f + ref: 0e8015fcce752ed01c80ee6a546108caec0dd663 required: false From a88641175a6897c8e9cac2b00a1e202e17088f9c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 18 Jul 2024 16:44:36 +0200 Subject: [PATCH 090/341] Port to std::snprintf() and mark the module qsnprintf()-clean Task-number: QTBUG-127110 Change-Id: I3f6cd72e3781b8cf0cc6ba1032eccf4ce485f989 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Thiago Macieira (cherry picked from commit 95f7e7cb09296ddcba93377cd80804e8d00f5d04) Reviewed-by: Qt Cherry-pick Bot --- .cmake.conf | 1 + tests/auto/quick/qmltests/tst_qmltests.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.cmake.conf b/.cmake.conf index 8c2e0e6728c..7bf893be9ee 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -3,3 +3,4 @@ set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_WEBENGINE "3.19") set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1") list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_FOREACH=1") +list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_QSNPRINTF=1") diff --git a/tests/auto/quick/qmltests/tst_qmltests.cpp b/tests/auto/quick/qmltests/tst_qmltests.cpp index 01a657e8b44..79c9965a25d 100644 --- a/tests/auto/quick/qmltests/tst_qmltests.cpp +++ b/tests/auto/quick/qmltests/tst_qmltests.cpp @@ -19,6 +19,8 @@ #include #include +#include + #if defined(Q_OS_LINUX) && defined(QT_DEBUG) #include #include @@ -75,7 +77,7 @@ static void stackTrace() fprintf(stderr, "\n========= Received signal, dumping stack ==============\n"); char cmd[512]; - qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null </dev/null < Date: Thu, 27 Jun 2024 16:22:34 +0200 Subject: [PATCH 091/341] Call QtWebEngineQuick::initialize() earlier in tests We don't need to call it at all when the test is registered with W_QTEST_MAIN, and for QTEST_MAIN we should call it within the static initMain() function called prior to test object instantiation. Change-Id: I92874d0ac2feede3ed687db52ca1e6f0358ec527 Reviewed-by: Michal Klocek (cherry picked from commit e508021e2553029d47bec5ca4912cdb0068bd7be) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/quick/inspectorserver/tst_inspectorserver.cpp | 8 +++++++- .../tst_qquickwebenginedefaultsurfaceformat.cpp | 2 +- .../quick/qquickwebengineview/tst_qquickwebengineview.cpp | 1 - tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp | 8 ++++++-- tests/auto/quick/uidelegates/tst_uidelegates.cpp | 8 +++++++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp index 32683ad1df5..b025c4eaafd 100644 --- a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp +++ b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp @@ -17,6 +17,8 @@ static const QUrl s_inspectorServerHttpBaseUrl("http://localhost/" INSPECTOR_SER class tst_InspectorServer : public QObject { Q_OBJECT public: + static void initMain(); + tst_InspectorServer(); private Q_SLOTS: @@ -36,11 +38,15 @@ private Q_SLOTS: QScopedPointer m_component; }; +void tst_InspectorServer::initMain() +{ + QtWebEngineQuick::initialize(); +} + tst_InspectorServer::tst_InspectorServer() { qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--remote-allow-origins=*"); qputenv("QTWEBENGINE_REMOTE_DEBUGGING", INSPECTOR_SERVER_PORT); - QtWebEngineQuick::initialize(); QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); prepareWebViewComponent(); } diff --git a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp index 64c1cfaa4ec..5b5ef04f252 100644 --- a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp +++ b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp @@ -90,8 +90,8 @@ void tst_QQuickWebEngineDefaultSurfaceFormat::customDefaultSurfaceFormat() format.setProfile( QSurfaceFormat::CoreProfile ); QSurfaceFormat::setDefaultFormat( format ); - QGuiApplication app(argc, argv); QtWebEngineQuick::initialize(); + QGuiApplication app(argc, argv); initEngineAndViewComponent(); initWindow(); diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 2a96061fbce..7e90b58b8ec 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -98,7 +98,6 @@ private Q_SLOTS: tst_QQuickWebEngineView::tst_QQuickWebEngineView() { - QtWebEngineQuick::initialize(); QVERIFY(QQuickWebEngineProfile::defaultProfile()->isOffTheRecord()); diff --git a/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp b/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp index 1cf62e80086..7368309c959 100644 --- a/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp +++ b/tests/auto/quick/qtbug-70248/tst_qtbug-70248.cpp @@ -11,14 +11,18 @@ class tst_qtbug_70248: public QObject { Q_OBJECT public: - tst_qtbug_70248(){} + static void initMain(); private slots: void test(); }; -void tst_qtbug_70248::test() +void tst_qtbug_70248::initMain() { QtWebEngineQuick::initialize(); +} + +void tst_qtbug_70248::test() +{ QScopedPointer engine; QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); engine.reset(new QQmlApplicationEngine()); diff --git a/tests/auto/quick/uidelegates/tst_uidelegates.cpp b/tests/auto/quick/uidelegates/tst_uidelegates.cpp index 1c3024d949f..419f2f877fb 100644 --- a/tests/auto/quick/uidelegates/tst_uidelegates.cpp +++ b/tests/auto/quick/uidelegates/tst_uidelegates.cpp @@ -16,6 +16,8 @@ class tst_UIDelegates : public QObject { Q_OBJECT public: + static void initMain(); + tst_UIDelegates(); private Q_SLOTS: @@ -39,9 +41,13 @@ private Q_SLOTS: QScopedPointer m_component; }; -tst_UIDelegates::tst_UIDelegates() +void tst_UIDelegates::initMain() { QtWebEngineQuick::initialize(); +} + +tst_UIDelegates::tst_UIDelegates() +{ static QQmlEngine *engine = new QQmlEngine(this); m_component.reset(new QQmlComponent(engine, this)); m_component->setData(QByteArrayLiteral("import QtQuick\n" From 7fbbcbb33b641393068c05afcce94d6d55c5397d Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 5 Aug 2024 21:58:27 +0000 Subject: [PATCH 092/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ibdb2e72b9f433e3707b5d278467d4c88a9d18dda Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 57bcc2da1bf..cbd2d6aca8b 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 523cca30bb6e0aaa1e3f7ebd26328613b893c174 + ref: ec89e7c3986fdfbb91acbb1cbe5594a8a1b5da73 required: true ../qtpositioning: - ref: 62b231fd7081a4211d5aff7908c0b83f1dcc79fd + ref: 5d8f1f6d222dd467cd892953dfa4695776666c5b required: false ../qttools: - ref: 912881b3dac1b2ec0b9444f64836fc1a3d703805 + ref: 020b796b547328360023bc871453eaa01990e180 required: false ../qtwebchannel: - ref: 0e8015fcce752ed01c80ee6a546108caec0dd663 + ref: eb217a03daa2b8fd18325d92e45a9b454d5dea62 required: false From 3807839e2b0d31e1fd1858d5ea0a7e0073dd41f9 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 6 Aug 2024 11:56:46 +0200 Subject: [PATCH 093/341] Fix embedded build without x11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix compilation issue when doing ozone build without x11, deals with: "error: 'HANDLE_EINTR' was not declared in this scope" Add also missing proxy channel include. "note: forward declaration of ‘class IPC::ChannelProxy’" Task-number: QTBUG-126655 Change-Id: I3d06e7d4ce7afbfa86bb9535a2016bfc4e5586a5 Reviewed-by: Michael BrĂ¼ning (cherry picked from commit 3c79245d74710a3f7948afff209359f0f838d278) Reviewed-by: Qt Cherry-pick Bot --- src/core/compositor/native_skia_output_device_opengl.cpp | 2 +- src/core/content_browser_client_qt.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index 137bc3e2113..017d1714d75 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -16,12 +16,12 @@ #include "ui/gl/gl_implementation.h" #if defined(USE_OZONE) +#include "base/posix/eintr_wrapper.h" #include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" #include "ui/gfx/linux/drm_util_linux.h" #include "ui/gfx/linux/native_pixmap_dmabuf.h" #if BUILDFLAG(IS_OZONE_X11) -#include "base/posix/eintr_wrapper.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/dri3.h" #include "ui/gfx/x/future.h" diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 341c4629588..642c534e17b 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -32,6 +32,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" +#include "ipc/ipc_channel_proxy.h" #include "extensions/buildflags/buildflags.h" #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" #include "pdf/buildflags.h" From 5ee7901bc6d7fc44af19a464074413de1a836881 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Tue, 6 Aug 2024 23:54:45 +0000 Subject: [PATCH 094/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I091439bb1a5322cf7c159b02140b5d18d8104bb9 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index cbd2d6aca8b..c3dd5b9136a 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: ec89e7c3986fdfbb91acbb1cbe5594a8a1b5da73 + ref: 1746bff970ef338c4c6ad48651a82878769675bc required: true ../qtpositioning: - ref: 5d8f1f6d222dd467cd892953dfa4695776666c5b + ref: 0e5943c80db8620b7577452d88ee1720bc67a27c required: false ../qttools: - ref: 020b796b547328360023bc871453eaa01990e180 + ref: 959cd4c2f091440d49cd1d03ccb3b5268e4b0f19 required: false ../qtwebchannel: - ref: eb217a03daa2b8fd18325d92e45a9b454d5dea62 + ref: 78a37dad3e3c859eb5726037916d358ad55e4a8a required: false From 57ba058ac34b6b7582a3b329bf3f5f8ee253e4e7 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Thu, 1 Aug 2024 11:29:59 +0200 Subject: [PATCH 095/341] Avoid crash on WebEngineView destruction with ASAN enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chromium's raw_ptr implementation sets the pointer to null on destruction if ASAN is enabled. This will lead to crash when trying to access m_factory which is null from the NativeSkiaOutputDevice::Buffer destructor. Both buffer and m_factory are members of the class NativeSkiaOutputDevice. Member variables are deleted in bottom-to-top order based on their declaration. So, by the time the buffer destructor is invoked, m_factory is set to null. Used C++ raw pointer instead of chromium’s raw_ptr and added a nullptr check. Change-Id: Idfad2f5b1bb2adf8923a8fab872fdbaedf6c49f9 Pick-to: 6.7 Fixes: QTBUG-127611 Reviewed-by: Peter Varga (cherry picked from commit 9bcb567b6799bffe90b6d9f90da42fc331684947) Reviewed-by: Qt Cherry-pick Bot --- src/core/compositor/native_skia_output_device.cpp | 2 +- src/core/compositor/native_skia_output_device.h | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp index 4420e8d59aa..3c916d114ff 100644 --- a/src/core/compositor/native_skia_output_device.cpp +++ b/src/core/compositor/native_skia_output_device.cpp @@ -212,7 +212,7 @@ NativeSkiaOutputDevice::Buffer::~Buffer() if (m_scopedSkiaWriteAccess) endWriteSkia(false); - if (!m_mailbox.IsZero()) + if (!m_mailbox.IsZero() && m_parent->m_factory) m_parent->m_factory->DestroySharedImage(m_mailbox); } diff --git a/src/core/compositor/native_skia_output_device.h b/src/core/compositor/native_skia_output_device.h index 2c35cef77b4..d2101c0fbf2 100644 --- a/src/core/compositor/native_skia_output_device.h +++ b/src/core/compositor/native_skia_output_device.h @@ -164,18 +164,17 @@ class NativeSkiaOutputDevice : public viz::SkiaOutputDevice, public Compositor void SwapBuffersFinished(); + bool m_requiresAlpha; + gpu::SharedImageFactory *const m_factory; + gpu::SharedImageRepresentationFactory *const m_representationFactory; + viz::SkiaOutputSurfaceDependency *const m_deps; mutable QMutex m_mutex; Shape m_shape; std::unique_ptr m_middleBuffer; std::unique_ptr m_backBuffer; viz::OutputSurfaceFrame m_frame; bool m_readyToUpdate = false; - bool m_requiresAlpha; scoped_refptr m_gpuTaskRunner; - - const raw_ptr m_factory; - const raw_ptr m_representationFactory; - const raw_ptr m_deps; }; } // namespace QtWebEngineCore From 446385fd971016efae38079d7fe660afe287892f Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 8 Aug 2024 02:24:24 +0000 Subject: [PATCH 096/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I67d8163c1d58443486e5cd9cbe358928d4c1c34b Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index c3dd5b9136a..6e2865b074b 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 1746bff970ef338c4c6ad48651a82878769675bc + ref: c948d354e00b5f2b3866bc8e39d546dfa475adbc required: true ../qtpositioning: - ref: 0e5943c80db8620b7577452d88ee1720bc67a27c + ref: ab2757138c785bb976ffe8196d01a43eb4681507 required: false ../qttools: - ref: 959cd4c2f091440d49cd1d03ccb3b5268e4b0f19 + ref: 453dbf701588b4f91bd1dfced5f5fc256af36b0f required: false ../qtwebchannel: - ref: 78a37dad3e3c859eb5726037916d358ad55e4a8a + ref: 63b7cf3b8df497845738969e95b6c74b90371fb3 required: false From ef42464fb2ed4d37beced79edee2f9568e399b05 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 9 Aug 2024 16:56:11 +0000 Subject: [PATCH 097/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ie26502f6626dbf0999ada55502224e4c8d9a98f7 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 6e2865b074b..7282ef2ccc0 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: c948d354e00b5f2b3866bc8e39d546dfa475adbc + ref: 10d00aca5e9da3973bca4b8d083ea11d5b0f1775 required: true ../qtpositioning: - ref: ab2757138c785bb976ffe8196d01a43eb4681507 + ref: 9891aed7411ddb70a3f07d92fca43e59149dc1d4 required: false ../qttools: - ref: 453dbf701588b4f91bd1dfced5f5fc256af36b0f + ref: b7ca1c6048043a3e0de84729067db18f78b5f92f required: false ../qtwebchannel: - ref: 63b7cf3b8df497845738969e95b6c74b90371fb3 + ref: 56ad85728e9396cfd917e59011d6e1d72fc25392 required: false From 7f5ef6861312fc13a39f056edeb6b12f47f1e3ae Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Sat, 10 Aug 2024 09:34:54 +0000 Subject: [PATCH 098/341] Doc: Fix qhp subproject for examples Qt WebEngine examples have been divided into two subgroups, Quick and Widgets -based examples. Modify the qhp subprojects in qtwebengine.qdocconf to reflect this. Fixes the following QDoc warning: Failed to find qhp.QtWebEngine.subprojects.examples.indexTitle 'Qt WebEngine Examples' Change-Id: Ic991e0a53e3c46f1dced0427d20aca3376a1d310 Reviewed-by: Paul Wicking (cherry picked from commit 4214333f968446ecb7fe84114b7f6dc52a502a5c) --- src/core/doc/qtwebengine.qdocconf | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf index 89136314743..4a869b96e15 100644 --- a/src/core/doc/qtwebengine.qdocconf +++ b/src/core/doc/qtwebengine.qdocconf @@ -13,7 +13,7 @@ qhp.QtWebEngine.virtualFolder = qtwebengine qhp.QtWebEngine.indexTitle = Qt WebEngine qhp.QtWebEngine.indexRoot = -qhp.QtWebEngine.subprojects = classes qmltypes examples +qhp.QtWebEngine.subprojects = classes qmltypes examples widgetexamples qhp.QtWebEngine.subprojects.classes.title = C++ Classes and Namespaces qhp.QtWebEngine.subprojects.classes.indexTitle = Qt WebEngine C++ Classes and Namespaces @@ -25,11 +25,16 @@ qhp.QtWebEngine.subprojects.qmltypes.indexTitle = Qt WebEngine QML Types qhp.QtWebEngine.subprojects.qmltypes.selectors = qmltype qhp.QtWebEngine.subprojects.qmltypes.sortPages = true -qhp.QtWebEngine.subprojects.examples.title = Examples -qhp.QtWebEngine.subprojects.examples.indexTitle = Qt WebEngine Examples -qhp.QtWebEngine.subprojects.examples.selectors = doc:example +qhp.QtWebEngine.subprojects.examples.title = Examples (Quick) +qhp.QtWebEngine.subprojects.examples.indexTitle = Qt WebEngine Quick Examples +qhp.QtWebEngine.subprojects.examples.selectors = group:webengine-examples qhp.QtWebEngine.subprojects.examples.sortPages = true +qhp.QtWebEngine.subprojects.widgetexamples.title = Examples (Widgets) +qhp.QtWebEngine.subprojects.widgetexamples.indexTitle = Qt WebEngine Widgets Examples +qhp.QtWebEngine.subprojects.widgetexamples.selectors = group:webengine-widgetexamples +qhp.QtWebEngine.subprojects.widgetexamples.sortPages = true + manifestmeta.highlighted.names += "QtWebEngine/WebEngine Widgets Simple Browser Example" \ "QtWebEngine/WebEngine Quick Nano Browser" \ "QtWebEngine/Recipe Browser" From b6d619ef94566f74baa33d8514bf54819c63b839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Wed, 26 Jun 2024 13:07:47 +0200 Subject: [PATCH 099/341] Mention need for --webEngineArgs also in command line options section We are referring to the command line options section from other sections, so it makes sense to mention the need to use --webEngineArgs there. Pick-to: 6.7 6.5 Fixes: QTBUG-124878 Change-Id: I600bfcd8cf2d8aada53b883608e2a10ea932bdc2 Reviewed-by: Michal Klocek (cherry picked from commit 4f2c8c194b535b54b1cba0f0f0e47a9f9e707cf2) Reviewed-by: Qt Cherry-pick Bot --- src/core/doc/src/qtwebengine-debugging.qdoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/doc/src/qtwebengine-debugging.qdoc b/src/core/doc/src/qtwebengine-debugging.qdoc index 3dd4d9276c3..1d996ad7dc8 100644 --- a/src/core/doc/src/qtwebengine-debugging.qdoc +++ b/src/core/doc/src/qtwebengine-debugging.qdoc @@ -90,6 +90,14 @@ sandboxing of the network service though. \endlist + Any WebEngine command line options should be specified after the + \c {--webEngineArgs} option, which is used to separate the user's application + specific options from the WebEngine's ones. + + \badcode + --webEngineArgs [WebEngine specific options] + \endcode + Alternatively, the environment variable QTWEBENGINE_CHROMIUM_FLAGS can be set. For example, the following value could be set to disable logging while debugging an application called \e mybrowser: From 227da48ad32159d820185223e680b7b4adf88240 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 6 Aug 2024 14:23:50 +0200 Subject: [PATCH 100/341] Use proper COM coding in Direct3D implementations Inspired by https://learn.microsoft.com/en-us/windows/win32/learnwin32/com-coding-practices https://learn.microsoft.com/en-us/windows/win32/learnwin32/error-handling-in-com Change-Id: Ia5b8545af434ca105d87e7634eabc39f731968f6 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 6306c67780038ff6b6c0c43037261475b143248f) Reviewed-by: Qt Cherry-pick Bot --- .../native_skia_output_device_direct3d11.cpp | 57 +++++++++++-------- .../native_skia_output_device_vulkan.cpp | 28 ++++----- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/core/compositor/native_skia_output_device_direct3d11.cpp b/src/core/compositor/native_skia_output_device_direct3d11.cpp index 2f1ed5f61ee..2f9d1dffcc2 100644 --- a/src/core/compositor/native_skia_output_device_direct3d11.cpp +++ b/src/core/compositor/native_skia_output_device_direct3d11.cpp @@ -37,43 +37,50 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_ absl::optional overlayImage = m_frontBuffer->overlayImage(); if (!overlayImage) { - qWarning("No overlay image."); + qWarning("D3D: No overlay image."); return nullptr; } - QSGRendererInterface *ri = win->rendererInterface(); - - HRESULT status = S_OK; - HANDLE sharedHandle = nullptr; - IDXGIResource1 *resource = nullptr; - if (!overlayImage->nv12_texture()) { - qWarning("No D3D texture."); + Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture); + Microsoft::WRL::ComPtr chromeTexture = overlayImage->nv12_texture(); + if (!chromeTexture) { + qWarning("D3D: No D3D texture."); return nullptr; } - status = overlayImage->nv12_texture()->QueryInterface(__uuidof(IDXGIResource1), - (void **)&resource); - Q_ASSERT(status == S_OK); - status = resource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ, NULL, &sharedHandle); - Q_ASSERT(status == S_OK); - Q_ASSERT(sharedHandle); - resource->Release(); + + HRESULT hr; + + Microsoft::WRL::ComPtr dxgiResource; + hr = chromeTexture->QueryInterface(IID_PPV_ARGS(&dxgiResource)); + Q_ASSERT(SUCCEEDED(hr)); + + HANDLE sharedHandle = INVALID_HANDLE_VALUE; + hr = dxgiResource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, + &sharedHandle); + Q_ASSERT(SUCCEEDED(hr)); + Q_ASSERT(sharedHandle != INVALID_HANDLE_VALUE); // Pass texture between two D3D devices: - ID3D11Device1 *device = static_cast( + QSGRendererInterface *ri = win->rendererInterface(); + ID3D11Device *device = static_cast( ri->getResource(win, QSGRendererInterface::DeviceResource)); - - ID3D11Texture2D *qtTexture; - status = device->OpenSharedResource1(sharedHandle, __uuidof(ID3D11Texture2D), - (void **)&qtTexture); - if (status != S_OK) { - qWarning("Failed to share D3D11 texture (%s). This will result in failed rendering. Report " - "the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu", - qPrintable(QSystemError::windowsComString(status))); + Q_ASSERT(device); + + Microsoft::WRL::ComPtr device1; + hr = device->QueryInterface(IID_PPV_ARGS(&device1)); + Q_ASSERT(SUCCEEDED(hr)); + + ID3D11Texture2D *qtTexture = nullptr; + hr = device1->OpenSharedResource1(sharedHandle, IID_PPV_ARGS(&qtTexture)); + if (FAILED(hr)) { + qWarning("D3D: Failed to share D3D11 texture (%s). This will result in failed rendering. " + "Report the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu", + qPrintable(QSystemError::windowsComString(hr))); ::CloseHandle(sharedHandle); return nullptr; } - Q_ASSERT(qtTexture); + QQuickWindow::CreateTextureOptions texOpts(textureOptions); QSGTexture *texture = QNativeInterface::QSGD3D11Texture::fromNative(qtTexture, win, size(), texOpts); diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index b775276f665..60ceea00d8e 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -177,22 +177,24 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te externalMemoryImageCreateInfo.pNext = nullptr; externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; - HRESULT status = S_OK; - HANDLE sharedHandle = nullptr; - IDXGIResource1 *resource = nullptr; - if (!overlayImage->nv12_texture()) { + Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture); + Microsoft::WRL::ComPtr chromeTexture = overlayImage->nv12_texture(); + if (!chromeTexture) { qWarning("VULKAN: No D3D texture."); return nullptr; } - status = overlayImage->nv12_texture()->QueryInterface(__uuidof(IDXGIResource1), - (void **)&resource); - Q_ASSERT(status == S_OK); - status = resource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ, NULL, &sharedHandle); - Q_ASSERT(status == S_OK); - resource->Release(); - - if (!sharedHandle) - qFatal("VULKAN: Unable to extract shared handle."); + + HRESULT hr; + + Microsoft::WRL::ComPtr dxgiResource; + hr = chromeTexture->QueryInterface(IID_PPV_ARGS(&dxgiResource)); + Q_ASSERT(SUCCEEDED(hr)); + + HANDLE sharedHandle = INVALID_HANDLE_VALUE; + hr = dxgiResource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, + &sharedHandle); + Q_ASSERT(SUCCEEDED(hr)); + Q_ASSERT(sharedHandle != INVALID_HANDLE_VALUE); #endif constexpr VkImageUsageFlags kUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT From b7b49831cd9fd556eb83bae3671786637f9a4049 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 7 Aug 2024 10:59:12 +0200 Subject: [PATCH 101/341] Remove kGLImplementationEGLGLES2 cases for Windows Native EGL/GLES2 is no longer an allowed GL implementation on Windows since https://crrev.com/c/1686700 Change-Id: Ic4e74c7f929341ddc42c1db19ea3834caecbe4ca Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 21b0b3431d38b18e02c992c749143daddef5385a) Reviewed-by: Qt Cherry-pick Bot --- src/core/ozone/gl_context_qt.cpp | 1 - src/core/ozone/gl_surface_qt.cpp | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index 08729a78a12..b65f5c75694 100644 --- a/src/core/ozone/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -391,7 +391,6 @@ scoped_refptr CreateGLContext(GLShareGroup *share_group, return context; } case kGLImplementationEGLANGLE: - case kGLImplementationEGLGLES2: return InitializeGLContext(new GLContextEGL(share_group), compatible_surface, attribs); case kGLImplementationDisabled: diff --git a/src/core/ozone/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp index cebeb8b67f2..b6f3fa7f6d6 100644 --- a/src/core/ozone/gl_surface_qt.cpp +++ b/src/core/ozone/gl_surface_qt.cpp @@ -102,7 +102,6 @@ gl::GLDisplay *InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) GLDisplayEGL *display = GetDisplayEGL(gpu_preference); switch (GetGLImplementation()) { case kGLImplementationEGLANGLE: - case kGLImplementationEGLGLES2: if (!InitializeDisplay(display, EGLDisplayPlatform(GetDC(nullptr)))) { LOG(ERROR) << "GLDisplayEGL::Initialize failed."; return nullptr; @@ -139,8 +138,7 @@ scoped_refptr CreateOffscreenGLSurface(GLDisplay *display, const gfx: return surface; break; } - case kGLImplementationEGLANGLE: - case kGLImplementationEGLGLES2: { + case kGLImplementationEGLANGLE: { GLDisplayEGL *display_egl = display->GetAs(); if (display_egl->IsEGLSurfacelessContextSupported() && size.width() == 0 && size.height() == 0) return InitializeGLSurface(new SurfacelessEGL(display_egl, size)); From 6462c894a141155bbf9a62b11438a0ca081c2935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Fri, 9 Aug 2024 16:13:19 +0200 Subject: [PATCH 102/341] Update Chromium Submodule src/3rdparty 95fda5a0..23009a64: * [Backport] CVE-2024-7532: Out of bounds memory access in ANGLE (2/2) * [Backport] CVE-2024-7532: Out of bounds memory access in ANGLE (1/2) * [Backport] CVE-2024-7550: Type Confusion in V8 * [Backport] CVE-2024-7536: Use after free in WebAudio * [Backport] Dependency for CVE-2024-7536 * [Backport] CVE-2024-7535: Inappropriate implementation in V8 * [Backport] Security bugs 40063014 and 40068800 * [Backport] Security bug 340895241 (2/2) * [Backport] Security bug 340895241 (1/2) * [Backport] Security bug 333453962 * [Backport] Security bug 341640868 * [Backport] CVE-2024-7000: Use after free in CSS * [Backport] CVE-2024-6999: Inappropriate implementation in FedCM * [Backport] CVE-2024-6996: Race in Frames * [Backport] CVE-2024-6993: Inappropriate implementation in Canvas * [Backport] CVE-2024-6992: Out of bounds memory access in ANGLE * [Backport] CVE-2024-6991: Use after free in Dawn * [Backport] CVE-2024-6989: Use after free in Loader * [Backport] CVE-2024-6778: Race in DevTools * [Backport] CVE-2024-6779: Out of bounds memory access in V8 * [Backport] CVE-2024-6777: Use after free in Navigation * [Backport] CVE-2024-6774: Use after free in Screen Capture * [Backport] CVE-2024-6776: Use after free in Audio * [Backport] CVE-2024-6101: Inappropriate implementation in WebAssembly * [Backport] CVE-2024-6103: Use after free in Dawn * [Backport] CVE-2024-6100: Type Confusion in V8 * [Backport] CVE-2024-5836: Inappropriate Implementation in DevTools (3/3) * [Backport] CVE-2024-5836: Inappropriate Implementation in DevTools (2/3) * [Backport] CVE-2024-5836: Inappropriate Implementation in DevTools (1/3) * [Backport] Security bug 332724843 * Reduce memory pool max size to 1GiB on iOS for QtPDF * Fixup: Fix building with system ffmpeg * Disable the DisplayLock console messages by default * [Backport] CVE-2024-5833: Type Confusion in V8 * [Backport] CVE-2024-5834: Inappropriate implementation in Dawn. * [Backport] Remove usage of AVCodecContext::reordered_opaque * [Backport] Roll FFmpeg dep * [Backport] Replace deprecated use of AVCodecContext::reordered_opaque * [Backport] CVE-2024-4060: Use after free in Dawn * [Backport] CVE-2024-6293: Use after free in Dawn * [Backport] CVE-2024-6292: Use after free in Dawn * [Backport] CVE-2024-6291: Use after free in Swiftshader * [Backport] CVE-2024-6290: Use after free in Dawn * [Backport] Security bug 346197738 * [Backport] Security bug 336214779 * [Backport] CVE-2024-5840: Policy Bypass in CORS * [Backport] CVE-2024-5841: Use after free in V8 * [Backport] CVE-2024-5845: Use after free in Audio * [Backport] CVE-2024-5847: Use after free in PDFium * [Backport] CVE-2024-5846: Use after free in PDFium * [Backport] CVE-2024-5831: Use after free in Dawn (2/2) * [Backport] CVE-2024-5831: Use after free in Dawn (1/2) * [Backport] CVE-2024-5832: Use after free in Dawn * [Backport] Remove 3PCD console messages issued from RFH * [Backport]Add message to console when 3PCD issue gets created Fixes: QTBUG-127159 Fixes: QTBUG-127901 Fixes: QTBUG-127902 Fixes: QTBUG-127903 Fixes: QTBUG-127893 Fixes: QTBUG-127894 Change-Id: Ie5bfb60deac77d69dcc3205c67edd5c482cff6b8 Reviewed-by: Anu Aliyas (cherry picked from commit 3986c5041dddd0a4d7cee4b7cab14bcb89d51ba2) Reviewed-by: Allan Sandfeld Jensen --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 39028d6d975..ffb8180d5dd 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 124.0.6367.202 +Patched with security patches up to Chromium version: 127.0.6533.99 diff --git a/src/3rdparty b/src/3rdparty index 95fda5a0e06..23009a64b01 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 95fda5a0e06d39e23be741dbd52bd8d6597ff86e +Subproject commit 23009a64b01fa6ee40e04d60ee35bb835dcd1951 diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 5c06a0879ed..ccbd333d1f2 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1259,7 +1259,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "124.0.6367.202"; // FIXME: Remember to update + return "127.0.6533.99"; // FIXME: Remember to update } QT_END_NAMESPACE From 26bf8a6561e26345307fde23a74a63a289530ad5 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 12 Aug 2024 10:27:40 +0200 Subject: [PATCH 103/341] Do not use system re2 by default It is now more likely to be incompatible than compatible. Pick-to: 6.7 Fixes: QTBUG-124274 Change-Id: Id0d257afc8964dd7ec7bce2f059b91dfd6391197 Reviewed-by: Peter Varga Reviewed-by: Moss Heim (cherry picked from commit dcd7664ab873b6476de1bb6cfcb5043fba9aaf3c) Reviewed-by: Qt Cherry-pick Bot --- configure.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.cmake b/configure.cmake index 9fff6c3d507..81b1c95bbe5 100644 --- a/configure.cmake +++ b/configure.cmake @@ -313,6 +313,7 @@ qt_feature("webengine-developer-build" PRIVATE ) qt_feature("webengine-system-re2" PRIVATE LABEL "re2" + AUTODETECT FALSE CONDITION UNIX AND TEST_re2 ) qt_feature("webengine-system-icu" PRIVATE From b282e4b03709dbfc3b4abab722173fc51d8579e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Mon, 12 Aug 2024 11:39:25 +0200 Subject: [PATCH 104/341] Document Microsoft CRT version runtime requirement Pick-to: 6.7 6.5 Fixes: QTBUG-125300 Change-Id: Idd9e61b7d081c09e32f44b79c9e49ead982acbc7 Reviewed-by: Oliver Wolff (cherry picked from commit 112efa88b70a1503fe781035e07e96f5af913539) Reviewed-by: Qt Cherry-pick Bot --- src/core/doc/src/qtwebengine-deploying.qdoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/doc/src/qtwebengine-deploying.qdoc b/src/core/doc/src/qtwebengine-deploying.qdoc index 3d8a976c8f0..e79d7e1a3fb 100644 --- a/src/core/doc/src/qtwebengine-deploying.qdoc +++ b/src/core/doc/src/qtwebengine-deploying.qdoc @@ -29,6 +29,8 @@ \li On Windows, \QWE only supports Windows Vista or newer as target platform. Due to use of newer API in Chromium, Windows XP is not supported. WinRT is not supported, either. + \li On Windows, the Visual C++ Redistributable version 14.28 or higher + is needed to run \QWE applications. \endlist \section1 Deploying Applications Manually From 5b7570636c57a22822f4181fb878abeee1e3de2c Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 29 Jul 2024 13:20:17 +0000 Subject: [PATCH 105/341] Doc: Fix linking warnings for Qt WebEngine Fixes the following warnings: src/core/doc/src/qwebenginepage_lgpl.qdoc:464: (qdoc) warning: Can't link to 'QWebEnginePage::action(WebAction action)' src/core/api/qwebenginewebauthuxrequest.cpp:109: (qdoc) warning: Can't link to 'WebEngineWebAuthUxRequest.PinEntryReason.Challenge' src/core/api/qwebenginewebauthuxrequest.cpp:113: (qdoc) warning: Can't link to 'WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin' src/core/api/qwebenginewebauthuxrequest.cpp:141: (qdoc) warning: Can't link to 'WebEngineWebAuthUxRequest.PinEntryReason.Challenge' src/webenginequick/api/qquickwebengineprofile.cpp:498: (qdoc) warning: Can't link to 'storageName()' src/webenginequick/api/qquickwebenginescriptcollection.cpp:119: (qdoc) warning: Undocumented return value src/webenginequick/doc/src/webengineview_lgpl.qdoc:879: (qdoc) warning: Can't link to 'WebEngineSettings::JavascriptCanPaste' src/webenginequick/doc/src/webengineview_lgpl.qdoc:880: (qdoc) warning: Can't link to 'WebEngineSettings::JavascriptCanAccessClipboard' In addition, drop remaining references to 'Pepper Plugin API' as that documentation was removed in 9d5f94b7f4b954bbe7e261d184420e237c704557. Change-Id: I41fcddcc909b703705f2c32c2c3860872da60a72 Reviewed-by: Paul Wicking (cherry picked from commit 08d9c610cda3571cbec4cf5f0f993e20c3b0acd9) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginewebauthuxrequest.cpp | 4 ++-- src/core/doc/src/qwebenginepage_lgpl.qdoc | 2 +- src/core/doc/src/qwebenginesettings_lgpl.qdoc | 1 - src/webenginequick/api/qquickwebengineprofile.cpp | 2 +- src/webenginequick/api/qquickwebenginescriptcollection.cpp | 3 ++- src/webenginequick/api/qquickwebenginesettings.cpp | 2 -- src/webenginequick/doc/src/webengineview_lgpl.qdoc | 6 +++--- 7 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/core/api/qwebenginewebauthuxrequest.cpp b/src/core/api/qwebenginewebauthuxrequest.cpp index 1f09e55bba2..8ae856af559 100644 --- a/src/core/api/qwebenginewebauthuxrequest.cpp +++ b/src/core/api/qwebenginewebauthuxrequest.cpp @@ -106,7 +106,7 @@ \li The error details for the PIN prompt. \li The number of attempts remaining before a hard lock. Should be ignored unless \l{WebEngineWebAuthPinRequest::reason} is - \l{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. + \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. \li The minimum PIN length that the authenticator will accept for the PIN. \endlist Use this structure to update the WebAuth UX dialog when the WebAuth UX state is \l @@ -138,7 +138,7 @@ \qmlproperty int WebEngineWebAuthPinRequest::remainingAttempts \brief The number of attempts remaining before a hard lock. Should be ignored unless \l{WebEngineWebAuthPinRequest::reason} is - \l{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. + \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. */ /*! diff --git a/src/core/doc/src/qwebenginepage_lgpl.qdoc b/src/core/doc/src/qwebenginepage_lgpl.qdoc index 630ea507e26..e464a2472b3 100644 --- a/src/core/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/core/doc/src/qwebenginepage_lgpl.qdoc @@ -461,7 +461,7 @@ The action is owned by the QWebEnginePage but you can customize the look by changing its properties. - \l{QWebEnginePage::action(WebAction action)} does not have a default styled icon. + The returned action does not have a default styled icon. Use \l{QWebEngineView::pageAction()} to have an action with a default styled icon. QWebEnginePage also takes care of implementing the action, so that upon diff --git a/src/core/doc/src/qwebenginesettings_lgpl.qdoc b/src/core/doc/src/qwebenginesettings_lgpl.qdoc index dbe9c1d349f..7bd6d292436 100644 --- a/src/core/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/core/doc/src/qwebenginesettings_lgpl.qdoc @@ -105,7 +105,6 @@ Enables displaying the built-in error pages of Chromium. Enabled by default. \value PluginsEnabled Enables support for Pepper plugins, such as the Flash player. Disabled by default. - See also \l{Pepper Plugin API}. (Added in Qt 5.6) \value FullScreenSupportEnabled Enables fullscreen support in an application. Disabled by default. (Added in Qt 5.6) \value ScreenCaptureEnabled diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index 1979d18a0cd..d4adbb45864 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -487,7 +487,7 @@ void QQuickWebEngineProfile::setStorageName(const QString &name) Changing a profile from \e off-the-record to disk-based behavior also requires setting a proper storageName. - \sa storageName() + \sa storageName */ diff --git a/src/webenginequick/api/qquickwebenginescriptcollection.cpp b/src/webenginequick/api/qquickwebenginescriptcollection.cpp index 00ddb78e5db..f5328a134e4 100644 --- a/src/webenginequick/api/qquickwebenginescriptcollection.cpp +++ b/src/webenginequick/api/qquickwebenginescriptcollection.cpp @@ -119,7 +119,8 @@ QQuickWebEngineScriptCollection::~QQuickWebEngineScriptCollection() { } /*! \qmlmethod bool WebEngineScriptCollection::contains(WebEngineScript script) \since QtWebEngine 6.2 - Checks if the specified \a script is in the collection. + Returns \c true if the specified \a script is in the collection, \c false + otherwise. \sa find() */ diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp index 50fb5c3b0f8..04fd8b61767 100644 --- a/src/webenginequick/api/qquickwebenginesettings.cpp +++ b/src/webenginequick/api/qquickwebenginesettings.cpp @@ -184,8 +184,6 @@ bool QQuickWebEngineSettings::errorPageEnabled() const Enables support for Pepper plugins, such as the Flash player. Disabled by default. - - \sa {Pepper Plugin API} */ bool QQuickWebEngineSettings::pluginsEnabled() const { diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc index ac90bb0183c..45b8ec6393b 100644 --- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc +++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc @@ -875,9 +875,9 @@ \value WebEngineView.Notifications Web notifications for the end-user. \value WebEngineView.ClipboardReadWrite - Read and write access for the clipboard. If both \l{WebEngineSettings::JavascriptCanPaste} - {JavascriptCanPaste} and \l{WebEngineSettings::JavascriptCanAccessClipboard} - {JavascriptCanAccessClipboard} settings are enabled, this permission will always be granted + Read and write access for the clipboard. If both \l{WebEngineSettings::} + {javascriptCanPaste} and \l{WebEngineSettings::} + {javascriptCanAccessClipboard} settings are enabled, this permission will always be granted automatically and no feature requests will be made. (Added in Qt 6.8) \value WebEngineView.LocalFontsAccess From 291c9168e152c8b8214ac57b94911980cbd91426 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 29 Jul 2024 10:18:27 +0000 Subject: [PATCH 106/341] Doc: Document value types with \qmlvaluetype As these types are value types, document them as such. Separate object and value types on the QML module page, and fix the incorrect \instantiates argument for webEngineFrame. Change-Id: Ieb654efef0ede0eea7c10537d51cc040dc4e9935 Reviewed-by: Ulf Hermann Reviewed-by: Moss Heim (cherry picked from commit 3b830b75df1dbc3eb51fe5b5f910e38e65e47a32) Reviewed-by: Qt Cherry-pick Bot --- src/core/doc/qtwebengine.qdocconf | 2 +- src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc | 7 +++++++ src/webenginequick/doc/src/webengine_permission.qdoc | 3 ++- src/webenginequick/doc/src/webengineframe.qdoc | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf index 4a869b96e15..25f55f154cf 100644 --- a/src/core/doc/qtwebengine.qdocconf +++ b/src/core/doc/qtwebengine.qdocconf @@ -22,7 +22,7 @@ qhp.QtWebEngine.subprojects.classes.sortPages = true qhp.QtWebEngine.subprojects.qmltypes.title = QML Types qhp.QtWebEngine.subprojects.qmltypes.indexTitle = Qt WebEngine QML Types -qhp.QtWebEngine.subprojects.qmltypes.selectors = qmltype +qhp.QtWebEngine.subprojects.qmltypes.selectors = qmltype qmlvaluetype qhp.QtWebEngine.subprojects.qmltypes.sortPages = true qhp.QtWebEngine.subprojects.examples.title = Examples (Quick) diff --git a/src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc b/src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc index ecf3a4a6edc..5966fef4741 100644 --- a/src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc +++ b/src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc @@ -7,6 +7,7 @@ \brief Provides QML types for rendering web content within a QML application. \ingroup qtwebengine-modules \ingroup qmlmodules + \noautolist To link against the module using build with qmake, add the following QT variable to your qmake .pro file: @@ -26,4 +27,10 @@ Where the content of main.qml is simply: \snippet minimal/main.qml Minimal Example + + \section1 QML object types + \generatelist qmltypesbymodule QtWebEngine + + \section1 QML value types + \generatelist qmlvaluetypesbymodule QtWebEngine */ diff --git a/src/webenginequick/doc/src/webengine_permission.qdoc b/src/webenginequick/doc/src/webengine_permission.qdoc index e36264240dd..6912ef4fa2c 100644 --- a/src/webenginequick/doc/src/webengine_permission.qdoc +++ b/src/webenginequick/doc/src/webengine_permission.qdoc @@ -2,9 +2,10 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - \qmltype webEnginePermission + \qmlvaluetype webEnginePermission \instantiates QWebEnginePermission \inqmlmodule QtWebEngine + \since 6.8 \brief An object used to access and modify the state of a single permission that's been granted or denied to a specific origin URL. diff --git a/src/webenginequick/doc/src/webengineframe.qdoc b/src/webenginequick/doc/src/webengineframe.qdoc index 8f852501ef8..3bcbd30b850 100644 --- a/src/webenginequick/doc/src/webengineframe.qdoc +++ b/src/webenginequick/doc/src/webengineframe.qdoc @@ -2,8 +2,8 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - \qmltype webEngineFrame - \instantiates QQuickWebEngineFrame + \qmlvaluetype webEngineFrame + \instantiates QWebEngineFrame \brief webEngineFrame provides information about and control over a page frame. \since 6.8 \ingroup qmlvaluetypes From 635144c58b127cd60434c9a235882413005ab89b Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 12 Aug 2024 10:16:52 +0200 Subject: [PATCH 107/341] Fix -no-opengl build Change-Id: I12e88207e1c0c0ece99cf7afd00c555af96bd31f Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 11ae74a9d56a06dee0caf7ffeb881e59d059c846) Reviewed-by: Qt Cherry-pick Bot --- src/core/ozone/gl_surface_egl_qt.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/ozone/gl_surface_egl_qt.cpp b/src/core/ozone/gl_surface_egl_qt.cpp index cc588453d16..0ac02681dd3 100644 --- a/src/core/ozone/gl_surface_egl_qt.cpp +++ b/src/core/ozone/gl_surface_egl_qt.cpp @@ -53,6 +53,7 @@ gl::GLDisplay *GLSurfaceEGLQt::InitializeOneOff(gl::GpuPreference preference) GLContextHelper::isCreateContextRobustnessSupported(); } +#if QT_CONFIG(opengl) if (egl_display->ext->b_EGL_EXT_image_dma_buf_import || egl_display->ext->b_EGL_EXT_image_dma_buf_import_modifiers || egl_display->ext->b_EGL_MESA_image_dma_buf_export) { @@ -61,6 +62,7 @@ gl::GLDisplay *GLSurfaceEGLQt::InitializeOneOff(gl::GpuPreference preference) egl_display->ext->b_EGL_EXT_image_dma_buf_import_modifiers = dmaBufSupported; egl_display->ext->b_EGL_MESA_image_dma_buf_export = dmaBufSupported; } +#endif g_config = GLContextHelper::getEGLConfig(); if (!g_config) { From 7e8eebaa65386d042c5034e077f31e95540542fa Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 12 Aug 2024 10:59:21 +0200 Subject: [PATCH 108/341] Do not set Vulkan rendering if RHI is disabled If Qt is built without OpenGL support, the default graphics API is Vulkan on Linux. In this case we initialize Chromium with Vulkan rendering. This doesn't make too much sense if the user requests software rendering what also disables RHI. Try to avoid this configuration even if it doesn't cause any known issue. Change-Id: Ia70366a4edfd7204940fd17dea8763a9aa8e4747 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit cb829408b5f178444d99400b44c37ea7624285cf) Reviewed-by: Qt Cherry-pick Bot --- src/core/web_engine_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index ccbd333d1f2..a9e0e292a01 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -982,7 +982,7 @@ WebEngineContext::WebEngineContext() } } - if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) { + if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan && usingSupportedSGBackend()) { enableFeatures.push_back(features::kVulkan.name); parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan, switches::kVulkanImplementationNameNative); From 37cff5478eed9d4cd7d3063204c0132e2c8d4cbf Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 8 Aug 2024 14:35:59 +0200 Subject: [PATCH 109/341] Exclude ozone sources from non-Linux builds Keep some of them for WGL on Windows. Change-Id: Ib10c0fac2fca4f548efc12e573b79838749f62fa Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit fdc2ab963483dbda411c03e621d59d6fe7def308) Reviewed-by: Qt Cherry-pick Bot --- src/core/CMakeLists.txt | 32 ++++++--- src/core/chromium_overrides.cpp | 3 + src/core/content_main_delegate_qt.cpp | 2 + src/core/content_main_delegate_qt.h | 9 ++- src/core/ozone/gl_share_context_qt.cpp | 3 - src/core/ozone/gl_surface_qt.cpp | 91 -------------------------- src/core/ozone/gl_surface_wgl_qt.cpp | 82 ++++++++++++++++++++++- src/core/ozone/gl_surface_wgl_qt.h | 6 +- src/core/web_engine_context.cpp | 14 +++- 9 files changed, 127 insertions(+), 115 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 24ccdacbbf4..487ac15fb49 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -98,7 +98,6 @@ foreach(arch ${archs}) color_chooser_qt.cpp color_chooser_qt.h common/qt_messages.cpp common/qt_messages.h compositor/compositor.cpp compositor/compositor.h - compositor/content_gpu_client_qt.cpp compositor/content_gpu_client_qt.h compositor/display_overrides.cpp compositor/display_software_output_surface.cpp compositor/display_software_output_surface.h compositor/native_skia_output_device.cpp compositor/native_skia_output_device.h @@ -148,15 +147,6 @@ foreach(arch ${archs}) net/url_request_custom_job_proxy.cpp net/url_request_custom_job_proxy.h net/version_ui_qt.cpp net/version_ui_qt.h net/webui_controller_factory_qt.cpp net/webui_controller_factory_qt.h - ozone/gl_context_qt.cpp ozone/gl_context_qt.h - ozone/gl_ozone_angle_qt.cpp ozone/gl_ozone_angle_qt.h - ozone/gl_ozone_egl_qt.cpp ozone/gl_ozone_egl_qt.h - ozone/gl_share_context_qt.cpp ozone/gl_share_context_qt.h - ozone/gl_surface_egl_qt.cpp ozone/gl_surface_egl_qt.h - ozone/gl_surface_qt.cpp ozone/gl_surface_qt.h - ozone/gl_surface_wgl_qt.cpp ozone/gl_surface_wgl_qt.h - ozone/platform_window_qt.cpp ozone/platform_window_qt.h - ozone/surface_factory_qt.cpp ozone/surface_factory_qt.h permission_manager_qt.cpp permission_manager_qt.h pdf_util_qt.cpp pdf_util_qt.h platform_notification_service_qt.cpp platform_notification_service_qt.h @@ -210,6 +200,28 @@ foreach(arch ${archs}) accessibility_activation_observer.cpp accessibility_activation_observer.h ) + extend_gn_target(${buildGn} CONDITION LINUX OR WIN32 + SOURCES + compositor/content_gpu_client_qt.cpp compositor/content_gpu_client_qt.h + ozone/gl_context_qt.cpp ozone/gl_context_qt.h + ozone/gl_share_context_qt.cpp ozone/gl_share_context_qt.h + ozone/gl_surface_qt.cpp ozone/gl_surface_qt.h + ) + + extend_gn_target(${buildGn} CONDITION WIN32 + SOURCES + ozone/gl_surface_wgl_qt.cpp ozone/gl_surface_wgl_qt.h + ) + + extend_gn_target(${buildGn} CONDITION LINUX + SOURCES + ozone/gl_ozone_angle_qt.cpp ozone/gl_ozone_angle_qt.h + ozone/gl_ozone_egl_qt.cpp ozone/gl_ozone_egl_qt.h + ozone/gl_surface_egl_qt.cpp ozone/gl_surface_egl_qt.h + ozone/platform_window_qt.cpp ozone/platform_window_qt.h + ozone/surface_factory_qt.cpp ozone/surface_factory_qt.h + ) + extend_gn_target(${buildGn} CONDITION QT_FEATURE_webengine_ozone_x11 SOURCES ozone/gl_ozone_glx_qt.cpp ozone/gl_ozone_glx_qt.h diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 28917e6c5c2..dd273d3b79b 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -17,6 +17,7 @@ #include "gpu/vulkan/buildflags.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" +#include "ui/base/ozone_buildflags.h" #include #include @@ -37,10 +38,12 @@ #endif // defined(USE_OZONE) #endif // defined(ENABLE_VULKAN) +#if BUILDFLAG(IS_OZONE_X11) void *GetQtXDisplay() { return GLContextHelper::getXDisplay(); } +#endif namespace content { class RenderViewHostDelegateView; diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index f949d93a5ad..148be4f1c9d 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -201,11 +201,13 @@ content::ContentBrowserClient *ContentMainDelegateQt::CreateContentBrowserClient return m_browserClient.get(); } +#if defined(USE_OZONE) || BUILDFLAG(IS_WIN) content::ContentGpuClient *ContentMainDelegateQt::CreateContentGpuClient() { m_gpuClient.reset(new ContentGpuClientQt); return m_gpuClient.get(); } +#endif content::ContentRendererClient *ContentMainDelegateQt::CreateContentRendererClient() { diff --git a/src/core/content_main_delegate_qt.h b/src/core/content_main_delegate_qt.h index a177bd6df84..534d9e4dd63 100644 --- a/src/core/content_main_delegate_qt.h +++ b/src/core/content_main_delegate_qt.h @@ -6,11 +6,14 @@ #include "content/public/app/content_main_delegate.h" -#include "compositor/content_gpu_client_qt.h" #include "content_browser_client_qt.h" #include "content_client_qt.h" #include "content_utility_client_qt.h" +#if defined(USE_OZONE) || BUILDFLAG(IS_WIN) +#include "compositor/content_gpu_client_qt.h" +#endif + namespace QtWebEngineCore { class ContentMainDelegateQt : public content::ContentMainDelegate @@ -23,7 +26,9 @@ class ContentMainDelegateQt : public content::ContentMainDelegate content::ContentClient *CreateContentClient() override; content::ContentBrowserClient* CreateContentBrowserClient() override; +#if defined(USE_OZONE) || BUILDFLAG(IS_WIN) content::ContentGpuClient* CreateContentGpuClient() override; +#endif content::ContentRendererClient* CreateContentRendererClient() override; content::ContentUtilityClient* CreateContentUtilityClient() override; absl::optional BasicStartupComplete() override; @@ -31,7 +36,9 @@ class ContentMainDelegateQt : public content::ContentMainDelegate private: ContentClientQt m_contentClient; std::unique_ptr m_browserClient; +#if defined(USE_OZONE) || BUILDFLAG(IS_WIN) std::unique_ptr m_gpuClient; +#endif std::unique_ptr m_utilityClient; }; diff --git a/src/core/ozone/gl_share_context_qt.cpp b/src/core/ozone/gl_share_context_qt.cpp index f2078b59785..56b50084aa5 100644 --- a/src/core/ozone/gl_share_context_qt.cpp +++ b/src/core/ozone/gl_share_context_qt.cpp @@ -20,9 +20,6 @@ QtShareGLContext::QtShareGLContext(QOpenGLContext *context) : gl::GLContext(nullptr), m_handle(nullptr) { #if QT_CONFIG(opengl) -#if defined(Q_OS_MACOS) - qFatal("macOS only support using ANGLE."); -#endif #if defined(Q_OS_WIN) auto *win_ctx = context->nativeInterface(); if (win_ctx && !m_handle) diff --git a/src/core/ozone/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp index b6f3fa7f6d6..68aa35df3e7 100644 --- a/src/core/ozone/gl_surface_qt.cpp +++ b/src/core/ozone/gl_surface_qt.cpp @@ -7,28 +7,10 @@ #include "qtwebenginecoreglobal_p.h" -#if !defined(Q_OS_MACOS) - #include "gl_surface_qt.h" #include "base/logging.h" -#if BUILDFLAG(IS_WIN) -#include "web_engine_context.h" -#include "ozone/gl_surface_wgl_qt.h" - -#include "gpu/ipc/service/image_transport_surface.h" -#include "ui/gl/init/gl_display_initializer.h" -#include "ui/gl/direct_composition_support.h" -#include "ui/gl/gl_angle_util_win.h" -#include "ui/gl/gl_display.h" -#include "ui/gl/gl_implementation.h" -#include "ui/gl/gl_surface_egl.h" -#include "ui/gl/gl_utils.h" -#include "ui/gl/vsync_provider_win.h" -#endif - - namespace gl { GLDisplay *GLSurfaceQt::g_display = nullptr; @@ -89,77 +71,4 @@ void* GLSurfaceQt::GetConfig() return g_config; } -#if BUILDFLAG(IS_WIN) -namespace init { - -gl::GLDisplay *InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) -{ - VSyncProviderWin::InitializeOneOff(); - - if (GetGLImplementation() == kGLImplementationDesktopGL || GetGLImplementation() == kGLImplementationDesktopGLCoreProfile) - return GLSurfaceWGLQt::InitializeOneOff(gpu_preference); - - GLDisplayEGL *display = GetDisplayEGL(gpu_preference); - switch (GetGLImplementation()) { - case kGLImplementationEGLANGLE: - if (!InitializeDisplay(display, EGLDisplayPlatform(GetDC(nullptr)))) { - LOG(ERROR) << "GLDisplayEGL::Initialize failed."; - return nullptr; - } - if (auto d3d11_device = QueryD3D11DeviceObjectFromANGLE()) - InitializeDirectComposition(std::move(d3d11_device)); - break; - case kGLImplementationMockGL: - case kGLImplementationStubGL: - break; - default: - NOTREACHED(); - } - return display; -} - -bool usingSoftwareDynamicGL() -{ -#if QT_CONFIG(opengl) - return QtWebEngineCore::usingSoftwareDynamicGL(); -#else - return false; -#endif // QT_CONFIG(opengl) -} - -scoped_refptr CreateOffscreenGLSurface(GLDisplay *display, const gfx::Size &size) -{ - scoped_refptr surface; - switch (GetGLImplementation()) { - case kGLImplementationDesktopGLCoreProfile: - case kGLImplementationDesktopGL: { - surface = new GLSurfaceWGLQt(size); - if (surface->Initialize(GLSurfaceFormat())) - return surface; - break; - } - case kGLImplementationEGLANGLE: { - GLDisplayEGL *display_egl = display->GetAs(); - if (display_egl->IsEGLSurfacelessContextSupported() && size.width() == 0 && size.height() == 0) - return InitializeGLSurface(new SurfacelessEGL(display_egl, size)); - return InitializeGLSurface(new PbufferGLSurfaceEGL(display_egl, size)); - } - default: - break; - } - LOG(ERROR) << "Requested OpenGL implementation is not supported. Implementation: " << GetGLImplementation(); - Q_UNREACHABLE(); - return nullptr; -} - -scoped_refptr -CreateViewGLSurface(GLDisplay *display, gfx::AcceleratedWidget window) -{ - return nullptr; -} - -} // namespace init -#endif // BUILDFLAG(IS_WIN) } // namespace gl - -#endif // !defined(Q_OS_MACOS) diff --git a/src/core/ozone/gl_surface_wgl_qt.cpp b/src/core/ozone/gl_surface_wgl_qt.cpp index db4aed88461..afd68e5a263 100644 --- a/src/core/ozone/gl_surface_wgl_qt.cpp +++ b/src/core/ozone/gl_surface_wgl_qt.cpp @@ -2,10 +2,18 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "gl_surface_wgl_qt.h" +#include "web_engine_context.h" -#if BUILDFLAG(IS_WIN) +#include "ui/gl/init/gl_display_initializer.h" +#include "ui/gl/direct_composition_support.h" +#include "ui/gl/gl_angle_util_win.h" +#include "ui/gl/gl_display.h" #include "ui/gl/gl_display_manager.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_surface_egl.h" #include "ui/gl/gl_surface_wgl.h" +#include "ui/gl/gl_utils.h" +#include "ui/gl/vsync_provider_win.h" namespace gl { @@ -55,6 +63,74 @@ void *GLSurfaceWGLQt::GetConfig() return m_surfaceBuffer->GetConfig(); } -} //namespace gl +// Overrides for WGL: +namespace init { -#endif // BUILDFLAG(IS_WIN) +gl::GLDisplay *InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) +{ + VSyncProviderWin::InitializeOneOff(); + + if (GetGLImplementation() == kGLImplementationDesktopGL || GetGLImplementation() == kGLImplementationDesktopGLCoreProfile) + return GLSurfaceWGLQt::InitializeOneOff(gpu_preference); + + GLDisplayEGL *display = GetDisplayEGL(gpu_preference); + switch (GetGLImplementation()) { + case kGLImplementationEGLANGLE: + if (!InitializeDisplay(display, EGLDisplayPlatform(GetDC(nullptr)))) { + LOG(ERROR) << "GLDisplayEGL::Initialize failed."; + return nullptr; + } + if (auto d3d11_device = QueryD3D11DeviceObjectFromANGLE()) + InitializeDirectComposition(std::move(d3d11_device)); + break; + case kGLImplementationMockGL: + case kGLImplementationStubGL: + break; + default: + NOTREACHED(); + } + return display; +} + +bool usingSoftwareDynamicGL() +{ +#if QT_CONFIG(opengl) + return QtWebEngineCore::usingSoftwareDynamicGL(); +#else + return false; +#endif // QT_CONFIG(opengl) +} + +scoped_refptr CreateOffscreenGLSurface(GLDisplay *display, const gfx::Size &size) +{ + scoped_refptr surface; + switch (GetGLImplementation()) { + case kGLImplementationDesktopGLCoreProfile: + case kGLImplementationDesktopGL: { + surface = new GLSurfaceWGLQt(size); + if (surface->Initialize(GLSurfaceFormat())) + return surface; + break; + } + case kGLImplementationEGLANGLE: { + GLDisplayEGL *display_egl = display->GetAs(); + if (display_egl->IsEGLSurfacelessContextSupported() && size.width() == 0 && size.height() == 0) + return InitializeGLSurface(new SurfacelessEGL(display_egl, size)); + return InitializeGLSurface(new PbufferGLSurfaceEGL(display_egl, size)); + } + default: + break; + } + LOG(ERROR) << "Requested OpenGL implementation is not supported. Implementation: " << GetGLImplementation(); + Q_UNREACHABLE(); + return nullptr; +} + +scoped_refptr +CreateViewGLSurface(GLDisplay *display, gfx::AcceleratedWidget window) +{ + return nullptr; +} + +} // namespace init +} // namespace gl diff --git a/src/core/ozone/gl_surface_wgl_qt.h b/src/core/ozone/gl_surface_wgl_qt.h index 6c590e46c6d..014b77d766e 100644 --- a/src/core/ozone/gl_surface_wgl_qt.h +++ b/src/core/ozone/gl_surface_wgl_qt.h @@ -6,8 +6,6 @@ #include "gl_surface_qt.h" -#if BUILDFLAG(IS_WIN) - namespace gl { class PbufferGLSurfaceWGL; @@ -31,7 +29,7 @@ class GLSurfaceWGLQt: public GLSurfaceQt { scoped_refptr m_surfaceBuffer; }; -} -#endif // BUILDFLAG(IS_WIN) +} // namespace gl + #endif // GL_SURFACE_WGL_QT_H diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index a9e0e292a01..bc55de20db0 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -95,7 +95,6 @@ #include "devtools_manager_delegate_qt.h" #include "media_capture_devices_dispatcher.h" #include "net/webui_controller_factory_qt.h" -#include "ozone/gl_context_qt.h" #include "profile_adapter.h" #include "type_conversion.h" #include "web_engine_library_info.h" @@ -114,7 +113,9 @@ #include #include -#if QT_CONFIG(opengl) +#if QT_CONFIG(opengl) && (defined(USE_OZONE) || defined(Q_OS_WIN)) +#include "ozone/gl_context_qt.h" + #include #include @@ -527,6 +528,7 @@ static void logContext(const std::string &glType, base::CommandLine *cmd) << QLatin1StringView(GLContextHelper::getEglPlatformInterface() ? "yes" : "no") << QLatin1StringView("\n"); #endif +#if defined(USE_OZONE) || defined(Q_OS_WIN) log << QLatin1StringView("Using Shared GL:") << QLatin1StringView(qt_gl_global_share_context() ? "yes" : "no") << QLatin1StringView("\n"); @@ -552,6 +554,7 @@ static void logContext(const std::string &glType, base::CommandLine *cmd) .arg(sharedFormat.minorVersion()); } log << QLatin1StringView("\n"); +#endif // defined(USE_OZONE) || defined(Q_OS_WIN) #endif // QT_CONFIG(opengl) log << QLatin1StringView("Init Parameters:\n"); @@ -732,8 +735,11 @@ void WebEngineContext::destroy() // Destroy the main runner, this stops main message loop m_browserRunner.reset(); - // gpu thread is no longer around, so no more cotnext is used, remove the helper + +#if QT_CONFIG(opengl) && (defined(USE_OZONE) || defined(Q_OS_WIN)) + // gpu thread is no longer around, so no more context is used, remove the helper GLContextHelper::destroy(); +#endif // These would normally be in the content-runner, but we allocated them separately: m_mojoIpcSupport.reset(); @@ -1026,7 +1032,9 @@ WebEngineContext::WebEngineContext() initializeFeatureList(parsedCommandLine, enableFeatures, disableFeatures); +#if QT_CONFIG(opengl) && (defined(USE_OZONE) || defined(Q_OS_WIN)) GLContextHelper::initialize(); +#endif // If user requested GL support instead of using Skia rendering to // bitmaps, use software rendering via software OpenGL. This might be less From 87b999b0fee11a1a2c4177c82760e9ce7ae00484 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Tue, 18 Jun 2024 15:25:37 +0200 Subject: [PATCH 110/341] Prevent OTR to non-OTR profile switching when the storage name is empty When switching from profile from OTR to non-OTR requires valid storage name. If it not there, then display a warning message and and don't switch to disk based behavior. Fixes: QTBUG-126312 Pick-to: 6.7 6.2 Change-Id: Id689c8b280b4070b9ecbf11c6001685ac4ffd2f3 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 5cf87f1919ec88d5830c1a635da8c70a9cad9d42) Reviewed-by: Qt Cherry-pick Bot --- .../quicknanobrowser/ApplicationRoot.qml | 4 ++-- src/webenginequick/api/qquickwebengineprofile.cpp | 7 +++++++ tests/auto/quick/qmltests/data/tst_basicProfiles.qml | 11 ++--------- tests/auto/quick/qmltests/data/tst_favicon.qml | 3 ++- .../auto/quick/qmltests/data/tst_faviconDatabase.qml | 9 ++++++--- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml b/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml index 5a27d46df95..bd93cd9aa06 100644 --- a/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml +++ b/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml @@ -8,14 +8,14 @@ QtObject { id: root property QtObject defaultProfile: WebEngineProfile { - storageName: "Profile" offTheRecord: false - + storageName: "Profile" Component.onCompleted: { let fullVersionList = defaultProfile.clientHints.fullVersionList; fullVersionList["QuickNanoBrowser"] = "1.0"; defaultProfile.clientHints.fullVersionList = fullVersionList; } + } property QtObject otrProfile: WebEngineProfile { diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index d4adbb45864..719c3380284 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -515,6 +515,13 @@ void QQuickWebEngineProfile::setOffTheRecord(bool offTheRecord) Q_D(QQuickWebEngineProfile); if (d->profileAdapter()->isOffTheRecord() == offTheRecord) return; + + if (!offTheRecord && d->profileAdapter()->storageName().isEmpty()) { + qWarning("Storage name is empty. Cannot change profile from off-the-record " + "to disk-based behavior as it requires a proper storage name"); + return; + } + ProfileAdapter::HttpCacheType oldCacheType = d->profileAdapter()->httpCacheType(); ProfileAdapter::PersistentCookiesPolicy oldCookiePolicy = d->profileAdapter()->persistentCookiesPolicy(); ProfileAdapter::PersistentPermissionsPolicy oldPermissionsPolicy = d->profileAdapter()->persistentPermissionsPolicy(); diff --git a/tests/auto/quick/qmltests/data/tst_basicProfiles.qml b/tests/auto/quick/qmltests/data/tst_basicProfiles.qml index 11d631344b9..6fcbb08ff8f 100644 --- a/tests/auto/quick/qmltests/data/tst_basicProfiles.qml +++ b/tests/auto/quick/qmltests/data/tst_basicProfiles.qml @@ -8,7 +8,7 @@ import Qt.labs.platform Item { WebEngineProfile { id: otrProfile; /* MEMO implicit offTheRecord: true */ } - WebEngineProfile { id: nonOtrProfile; offTheRecord: false } + WebEngineProfile { id: nonOtrProfile; offTheRecord: false; storageName: 'Test' } function getPath(path, offset = 1) { return path.substr(path.indexOf(':') + offset, path.length) } property string appDataLocation: getPath(getPath(StandardPaths.writableLocation(StandardPaths.AppDataLocation).toString(), 3)) @@ -60,15 +60,9 @@ Item { function test_nonOtrProfile() { let p = nonOtrProfile + compare(p.storageName, 'Test') verify(!p.offTheRecord) - compare(p.storageName, '') - compare(p.cachePath, '') - compare(getPath(p.persistentStoragePath), appDataLocation + '/QtWebEngine/UnknownProfile') - compare(p.httpCacheType, WebEngineProfile.MemoryHttpCache) - compare(p.httpCacheMaximumSize, 0) - compare(p.persistentCookiesPolicy, WebEngineProfile.NoPersistentCookies) - compare(getPath(p.downloadPath), downloadLocation) compare(p.httpAcceptLanguage, '') verify(p.httpUserAgent !== '') @@ -77,7 +71,6 @@ Item { compare(p.userScripts.collection, []) - p.storageName = 'Test' compare(p.storageName, 'Test') compare(getPath(p.cachePath), cacheLocation + '/QtWebEngine/' + p.storageName) compare(getPath(p.persistentStoragePath), appDataLocation + '/QtWebEngine/' + p.storageName) diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index d4b5c805366..ce2995424d6 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -19,8 +19,9 @@ TestWebEngineView { } property QtObject nonOTRProfile: WebEngineProfile { - persistentStoragePath: tempDir.path() + '/WebEngineFavicon' offTheRecord: false + storageName: 'WebEngineFavicon' + persistentStoragePath: tempDir.path() + '/WebEngineFavicon' } function removeFaviconProviderPrefix(url) { diff --git a/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml index 22250852048..d0292851194 100644 --- a/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml +++ b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml @@ -19,8 +19,9 @@ TestWebEngineView { } property QtObject nonOTRProfile: WebEngineProfile { - persistentStoragePath: tempDir.path() + '/WebEngineFavicon' offTheRecord: false + storageName: 'WebEngineFavicon' + persistentStoragePath: tempDir.path() + '/WebEngineFavicon' } function getFaviconPixel(faviconImage) { @@ -147,8 +148,9 @@ TestWebEngineView { TestWebEngineView {\n TempDir { id: tempDir } profile: WebEngineProfile {\n - persistentStoragePath: tempDir.path() + '/WebEngineFavicon1'\n offTheRecord: false\n + storageName: 'WebEngineFavicon1'\n + persistentStoragePath: tempDir.path() + '/WebEngineFavicon1'\n }\n }", testCase); @@ -159,8 +161,9 @@ TestWebEngineView { TestWebEngineView {\n TempDir { id: tempDir } profile: WebEngineProfile {\n - persistentStoragePath: tempDir.path() + '/WebEngineFavicon2'\n offTheRecord: false\n + storageName: 'WebEngineFavicon2'\n + persistentStoragePath: tempDir.path() + '/WebEngineFavicon2'\n }\n }", testCase); From adf1e4736f3c4f2490c108abeaaa546213cd3878 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Wed, 14 Aug 2024 17:08:34 +0000 Subject: [PATCH 111/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I07d6c79d270da1e469b0306ee66346f48dfdf0ff Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 7282ef2ccc0..6a42ca64446 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 10d00aca5e9da3973bca4b8d083ea11d5b0f1775 + ref: 2f25a48950aa879049029abe5a0450e2d4441d08 required: true ../qtpositioning: - ref: 9891aed7411ddb70a3f07d92fca43e59149dc1d4 + ref: 3b2af9765053f1d07cb9af4736462ca406be27e7 required: false ../qttools: - ref: b7ca1c6048043a3e0de84729067db18f78b5f92f + ref: b86f119560588634519a6c49846a6109d88ba20d required: false ../qtwebchannel: - ref: 56ad85728e9396cfd917e59011d6e1d72fc25392 + ref: 6fe7d5b306da9588f17c1a436f717ada7a3ce6c2 required: false From 5fff4a3a9507c741e2dc5918e08a3be54bf6a0d4 Mon Sep 17 00:00:00 2001 From: Tian Shilin Date: Wed, 14 Aug 2024 13:20:00 +0800 Subject: [PATCH 112/341] fix conditional redundancy for totalBytes m_progressBar->setValue(qRound(100 * receivedBytes / totalBytes)); There is a potential risk of de-zeroing here, since receivedBytes / totalBytes will trigger a runtime error if totalBytes is zero. In addition, if totalBytes is always greater than or equal to 0, then checking for totalBytes >= 0 is actually redundant, since the concern should be that totalBytes is not zero. To ensure the robustness of the code, a check that totalBytes is zero should be added to prevent divide-by-zero errors. By ensuring that totalBytes is greater than zero, this improvement not only avoids the risk of de-zeroing, but also ensures that the percentage calculation of the progress bar is meaningful. At the same time, for cases where totalBytes is 0 or unknown, the progress bar is displayed as 0% and the format is "unknown size". This is a safer way to handle the situation and is more in line with the needs of the actual application. Pick-to: 6.7 Change-Id: I7537243e375f336f5c68ef1cc6ec8ade8fa16e5c Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 16aa88039199e6ffbed95818fb9366db8f47aecf) Reviewed-by: Qt Cherry-pick Bot --- examples/webenginewidgets/simplebrowser/downloadwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webenginewidgets/simplebrowser/downloadwidget.cpp b/examples/webenginewidgets/simplebrowser/downloadwidget.cpp index 2fb65e1a8fc..c6d3b0921ee 100644 --- a/examples/webenginewidgets/simplebrowser/downloadwidget.cpp +++ b/examples/webenginewidgets/simplebrowser/downloadwidget.cpp @@ -59,7 +59,7 @@ void DownloadWidget::updateWidget() Q_UNREACHABLE(); break; case QWebEngineDownloadRequest::DownloadInProgress: - if (totalBytes >= 0) { + if (totalBytes > 0) { m_progressBar->setValue(qRound(100 * receivedBytes / totalBytes)); m_progressBar->setDisabled(false); m_progressBar->setFormat( From ff364fcb12049afcfe58159ed137203f7b6773fc Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Tue, 23 Jul 2024 12:24:44 +0200 Subject: [PATCH 113/341] CMake: Skip Intel CET hardening on MSVC The WebEngineCore library should be built without hardening, to avoid runtime crashes. Fixes: QTBUG-127464 Change-Id: I670178acc1dfe67a2e5523e113bba4ca0cbdefbb Reviewed-by: Michal Klocek (cherry picked from commit 19a977443c628ad819923b308266699bfb019219) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt index 916c219d0a3..9ca610d3299 100644 --- a/src/core/api/CMakeLists.txt +++ b/src/core/api/CMakeLists.txt @@ -67,6 +67,10 @@ qt_internal_add_module(WebEngineCore SBOM_INCOMPLETE_3RD_PARTY_DEPENDENCIES ) +if(MSVC) + qt_internal_skip_intel_cet_hardening(WebEngineCore) +endif() + set_target_properties(WebEngineCore PROPERTIES QTWEBENGINEPROCESS_NAME ${qtWebEngineProcessName}) set_target_properties(WebEngineCore PROPERTIES CXX_STANDARD 20) # Chromium included headers are not clean From 3933bf51e4858380f5bea854e912acb57de76cb7 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Mon, 19 Aug 2024 16:37:45 +0200 Subject: [PATCH 114/341] Update Chromium MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule src/3rdparty 23009a64..c091eb3f: * Add missing check for use_cups * FIXUP: "Shut GL down on process exit to silence Direct3D11 warnings" * Shut GL down on process exit to silence Direct3D11 warnings * [Backport] Enable the PriorityHeader feature by default * [Backport]Ship Zstd Content-Encoding Change-Id: I1e28a35a90e37ae1f2c652ff94160e37ded21c55 Reviewed-by: Michael BrĂ¼ning --- src/3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index 23009a64b01..c091eb3fa68 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 23009a64b01fa6ee40e04d60ee35bb835dcd1951 +Subproject commit c091eb3fa68e1e9c03147623071fa2015a9e3692 From 0cd5541a1062efb46a0a890ea58b8e031c998dd1 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 14 Aug 2024 11:56:13 +0200 Subject: [PATCH 115/341] Do not use cups We do not use print dialog and it seems 'use_cups' is anyway overridden on linux in config setup to 'false'. Therefore make sure it stays 'false' also for 'qtpdf'. In case cups is needed at some point we should switch from 'cups-config' (wrapped by cups_config_helper.py) to 'pkg-config' during gn run as the use of former one is deprecated. Task-number: QTBUG-120248 Fixes: QTBUG-122407 Change-Id: I150a0b30f4f57fe0f4fe92fe8760eaebe4136bd8 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 09c09126e10f0e7428eab7ede5da6498a560e688) Reviewed-by: Qt Cherry-pick Bot --- src/core/CMakeLists.txt | 6 +----- src/core/api/configure.cmake | 5 +---- src/pdf/CMakeLists.txt | 1 + 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 487ac15fb49..a05842be2b8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -356,6 +356,7 @@ foreach(arch ${archs}) optimize_webui=false strip_absolute_paths_from_debug_symbols=false pdf_use_skia=true + use_cups=false use_dawn=false skia_use_dawn=false devtools_fast_bundle=false @@ -373,10 +374,6 @@ foreach(arch ${archs}) ARGS enable_printing enable_basic_printing enable_print_preview enable_pdf CONDITION QT_FEATURE_webengine_printing_and_pdf ) - extend_gn_list(gnArgArg - ARGS use_cups - CONDITION QT_FEATURE_webengine_printing_and_pdf AND NOT WIN32 - ) extend_gn_list(gnArgArg ARGS enable_plugins CONDITION QT_FEATURE_webengine_printing_and_pdf OR @@ -443,7 +440,6 @@ foreach(arch ${archs}) angle_enable_gl=true use_gtk=false # GTK toolkit bindings use_qt=false # Qt5 toolkit bindings - use_cups=false use_gio=false use_bundled_fontconfig=false use_glib=false diff --git a/src/core/api/configure.cmake b/src/core/api/configure.cmake index f8488c05718..47d72767180 100644 --- a/src/core/api/configure.cmake +++ b/src/core/api/configure.cmake @@ -18,8 +18,6 @@ if(NOT QT_CONFIGURE_RUNNING) pkg_check_modules(GIO gio-2.0) endif() endif() - find_package(Cups) - find_package(Qt6 ${PROJECT_VERSION} CONFIG QUIET OPTIONAL_COMPONENTS Positioning WebChannel PrintSupport) endif() @@ -87,8 +85,7 @@ qt_feature("webengine-printing-and-pdf" PRIVATE LABEL "Printing and PDF" PURPOSE "Provides printing and output to PDF." AUTODETECT NOT QT_FEATURE_webengine_embedded_build - CONDITION TARGET Qt::PrintSupport AND QT_FEATURE_printer AND - (CUPS_FOUND OR WIN32) + CONDITION TARGET Qt::PrintSupport AND QT_FEATURE_printer ) qt_feature("webengine-pepper-plugins" PRIVATE LABEL "Pepper Plugins" diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt index eeb84a8e1c7..fcb5f1186cc 100644 --- a/src/pdf/CMakeLists.txt +++ b/src/pdf/CMakeLists.txt @@ -124,6 +124,7 @@ foreach(arch ${archs}) enable_swiftshader_vulkan=false angle_enable_swiftshader=false dawn_use_swiftshader=false + use_cups=false use_dawn=false build_dawn_tests=false enable_ipc_fuzzer=false From 3b59323898ae990e8f3ae9983c6dea6c3f714a38 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Mon, 19 Aug 2024 10:36:50 +0200 Subject: [PATCH 116/341] QQuickWebEngineProfile: Add missing REVISION to new property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found during API review. Change-Id: I2e84f4d9fd5f95f8f4726ed130d67fc715d57d18 Reviewed-by: Michael BrĂ¼ning (cherry picked from commit a2d039da3af62246867c2c6c072893da2f324c39) Reviewed-by: Qt Cherry-pick Bot --- src/webenginequick/api/qquickwebengineprofile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h index 27ce9d9fcec..90425c5ca76 100644 --- a/src/webenginequick/api/qquickwebengineprofile.h +++ b/src/webenginequick/api/qquickwebengineprofile.h @@ -34,7 +34,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject { Q_PROPERTY(HttpCacheType httpCacheType READ httpCacheType WRITE setHttpCacheType NOTIFY httpCacheTypeChanged FINAL) Q_PROPERTY(QString httpAcceptLanguage READ httpAcceptLanguage WRITE setHttpAcceptLanguage NOTIFY httpAcceptLanguageChanged FINAL REVISION(1,1)) Q_PROPERTY(PersistentCookiesPolicy persistentCookiesPolicy READ persistentCookiesPolicy WRITE setPersistentCookiesPolicy NOTIFY persistentCookiesPolicyChanged FINAL) - Q_PROPERTY(PersistentPermissionsPolicy persistentPermissionsPolicy READ persistentPermissionsPolicy WRITE setPersistentPermissionsPolicy NOTIFY persistentPermissionsPolicyChanged FINAL) + Q_PROPERTY(PersistentPermissionsPolicy persistentPermissionsPolicy READ persistentPermissionsPolicy WRITE setPersistentPermissionsPolicy NOTIFY persistentPermissionsPolicyChanged FINAL REVISION(6,8)) Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL) Q_PROPERTY(QStringList spellCheckLanguages READ spellCheckLanguages WRITE setSpellCheckLanguages NOTIFY spellCheckLanguagesChanged FINAL REVISION(1,3)) Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY spellCheckEnabledChanged FINAL REVISION(1,3)) From 41e27f4e4377b9f567532c29c4cec664061f84ea Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 19 Aug 2024 16:49:36 +0000 Subject: [PATCH 117/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I32aef9d82dce53c6112483367671b885daab4059 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 6a42ca64446..da7c80c4d53 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 2f25a48950aa879049029abe5a0450e2d4441d08 + ref: b3a855155422b6183148ad0a8b0a861cb0d84e1b required: true ../qtpositioning: - ref: 3b2af9765053f1d07cb9af4736462ca406be27e7 + ref: e926e1d7a86a65b3dd6132c43e6866d3eceb6114 required: false ../qttools: - ref: b86f119560588634519a6c49846a6109d88ba20d + ref: 751d170ff4b4b56f251875b8e0ffd1fc4e96f7e7 required: false ../qtwebchannel: - ref: 6fe7d5b306da9588f17c1a436f717ada7a3ce6c2 + ref: 21ba04c7bd7880e23482eec9b464e48609e589b5 required: false From d230f880f6c736776c4f1354aa06d20700161156 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Wed, 17 Jul 2024 12:01:49 +0200 Subject: [PATCH 118/341] QWebEnginePermission: Simplify copy constructor and assignment Found during API review Change-Id: I958fd3d1b719eedb72970c2718ab9d35a2d887e8 Reviewed-by: Michal Klocek (cherry picked from commit 69d2e050434c17483b94f0f9be9ba6cdd6883333) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginepermission.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp index 0cee6506b8a..7a5a2ab414e 100644 --- a/src/core/api/qwebenginepermission.cpp +++ b/src/core/api/qwebenginepermission.cpp @@ -89,7 +89,7 @@ QWebEnginePermission::QWebEnginePermission(QWebEnginePermissionPrivate *pvt) } QWebEnginePermission::QWebEnginePermission(const QWebEnginePermission &other) - : d_ptr(new QWebEnginePermissionPrivate(*other.d_ptr)) + : d_ptr(other.d_ptr) { } @@ -102,10 +102,7 @@ QWebEnginePermission::~QWebEnginePermission() = default; QWebEnginePermission &QWebEnginePermission::operator=(const QWebEnginePermission &other) { - if (this == &other) - return *this; - - d_ptr.reset(new QWebEnginePermissionPrivate(*other.d_ptr)); + d_ptr = other.d_ptr; return *this; } From 1dba5a2a42f75db182081f1e48ea35759bb7d62a Mon Sep 17 00:00:00 2001 From: Tian Shilin Date: Wed, 14 Aug 2024 14:38:55 +0800 Subject: [PATCH 119/341] fix: Avoid empty engine The engine variable is obtained by calling qmlEngine(m_view). If m_view is not associated with a valid QML engine, then the engine may be null,so advancing the null check on the engine to immediately after the engine is fetched ensures that an invalid engine is not accidentally used in subsequent code, especially if(m_importDirs.isEmpty() && !initializeImportDirs(m_importDirs, engine)),which I verified with a static scan tool to verify the above statement,and found that it does indeed result in a nullpointer error of type Pick-to: 6.7 Change-Id: I8cc427d2b94f93e8c9fc24a202d41abd8e00143d Reviewed-by: Michal Klocek (cherry picked from commit b13a99a01e950bfd471f5ade8455dade2504fe6b) Reviewed-by: Qt Cherry-pick Bot --- src/webenginequick/ui_delegates_manager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/webenginequick/ui_delegates_manager.cpp b/src/webenginequick/ui_delegates_manager.cpp index a4a22fedd7d..3b14c2821f4 100644 --- a/src/webenginequick/ui_delegates_manager.cpp +++ b/src/webenginequick/ui_delegates_manager.cpp @@ -111,6 +111,10 @@ UIDelegatesManager::~UIDelegatesManager() bool UIDelegatesManager::ensureComponentLoaded(ComponentType type) { QQmlEngine* engine = qmlEngine(m_view); + + if (!engine) + return false; + if (m_importDirs.isEmpty() && !initializeImportDirs(m_importDirs, engine)) return false; @@ -128,8 +132,6 @@ bool UIDelegatesManager::ensureComponentLoaded(ComponentType type) #else // Unconditionally reload the components each time. fprintf(stderr, "%s: %s\n", Q_FUNC_INFO, qPrintable(fileName)); #endif - if (!engine) - return false; for (const QString &importDir : std::as_const(m_importDirs)) { const QString componentFilePath = importDir % QLatin1Char('/') % fileName; From c407b198b7f8a42ad639d04be5d11cef3e7e6c7b Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Mon, 4 Mar 2024 13:38:47 +0100 Subject: [PATCH 120/341] Hook up quicknanobrowser to screen capturing API A Qt Quick API was implemented alongside the Widgets one, but it seems the quicknanobrowser example was never updated to make use of it. Pick-to: 6.7 Change-Id: I8ac996f2237a2673bdbbab85a8174fa166fdd5b1 Reviewed-by: Michal Klocek (cherry picked from commit 0d9e429b4de070eaac5d5508832f22efdcdf633f) Reviewed-by: Qt Cherry-pick Bot --- examples/webenginequick/quicknanobrowser/BrowserWindow.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml index 02f5564aca2..1c31ea94409 100644 --- a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml +++ b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml @@ -561,6 +561,7 @@ ApplicationWindow { settings.webRTCPublicInterfacesOnly: appSettings.webRTCPublicInterfacesOnly settings.pdfViewerEnabled: appSettings.pdfViewerEnabled settings.imageAnimationPolicy: appSettings.imageAnimationPolicy + settings.screenCaptureEnabled: true onCertificateError: function(error) { if (!error.isMainFrame) { @@ -610,6 +611,11 @@ ApplicationWindow { request.accept(); } + onDesktopMediaRequested: function(request) { + // select the primary screen + request.selectScreen(request.screensModel.index(0, 0)); + } + onRenderProcessTerminated: function(terminationStatus, exitCode) { var status = ""; switch (terminationStatus) { From b12082cec301d108074fb468471e5d1f6e86bb2e Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Mon, 19 Aug 2024 16:11:20 +0200 Subject: [PATCH 121/341] Make ResourceTypeJson documented as 6.8 value in enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adaptations 122-based return this resource type so make it already documented in 6.8. Change-Id: I2e03eb387c60dca6ef4b7326b5ce786ea122f55b Reviewed-by: Michael BrĂ¼ning (cherry picked from commit 78bcc5b2f1348f328a22c45d642e0eb7251e4265) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineurlrequestinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp index b323b5ec3b3..e3335f559c0 100644 --- a/src/core/api/qwebengineurlrequestinfo.cpp +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -161,7 +161,7 @@ QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPriva \value ResourceTypeNavigationPreloadSubFrame A sub-frame service worker navigation preload request. (Added in Qt 5.14) \value ResourceTypeWebSocket A WebSocket request. (Added in Qt 6.4) \value ResourceTypeUnknown Unknown request type. - \value ResourceTypeJson A JSON module. (Added in Qt 6.9) + \value ResourceTypeJson A JSON module. (Added in Qt 6.8) \note For forward compatibility all values not matched should be treated as unknown, not just \c ResourceTypeUnknown. From 707e2ef267f5798245b5d0d646aaa121137fdd43 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Thu, 22 Aug 2024 09:54:45 +0200 Subject: [PATCH 122/341] Fix cross comile error for apalis-imx8 Deals with: "error: operands to '?:' have different types 'intptr_t' {aka 'long int'} and 'EGLNativeDisplayType' {aka 'wl_display*'}" Task-number: QTBUG-126655 Change-Id: I62b2369b2dff2b7a2929a91d59cde4d24b8c2398 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 639d9f5b547486281bb1c218dc87f968c69a2642) Reviewed-by: Qt Cherry-pick Bot --- src/core/ozone/gl_ozone_egl_qt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/ozone/gl_ozone_egl_qt.cpp b/src/core/ozone/gl_ozone_egl_qt.cpp index 26d11df3157..8cc79384151 100644 --- a/src/core/ozone/gl_ozone_egl_qt.cpp +++ b/src/core/ozone/gl_ozone_egl_qt.cpp @@ -75,7 +75,8 @@ scoped_refptr GLOzoneEGLQt::CreateOffscreenGLSurface(gl::GLDispla gl::EGLDisplayPlatform GLOzoneEGLQt::GetNativeDisplay() { static void *display = GLContextHelper::getNativeDisplay(); - static gl::EGLDisplayPlatform platform(display ? reinterpret_cast(display) : EGL_DEFAULT_DISPLAY); + static gl::EGLDisplayPlatform platform(display ? reinterpret_cast(display) + : EGL_DEFAULT_DISPLAY); return platform; } From 8e25079b80ae53d2192e33f8162cd1f9afa9f92c Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 22 Aug 2024 22:26:45 +0000 Subject: [PATCH 123/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I46e6cbb8bf5e00178fd4a11cebaa214170202027 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index da7c80c4d53..86f8978b78f 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: b3a855155422b6183148ad0a8b0a861cb0d84e1b + ref: 68a468980fe9831ad81fb382cf9d17a03236d4bb required: true ../qtpositioning: - ref: e926e1d7a86a65b3dd6132c43e6866d3eceb6114 + ref: 2977c2489d6a8434cfac6b055564eaf19cd4faf5 required: false ../qttools: - ref: 751d170ff4b4b56f251875b8e0ffd1fc4e96f7e7 + ref: 5a3155df8ca8fc9ff491ebf0b28f5c4a4ec5a30d required: false ../qtwebchannel: - ref: 21ba04c7bd7880e23482eec9b464e48609e589b5 + ref: 518ce9061cad91d3780c559412c2657ee38bd527 required: false From 9f4c1bc7c7baac93995e764b1a177e5772c29b93 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 2 Feb 2024 13:49:16 +0100 Subject: [PATCH 124/341] Make QQuickWebEngineDownloadRequest public We only really need the QWebEngineDownloadRequest, but the fact it was just that was in the private header. Fixes: QTBUG-120370 Change-Id: I9bcd79e068e67ec0ed07ae31cfb2a0d4e011e22b Reviewed-by: Anu Aliyas (cherry picked from commit 712607ff9ce24779393fa44163705916ebf9b3a7) Reviewed-by: Qt Cherry-pick Bot --- src/webenginequick/CMakeLists.txt | 2 +- .../api/qquickwebenginedownloadrequest.cpp | 5 ++-- ...t_p.h => qquickwebenginedownloadrequest.h} | 23 +++++-------------- .../api/qquickwebengineprofile.cpp | 2 +- tests/auto/quick/publicapi/tst_publicapi.cpp | 4 ++-- .../tst_qquickwebengineview.cpp | 2 +- 6 files changed, 14 insertions(+), 24 deletions(-) rename src/webenginequick/api/{qquickwebenginedownloadrequest_p.h => qquickwebenginedownloadrequest.h} (63%) diff --git a/src/webenginequick/CMakeLists.txt b/src/webenginequick/CMakeLists.txt index b7de1c2af35..50d038cc9fa 100644 --- a/src/webenginequick/CMakeLists.txt +++ b/src/webenginequick/CMakeLists.txt @@ -18,7 +18,7 @@ qt_internal_add_qml_module(WebEngineQuick api/qquickwebengineaction_p_p.h api/qquickwebengineclientcertificateselection.cpp api/qquickwebengineclientcertificateselection_p.h api/qquickwebenginedialogrequests.cpp api/qquickwebenginedialogrequests_p.h - api/qquickwebenginedownloadrequest.cpp api/qquickwebenginedownloadrequest_p.h + api/qquickwebenginedownloadrequest.cpp api/qquickwebenginedownloadrequest.h api/qquickwebenginefaviconprovider.cpp api/qquickwebenginefaviconprovider_p_p.h api/qquickwebenginenewwindowrequest.cpp api/qquickwebenginenewwindowrequest_p.h diff --git a/src/webenginequick/api/qquickwebenginedownloadrequest.cpp b/src/webenginequick/api/qquickwebenginedownloadrequest.cpp index f745ba3b309..e4892977163 100644 --- a/src/webenginequick/api/qquickwebenginedownloadrequest.cpp +++ b/src/webenginequick/api/qquickwebenginedownloadrequest.cpp @@ -1,7 +1,8 @@ // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#include "qquickwebenginedownloadrequest_p.h" +#include "qquickwebenginedownloadrequest.h" +#include "qquickwebengineview_p.h" #include "QtWebEngineCore/private/qwebenginedownloadrequest_p.h" #include "web_contents_adapter_client.h" @@ -29,4 +30,4 @@ QQuickWebEngineView *QQuickWebEngineDownloadRequest::view() const QT_END_NAMESPACE -#include "moc_qquickwebenginedownloadrequest_p.cpp" +#include "moc_qquickwebenginedownloadrequest.cpp" diff --git a/src/webenginequick/api/qquickwebenginedownloadrequest_p.h b/src/webenginequick/api/qquickwebenginedownloadrequest.h similarity index 63% rename from src/webenginequick/api/qquickwebenginedownloadrequest_p.h rename to src/webenginequick/api/qquickwebenginedownloadrequest.h index 42a0d88bade..291b59e08ba 100644 --- a/src/webenginequick/api/qquickwebenginedownloadrequest_p.h +++ b/src/webenginequick/api/qquickwebenginedownloadrequest.h @@ -1,27 +1,16 @@ // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#ifndef QQUICKWEBENGINEDOWNLOADREQUEST_P_H -#define QQUICKWEBENGINEDOWNLOADREQUEST_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 -#include +#ifndef QQUICKWEBENGINEDOWNLOADREQUEST_H +#define QQUICKWEBENGINEDOWNLOADREQUEST_H + #include +#include #include QT_BEGIN_NAMESPACE +class QQuickWebEngineView; class QQuickWebEngineProfilePrivate; class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineDownloadRequest : public QWebEngineDownloadRequest @@ -43,4 +32,4 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineDownloadRequest : public QWebEngine QT_END_NAMESPACE -#endif // QQUICKWEBENGINEDOWNLOADREQUEST_P_H +#endif // QQUICKWEBENGINEDOWNLOADREQUEST_H diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index 719c3380284..4dcdb1af465 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -3,7 +3,7 @@ #include "qquickwebengineprofile.h" #include "qquickwebengineprofile_p.h" -#include "qquickwebenginedownloadrequest_p.h" +#include "qquickwebenginedownloadrequest.h" #include "qquickwebenginesettings_p.h" #include "qquickwebenginescriptcollection_p.h" #include "qquickwebenginescriptcollection_p_p.h" diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 6abaac31567..499acbfc51e 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -28,11 +27,12 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include #include diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 7e90b58b8ec..c2e4ef210eb 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -15,11 +15,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include From 926ed58d2fa9e4cbea9a0fea30637f6627150820 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 26 Jul 2024 14:29:10 +0200 Subject: [PATCH 125/341] Mark the persistentPermissionPolicy API as new in 6.8 Was missing. Change-Id: Ie6bd9659c60bab240431329f469f91dac6b3b176 Reviewed-by: Anu Aliyas Reviewed-by: Kaloyan Chehlarski (cherry picked from commit 86a208192e11563708d262f3415c5b6a4f1c9781) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebengineprofile.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index b238d32a5d9..1d78a804af1 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -599,6 +599,7 @@ void QWebEngineProfile::setPersistentCookiesPolicy(QWebEngineProfile::Persistent Off-the-record profiles are not allowed to save data to the disk, so they can only return \c StoreInMemory or \c AskEveryTime. + \since 6.8 \sa QWebEngineProfile::PersistentPermissionsPolicy, setPersistentPermissionsPolicy() */ QWebEngineProfile::PersistentPermissionsPolicy QWebEngineProfile::persistentPermissionsPolicy() const @@ -610,6 +611,7 @@ QWebEngineProfile::PersistentPermissionsPolicy QWebEngineProfile::persistentPerm /*! Sets the policy for persistent permissions to \a newPersistentPermissionsPolicy. + \since 6.8 \sa QWebEngineProfile::PersistentPermissionsPolicy, persistentPermissionsPolicy() */ void QWebEngineProfile::setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy newPersistentPermissionsPolicy) From 52455440635a2cc9beb6a5e667fe78f21963030e Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Wed, 21 Aug 2024 11:41:07 +0200 Subject: [PATCH 126/341] Document sourceUrl() and setSourceUrl() in QWebEngineScript Added missing documentation for sourceUrl and setSourceUrl in QWebEngineScript. Fixes: QTBUG-128140 Pick-to: 6.7 Change-Id: Iff77961060a8b3efea42d074ac66c4800afc0fb3 Reviewed-by: Michal Klocek (cherry picked from commit e013c508e99b74866a480a52d6a23aeda0473b4b) Reviewed-by: Qt Cherry-pick Bot --- src/core/api/qwebenginescript.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/core/api/qwebenginescript.cpp b/src/core/api/qwebenginescript.cpp index 29b92a39652..846b011967c 100644 --- a/src/core/api/qwebenginescript.cpp +++ b/src/core/api/qwebenginescript.cpp @@ -131,12 +131,26 @@ void QWebEngineScript::setName(const QString &scriptName) d->setName(scriptName); } - +/*! + * Returns the remote source location of the user script (if any). + */ QUrl QWebEngineScript::sourceUrl() const { return d->sourceUrl(); } +/*! + * Sets the remote source location of the user script to \a url. + * + * Unlike \l setSourceCode(), this function allows referring to user scripts that + * are not already loaded in memory, for instance, when stored on disk. + * + * Setting this value will change the \l sourceCode of the script. + * + * \note At present, only file-based sources are supported. + * + * \sa setSourceCode() + */ void QWebEngineScript::setSourceUrl(const QUrl &url) { if (url == sourceUrl()) From f1980f9d7da50d49e4f7bf3ac01d70affc5a9bde Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Sat, 24 Aug 2024 14:06:00 +0000 Subject: [PATCH 127/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I465136e9041aa6136938812b057d1af0c687e42d Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 86f8978b78f..71c937db2b2 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 68a468980fe9831ad81fb382cf9d17a03236d4bb + ref: 752bce98f903052d7b9bd30610c326592784576f required: true ../qtpositioning: - ref: 2977c2489d6a8434cfac6b055564eaf19cd4faf5 + ref: 4b0791714b45c68e9afff61c4bef661ece88235d required: false ../qttools: - ref: 5a3155df8ca8fc9ff491ebf0b28f5c4a4ec5a30d + ref: 10dbff6001deea0339f38c5f84edf332c65c665a required: false ../qtwebchannel: - ref: 518ce9061cad91d3780c559412c2657ee38bd527 + ref: 67d7422d9814f7a9b58ca095ad83791210f85d60 required: false From 7107fee8627dd7743f511bc887ad752524711b4a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 20 Aug 2024 10:58:08 +0200 Subject: [PATCH 128/341] Set content_enable_legacy_ipc to true Otherwise it is only indirectly enabled by enable_ppapi, and we still use legacy ipc. Change-Id: I0d7c754b746463d43acc5ffc2342280101939ee6 Reviewed-by: Michal Klocek (cherry picked from commit bc5cec1a57afd85f0030a04af1ec26af8857c284) Reviewed-by: Qt Cherry-pick Bot --- src/core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a05842be2b8..de52226456a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -363,6 +363,7 @@ foreach(arch ${archs}) devtools_skip_typecheck=false use_static_angle=true use_perfetto_client_library=false + content_enable_legacy_ipc=true enable_extensions_legacy_ipc=true enable_bound_session_credentials=false ) From c6958702d75e2942fe708427a0bf7d44278c0033 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Thu, 15 Aug 2024 16:27:44 +0200 Subject: [PATCH 129/341] Permission manager: separate tracking of transient permissions Following the rewrite of the permissions API, transient (a.k.a non-persistent) permissions still passed through the persistent store sometimes, but were filtered out when using user-facing APIs. Unfortunately, thisstill presented some edge cases in the AskEveryTime permission policy mode. This change modifies the PermissionManagerQt class to store a second set of permissions, and associate them with a RenderFrameHost the way the Chromium API is designed to do anyway. This way, a permission will be kept around for the lifetime of a web page, and calling JavaScript APIs that trigger checks for permission state will work properly (e.g. navigator.mediaDevices.enumerateDevices). The new store is regularly cleaned up to make sure expired permissions are purged before they impact performance. As a side effect, this change also introduces pre-granting of non-persistent permissions, which was the biggest omission in the permissions rewrite. In those cases, the permissions will be temporarily stored inside the persistent store, and moved to the transient one the next time they're queried (and can thus be associated with a RenderFrameHost). This also fixes some extremely broken test cases that relied on invalid web API. Fixes: QTBUG-127951 Change-Id: Ic084af7673ea0b255d98d94382e77323bb5e7ab0 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 8001d8e149b2d109718f6a671c93e3489c4ecd54) Reviewed-by: Qt Cherry-pick Bot --- .../simplebrowser/browser.cpp | 1 + src/core/api/qwebenginepermission.cpp | 21 +- src/core/api/qwebengineprofile.cpp | 11 +- src/core/permission_manager_qt.cpp | 224 +++++++++++++++--- src/core/permission_manager_qt.h | 30 ++- src/core/profile_adapter.cpp | 13 +- src/core/profile_adapter.h | 10 +- src/core/web_contents_adapter.cpp | 23 +- src/core/web_contents_delegate_qt.cpp | 17 +- .../doc/src/webengine_permission.qdoc | 9 +- tests/auto/httpserver/data/notification.html | 4 +- .../quick/qmltests/data/tst_geopermission.qml | 5 + .../quick/qmltests/data/tst_notification.qml | 4 +- .../qwebenginepage/tst_qwebenginepage.cpp | 2 - .../tst_qwebengineprofile.cpp | 8 +- 15 files changed, 292 insertions(+), 90 deletions(-) diff --git a/examples/webenginewidgets/simplebrowser/browser.cpp b/examples/webenginewidgets/simplebrowser/browser.cpp index fd68246d0ce..30c7fc98eab 100644 --- a/examples/webenginewidgets/simplebrowser/browser.cpp +++ b/examples/webenginewidgets/simplebrowser/browser.cpp @@ -33,6 +33,7 @@ BrowserWindow *Browser::createHiddenWindow(bool offTheRecord) } auto profile = !offTheRecord ? m_profile.get() : QWebEngineProfile::defaultProfile(); auto mainWindow = new BrowserWindow(this, profile, false); + profile->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime); m_windows.append(mainWindow); QObject::connect(mainWindow, &QObject::destroyed, [this, mainWindow]() { m_windows.removeOne(mainWindow); diff --git a/src/core/api/qwebenginepermission.cpp b/src/core/api/qwebenginepermission.cpp index 7a5a2ab414e..d6f5ed98fcc 100644 --- a/src/core/api/qwebenginepermission.cpp +++ b/src/core/api/qwebenginepermission.cpp @@ -54,7 +54,7 @@ QWebEnginePermissionPrivate::QWebEnginePermissionPrivate(const QUrl &origin_, QW \l QWebEnginePermission::PermissionType describes all the permission types Qt WebEngine supports. Only some permission types are remembered between browsing sessions; they are \e persistent. Non-persistent permissions query the user every time a - website requests them, and cannot be granted in advance. You can check whether a permission type is persistent at runtime + website requests them. You can check whether a permission type is persistent at runtime using the static method QWebEnginePermission::isPersistent(). Persistent permissions are stored inside the active QWebEngineProfile, and their lifetime depends on the value of @@ -166,8 +166,7 @@ QUrl QWebEnginePermission::origin() const \value Unsupported An unsupported permission type. \note Non-persistent permission types are ones that will never be remembered by the underlying storage, and will trigger - a permission request every time a website tries to use them. They can only be denied/granted as they're needed; - any attempts to pre-grant a non-persistent permission will fail. + a permission request every time a website tries to use them. */ /*! @@ -196,7 +195,7 @@ QWebEnginePermission::PermissionType QWebEnginePermission::permissionType() cons If a permission for the specified \l permissionType() and \l origin() has already been granted or denied, the return value is QWebEnginePermission::Granted, or QWebEnginePermission::Denied, respectively. - When this is the first time the permission is requested, or if the \l permissionType() is non-persistent, + When this is the first time the permission is requested, the return value is QWebEnginePermission::Ask. If the object is in an invalid state, the returned value is QWebEnginePermission::Invalid. @@ -210,8 +209,7 @@ QWebEnginePermission::State QWebEnginePermission::state() const return d_ptr->webContentsAdapter.toStrongRef()->getPermissionState(origin(), permissionType()); if (d_ptr->profileAdapter) return d_ptr->profileAdapter->getPermissionState(origin(), permissionType()); - Q_UNREACHABLE(); - return State::Ask; + Q_UNREACHABLE_RETURN(State::Ask); } /*! @@ -221,9 +219,8 @@ QWebEnginePermission::State QWebEnginePermission::state() const An invalid QWebEnginePermission is either: \list \li One whose \l permissionType() is unsupported; - \li One whose \l permissionType() is non-persistent, and the user has navigated away from the web page that triggered the request; - \li One whose \l permissionType() is persistent, but the associated profile has been destroyed; - \li One whose \l origin() is invalid. + \li One whose \l origin() is invalid; + \li One whose associated profile has been destroyed \endlist \sa isPersistent() @@ -234,9 +231,7 @@ bool QWebEnginePermission::isValid() const return false; if (permissionType() == PermissionType::Unsupported) return false; - if (!isPersistent(permissionType()) && !d_ptr->webContentsAdapter) - return false; - if (!d_ptr->profileAdapter) + if (!d_ptr->profileAdapter && !d_ptr->webContentsAdapter) return false; if (!d_ptr->origin.isValid()) return false; @@ -277,7 +272,7 @@ void QWebEnginePermission::deny() const Removes the permission from the profile's underlying storage. By default, permissions are stored on disk (except for off-the-record profiles, where permissions are stored in memory and are destroyed with the profile). This means that an already granted/denied permission will not be requested twice, but will get automatically - granted/denied every subsequent time a website requests it. Calling reset() allows the query to be asked + granted/denied every subsequent time a website requests it. Calling reset() allows the query to be displayed again the next time the website requests it. Does nothing when \l isValid() evaluates to false. diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index 1d78a804af1..b0824af3503 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -985,7 +985,11 @@ void QWebEngineProfile::requestIconForIconURL(const QUrl &url, int desiredSizeIn * for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is * known to use it. * - * \note This may only be used for persistent permission types. Calling it with a non-persistent type will return an invalid object. + * You may use this to pre-grant a permission of a non-persistent type. Doing so will keep the permission in + * the granted (or denied) state until the next time a website with the associated origin requests it. At that point, + * the permission's lifetime will be tied to that specific web page's lifetime, and navigating away will invalidate + * the permission. + * * \since 6.8 * \sa listAllPermissions(), listPermissionsForOrigin(), listPermissionsForPermissionType(), QWebEnginePermission::PermissionType */ @@ -998,11 +1002,6 @@ QWebEnginePermission QWebEngineProfile::queryPermission(const QUrl &securityOrig return QWebEnginePermission(new QWebEnginePermissionPrivate()); } - if (!QWebEnginePermission::isPersistent(permissionType)) { - qWarning() << "Attempting to get permission for permission type" << permissionType << ". Returned object will be in an invalid state."; - return QWebEnginePermission(new QWebEnginePermissionPrivate()); - } - auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, permissionType, nullptr, d->profileAdapter()); return QWebEnginePermission(pvt); } diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 2792a07edf1..2ecac308a8c 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -28,6 +28,11 @@ namespace QtWebEngineCore { +// Extra permission types that don't exist on the Chromium side. +enum class ExtraPermissionType { + POINTER_LOCK = 39, // TODO this exists in Chromium 126, remove after we merge +}; + static QWebEnginePermission::PermissionType toQt(blink::PermissionType type) { switch (type) { @@ -48,6 +53,8 @@ static QWebEnginePermission::PermissionType toQt(blink::PermissionType type) return QWebEnginePermission::PermissionType::Notifications; case blink::PermissionType::LOCAL_FONTS: return QWebEnginePermission::PermissionType::LocalFontsAccess; + case (blink::PermissionType)ExtraPermissionType::POINTER_LOCK: + return QWebEnginePermission::PermissionType::MouseLock; case blink::PermissionType::ACCESSIBILITY_EVENTS: case blink::PermissionType::CAMERA_PAN_TILT_ZOOM: case blink::PermissionType::WINDOW_MANAGEMENT: @@ -97,8 +104,9 @@ static blink::PermissionType toBlink(QWebEnginePermission::PermissionType permis return blink::PermissionType::CLIPBOARD_READ_WRITE; case QWebEnginePermission::PermissionType::LocalFontsAccess: return blink::PermissionType::LOCAL_FONTS; - case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: case QWebEnginePermission::PermissionType::MouseLock: + return (blink::PermissionType)ExtraPermissionType::POINTER_LOCK; + case QWebEnginePermission::PermissionType::MediaAudioVideoCapture: case QWebEnginePermission::PermissionType::Unsupported: LOG(INFO) << "Unexpected unsupported WebEngine permission type: " << static_cast(permissionType); return blink::PermissionType::NUM; @@ -138,6 +146,14 @@ std::string permissionTypeString(QWebEnginePermission::PermissionType permission // e.g. in case we add extra Features that do not correspond to a PermissionType, and // we need to store them. switch (permissionType) { + case QWebEnginePermission::PermissionType::MediaAudioCapture: + return "MediaAudioCapture"; + case QWebEnginePermission::PermissionType::MediaVideoCapture: + return "MediaVideoCapture"; + case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: + return "DesktopAudioVideoCapture"; + case QWebEnginePermission::PermissionType::MouseLock: + return "MouseLock"; case QWebEnginePermission::PermissionType::Notifications: return "Notifications"; case QWebEnginePermission::PermissionType::Geolocation: @@ -146,12 +162,6 @@ std::string permissionTypeString(QWebEnginePermission::PermissionType permission return "ClipboardReadWrite"; case QWebEnginePermission::PermissionType::LocalFontsAccess: return "LocalFontsAccess"; - case QWebEnginePermission::PermissionType::MediaAudioCapture: - return "MediaAudioCapture"; - case QWebEnginePermission::PermissionType::MediaVideoCapture: - return "MediaVideoCapture"; - case QWebEnginePermission::PermissionType::DesktopAudioVideoCapture: - return "DesktopAudioVideoCapture"; default: Q_UNREACHABLE(); return nullptr; @@ -174,6 +184,7 @@ static blink::mojom::PermissionStatus getStatusFromSettings(blink::PermissionTyp PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) : m_requestIdCount(0) + , m_transientWriteCount(0) , m_profileAdapter(profileAdapter) , m_persistence(true) { @@ -195,15 +206,14 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) factory.set_user_prefs(new InMemoryPrefStore); } + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaAudioCapture); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaVideoCapture); + m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MouseLock); m_permissionTypes.push_back(QWebEnginePermission::PermissionType::Notifications); m_permissionTypes.push_back(QWebEnginePermission::PermissionType::Geolocation); m_permissionTypes.push_back(QWebEnginePermission::PermissionType::ClipboardReadWrite); m_permissionTypes.push_back(QWebEnginePermission::PermissionType::LocalFontsAccess); - // Transient, but the implementation relies on them being written to storage - m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaAudioCapture); - m_permissionTypes.push_back(QWebEnginePermission::PermissionType::MediaVideoCapture); - // Register all preference types as keys prior to doing anything else for (auto &type : m_permissionTypes) { prefRegistry->RegisterDictionaryPref(permissionTypeString(type)); @@ -224,23 +234,39 @@ PermissionManagerQt::~PermissionManagerQt() commit(); } -void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state) +void PermissionManagerQt::setPermission( + const QUrl &url, + QWebEnginePermission::PermissionType permissionType, + QWebEnginePermission::State state, + content::RenderFrameHost *rfh) { // Normalize the QUrl to Chromium origin form. const GURL gorigin = toG/service/https://github.com/url(url).DeprecatedGetOriginAsURL(); const QUrl origin = gorigin.is_empty() ? url : toQt(gorigin); if (origin.isEmpty()) return; - if (state == QWebEnginePermission::State::Ask) - ResetPermission(toBlink(permissionType), gorigin, gorigin); - else - setPermission(toBlink(permissionType), gorigin, state == QWebEnginePermission::State::Granted); - blink::mojom::PermissionStatus status = toBlink(state); - if (state != QWebEnginePermission::State::Ask) { + + // Send eligible permissions with an associated rfh to the transient store. When pre-granting + // a non-persistent permission (or pre-granting any permission in AskEveryTime mode), it is allowed + // to pass through the persistent store. It will be moved to the transient store and associated + // with a rfh the next time its status is requested. + bool inTransientStore = rfh && (!QWebEnginePermission::isPersistent(permissionType) || !m_persistence); + + blink::mojom::PermissionStatus blinkStatus = toBlink(state); + if (state == QWebEnginePermission::State::Ask) { + if (inTransientStore) + resetTransientPermission(toBlink(permissionType), gorigin, rfh->GetGlobalFrameToken()); + else + ResetPermission(toBlink(permissionType), gorigin, gorigin); + } else { + if (inTransientStore) + setTransientPermission(toBlink(permissionType), gorigin, state == QWebEnginePermission::State::Granted, rfh->GetGlobalFrameToken()); + else + setPersistentPermission(toBlink(permissionType), gorigin, state == QWebEnginePermission::State::Granted); auto it = m_requests.begin(); while (it != m_requests.end()) { if (it->origin == origin && it->type == permissionType) { - std::move(it->callback).Run(status); + std::move(it->callback).Run(blinkStatus); it = m_requests.erase(it); } else ++it; @@ -249,7 +275,7 @@ void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::P for (const auto &it : m_subscribers) { if (it.second.origin == origin && it.second.type == permissionType) - it.second.callback.Run(status); + it.second.callback.Run(blinkStatus); } if (state == QWebEnginePermission::State::Ask) @@ -267,7 +293,12 @@ void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::P continue; } - blink::mojom::PermissionStatus permissionStatus = GetPermissionStatus(permission, gorigin, GURL()); + blink::mojom::PermissionStatus permissionStatus; + if (inTransientStore) + permissionStatus = toBlink(getPermissionState(url, permissionType, rfh)); + else + permissionStatus = GetPermissionStatus(permission, gorigin, GURL()); + if (permissionStatus == toBlink(state)) { if (permissionStatus == blink::mojom::PermissionStatus::ASK) { answerable = false; @@ -290,8 +321,14 @@ void PermissionManagerQt::setPermission(const QUrl &url, QWebEnginePermission::P } } -QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) +QWebEnginePermission::State PermissionManagerQt::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, + content::RenderFrameHost *rfh) { + if (rfh) { + // Ignore the origin parameter + return toQt(GetPermissionStatusForCurrentDocument(toBlink(permissionType), rfh)); + } + return toQt(GetPermissionStatus(toBlink(permissionType), toGurl(https://github.com/origin), GURL())); } @@ -368,8 +405,35 @@ void PermissionManagerQt::RequestPermissions(content::RenderFrameHost *frameHost blink::mojom::PermissionStatus permissionStatus = getStatusFromSettings(permission, contentsDelegate->webEngineSettings()); if (permissionStatus == blink::mojom::PermissionStatus::ASK) { - permissionStatus = GetPermissionStatus(permission, requestDescription.requesting_origin, GURL()); - if (m_persistence && permissionStatus != blink::mojom::PermissionStatus::ASK) { + const GURL &rorigin = requestDescription.requesting_origin; + + if (!m_persistence) { + answerable = false; + break; + } + + bool inTransientStore = !QWebEnginePermission::isPersistent(toQt(permission)); + if (inTransientStore) { + permissionStatus = getTransientPermissionStatus(permission, rorigin, frameHost->GetGlobalFrameToken()); + + if (permissionStatus != blink::mojom::PermissionStatus::ASK) { + result.push_back(permissionStatus); + continue; + } + + // Fall through to check if permission was pre-granted (and thus landed in the permanent store) + } + + permissionStatus = GetPermissionStatus(permission, rorigin, rorigin); + + if (inTransientStore && permissionStatus != blink::mojom::PermissionStatus::ASK) { + // Move the pre-granted permission to the transient store and associate it with the rfh + ResetPermission(permission, rorigin, rorigin); + setTransientPermission(permission, rorigin, permissionStatus == blink::mojom::PermissionStatus::GRANTED, + frameHost->GetGlobalFrameToken()); + } + + if (permissionStatus != blink::mojom::PermissionStatus::ASK) { // Automatically grant/deny without prompt if already asked once result.push_back(permissionStatus); } else { @@ -428,8 +492,7 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus( // Workaround: local fonts are entirely managed by Chromium, which only calls RequestPermission() _after_ // it's checked whether the permission has been granted. By always returning ASK, we force the request to // come through every time. - if (permission == blink::PermissionType::LOCAL_FONTS - && m_profileAdapter->persistentPermissionsPolicy() == ProfileAdapter::PersistentPermissionsPolicy::AskEveryTime) + if (permission == blink::PermissionType::LOCAL_FONTS && !m_persistence) return blink::mojom::PermissionStatus::ASK; if (requestedPermission.value()) @@ -441,6 +504,8 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForCurren blink::PermissionType permission, content::RenderFrameHost *render_frame_host) { + Q_ASSERT(render_frame_host); + if (permission == blink::PermissionType::CLIPBOARD_READ_WRITE || permission == blink::PermissionType::CLIPBOARD_SANITIZED_WRITE) { WebContentsDelegateQt *delegate = static_cast( @@ -451,10 +516,34 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForCurren return status; } - return GetPermissionStatus( - permission, - render_frame_host->GetLastCommittedOrigin().GetURL(), - render_frame_host->GetLastCommittedOrigin().GetURL()); + permission = toBlink(toQt(permission)); // Filter out merged/unsupported permissions (e.g. clipboard) + if (toQt(permission) == QWebEnginePermission::PermissionType::Unsupported) + return blink::mojom::PermissionStatus::DENIED; + + GURL origin = render_frame_host->GetLastCommittedOrigin().GetURL(); + auto status = blink::mojom::PermissionStatus::ASK; + + bool inTransientStore = !QWebEnginePermission::isPersistent(toQt(permission)) || !m_persistence; + if (inTransientStore) { + status = getTransientPermissionStatus(permission, origin, render_frame_host->GetGlobalFrameToken()); + + if (status != blink::mojom::PermissionStatus::ASK) { + return status; + } + + // Fall through to check if permission was pre-granted (and thus landed in the permanent store) + } + + status = GetPermissionStatus(permission, origin, origin); + + if (inTransientStore && status != blink::mojom::PermissionStatus::ASK) { + // Move the pre-granted permission to the transient store and associate it with the rfh + ResetPermission(permission, origin, origin); + setTransientPermission(permission, origin, status == blink::mojom::PermissionStatus::GRANTED, + render_frame_host->GetGlobalFrameToken()); + } + + return status; } blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForWorker( @@ -462,6 +551,7 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForWorker content::RenderProcessHost *render_process_host, const GURL &url) { + Q_UNUSED(render_process_host); return GetPermissionStatus(permission, url, url); } @@ -517,7 +607,28 @@ void PermissionManagerQt::UnsubscribeFromPermissionStatusChange( LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id; } -void PermissionManagerQt::setPermission( +blink::mojom::PermissionStatus PermissionManagerQt::getTransientPermissionStatus(blink::PermissionType permission, + const GURL& requesting_origin, + content::GlobalRenderFrameHostToken token) +{ + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) + return blink::mojom::PermissionStatus::DENIED; + + if (!m_transientPermissions.contains(token)) + return blink::mojom::PermissionStatus::ASK; + + auto &permissionsForToken = m_transientPermissions[token]; + for (auto p = permissionsForToken.begin(); p != permissionsForToken.end(); ++p) { + if (get<0>(*p) == requesting_origin && get<1>(*p) == permission) { + return get<2>(*p) ? blink::mojom::PermissionStatus::GRANTED : blink::mojom::PermissionStatus::DENIED; + } + } + + return blink::mojom::PermissionStatus::ASK; +} + +void PermissionManagerQt::setPersistentPermission( blink::PermissionType permission, const GURL& requesting_origin, bool granted) @@ -535,4 +646,55 @@ void PermissionManagerQt::setPermission( m_prefService->SchedulePendingLossyWrites(); } +void PermissionManagerQt::setTransientPermission(blink::PermissionType permission, + const GURL& requesting_origin, + bool granted, + content::GlobalRenderFrameHostToken token) +{ + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) + return; + + auto &permissionsForToken = m_transientPermissions[token]; + for (auto &p : permissionsForToken) { + if (get<0>(p) == requesting_origin && get<1>(p) == permission) { + get<2>(p) = granted; + return; + } + } + + permissionsForToken.push_back({requesting_origin, permission, granted}); + + // Render frame hosts get discarded often, so the map will eventualy fill up with junk unless + // periodically cleaned. The number 25 was chosen arbitrarily. + if (++m_transientWriteCount > 25) { + content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, + base::BindOnce([](PermissionManagerQt *p){ + for (auto i = p->m_transientPermissions.begin(); i != p->m_transientPermissions.end(); ++i) { + if (content::RenderFrameHost::FromFrameToken(i->first) == nullptr) { + i = p->m_transientPermissions.erase(i); + } + } + }, this)); + m_transientWriteCount = 0; + } +} + +void PermissionManagerQt::resetTransientPermission(blink::PermissionType permission, + const GURL& requesting_origin, + content::GlobalRenderFrameHostToken token) +{ + const QWebEnginePermission::PermissionType permissionType = toQt(permission); + if (permissionType == QWebEnginePermission::PermissionType::Unsupported) + return; + + auto &permissionsForToken = m_transientPermissions[token]; + for (auto i = permissionsForToken.begin(); i != permissionsForToken.end(); ++i) { + if (get<0>(*i) == requesting_origin && get<1>(*i) == permission) { + permissionsForToken.erase(i); + return; + } + } +} + } // namespace QtWebEngineCore diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index ea69243b5f1..88b777c7faa 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -5,12 +5,15 @@ #define PERMISSION_MANAGER_QT_H #include "base/functional/callback.h" +#include "content/public/browser/global_routing_id.h" #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/render_frame_host.h" #include #include "profile_adapter.h" #include +#include class PrefService; @@ -22,8 +25,13 @@ class PermissionManagerQt : public content::PermissionControllerDelegate PermissionManagerQt(ProfileAdapter *adapter); ~PermissionManagerQt(); - void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state); - QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType); + void setPermission( + const QUrl &origin, + QWebEnginePermission::PermissionType permissionType, + QWebEnginePermission::State state, + content::RenderFrameHost *rfh = nullptr); + QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, + content::RenderFrameHost *rfh = nullptr); QList listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType); void commit(); @@ -84,16 +92,32 @@ class PermissionManagerQt : public content::PermissionControllerDelegate base::RepeatingCallback callback; }; - void setPermission(blink::PermissionType permission, + blink::mojom::PermissionStatus getTransientPermissionStatus(blink::PermissionType permission, + const GURL& requesting_origin, + content::GlobalRenderFrameHostToken token); + + void setPersistentPermission(blink::PermissionType permission, const GURL& requesting_origin, bool granted); + void setTransientPermission(blink::PermissionType permission, + const GURL& requesting_origin, + bool granted, + content::GlobalRenderFrameHostToken token); + + void resetTransientPermission(blink::PermissionType permission, + const GURL& requesting_origin, + content::GlobalRenderFrameHostToken token); + std::vector m_requests; std::vector m_multiRequests; std::vector m_permissionTypes; + std::map>> m_transientPermissions; std::map m_subscribers; content::PermissionControllerDelegate::SubscriptionId::Generator subscription_id_generator_; int m_requestIdCount; + int m_transientWriteCount; std::unique_ptr m_prefService; QPointer m_profileAdapter; bool m_persistence; diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 031ee6dec87..952e5031e0c 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -568,17 +568,16 @@ UserResourceControllerHost *ProfileAdapter::userResourceController() return m_userResourceController.data(); } -void ProfileAdapter::setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state) +void ProfileAdapter::setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, + QWebEnginePermission::State state, content::RenderFrameHost *rfh) { - static_cast(profile()->GetPermissionControllerDelegate())->setPermission(origin, permissionType, state); + static_cast(profile()->GetPermissionControllerDelegate())->setPermission(origin, permissionType, state, rfh); } -QWebEnginePermission::State ProfileAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) +QWebEnginePermission::State ProfileAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, + content::RenderFrameHost *rfh) { - if (persistentPermissionsPolicy() == ProfileAdapter::PersistentPermissionsPolicy::AskEveryTime) - return QWebEnginePermission::State::Ask; - - return static_cast(profile()->GetPermissionControllerDelegate())->getPermissionState(origin, permissionType); + return static_cast(profile()->GetPermissionControllerDelegate())->getPermissionState(origin, permissionType, rfh); } QList ProfileAdapter::listPermissions(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index d0194df99c7..06628632193 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -37,6 +37,10 @@ namespace base { class CancelableTaskTracker; } +namespace content { +class RenderFrameHost; +} + namespace QtWebEngineCore { class UserNotificationController; @@ -172,8 +176,10 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject const QList customUrlSchemes() const; UserResourceControllerHost *userResourceController(); - void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state); - QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType); + void setPermission(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, + QWebEnginePermission::State state, content::RenderFrameHost *rfh = nullptr); + QWebEnginePermission::State getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType, + content::RenderFrameHost *rfh = nullptr); QList listPermissions(const QUrl &origin = QUrl(), QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType::Unsupported); diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index c49331f1e76..807b733e001 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1416,7 +1416,12 @@ void WebContentsAdapter::setPermission(const QUrl &origin, QWebEnginePermission: if (QWebEnginePermission::isPersistent(permissionType)) { // Do not check for initialization in this path so permissions can be set before first navigation Q_ASSERT(m_profileAdapter); - m_profileAdapter->setPermission(origin, permissionType, state); + if (!isInitialized()) { + m_profileAdapter->setPermission(origin, permissionType, state); + } else { + m_profileAdapter->setPermission(origin, permissionType, state, m_webContents.get()->GetPrimaryMainFrame()); + } + return; } @@ -1484,11 +1489,7 @@ void WebContentsAdapter::setPermission(const QUrl &origin, QWebEnginePermission: QWebEnginePermission::State WebContentsAdapter::getPermissionState(const QUrl &origin, QWebEnginePermission::PermissionType permissionType) { - // For now, we just return Ask for transient (a.k.a non-persistent) PermissionTypes - if (!QWebEnginePermission::isPersistent(permissionType)) - return QWebEnginePermission::State::Ask; - - return m_profileAdapter->getPermissionState(origin, permissionType); + return m_profileAdapter->getPermissionState(origin, permissionType, m_webContents.get()->GetPrimaryMainFrame()); } void WebContentsAdapter::grantMediaAccessPermission(const QUrl &origin, WebContentsAdapterClient::MediaRequestFlags flags) @@ -1496,9 +1497,15 @@ void WebContentsAdapter::grantMediaAccessPermission(const QUrl &origin, WebConte CHECK_INITIALIZED(); // Let the permission manager remember the reply. if (flags & WebContentsAdapterClient::MediaAudioCapture) - m_profileAdapter->setPermission(origin, QWebEnginePermission::PermissionType::MediaAudioCapture, QWebEnginePermission::State::Granted); + m_profileAdapter->setPermission(origin, + QWebEnginePermission::PermissionType::MediaAudioCapture, + QWebEnginePermission::State::Granted, + m_webContents.get()->GetPrimaryMainFrame()); if (flags & WebContentsAdapterClient::MediaVideoCapture) - m_profileAdapter->setPermission(origin, QWebEnginePermission::PermissionType::MediaVideoCapture, QWebEnginePermission::State::Granted); + m_profileAdapter->setPermission(origin, + QWebEnginePermission::PermissionType::MediaVideoCapture, + QWebEnginePermission::State::Granted, + m_webContents.get()->GetPrimaryMainFrame()); MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), origin, flags); } diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 2eada9d3c86..d0bbb98564d 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -794,17 +794,24 @@ void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool pr m_viewClient->windowCloseRejected(); } -bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *, +bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *rfh, const url::Origin &security_origin, blink::mojom::MediaStreamType type) { + Q_ASSERT(rfh); switch (type) { case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE: - return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::PermissionType::MediaAudioCapture) - == QWebEnginePermission::State::Granted; + return m_viewClient->profileAdapter()->getPermissionState( + toQt(security_origin), + QWebEnginePermission::PermissionType::MediaAudioCapture, + rfh) + == QWebEnginePermission::State::Granted; case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE: - return m_viewClient->profileAdapter()->getPermissionState(toQt(security_origin), QWebEnginePermission::PermissionType::MediaVideoCapture) - == QWebEnginePermission::State::Granted; + return m_viewClient->profileAdapter()->getPermissionState( + toQt(security_origin), + QWebEnginePermission::PermissionType::MediaVideoCapture, + rfh) + == QWebEnginePermission::State::Granted; default: LOG(INFO) << "WebContentsDelegateQt::CheckMediaAccessPermission: " << "Unsupported media stream type checked " << type; diff --git a/src/webenginequick/doc/src/webengine_permission.qdoc b/src/webenginequick/doc/src/webengine_permission.qdoc index 6912ef4fa2c..efe434dde60 100644 --- a/src/webenginequick/doc/src/webengine_permission.qdoc +++ b/src/webenginequick/doc/src/webengine_permission.qdoc @@ -27,7 +27,7 @@ The \l permissionType enumeration describes all the permission types Qt WebEngine supports. Only some permission types are remembered between browsing sessions; they are \e persistent. Non-persistent permissions query the user every time a - website requests them, and cannot be granted in advance. You can check whether a permission type is persistent at runtime + website requests them. You can check whether a permission type is persistent at runtime using the static method WebEnginePermission::isPersistent(). Persistent permissions are stored inside the active WebEngineProfile, and their lifetime depends on the value of @@ -72,8 +72,7 @@ \omitvalue WebEnginePermission.MouseLock \note Non-persistent permission types are ones that will never be remembered by the underlying storage, and will trigger - a permission request every time a website tries to use them. They can only be denied/granted as they're needed; - any attempts to pre-grant a non-persistent permission will fail. + a permission request every time a website tries to use them. */ /*! @@ -87,7 +86,7 @@ If a permission for the specified \l permissionType and \l origin has already been granted or denied, the return value is WebEnginePermission.Granted, or WebEnginePermission.Denied, respectively. - When this is the first time the permission is requested, or if the \l permissionType is non-persistent, + When this is the first time the permission is requested, the return value is WebEnginePermission.Ask. If the object is in an invalid state, the returned value is WebEnginePermission.Invalid. @@ -131,7 +130,7 @@ Removes the permission from the profile's underlying storage. By default, permissions are stored on disk (except for off-the-record profiles, where permissions are stored in memory and are destroyed with the profile). This means that an already granted/denied permission will not be requested twice, but will get automatically - granted/denied every subsequent time a website requests it. Calling reset() allows the query to be asked + granted/denied every subsequent time a website requests it. Calling reset() allows the query to be displayed again the next time the website requests it. Does nothing when \l isValid evaluates to false. diff --git a/tests/auto/httpserver/data/notification.html b/tests/auto/httpserver/data/notification.html index 1d1e9c4119d..11ebf534e58 100644 --- a/tests/auto/httpserver/data/notification.html +++ b/tests/auto/httpserver/data/notification.html @@ -3,9 +3,7 @@ Desktop Notifications Demo " \ + "

    hello world

    "); + page.setHtml(html, QUrl("about:blank")); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passCreation", QWebEngineScript::MainWorld), + QVariant(1)); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passReady", QWebEngineScript::MainWorld), + QVariant(3)); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passDeferred", QWebEngineScript::MainWorld), + QVariant(5)); + + QString url2 = QStringLiteral("chrome://gpu/"); + page.setUrl(url2); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passCreation", QWebEngineScript::MainWorld), + QVariant(1)); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passReady", QWebEngineScript::MainWorld), + QVariant(2)); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passDeferred", QWebEngineScript::MainWorld), + QVariant(3)); + + QString url3 = QStringLiteral("qrc:/resources/test_iframe_main.html"); + page.setUrl(url3); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passCreation", QWebEngineScript::MainWorld), + QVariant(1)); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passReady", QWebEngineScript::MainWorld), + QVariant(2)); + QTRY_COMPARE(evaluateJavaScriptSyncInWorld(&page, "document.passDeferred", QWebEngineScript::MainWorld), + QVariant(3)); +} + // Try to set TestObject::text to an invalid UTF-16 string. // // See QTBUG-61969. From 518bc89f68f2b792297e056ac85a14e92c5c8680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Wed, 4 Dec 2024 11:15:10 +0100 Subject: [PATCH 221/341] Update Chromium Submodule src/3rdparty a7fd4fa29..207acfe0: * [Backport] Security bug 378725734 (2/2) * [Backport] Security bug 378725734 (1/2) * [Backport] Security bug 378701682 * Disable accelerated_2d_canvas for Intel on Linux * [Backport] Make "key" argument in std::erase_if predicate const. Fixes: QTBUG-131873 Change-Id: Ia9655a02e23e5b85249a073f9315e8daa810322c Reviewed-by: Anu Aliyas --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index dbde2f0b30a..f184ba63e7b 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 131.0.6778.70 +Patched with security patches up to Chromium version: 131.0.6778.108 diff --git a/src/3rdparty b/src/3rdparty index a7fd4fa29e0..207acfe0ee5 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit a7fd4fa29e0bd7cc44aa1c9dd3cf63b1144d1c74 +Subproject commit 207acfe0ee54df6dc713b2df6c60390fd8bf7748 diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 771894a0f63..0c83db99216 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1268,7 +1268,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "131.0.6778.70"; // FIXME: Remember to update + return "131.0.6778.108"; // FIXME: Remember to update } QT_END_NAMESPACE From 223d069a7d07cde3a5df6643bf34cdfb3bc7c6f8 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Mon, 2 Dec 2024 09:46:08 +0100 Subject: [PATCH 222/341] Fix for broken rendering when reparenting view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the dirty scene nodes are updated after reparenting the view, the texture is not ready and as result rendering is broken. The parent change triggers QQuickItem::ItemSceneChange, which in turn calls the RenderWidgetHostViewQtDelegateClient::visualPropertiesChanged(). Even though the window geometry is changed, this wouldn’t lead to generating new texture, as the call to synchronize the visual properties is missing. Invoked synchronizeVisualProperties to avoid such issues. Fixes: QTBUG-131304 Change-Id: I29e6934c33b3fc9f54bfc6e17b29e5ea736cfee0 Reviewed-by: Peter Varga (cherry picked from commit cc9ab80c81af5fb9da878fc7baf8be8310c6436c) Reviewed-by: Qt Cherry-pick Bot --- src/core/render_widget_host_view_qt_delegate_client.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp index ad4da26fcb7..a50eb9a4451 100644 --- a/src/core/render_widget_host_view_qt_delegate_client.cpp +++ b/src/core/render_widget_host_view_qt_delegate_client.cpp @@ -199,8 +199,10 @@ void RenderWidgetHostViewQtDelegateClient::visualPropertiesChanged() bool screenInfoChanged = m_rwhv->updateScreenInfo(); - if (m_viewRectInDips != oldViewRect || m_windowRectInDips != oldWindowRect) + if (m_viewRectInDips != oldViewRect || m_windowRectInDips != oldWindowRect) { m_rwhv->host()->SendScreenRects(); + m_rwhv->synchronizeVisualProperties(std::nullopt); + } if (m_viewRectInDips.size() != oldViewRect.size() || screenInfoChanged) m_rwhv->synchronizeVisualProperties(absl::nullopt); From bd50c00c04ec06fefd9e1013b6bedd3b30ce08b1 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Thu, 12 Sep 2024 14:45:26 +0200 Subject: [PATCH 223/341] Fix wheel scrolling issue As per the current design QtWeEngine combines wheel events when possible to improve latency and perceived performance. The current logic updates pending wheel events with new angleDelta values and positions instead of accumulating it, which causes some events being missed. Since angleDelta values are relative, when combining events, accumulate it. Fixes: QTBUG-123095 Pick-to: 6.7 Change-Id: Idd5438407740f62a4315ea0fe50c24b777ac2ec2 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit cf37b4425cfe94e0b8afcb51a433256a4bfe173d) Reviewed-by: Qt Cherry-pick Bot --- src/core/web_event_factory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index fcf14b45f57..86f10315b2b 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -1633,8 +1633,8 @@ bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, webEvent.SetPositionInScreen(static_cast(ev->globalPosition().x()), static_cast(ev->globalPosition().y())); - webEvent.wheel_ticks_x = ev->angleDelta().x() / static_cast(QWheelEvent::DefaultDeltasPerStep); - webEvent.wheel_ticks_y = ev->angleDelta().y() / static_cast(QWheelEvent::DefaultDeltasPerStep); + webEvent.wheel_ticks_x += ev->angleDelta().x() / static_cast(QWheelEvent::DefaultDeltasPerStep); + webEvent.wheel_ticks_y += ev->angleDelta().y() / static_cast(QWheelEvent::DefaultDeltasPerStep); setBlinkWheelEventDelta(webEvent); return true; From e7c9f9a7ddca8fec772c893422b2eac4b12066d8 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 13 Dec 2024 10:40:42 +0000 Subject: [PATCH 224/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ibb09d18ee7ff4c9bd674eb5ae7ccb3d1a922723a Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 11fed2d41c4..9415a399ba5 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 0011dad7f1f4f0945ae17876146619719b723e4d + ref: ac6425d3eca23da0463d68e61de912079aea17ab required: true ../qtpositioning: - ref: e2012e7529c83953e64e9dbee0cbcb2423960bc3 + ref: a943bda6f483f3faa60127220035023bca17cce8 required: false ../qttools: - ref: 0d6b5c5fe5aa635d59c923c93377da1cd03f3e88 + ref: f2dbab334df5b001bd38d6b29f910f87fdaf5ab6 required: false ../qtwebchannel: - ref: 1449463a3c956468309e53b2924da13d78b9e9dc + ref: 7bf5f5a79bb815bf82d7c1a4fabc99083ff957b5 required: false From 0c58e6581b3aabd0341d00ea7149bd668f6638f8 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Wed, 18 Dec 2024 08:48:02 +0000 Subject: [PATCH 225/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I6d467bab0f35e494716c85b7f5e942d2b3a5d2a6 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 9415a399ba5..3d63467546d 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: ac6425d3eca23da0463d68e61de912079aea17ab + ref: 0c85a2ac966b043b6c29c4bf433117cc8114f27e required: true ../qtpositioning: - ref: a943bda6f483f3faa60127220035023bca17cce8 + ref: b88dda3aaa85dbe88acf8d8ae0910942ea32d0ab required: false ../qttools: - ref: f2dbab334df5b001bd38d6b29f910f87fdaf5ab6 + ref: d027c6050b96cda00025aa9623c7331454d0731b required: false ../qtwebchannel: - ref: 7bf5f5a79bb815bf82d7c1a4fabc99083ff957b5 + ref: 77cac0589a6ce0736a6b3a9f4ca2e5e716669d18 required: false From 3cdf0a2129448a7ac061d1a7eedc60842ce25a64 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 20 Dec 2024 13:07:44 +0000 Subject: [PATCH 226/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I6e2c1b86103076996225ae263b468f192928ad92 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 3d63467546d..f6d6cf7c443 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 0c85a2ac966b043b6c29c4bf433117cc8114f27e + ref: 28955a0dc80b7eb0bf5a02181f458161085a0823 required: true ../qtpositioning: - ref: b88dda3aaa85dbe88acf8d8ae0910942ea32d0ab + ref: 7dabe03d504f020887d454e3f50ce5b01c2ea1f2 required: false ../qttools: - ref: d027c6050b96cda00025aa9623c7331454d0731b + ref: cee47fe6d3034be007bf3e77dfc6c6283a2a4bba required: false ../qtwebchannel: - ref: 77cac0589a6ce0736a6b3a9f4ca2e5e716669d18 + ref: cf2747f89861f9881ecb4e6e957795d094691564 required: false From 30122758f32a3aa8d6097caecf76ffd5d2981b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Thu, 9 Jan 2025 11:22:47 +0100 Subject: [PATCH 227/341] Update Chromium Submodule src/3rdparty 207acfe0..c5287f4d: * [Backport] Security bug 379869752 * [Backport] Security bug 384565015 * [Backport] Security bug 379715150 * [Backport] Security bug 382135228 * [Backport] CVE-2024-12694: Use after free in Compositing * [Backport] CVE-2024-12693: Out of bounds memory access in V8 Fixes: QTBUG-132674 Fixes: QTBUG-132679 Task-number: QTBUG-131166 Change-Id: I6ec9526ad4c9d143a18a97b2cf7eae826d2bb8b7 Reviewed-by: Anu Aliyas --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index f184ba63e7b..c715e74aaba 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 131.0.6778.108 +Patched with security patches up to Chromium version: 131.0.6778.265 diff --git a/src/3rdparty b/src/3rdparty index 207acfe0ee5..c5287f4d6a0 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 207acfe0ee54df6dc713b2df6c60390fd8bf7748 +Subproject commit c5287f4d6a0e64d357e7405599ecb6c7d2d4e5fd diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 0c83db99216..39027b35467 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1268,7 +1268,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "131.0.6778.108"; // FIXME: Remember to update + return "131.0.6778.265"; // FIXME: Remember to update } QT_END_NAMESPACE From 460809c089cfd5dbe0f12ca16f85aa89e928dbcb Mon Sep 17 00:00:00 2001 From: Andreas Eliasson Date: Wed, 11 Dec 2024 13:53:13 +0100 Subject: [PATCH 228/341] Doc: Remove left-over text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The example that this text used to refer to has been removed from Qt 6. Fixes: QTBUG-131896 Pick-to: 6.7 6.5 Change-Id: I4abd12028880267bbc7d8eb707841af30b04e84f Reviewed-by: Michael BrĂ¼ning (cherry picked from commit 5ff1c88091befd0d9c3ffc1e6ecdd71ff709c0aa) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit b3fee7ef9aa46a56ad26b1fa4ee036dd568a03fa) --- src/core/doc/src/qtwebengine-features.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/doc/src/qtwebengine-features.qdoc b/src/core/doc/src/qtwebengine-features.qdoc index c7221677cd1..1dc58a133ea 100644 --- a/src/core/doc/src/qtwebengine-features.qdoc +++ b/src/core/doc/src/qtwebengine-features.qdoc @@ -457,7 +457,7 @@ WebEngineView::javaScriptDialogRequested(), WebEngineView::colorDialogRequested(), WebEngineView::fileDialogRequested(), and - WebEngineView::formValidationMessageRequested() signals. For an example, + WebEngineView::formValidationMessageRequested() signals. \section1 PDF File Viewing From 7e1eb0a370f2ce5031ef2dfbf9da3648ebc5edad Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Mon, 6 Jan 2025 15:47:42 +0100 Subject: [PATCH 229/341] qwebengine_convert_dict: fix word length limit The conversion tool had an implicit limit of 128 bytes, which was too short for the entries in the supplied Bengali dic file. Instead we read into a dynamically sized std::string. Fixes: QTBUG-132564 Change-Id: I250904ef809ccbd9a110e87cd6b940c401f71f78 Reviewed-by: Anu Aliyas (cherry picked from commit 95e926d3b9452d38289e3832e3e044c08b4a7e32) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 9c4230280d78c1f2e4f5aae20fd0c89b5d932800) --- src/core/tools/qwebengine_convert_dict/main.cpp | 12 ++++++------ tests/auto/widgets/spellchecking/dict/en-US.dic | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/tools/qwebengine_convert_dict/main.cpp b/src/core/tools/qwebengine_convert_dict/main.cpp index 17dd3eec6aa..8b82b930f5d 100644 --- a/src/core/tools/qwebengine_convert_dict/main.cpp +++ b/src/core/tools/qwebengine_convert_dict/main.cpp @@ -93,20 +93,20 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words, int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD]; - static const int buf_size = 128; - char buf[buf_size]; for (size_t i = 0; i < org_words.size(); i++) { - int affix_matches = iter.Advance(buf, buf_size, affix_ids); + auto buf_size = org_words[i].first.size() + 1; + std::string buf(buf_size, '\0'); + int affix_matches = iter.Advance(buf.data(), buf_size, affix_ids); if (affix_matches == 0) { out << "Found the end before we expected\n"; return false; } - if (org_words[i].first != buf) { + if (buf.back() != '\0' || buf.compare(0, buf_size - 1, org_words[i].first) != 0) { out << "Word does not match!\n" << " Index: " << i << "\n" << " Expected: " << QString::fromStdString(org_words[i].first) << "\n" - << " Actual: " << QString::fromUtf8(buf) << "\n"; + << " Actual: " << QString::fromStdString(buf) << "\n"; return false; } @@ -118,7 +118,7 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words, [](int a, int b) { return a == b; })) { out << "Affixes do not match!\n" << " Index: " << i << "\n" - << " Word: " << QString::fromUtf8(buf) << "\n" + << " Word: " << QString::fromStdString(buf) << "\n" << " Expected: " << expectedAffixes << "\n" << " Actual: " << actualAffixes << "\n"; return false; diff --git a/tests/auto/widgets/spellchecking/dict/en-US.dic b/tests/auto/widgets/spellchecking/dict/en-US.dic index 63e9164ccd5..93c7198a385 100644 --- a/tests/auto/widgets/spellchecking/dict/en-US.dic +++ b/tests/auto/widgets/spellchecking/dict/en-US.dic @@ -10,3 +10,4 @@ she/Q they/Q we/Q you/Q +very-long-word-to-test-old-fixed-size-buffer-limit-QTBUG-132564-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Q From 00ab2112377d579d80bad289df8a15cb976eaf6b Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 14 Nov 2024 17:14:24 +0100 Subject: [PATCH 230/341] CMake: Create separate SBOM documents for QtWebEngine and QtPdf Because QtWebEngine and QtPdf can be installed as separate components in the online installer, as well as because they are shipped as separate packages in Boot2Qt, create two separate SBOM documents for them. Fixes: QTBUG-128893 Task-number: QTBUG-122899 Task-number: QTBUG-129901 Change-Id: Icdcc8766e3338304ae7d85fa777ca74a59c14b06 Reviewed-by: Alexey Edelev (cherry picked from commit a29566090106af219f3b19b342ef5005e130b336) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit f19df5e7c81041a4f80e03c8e2310231a1b79d35) --- CMakeLists.txt | 3 +++ src/CMakeLists.txt | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7388dd55bd8..c647140e604 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,4 +45,7 @@ if(MATRIX_BUILD AND NOT MATRIX_SUBBUILD AND NOT QT_SUPERBUILD) return() endif() +# Don't auto create the SBOM projects, they will be manually created +# for each sub-project. +set(QT_SKIP_SBOM_AUTO_PROJECT TRUE) qt_build_repo() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eb36e70539d..c58bccb8d05 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,6 +63,8 @@ cmake_minimum_required(VERSION ${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_WEB # MODULES ## +# Use implicit PROJECT_NAME. +qt_internal_sbom_begin_qt_repo_project() if(QT_FEATURE_qtwebengine_core_build) add_subdirectory(core) add_subdirectory(process) @@ -73,7 +75,9 @@ endif() if(QT_FEATURE_qtwebengine_quick_build) add_subdirectory(webenginequick) endif() +qt_internal_sbom_end_qt_repo_project() +qt_internal_sbom_begin_qt_repo_project(SBOM_PROJECT_NAME QtPdf) if(QT_FEATURE_qtpdf_build) add_subdirectory(pdf) # keep log order, pdf build after webengine @@ -98,6 +102,11 @@ endif() # NINJA PROJECT ## +# No SBOM information will be generated for any targets created past this point in the file +# or any add_subdirectory calls. For the external project GN, we'll have to come up with some +# additional API. +qt_internal_sbom_end_qt_repo_project() + set(installDir ${PROJECT_BINARY_DIR}/install) if(NOT Ninja_FOUND) From 0beb588245230f5d4034d475d279cac6e4806056 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 17 Jan 2025 19:55:56 +0000 Subject: [PATCH 231/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Idf5b673ec7df8c024ec0d6add07a5ab4059b67be Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index f6d6cf7c443..7fc7934cd49 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 28955a0dc80b7eb0bf5a02181f458161085a0823 + ref: 2f13709a649bfbaf17f619da7f5f04d0641e08fb required: true ../qtpositioning: - ref: 7dabe03d504f020887d454e3f50ce5b01c2ea1f2 + ref: 4ebea88f0ffc2bb1c43ffae0097cfcb9c9c41f1b required: false ../qttools: - ref: cee47fe6d3034be007bf3e77dfc6c6283a2a4bba + ref: 1500ab1758e8bb37f94ec788aa89b7aa03f82533 required: false ../qtwebchannel: - ref: cf2747f89861f9881ecb4e6e957795d094691564 + ref: 1d9b0323b70e83461aedec08093da03aa48fcf8a required: false From 54ecf0cc289cb5f71a8ad63ac4a778e4c46ce0fc Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 20 Jan 2025 07:35:47 +0000 Subject: [PATCH 232/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I34827dcb4af62e1b2fcd5710ab16c4165720fe3b Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 7fc7934cd49..3bd4179f484 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 2f13709a649bfbaf17f619da7f5f04d0641e08fb + ref: d9d4c8c948b21e2ff96d5e90ab7bf78f77258329 required: true ../qtpositioning: - ref: 4ebea88f0ffc2bb1c43ffae0097cfcb9c9c41f1b + ref: f9f194cf33ed5ebe9eb0dd6b79feeb21838037a2 required: false ../qttools: - ref: 1500ab1758e8bb37f94ec788aa89b7aa03f82533 + ref: d2a55ba82b692c9403fe0df95bd30591c154cfc8 required: false ../qtwebchannel: - ref: 1d9b0323b70e83461aedec08093da03aa48fcf8a + ref: 0a0648ea62f5359082c88240cba7842a6bf1d78b required: false From 91c0e422414070e778bdb672bd436436f98e0343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Mon, 6 Jan 2025 15:58:02 +0100 Subject: [PATCH 233/341] Fix scaling and positioning of popup windows in WebEngineQuick When using QQuickItem::scale to scale up the UI, popups were misplaced when a WebEngineView was a child of this scaled item. After trying different approaches similar to other popups in Qt Quick, it turned out that the approach that we use to handle rotation can also be applied to handle scaled items. This also adds the handling of rotation and scale of items higher up the item tree. Fixes: QTBUG-130608 Change-Id: If6b6c39113d0f07146d633e9d11d0745f6b0ff15 Reviewed-by: Michal Klocek (cherry picked from commit a245afb450d49f4a5f77742fb39f31c44549b134) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 7044fe6887adb198a8b57dee5e62a41f8042c7ac) Reviewed-by: Anu Aliyas (cherry picked from commit 8987a7b480dbc27f20fd042a8a83c2d1741c329a) --- ...dget_host_view_qt_delegate_quickwindow.cpp | 44 +++++++++++++++---- ...dget_host_view_qt_delegate_quickwindow_p.h | 2 +- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp index 090b0928109..b507d760b79 100644 --- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp +++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp @@ -7,6 +7,25 @@ namespace QtWebEngineCore { +struct ItemTransform { + qreal rotation = 0.; + qreal scale = 1.; +}; + +// Helper function to calculate the cumulative rotation and scale. +static inline struct ItemTransform getTransformValuesFromItemTree(QQuickItem *item) +{ + struct ItemTransform returnValue; + + while (item) { + returnValue.rotation += item->rotation(); + returnValue.scale *= item->scale(); + item = item->parentItem(); + } + + return returnValue; +} + static inline QPoint getOffset(QQuickItem *item) { // get parent window (scene) offset @@ -32,7 +51,7 @@ static inline QPointF transformPoint(const QPointF &point, const QTransform &tra RenderWidgetHostViewQtDelegateQuickWindow::RenderWidgetHostViewQtDelegateQuickWindow( RenderWidgetHostViewQtDelegateItem *realDelegate, QWindow *parent) - : QQuickWindow(parent), m_realDelegate(realDelegate), m_virtualParent(nullptr), m_rotated(false) + : QQuickWindow(parent), m_realDelegate(realDelegate), m_virtualParent(nullptr), m_transformed(false) { setFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); realDelegate->setParentItem(contentItem()); @@ -56,9 +75,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::setVirtualParent(QQuickItem *vir // chromium knows nothing about local transformation void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) { - m_rotated = m_virtualParent->rotation() > 0 || m_virtualParent->parentItem()->rotation() > 0; - if (m_rotated) { - // code below tries to cover the case where webengine view is rotated, + // To decide if there is a scale or rotation, we check it from the transfrom + // to also cover the case where the scale is higher up in the item tree. + QTransform transform = m_virtualParent->itemTransform(nullptr, nullptr); + m_transformed = transform.isRotating() || transform.isScaling(); + + if (m_transformed) { + // code below tries to cover the case where webengine view is rotated or scaled, // the code assumes the rotation is in the form of 90, 180, 270 degrees // to archive that we keep chromium unaware of transformation and we transform // just the window content. @@ -67,7 +90,6 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) QPointF offset = m_virtualParent->mapFromScene(QPoint(0, 0)); offset = m_virtualParent->mapToGlobal(offset); // get local transform - QTransform transform = m_virtualParent->itemTransform(nullptr, nullptr); QPointF tl = transformPoint(rect.topLeft(), transform, offset, m_virtualParent); QPointF br = transformPoint(rect.bottomRight(), transform, offset, m_virtualParent); QRectF popupRect(tl, br); @@ -80,7 +102,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) m_realDelegate->setX(-rect.width() / 2.0 + geometry().width() / 2.0); m_realDelegate->setY(-rect.height() / 2.0 + geometry().height() / 2.0); m_realDelegate->setTransformOrigin(QQuickItem::Center); - m_realDelegate->setRotation(m_virtualParent->parentItem()->rotation()); + + // We need to read the values for scale and rotation from the item tree as it is not + // sufficient to only use the virtual parent item and its parent for the case that the + // scale or rotation is applied higher up the item tree. + struct ItemTransform transformValues = getTransformValuesFromItemTree(m_virtualParent); + m_realDelegate->setRotation(transformValues.rotation); + m_realDelegate->setScale(transformValues.scale); } else { QRect geometry(rect); geometry.moveTo(rect.topLeft() - getOffset(m_virtualParent)); @@ -93,13 +121,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) void RenderWidgetHostViewQtDelegateQuickWindow::Resize(int width, int height) { - if (!m_rotated) + if (!m_transformed) QQuickWindow::resize(width, height); } void RenderWidgetHostViewQtDelegateQuickWindow::MoveWindow(const QPoint &screenPos) { - if (!m_rotated) + if (!m_transformed) QQuickWindow::setPosition(screenPos - getOffset(m_virtualParent)); } diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h index 3559bd2f080..691fceb5257 100644 --- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h +++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h @@ -49,7 +49,7 @@ class RenderWidgetHostViewQtDelegateQuickWindow : public QQuickWindow , public W QPointer m_realDelegate; QQuickItem *m_virtualParent; QRect m_rect; - bool m_rotated; + bool m_transformed; }; } // namespace QtWebEngineCore From f2001e30f9c4d6d2045c531addde6e217526485e Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 20 Jan 2025 13:30:20 +0100 Subject: [PATCH 234/341] Fix conflicting rtti GN configs for Windows build no_rtti is a default compiler config in Chromium. We enable rtti for QtWebEngineCore build on Windows. Remove the no_rtti config first to silence warning: cl : Command line warning D9025 : overriding '/GR-' with '/GR' Change-Id: I0ccf592095e39a7d83dd2d959ab50aa0c0aca097 Reviewed-by: Michal Klocek Reviewed-by: Moss Heim (cherry picked from commit 9458886d3490f0981021d98e5ec276bccce47ad7) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 6c2b6c12c8bf94021ab7ab8df509b5f7179f117b) --- src/core/configure/BUILD.root.gn.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in index 0e913f1d44b..42b06d4f7b7 100644 --- a/src/core/configure/BUILD.root.gn.in +++ b/src/core/configure/BUILD.root.gn.in @@ -170,6 +170,7 @@ shared_library("QtWebEngineCore") { } if (is_win) { + configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] data_deps += [ ":QtWebEngineCoreSandbox" ] } From b744f9189f45b7fbf822e8f9357a874ec1b7ae8d Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 20 Jan 2025 16:13:51 +0100 Subject: [PATCH 235/341] CMake: Only create sbom documents when the respective feature is on Previously if -DFEATURE_qtwebengine_build=OFF was passed to configure, we still installed an almost empty sbom document for the qtwebengine project. Same for qtpdf. Guard the creation and installation of the sbom documents with the appropriate feature checks, for both QtWebEngine and QtPdf. Amends a29566090106af219f3b19b342ef5005e130b336 Fixes: QTBUG-128893 Task-number: QTBUG-122899 Task-number: QTBUG-129901 Change-Id: If123dfcae9408f1d559939f885009f920c09eac6 Reviewed-by: Michal Klocek Reviewed-by: Moss Heim (cherry picked from commit 74e88184d11514288aff41851de71ee0b55641cb) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit ba890f909a5ed1440b55dac17d1fda49a4dfe07e) Reviewed-by: Joerg Bornemann --- src/CMakeLists.txt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c58bccb8d05..789f15bc630 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,8 +63,10 @@ cmake_minimum_required(VERSION ${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_WEB # MODULES ## -# Use implicit PROJECT_NAME. -qt_internal_sbom_begin_qt_repo_project() +if(QT_FEATURE_qtwebengine_build) + # Use implicit PROJECT_NAME. + qt_internal_sbom_begin_qt_repo_project() +endif() if(QT_FEATURE_qtwebengine_core_build) add_subdirectory(core) add_subdirectory(process) @@ -75,10 +77,12 @@ endif() if(QT_FEATURE_qtwebengine_quick_build) add_subdirectory(webenginequick) endif() -qt_internal_sbom_end_qt_repo_project() +if(QT_FEATURE_qtwebengine_build) + qt_internal_sbom_end_qt_repo_project() +endif() -qt_internal_sbom_begin_qt_repo_project(SBOM_PROJECT_NAME QtPdf) if(QT_FEATURE_qtpdf_build) + qt_internal_sbom_begin_qt_repo_project(SBOM_PROJECT_NAME QtPdf) add_subdirectory(pdf) # keep log order, pdf build after webengine if(QT_FEATURE_qtwebengine_core_build) @@ -105,7 +109,9 @@ endif() # No SBOM information will be generated for any targets created past this point in the file # or any add_subdirectory calls. For the external project GN, we'll have to come up with some # additional API. -qt_internal_sbom_end_qt_repo_project() +if(QT_FEATURE_qtpdf_build) + qt_internal_sbom_end_qt_repo_project() +endif() set(installDir ${PROJECT_BINARY_DIR}/install) From 200f19cf94380039130bc9e056e1f2a4460591ec Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 27 Jan 2025 08:54:51 +0000 Subject: [PATCH 236/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I7dccab03a6dbe37d88ca106e65c255456dc31dcc Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 3bd4179f484..96ab7fdd72b 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: d9d4c8c948b21e2ff96d5e90ab7bf78f77258329 + ref: 6aa1a9772709feba9761574e607a4d66fc0215de required: true ../qtpositioning: - ref: f9f194cf33ed5ebe9eb0dd6b79feeb21838037a2 + ref: 8c21d8b72c25dd9cf1631f4fb9935fa075e7dd41 required: false ../qttools: - ref: d2a55ba82b692c9403fe0df95bd30591c154cfc8 + ref: bb53cfd19768fdf38cee17ce17e4e67857ee3802 required: false ../qtwebchannel: - ref: 0a0648ea62f5359082c88240cba7842a6bf1d78b + ref: ed8af9fd6da84e75a414f7d683456b6281e7b617 required: false From 8ff002c1091f6499f7e2250766239d63ff35cfd7 Mon Sep 17 00:00:00 2001 From: Jani Heikkinen Date: Thu, 23 Jan 2025 09:03:18 +0000 Subject: [PATCH 237/341] Bump version to 6.8.3 Change-Id: I3c888b2073774042aa5a2420ad6be92893cd95dc Reviewed-by: Qt Submodule Update Bot --- .cmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cmake.conf b/.cmake.conf index 02007225629..81507b42a70 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -1,4 +1,4 @@ -set(QT_REPO_MODULE_VERSION "6.8.2") +set(QT_REPO_MODULE_VERSION "6.8.3") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_WEBENGINE "3.19") set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1") From 7a4b0f128baf2c7d5bc92ecd5742c8d848e7a3ea Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Tue, 28 Jan 2025 11:22:00 +0000 Subject: [PATCH 238/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ibf6555c646b042c91c55e825d63e5b093497d947 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 96ab7fdd72b..25d2b4fb594 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 6aa1a9772709feba9761574e607a4d66fc0215de + ref: ca9ff6bd040372c91b2b493d89bb58b231a82afc required: true ../qtpositioning: - ref: 8c21d8b72c25dd9cf1631f4fb9935fa075e7dd41 + ref: be59c8f65b84f9c008f45bf8110668c6eab0d9a5 required: false ../qttools: - ref: bb53cfd19768fdf38cee17ce17e4e67857ee3802 + ref: 2d2f9c09fafba1bcf50dfb5eb4c82351a5610997 required: false ../qtwebchannel: - ref: ed8af9fd6da84e75a414f7d683456b6281e7b617 + ref: ebd28d7bab9237c661b88d4fca971302cf7ec860 required: false From 60f8c89e9cdf5fff032d213d84315c191fca39c6 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Thu, 9 Jan 2025 12:10:27 +0100 Subject: [PATCH 239/341] Add sync headers dependency to recursvie ninja run During chromium part build we do generate some mocs which can include headers synced by syncqt. Chromium part is built before linking the WebEngineCore and it can happen than syncqt was not executed yet as there was not direct dependency on sync headers task, only WebEngineCore target had this dependency. Add missing direct dependency. Change-Id: I16a29764805cdfcf32776c9f1cb8318704164b93 Reviewed-by: Alexey Edelev (cherry picked from commit e372bb3dad121465d61cc15de18c06c85f938072) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 694eab07885772b465555b75e1f714ce4c86d558) --- cmake/Functions.cmake | 7 ++++--- src/core/CMakeLists.txt | 1 + src/pdf/CMakeLists.txt | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 93be1725e9a..f957bea42e9 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -1122,7 +1122,7 @@ endmacro() function(add_ninja_command) cmake_parse_arguments(PARSE_ARGV 0 arg - "" "TARGET;BUILDDIR;MODULE" "OUTPUT;BYPRODUCTS" + "" "TARGET;BUILDDIR;MODULE" "OUTPUT;BYPRODUCTS;DEPENDS" ) _qt_internal_validate_all_args_are_parsed(arg) @@ -1142,7 +1142,7 @@ function(add_ninja_command) USES_TERMINAL VERBATIM COMMAND_EXPAND_LISTS - DEPENDS run_${arg_MODULE}_NinjaReady + DEPENDS run_${arg_MODULE}_NinjaReady ${arg_DEPENDS} ) endfunction() @@ -1172,7 +1172,7 @@ endfunction() function(add_gn_build_artifacts_to_target) cmake_parse_arguments(PARSE_ARGV 0 arg - "" "CMAKE_TARGET;NINJA_TARGET;BUILDDIR;MODULE;COMPLETE_STATIC;NINJA_STAMP;NINJA_DATA_STAMP" "" + "" "CMAKE_TARGET;NINJA_TARGET;BUILDDIR;MODULE;COMPLETE_STATIC;NINJA_STAMP;NINJA_DATA_STAMP;DEPENDS" "" ) _qt_internal_validate_all_args_are_parsed(arg) @@ -1200,6 +1200,7 @@ function(add_gn_build_artifacts_to_target) OUTPUT ${stamps} BUILDDIR ${arg_BUILDDIR}/${config}/${arch} MODULE ${arg_MODULE} + DEPENDS ${arg_DEPENDS} ) add_dependencies(run_${arg_MODULE}_NinjaDone ${target}) set_target_properties(${arg_CMAKE_TARGET} PROPERTIES diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index de52226456a..3d871f65205 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -597,6 +597,7 @@ add_gn_build_artifacts_to_target( CMAKE_TARGET WebEngineCore NINJA_TARGET QtWebEngineCore MODULE core + DEPENDS WebEngineCore_sync_headers BUILDDIR ${buildDir} COMPLETE_STATIC FALSE NINJA_STAMP QtWebEngineCore.stamp diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt index fcb5f1186cc..95931a261f8 100644 --- a/src/pdf/CMakeLists.txt +++ b/src/pdf/CMakeLists.txt @@ -253,6 +253,7 @@ add_gn_build_artifacts_to_target( CMAKE_TARGET Pdf NINJA_TARGET QtPdf MODULE pdf + DEPENDS Pdf_sync_headers BUILDDIR ${buildDir} COMPLETE_STATIC TRUE NINJA_STAMP QtPdf.stamp From f6ba4e58ece5ea5873dbce4d5bc19c788a8823ab Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Wed, 29 Jan 2025 08:07:51 +0000 Subject: [PATCH 240/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I1455381f5ec728ab0123d368c1f183c069efe68e Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 25d2b4fb594..f2ecdedc7b7 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: ca9ff6bd040372c91b2b493d89bb58b231a82afc + ref: fcd48036a29428a333e5ee0a0301994edd5025fa required: true ../qtpositioning: - ref: be59c8f65b84f9c008f45bf8110668c6eab0d9a5 + ref: 4637d0a4e9b91f6f525d1ed21363baadc291d61f required: false ../qttools: - ref: 2d2f9c09fafba1bcf50dfb5eb4c82351a5610997 + ref: f66065751b537bb3fa3cc0957759dcd248ded716 required: false ../qtwebchannel: - ref: ebd28d7bab9237c661b88d4fca971302cf7ec860 + ref: 96ba65c4ff8e02b742e68c5e5ecc8d46c37f210f required: false From 17d252f02da75a1e30349a2b3919b00a1a295bea Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 30 Jan 2025 08:14:57 +0000 Subject: [PATCH 241/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I0692fff9a384b9408aeeca0de6605dc523afc082 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index f2ecdedc7b7..6b4c0c5a26f 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: fcd48036a29428a333e5ee0a0301994edd5025fa + ref: 72d314d1e51709a71d856fa0bf1eb0d146013f8e required: true ../qtpositioning: - ref: 4637d0a4e9b91f6f525d1ed21363baadc291d61f + ref: d439b858a902e16f198a973ac605bdc13c171ad7 required: false ../qttools: - ref: f66065751b537bb3fa3cc0957759dcd248ded716 + ref: 53798d1ceb1ff9fa4fc1b291b49f656929f8059d required: false ../qtwebchannel: - ref: 96ba65c4ff8e02b742e68c5e5ecc8d46c37f210f + ref: fcfe7c1a7d3f841111bb6e5409411e46d0f5b116 required: false From d6bc753576b506701c41839ac7d4fe2b77a6f8e5 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Fri, 10 Jan 2025 14:21:50 +0100 Subject: [PATCH 242/341] Use the reduced User-Agent header User-Agent reduction minimizes the identifying information shared in the User-Agent string, which may be used for passive fingerprinting. Chromium already uses the reduced User-Agent. With this change, webengine also uses the reduced User-Agent for improved security. Fixes: QTBUG-132411 Change-Id: Idc3314ca1744bc95e20ba2b23859093739146d58 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 208fe51a84a173404efa37aec40f08199b653701) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 145a30d433cd06ff21f8864b5afe094ce401cdf0) --- src/core/content_browser_client_qt.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 0634a5a395d..44d8ce0e278 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -32,6 +32,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" +#include "base/version_info/version_info.h" #include "ipc/ipc_channel_proxy.h" #include "extensions/buildflags/buildflags.h" #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" @@ -977,8 +978,8 @@ std::string ContentBrowserClientQt::getUserAgent() { // Mention the Chromium version we're based on to get passed stupid UA-string-based feature detection (several WebRTC demos need this) return content::BuildUserAgentFromProduct("QtWebEngine/" + std::string(qWebEngineVersion()) - + " Chrome/" - + std::string(qWebEngineChromiumVersion())); + + " Chrome/" + version_info::GetMajorVersionNumber() + + ".0.0.0"); } blink::UserAgentMetadata ContentBrowserClientQt::GetUserAgentMetadata() From 2c782af9655b58e954c3fb37ee1bac9ad0529102 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Wed, 18 Dec 2024 16:15:46 +0100 Subject: [PATCH 243/341] Do not warn needlessly about missing dictionaries directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The warning message will be displayed only when trying to enable spell checking and the dictionary path is empty. The function has been modified so that it doesn’t perform any action if the new state and the current state are the same. Fixes: QTBUG-131969 Change-Id: Ib69422cdd0285392a6fda967012f9779c950401d Reviewed-by: Michael BrĂ¼ning (cherry picked from commit a069e0bba44e59c9041205a5432b736bfd980be0) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 7f05c72cb05db9475c1258eddf66f19025fc6928) --- src/core/pref_service_adapter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index 2512c3c44f3..7a7abf2c48c 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -205,7 +205,10 @@ QStringList PrefServiceAdapter::spellCheckLanguages() const void PrefServiceAdapter::setSpellCheckEnabled(bool enabled) { - if (!WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES, true).empty()) { + if (enabled == m_prefService->GetBoolean(spellcheck::prefs::kSpellCheckEnable)) + return; + + if (!WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES, enabled).empty()) { m_prefService->SetBoolean(spellcheck::prefs::kSpellCheckEnable, enabled); m_prefService->SchedulePendingLossyWrites(); } From 84dd8008b637e2bb9ec723ebc2343ba590ce4ed2 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 30 Jan 2025 16:27:22 +0100 Subject: [PATCH 244/341] Fix flaky tst_QWebEngineProfile::clearDataFromCache on Windows Wait for dereferencing http cache entries. Change-Id: Iab3e9a56fa4008f60552f737b16b9716d69c376e Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit a807b591a0e367ea9645448338edc3c2b6737f64) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 6f3265cf38f4832dab0b9a7e43b3d20724ec8510) --- .../widgets/qwebengineprofile/tst_qwebengineprofile.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index d9997d50c36..866daa77305 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -205,6 +205,12 @@ void tst_QWebEngineProfile::clearDataFromCache() // Wait for GET /favicon.ico QTRY_COMPARE(serverSpy.size(), 3); +#if defined(Q_OS_WIN) + // FIXME: A http cache entry might be still in use after all the wait above and this blocks + // clearing the http cache. Find a better way to wait for cache entries. + QTest::qWait(500); +#endif + QVERIFY(cacheDir.exists("Cache")); qint64 sizeBeforeClear = totalSize(cacheDir); QCOMPARE_GT(sizeBeforeClear, 0); From a3e47b5b10e2f90fc465042d92d7331d2a047028 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 31 Jan 2025 12:50:15 +0100 Subject: [PATCH 245/341] Fix flaky WebEngineViewLoadUrl::test_stopStatus The test fail was reproducible on arm64 macOS but it could happen on any platform if it is fast enough. The value of WebEngineView.url property is just not reliable when a page's load status is changed to LoadStoppedStatus. If the navigation events are processed fast enough the navigation request can be committed right before we call stop() on the view. If the request is committed it has already updated the url of the current page. As a fix just ignore the current page url after calling stop in the test. Change-Id: I9605696dfb1a0e15343afc384fcc2097cfa2994a Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit ccff8d6d518c402759725723e34b5302fdbcf9e1) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 8ba624747ab9f29a9fdf059b9c939c91712b0c96) --- tests/auto/quick/qmltests/data/tst_loadUrl.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml index 757343703c5..e43c8d5d983 100644 --- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml +++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml @@ -265,7 +265,6 @@ TestWebEngineView { compare(loadRequest.status, WebEngineView.LoadStoppedStatus); compare(loadRequest.status, WebEngineLoadingInfo.LoadStoppedStatus); compare(loadRequest.url, stoppedUrl); - compare(loadRequest.activeUrl, initialUrl); webEngineView.clear(); } From cca5fb10472ae6528c1a7bccbd48de395bfd4400 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 9 Jan 2025 17:04:23 +0100 Subject: [PATCH 246/341] Do not try to import native textures with offscreen platform plugin Native texture import implementations rely on platform specific APIs which may not be working with offscreen platform plugin. Fixes: QTBUG-132682 Change-Id: I6d68dacaa54fa42c8464c3ba2d29a879dad8a1e5 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit a9944c7c0a704ded9fcfb9365688c240dc1303e0) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 13bddc733f435167ae9f7140c7b3752d1687fd89) --- src/core/compositor/native_skia_output_device_opengl.cpp | 1 + src/core/render_widget_host_view_qt_delegate_item.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index f1ae3651089..a65cb2dc155 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -231,6 +231,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te #if defined(USE_OZONE) QOpenGLContext *glContext = QOpenGLContext::currentContext(); + Q_ASSERT(glContext); auto glFun = glContext->functions(); GLuint glTexture = 0; diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp index 6ece45f9bb2..94f786d1ca8 100644 --- a/src/core/render_widget_host_view_qt_delegate_item.cpp +++ b/src/core/render_widget_host_view_qt_delegate_item.cpp @@ -14,6 +14,8 @@ #include #endif +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWidgetHostViewQtDelegateClient *client, bool isPopup) @@ -368,6 +370,12 @@ QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, U if (!comp) return oldNode; + if (comp->type() == Compositor::Type::Native + && QGuiApplication::platformName() == "offscreen"_L1) { + comp->swapFrame(); + return oldNode; + } + QQuickWindow *win = QQuickItem::window(); QSGImageNode *node = nullptr; From 3488e143b2b145fec22fbbbd8875709aa9ae2ec5 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 27 Jan 2025 09:47:42 +0100 Subject: [PATCH 247/341] Add float QImage format support to toQImage Change-Id: I759c02641bbb519135375054465795e7f3b1347f Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 4c8ec6a5d35a773a2c4b358a4f150acf798b23ab) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit c5c5c624c7df52b24814a5b191028c6c35633126) --- src/core/type_conversion.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index 0a3c2489c45..1d821df8c1a 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -23,8 +23,6 @@ QImage toQImage(const SkBitmap &bitmap) QImage image; switch (bitmap.colorType()) { case kUnknown_SkColorType: - case kRGBA_F16_SkColorType: - case kRGBA_F32_SkColorType: case kRGBA_F16Norm_SkColorType: case kR8G8_unorm_SkColorType: case kA16_float_SkColorType: @@ -137,6 +135,36 @@ QImage toQImage(const SkBitmap &bitmap) break; } break; + case kRGBA_F16_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kUnpremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA16FPx4); + break; + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBX16FPx4); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA16FPx4_Premultiplied); + break; + } + break; + case kRGBA_F32_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kUnpremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA32FPx4); + break; + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBX32FPx4); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA32FPx4_Premultiplied); + break; + } + break; } return image; } From 3493538f94029b04ea9a43c44482937af4bdc423 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 20 Jan 2025 10:51:37 +0100 Subject: [PATCH 248/341] Fix discarded QFile::open() results Also validate return value of QIODevice::open() and QBuffer::open() calls. Change-Id: I71ea58f62cab5aafdd2b4eca217394dddf0033cd Reviewed-by: Michal Klocek Reviewed-by: Moss Heim (cherry picked from commit 90fb632348ea5226a9aefd1e3707f112b80aa6b9) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 73eb4a364eac89454dcf078ec4fecb4f69271808) Reviewed-by: Allan Sandfeld Jensen --- .../webenginewidgets/clientcertificate/client.cpp | 10 ++++++++-- .../webenginewidgets/clientcertificate/server.cpp | 5 ++++- .../contentmanipulation/mainwindow.cpp | 5 ++++- src/core/net/resource_request_body_qt.cpp | 11 ++++++++++- .../tst_qwebengineclientcertificatestore.cpp | 12 ++++++------ .../tst_qwebengineurlrequestinterceptor.cpp | 3 ++- .../tst_qwebengineurlrequestjob.cpp | 7 ++++--- tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp | 2 +- .../tst_qwebenginedownloadrequest.cpp | 4 ++-- .../widgets/qwebenginepage/tst_qwebenginepage.cpp | 2 +- .../qwebengineprofile/tst_qwebengineprofile.cpp | 6 +++--- .../qwebenginescript/tst_qwebenginescript.cpp | 5 ++++- 12 files changed, 49 insertions(+), 23 deletions(-) diff --git a/examples/webenginewidgets/clientcertificate/client.cpp b/examples/webenginewidgets/clientcertificate/client.cpp index 1227fa28e8a..de09120ca0d 100644 --- a/examples/webenginewidgets/clientcertificate/client.cpp +++ b/examples/webenginewidgets/clientcertificate/client.cpp @@ -21,11 +21,17 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); QFile certFile(":/resources/client.pem"); - certFile.open(QIODevice::ReadOnly); + if (!certFile.open(QIODevice::ReadOnly)) { + qFatal("Failed to read cert file %s: %s", qPrintable(certFile.fileName()), + qPrintable(certFile.errorString())); + } const QSslCertificate cert(certFile.readAll(), QSsl::Pem); QFile keyFile(":/resources/client.key"); - keyFile.open(QIODevice::ReadOnly); + if (!keyFile.open(QIODevice::ReadOnly)) { + qFatal("Failed to read key file %s: %s", qPrintable(keyFile.fileName()), + qPrintable(keyFile.errorString())); + } const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); QWebEngineProfile::defaultProfile()->clientCertificateStore()->add(cert, sslKey); diff --git a/examples/webenginewidgets/clientcertificate/server.cpp b/examples/webenginewidgets/clientcertificate/server.cpp index ee83dab8a59..0d1bf771030 100644 --- a/examples/webenginewidgets/clientcertificate/server.cpp +++ b/examples/webenginewidgets/clientcertificate/server.cpp @@ -38,7 +38,10 @@ int main(int argc, char *argv[]) configuration.setPeerVerifyMode(QSslSocket::VerifyPeer); QFile keyFile(":/resources/server.key"); - keyFile.open(QIODevice::ReadOnly); + if (!keyFile.open(QIODevice::ReadOnly)) { + qFatal("Failed to read key file %s: %s", qPrintable(keyFile.fileName()), + qPrintable(keyFile.errorString())); + } QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); configuration.setPrivateKey(key); diff --git a/examples/webenginewidgets/contentmanipulation/mainwindow.cpp b/examples/webenginewidgets/contentmanipulation/mainwindow.cpp index 3990be2b8a7..4e661f4d825 100644 --- a/examples/webenginewidgets/contentmanipulation/mainwindow.cpp +++ b/examples/webenginewidgets/contentmanipulation/mainwindow.cpp @@ -12,7 +12,10 @@ MainWindow::MainWindow(const QUrl& url) QFile file; file.setFileName(":/jquery.min.js"); - file.open(QIODevice::ReadOnly); + if (!file.open(QIODevice::ReadOnly)) { + qFatal("Failed to read jQuery file %s: %s", qPrintable(file.fileName()), + qPrintable(file.errorString())); + } jQuery = file.readAll(); jQuery.append("\nvar qt = { 'jQuery': jQuery.noConflict(true) };"); file.close(); diff --git a/src/core/net/resource_request_body_qt.cpp b/src/core/net/resource_request_body_qt.cpp index d0d54784dd9..429d1f8048e 100644 --- a/src/core/net/resource_request_body_qt.cpp +++ b/src/core/net/resource_request_body_qt.cpp @@ -9,6 +9,8 @@ #include "services/network/public/mojom/url_request.mojom-shared.h" #include "mojo/public/cpp/bindings/remote.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { ResourceRequestBody::ResourceRequestBody(network::ResourceRequestBody *requestBody, QObject *parent) @@ -110,7 +112,14 @@ void ResourceRequestBody::readDataElementFile(const base::FilePath &filePath, co const std::size_t fileSize = std::min(file.size(), length) - realOffset; const std::size_t bytesToRead = std::min(fileSize, static_cast(maxSize)); - file.open(QFile::ReadOnly); + if (!file.open(QFile::ReadOnly)) { + m_dataElementsIdx++; + m_dataElementFileIdx = 0; + setErrorString(u"Error while reading from file, skipping remaining content of "_s + % file.fileName() % u": "_s % file.errorString()); + return; + } + file.seek(realOffset); std::memcpy(*data, file.read(bytesToRead).data(), bytesToRead); diff --git a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp index 27ef7383a3b..42c394a847b 100644 --- a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp +++ b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp @@ -55,22 +55,22 @@ void tst_QWebEngineClientCertificateStore::addAndListCertificates() { // Load QSslCertificate QFile certFile(":/resources/certificate.crt"); - certFile.open(QIODevice::ReadOnly); + QVERIFY2(certFile.open(QIODevice::ReadOnly), qPrintable(certFile.errorString())); const QSslCertificate cert(certFile.readAll(), QSsl::Pem); // Load QSslKey QFile keyFile(":/resources/privatekey.key"); - keyFile.open(QIODevice::ReadOnly); + QVERIFY2(keyFile.open(QIODevice::ReadOnly), qPrintable(keyFile.errorString())); const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); // Load second QSslCertificate QFile certFileSecond(":/resources/certificate1.crt"); - certFileSecond.open(QIODevice::ReadOnly); + QVERIFY2(certFileSecond.open(QIODevice::ReadOnly), qPrintable(certFileSecond.errorString())); const QSslCertificate certSecond(certFileSecond.readAll(), QSsl::Pem); // Load second QSslKey QFile keyFileSecond(":/resources/privatekey1.key"); - keyFileSecond.open(QIODevice::ReadOnly); + QVERIFY2(keyFileSecond.open(QIODevice::ReadOnly), qPrintable(keyFileSecond.errorString())); const QSslKey sslKeySecond(keyFileSecond.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); // Add certificates to in-memory store @@ -138,11 +138,11 @@ void tst_QWebEngineClientCertificateStore::clientAuthentication() }); QFile certFile(client_certificate); - certFile.open(QIODevice::ReadOnly); + QVERIFY2(certFile.open(QIODevice::ReadOnly), qPrintable(certFile.errorString())); const QSslCertificate cert(certFile.readAll(), QSsl::Pem); QFile keyFile(client_key); - keyFile.open(QIODevice::ReadOnly); + QVERIFY2(keyFile.open(QIODevice::ReadOnly), qPrintable(keyFile.errorString())); const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); if (in_memory) diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index c84de3599f8..7f8e040158f 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -962,7 +962,8 @@ class TestPostRequestInterceptor : public QWebEngineUrlRequestInterceptor info.d_ptr->appendFileToResourceRequestBodyForTest(":/resources/postBodyFile.txt"); } - requestBodyDevice->open(QIODevice::ReadOnly); + QVERIFY2(requestBodyDevice->open(QIODevice::ReadOnly), + qPrintable(requestBodyDevice->errorString())); const QString webKitBoundary = requestBodyDevice->read(40); QVERIFY(webKitBoundary.contains("------WebKitFormBoundary")); diff --git a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp index acddfb0e021..8552ba441b7 100644 --- a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp +++ b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp @@ -77,7 +77,7 @@ class AdditionalResponseHeadersHandler : public QWebEngineUrlSchemeHandler job->setAdditionalResponseHeaders(additionalResponseHeaders); QFile *file = new QFile(QStringLiteral(":additionalResponseHeadersScript.html"), job); - file->open(QIODevice::ReadOnly); + QVERIFY2(file->open(QIODevice::ReadOnly), qPrintable(file->errorString())); job->reply(QByteArrayLiteral("text/html"), file); } @@ -106,12 +106,13 @@ class RequestBodyHandler : public QWebEngineUrlSchemeHandler QCOMPARE(job->requestMethod(), QByteArrayLiteral("POST")); QIODevice *requestBodyDevice = job->requestBody(); - requestBodyDevice->open(QIODevice::ReadOnly); + QVERIFY2(requestBodyDevice->open(QIODevice::ReadOnly), + qPrintable(requestBodyDevice->errorString())); QByteArray requestBody = requestBodyDevice->readAll(); requestBodyDevice->close(); QBuffer *buf = new QBuffer(job); - buf->open(QBuffer::ReadWrite); + QVERIFY2(buf->open(QBuffer::ReadWrite), qPrintable(buf->errorString())); buf->write(requestBody); job->reply(QByteArrayLiteral("text/plain"), buf); buf->close(); diff --git a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp index 45d1d5a7b01..1e90b221d2d 100644 --- a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp +++ b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp @@ -62,7 +62,7 @@ struct TemporaryPdf: public QTemporaryFile TemporaryPdf::TemporaryPdf():QTemporaryFile(QStringLiteral("qpdfdocument")) { - open(); + QVERIFY2(open(), qPrintable(errorString())); pageLayout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); { diff --git a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp index a47bdbcc4d3..455fa5e73ef 100644 --- a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp +++ b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp @@ -921,13 +921,13 @@ void tst_QWebEngineDownloadRequest::downloadUniqueFilenameWithTimestamp() // Create the first empty file without uniquifier. { QFile file(m_profile->downloadPath() + "/" + fileName); - file.open(QIODevice::ReadWrite); + QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString())); } // Create 99 empty files with uniquifier. for (int i = 1; i < 100; i++) { QFile file(m_profile->downloadPath() + "/" + baseName + " (" + QString::number(i) + ")." + extension); - file.open(QIODevice::ReadWrite); + QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString())); } // Create 100th (kMaxUniqueFiles) empty file with uniquifier. diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index c2f189bb78a..e8dac91e788 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -2687,7 +2687,7 @@ void tst_QWebEnginePage::setContent_data() QTest::newRow("UTF-8 plain text") << "text/plain; charset=utf-8" << str.toUtf8() << str; QBuffer out16; - out16.open(QIODevice::WriteOnly); + QVERIFY2(out16.open(QIODevice::WriteOnly), qPrintable(out16.errorString())); QTextStream stream16(&out16); stream16.setEncoding(QStringConverter::Utf16); stream16 << str; diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 866daa77305..e7492ce7e28 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -173,7 +173,7 @@ class TestServer : public HttpServer } QFile file(resourceDir.filePath(path)); - file.open(QIODevice::ReadOnly); + QVERIFY2(file.open(QIODevice::ReadOnly), qPrintable(file.errorString())); QByteArray data = file.readAll(); rr->setResponseBody(data); QMimeDatabase db; @@ -671,7 +671,7 @@ class XhrStatusUrlSchemeHandler : public QWebEngineUrlSchemeHandler QString path = job->requestUrl().path(); if (path == "/") { QBuffer *buffer = new QBuffer(job); - buffer->open(QBuffer::ReadWrite); + QVERIFY2(buffer->open(QBuffer::ReadWrite), qPrintable(buffer->errorString())); buffer->write(QByteArrayLiteral(R"( @@ -695,7 +695,7 @@ class XhrStatusUrlSchemeHandler : public QWebEngineUrlSchemeHandler job->reply("text/html", buffer); } else if (path == "/qwebchannel.js") { QFile *file = new QFile(":/qtwebchannel/qwebchannel.js", job); - file->open(QFile::ReadOnly); + QVERIFY2(file->open(QFile::ReadOnly), qPrintable(file->errorString())); job->reply("application/javascript", file); } else if (path == "/ok") { QBuffer *buffer = new QBuffer(job); diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp index 1a4ee9c4b4b..1dfa94565e7 100644 --- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp +++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp @@ -359,7 +359,10 @@ class TestObject : public QObject static QString readFile(const QString &path) { QFile file(path); - file.open(QFile::ReadOnly); + if (!file.open(QFile::ReadOnly)) { + qWarning("Failed to read file %s: %s", qPrintable(path), qPrintable(file.errorString())); + return QString(); + } QByteArray contents = file.readAll(); file.close(); return contents; From 941b917aa260dc9ba1b8d67a5dcfe8a66fd53b96 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 27 Jan 2025 10:54:46 +0100 Subject: [PATCH 249/341] Add logging category for graphics integration The logging can be enabled with QT_LOGGING_RULES="qt.webengine.compositor=true" Change-Id: Ibf48c7bd9a6bf560e2ef2c88abb5f6c4fe122916 Reviewed-by: Moss Heim Reviewed-by: Michal Klocek (cherry picked from commit 36c8d988aa1cb9566bc1d41af6ddc8c6596cfb53) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 31651eb566d483bf49f9a45cf1802ef12a5a6481) Reviewed-by: Allan Sandfeld Jensen --- src/core/api/qtwebenginecoreglobal_p.h | 1 + src/core/compositor/compositor.cpp | 22 +++++++++++++++++++ src/core/compositor/compositor.h | 4 +++- .../compositor/display_skia_output_device.cpp | 8 +++++++ .../compositor/native_skia_output_device.cpp | 18 +++++++++++++-- .../native_skia_output_device_direct3d11.cpp | 4 ++++ .../native_skia_output_device_metal.cpp | 4 ++++ .../native_skia_output_device_opengl.cpp | 9 ++++++++ .../native_skia_output_device_vulkan.cpp | 5 +++++ 9 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/core/api/qtwebenginecoreglobal_p.h b/src/core/api/qtwebenginecoreglobal_p.h index a63568c8acd..0b8f40e562c 100644 --- a/src/core/api/qtwebenginecoreglobal_p.h +++ b/src/core/api/qtwebenginecoreglobal_p.h @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef QT_WEBENGINE_LOGGING #define QT_NOT_YET_IMPLEMENTED fprintf(stderr, "function %s not implemented! - %s:%d\n", __func__, __FILE__, __LINE__); diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp index 35b30234f14..1ea92250501 100644 --- a/src/core/compositor/compositor.cpp +++ b/src/core/compositor/compositor.cpp @@ -6,12 +6,15 @@ #include "base/memory/ref_counted.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include #include #include #include namespace QtWebEngineCore { +Q_LOGGING_CATEGORY(lcWebEngineCompositor, "qt.webengine.compositor"); + // Compositor::Id Compositor::Id::Id(viz::FrameSinkId fid) : client_id(fid.client_id()), sink_id(fid.sink_id()) { } @@ -161,6 +164,25 @@ bool Compositor::textureIsFlipped() void Compositor::releaseResources() { } +Compositor::Compositor(Type type) : m_type(type) +{ + if (Q_UNLIKELY(lcWebEngineCompositor().isDebugEnabled())) { + switch (m_type) { + case Type::Software: + qCDebug(lcWebEngineCompositor, "Compositor Type: Software"); + break; + case Type::OpenGL: + qCDebug(lcWebEngineCompositor, "Compositor Type: OpenGL"); + break; + case Type::Native: + qCDebug(lcWebEngineCompositor, "Compositor Type: Native"); + break; + } + } + qCDebug(lcWebEngineCompositor, "QPA Platform Plugin: %s", + qPrintable(QGuiApplication::platformName())); +} + Compositor::~Compositor() { DCHECK(!m_binding); // check that unbind() was called by derived final class diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h index 5d3033f8ef4..041835dd0c2 100644 --- a/src/core/compositor/compositor.h +++ b/src/core/compositor/compositor.h @@ -18,6 +18,8 @@ class FrameSinkId; namespace QtWebEngineCore { +Q_DECLARE_LOGGING_CATEGORY(lcWebEngineCompositor); + // Produces composited frames for display. // // Used by quick/widgets libraries for accessing the frames and @@ -136,7 +138,7 @@ class Q_WEBENGINECORE_EXPORT Compositor virtual void releaseResources(); protected: - Compositor(Type type) : m_type(type) { } + Compositor(Type type); virtual ~Compositor(); private: diff --git a/src/core/compositor/display_skia_output_device.cpp b/src/core/compositor/display_skia_output_device.cpp index 800e2cc1b24..07986278e80 100644 --- a/src/core/compositor/display_skia_output_device.cpp +++ b/src/core/compositor/display_skia_output_device.cpp @@ -26,6 +26,10 @@ class DisplaySkiaOutputDevice::Buffer } void initialize() { + qCDebug(lcWebEngineCompositor, "Initializing buffer %p with GrBackendTexture:", this); + qCDebug(lcWebEngineCompositor, " Pixels size: %dx%d", m_shape.imageInfo.width(), + m_shape.imageInfo.height()); + const auto &colorType = m_shape.imageInfo.colorType(); DCHECK(colorType != kUnknown_SkColorType); @@ -95,6 +99,8 @@ DisplaySkiaOutputDevice::DisplaySkiaOutputDevice( , m_contextState(contextState) , m_requiresAlpha(requiresAlpha) { + qCDebug(lcWebEngineCompositor, "Display Skia Output Device: OpenGL"); + capabilities_.uses_default_gl_framebuffer = false; capabilities_.supports_surfaceless = true; capabilities_.preserve_buffer_content = true; @@ -194,6 +200,8 @@ void DisplaySkiaOutputDevice::waitForTexture() QSGTexture *DisplaySkiaOutputDevice::texture(QQuickWindow *win, uint32_t textureOptions) { + qCDebug(lcWebEngineCompositor, "OPENGL: Importing shared GL Texture."); + if (!m_frontBuffer) return nullptr; diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp index fbe60277822..64688f9a018 100644 --- a/src/core/compositor/native_skia_output_device.cpp +++ b/src/core/compositor/native_skia_output_device.cpp @@ -60,6 +60,8 @@ NativeSkiaOutputDevice::NativeSkiaOutputDevice( m_isNativeBufferSupported = ui::OzonePlatform::GetInstance() ->GetPlatformRuntimeProperties() .supports_native_pixmaps; + qCDebug(lcWebEngineCompositor, "Native Buffer Supported: %s", + m_isNativeBufferSupported ? "yes" : "no"); #endif } @@ -226,17 +228,29 @@ NativeSkiaOutputDevice::Buffer::~Buffer() // found in the LICENSE file. bool NativeSkiaOutputDevice::Buffer::initialize() { + qCDebug(lcWebEngineCompositor, "Initializing buffer %p with SharedImage:", this); + uint32_t kDefaultSharedImageUsage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE | gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT; + if (m_parent->m_isNativeBufferSupported) kDefaultSharedImageUsage |= gpu::SHARED_IMAGE_USAGE_SCANOUT; + qCDebug(lcWebEngineCompositor, " Usage: %s", + gpu::CreateLabelForSharedImageUsage(kDefaultSharedImageUsage).c_str()); + qCDebug(lcWebEngineCompositor, " Pixels size: %dx%d", m_shape.imageInfo.width(), + m_shape.imageInfo.height()); + auto mailbox = gpu::Mailbox::GenerateForSharedImage(); - SkColorType skColorType = m_shape.imageInfo.colorType(); + const SkColorType skColorType = m_shape.imageInfo.colorType(); + const viz::SharedImageFormat sharedImageFormat = + viz::SkColorTypeToSinglePlaneSharedImageFormat(skColorType); + qCDebug(lcWebEngineCompositor, " Format: %s", sharedImageFormat.ToString().c_str()); + if (!m_parent->m_factory->CreateSharedImage( - mailbox, viz::SkColorTypeToSinglePlaneSharedImageFormat(skColorType), + mailbox, sharedImageFormat, { m_shape.imageInfo.width(), m_shape.imageInfo.height() }, m_shape.colorSpace, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, m_parent->m_deps->GetSurfaceHandle(), kDefaultSharedImageUsage, "QWE_SharedImageBuffer")) { diff --git a/src/core/compositor/native_skia_output_device_direct3d11.cpp b/src/core/compositor/native_skia_output_device_direct3d11.cpp index c9e4b22c2c7..e2f33506890 100644 --- a/src/core/compositor/native_skia_output_device_direct3d11.cpp +++ b/src/core/compositor/native_skia_output_device_direct3d11.cpp @@ -21,6 +21,8 @@ NativeSkiaOutputDeviceDirect3D11::NativeSkiaOutputDeviceDirect3D11( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Direct3D11"); + SkColorType skColorType = kRGBA_8888_SkColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; @@ -41,6 +43,8 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_ return nullptr; } + qCDebug(lcWebEngineCompositor, "D3D: Importing DXGI Resource into D3D11 Texture."); + Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture); Microsoft::WRL::ComPtr chromeTexture = overlayImage->nv12_texture(); if (!chromeTexture) { diff --git a/src/core/compositor/native_skia_output_device_metal.cpp b/src/core/compositor/native_skia_output_device_metal.cpp index a9d6e4fd53b..5ca0a58b689 100644 --- a/src/core/compositor/native_skia_output_device_metal.cpp +++ b/src/core/compositor/native_skia_output_device_metal.cpp @@ -18,6 +18,8 @@ NativeSkiaOutputDeviceMetal::NativeSkiaOutputDeviceMetal( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Metal"); + SkColorType skColorType = kRGBA_8888_SkColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; @@ -42,6 +44,8 @@ QSGTexture *NativeSkiaOutputDeviceMetal::texture(QQuickWindow *win, uint32_t tex return nullptr; } + qCDebug(lcWebEngineCompositor, "METAL: Importing IOSurface into Metal Texture."); + // This is a workaround to not to release metal texture too early. // In RHI, QMetalTexture wraps MTLTexture. QMetalTexture seems to be only destructed after the // next MTLTexture is imported. The "old" MTLTexture can be still pontentially used by RHI diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index a65cb2dc155..ac967f26da9 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -142,6 +142,8 @@ NativeSkiaOutputDeviceOpenGL::NativeSkiaOutputDeviceOpenGL( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: OpenGL"); + SkColorType skColorType = kRGBA_8888_SkColorType; #if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface() @@ -240,6 +242,8 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te #if BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getGlxPlatformInterface()) { + qCDebug(lcWebEngineCompositor, "GLX: Importing NativePixmap into GL Texture."); + x11::Pixmap pixmapId = XPixmapFromNativePixmap(*(gfx::NativePixmapDmaBuf *)nativePixmap.get()); if (pixmapId == x11::Pixmap::None) @@ -270,6 +274,8 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te #endif // BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getEglPlatformInterface()) { + qCDebug(lcWebEngineCompositor, "EGL: Importing NativePixmap into GL Texture."); + EGLHelper *eglHelper = EGLHelper::instance(); auto *eglFun = eglHelper->functions(); @@ -317,6 +323,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te } } else { #if BUILDFLAG(ENABLE_VULKAN) + qCDebug(lcWebEngineCompositor, "VULKAN: Importing VkImage into GL Texture."); Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kVulkan); gpu::VulkanFunctionPointers *vfp = gpu::GetVulkanFunctionPointers(); @@ -378,9 +385,11 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts); Q_ASSERT(glFun->glGetError() == GL_NO_ERROR); #elif defined(Q_OS_WIN) + qCDebug(lcWebEngineCompositor, "WGL: Importing DXGI Resource into GL Texture."); // TODO: Add WGL support over ANGLE. QT_NOT_YET_IMPLEMENTED #elif defined(Q_OS_MACOS) + qCDebug(lcWebEngineCompositor, "CGL: Importing IOSurface into GL Texture."); uint32_t glTexture = makeCGLTexture(win, ioSurface.get(), size()); texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts); diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index 3aec31dcb56..1e3ba2d51c3 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -37,6 +37,8 @@ NativeSkiaOutputDeviceVulkan::NativeSkiaOutputDeviceVulkan( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Vulkan"); + SkColorType skColorType = kRGBA_8888_SkColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; @@ -145,6 +147,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te }; if (nativePixmap) { + qCDebug(lcWebEngineCompositor, "VULKAN: Importing NativePixmap into VkImage."); gfx::NativePixmapHandle nativePixmapHandle = nativePixmap->ExportHandle(); if (nativePixmapHandle.planes.size() != 1) qFatal("VULKAN: Multiple planes are not supported."); @@ -158,6 +161,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te scopedFd = std::move(nativePixmapHandle.planes[0].fd); } else { + qCDebug(lcWebEngineCompositor, "VULKAN: Importing VkImage into VkImage."); externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; @@ -183,6 +187,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te if (!scopedFd.is_valid()) qFatal("VULKAN: Unable to extract file descriptor."); #elif defined(Q_OS_WIN) + qCDebug(lcWebEngineCompositor, "VULKAN: Importing DXGI Resource into VkImage."); externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture); From 5d031d4425cfed541e6abaffb2c1d99daa0c07e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Thu, 23 Jan 2025 09:37:42 +0100 Subject: [PATCH 250/341] Update Chromium Submodule src/3rdparty c5287f4d..c8dcfa48: * [Backport] Security bug 385386138 * [Backport] CVE-2025-0611: Object corruption in V8 * [Backport] CVE-2025-0437: Out of bounds read in Metrics * [Backport] CVE-2025-0447: Inappropriate implementation in Navigation * [Backport] CVE-2025-0441: Inappropriate implementation in Fenced Frames * [Backport] CVE-2025-0443: Insufficient data validation in Extensions * [Backport] CVE-2025-0438: Stack buffer overflow in Tracing * [Backport] CVE-2025-0436: Integer overflow in Skia Task-number: QTBUG-133105 Fixes: QTBUG-133107 Fixes: QTBUG-133108 Change-Id: I0a0670b356905a51ae7a063970bfda3259e11b1a Reviewed-by: Anu Aliyas (cherry picked from commit d3c9c1d8cb8f9dac09e1fd3457a5850e029090d7) --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index c715e74aaba..4a17fe015bd 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 131.0.6778.265 +Patched with security patches up to Chromium version: 132.0.6834.111 diff --git a/src/3rdparty b/src/3rdparty index c5287f4d6a0..c8dcfa4891c 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit c5287f4d6a0e64d357e7405599ecb6c7d2d4e5fd +Subproject commit c8dcfa4891c8dcf733b0c6ecc6ddcfe781d4567d diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 39027b35467..52c017dffb9 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1268,7 +1268,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "131.0.6778.265"; // FIXME: Remember to update + return "132.0.6834.111"; // FIXME: Remember to update } QT_END_NAMESPACE From 24ee881290f8d1fc3292f14f726de34d2d81217e Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 31 Jan 2025 09:55:48 +0100 Subject: [PATCH 251/341] Set rtc_use_h264 to true again Enables H264 on Windows with proprietary codecs. Pick-to: 6.5 Task-number: QTBUG-117478 Change-Id: Ie46fcce555fac751e7eb5e90c0e079462dcadc0c Reviewed-by: Peter Varga Reviewed-by: Kaloyan Chehlarski (cherry picked from commit 4a43f458ee9971aca82c1b28586be58f88ce8a8b) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 073857250cc13c6627bb80dcba86d77d00345155) --- src/core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 3d871f65205..8059d1dcf90 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -417,7 +417,7 @@ foreach(arch ${archs}) CONDITION QT_FEATURE_webengine_kerberos ) extend_gn_list(gnArgArg - ARGS proprietary_codecs + ARGS proprietary_codecs rtc_use_h264 CONDITION QT_FEATURE_webengine_proprietary_codecs ) if(QT_FEATURE_webengine_proprietary_codecs) From 3d88b5e9011c92beff016fea6f2af51330398c26 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 22 Jan 2025 17:32:52 +0100 Subject: [PATCH 252/341] Unify and modernize Latin1 string literals - Fix some deprecated string literal compiler warnings - Replace deprecated QLatin1String usages - Use QLatin1StringView where QString conversion is not needed - Replace QLatin1StringView usages with shorter _L1 suffix Change-Id: I8adb6dcd06ac5dfc248d39455c14a26957876512 Reviewed-by: Marc Mutz (cherry picked from commit 900ae370f5d6c06a29b08fd94523d30bdc089b88) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit fca622c2cc915fa9d980d7a715d88cc2dc8b443b) Reviewed-by: Allan Sandfeld Jensen --- .../accessibility_activation_observer.cpp | 7 +- src/core/api/qwebenginepage.cpp | 27 ++-- src/core/api/qwebenginescript.cpp | 3 +- src/core/clipboard_qt.cpp | 4 +- src/core/content_client_qt.cpp | 52 ++++---- src/core/devtools_manager_delegate_qt.cpp | 3 +- src/core/download_manager_delegate_qt.cpp | 6 +- src/core/file_picker_controller.cpp | 18 +-- src/core/net/qrc_url_scheme_handler.cpp | 4 +- src/core/permission_manager_qt.cpp | 7 +- src/core/pref_service_adapter.cpp | 7 +- .../printing/print_view_manager_base_qt.cpp | 6 +- src/core/profile_adapter.cpp | 11 +- .../tools/qwebengine_convert_dict/main.cpp | 11 +- src/core/web_contents_adapter.cpp | 16 ++- src/core/web_contents_delegate_qt.cpp | 3 +- src/core/web_engine_context.cpp | 91 ++++++------- src/core/web_engine_library_info.cpp | 124 ++++++++---------- src/core/web_event_factory.cpp | 12 +- 19 files changed, 212 insertions(+), 200 deletions(-) diff --git a/src/core/accessibility_activation_observer.cpp b/src/core/accessibility_activation_observer.cpp index 4f25a35ffed..4e90b9b3b38 100644 --- a/src/core/accessibility_activation_observer.cpp +++ b/src/core/accessibility_activation_observer.cpp @@ -5,6 +5,8 @@ #include "content/browser/accessibility/browser_accessibility_state_impl.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { namespace { @@ -14,9 +16,8 @@ bool isAccessibilityEnabled() { // QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment variable to 0. For details, // see QTBUG-59922. #ifdef Q_OS_LINUX - static bool accessibility_enabled - = qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", QLatin1String("1")) - == QLatin1String("1"); + static bool accessibility_enabled = + qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", u"1"_s) == "1"_L1; #else const bool accessibility_enabled = true; #endif diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index d209e0ca965..b180b58b99d 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; using namespace QtWebEngineCore; static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) @@ -1341,11 +1342,10 @@ void QWebEnginePage::triggerAction(WebAction action, bool) QString linkText = d->view->lastContextMenuRequest()->linkText().toHtmlEscaped(); QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) - title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - QString html = QStringLiteral("") - + linkText + QStringLiteral(""); + QString html = "' + linkText + ""_L1; data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->linkUrl()); QGuiApplication::clipboard()->setMimeData(data); @@ -1376,13 +1376,13 @@ void QWebEnginePage::triggerAction(WebAction action, bool) d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded); QString alt = d->view->lastContextMenuRequest()->altText(); if (!alt.isEmpty()) - alt = QStringLiteral(" alt=\"%1\"").arg(alt.toHtmlEscaped()); + alt = " alt=\""_L1 + alt.toHtmlEscaped() + u'"'; QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) - title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - QString html = QStringLiteral(""); + QString html = ""_L1; data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->mediaUrl()); QGuiApplication::clipboard()->setMimeData(data); @@ -1406,16 +1406,15 @@ void QWebEnginePage::triggerAction(WebAction action, bool) d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded); QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) - title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - if (d->view->lastContextMenuRequest()->mediaType() - == QWebEngineContextMenuRequest::MediaTypeAudio) - data->setHtml(QStringLiteral("")); - else - data->setHtml(QStringLiteral("")); + const bool isAudio = d->view->lastContextMenuRequest()->mediaType() + == QWebEngineContextMenuRequest::MediaTypeAudio; + const auto avTagName = isAudio ? "audio"_L1 : "video"_L1; + QString html = u'<' + avTagName + "src=\""_L1 + urlString + u'"' + title + ">'; + data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->mediaUrl()); QGuiApplication::clipboard()->setMimeData(data); } diff --git a/src/core/api/qwebenginescript.cpp b/src/core/api/qwebenginescript.cpp index 846b011967c..8d1ff46bf49 100644 --- a/src/core/api/qwebenginescript.cpp +++ b/src/core/api/qwebenginescript.cpp @@ -7,6 +7,7 @@ #include #include +using namespace Qt::StringLiterals; using QtWebEngineCore::UserScript; QT_BEGIN_NAMESPACE @@ -161,7 +162,7 @@ void QWebEngineScript::setSourceUrl(const QUrl &url) QFile file; if (url.isLocalFile()) { file.setFileName(url.toLocalFile()); - } else if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { + } else if (url.scheme().compare("qrc"_L1, Qt::CaseInsensitive) == 0) { if (url.authority().isEmpty()) file.setFileName(QLatin1Char(':') + url.path()); } diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 1140164ae98..cd63b0b6f29 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -32,6 +32,8 @@ #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { static void registerMetaTypes() @@ -139,7 +141,7 @@ void ClipboardQt::WriteHTML(base::StringPiece markup, absl::optional")); + markup_string.prepend(""_L1); #endif #if !defined(Q_OS_WIN) diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 5d9cc7b3576..95d6ec4e3c6 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -57,13 +57,15 @@ const char kWidevineCdmFileName[] = const char kPdfPluginPath[] = "internal-pdf-viewer"; #endif // QT_CONFIG(webengine_printing_and_pdf) +using namespace Qt::StringLiterals; using Robustness = content::CdmInfo::Robustness; static QString webenginePluginsPath() { // Look for plugins in /plugins/webengine or application dir. static bool initialized = false; - static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/webengine"); + static QString potentialPluginsPath = + QLibraryInfo::path(QLibraryInfo::PluginsPath) % "/webengine"_L1; if (!initialized) { initialized = true; if (!QFileInfo::exists(potentialPluginsPath)) @@ -107,7 +109,8 @@ static QString ppapiPluginsPath() { // Look for plugins in /plugins/ppapi or application dir. static bool initialized = false; - static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/ppapi"); + static QString potentialPluginsPath = + QLibraryInfo::path(QLibraryInfo::PluginsPath) % "/ppapi"_L1; if (!initialized) { initialized = true; if (!QFileInfo::exists(potentialPluginsPath)) @@ -151,7 +154,7 @@ namespace QtWebEngineCore { static const QDir widevineCdmDirHint(const QDir &widevineDir) { const QString hintFilePath = widevineDir.absolutePath() % QDir::separator() - % QLatin1String("latest-component-updated-widevine-cdm"); + % "latest-component-updated-widevine-cdm"_L1; if (!QFileInfo::exists(hintFilePath)) { // CDM hint file does not exist. return widevineDir; @@ -189,32 +192,33 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, if (!widevine_argument.empty()) pluginPaths << QtWebEngineCore::toQt(widevine_argument); else { - pluginPaths << webenginePluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); + pluginPaths << webenginePluginsPath() + QStringLiteral("/") + QLatin1StringView(kWidevineCdmFileName); #if QT_CONFIG(webengine_pepper_plugins) - pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); + pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QLatin1StringView(kWidevineCdmFileName); #endif #if defined(Q_OS_OSX) QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Frameworks"); if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); - const QString library = QLatin1String("/Versions/Current/Libraries/" - "WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib"); + const auto library = + "/Versions/Current/Libraries/WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib"_L1; for (const QFileInfo &info : widevineVersionDirs) pluginPaths << info.absoluteFilePath() + library; } - QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"); + QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"_L1); if (oldPotentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = oldPotentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmFileName); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/"_L1 + + QLatin1StringView(kWidevineCdmFileName); pluginPaths << potentialWidevinePluginPath; } } #elif defined(Q_OS_WIN) - const QString googleChromeDir = QLatin1String("/Google/Chrome/Application"); + const auto googleChromeDir = "/Google/Chrome/Application"_L1; const QStringList programFileDirs{getProgramFilesDir() + googleChromeDir, getProgramFilesDir(true) + googleChromeDir}; for (const QString &dir : programFileDirs) { @@ -225,26 +229,26 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); #ifdef WIN64 QString potentialWidevinePluginPath = versionDirPath + - "/WidevineCdm/_platform_specific/win_x64/" + - QString::fromLatin1(kWidevineCdmFileName); + "/WidevineCdm/_platform_specific/win_x64/"_L1 + + QLatin1StringView(kWidevineCdmFileName); #else QString potentialWidevinePluginPath = versionDirPath + - "/WidevineCdm/_platform_specific/win_x86/" + - QString::fromLatin1(kWidevineCdmFileName); + "/WidevineCdm/_platform_specific/win_x86/"_L1 + + QLatin1StringView(kWidevineCdmFileName); #endif pluginPaths << potentialWidevinePluginPath; } } } - QDir potentialWidevineDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM"); + QDir potentialWidevineDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM"_L1); if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); #ifdef WIN64 - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/" + QString::fromLatin1(kWidevineCdmFileName); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/"_L1 + QLatin1StringView(kWidevineCdmFileName); #else - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/" + QString::fromLatin1(kWidevineCdmFileName); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/"_L1 + QLatin1StringView(kWidevineCdmFileName); #endif pluginPaths << potentialWidevinePluginPath; } @@ -253,23 +257,23 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, QList potentialWidevineVersionDirs; // Google Chrome widevine modules - QDir chromeWidevineDir(QDir::homePath() + "/.config/google-chrome/WidevineCdm"); + QDir chromeWidevineDir(QDir::homePath() + "/.config/google-chrome/WidevineCdm"_L1); if (chromeWidevineDir.exists()) potentialWidevineVersionDirs << widevineCdmDirHint(chromeWidevineDir); // Firefox widevine modules - QDir firefoxPotentialProfilesDir(QDir::homePath() + "/.mozilla/firefox"); + QDir firefoxPotentialProfilesDir(QDir::homePath() + "/.mozilla/firefox"_L1); if (firefoxPotentialProfilesDir.exists()) { QFileInfoList firefoxProfileDirs = firefoxPotentialProfilesDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (const QFileInfo &info : firefoxProfileDirs) { - QDir widevinePluginsDir(info.absoluteFilePath() + "/gmp-widevinecdm"); + QDir widevinePluginsDir(info.absoluteFilePath() + "/gmp-widevinecdm"_L1); if (widevinePluginsDir.exists()) potentialWidevineVersionDirs << widevinePluginsDir; } } // Chromium widevine modules (might not work with proprietary codecs) - QDir chromiumWidevineDir(QDir::homePath() + "/.config/chromium/WidevineCdm"); + QDir chromiumWidevineDir(QDir::homePath() + "/.config/chromium/WidevineCdm"_L1); if (chromiumWidevineDir.exists()) potentialWidevineVersionDirs << widevineCdmDirHint(chromiumWidevineDir); @@ -279,12 +283,12 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, widevineVersionDirs.prepend(QFileInfo(dir.absolutePath())); // ### alternatively look up in the manifest.json and take the path from there. #if Q_PROCESSOR_WORDSIZE == 8 - const QString library = QLatin1String("/_platform_specific/linux_x64/libwidevinecdm.so"); + const auto library = "/_platform_specific/linux_x64/libwidevinecdm.so"_L1; #else - const QString library = QLatin1String("/_platform_specific/linux_x86/libwidevinecdm.so"); + const auto library = "/_platform_specific/linux_x86/libwidevinecdm.so"_L1; #endif for (const QFileInfo &info : widevineVersionDirs) { - pluginPaths << info.absoluteFilePath() + "/libwidevinecdm.so"; + pluginPaths << info.absoluteFilePath() + "/libwidevinecdm.so"_L1; pluginPaths << info.absoluteFilePath() + library; } } diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp index 6654ead0ec6..433effed4d8 100644 --- a/src/core/devtools_manager_delegate_qt.cpp +++ b/src/core/devtools_manager_delegate_qt.cpp @@ -20,6 +20,7 @@ #include "net/socket/tcp_server_socket.h" #include "ui/base/resource/resource_bundle.h" +using namespace Qt::StringLiterals; using content::DevToolsAgentHost; namespace { @@ -52,7 +53,7 @@ class TCPServerSocketFactory : public content::DevToolsSocketFactory { namespace QtWebEngineCore { DevToolsServerQt::DevToolsServerQt() - : m_bindAddress(QLatin1String("127.0.0.1")) + : m_bindAddress(u"127.0.0.1"_s) , m_port(0) , m_valid(false) , m_isStarted(false) diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 7ccd063ffda..61f789c79ec 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -22,6 +22,8 @@ #include "type_conversion.h" #include "web_contents_delegate_qt.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { DownloadManagerDelegateQt::DownloadManagerDelegateQt(ProfileAdapter *profileAdapter) @@ -262,8 +264,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content } if (suggestedFilePath.isEmpty()) { - suggestedFilePath = QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName() - + QStringLiteral(".mhtml"); + suggestedFilePath += + QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName() + ".mhtml"_L1; } else { acceptedByDefault = true; } diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index fb124df7bb8..fc52a387daa 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -18,6 +18,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { class FilePickerControllerPrivate { @@ -75,7 +77,7 @@ void FilePickerController::accepted(const QStringList &files) continue; } - if (urlString.startsWith("file:")) { + if (urlString.startsWith("file:"_L1)) { base::FilePath filePath = toFilePath(urlString).NormalizePathSeparators(); std::vector pathComponents; // Splits the file URL into scheme, host name, path and file name. @@ -91,7 +93,7 @@ void FilePickerController::accepted(const QStringList &files) #if defined(Q_OS_WIN) // There is no slash at the end of the file scheme and it is valid on Windows: file:C:/ if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == ':') { - absolutePath += scheme.at(5) + ":/"; + absolutePath += scheme.at(5) + ":/"_L1; } else { #endif qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); @@ -107,7 +109,7 @@ void FilePickerController::accepted(const QStringList &files) && !base::FilePath::IsSeparator(urlString.at(7).toLatin1())) { #if defined(Q_OS_WIN) if (urlString.at(8) != ':' && pathComponents.size() > 2) { - absolutePath += "//"; + absolutePath += "//"_L1; #else if (pathComponents.size() > 2) { absolutePath += "/"; @@ -161,7 +163,7 @@ static QStringList listRecursively(const QDir &dir) const QFileInfoList infoList(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden)); for (const QFileInfo &fileInfo : infoList) { if (fileInfo.isDir()) { - ret.append(fileInfo.absolutePath() + QStringLiteral("/.")); // Match chromium's behavior. See chrome/browser/file_select_helper.cc + ret.append(fileInfo.absolutePath() + "/."_L1); // Match chromium's behavior. See chrome/browser/file_select_helper.cc ret.append(listRecursively(QDir(fileInfo.absoluteFilePath()))); } else ret.append(fileInfo.absoluteFilePath()); @@ -256,7 +258,7 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp if (mimeType.isValid()) { QString glob = "*" + type; acceptedGlobs.append(glob); - nameFilters.append(mimeType.comment() + " (" + glob + ")"); + nameFilters.append(mimeType.comment() + " ("_L1 + glob + ")"); } } else if (type.contains("/") && !type.endsWith("*")) { // All suffixes for a given MIME type @@ -264,9 +266,9 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp if (mimeType.isValid() && !mimeType.globPatterns().isEmpty()) { QString globs = mimeType.globPatterns().join(" "); acceptedGlobs.append(mimeType.globPatterns()); - nameFilters.append(mimeType.comment() + " (" + globs + ")"); + nameFilters.append(mimeType.comment() + " ("_L1 + globs + ")"); } - } else if (type.endsWith("/*")) { + } else if (type.endsWith("/*"_L1)) { // All MIME types for audio/*, image/* or video/* // as separate filters as Chrome does static const QList &allMimeTypes = mimeDatabase.allMimeTypes(); @@ -275,7 +277,7 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp if (m.name().startsWith(type) && !m.globPatterns().isEmpty()) { QString globs = m.globPatterns().join(" "); acceptedGlobs.append(m.globPatterns()); - nameFilters.append(m.comment() + " (" + globs + ")"); + nameFilters.append(m.comment() + " ("_L1 + globs + ")"); } } } else { diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp index a8b4e4388a2..82554827ead 100644 --- a/src/core/net/qrc_url_scheme_handler.cpp +++ b/src/core/net/qrc_url_scheme_handler.cpp @@ -12,6 +12,8 @@ #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) @@ -33,7 +35,7 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) QFileInfo fileInfo(*file); QMimeDatabase mimeDatabase; QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo); - if (mimeType.name() == QStringLiteral("application/x-extension-html")) + if (mimeType.name() == "application/x-extension-html"_L1) job->reply("text/html", file.release()); else job->reply(mimeType.name().toUtf8(), file.release()); diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 247c1936fef..058cefddcb7 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -26,6 +26,8 @@ #include "web_contents_delegate_qt.h" #include "web_engine_settings.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { // Extra permission types that don't exist on the Chromium side. @@ -198,14 +200,15 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) factory.set_command_line_prefs(base::MakeRefCounted( base::CommandLine::ForCurrentProcess())); - QString userPrefStorePath = profileAdapter->dataPath(); + QString userPrefStorePath; + userPrefStorePath += profileAdapter->dataPath(); auto prefRegistry = base::MakeRefCounted(); auto policy = profileAdapter->persistentPermissionsPolicy(); if (!profileAdapter->isOffTheRecord() && policy == ProfileAdapter::PersistentPermissionsPolicy::StoreOnDisk && !userPrefStorePath.isEmpty() && profileAdapter->ensureDataPathExists()) { userPrefStorePath += QDir::separator(); - userPrefStorePath += QStringLiteral("permissions.json"); + userPrefStorePath += "permissions.json"_L1; factory.set_user_prefs(base::MakeRefCounted(toFilePath(userPrefStorePath))); } else { factory.set_user_prefs(new InMemoryPrefStore); diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index 7a7abf2c48c..210d900e25a 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -55,6 +55,8 @@ namespace { static const char kPrefMediaDeviceIDSalt[] = "qtwebengine.media_device_salt_id"; } +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) @@ -64,11 +66,12 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) factory.set_command_line_prefs(base::MakeRefCounted( base::CommandLine::ForCurrentProcess())); - QString userPrefStorePath = profileAdapter.dataPath(); + QString userPrefStorePath; + userPrefStorePath += profileAdapter.dataPath(); if (!profileAdapter.isOffTheRecord() && !userPrefStorePath.isEmpty() && const_cast(&profileAdapter)->ensureDataPathExists()) { userPrefStorePath += QDir::separator(); - userPrefStorePath += QStringLiteral("user_prefs.json"); + userPrefStorePath += "user_prefs.json"_L1; factory.set_user_prefs(base::MakeRefCounted(toFilePath(userPrefStorePath))); } else { factory.set_user_prefs(new InMemoryPrefStore); diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp index a691bc2b64b..a8af1f6037b 100644 --- a/src/core/printing/print_view_manager_base_qt.cpp +++ b/src/core/printing/print_view_manager_base_qt.cpp @@ -33,6 +33,10 @@ #include "printing/print_job_constants.h" #include "printing/printed_document.h" +#include + +using namespace std::string_literals; + namespace QtWebEngineCore { namespace { @@ -160,7 +164,7 @@ void PrintViewManagerBaseQt::NavigationStopped() std::u16string PrintViewManagerBaseQt::RenderSourceName() { - return toString16(QLatin1String("")); + return u""s; } void PrintViewManagerBaseQt::PrintDocument(scoped_refptr print_data, diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index a74ecc8cf38..c5cc86eb15c 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -44,13 +44,16 @@ #include #include +using namespace Qt::StringLiterals; + namespace { inline QString buildLocationFromStandardPath(const QString &standardPath, const QString &name) { - QString location = standardPath; + QString location; + location += standardPath; if (location.isEmpty()) - location = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName(); + location += QDir::homePath() % "/."_L1 % QCoreApplication::applicationName(); - location.append(QLatin1String("/QtWebEngine/") % name); + location += "/QtWebEngine/"_L1 % name; return location; } } @@ -307,7 +310,7 @@ QString ProfileAdapter::httpCachePath() const return QString(); QString basePath = cachePath(); if (!basePath.isEmpty()) - return basePath % QLatin1String("/Cache"); + return basePath % "/Cache"_L1; return QString(); } diff --git a/src/core/tools/qwebengine_convert_dict/main.cpp b/src/core/tools/qwebengine_convert_dict/main.cpp index 8b82b930f5d..b49ae0279a5 100644 --- a/src/core/tools/qwebengine_convert_dict/main.cpp +++ b/src/core/tools/qwebengine_convert_dict/main.cpp @@ -32,6 +32,8 @@ #include #include +using namespace Qt::StringLiterals; + // see also src/core/type_conversion.h inline base::FilePath::StringType toFilePathString(const QString &str) { @@ -131,8 +133,8 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words, #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) QString frameworkIcuDataPath() { - return QLibraryInfo::location(QLibraryInfo::LibrariesPath) + - QStringLiteral("/QtWebEngineCore.framework/Resources/"); + return QLibraryInfo::location(QLibraryInfo::LibrariesPath) + + "/QtWebEngineCore.framework/Resources/"_L1; } #endif @@ -155,15 +157,14 @@ int main(int argc, char *argv[]) } #if defined(USE_ICU_FILE) bool icuDataDirFound = false; - QString icuDataDir = QLibraryInfo::path(QLibraryInfo::DataPath) - % QLatin1String("/resources"); + QString icuDataDir = QLibraryInfo::path(QLibraryInfo::DataPath) % "/resources"_L1; // Try to look up the path to the ICU data directory via an environment variable // (e.g. for the case when the tool is ran during build phase, and regular installed // ICU data file is not available). const QString icuPossibleEnvDataDir = qEnvironmentVariable("QT_WEBENGINE_ICU_DATA_DIR"); const QString appPath = QCoreApplication::applicationDirPath(); - QLatin1String icuDataFilePath("/icudtl.dat"); + const auto icuDataFilePath = "/icudtl.dat"_L1; if (!icuPossibleEnvDataDir.isEmpty() && QFileInfo::exists(icuPossibleEnvDataDir)) { icuDataDir = icuPossibleEnvDataDir; icuDataDirFound = true; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index f98c6a9300d..238c81504f1 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -93,6 +93,8 @@ #include "extensions/extension_web_contents_observer_qt.h" #endif +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { #define CHECK_INITIALIZED(return_value) \ @@ -659,12 +661,12 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) Q_UNUSED(guard); // Add URL scheme if missing from view-source URL. - if (request.url().scheme() == content::kViewSourceScheme) { + if (request.url().scheme() == QLatin1StringView(content::kViewSourceScheme)) { QUrl pageUrl = QUrl(request.url().toString().remove(0, strlen(content::kViewSourceScheme) + 1)); if (pageUrl.scheme().isEmpty()) { QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString()); - extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, + extendedUrl = QUrl(QString("%1:%2").arg(QLatin1StringView(content::kViewSourceScheme), extendedUrl.toString())); gurl = toGurl(https://github.com/extendedUrl); } @@ -1620,7 +1622,8 @@ static QMimeData *mimeDataFromDropData(const content::DropData &dropData) if (!dropData.custom_data.empty()) { base::Pickle pickle; ui::WriteCustomDataToPickle(dropData.custom_data, &pickle); - mimeData->setData(QLatin1String(ui::kMimeTypeWebCustomData), QByteArray((const char*)pickle.data(), pickle.size())); + mimeData->setData(QLatin1StringView(ui::kMimeTypeWebCustomData), + QByteArray((const char *)pickle.data(), pickle.size())); } return mimeData; } @@ -1750,8 +1753,9 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat dropData->html = toOptionalString16(mimeData->html()); if (mimeData->hasText()) dropData->text = toOptionalString16(mimeData->text()); - if (mimeData->hasFormat(QLatin1String(ui::kMimeTypeWebCustomData))) { - const QByteArray customData = mimeData->data(QLatin1String(ui::kMimeTypeWebCustomData)); + const QString mimeType = QString::fromLatin1(ui::kMimeTypeWebCustomData); + if (mimeData->hasFormat(mimeType)) { + const QByteArray customData = mimeData->data(mimeType); const base::span custom_data(customData.constData(), (long unsigned)customData.length()); if (auto maybe_data = ui::ReadCustomDataIntoMap(base::as_bytes(custom_data))) dropData->custom_data = *std::move(maybe_data); @@ -1966,7 +1970,7 @@ QString WebContentsAdapter::frameHtmlName(quint64 id) const { CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, QString()); auto &maybeName = ftn->html_name(); - return maybeName ? QString::fromStdString(*maybeName) : QString(""); + return maybeName ? QString::fromStdString(*maybeName) : ""_L1; } QList WebContentsAdapter::frameChildren(quint64 id) const diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index d0bbb98564d..de045da4ee1 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -199,7 +199,8 @@ QUrl WebContentsDelegateQt::url(/service/content::WebContents *source) const if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme) && (url.has_password() || url.has_username() || url.has_ref())) { GURL strippedUrl = net::SimplifyUrlForRequest(url); - newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec()))); + newUrl = QUrl(QString("%1:%2").arg(QLatin1StringView(content::kViewSourceScheme), + QString::fromStdString(strippedUrl.spec()))); } // If there is a visible entry there are special cases where we dont wan't to use the actual URL if (newUrl.isEmpty()) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 52c017dffb9..da1aea48de8 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -127,6 +127,8 @@ QT_END_NAMESPACE #define STRINGIFY_LITERAL(x) #x #define STRINGIFY_EXPANDED(x) STRINGIFY_LITERAL(x) +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { Q_LOGGING_CATEGORY(webEngineContextLog, "qt.webenginecontext") @@ -203,23 +205,23 @@ class GPUInfo return Unknown; } - static Vendor deviceNameToVendor(const QString &deviceName) + static Vendor deviceNameToVendor(QLatin1StringView deviceName) { // TODO: Test and add more vendors to the list. - if (deviceName.contains(QLatin1StringView("AMD"), Qt::CaseInsensitive)) + if (deviceName.contains("AMD"_L1, Qt::CaseInsensitive)) return AMD; - if (deviceName.contains(QLatin1StringView("Intel"), Qt::CaseInsensitive)) + if (deviceName.contains("Intel"_L1, Qt::CaseInsensitive)) return Intel; - if (deviceName.contains(QLatin1StringView("Nvidia"), Qt::CaseInsensitive)) + if (deviceName.contains("Nvidia"_L1, Qt::CaseInsensitive)) return Nvidia; #if defined(USE_OZONE) - if (deviceName.contains(QLatin1StringView("Mesa llvmpipe"))) + if (deviceName.contains("Mesa llvmpipe"_L1)) return Mesa; #endif #if defined(Q_OS_MACOS) - if (deviceName.contains(QLatin1StringView("Apple"))) + if (deviceName.contains("Apple"_L1)) return Apple; #endif @@ -356,7 +358,7 @@ static bool usingSupportedSGBackend() QString device = QQuickWindow::sceneGraphBackend(); for (int index = 0; index < args.count(); ++index) { - if (args.at(index).startsWith(QLatin1StringView("--device="))) { + if (args.at(index).startsWith("--device="_L1)) { device = args.at(index).mid(9); break; } @@ -367,7 +369,7 @@ static bool usingSupportedSGBackend() if (device.isEmpty()) device = qEnvironmentVariable("QMLSCENE_DEVICE"); - return device.isEmpty() || device == QLatin1StringView("rhi"); + return device.isEmpty() || device == "rhi"_L1; } #if QT_CONFIG(opengl) @@ -495,43 +497,33 @@ void dummyGetPluginCallback(const std::vector&) static void logContext(const std::string &glType, base::CommandLine *cmd) { if (Q_UNLIKELY(webEngineContextLog().isDebugEnabled())) { - QStringList log; - log << QLatin1StringView("\n"); - - log << QLatin1StringView("Chromium GL Backend: " + glType) << QLatin1StringView("\n"); - log << QLatin1StringView("Chromium ANGLE Backend: " + getAngleType(glType, cmd)) - << QLatin1StringView("\n"); - log << QLatin1StringView("Chromium Vulkan Backend: " + getVulkanType(cmd)) - << QLatin1StringView("\n"); - log << QLatin1StringView("\n"); - - log << QLatin1StringView("QSG RHI Backend:") << QSGRhiSupport::instance()->rhiBackendName() - << QLatin1StringView("\n"); - log << QLatin1StringView("QSG RHI Backend Supported:") - << QLatin1StringView(usingSupportedSGBackend() ? "yes" : "no") - << QLatin1StringView("\n"); - log << QLatin1StringView("GPU Vendor: " - + GPUInfo::vendorToString(GPUInfo::instance()->vendor())) - << QLatin1StringView("\n"); - log << QLatin1StringView("\n"); + QString log; + log += u'\n'; + + log += "Chromium GL Backend: "_L1 + QLatin1StringView(glType) + "\n"_L1; + log += "Chromium ANGLE Backend: "_L1 + QLatin1StringView(getAngleType(glType, cmd)) + u'\n'; + log += "Chromium Vulkan Backend: "_L1 + QLatin1StringView(getVulkanType(cmd)) + u'\n'; + log += u'\n'; + + log += "QSG RHI Backend: "_L1 + QSGRhiSupport::instance()->rhiBackendName() + u'\n'; + log += "QSG RHI Backend Supported: "_L1 + (usingSupportedSGBackend() ? "yes"_L1 : "no"_L1) + + u'\n'; + log += "GPU Vendor: "_L1 + + QLatin1StringView(GPUInfo::vendorToString(GPUInfo::instance()->vendor())) + u'\n'; + log += u'\n'; #if QT_CONFIG(opengl) #if defined(USE_OZONE) - log << QLatin1StringView("Using GLX:") - << QLatin1StringView(GLContextHelper::getGlxPlatformInterface() ? "yes" : "no") - << QLatin1StringView("\n"); - log << QLatin1StringView("Using EGL:") - << QLatin1StringView(GLContextHelper::getEglPlatformInterface() ? "yes" : "no") - << QLatin1StringView("\n"); + log += "Using GLX: "_L1 + (GLContextHelper::getGlxPlatformInterface() ? "yes"_L1 : "no"_L1) + + u'\n'; + log += "Using EGL: "_L1 + (GLContextHelper::getEglPlatformInterface() ? "yes"_L1 : "no"_L1) + + u'\n'; #endif #if defined(USE_OZONE) || defined(Q_OS_WIN) - log << QLatin1StringView("Using Shared GL:") - << QLatin1StringView(qt_gl_global_share_context() ? "yes" : "no") - << QLatin1StringView("\n"); + log += "Using Shared GL: "_L1 + (qt_gl_global_share_context() ? "yes"_L1 : "no"_L1) + u'\n'; if (qt_gl_global_share_context()) { - log << QLatin1StringView("Using Software Dynamic GL:") - << QLatin1StringView(usingSoftwareDynamicGL() ? "yes" : "no") - << QLatin1StringView("\n"); + log += "Using Software Dynamic GL: "_L1 + + (usingSoftwareDynamicGL() ? "yes"_L1 : "no"_L1) + u'\n'; const QSurfaceFormat sharedFormat = qt_gl_global_share_context() ? qt_gl_global_share_context()->format() @@ -541,24 +533,21 @@ static void logContext(const std::string &glType, base::CommandLine *cmd) sharedFormat.profile()); const auto type = QMetaEnum::fromType().valueToKey( sharedFormat.renderableType()); - log << QLatin1StringView("Surface Type:") << QLatin1StringView(type) - << QLatin1StringView("\n"); - log << QLatin1StringView("Surface Profile:") << QLatin1StringView(profile) - << QLatin1StringView("\n"); - log << QStringLiteral("Surface Version: %1.%2\n") - .arg(sharedFormat.majorVersion()) - .arg(sharedFormat.minorVersion()); + log += "Surface Type: "_L1 + QLatin1StringView(type) + u'\n'; + log += "Surface Profile: "_L1 + QLatin1StringView(profile) + u'\n'; + log += "Surface Version: "_L1 + QString::number(sharedFormat.majorVersion()) + u'.' + + QString::number(sharedFormat.minorVersion()) + u'\n'; } - log << QLatin1StringView("\n"); + log += u'\n'; #endif // defined(USE_OZONE) || defined(Q_OS_WIN) #endif // QT_CONFIG(opengl) - log << QLatin1StringView("Init Parameters:\n"); + log += "Init Parameters:\n"_L1; const base::CommandLine::SwitchMap switchMap = cmd->GetSwitches(); for (const auto &pair : switchMap) - log << QStringLiteral(" * %1 %2\n").arg(toQt(pair.first)).arg(toQt(pair.second)); + log += " * "_L1 + toQt(pair.first) + u' ' + toQt(pair.second) + u'\n'; - qCDebug(webEngineContextLog) << qPrintable(log.join(QLatin1Char(' '))); + qCDebug(webEngineContextLog, "%ls", qUtf16Printable(log)); } } @@ -570,7 +559,7 @@ static void setupProxyPac(base::CommandLine *commandLine) QUrl pac_url(https://github.com/toQt(commandLine-%3EGetSwitchValueASCII(switches::kProxyPacUrl))); if (pac_url.isValid() && (pac_url.isLocalFile() - || !pac_url.scheme().compare(QLatin1StringView("qrc"), Qt::CaseInsensitive))) { + || !pac_url.scheme().compare("qrc"_L1, Qt::CaseInsensitive))) { QFile file; if (pac_url.isLocalFile()) file.setFileName(pac_url.toLocalFile()); diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index b6b8fc76340..b3a0050ba63 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -34,6 +34,7 @@ #error "No name defined for QtWebEngine's process" #endif +using namespace Qt::StringLiterals; using namespace QtWebEngineCore; Q_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo") @@ -41,7 +42,7 @@ Q_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo") namespace { QString fallbackDir() { - static QString directory = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName(); + static QString directory = QDir::homePath() % "/."_L1 % QCoreApplication::applicationName(); return directory; } @@ -57,8 +58,8 @@ static QString getBundlePath(CFBundleRef frameworkBundle) // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before. // We use it for the other OS X versions as well to make sure it works and because // the directory structure should be the same. - if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) { - path = QDir::cleanPath(qApp->applicationDirPath() % QLatin1String("/../../../..")); + if (qApp->applicationName() == QLatin1StringView(qWebEngineProcessName())) { + path = QDir::cleanPath(qApp->applicationDirPath() % "/../../../.."_L1); } else if (frameworkBundle) { CFURLRef bundleUrl = CFBundleCopyBundleURL(frameworkBundle); CFStringRef bundlePath = CFURLCopyFileSystemPath(bundleUrl, kCFURLPOSIXPathStyle); @@ -75,8 +76,8 @@ static QString getResourcesPath(CFBundleRef frameworkBundle) // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before. // We use it for the other OS X versions as well to make sure it works and because // the directory structure should be the same. - if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) { - path = getBundlePath(frameworkBundle) % QLatin1String("/Resources"); + if (qApp->applicationName() == QLatin1StringView(qWebEngineProcessName())) { + path = getBundlePath(frameworkBundle) % "/Resources"_L1; } else if (frameworkBundle) { CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(frameworkBundle); CFStringRef resourcesRelativePath = CFURLCopyFileSystemPath(resourcesRelativeUrl, kCFURLPOSIXPathStyle); @@ -121,9 +122,9 @@ QString subProcessPath() static QString processPath; if (processPath.isEmpty()) { #if defined(Q_OS_WIN) - const QString processBinary = QLatin1String(qWebEngineProcessName()) % QLatin1String(".exe"); + const QString processBinary = QLatin1StringView(qWebEngineProcessName()) % ".exe"_L1; #else - const QString processBinary = QLatin1String(qWebEngineProcessName()); + const auto processBinary = QLatin1StringView(qWebEngineProcessName()); #endif QStringList candidatePaths; @@ -133,8 +134,8 @@ QString subProcessPath() candidatePaths << fromEnv; } else { #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) - candidatePaths << getBundlePath(frameworkBundle()) % QStringLiteral("/Helpers/") - % qWebEngineProcessName() % QStringLiteral(".app/Contents/MacOS/") + candidatePaths << getBundlePath(frameworkBundle()) % "/Helpers/"_L1 + % qWebEngineProcessName() % ".app/Contents/MacOS/"_L1 % qWebEngineProcessName(); #else candidatePaths << QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath) @@ -155,18 +156,16 @@ QString subProcessPath() } } if (processPath.isEmpty()) { - QStringList errorMessage; - errorMessage.append( - QStringLiteral("The following paths were searched for Qt WebEngine Process:")); + QString errorMessage; + errorMessage += "The following paths were searched for Qt WebEngine Process:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - errorMessage.append(QStringLiteral(" ") % candidate); - errorMessage.append(QStringLiteral("but could not find it.")); + errorMessage += " "_L1 + candidate + u'\n'; + errorMessage += "but could not find it.\n"_L1; if (fromEnv.isEmpty()) { - errorMessage.append( - QStringLiteral("You may override the default search path by using " - "QTWEBENGINEPROCESS_PATH environment variable.")); + errorMessage += "You may override the default search path by using " + "QTWEBENGINEPROCESS_PATH environment variable.\n"_L1; } - qFatal("%s", qPrintable(errorMessage.join('\n'))); + qFatal("%ls", qUtf16Printable(errorMessage)); } #if defined(Q_OS_WIN) @@ -189,11 +188,7 @@ QString localesPath() if (potentialLocalesPath.isEmpty()) { QStringList candidatePaths; const QString translationPakFilename = -#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0) - QLatin1String(WebEngineLibraryInfo::getResolvedLocale() + ".pak"); -#else - QLatin1String((WebEngineLibraryInfo::getResolvedLocale() + ".pak").c_str()); -#endif + QLatin1StringView(WebEngineLibraryInfo::getResolvedLocale()) % ".pak"_L1; const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH"); if (!fromEnv.isEmpty()) { // Only search in QTWEBENGINE_LOCALES_PATH if set @@ -201,10 +196,10 @@ QString localesPath() } else { #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) candidatePaths << getResourcesPath(frameworkBundle()) % QDir::separator() - % QLatin1String("qtwebengine_locales"); + % "qtwebengine_locales"_L1; #endif candidatePaths << QLibraryInfo::path(QLibraryInfo::TranslationsPath) % QDir::separator() - % QLatin1String("qtwebengine_locales"); + % "qtwebengine_locales"_L1; candidatePaths << fallbackDir(); } @@ -218,22 +213,18 @@ QString localesPath() } if (potentialLocalesPath.isEmpty()) { - QStringList warningMessage; - warningMessage.append( - QStringLiteral("The following paths were searched for Qt WebEngine locales:")); + QString warningMessage; + warningMessage += "The following paths were searched for Qt WebEngine locales:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - warningMessage.append(QStringLiteral(" ") % candidate); - warningMessage.append( - QStringLiteral( - "but could not find the translation file for the current locale: ") - % translationPakFilename); + warningMessage += " "_L1 % candidate + u'\n'; + warningMessage += "but could not find the translation file for the current locale: "_L1 + + translationPakFilename + u'\n'; if (fromEnv.isEmpty()) { - warningMessage.append( - QStringLiteral("You may override the default search paths by using " - "QTWEBENGINE_LOCALES_PATH environment variable.")); + warningMessage += "You may override the default search paths by using " + "QTWEBENGINE_LOCALES_PATH environment variable.\n"_L1; } - warningMessage.append(QStringLiteral("Translations WILL NOT be correct.")); - qWarning("%s", qPrintable(warningMessage.join('\n'))); + warningMessage += "Translations WILL NOT be correct.\n"_L1; + qWarning("%ls", qUtf16Printable(warningMessage)); } } @@ -244,7 +235,7 @@ QString localesPath() QString dictionariesPath(bool showWarnings) { static QString potentialDictionariesPath; - static QStringList warningMessage; + static QString warningMessage; static bool initialized = false; QStringList candidatePaths; if (!initialized) { @@ -258,22 +249,22 @@ QString dictionariesPath(bool showWarnings) // First try to find dictionaries near the application. #ifdef Q_OS_DARWIN QString resourcesDictionariesPath = getMainApplicationResourcesPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + % QDir::separator() % "qtwebengine_dictionaries"_L1; candidatePaths << resourcesDictionariesPath; #endif QString applicationDictionariesPath = QCoreApplication::applicationDirPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + % QDir::separator() % "qtwebengine_dictionaries"_L1; candidatePaths << applicationDictionariesPath; // Then try to find dictionaries near the installed library. #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) - QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) - % QLatin1String("/qtwebengine_dictionaries"); + QString frameworkDictionariesPath = + getResourcesPath(frameworkBundle()) % "/qtwebengine_dictionaries"_L1; candidatePaths << frameworkDictionariesPath; #endif QString libraryDictionariesPath = QLibraryInfo::path(QLibraryInfo::DataPath) - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + % QDir::separator() % "qtwebengine_dictionaries"_L1; candidatePaths << libraryDictionariesPath; } @@ -286,22 +277,21 @@ QString dictionariesPath(bool showWarnings) } } if (potentialDictionariesPath.isEmpty()) { - warningMessage.append(QStringLiteral( - "The following paths were searched for Qt WebEngine dictionaries:")); + warningMessage += + "The following paths were searched for Qt WebEngine dictionaries:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - warningMessage.append(QStringLiteral(" ") % candidate); - warningMessage.append(QStringLiteral("but could not find it.")); + warningMessage += " "_L1 + candidate + u'\n'; + warningMessage += "but could not find it.\n"_L1; if (fromEnv.isEmpty()) { - warningMessage.append( - QStringLiteral("You may override the default search path by using " - "QTWEBENGINE_DICTIONARIES_PATH environment variable.")); + warningMessage += "You may override the default search path by using " + "QTWEBENGINE_DICTIONARIES_PATH environment variable.\n"_L1; } - warningMessage.append(QStringLiteral("Spellchecking can not be enabled.")); + warningMessage += "Spellchecking can not be enabled.\n"_L1; } } if (showWarnings && !warningMessage.isEmpty()) { - qWarning("%s", qPrintable(warningMessage.join('\n'))); + qWarning("%ls", qUtf16Printable(warningMessage)); } return potentialDictionariesPath; @@ -313,7 +303,7 @@ QString resourcesPath() static QString potentialResourcesPath; if (potentialResourcesPath.isEmpty()) { QStringList candidatePaths; - const QString resourcesPakFilename = QLatin1String("qtwebengine_resources.pak"); + const auto resourcesPakFilename = "qtwebengine_resources.pak"_L1; const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH"); if (!fromEnv.isEmpty()) { // Only search in QTWEBENGINE_RESOURCES_PATH if set @@ -323,7 +313,7 @@ QString resourcesPath() candidatePaths << getResourcesPath(frameworkBundle()); #endif candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath) % QDir::separator() - % QLatin1String("resources"); + % "resources"_L1; candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath); candidatePaths << QCoreApplication::applicationDirPath(); candidatePaths << fallbackDir(); @@ -339,18 +329,16 @@ QString resourcesPath() } if (potentialResourcesPath.isEmpty()) { - QStringList errorMessage; - errorMessage.append(QStringLiteral( - "The following paths were searched for Qt WebEngine resources:")); + QString errorMessage; + errorMessage += "The following paths were searched for Qt WebEngine resources:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - errorMessage.append(QStringLiteral(" ") % candidate); - errorMessage.append(QStringLiteral("but could not find any.")); + errorMessage += " "_L1 + candidate + u'\n'; + errorMessage += "but could not find any.\n"_L1; if (fromEnv.isEmpty()) { - errorMessage.append( - QStringLiteral("You may override the default search paths by using " - "QTWEBENGINE_RESOURCES_PATH environment variable.")); + errorMessage += "You may override the default search paths by using " + "QTWEBENGINE_RESOURCES_PATH environment variable.\n"_L1; } - qFatal("%s", qPrintable(errorMessage.join('\n'))); + qFatal("%ls", qUtf16Printable(errorMessage)); } } @@ -363,13 +351,13 @@ base::FilePath WebEngineLibraryInfo::getPath(int key, bool showWarnings) QString directory; switch (key) { case QT_RESOURCES_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_resources.pak"_L1); case QT_RESOURCES_100P_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_100p.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_resources_100p.pak"_L1); case QT_RESOURCES_200P_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_200p.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_resources_200p.pak"_L1); case QT_RESOURCES_DEVTOOLS_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_devtools_resources.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_devtools_resources.pak"_L1); #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) case QT_FRAMEWORK_BUNDLE: return toFilePath(getBundlePath(frameworkBundle())); diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 86f10315b2b..d47d6a9ced1 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -51,6 +51,8 @@ #endif #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { using namespace blink; @@ -61,24 +63,24 @@ static KeyboardDriver keyboardDriverImpl() { QString platformName = QGuiApplication::platformName(); - if (platformName == QLatin1String("windows")) + if (platformName == "windows"_L1) return KeyboardDriver::Windows; - if (platformName == QLatin1String("cocoa")) + if (platformName == "cocoa"_L1) return KeyboardDriver::Cocoa; - if (platformName == QLatin1String("xcb") || platformName == QLatin1String("wayland")) + if (platformName == "xcb"_L1 || platformName == "wayland"_L1) return KeyboardDriver::Xkb; #if QT_CONFIG(libinput) // Based on QEglFSIntegration::createInputHandlers and QLibInputKeyboard::processKey. - if (platformName == QLatin1String("eglfs") && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) + if (platformName == "eglfs"_L1 && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) return KeyboardDriver::Xkb; #endif #if QT_CONFIG(evdev) // Based on QEglFSIntegration::createInputHandlers. - if (platformName == QLatin1String("eglfs")) + if (platformName == "eglfs"_L1) return KeyboardDriver::Evdev; #endif From 95690ca93a791f691cd894c28f8d21459c174554 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 23 Jan 2025 16:28:37 +0100 Subject: [PATCH 253/341] Use unicode character literals - Fix QStringBuilder warnings when concatenating 8 bit characters - Prefer single character over one character long string literals Change-Id: Ibfec384b6e5421cb64255a5a52a43001724bf301 Reviewed-by: Marc Mutz (cherry picked from commit 6a67fd58bd3c8a4d0483e7f55672d0d07273940e) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit ce7a29201777a85da3d89b10c12f0af6ebb94eee) Reviewed-by: Allan Sandfeld Jensen --- src/core/content_browser_client_qt.cpp | 2 +- src/core/content_client_qt.cpp | 4 +-- src/core/devtools_manager_delegate_qt.cpp | 2 +- src/core/download_manager_delegate_qt.cpp | 2 +- src/core/file_picker_controller.cpp | 35 ++++++++++++---------- src/core/net/qrc_url_scheme_handler.cpp | 2 +- src/core/select_file_dialog_factory_qt.cpp | 2 +- 7 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 44d8ce0e278..1c12a72eaa5 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -991,7 +991,7 @@ blink::UserAgentMetadata ContentBrowserClientQt::GetUserAgentMetadata() std::string ContentBrowserClientQt::GetProduct() { - QString productName(qApp->applicationName() % '/' % qApp->applicationVersion()); + QString productName(qApp->applicationName() % u'/' % qApp->applicationVersion()); return productName.toStdString(); } diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 95d6ec4e3c6..19302c2d9ed 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -192,9 +192,9 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, if (!widevine_argument.empty()) pluginPaths << QtWebEngineCore::toQt(widevine_argument); else { - pluginPaths << webenginePluginsPath() + QStringLiteral("/") + QLatin1StringView(kWidevineCdmFileName); + pluginPaths << webenginePluginsPath() + u'/' + QLatin1StringView(kWidevineCdmFileName); #if QT_CONFIG(webengine_pepper_plugins) - pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QLatin1StringView(kWidevineCdmFileName); + pluginPaths << ppapiPluginsPath() + u'/' + QLatin1StringView(kWidevineCdmFileName); #endif #if defined(Q_OS_OSX) QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Frameworks"); diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp index 433effed4d8..47651929e6e 100644 --- a/src/core/devtools_manager_delegate_qt.cpp +++ b/src/core/devtools_manager_delegate_qt.cpp @@ -73,7 +73,7 @@ void DevToolsServerQt::parseAddressAndPort() if (commandLine.HasSwitch(switches::kRemoteDebuggingPort)) { portStr = QString::fromStdString(commandLine.GetSwitchValueASCII(switches::kRemoteDebuggingPort)); } else if (!inspectorEnv.isEmpty()) { - int portColonPos = inspectorEnv.lastIndexOf(':'); + int portColonPos = inspectorEnv.lastIndexOf(u':'); if (portColonPos != -1) { portStr = inspectorEnv.mid(portColonPos + 1); m_bindAddress = inspectorEnv.mid(0, portColonPos); diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 61f789c79ec..393e96ad0c2 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -154,7 +154,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * suggestedFilename = QStringLiteral("qwe_download"); QMimeType mimeType = QMimeDatabase().mimeTypeForName(mimeTypeString); if (mimeType.isValid() && !mimeType.preferredSuffix().isEmpty()) - suggestedFilename += QStringLiteral(".") + mimeType.preferredSuffix(); + suggestedFilename += u'.' + mimeType.preferredSuffix(); } QDir defaultDownloadDirectory(m_profileAdapter->downloadPath()); diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index fc52a387daa..098f1b40022 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -85,14 +85,14 @@ void FilePickerController::accepted(const QStringList &files) QString absolutePath; #if !defined(Q_OS_WIN) - absolutePath = "/"; + absolutePath += u'/'; #endif QString scheme = toQt(pathComponents[0]); if (scheme.size() > 5) { #if defined(Q_OS_WIN) // There is no slash at the end of the file scheme and it is valid on Windows: file:C:/ - if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == ':') { + if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == u':') { absolutePath += scheme.at(5) + ":/"_L1; } else { #endif @@ -108,11 +108,11 @@ void FilePickerController::accepted(const QStringList &files) && base::FilePath::IsSeparator(urlString.at(6).toLatin1()) && !base::FilePath::IsSeparator(urlString.at(7).toLatin1())) { #if defined(Q_OS_WIN) - if (urlString.at(8) != ':' && pathComponents.size() > 2) { + if (urlString.at(8) != u':' && pathComponents.size() > 2) { absolutePath += "//"_L1; #else if (pathComponents.size() > 2) { - absolutePath += "/"; + absolutePath += u'/'; #endif } else { qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); @@ -120,9 +120,12 @@ void FilePickerController::accepted(const QStringList &files) } } - // Build absolute path from file URI componenets. - for (size_t j = 1; j < pathComponents.size(); j++) - absolutePath += toQt(pathComponents[j]) + (j != pathComponents.size()-1 ? "/" : ""); + // Build absolute path from file URI components. + for (size_t j = 1; j < pathComponents.size(); j++) { + absolutePath += toQt(pathComponents[j]); + if (j != pathComponents.size() - 1) + absolutePath += u'/'; + } if (toFilePath(absolutePath).IsAbsolute()) { stringList.append(absolutePath); @@ -250,23 +253,23 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp return nameFilters; for (QString type : acceptedMimeTypes) { - if (type.startsWith(".")) { + if (type.startsWith(u'.')) { // A single suffix // Filename.type doesn't have to exist and mimeTypeForFile() supports // custom suffixes as valid (but unknown) MIME types. const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename" + type); if (mimeType.isValid()) { - QString glob = "*" + type; + QString glob = u'*' + type; acceptedGlobs.append(glob); - nameFilters.append(mimeType.comment() + " ("_L1 + glob + ")"); + nameFilters.append(mimeType.comment() + " ("_L1 + glob + u')'); } - } else if (type.contains("/") && !type.endsWith("*")) { + } else if (type.contains(u'/') && !type.endsWith(u'*')) { // All suffixes for a given MIME type const QMimeType &mimeType = mimeDatabase.mimeTypeForName(type); if (mimeType.isValid() && !mimeType.globPatterns().isEmpty()) { - QString globs = mimeType.globPatterns().join(" "); + QString globs = mimeType.globPatterns().join(u' '); acceptedGlobs.append(mimeType.globPatterns()); - nameFilters.append(mimeType.comment() + " ("_L1 + globs + ")"); + nameFilters.append(mimeType.comment() + " ("_L1 + globs + u')'); } } else if (type.endsWith("/*"_L1)) { // All MIME types for audio/*, image/* or video/* @@ -275,9 +278,9 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp type = type.remove("/*"); for (const QMimeType &m : allMimeTypes) { if (m.name().startsWith(type) && !m.globPatterns().isEmpty()) { - QString globs = m.globPatterns().join(" "); + QString globs = m.globPatterns().join(u' '); acceptedGlobs.append(m.globPatterns()); - nameFilters.append(m.comment() + " ("_L1 + globs + ")"); + nameFilters.append(m.comment() + " ("_L1 + globs + u')'); } } } else { @@ -287,7 +290,7 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp const QString filter = QCoreApplication::translate("FilePickerController", - "Accepted types (%1)").arg(acceptedGlobs.join(' ')); + "Accepted types (%1)").arg(acceptedGlobs.join(u' ')); nameFilters.prepend(filter); return nameFilters; diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp index 82554827ead..f1925da14dd 100644 --- a/src/core/net/qrc_url_scheme_handler.cpp +++ b/src/core/net/qrc_url_scheme_handler.cpp @@ -26,7 +26,7 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) QUrl requestUrl = job->requestUrl(); QString requestPath = requestUrl.path(); - auto file = std::make_unique(':' + requestPath, job); + auto file = std::make_unique(u':' + requestPath, job); if (!file->exists() || file->size() == 0) { qWarning("QResource '%s' not found or is empty", qUtf8Printable(requestPath)); job->fail(QWebEngineUrlRequestJob::UrlNotFound); diff --git a/src/core/select_file_dialog_factory_qt.cpp b/src/core/select_file_dialog_factory_qt.cpp index 1f897a805c3..f3f35c1aa6a 100644 --- a/src/core/select_file_dialog_factory_qt.cpp +++ b/src/core/select_file_dialog_factory_qt.cpp @@ -119,7 +119,7 @@ void SelectFileDialogQt::SelectFileImpl(Type type, const std::u16string &title, if (file_types) { for (const auto &type : file_types->extensions) { for (const auto &extension : type) - acceptedSuffixes.append("." + toQt(extension)); + acceptedSuffixes.append(u'.' + toQt(extension)); } } From 093df5a6c33820adfedd2c48339e817b2c81753d Mon Sep 17 00:00:00 2001 From: Andreas Eliasson Date: Wed, 18 Dec 2024 13:34:00 +0100 Subject: [PATCH 254/341] Doc: Add link to qt_add_webengine_dictionary in spell checker section The cmake command qt_add_webengine_dictionary was introduced in 6.3. Add a link and a short description of the command in the spell checker section. Fixes: QTBUG-131904 Change-Id: I5f5a2f307ce972b36c5d57c4d2ba37dab2c37343 Reviewed-by: Michal Klocek (cherry picked from commit d813d9b8b37289d3c9773b443479e64d32faf9ec) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 5c48638af3b31560305e6f1ad5617348d965b62f) --- src/core/doc/src/qtwebengine-features.qdoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/doc/src/qtwebengine-features.qdoc b/src/core/doc/src/qtwebengine-features.qdoc index 1dc58a133ea..6599a229f96 100644 --- a/src/core/doc/src/qtwebengine-features.qdoc +++ b/src/core/doc/src/qtwebengine-features.qdoc @@ -643,6 +643,11 @@ When the \QWE spellchecker initializes, it will try to load the \c bdict dictionaries and to check them for consistency. + For CMake, you can use the \l qt_add_webengine_dictionary command to convert + Hunspell \c .dic files into the \c .bdic binary format. The command creates + a \c qtwebengine_dictionaries target, which your project can use a + dependency. + If \c QTWEBENGINE_DICTIONARIES_PATH is set, the spellchecker uses the dictionaries in the specified directory without looking anywere else. Otherwise, it uses the \e qtwebengine_dictionaries directory relative to the From 04981e005db976d9740ac357c42b6c8203ba0c3d Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Thu, 6 Feb 2025 16:22:23 +0100 Subject: [PATCH 255/341] Bump permissionbrowser example cmake version All our other examples use 3.16, and cmake 3.30 now gives a deprecation warning about this. Change-Id: If2aff723cedab0339ba506484b44bddd89858307 Reviewed-by: Anu Aliyas (cherry picked from commit 7feb1ff93040ad1e40e86fadf04c107aa9f4806c) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 6ba27b8bc8ab191c743f046d4b58d574b4abf5a1) --- examples/webenginewidgets/permissionbrowser/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt index c4d8f9cd43e..c7d241d8f67 100644 --- a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt +++ b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2024 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) project(permissionbrowser LANGUAGES CXX) set(CMAKE_AUTOMOC ON) From eb24f979145df02bbd9384c9b664d2e98aa72a7a Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 10 Dec 2024 09:35:12 +0100 Subject: [PATCH 256/341] Fix clang libraries path detection So far we passed clang_base_path and clang_version as major version of clang compiler so gn could assemble clang runtime libraries path. However this approach does not always correctly work as some machines can have single or multiple number version. In this case path can take a form of: ../XcodeDefault.xctoolchain/usr/lib/clang/16 some other machines have major,minor,patch level form, like: ../XcodeDefault.xctoolchain/usr/lib/clang/15.0.0 Moreover clang compiler version is 4 digit value, so this can still have different variations. Instead of trying guess the path based on some logic simply ask clang compiler what is runtime dir path. Unfortunately we can just push this path to gn since this path has to be adjusted for target or host clang runtime libs during gn run. Therefore get runtime libs path from clang compiler, however use it to extract version number which is used in filesystem and this later is used to assemble library path in gn. Cache the variable so we run this check once during configure. Change-Id: I912ab7d5d7b32e1cbe19fa3e8da012f669f6bec7 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit f13bb554d14bab8ba35d814d14c0e72c485f023b) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit af78aa72e2425421cbb2919bdfbc8dbcc894ee11) --- cmake/Functions.cmake | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index f957bea42e9..8d5a977771d 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -887,6 +887,25 @@ macro(append_build_type_setup) ) endmacro() +function(get_clang_version_from_runtime_path result) +if(CLANG AND CMAKE_CXX_COMPILER) + if( NOT DEFINED CLANG_RUNTIME_PATH) + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} -print-runtime-dir + OUTPUT_VARIABLE clang_output + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + cmake_path(CONVERT "${clang_output}" TO_CMAKE_PATH_LIST clang_output NORMALIZE) + set(CLANG_RUNTIME_PATH "${clang_output}" CACHE INTERNAL "internal") + mark_as_advanced(CLANG_RUNTIME_PATH) + endif() + string(REGEX MATCH "\\/([0-9.]+)\\/" clang_run_time_path_version "${CLANG_RUNTIME_PATH}") + string(REPLACE "/" "" clang_run_time_path_version ${clang_run_time_path_version}) + set(${result} ${clang_run_time_path_version} PARENT_SCOPE) +endif() +endfunction() + macro(append_compiler_linker_sdk_setup) if(CMAKE_CXX_COMPILER_LAUNCHER) list(APPEND gnArgArg cc_wrapper="${CMAKE_CXX_COMPILER_LAUNCHER}") @@ -907,12 +926,16 @@ macro(append_compiler_linker_sdk_setup) get_filename_component(clangBasePath ${CMAKE_CXX_COMPILER} DIRECTORY) get_filename_component(clangBasePath ${clangBasePath} DIRECTORY) endif() - - string(REGEX MATCH "[0-9]+" clangVersion ${CMAKE_CXX_COMPILER_VERSION}) + get_clang_version_from_runtime_path(clang_version) + if (NOT DEFINED clang_version) + message(FATAL_ERROR "Clang version for runtime is missing." + "Please open bug report.Found clang runtime path: ${CLANG_RUNTIME_PATH}" + ) + endif() list(APPEND gnArgArg clang_base_path="${clangBasePath}" + clang_version="${clang_version}" clang_use_chrome_plugins=false - clang_version=${clangVersion} fatal_linker_warnings=false ) From 78863287a4c019651ffd36dfc78d6f9f776c4fc6 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Thu, 6 Feb 2025 16:21:03 +0100 Subject: [PATCH 257/341] Remove unused lambda captures Clang warns about these when compiling. Change-Id: Idf0daf9f4b7c71fefaddb4531d9ed164e90d118e Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Anu Aliyas (cherry picked from commit c4cd6aa4df40e8c62f2f1209e036286e6cec1b1f) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit a922d5905c4e329688db482c47476beb48794d4e) --- examples/webenginewidgets/clientcertificate/client.cpp | 2 +- examples/webenginewidgets/maps/mainwindow.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/webenginewidgets/clientcertificate/client.cpp b/examples/webenginewidgets/clientcertificate/client.cpp index de09120ca0d..c10cff24769 100644 --- a/examples/webenginewidgets/clientcertificate/client.cpp +++ b/examples/webenginewidgets/clientcertificate/client.cpp @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) QObject::connect( &page, &QWebEnginePage::selectClientCertificate, &page, - [&cert](QWebEngineClientCertificateSelection selection) { + [](QWebEngineClientCertificateSelection selection) { QDialog dialog; QVBoxLayout *layout = new QVBoxLayout; QLabel *label = new QLabel(QLatin1String("Select certificate")); diff --git a/examples/webenginewidgets/maps/mainwindow.cpp b/examples/webenginewidgets/maps/mainwindow.cpp index 07b8d8ab3da..31cc0bbf0cb 100644 --- a/examples/webenginewidgets/maps/mainwindow.cpp +++ b/examples/webenginewidgets/maps/mainwindow.cpp @@ -13,8 +13,7 @@ MainWindow::MainWindow(QWidget *parent) QWebEnginePage *page = m_view->page(); - connect(page, &QWebEnginePage::permissionRequested, - [this, page](QWebEnginePermission permission) { + connect(page, &QWebEnginePage::permissionRequested, [this](QWebEnginePermission permission) { if (permission.permissionType() != QWebEnginePermission::PermissionType::Geolocation) return; From b9231f8b20914498a3fa697d65df68d23eb3818f Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 6 Feb 2025 12:37:41 +0100 Subject: [PATCH 258/341] macOS: Fix code signing for manual tests - Fix path for -debug-and-release build - Fix ".app: is already signed" error during build Change-Id: I63c8a34be9e531fa07e2ac2f39ad4f6a67b4be65 Reviewed-by: Anu Aliyas (cherry picked from commit 9a66024228ecbc2251f7ea4185bda74d11c2c600) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit ba8f5af7e688aa5e17c55ff96d2db6c3fe92031a) --- tests/manual/quick/geopermission/CMakeLists.txt | 7 ++++++- tests/manual/widgets/geolocation/CMakeLists.txt | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/manual/quick/geopermission/CMakeLists.txt b/tests/manual/quick/geopermission/CMakeLists.txt index 6602ceb6ff6..e6f91356074 100644 --- a/tests/manual/quick/geopermission/CMakeLists.txt +++ b/tests/manual/quick/geopermission/CMakeLists.txt @@ -49,8 +49,13 @@ if (APPLE) if (NOT CMAKE_GENERATOR STREQUAL "Xcode") # Need to sign application for location permissions to work + if(QT_FEATURE_debug_and_release) + set(exe_path "${CMAKE_CURRENT_BINARY_DIR}/$/") + else() + unset(exe_path) + endif() add_custom_command(TARGET tst_geopermission - POST_BUILD COMMAND codesign -s - tst_geopermission.app) + POST_BUILD COMMAND codesign --force -s - ${exe_path}tst_geopermission.app) endif() endif() diff --git a/tests/manual/widgets/geolocation/CMakeLists.txt b/tests/manual/widgets/geolocation/CMakeLists.txt index 2ca8c2f524b..25704bfdff2 100644 --- a/tests/manual/widgets/geolocation/CMakeLists.txt +++ b/tests/manual/widgets/geolocation/CMakeLists.txt @@ -49,7 +49,12 @@ if (APPLE) if (NOT CMAKE_GENERATOR STREQUAL "Xcode") # Need to sign application for location permissions to work + if(QT_FEATURE_debug_and_release) + set(exe_path "${CMAKE_CURRENT_BINARY_DIR}/$/") + else() + unset(exe_path) + endif() add_custom_command(TARGET geolocation - POST_BUILD COMMAND codesign -s - geolocation.app) + POST_BUILD COMMAND codesign --force -s - ${exe_path}geolocation.app) endif() endif() From fc9e81c808e837433f8ad08af4efe1767b786df8 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Fri, 7 Feb 2025 15:15:04 +0100 Subject: [PATCH 259/341] Fix Widevine path detection on ARM macOS The path to the Widevine CDM plugin on macOS was hardcoded to where it's located on x64 machines, which led to DRM content not working on ARM-based machines. Fixes: QTBUG-133558 Change-Id: I723033dfd7d011b1d8635fb88549c7fd58331856 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit b13fd82027b73bc4addab727f9fa818d65c1dde0) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 50b7e625daab642aba6d33546a366d5783e734cd) --- src/core/content_client_qt.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 19302c2d9ed..0b16c01e9b2 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #if BUILDFLAG(ENABLE_LIBRARY_CDMS) @@ -198,13 +199,16 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, #endif #if defined(Q_OS_OSX) QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Frameworks"); + const auto archDir = QSysInfo::currentCpuArchitecture() == "x86_64"_L1 + ? "mac_x64/"_L1 + : "mac_arm64/"_L1; if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); - const auto library = - "/Versions/Current/Libraries/WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib"_L1; + const auto libraryBase = "/Versions/Current/Libraries/WidevineCdm/_platform_specific/"_L1; + const auto libraryFilename = "libwidevinecdm.dylib"_L1; for (const QFileInfo &info : widevineVersionDirs) - pluginPaths << info.absoluteFilePath() + library; + pluginPaths << info.absoluteFilePath() + libraryBase + archDir + libraryFilename; } QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"_L1); @@ -212,7 +216,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, QFileInfoList widevineVersionDirs = oldPotentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/"_L1 + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/"_L1 + archDir + QLatin1StringView(kWidevineCdmFileName); pluginPaths << potentialWidevinePluginPath; } From b35886854e4595369791343a58cb66187219fd1e Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 11 Feb 2025 14:11:05 +0100 Subject: [PATCH 260/341] Fix flaky tst_QWebEngineView::keyboardFocusAfterPopup on macOS On macOS, Qt closes all popups when NSWindowDidResignKeyNotification event is triggered by the OS, see QTBUG-105474. This event somehow is triggered after we call show() on a widget. The event might be triggered while the QCompleter's popup is already open and it breaks the test. Wait for the OS events to be processed with qWaitForWindowExposed(). Fixes: QTBUG-133590 Change-Id: I51b05df375046fcfb28ae213173a517d60216ae2 Reviewed-by: Anu Aliyas (cherry picked from commit 6845b1d256efd2abf5f45b333de3b03bb80a58a2) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 3670fe65d797a012cce3882df39c378eee61c12c) --- tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 2eec0901a69..d44167d9de8 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -1620,6 +1620,7 @@ void tst_QWebEngineView::keyboardFocusAfterPopup() connect(window.lineEdit, &QLineEdit::editingFinished, [&] { window.webView->setHtml(html); }); window.webView->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); // Focus will initially go to the QLineEdit. QTRY_COMPARE(QApplication::focusWidget(), window.lineEdit); From 6da5aeb5dae0e72358297f8655ca29de27b62721 Mon Sep 17 00:00:00 2001 From: Anu Aliyas Date: Wed, 12 Feb 2025 16:19:22 +0100 Subject: [PATCH 261/341] Perform the focus check earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While loading URLs, QtWebEngine will remove the old widget from the layout and then add the new widget. When hiding the old widget from the layout, it loses focus. As a result, the focus is not set to the new widget. Modified the code to check whether the old widget has focus before it is hidden. Amends e227bbddbfc03c45735978f5b83994235225569a Fixes: QTBUG-133649 Change-Id: Iac4b1317ed469bfa32e18f0e18361a2279b77cf6 Reviewed-by: Michael BrĂ¼ning (cherry picked from commit c8f8749e8810e33396b1dbf7f65e3b58f7b8be39) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 4942d3cee3f2c7bf643dea6901765252923509ed) --- src/webenginewidgets/api/qwebengineview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 0ef881b5ae7..4a96a92fce2 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -439,6 +439,7 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget { Q_Q(QWebEngineView); + bool hasFocus = oldWidget ? oldWidget->hasFocus() : false; if (oldWidget) { q->layout()->removeWidget(oldWidget); oldWidget->hide(); @@ -457,7 +458,7 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget #endif q->layout()->addWidget(newWidget); q->setFocusProxy(newWidget); - if (oldWidget && oldWidget == QApplication::focusWidget()) + if (hasFocus) newWidget->setFocus(); newWidget->show(); } From 7eb5f8a92c2ab02fc8cb97748ad1cea598880438 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 10 Feb 2025 15:52:07 +0100 Subject: [PATCH 262/341] qwebengine_convert_dict: Avoid to construct QString for a character Change-Id: Icd44c96715358c92f21e82e42352e58c3c8bc4d7 Reviewed-by: Marc Mutz (cherry picked from commit cb8527103f0f21155694345e75ed11afd7aeb8db) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit ea6fac65ce76b2fac827579994e793d1c0659d1c) --- src/core/tools/qwebengine_convert_dict/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/tools/qwebengine_convert_dict/main.cpp b/src/core/tools/qwebengine_convert_dict/main.cpp index b49ae0279a5..5dc750ee261 100644 --- a/src/core/tools/qwebengine_convert_dict/main.cpp +++ b/src/core/tools/qwebengine_convert_dict/main.cpp @@ -70,11 +70,11 @@ template QTextStream &operator<<(QTextStream &out, base::span span) { out << '['; - QString prefix; + QLatin1StringView prefix; for (const auto &element : span) { out << prefix; out << element; - prefix = QStringLiteral(","); + prefix = ","_L1; } out << ']'; return out; From 70149a85de61c6775a335f734778421f2d7220a6 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 12 Feb 2025 15:50:33 +0100 Subject: [PATCH 263/341] Fix source file path reported in "js" logging category Also add auto tests for validating javaScriptConsoleMessage() arguments. Change-Id: Ife6a2db66898a15071b6f8d082195794f2f45e27 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit ef4e9a07bda2e676a02435080355be30dc0abf09) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 4a6ff28b8797e16460d44675d85d57f11a1c6138) --- src/core/api/qwebenginepage.cpp | 2 +- .../html/resources/hello.js | 7 ++ .../qquickwebengineview/html/resources/hi.js | 8 ++ .../qquickwebengineview/html/script2.html | 4 + .../tst_qquickwebengineview.cpp | 79 +++++++++++++++++++ .../widgets/qwebenginepage/CMakeLists.txt | 3 + .../widgets/qwebenginepage/resources/hello.js | 7 ++ .../widgets/qwebenginepage/resources/hi.js | 8 ++ .../qwebenginepage/resources/script2.html | 4 + .../qwebenginepage/tst_qwebenginepage.cpp | 77 +++++++++++++++++- 10 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 tests/auto/quick/qquickwebengineview/html/resources/hello.js create mode 100644 tests/auto/quick/qquickwebengineview/html/resources/hi.js create mode 100644 tests/auto/quick/qquickwebengineview/html/script2.html create mode 100644 tests/auto/widgets/qwebenginepage/resources/hello.js create mode 100644 tests/auto/widgets/qwebenginepage/resources/hi.js create mode 100644 tests/auto/widgets/qwebenginepage/resources/script2.html diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index b180b58b99d..826d8ce492c 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -2283,7 +2283,7 @@ bool QWebEnginePage::javaScriptPrompt(const QUrl &securityOrigin, const QString void QWebEnginePage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID) { static QLoggingCategory loggingCategory("js", QtWarningMsg); - static QByteArray file = sourceID.toUtf8(); + const QByteArray file = sourceID.toUtf8(); QMessageLogger logger(file.constData(), lineNumber, nullptr, loggingCategory.categoryName()); switch (level) { diff --git a/tests/auto/quick/qquickwebengineview/html/resources/hello.js b/tests/auto/quick/qquickwebengineview/html/resources/hello.js new file mode 100644 index 00000000000..6f5e79ebf4d --- /dev/null +++ b/tests/auto/quick/qquickwebengineview/html/resources/hello.js @@ -0,0 +1,7 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHello() +{ + console.warn("hello"); +} diff --git a/tests/auto/quick/qquickwebengineview/html/resources/hi.js b/tests/auto/quick/qquickwebengineview/html/resources/hi.js new file mode 100644 index 00000000000..30e7cc972d1 --- /dev/null +++ b/tests/auto/quick/qquickwebengineview/html/resources/hi.js @@ -0,0 +1,8 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHi() +{ + // Placeholder + console.warn("hi"); +} diff --git a/tests/auto/quick/qquickwebengineview/html/script2.html b/tests/auto/quick/qquickwebengineview/html/script2.html new file mode 100644 index 00000000000..5faf58daab3 --- /dev/null +++ b/tests/auto/quick/qquickwebengineview/html/script2.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index b4eaeb37c18..1177d8adf53 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -27,6 +27,8 @@ #include +using namespace Qt::StringLiterals; + class tst_QQuickWebEngineView : public QObject { Q_OBJECT public: @@ -80,6 +82,7 @@ private Q_SLOTS: void htmlSelectPopup(); void savePage_data(); void savePage(); + void javaScriptConsoleMessage(); private: inline QQuickWebEngineView *newWebEngineView(); @@ -1362,6 +1365,82 @@ void tst_QQuickWebEngineView::savePage() originalData); } +class TestJSMessageHandler +{ +public: + inline static QList levels; + inline static QStringList messages; + inline static QList lineNumbers; + inline static QStringList sourceIDs; + + static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) + { + if (strcmp(context.category, "js") != 0) { + m_originalHandler(type, context, msg); + return; + } + + levels.append(type); + messages.append(msg); + lineNumbers.append(context.line); + sourceIDs.append(context.file); + } + + TestJSMessageHandler() { m_originalHandler = qInstallMessageHandler(handler); } + ~TestJSMessageHandler() { qInstallMessageHandler(m_originalHandler); } + +private: + inline static QtMessageHandler m_originalHandler = nullptr; +}; + +void tst_QQuickWebEngineView::javaScriptConsoleMessage() +{ + QQuickWebEngineView *view = webEngineView(); + + // Test QQuickWebEngineView::javaScriptConsoleMessage() signal. + { + QSignalSpy jsSpy( + view, + SIGNAL(javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel, + const QString &, int, const QString &))); + view->setUrl(urlFromTestPath("html/script2.html")); + QVERIFY(waitForLoadSucceeded(view)); + + runJavaScript("sayHello()"); + QTRY_COMPARE(jsSpy.size(), 1); + QCOMPARE(jsSpy.last().at(0).toInt(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(jsSpy.last().at(1).toString(), "hello"_L1); + QCOMPARE(jsSpy.last().at(2).toInt(), 6); + QCOMPARE(jsSpy.last().at(3).toString(), urlFromTestPath("html/resources/hello.js")); + + runJavaScript("sayHi()"); + QTRY_COMPARE(jsSpy.size(), 2); + QCOMPARE(jsSpy.last().at(0).toInt(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(jsSpy.last().at(1).toString(), "hi"_L1); + QCOMPARE(jsSpy.last().at(2).toInt(), 7); + QCOMPARE(jsSpy.last().at(3).toString(), urlFromTestPath("html/resources/hi.js")); + } + + // Test default QQuickWebEngineViewPrivate::javaScriptConsoleMessage() handler. + { + TestJSMessageHandler handler; + view->setUrl(urlFromTestPath("html/script2.html")); + QVERIFY(waitForLoadSucceeded(view)); + + evaluateJavaScriptSync(view, "sayHello()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hello"_L1); + QCOMPARE(handler.lineNumbers.last(), 6); + QCOMPARE(handler.sourceIDs.last(), urlFromTestPath("html/resources/hello.js")); + + evaluateJavaScriptSync(view, "sayHi()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hi"_L1); + QCOMPARE(handler.lineNumbers.last(), 7); + QCOMPARE(handler.sourceIDs.last(), urlFromTestPath("html/resources/hi.js")); + } +} + #if QT_CONFIG(accessibility) static QByteArrayList params = QByteArrayList() << "--force-renderer-accessibility"; diff --git a/tests/auto/widgets/qwebenginepage/CMakeLists.txt b/tests/auto/widgets/qwebenginepage/CMakeLists.txt index 55c35af8810..a0470e25a37 100644 --- a/tests/auto/widgets/qwebenginepage/CMakeLists.txt +++ b/tests/auto/widgets/qwebenginepage/CMakeLists.txt @@ -30,6 +30,8 @@ set(tst_qwebenginepage_resource_files "resources/frame_c.html" "resources/framedindex.html" "resources/fullscreen.html" + "resources/hello.js" + "resources/hi.js" "resources/iframe.html" "resources/iframe2.html" "resources/iframe3.html" @@ -40,6 +42,7 @@ set(tst_qwebenginepage_resource_files "resources/path with spaces.txt" "resources/reload.html" "resources/script.html" + "resources/script2.html" "resources/style.css" "resources/test1.html" "resources/test2.html" diff --git a/tests/auto/widgets/qwebenginepage/resources/hello.js b/tests/auto/widgets/qwebenginepage/resources/hello.js new file mode 100644 index 00000000000..6f5e79ebf4d --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/hello.js @@ -0,0 +1,7 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHello() +{ + console.warn("hello"); +} diff --git a/tests/auto/widgets/qwebenginepage/resources/hi.js b/tests/auto/widgets/qwebenginepage/resources/hi.js new file mode 100644 index 00000000000..30e7cc972d1 --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/hi.js @@ -0,0 +1,8 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHi() +{ + // Placeholder + console.warn("hi"); +} diff --git a/tests/auto/widgets/qwebenginepage/resources/script2.html b/tests/auto/widgets/qwebenginepage/resources/script2.html new file mode 100644 index 00000000000..7d511503771 --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/script2.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index e8dac91e788..31c82b28a8b 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -80,6 +80,8 @@ #include #include +using namespace Qt::StringLiterals; + static void removeRecursive(const QString& dirname) { QDir dir(dirname); @@ -137,6 +139,7 @@ private Q_SLOTS: void backActionUpdate(); void localStorageVisibility(); void consoleOutput(); + void javaScriptConsoleMessage(); void userAgentNewlineStripping(); void renderWidgetHostViewNotShowTopLevel(); void getUserMediaRequest_data(); @@ -613,7 +616,7 @@ class ConsolePage : public QWebEnginePage sourceIDs.append(sourceID); } - QList levels; + QList levels; QStringList messages; QList lineNumbers; QStringList sourceIDs; @@ -628,6 +631,78 @@ void tst_QWebEnginePage::consoleOutput() QCOMPARE(page.lineNumbers.at(0), 1); } +class TestJSMessageHandler +{ +public: + inline static QList levels; + inline static QStringList messages; + inline static QList lineNumbers; + inline static QStringList sourceIDs; + + static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) + { + if (strcmp(context.category, "js") != 0) { + m_originalHandler(type, context, msg); + return; + } + + levels.append(type); + messages.append(msg); + lineNumbers.append(context.line); + sourceIDs.append(context.file); + } + + TestJSMessageHandler() { m_originalHandler = qInstallMessageHandler(handler); } + ~TestJSMessageHandler() { qInstallMessageHandler(m_originalHandler); } + +private: + inline static QtMessageHandler m_originalHandler = nullptr; +}; + +void tst_QWebEnginePage::javaScriptConsoleMessage() +{ + // Test overridden QWebEnginePage::javaScriptConsoleMessage(). + { + ConsolePage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + page.load(QUrl("qrc:///resources/script2.html")); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000); + + evaluateJavaScriptSync(&page, "sayHello()"); + QCOMPARE(page.levels.last(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(page.messages.last(), "hello"_L1); + QCOMPARE(page.lineNumbers.last(), 6); + QCOMPARE(page.sourceIDs.last(), "qrc:///resources/hello.js"_L1); + + evaluateJavaScriptSync(&page, "sayHi()"); + QCOMPARE(page.levels.last(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(page.messages.last(), "hi"_L1); + QCOMPARE(page.lineNumbers.last(), 7); + QCOMPARE(page.sourceIDs.last(), "qrc:///resources/hi.js"_L1); + } + + // Test default QWebEnginePage::javaScriptConsoleMessage() handler. + { + TestJSMessageHandler handler; + QWebEnginePage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + page.load(QUrl("qrc:///resources/script2.html")); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000); + + evaluateJavaScriptSync(&page, "sayHello()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hello"_L1); + QCOMPARE(handler.lineNumbers.last(), 6); + QCOMPARE(handler.sourceIDs.last(), "qrc:///resources/hello.js"_L1); + + evaluateJavaScriptSync(&page, "sayHi()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hi"_L1); + QCOMPARE(handler.lineNumbers.last(), 7); + QCOMPARE(handler.sourceIDs.last(), "qrc:///resources/hi.js"_L1); + } +} + class TestPage : public QWebEnginePage { Q_OBJECT public: From 89a0f31c2532c4b621556767161dea22e8766370 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 14 Feb 2025 10:41:14 +0100 Subject: [PATCH 264/341] Fix flaky tst_QWebEnginePage::discardAbortsPendingLoadAndPreservesCommittedLoad The test fail was reproducible on arm64 macOS but it could happen on any platform if it is fast enough. The about:blank page load is interrupted by Discarded lifecycle state in the test. Loading about:blank can be so fast that the navigation is committed before we could send the QWebEnginePage::loadStarted signal. Interrupting the load at this point won't restore the previous commit and breaks the test. As a fix, load a page from the disk which load time is potentially longer than the about:blank page's load time. Change-Id: Id885f8a67b5566c5ad9024e40ce36153ff03f832 Reviewed-by: Anu Aliyas (cherry picked from commit 0730ae7dd64aeef7a23a3a108b95c5057292c56f) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 2d3eb5d56da519bf788704f24545082f82b176db) --- tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 31c82b28a8b..9fd9d2a58c0 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -4789,7 +4789,7 @@ void tst_QWebEnginePage::discardAbortsPendingLoadAndPreservesCommittedLoad() connect(&page, &QWebEnginePage::loadStarted, [&]() { page.setLifecycleState(QWebEnginePage::LifecycleState::Discarded); }); - QString url2 = QStringLiteral("about:blank"); + QString url2 = QStringLiteral("qrc:/resources/test1.html"); page.setUrl(url2); QTRY_COMPARE(loadStartedSpy.size(), 1); loadStartedSpy.clear(); From 77a14558feb6e97fa7b03d2c8e49b2c7d12e35db Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 6 Feb 2025 15:22:21 +0100 Subject: [PATCH 265/341] Do not assign the first part of string in case of concatenations This may avoid unnecessary QString allocations. Change-Id: I9b1c2d3ce06c6798f6b777660f897c02deb8fbfd Reviewed-by: Marc Mutz (cherry picked from commit 12f8f37e1a81fd9dcb5c2925e5a9b5e0df500ad1) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 3dcf43316be6f3383d232d649ae2a6c78a977fce) --- src/core/clipboard_qt.cpp | 5 +++-- src/core/download_manager_delegate_qt.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index cd63b0b6f29..39955719005 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -136,13 +136,14 @@ void ClipboardQt::WriteHTML(base::StringPiece markup, absl::optional"_L1); + markup_string += ""_L1; #endif + markup_string += toQString(markup); #if !defined(Q_OS_WIN) getUncommittedData()->setHtml(markup_string); diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 393e96ad0c2..ec80d548a91 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -151,7 +151,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * } if (suggestedFilename.isEmpty()) { - suggestedFilename = QStringLiteral("qwe_download"); + suggestedFilename += QStringLiteral("qwe_download"); QMimeType mimeType = QMimeDatabase().mimeTypeForName(mimeTypeString); if (mimeType.isValid() && !mimeType.preferredSuffix().isEmpty()) suggestedFilename += u'.' + mimeType.preferredSuffix(); From 06b0c1f0c36f994721fb6e4a84101fabd3ceb160 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 23 Jan 2025 16:42:00 +0100 Subject: [PATCH 266/341] Remove unnecessary QString conversions Some of them fix compiler warnings. Change-Id: I93a605090567ae9cd2a101d83eeaac88f39b9ffa Reviewed-by: Marc Mutz Reviewed-by: Michal Klocek (cherry picked from commit ecb4782cbc058047068603f41140fe3e28e7d9a3) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 64893881c14ba36ce7002e5177b9df2c19c18a88) --- src/core/devtools_manager_delegate_qt.cpp | 5 +++-- src/core/file_picker_controller.cpp | 2 +- src/core/net/cookie_monster_delegate_qt.cpp | 2 +- src/core/render_view_context_menu_qt.cpp | 2 +- src/core/user_script.cpp | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp index 47651929e6e..838964d01be 100644 --- a/src/core/devtools_manager_delegate_qt.cpp +++ b/src/core/devtools_manager_delegate_qt.cpp @@ -124,8 +124,9 @@ void DevToolsServerQt::stop() void DevToolsManagerDelegateQt::Initialized(const net::IPEndPoint *ip_address) { if (ip_address && ip_address->address().size()) { - QString addressAndPort = QString::fromStdString(ip_address->ToString()); - qWarning("Remote debugging server started successfully. Try pointing a Chromium-based browser to http://%s", qPrintable(addressAndPort)); + qWarning("Remote debugging server started successfully. " + "Try pointing a Chromium-based browser to http://%s", + ip_address->ToString().c_str()); } else qWarning("Couldn't start the inspector server on bind address. In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface)."); diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 098f1b40022..e7b7de7b192 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -275,7 +275,7 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp // All MIME types for audio/*, image/* or video/* // as separate filters as Chrome does static const QList &allMimeTypes = mimeDatabase.allMimeTypes(); - type = type.remove("/*"); + type.chop(2); for (const QMimeType &m : allMimeTypes) { if (m.name().startsWith(type) && !m.globPatterns().isEmpty()) { QString globs = m.globPatterns().join(u' '); diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp index d107c520c41..da5f50c75cc 100644 --- a/src/core/net/cookie_monster_delegate_qt.cpp +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -50,7 +50,7 @@ class CookieAccessFilter : public network::mojom::CookieRemoteAccessFilter static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { - QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); + const QString urlFragment = cookie.domain() % cookie.path(); return net::cookie_util::CookieOriginToURL(urlFragment.toStdString(), /* is_https */ cookie.isSecure()); } diff --git a/src/core/render_view_context_menu_qt.cpp b/src/core/render_view_context_menu_qt.cpp index b7aabfd5b66..089b9202003 100644 --- a/src/core/render_view_context_menu_qt.cpp +++ b/src/core/render_view_context_menu_qt.cpp @@ -36,7 +36,7 @@ namespace QtWebEngineCore { QT_TRANSLATE_NOOP("RenderViewContextMenuQt", "Save page"), QT_TRANSLATE_NOOP("RenderViewContextMenuQt", "View page source") }; - return QCoreApplication::translate("RenderViewContextMenuQt", qUtf8Printable(names[menuItem])); + return QCoreApplication::translate("RenderViewContextMenuQt", names[menuItem]); } RenderViewContextMenuQt::RenderViewContextMenuQt(QWebEngineContextMenuRequest *request) diff --git a/src/core/user_script.cpp b/src/core/user_script.cpp index c33fb908178..a91d470ed24 100644 --- a/src/core/user_script.cpp +++ b/src/core/user_script.cpp @@ -62,7 +62,7 @@ QString UserScript::name() const void UserScript::setName(const QString &name) { m_name = name; - m_scriptData.url = GURL(QStringLiteral("userScript:%1").arg(name).toStdString()); + m_scriptData.url = GURL("userScript:" + name.toStdString()); } QString UserScript::sourceCode() const From 4cdfbbf0908d4d4b3799465c2a7079d8d4e1e6d7 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 5 Feb 2025 14:42:49 +0100 Subject: [PATCH 267/341] Fix flaky tst_QWebEngineDownloadRequest auto tests Some of the test cases rely on context menu triggered by simulated user action. Input events are suppressed by blink if the page is not painted yet because the cc compositor deferred a commit. See SuppressingInputEventsBits::kDeferCommits and WidgetInputHandlerManager::DispatchEvent(). Wait for the HTML element to be painted to make sure the simulated mouse events will trigger the context menu. Change-Id: Ic41c03fbceb4a12ff90fc601560d48a50db6488c Reviewed-by: Moss Heim Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit ff77f316eb322b252155886f572e6561c5a2916f) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 2ff00521ffa7e422fefddb5b56040aad7c2fc5e2) --- .../tst_qwebenginedownloadrequest.cpp | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp index 455fa5e73ef..30c480f951f 100644 --- a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp +++ b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp @@ -16,6 +16,38 @@ #include #include +using namespace Qt::StringLiterals; + +// Based on PageWithPaintListeners in tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +// TODO: Factor PageWithPaintListeners out to tests/auto/util/util.h +class TestPage : public QWebEnginePage +{ + Q_OBJECT +public: + TestPage(QWebEngineProfile *profile) : QWebEnginePage(profile) + { + QObject::connect(this, &QWebEnginePage::loadFinished, [this]() { + const QString jsLCPObserver = QStringLiteral( + "new PerformanceObserver((list) => {" + " const entries = list.getEntries();" + " const lastEntry = entries[entries.length - 1];" + " console.log('largestContentfulPaint: ' + lastEntry.element);" + "}).observe({type: 'largest-contentful-paint', buffered: true});"); + runJavaScript(jsLCPObserver); + }); + } + + void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel, const QString &message, int, + const QString &) override + { + if (message == "largestContentfulPaint: [object HTMLBodyElement]"_L1) + emit htmlBodyElementPainted(); + } + +signals: + void htmlBodyElementPainted(); +}; + class tst_QWebEngineDownloadRequest : public QObject { Q_OBJECT @@ -66,7 +98,7 @@ private Q_SLOTS: HttpServer *m_server; QWebEngineProfile *m_profile; - QWebEnginePage *m_page; + TestPage *m_page; QWebEngineView *m_view; QSet m_requestedDownloads; QSet m_finishedDownloads; @@ -91,7 +123,7 @@ void tst_QWebEngineDownloadRequest::initTestCase() m_finishedDownloads.insert(item); }); }); - m_page = new QWebEnginePage(m_profile); + m_page = new TestPage(m_profile); m_view = new QWebEngineView; m_view->setPage(m_page); m_view->resize(640, 480); @@ -452,10 +484,12 @@ void tst_QWebEngineDownloadRequest::downloadLink() // The only variation being whether the element has a "download" // attribute or not. QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted); m_view->load(m_server->url()); QTRY_COMPARE(loadSpy.size(), 1); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); QCOMPARE(indexRequestCount, 1); + QTRY_COMPARE(paintSpy.size(), 1); simulateUserAction(QPoint(10, 10), userAction); @@ -550,9 +584,11 @@ void tst_QWebEngineDownloadRequest::downloadTwoLinks() }); QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted); m_view->load(m_server->url()); QTRY_COMPARE(loadSpy.size(), 1); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QTRY_COMPARE(paintSpy.size(), 1); // Trigger downloads simulateUserAction(QPoint(10, 10), action1); @@ -1273,9 +1309,11 @@ void tst_QWebEngineDownloadRequest::downloadDataUrls() }); QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted); m_view->load(m_server->url()); QTRY_COMPARE(loadSpy.size(), 1); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QTRY_COMPARE(paintSpy.size(), 1); // Trigger download simulateUserAction(QPoint(10, 10), UserAction::ClickLink); From 9755cc0963f63aacc19895870a58d7ba76c1f32a Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 12 Feb 2025 10:51:32 +0100 Subject: [PATCH 268/341] Fix tst_QWebEngineView::pageWithPaintListeners on macOS macOS hides scrollbars by default, skip the scrollbar test. Also replace QTRY_VERIFY with QTRY_COMPARE to get meaningful messages on test failure. Change-Id: I22b9cb55cd952ad0424271cb86ac68c7793281c2 Reviewed-by: Anu Aliyas (cherry picked from commit 845b4ed898183606a5cd4c18fb379a2723c7cf74) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit cc21b907007b5d8c9b444871813ec6b616b76685) --- .../qwebengineview/tst_qwebengineview.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index d44167d9de8..86852ae35ef 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -288,20 +288,20 @@ void tst_QWebEngineView::pageWithPaintListeners() page.setHtml(empty); QTest::qWait(500); // empty page should not trigger - QVERIFY(firstContentfulPaintSpy.size() == 0); - QVERIFY(largestContentfulPaintSpy.size() == 0); + QCOMPARE(firstContentfulPaintSpy.size(), 0); + QCOMPARE(largestContentfulPaintSpy.size(), 0); page.setHtml(backgroundColor); - QTRY_VERIFY(firstContentfulPaintSpy.size() == 1); + QTRY_COMPARE(firstContentfulPaintSpy.size(), 1); page.setHtml(text); - QTRY_VERIFY(firstContentfulPaintSpy.size() == 2); - QTRY_VERIFY(largestContentfulPaintSpy.size() == 1); + QTRY_COMPARE(firstContentfulPaintSpy.size(), 2); + QTRY_COMPARE(largestContentfulPaintSpy.size(), 1); -#if !QT_CONFIG(webengine_embedded_build) - // Embedded builds have different scrollbars that are only painted on hover +#if !QT_CONFIG(webengine_embedded_build) && !defined(Q_OS_MACOS) + // Embedded builds and macOS have different scrollbars that are only painted on hover page.setHtml(scrollBars); - QTRY_VERIFY(firstContentfulPaintSpy.size() == 3); + QTRY_COMPARE(firstContentfulPaintSpy.size(), 3); #endif } From 26533ea5b67ed62082e6f973516c373f9d6d0480 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 14 Feb 2025 16:00:05 +0100 Subject: [PATCH 269/341] Warn when PdfDocument.source can't be opened; add note to docs When PdfDocument is instantiated in some QML file that comes from application resources, it can be surprising when giving a plain file path to the source property that it tries to resolve it as a resource URL instead of a filesystem URL. But this behavior is consistent with how we handle URLs in other components, such as Image; and Image also generates a QML warning if the file cannot be found. Followup to 3159ac9ff7edf0eea93fa8331ea6cb8abc201ca2 Fixes: QTBUG-131841 Change-Id: I8fb66b321406e14c88ff1eb253d46742c0c99b5a Reviewed-by: Ulf Hermann (cherry picked from commit 8c07478a3b1d5eac8db3df0144e824fd0263f9ef) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit f26d74681fcc46dec443155f684287e1cf7701d3) --- src/pdfquick/qquickpdfdocument.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pdfquick/qquickpdfdocument.cpp b/src/pdfquick/qquickpdfdocument.cpp index 268036d39fe..6bf1744f666 100644 --- a/src/pdfquick/qquickpdfdocument.cpp +++ b/src/pdfquick/qquickpdfdocument.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,13 @@ void QQuickPdfDocument::classBegin() This property holds a URL pointing to the PDF file to be loaded. - \note At this time, only local filesystem URLs are supported. + \note At this time, only local filesystem and + \l {The Qt Resource System} {resource} URLs are supported. Nevertheless, + the \c source property is a \l {QUrl}{URL}, not merely a filesystem path. + PdfDocument resolves it via QQmlContext::resolvedUrl(). You should + typically ensure that the URL starts with a \c {file://} scheme, unless you + mean to load the PDF file from resources, or it comes from some component + (such as \l {QtQuick.Controls::}{FileDialog}) that resolves it in advance. */ void QQuickPdfDocument::setSource(QUrl source) { @@ -80,6 +87,8 @@ void QQuickPdfDocument::setSource(QUrl source) m_resolvedSource = context ? context->resolvedUrl(source) : source; if (m_resolvedSource.isValid()) m_doc->load(QQmlFile::urlToLocalFileOrQrc(m_resolvedSource)); + else + qmlWarning(this) << QQuickPdfDocument::tr("Cannot open: %1").arg(m_resolvedSource.toString()); } /*! From f4ad6f6f3914be174f408391acdb96a86818dfb2 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 18 Feb 2025 14:41:18 +0100 Subject: [PATCH 270/341] Fix flaky tst_QWebEngineView::deferredDelete A replacement widget for the obsolete QDesktopWidget might be created while hovering a widget in an earlier test during destruction. The extra widget is destructed together with QApplication so it is listed by QApplication::allWidgets() in the subsequent tests. For reproducing this issue run ./tst_qwebengine doNotSendMouseKeyboardEventsWhenDisabled deferredDelete and keep the mouse cursor above the window while running tst_QWebEngineView::doNotSendMouseKeybooardEventsWhenDisabled(). As a workaround take the extra widget into account when testing the size of QApplication::allWidgets(). Change-Id: I84cfb75fcee944e8a22b7c12a725f131e96b3719 Reviewed-by: Moss Heim Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 5436b61f42e616d0d591e5b55d1e2a586dd4e5f9) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit f60a380de78504c6e9e446d75a420e8a9fcf8893) --- .../auto/widgets/qwebengineview/tst_qwebengineview.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 86852ae35ef..5dfdd147c2f 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -4011,16 +4011,22 @@ void tst_QWebEngineView::longKeyEventText() void tst_QWebEngineView::deferredDelete() { + // TODO: Remove this workaround when temporary qt_desktopWidget is removed from + // qapplication.cpp. + const size_t desktopWidget = QApplication::allWidgets().size(); + QVERIFY(desktopWidget <= 1); + { QWebEngineView view; QSignalSpy loadFinishedSpy(view.page(), &QWebEnginePage::loadFinished); view.load(QUrl("chrome://qt")); view.show(); QTRY_VERIFY(loadFinishedSpy.size()); - QCOMPARE(QApplication::allWidgets().size(), 2); // QWebEngineView and WebEngineQuickWidget + // QWebEngineView and WebEngineQuickWidget + QCOMPARE(QApplication::allWidgets().size(), desktopWidget + 2); } - QCOMPARE(QApplication::allWidgets().size(), 0); + QCOMPARE(QApplication::allWidgets().size(), desktopWidget); } // QTBUG-111927 From 03cd9ecba4caf4f759836adb5a08b2dc736e0a71 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Wed, 12 Feb 2025 15:16:34 +0100 Subject: [PATCH 271/341] Fix download behavior when network error occurs We assume that DownloadManagerDelegateQt::DetermineDownloadTarget() is always the starting point of a download request, but there are special cases when a download item needs more than one target determination (for example when the server is being killed during a large download, Content API tries to check the target again before reporting the error). Handle this case by not decreasing m_currentId and preventing the manager class adding itself as an observer of the same item multiple times. Due to the weird internal state of DownloadItem (INTERRUPTED_TARGET_PENDING_INTERNAL) it still counts as an in progress download and its functions (e.g. Resume()) are inactive. Don't expose this state to our users, just re-use the already provided target path again and they will be informed about the issue in the next OnDownloadUpdated(). Task-number: QTBUG-132479 Task-number: QTBUG-132473 Change-Id: Id8d39881b9225d76456edec150035e4331e752c7 Reviewed-by: Anu Aliyas (cherry picked from commit 56fbb0fa569287ab00538fbefd6abefe05c3141d) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 95badf9e679cbf4cc5c90ea6569cb683894d8291) --- src/core/download_manager_delegate_qt.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index ec80d548a91..05d3d77c609 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -26,6 +26,20 @@ using namespace Qt::StringLiterals; namespace QtWebEngineCore { +void provideDownloadTarget(download::DownloadItem *item, download::DownloadTargetCallback *callback, + const base::FilePath &target) +{ + download::DownloadTargetInfo target_info; + target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE; + target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; + target_info.insecure_download_status = download::DownloadItem::VALIDATED; + target_info.mime_type = item->GetMimeType(); + target_info.display_name = item->GetFileNameToReportUser(); + target_info.target_path = target; + target_info.intermediate_path = target.AddExtensionASCII("download"); + std::move(*callback).Run(std::move(target_info)); +} + DownloadManagerDelegateQt::DownloadManagerDelegateQt(ProfileAdapter *profileAdapter) : m_profileAdapter(profileAdapter) , m_currentId(0) @@ -88,6 +102,14 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId) bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *item, download::DownloadTargetCallback *callback) { + // The item came back for another round of target determination; this happens for example when + // network error occurs. We already gave it a target path, let it use that, then it can report + // the reason of its failure in OnDownloadUpdated(). + if (m_currentId >= item->GetId() && !item->GetTargetFilePath().empty()) { + provideDownloadTarget(item, callback, item->GetTargetFilePath()); + return true; + } + m_currentId = item->GetId(); // Keep the forced file path if set, also as the temporary file, so the check for existence @@ -165,7 +187,6 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * item->AddObserver(this); QList clients = m_profileAdapter->clients(); if (!clients.isEmpty()) { - Q_ASSERT(m_currentId == item->GetId()); ProfileAdapterClient::DownloadItemInfo info = { item->GetId(), toQt(item->GetURL()), From 00ff092949b735e0e7079da606fddb6552b00336 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 13 Feb 2025 16:52:06 +0100 Subject: [PATCH 272/341] Use QL1SV where QString conversion is not needed Change-Id: I1e819d5f570eb52d703691b6e7bd0de29adc9318 Reviewed-by: Marc Mutz (cherry picked from commit 676eea8bbe4c3c943058561e4ceb02800fd6d76e) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 131ddcbf9e7bf04d46f5bdc5c0c28d6179a8ed60) --- src/core/download_manager_delegate_qt.cpp | 2 +- src/core/file_picker_controller.cpp | 2 +- src/core/net/resource_request_body_qt.cpp | 4 ++-- src/core/web_engine_context.cpp | 11 +++++------ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 05d3d77c609..e67b59d02cf 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -173,7 +173,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * } if (suggestedFilename.isEmpty()) { - suggestedFilename += QStringLiteral("qwe_download"); + suggestedFilename += "qwe_download"_L1; QMimeType mimeType = QMimeDatabase().mimeTypeForName(mimeTypeString); if (mimeType.isValid() && !mimeType.preferredSuffix().isEmpty()) suggestedFilename += u'.' + mimeType.preferredSuffix(); diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index e7b7de7b192..1c98b90c74c 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -257,7 +257,7 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp // A single suffix // Filename.type doesn't have to exist and mimeTypeForFile() supports // custom suffixes as valid (but unknown) MIME types. - const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename" + type); + const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename"_L1 + type); if (mimeType.isValid()) { QString glob = u'*' + type; acceptedGlobs.append(glob); diff --git a/src/core/net/resource_request_body_qt.cpp b/src/core/net/resource_request_body_qt.cpp index 429d1f8048e..bc7fffdf2be 100644 --- a/src/core/net/resource_request_body_qt.cpp +++ b/src/core/net/resource_request_body_qt.cpp @@ -163,8 +163,8 @@ void ResourceRequestBody::readDataElementPipe( *data += bytesToRead; bytesRead += bytesToRead; } else if (result != MOJO_RESULT_SHOULD_WAIT && result != MOJO_RESULT_FAILED_PRECONDITION) { - setErrorString(QString::fromLatin1("Error while reading from data pipe, skipping" - "remaining content of data pipe. Mojo error code: ") + setErrorString("Error while reading from data pipe, skipping " + "remaining content of data pipe. Mojo error code: "_L1 + QString::number(result)); } } while ((result == MOJO_RESULT_SHOULD_WAIT || result == MOJO_RESULT_OK) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index da1aea48de8..0946238d656 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1186,14 +1186,13 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, } } #if defined(QTWEBENGINE_EMBEDDED_SWITCHES) - useEmbeddedSwitches = !appArgs.contains(QStringLiteral("--disable-embedded-switches")); + useEmbeddedSwitches = !appArgs.contains("--disable-embedded-switches"_L1); #else - useEmbeddedSwitches = appArgs.contains(QStringLiteral("--enable-embedded-switches")); + useEmbeddedSwitches = appArgs.contains("--enable-embedded-switches"_L1); #endif - enableGLSoftwareRendering = - appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering")); - appArgs.removeAll(QStringLiteral("--disable-embedded-switches")); - appArgs.removeAll(QStringLiteral("--enable-embedded-switches")); + enableGLSoftwareRendering = appArgs.removeAll("--enable-webgl-software-rendering"_L1); + appArgs.removeAll("--disable-embedded-switches"_L1); + appArgs.removeAll("--enable-embedded-switches"_L1); bool isRemoteDebugPort = (-1 From 4c35b99d0f3d6899b3397576eea5fbfa28c1b8e4 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 13 Feb 2025 14:43:22 +0100 Subject: [PATCH 273/341] Optimize removing quality values from Accept-Language string Also add auto test for QWebEngineProfile::setHttpAcceptLanguage() to validate if argument with quality values is parsed properly. Change-Id: Ide3acfe93bfe2d4c6afd76bd7239f471942ea467 Reviewed-by: Marc Mutz Reviewed-by: Michal Klocek (cherry picked from commit 9164704c9a3b89c33f0c1cade84c4a11740c1833) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit da5f1c1cb51de0988f1a96a872d911a529969c40) --- src/core/profile_adapter.cpp | 10 +++++----- .../qwebengineprofile/tst_qwebengineprofile.cpp | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index c5cc86eb15c..765841b89ff 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -594,12 +594,12 @@ QList ProfileAdapter::listPermissions(const QUrl &origin, QString ProfileAdapter::httpAcceptLanguageWithoutQualities() const { - const QStringList list = m_httpAcceptLanguage.split(QLatin1Char(',')); QString out; - for (const QString &str : list) { - if (!out.isEmpty()) - out.append(QLatin1Char(',')); - out.append(str.split(QLatin1Char(';')).first()); + auto sep = ""_L1; + for (auto lang : m_httpAcceptLanguage.tokenize(u',')) { + out += sep; + out += *lang.tokenize(u';').begin(); // tokenize() is never empty with KeepEmptyParts! + sep = ","_L1; } return out; } diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index e7492ce7e28..97e5bd6017f 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -26,6 +26,8 @@ #include #include +using namespace Qt::StringLiterals; + class tst_QWebEngineProfile : public QObject { Q_OBJECT @@ -847,6 +849,12 @@ void tst_QWebEngineProfile::httpAcceptLanguage() // Test changing an existing page and profile QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage(testLang); QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.languages")).toStringList(), QStringList(testLang)); + + // Test language list with quality values + QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage( + u"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"_s); + QCOMPARE(evaluateJavaScriptSync(&page, u"navigator.languages"_s).toStringList(), + QStringList({u"en-US"_s, u"en"_s, u"zh-CN"_s, u"zh"_s})); } void tst_QWebEngineProfile::downloadItem() From 20319ec5c2f430655d61aa41d25fba6752ab49bd Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 13 Feb 2025 14:52:24 +0100 Subject: [PATCH 274/341] Remove more unnecessary QString conversions Change-Id: Ifb8e87cb5e49d71d7d8a61f99305d86a986aa032 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Marc Mutz (cherry picked from commit 100682f8954ba1de309976cd54c86982f5130ae7) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 3dee4ca7b3cbf078f7c5bb310f425ccb67ca26f9) --- src/core/browser_accessibility_qt.cpp | 4 ++-- src/core/web_event_factory.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index 60e5390e3d0..f2959350d0a 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -159,8 +159,8 @@ BrowserAccessibilityInterface::BrowserAccessibilityInterface(BrowserAccessibilit { if (parent() && parent()->object()) { m_object = new QObject(parent()->object()); - QString name = toQt(q->GetAuthorUniqueId()); - if (!name.isEmpty()) + const std::u16string name = q->GetAuthorUniqueId(); + if (!name.empty()) m_object->setObjectName(name); } diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index d47d6a9ced1..6457d456ee2 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -38,6 +38,7 @@ #include "native_web_keyboard_event_qt.h" #include "render_widget_host_view_qt_delegate.h" +#include #include #include @@ -1682,9 +1683,10 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e if (qtKey >= Qt::Key_Escape) webKitEvent.dom_key = domKeyForQtKey(qtKey); - else if (!qtText.isEmpty()) - webKitEvent.dom_key = ui::DomKey::FromCharacter(qtText.toUcs4().first()); - else { + else if (!qtText.isEmpty()) { + QStringIterator it(qtText); + webKitEvent.dom_key = ui::DomKey::FromCharacter(it.next()); + } else { QChar ch(qtKey); if (!(qtModifiers & Qt::ShiftModifier)) // No way to check for caps lock ch = ch.toLower(); From 4d13c5071ebdad3aab57dba52973d2d42ab515ae Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 6 Feb 2025 17:20:41 +0100 Subject: [PATCH 275/341] Use QSL where the string is converted to QString Change-Id: I14bf140ba6dbfdedf1b010070ca8d92078fee8ea Reviewed-by: Marc Mutz (cherry picked from commit c93e694728cf0661009851d4c3e547dd609924eb) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 5b543d32952802553257df9c401e2d13bc583169) --- src/core/content_client_qt.cpp | 2 +- src/core/web_engine_context.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 0b16c01e9b2..1dc60cdf195 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -198,7 +198,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, pluginPaths << ppapiPluginsPath() + u'/' + QLatin1StringView(kWidevineCdmFileName); #endif #if defined(Q_OS_OSX) - QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Frameworks"); + QDir potentialWidevineDir(u"/Applications/Google Chrome.app/Contents/Frameworks"_s); const auto archDir = QSysInfo::currentCpuArchitecture() == "x86_64"_L1 ? "mac_x64/"_L1 : "mac_arm64/"_L1; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 0946238d656..f123a9f1ee0 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1171,7 +1171,7 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, } base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); - int index = appArgs.indexOf(QRegularExpression(QLatin1StringView("--webEngineArgs"), + int index = appArgs.indexOf(QRegularExpression(u"--webEngineArgs"_s, QRegularExpression::CaseInsensitiveOption)); if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) { appArgs = appArgs.mid(0, 1); // Take application name and drop the rest From d7b9205c7246d1a7d774a839cdedcb4beb7bf896 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 13 Feb 2025 16:57:16 +0100 Subject: [PATCH 276/341] Concatenate strings with QStringBuilder instead of QString::arg() Change-Id: I07423cdaf68e7a7333e270f25983584655467e85 Reviewed-by: Marc Mutz (cherry picked from commit df367e1ffa8c166016dff2f1ec5b547033a9b5ba) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit b1ba0a4cb74ba2bf42eebd0467908649af7d3b53) --- src/core/web_contents_adapter.cpp | 4 ++-- src/core/web_contents_delegate_qt.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 238c81504f1..c570ba033f5 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -666,8 +666,8 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) strlen(content::kViewSourceScheme) + 1)); if (pageUrl.scheme().isEmpty()) { QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString()); - extendedUrl = QUrl(QString("%1:%2").arg(QLatin1StringView(content::kViewSourceScheme), - extendedUrl.toString())); + extendedUrl = QUrl(QLatin1StringView(content::kViewSourceScheme) + u':' + + extendedUrl.toString()); gurl = toGurl(https://github.com/extendedUrl); } } diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index de045da4ee1..5ce99761351 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -199,8 +199,8 @@ QUrl WebContentsDelegateQt::url(/service/content::WebContents *source) const if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme) && (url.has_password() || url.has_username() || url.has_ref())) { GURL strippedUrl = net::SimplifyUrlForRequest(url); - newUrl = QUrl(QString("%1:%2").arg(QLatin1StringView(content::kViewSourceScheme), - QString::fromStdString(strippedUrl.spec()))); + newUrl = QUrl(QLatin1StringView(content::kViewSourceScheme) + u':' + + QString::fromStdString(strippedUrl.spec())); } // If there is a visible entry there are special cases where we dont wan't to use the actual URL if (newUrl.isEmpty()) From af3d521a539b57f7a934a3f19e28d03288566333 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 20 Jan 2025 12:18:51 +0100 Subject: [PATCH 277/341] Fix failing test Wait for the last interceptor to intercept Change-Id: I830f2c71e75ab99bb037562445081eb23412e61f Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Moss Heim (cherry picked from commit 5d7a87193f976f9b118b45724603436b6c6ef84e) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 8fcecc184e5450645a81ba191906e08f3ad3b300) Reviewed-by: Marc Mutz --- .../tst_qwebengineurlrequestinterceptor.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index 7f8e040158f..bf82194f50f 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -159,7 +159,7 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor { QList infos; - foreach (auto requestInfo, requestInfos) { + for (const auto &requestInfo : requestInfos) { if (shouldSkipRequest(requestInfo)) continue; @@ -172,7 +172,7 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor bool hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceType type) { - foreach (auto requestInfo, requestInfos) { + for (const auto &requestInfo : requestInfos) { if (shouldSkipRequest(requestInfo)) continue; @@ -802,17 +802,17 @@ void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker() void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor_data() { QTest::addColumn("firstInterceptIsInPage"); - QTest::addColumn("keepInterceptionPoint"); + QTest::addColumn("secondInterceptIsInPage"); QTest::newRow("page") << true << true; QTest::newRow("page-profile") << true << false; - QTest::newRow("profile") << false << true; - QTest::newRow("profile-page") << false << false; + QTest::newRow("profile") << false << false; + QTest::newRow("profile-page") << false << true; } void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor() { QFETCH(bool, firstInterceptIsInPage); - QFETCH(bool, keepInterceptionPoint); + QFETCH(bool, secondInterceptIsInPage); HttpServer server; server.setResourceDirs({ ":/resources" }); @@ -837,17 +837,14 @@ void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor() requestsOnReplace.push_back(interceptors[currentInterceptorIndex].requestInfos.size()); bool isFirstReinstall = currentInterceptorIndex == 0; - bool interceptInPage = keepInterceptionPoint ? firstInterceptIsInPage : (isFirstReinstall ^ firstInterceptIsInPage); + bool interceptInPage = isFirstReinstall ? firstInterceptIsInPage : secondInterceptIsInPage; setInterceptor(&interceptors[++currentInterceptorIndex], interceptInPage); - if (!keepInterceptionPoint) - setInterceptor(nullptr, !interceptInPage); + setInterceptor(nullptr, !interceptInPage); if (isFirstReinstall) { page.triggerAction(QWebEnginePage::Reload); } else { - page.runJavaScript("fetch('https://github.com/service/http://nonexistent.invalid/').catch(() => {})", [&, interceptInPage] (const QVariant &) { - requestsOnReplace.push_back(interceptors.back().requestInfos.size()); - setInterceptor(nullptr, interceptInPage); + page.runJavaScript("fetch('https://github.com/service/http://nonexistent.invalid/').catch(() => {})", [&fetchFinished] (const QVariant &) { fetchFinished = true; }); } @@ -856,6 +853,10 @@ void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor() page.setUrl(server.url("https://github.com/favicon.html")); QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 2, 20000); QTRY_VERIFY(fetchFinished); + QTRY_VERIFY(!interceptors.back().requestInfos.isEmpty()); + setInterceptor(nullptr, true); + setInterceptor(nullptr, false); + requestsOnReplace.push_back(interceptors.back().requestInfos.size()); QString s; QDebug d(&s); for (auto i = 0u; i < interceptors.size(); ++i) { From 56321460212a5c2f0659369376d4029e3a281511 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 14 Feb 2025 14:55:10 +0100 Subject: [PATCH 278/341] Port away from foreach All containers are non-const local variables, and the loop bodies clearly do not modify the container, so can use ranged for loops with std::as_const() to avoid the detach (attempt). Fixes: QTBUG-115805 Change-Id: Ie3eec615112a32c44ef81e4c2e5879997e5dc619 Reviewed-by: Marc Mutz (cherry picked from commit 0ff112a78af56ba03042872b4bb3066754f367f9) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit eb3cdb90d3f802680df60a18e558f8db8b2b8c21) --- .../tst_qwebengineurlrequestinterceptor.cpp | 32 +++++++++---------- .../tst_qquickwebengineview.cpp | 6 ++-- .../qwebengineview/tst_qwebengineview.cpp | 6 ++-- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index bf82194f50f..e366bab969e 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -1,8 +1,6 @@ // Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses - #include #include #include @@ -572,43 +570,43 @@ void tst_QWebEngineUrlRequestInterceptor::firstPartyUrlHttp() // Stylesheet QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Script QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Image QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // FontResource QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Media QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Favicon QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // XMLHttpRequest QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); } @@ -724,43 +722,43 @@ void tst_QWebEngineUrlRequestInterceptor::initiator() // Stylesheet QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Script QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Image QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // FontResource QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Media QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Favicon QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // XMLHttpRequest QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); } @@ -793,7 +791,7 @@ void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker() // Service Worker QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); QVERIFY(server.stop()); diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 1177d8adf53..1fdccb7d4b3 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses - #include "testwindow.h" #include "quickutil.h" #include "util.h" @@ -617,7 +615,7 @@ void tst_QQuickWebEngineView::inputContextQueryInput() QTest::mouseClick(view->window(), Qt::LeftButton, {}, textInputCenter); QTRY_COMPARE(testContext.infos.size(), 2); QCOMPARE(evaluateJavaScriptSync(view, "document.activeElement.id").toString(), QStringLiteral("input1")); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("")); @@ -712,7 +710,7 @@ void tst_QQuickWebEngineView::inputContextQueryInput() QGuiApplication::sendEvent(qApp->focusObject(), &event); } QTRY_COMPARE(testContext.infos.size(), 2); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!")); diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 5dfdd147c2f..0d9b078c064 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -19,8 +19,6 @@ Boston, MA 02110-1301, USA. */ -#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses - #include #include #include @@ -2078,7 +2076,7 @@ void tst_QWebEngineView::inputContextQueryInput() QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, textInputCenter); QTRY_COMPARE(testContext.infos.size(), 2); QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1")); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("")); @@ -2177,7 +2175,7 @@ void tst_QWebEngineView::inputContextQueryInput() QApplication::sendEvent(view.focusProxy(), &event); } QTRY_COMPARE(testContext.infos.size(), 2); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!")); From 9d0dceb1e6645c1a511face787c7df4a9a049e9d Mon Sep 17 00:00:00 2001 From: Teemu Jokitulppo Date: Mon, 24 Feb 2025 12:05:06 +0200 Subject: [PATCH 279/341] Fix spdx files not included in MinGW/LLVM content Missing entries in qt-installer-package-config.json file caused some spdx files be excluded from Qt PDF installations. Fixed this by adding those entries. Task-number: QTBUG-133970 Change-Id: I9a8d857a05c2b93fbe6ff2fd70f2cd8c3644e53b Reviewed-by: Antti Kokko (cherry picked from commit ca222db0ac6780e1867adc598a919bdfe2777722) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 2668a8e64de9e857714c4f1e5223391087cc873d) --- coin/qt-installer-package-config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/coin/qt-installer-package-config.json b/coin/qt-installer-package-config.json index aec45688b39..433ddfd824a 100644 --- a/coin/qt-installer-package-config.json +++ b/coin/qt-installer-package-config.json @@ -3,6 +3,7 @@ "module-split": { "qtpdf": [ "**/bin/*Pdf*", + "**/sbom/qtpdf*", "**/include/*QtPdf*/**/*", "**/lib/cmake/Qt*Gui/*Pdf*", "**/lib/cmake/Qt*Pdf*/*", From fe20ccb46b0cc8a6f13b2c847fcc93d90851b211 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 6 Feb 2025 15:22:21 +0100 Subject: [PATCH 280/341] Make QString and QByteArray strings constants if not modified Merge conflict resolution for 6.8: - No QWebEngineDownloadeRequestPrivate::answer() in 6.8 Change-Id: If6c704cf5dada72d2c5c069fcbbcfea16af845ac Reviewed-by: Marc Mutz (cherry picked from commit 2ccca2f0663e866b94fd1d7f0195ebff280583fb) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit ae8651a621cb9f2b8a6678aabd57648a699acc59) --- src/core/api/qwebenginehttprequest.cpp | 4 ++-- src/core/api/qwebenginepage.cpp | 19 ++++++++++--------- src/core/api/qwebenginescript.cpp | 2 +- src/core/client_cert_select_controller.cpp | 2 +- src/core/clipboard_qt.cpp | 4 ++-- src/core/content_client_qt.cpp | 6 +++--- src/core/native_web_keyboard_event_qt_mac.mm | 2 +- src/core/net/client_cert_store_data.cpp | 4 ++-- src/core/net/qrc_url_scheme_handler.cpp | 6 +++--- src/core/profile_adapter.cpp | 6 +++--- ...er_widget_host_view_qt_delegate_client.cpp | 4 ++-- .../web_channel_ipc_transport_host.cpp | 2 +- src/core/web_contents_adapter.cpp | 2 +- src/core/web_engine_context.cpp | 2 +- src/core/web_engine_library_info.cpp | 3 ++- src/core/web_event_factory.cpp | 4 ++-- 16 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/core/api/qwebenginehttprequest.cpp b/src/core/api/qwebenginehttprequest.cpp index 050213d1e2d..0039533d687 100644 --- a/src/core/api/qwebenginehttprequest.cpp +++ b/src/core/api/qwebenginehttprequest.cpp @@ -148,8 +148,8 @@ QWebEngineHttpRequest QWebEngineHttpRequest::postRequest(const QUrl &url, QByteArray buffer; for (QMap::const_iterator it = postData.begin(); it != postData.end(); it++) { - QByteArray key = QUrl::toPercentEncoding(it.key()); - QByteArray value = QUrl::toPercentEncoding(it.value()); + const QByteArray key = QUrl::toPercentEncoding(it.key()); + const QByteArray value = QUrl::toPercentEncoding(it.value()); if (buffer.size() > 0) buffer += '&'; diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 826d8ce492c..640e2c5e938 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -1337,15 +1337,16 @@ void QWebEnginePage::triggerAction(WebAction action, bool) break; case CopyLinkToClipboard: if (d->view && d->view->lastContextMenuRequest() && !d->view->lastContextMenuRequest()->linkUrl().isEmpty()) { - QString urlString = d->view->lastContextMenuRequest()->linkUrl().toString( - QUrl::FullyEncoded); - QString linkText = d->view->lastContextMenuRequest()->linkText().toHtmlEscaped(); + const QString urlString = + d->view->lastContextMenuRequest()->linkUrl().toString(QUrl::FullyEncoded); + const QString linkText = d->view->lastContextMenuRequest()->linkText().toHtmlEscaped(); QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - QString html = "' + linkText + ""_L1; + const QString html = + "' + linkText + ""_L1; data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->linkUrl()); QGuiApplication::clipboard()->setMimeData(data); @@ -1372,7 +1373,7 @@ void QWebEnginePage::triggerAction(WebAction action, bool) if (d->view && d->view->lastContextMenuRequest() && d->view->lastContextMenuRequest()->mediaUrl().isValid() && d->view->lastContextMenuRequest()->mediaType() == QWebEngineContextMenuRequest::MediaTypeImage) { - QString urlString = + const QString urlString = d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded); QString alt = d->view->lastContextMenuRequest()->altText(); if (!alt.isEmpty()) @@ -1382,7 +1383,7 @@ void QWebEnginePage::triggerAction(WebAction action, bool) title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - QString html = ""_L1; + const QString html = ""_L1; data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->mediaUrl()); QGuiApplication::clipboard()->setMimeData(data); @@ -1402,7 +1403,7 @@ void QWebEnginePage::triggerAction(WebAction action, bool) == QWebEngineContextMenuRequest::MediaTypeAudio || d->view->lastContextMenuRequest()->mediaType() == QWebEngineContextMenuRequest::MediaTypeVideo)) { - QString urlString = + const QString urlString = d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded); QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) @@ -1412,8 +1413,8 @@ void QWebEnginePage::triggerAction(WebAction action, bool) const bool isAudio = d->view->lastContextMenuRequest()->mediaType() == QWebEngineContextMenuRequest::MediaTypeAudio; const auto avTagName = isAudio ? "audio"_L1 : "video"_L1; - QString html = u'<' + avTagName + "src=\""_L1 + urlString + u'"' + title + ">'; + const QString html = u'<' + avTagName + "src=\""_L1 + urlString + u'"' + title + + ">'; data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->mediaUrl()); QGuiApplication::clipboard()->setMimeData(data); diff --git a/src/core/api/qwebenginescript.cpp b/src/core/api/qwebenginescript.cpp index 8d1ff46bf49..772dd7dfb2c 100644 --- a/src/core/api/qwebenginescript.cpp +++ b/src/core/api/qwebenginescript.cpp @@ -172,7 +172,7 @@ void QWebEngineScript::setSourceUrl(const QUrl &url) return; } - QString source = QString::fromUtf8(file.readAll()); + const QString source = QString::fromUtf8(file.readAll()); setSourceCode(source); } diff --git a/src/core/client_cert_select_controller.cpp b/src/core/client_cert_select_controller.cpp index d6af984c187..e898da618ae 100644 --- a/src/core/client_cert_select_controller.cpp +++ b/src/core/client_cert_select_controller.cpp @@ -75,7 +75,7 @@ void ClientCertSelectController::select(const QSslCertificate &certificate) LOG(WARNING) << "ClientCertSelectController::select() certificate already selected"; return; } - QByteArray derCertificate = certificate.toDer(); + const QByteArray derCertificate = certificate.toDer(); scoped_refptr selectedCert = net::X509Certificate::CreateFromBytes(base::make_span((const unsigned char *)derCertificate.constData(), (long unsigned)derCertificate.length())); diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 39955719005..25ea8897136 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -185,8 +185,8 @@ void ClipboardQt::WriteBookmark(base::StringPiece title_in, base::StringPiece ur { // FIXME: Untested, seems to be used only for drag-n-drop. // Write as a mozilla url (UTF16: URL, newline, title). - QString url = toQString(url_in); - QString title = toQString(title_in); + const QString url = toQString(url_in); + const QString title = toQString(title_in); QByteArray data; data.append(reinterpret_cast(url.utf16()), url.size() * 2); diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 1dc60cdf195..88eebed23cf 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -215,7 +215,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, if (oldPotentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = oldPotentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { - QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); + const QString versionDirPath = widevineVersionDirs.at(i).absoluteFilePath(); QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/"_L1 + archDir + QLatin1StringView(kWidevineCdmFileName); pluginPaths << potentialWidevinePluginPath; @@ -230,7 +230,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, if (d.exists()) { QFileInfoList widevineVersionDirs = d.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { - QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); + const QString versionDirPath = widevineVersionDirs.at(i).absoluteFilePath(); #ifdef WIN64 QString potentialWidevinePluginPath = versionDirPath + "/WidevineCdm/_platform_specific/win_x64/"_L1 + @@ -248,7 +248,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { - QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); + const QString versionDirPath = widevineVersionDirs.at(i).absoluteFilePath(); #ifdef WIN64 QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/"_L1 + QLatin1StringView(kWidevineCdmFileName); #else diff --git a/src/core/native_web_keyboard_event_qt_mac.mm b/src/core/native_web_keyboard_event_qt_mac.mm index 0f5b12db43d..1499631eb23 100644 --- a/src/core/native_web_keyboard_event_qt_mac.mm +++ b/src/core/native_web_keyboard_event_qt_mac.mm @@ -103,7 +103,7 @@ key = QAppleKeyMapper::fromCocoaKey(character); } - QString text = QString::fromNSString(characters); + const QString text = QString::fromNSString(characters); bool autorep = nsevent.ARepeat; return new QKeyEvent(type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp index 0de6885df85..5f9c8243af9 100644 --- a/src/core/net/client_cert_store_data.cpp +++ b/src/core/net/client_cert_store_data.cpp @@ -92,8 +92,8 @@ namespace QtWebEngineCore { void ClientCertificateStoreData::add(const QSslCertificate &certificate, const QSslKey &privateKey) { - QByteArray sslKeyInBytes = privateKey.toPem(); - QByteArray certInBytes = certificate.toDer(); + const QByteArray sslKeyInBytes = privateKey.toPem(); + const QByteArray certInBytes = certificate.toDer(); Entry *data = new Entry; data->keyPtr = wrapOpenSSLPrivateKey(sslKeyInBytes); diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp index f1925da14dd..876c7d2031f 100644 --- a/src/core/net/qrc_url_scheme_handler.cpp +++ b/src/core/net/qrc_url_scheme_handler.cpp @@ -18,14 +18,14 @@ namespace QtWebEngineCore { void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) { - QByteArray requestMethod = job->requestMethod(); + const QByteArray requestMethod = job->requestMethod(); if (requestMethod != "GET") { job->fail(QWebEngineUrlRequestJob::RequestDenied); return; } - QUrl requestUrl = job->requestUrl(); - QString requestPath = requestUrl.path(); + const QUrl requestUrl = job->requestUrl(); + const QString requestPath = requestUrl.path(); auto file = std::make_unique(u':' + requestPath, job); if (!file->exists() || file->size() == 0) { qWarning("QResource '%s' not found or is empty", qUtf8Printable(requestPath)); diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 765841b89ff..89ecdfcacb3 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -308,7 +308,7 @@ QString ProfileAdapter::httpCachePath() const { if (m_offTheRecord) return QString(); - QString basePath = cachePath(); + const QString basePath = cachePath(); if (!basePath.isEmpty()) return basePath % "/Cache"_L1; return QString(); @@ -523,7 +523,7 @@ void ProfileAdapter::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) void ProfileAdapter::removeUrlScheme(const QByteArray &scheme) { - QByteArray canonicalScheme = scheme.toLower(); + const QByteArray canonicalScheme = scheme.toLower(); if (schemeType(canonicalScheme) == SchemeType::Protected) { qWarning("Cannot remove the URL scheme handler for an internal scheme: %s", scheme.constData()); return; @@ -535,7 +535,7 @@ void ProfileAdapter::removeUrlScheme(const QByteArray &scheme) void ProfileAdapter::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler) { Q_ASSERT(handler); - QByteArray canonicalScheme = scheme.toLower(); + const QByteArray canonicalScheme = scheme.toLower(); SchemeType type = schemeType(canonicalScheme); if (type == SchemeType::Protected) { diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp index a50eb9a4451..934df0ce489 100644 --- a/src/core/render_widget_host_view_qt_delegate_client.cpp +++ b/src/core/render_widget_host_view_qt_delegate_client.cpp @@ -738,8 +738,8 @@ void RenderWidgetHostViewQtDelegateClient::handleInputMethodEvent(QInputMethodEv if (!m_rwhv->host()) return; - QString commitString = event->commitString(); - QString preeditString = event->preeditString(); + const QString commitString = event->commitString(); + const QString preeditString = event->preeditString(); int cursorPositionInPreeditString = -1; gfx::Range selectionRange = gfx::Range::InvalidRange(); diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp index 613ca9dc044..41ef98c8bb9 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -48,7 +48,7 @@ uint WebChannelIPCTransportHost::worldId() const void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) { QJsonDocument doc(message); - QByteArray json = doc.toJson(QJsonDocument::Compact); + const QByteArray json = doc.toJson(QJsonDocument::Compact); content::RenderFrameHost *frame = web_contents()->GetPrimaryMainFrame(); qCDebug(log).nospace() << "sending webchannel message to " << frame << ": " << doc; GetWebChannelIPCTransportRemote(frame)->DispatchWebChannelMessage( diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index c570ba033f5..60c3febc0e1 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -735,7 +735,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT WebEngineSettings::get(m_adapterClient->webEngineSettings())->doApply(); - QByteArray encodedData = data.toPercentEncoding(); + const QByteArray encodedData = data.toPercentEncoding(); std::string urlString; if (!mimeType.isEmpty()) urlString = std::string("data:") + mimeType.toStdString() + std::string(","); diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index f123a9f1ee0..cdb967c4857 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -566,7 +566,7 @@ static void setupProxyPac(base::CommandLine *commandLine) else file.setFileName(pac_url.path().prepend(QLatin1Char(':'))); if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QByteArray ba = file.readAll(); + const QByteArray ba = file.readAll(); commandLine->RemoveSwitch(switches::kProxyPacUrl); commandLine->AppendSwitchASCII(switches::kProxyPacUrl, ba.toBase64().prepend("data:application/x-javascript-config;base64,").toStdString()); diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index b3a0050ba63..960b768d701 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -42,7 +42,8 @@ Q_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo") namespace { QString fallbackDir() { - static QString directory = QDir::homePath() % "/."_L1 % QCoreApplication::applicationName(); + static const QString directory = + QDir::homePath() % "/."_L1 % QCoreApplication::applicationName(); return directory; } diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 6457d456ee2..fc15134eb27 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -62,7 +62,7 @@ enum class KeyboardDriver { Unknown, Windows, Cocoa, Xkb, Evdev }; static KeyboardDriver keyboardDriverImpl() { - QString platformName = QGuiApplication::platformName(); + const QString platformName = QGuiApplication::platformName(); if (platformName == "windows"_L1) return KeyboardDriver::Windows; @@ -1676,7 +1676,7 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e int qtKey = qtKeyForKeyEvent(ev); Qt::KeyboardModifiers qtModifiers = isBackTabWithoutModifier ? Qt::ShiftModifier : qtModifiersForEvent(ev); - QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers); + const QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers); webKitEvent.native_key_code = nativeKeyCodeForKeyEvent(ev); webKitEvent.windows_key_code = windowsKeyCodeForQtKey(qtKey, qtModifiers & Qt::KeypadModifier); From d4e58bab669ad02b92070d696b2ac535fe8713c3 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 23 Jan 2025 15:50:33 +0100 Subject: [PATCH 281/341] Replace QStringLiteral with shorter u""_s notation Merge conflict resolution for 6.8: - Adapt change to initializer list in DownloadManagerDelegateQt::ChooseSavePath() Change-Id: I6d45505c808a48a1ea52ddbd39e74ada4c29136d Reviewed-by: Marc Mutz (cherry picked from commit dbb7830eb9ed95ab9c2f105b850586a9a517cf16) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 6736cf6e65cc83f74473c5c8863ec88b625a4c0c) --- src/core/api/qwebenginepage.cpp | 33 ++++++++++++++--------- src/core/content_client_qt.cpp | 17 ++++++------ src/core/download_manager_delegate_qt.cpp | 2 +- src/core/net/resource_request_body_qt.cpp | 4 +-- src/core/profile_adapter.cpp | 4 +-- src/core/web_contents_adapter.cpp | 2 +- src/core/web_contents_delegate_qt.cpp | 13 ++++++--- src/core/web_engine_context.cpp | 6 ++--- src/core/web_engine_settings.cpp | 4 ++- 9 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 640e2c5e938..ee9af797e86 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -1491,40 +1491,47 @@ void QWebEnginePage::triggerAction(WebAction action, bool) QTimer::singleShot(0, this, [d](){ d->adapter->viewSource(); }); break; case ToggleBold: - runJavaScript(QStringLiteral("document.execCommand('bold');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('bold');"_s, QWebEngineScript::ApplicationWorld); break; case ToggleItalic: - runJavaScript(QStringLiteral("document.execCommand('italic');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('italic');"_s, QWebEngineScript::ApplicationWorld); break; case ToggleUnderline: - runJavaScript(QStringLiteral("document.execCommand('underline');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('underline');"_s, QWebEngineScript::ApplicationWorld); break; case ToggleStrikethrough: - runJavaScript(QStringLiteral("document.execCommand('strikethrough');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('strikethrough');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignLeft: - runJavaScript(QStringLiteral("document.execCommand('justifyLeft');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyLeft');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignCenter: - runJavaScript(QStringLiteral("document.execCommand('justifyCenter');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyCenter');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignRight: - runJavaScript(QStringLiteral("document.execCommand('justifyRight');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyRight');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignJustified: - runJavaScript(QStringLiteral("document.execCommand('justifyFull');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyFull');"_s, + QWebEngineScript::ApplicationWorld); break; case Indent: - runJavaScript(QStringLiteral("document.execCommand('indent');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('indent');"_s, QWebEngineScript::ApplicationWorld); break; case Outdent: - runJavaScript(QStringLiteral("document.execCommand('outdent');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('outdent');"_s, QWebEngineScript::ApplicationWorld); break; case InsertOrderedList: - runJavaScript(QStringLiteral("document.execCommand('insertOrderedList');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('insertOrderedList');"_s, + QWebEngineScript::ApplicationWorld); break; case InsertUnorderedList: - runJavaScript(QStringLiteral("document.execCommand('insertUnorderedList');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('insertUnorderedList');"_s, + QWebEngineScript::ApplicationWorld); break; case ChangeTextDirectionLTR: d->adapter->changeTextDirection(true /*left to right*/); @@ -2015,7 +2022,7 @@ void QWebEnginePage::toPlainText(const std::function &res void QWebEnginePage::setHtml(const QString &html, const QUrl &baseUrl) { - setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl); + setContent(html.toUtf8(), u"text/html;charset=UTF-8"_s, baseUrl); } void QWebEnginePage::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 88eebed23cf..b5f40590a3c 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -298,17 +298,18 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, } // Fixed paths: - pluginPaths << QStringLiteral("/usr/lib/chromium/libwidevinecdm.so") // Arch - << QStringLiteral("/usr/lib/chromium-browser/libwidevinecdm.so") // Ubuntu/neon - << QStringLiteral("/usr/lib64/chromium/libwidevinecdm.so") // OpenSUSE style + pluginPaths + << u"/usr/lib/chromium/libwidevinecdm.so"_s // Arch + << u"/usr/lib/chromium-browser/libwidevinecdm.so"_s // Ubuntu/neon + << u"/usr/lib64/chromium/libwidevinecdm.so"_s // OpenSUSE style #if Q_PROCESSOR_WORDSIZE == 8 - << QStringLiteral("/usr/lib64/chromium-browser/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so") // Gentoo - << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so") // Old Google Chrome + << u"/usr/lib64/chromium-browser/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so"_s // Gentoo + << u"/opt/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so"_s // Old Google Chrome #else - << QStringLiteral("/usr/lib/chromium-browser/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so") // Gentoo - << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so") // Old Google Chrome + << u"/usr/lib/chromium-browser/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so"_s // Gentoo + << u"/opt/google/chrome/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so"_s // Old Google Chrome #endif - << QStringLiteral("/opt/google/chrome/libwidevinecdm.so"); // Older Google Chrome + << u"/opt/google/chrome/libwidevinecdm.so"_s; // Older Google Chrome #endif } diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index e67b59d02cf..43a853fdca5 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -309,7 +309,7 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content download::DownloadItem::IN_PROGRESS, -1, /* totalBytes */ 0, /* receivedBytes */ - QStringLiteral("application/x-mimearchive"), + u"application/x-mimearchive"_s, suggestedFilePath, suggestedSaveFormat, acceptedByDefault, diff --git a/src/core/net/resource_request_body_qt.cpp b/src/core/net/resource_request_body_qt.cpp index bc7fffdf2be..e41da9e6806 100644 --- a/src/core/net/resource_request_body_qt.cpp +++ b/src/core/net/resource_request_body_qt.cpp @@ -60,8 +60,8 @@ qint64 ResourceRequestBody::readData(char *data, qint64 maxSize) break; } case network::mojom::DataElementDataView::Tag::kChunkedDataPipe: { - setErrorString(QStringLiteral("Chunked data pipe is used in request body upload, which " - "is currently not supported")); + setErrorString(u"Chunked data pipe is used in request body upload, which " + "is currently not supported"_s); // Nothing should come before or after DataElementChunkedDataPipe return -1; } diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 89ecdfcacb3..9f8fc958680 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -256,9 +256,9 @@ QString ProfileAdapter::dataPath() const // a location to do so. QString name = m_name; if (m_offTheRecord) - name = QStringLiteral("OffTheRecord"); + name = u"OffTheRecord"_s; else if (m_name.isEmpty()) - name = QStringLiteral("UnknownProfile"); + name = u"UnknownProfile"_s; return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), name); } diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 60c3febc0e1..adbae106017 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -2232,7 +2232,7 @@ void WebContentsAdapter::discard() if (m_webContents->IsLoading()) { m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(https://github.com/webContents()), net::Error::ERR_ABORTED, - QStringLiteral("Discarded")); + u"Discarded"_s); m_webContentsDelegate->DidStopLoading(); } diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 5ce99761351..5371e9a5448 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -57,6 +57,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(blink::mojom::ConsoleMessageLevel log_level) @@ -778,10 +780,13 @@ void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransitio if (!navigationAllowedByPolicy || !navigationRequestAccepted) { QString errorDescription; - if (!navigationAllowedByPolicy) - errorDescription = QStringLiteral("Launching external protocol forbidden by WebEngineSettings::UnknownUrlSchemePolicy"); - else - errorDescription = QStringLiteral("Launching external protocol suppressed by 'navigationRequested' API"); + if (!navigationAllowedByPolicy) { + errorDescription = u"Launching external protocol forbidden by " + "WebEngineSettings::UnknownUrlSchemePolicy"_s; + } else { + errorDescription = u"Launching external protocol suppressed by " + "'navigationRequested' API"_s; + } didFailLoad(url, net::Error::ERR_ABORTED, errorDescription); } } diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index cdb967c4857..c8de0a83cd9 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1196,16 +1196,16 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, bool isRemoteDebugPort = (-1 - != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-debugging-port=.*"), + != appArgs.indexOf(QRegularExpression(u"--remote-debugging-port=.*"_s, QRegularExpression::CaseInsensitiveOption))) || !qEnvironmentVariable("QTWEBENGINE_REMOTE_DEBUGGING").isEmpty(); bool isRemoteAllowOrigins = (-1 - != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-allow-origins=.*"), + != appArgs.indexOf(QRegularExpression(u"--remote-allow-origins=.*"_s, QRegularExpression::CaseInsensitiveOption))); if (isRemoteDebugPort && !isRemoteAllowOrigins) { - appArgs.append(QStringLiteral("--remote-allow-origins=*")); + appArgs.append(u"--remote-allow-origins=*"_s); qWarning("Added {--remote-allow-origins=*} to command-line arguments " "to avoid web socket connection errors during remote debugging."); } diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 452ba639330..6e159658ff9 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -25,6 +25,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { QHash WebEngineSettings::s_defaultAttributes; @@ -333,7 +335,7 @@ void WebEngineSettings::initDefaults() s_defaultFontSizes.insert(QWebEngineSettings::DefaultFontSize, 16); } - m_defaultEncoding = QStringLiteral("ISO-8859-1"); + m_defaultEncoding = u"ISO-8859-1"_s; m_unknownUrlSchemePolicy = QWebEngineSettings::InheritedUnknownUrlSchemePolicy; m_imageAnimationPolicy = QWebEngineSettings::ImageAnimationPolicy::Inherited; } From 1e6539f7a5249ce666159e552d1e14dcf4817de5 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 20 Feb 2025 11:07:14 +0100 Subject: [PATCH 282/341] Add WebEngineContext::isGbmSupported() Factor GBM support detection out to avoid repetitive Nvidia checks. Also add QTWEBENGINE_FORCE_USE_GBM environment variable to be able to force disable/enable GBM and dma-buf code paths for debugging purposes. Setting the variable to 0 force disables GBM, setting any other integer value force enables it. Merge conflict resolution for 6.8: - No EGLHelper in 6.8 - No BUILDFLAG(IS_OZONE) in 6.8 Change-Id: I39fc0161467a6a8d86dd9f380be3bfb2018aa4e6 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 284d269eda53575d681c5d9f91bc934cf19b2f07) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 3aab3da507cc55dea5833369892c9a72b05082f2) --- src/core/ozone/gl_context_qt.cpp | 22 +++++----------- src/core/web_engine_context.cpp | 44 ++++++++++++++++++++++++++++++-- src/core/web_engine_context.h | 3 +++ 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index ce099a4a3d6..f59c3fa14d0 100644 --- a/src/core/ozone/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "gl_context_qt.h" +#include "web_engine_context.h" #include #include @@ -298,23 +299,14 @@ EGLHelper::EGLHelper() Q_ASSERT(QThread::currentThread() == qApp->thread()); m_offscreenSurface->create(); - const char *displayExtensions = m_functions->eglQueryString(eglDisplay, EGL_EXTENSIONS); - m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import") - && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers") - && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export"); + m_isDmaBufSupported = QtWebEngineCore::WebEngineContext::isGbmSupported(); + // Check extensions. if (m_isDmaBufSupported) { - // FIXME: This disables GBM for nvidia. Remove this when nvidia fixes its GBM support. - // - // "Buffer allocation and submission to DRM KMS using gbm is not currently supported." - // See: https://download.nvidia.com/XFree86/Linux-x86_64/550.40.07/README/kms.html - // - // Chromium uses GBM to allocate scanout buffers. Scanout requires DRM KMS. If KMS is - // enabled, gbm_device and gbm_buffer are created without any issues but rendering to the - // buffer will malfunction. It is not known how to detect this problem before rendering - // so we just disable GBM for nvidia. - const char *displayVendor = m_functions->eglQueryString(eglDisplay, EGL_VENDOR); - m_isDmaBufSupported = !strstr(displayVendor, "NVIDIA"); + const char *displayExtensions = m_functions->eglQueryString(eglDisplay, EGL_EXTENSIONS); + m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import") + && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers") + && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export"); } // Try to create dma-buf. diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index c8de0a83cd9..f77b380db33 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -952,7 +952,7 @@ WebEngineContext::WebEngineContext() } #if defined(USE_OZONE) - if (GPUInfo::instance()->vendor() == GPUInfo::Nvidia) { + if (!isGbmSupported()) { disableFeatures.push_back(media::kVaapiVideoDecodeLinux.name); parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); } @@ -965,7 +965,7 @@ WebEngineContext::WebEngineContext() if (parsedCommandLine->HasSwitch(switches::kUseGL)) usingANGLE = (parsedCommandLine->GetSwitchValueASCII(switches::kUseGL) == gl::kGLImplementationANGLEName); - if (usingANGLE && GPUInfo::instance()->vendor() == GPUInfo::Nvidia) { + if (usingANGLE && !isGbmSupported()) { qWarning("Disable ANGLE because GBM is not supported with the current configuration. " "Fallback to Vulkan rendering in Chromium."); parsedCommandLine->RemoveSwitch(switches::kUseANGLE); @@ -1229,6 +1229,46 @@ bool WebEngineContext::closingDown() return m_closingDown; } +#if defined(USE_OZONE) +bool WebEngineContext::isGbmSupported() +{ + static bool supported = []() { + const static char kForceGbmEnv[] = "QTWEBENGINE_FORCE_USE_GBM"; + if (Q_UNLIKELY(qEnvironmentVariableIsSet(kForceGbmEnv))) { + qWarning("%s environment variable is set and it is for debugging purposes only.", + kForceGbmEnv); + bool ok; + int forceGbm = qEnvironmentVariableIntValue(kForceGbmEnv, &ok); + if (ok) { + qWarning("GBM support is force %s.", forceGbm != 0 ? "enabled" : "disabled"); + return (forceGbm != 0); + } + + qWarning("Ignoring invalid value of %s and do not force GBM. " + "Use 0 to force disable or 1 to force enable.", + kForceGbmEnv); + } + + if (GPUInfo::instance()->vendor() == GPUInfo::Nvidia) { + // FIXME: This disables GBM for Nvidia. Remove this when Nvidia fixes its GBM support. + // + // "Buffer allocation and submission to DRM KMS using gbm is not currently supported." + // See: https://download.nvidia.com/XFree86/Linux-x86_64/570.86.16/README/kms.html" + // + // Chromium uses GBM to allocate scanout buffers. Scanout requires DRM KMS. If KMS is + // enabled, gbm_device and gbm_buffer are created without any issues but rendering to + // the buffer will malfunction. It is not known how to detect this problem before + // rendering so we just disable GBM for Nvidia. + return false; + } + + return true; + }(); + + return supported; +} +#endif + void WebEngineContext::registerMainThreadFactories() { content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 7a36fd00187..606c41ef238 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -67,6 +67,9 @@ class WebEngineContext : public base::RefCounted { static ProxyAuthentication qProxyNetworkAuthentication(QString host, int port); static void flushMessages(); static bool closingDown(); +#if defined(USE_OZONE) + static bool isGbmSupported(); +#endif ProfileAdapter *createDefaultProfileAdapter(); ProfileAdapter *defaultProfileAdapter(); From 3a0dad099d1966879a9f41eb56735a971958e7b8 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 9 Jan 2025 13:26:02 +0100 Subject: [PATCH 283/341] Disable dma-buf and GBM for nvidia with GLX It is already disabled with EGL. Checking the existence of a GBM device is just not enough. It is possible to create GBM device and buffer with nvidia driver but it will not work. Merge conflict resolution for 6.8: - No GLXHelper in 6.8 Change-Id: I3806594371d3e266d499bdc396c8f2a4ca17580d Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Moss Heim (cherry picked from commit a3604e0a41b586d1f32865d9c60003ed31e46884) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit b1b0246839b97a5c642ae8093e0c7d61a22eea37) --- src/core/ozone/surface_factory_qt.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index 726c2c0465f..835d2fed210 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -9,6 +9,7 @@ #include "ozone/gl_ozone_angle_qt.h" #include "ozone/gl_ozone_egl_qt.h" #include "qtwebenginecoreglobal_p.h" +#include "web_engine_context.h" #include "media/gpu/buildflags.h" #include "ui/base/ozone_buildflags.h" @@ -265,8 +266,10 @@ bool SurfaceFactoryQt::SupportsNativePixmaps() { #if QT_CONFIG(opengl) #if BUILDFLAG(IS_OZONE_X11) - if (GLContextHelper::getGlxPlatformInterface()) - return ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device(); + if (GLContextHelper::getGlxPlatformInterface()) { + return QtWebEngineCore::WebEngineContext::isGbmSupported() + && ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device(); + } #endif // BUILDFLAG(IS_OZONE_X11) if (GLContextHelper::getEglPlatformInterface()) From d35615c60b3e353122e60b86159dd0d9f423843f Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 20 Feb 2025 09:05:14 +0100 Subject: [PATCH 284/341] Fix importing memory object for rendering without NativePixmap This fixes rendering with newer Nvidia drivers on Linux. - Make memory object dedicated to match Vulkan allocation - Set tiling of the GL texture to match VkImage tiling - Make the TexStorage command non-DSA to uniform GL calls Amends 8ce04357b4ce39b8c4c2243991eae70f78f9b61b Merge conflict resolution for 6.8: - No GLHelper in 6.8, add GL function bindings to NativeSkiaOutputDeviceOpenGL - No GLXHelper and EGLHelper in 6.8, do not change guards around header includes Change-Id: I43e953412acf6d39b67dcd8af02aac4003fc5c8e Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Moss Heim (cherry picked from commit 558bbf10544c9c96cde4ef3c7923c8b3bb8aa237) (cherry picked from commit 8de829cb150989673c6051d4c8e8d04b3b9c89db) --- .../native_skia_output_device_opengl.cpp | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index ac967f26da9..195d4dc72f3 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -24,7 +24,10 @@ #undef glGenTextures #undef glGetError #undef glImportMemoryFdEXT -#undef glTextureStorageMem2DEXT +#undef glIsMemoryObjectEXT +#undef glMemoryObjectParameterivEXT +#undef glTexParameteri +#undef glTexStorageMem2DEXT #include "base/posix/eintr_wrapper.h" #include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" @@ -350,17 +353,32 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te "glCreateMemoryObjectsEXT"); static PFNGLIMPORTMEMORYFDEXTPROC glImportMemoryFdEXT = (PFNGLIMPORTMEMORYFDEXTPROC)glContext->getProcAddress("glImportMemoryFdEXT"); - static PFNGLTEXTURESTORAGEMEM2DEXTPROC glTextureStorageMem2DEXT = - (PFNGLTEXTURESTORAGEMEM2DEXTPROC)glContext->getProcAddress( - "glTextureStorageMem2DEXT"); - + static PFNGLISMEMORYOBJECTEXTPROC glIsMemoryObjectEXT = + (PFNGLISMEMORYOBJECTEXTPROC)glContext->getProcAddress("glIsMemoryObjectEXT"); + static PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glMemoryObjectParameterivEXT = + (PFNGLMEMORYOBJECTPARAMETERIVEXTPROC)glContext->getProcAddress( + "glMemoryObjectParameterivEXT"); + static PFNGLTEXSTORAGEMEM2DEXTPROC glTexStorageMem2DEXT = + (PFNGLTEXSTORAGEMEM2DEXTPROC)glContext->getProcAddress("glTexStorageMem2DEXT"); + + // Import memory object GLuint glMemoryObject; - glFun->glGenTextures(1, &glTexture); - glFun->glBindTexture(GL_TEXTURE_2D, glTexture); glCreateMemoryObjectsEXT(1, &glMemoryObject); + GLint dedicated = GL_TRUE; + glMemoryObjectParameterivEXT(glMemoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicated); glImportMemoryFdEXT(glMemoryObject, importedImageSize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); - glTextureStorageMem2DEXT(glTexture, 1, GL_RGBA8_OES, size().width(), size().height(), - glMemoryObject, 0); + if (!glIsMemoryObjectEXT(glMemoryObject)) + qFatal("VULKAN: Failed to import memory object."); + + // Bind memory object to texture + glFun->glGenTextures(1, &glTexture); + glFun->glBindTexture(GL_TEXTURE_2D, glTexture); + glFun->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, + vkImageInfo.fImageTiling == VK_IMAGE_TILING_OPTIMAL + ? GL_OPTIMAL_TILING_EXT + : GL_LINEAR_TILING_EXT); + glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, size().width(), size().height(), + glMemoryObject, 0); glFun->glBindTexture(GL_TEXTURE_2D, 0); m_frontBuffer->textureCleanupCallback = [glTexture, glMemoryObject]() { From ea7cb8ea1f9ae56f0eb1c89cc7608c7514e8ea11 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 21 Feb 2025 13:56:16 +0100 Subject: [PATCH 285/341] Make MotionEventQt assert more informative Change-Id: I1a91b8fa3004d70f2467085f198d8eaa0ecfdc10 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 254d7db17d09b6c567a3c22567ba322ff952c358) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 0da0582bf8359180bca0edc91a97e5018a7155a9) --- ...er_widget_host_view_qt_delegate_client.cpp | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp index 934df0ce489..493648ceaa4 100644 --- a/src/core/render_widget_host_view_qt_delegate_client.cpp +++ b/src/core/render_widget_host_view_qt_delegate_client.cpp @@ -14,6 +14,7 @@ #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "ui/touch_selection/touch_selection_controller.h" +#include #include #include #include @@ -24,6 +25,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { static inline int firstAvailableId(const QMap &map) @@ -76,12 +79,31 @@ class MotionEventQt : public ui::MotionEvent , flags(flagsFromModifiers(modifiers)) , index(index) { +#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) // index is only valid for POINTER_DOWN and POINTER_UP and should correspond to the point // causing it see blink_event_util.cc:ToWebTouchPointState for details - Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1) - || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == QEventPoint::Pressed) - || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == QEventPoint::Released), - "MotionEventQt", qPrintable(QString("action: %1, index: %2, state: %3").arg(int(action)).arg(index).arg(touchPoint(index).state()))); + if (action == Action::POINTER_DOWN || action == Action::POINTER_UP) { + const auto actionString = (action == Action::POINTER_DOWN ? "Action::POINTER_DOWN"_L1 + : "Action::POINTER_UP"_L1); + Q_ASSERT_X(index >= 0 && index < touchPoints.size(), "MotionEventQt", + qPrintable("Invalid index for "_L1 + actionString + ": "_L1 + + QString::number(index))); + + const QEventPoint::State state = touchPoint(index).state(); + QString stateString; + QDebug(&stateString) << state; + Q_ASSERT_X( + (action == Action::POINTER_DOWN && state == QEventPoint::Pressed) + || (action == Action::POINTER_UP && state == QEventPoint::Released), + "MotionEventQt", + qPrintable("Unexpected state for "_L1 + actionString + ": "_L1 + stateString)); + } else { + Q_ASSERT_X(index == -1, "MotionEventQt", + qPrintable("Unexpected index for action "_L1 + + QString::number(static_cast(action)) + ": "_L1 + + QString::number(index))); + } +#endif } uint32_t GetUniqueEventId() const override { return eventId; } From 5efb3c2e246709fe4591ae4c7781570b0aede17e Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 13 Feb 2025 13:22:12 +0100 Subject: [PATCH 286/341] Use QStringList::append() where the string can be moved into the list As a drive-by, refactor web_engine_library_info.cpp's fromEnv occurrences to use them in the if blocks only and make the code a little bit more readable. Merge conflict resolution for 6.8: - Adapt change to initializer list in DownloadManagerDelegateQt::ChooseSavePath() Change-Id: Ib3ee6390003bc6e196398979d992e71b7fc50a8a Reviewed-by: Moss Heim Reviewed-by: Marc Mutz (cherry picked from commit 26c43ef73cf6a5184ded71d173224e1cd733c90f) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 2d73011de5276e997a9af159531a5830ba97b371) Reviewed-by: Allan Sandfeld Jensen --- src/core/api/qwebenginedownloadrequest.cpp | 2 +- ...thenticator_request_client_delegate_qt.cpp | 2 +- src/core/content_client_qt.cpp | 6 +- src/core/download_manager_delegate_qt.cpp | 6 +- src/core/file_picker_controller.cpp | 6 +- src/core/web_engine_library_info.cpp | 62 ++++++++++--------- 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/core/api/qwebenginedownloadrequest.cpp b/src/core/api/qwebenginedownloadrequest.cpp index cbf46b4481b..70f4b094197 100644 --- a/src/core/api/qwebenginedownloadrequest.cpp +++ b/src/core/api/qwebenginedownloadrequest.cpp @@ -465,7 +465,7 @@ void QWebEngineDownloadRequest::setDownloadDirectory(const QString &directory) d->suggestedFileName, d->startTime)).fileName(); if (d->downloadFileName != newFileName) { - d->downloadFileName = newFileName; + d->downloadFileName = std::move(newFileName); Q_EMIT downloadFileNameChanged(); } } diff --git a/src/core/authenticator_request_client_delegate_qt.cpp b/src/core/authenticator_request_client_delegate_qt.cpp index 5f9fd9ca37d..8837dd85e96 100644 --- a/src/core/authenticator_request_client_delegate_qt.cpp +++ b/src/core/authenticator_request_client_delegate_qt.cpp @@ -150,7 +150,7 @@ void AuthenticatorRequestClientDelegateQt::SelectAccount( if (has_user_identifying_info) { QString userName = toQt(*response.user_entity->name); m_userMap[userName] = nIndex; - userList.append(userName); + userList.append(std::move(userName)); } } m_dialogController->selectAccount(userList); diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index b5f40590a3c..0901f39b6b4 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -218,7 +218,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, const QString versionDirPath = widevineVersionDirs.at(i).absoluteFilePath(); QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/"_L1 + archDir + QLatin1StringView(kWidevineCdmFileName); - pluginPaths << potentialWidevinePluginPath; + pluginPaths.append(std::move(potentialWidevinePluginPath)); } } #elif defined(Q_OS_WIN) @@ -240,7 +240,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, "/WidevineCdm/_platform_specific/win_x86/"_L1 + QLatin1StringView(kWidevineCdmFileName); #endif - pluginPaths << potentialWidevinePluginPath; + pluginPaths.append(std::move(potentialWidevinePluginPath)); } } } @@ -254,7 +254,7 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, #else QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/"_L1 + QLatin1StringView(kWidevineCdmFileName); #endif - pluginPaths << potentialWidevinePluginPath; + pluginPaths.append(std::move(potentialWidevinePluginPath)); } } #elif defined(Q_OS_LINUX) diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 43a853fdca5..afd616e5468 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -193,8 +193,8 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * item->GetState(), item->GetTotalBytes(), item->GetReceivedBytes(), - mimeTypeString, - suggestedFilePath, + std::move(mimeTypeString), + std::move(suggestedFilePath), ProfileAdapterClient::UnknownSavePageFormat, acceptedByDefault, false /* paused */, @@ -202,7 +202,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * isSavePageDownload, item->GetLastReason(), adapterClient, - suggestedFilename, + std::move(suggestedFilename), item->GetStartTime().ToTimeT() }; diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 1c98b90c74c..8f6bd40702c 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -260,16 +260,16 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename"_L1 + type); if (mimeType.isValid()) { QString glob = u'*' + type; - acceptedGlobs.append(glob); nameFilters.append(mimeType.comment() + " ("_L1 + glob + u')'); + acceptedGlobs.append(std::move(glob)); } } else if (type.contains(u'/') && !type.endsWith(u'*')) { // All suffixes for a given MIME type const QMimeType &mimeType = mimeDatabase.mimeTypeForName(type); if (mimeType.isValid() && !mimeType.globPatterns().isEmpty()) { QString globs = mimeType.globPatterns().join(u' '); - acceptedGlobs.append(mimeType.globPatterns()); nameFilters.append(mimeType.comment() + " ("_L1 + globs + u')'); + acceptedGlobs.append(mimeType.globPatterns()); } } else if (type.endsWith("/*"_L1)) { // All MIME types for audio/*, image/* or video/* @@ -279,8 +279,8 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp for (const QMimeType &m : allMimeTypes) { if (m.name().startsWith(type) && !m.globPatterns().isEmpty()) { QString globs = m.globPatterns().join(u' '); - acceptedGlobs.append(m.globPatterns()); nameFilters.append(m.comment() + " ("_L1 + globs + u')'); + acceptedGlobs.append(m.globPatterns()); } } } else { diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index 960b768d701..f7ab89681eb 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -129,11 +129,9 @@ QString subProcessPath() #endif QStringList candidatePaths; - const QString fromEnv = qEnvironmentVariable("QTWEBENGINEPROCESS_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINEPROCESS_PATH if set - candidatePaths << fromEnv; - } else { + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINEPROCESS_PATH"); fromEnv.isEmpty()) { + includeOverrideMessage = true; #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) candidatePaths << getBundlePath(frameworkBundle()) % "/Helpers/"_L1 % qWebEngineProcessName() % ".app/Contents/MacOS/"_L1 @@ -146,6 +144,9 @@ QString subProcessPath() #endif candidatePaths << QCoreApplication::applicationDirPath() % QLatin1Char('/') % processBinary; + } else { + // Only search in QTWEBENGINEPROCESS_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { @@ -162,7 +163,7 @@ QString subProcessPath() for (const QString &candidate : std::as_const(candidatePaths)) errorMessage += " "_L1 + candidate + u'\n'; errorMessage += "but could not find it.\n"_L1; - if (fromEnv.isEmpty()) { + if (includeOverrideMessage) { errorMessage += "You may override the default search path by using " "QTWEBENGINEPROCESS_PATH environment variable.\n"_L1; } @@ -190,11 +191,9 @@ QString localesPath() QStringList candidatePaths; const QString translationPakFilename = QLatin1StringView(WebEngineLibraryInfo::getResolvedLocale()) % ".pak"_L1; - const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINE_LOCALES_PATH if set - candidatePaths << fromEnv; - } else { + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH"); fromEnv.isEmpty()) { + includeOverrideMessage = true; #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) candidatePaths << getResourcesPath(frameworkBundle()) % QDir::separator() % "qtwebengine_locales"_L1; @@ -202,6 +201,9 @@ QString localesPath() candidatePaths << QLibraryInfo::path(QLibraryInfo::TranslationsPath) % QDir::separator() % "qtwebengine_locales"_L1; candidatePaths << fallbackDir(); + } else { + // Only search in QTWEBENGINE_LOCALES_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { @@ -220,7 +222,7 @@ QString localesPath() warningMessage += " "_L1 % candidate + u'\n'; warningMessage += "but could not find the translation file for the current locale: "_L1 + translationPakFilename + u'\n'; - if (fromEnv.isEmpty()) { + if (includeOverrideMessage) { warningMessage += "You may override the default search paths by using " "QTWEBENGINE_LOCALES_PATH environment variable.\n"_L1; } @@ -242,31 +244,33 @@ QString dictionariesPath(bool showWarnings) if (!initialized) { initialized = true; - const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINE_DICTIONARIES_PATH if set - candidatePaths << fromEnv; - } else { + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"); + fromEnv.isEmpty()) { + includeOverrideMessage = true; // First try to find dictionaries near the application. #ifdef Q_OS_DARWIN QString resourcesDictionariesPath = getMainApplicationResourcesPath() % QDir::separator() % "qtwebengine_dictionaries"_L1; - candidatePaths << resourcesDictionariesPath; + candidatePaths.append(std::move(resourcesDictionariesPath)); #endif QString applicationDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator() % "qtwebengine_dictionaries"_L1; - candidatePaths << applicationDictionariesPath; + candidatePaths.append(std::move(applicationDictionariesPath)); // Then try to find dictionaries near the installed library. #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) % "/qtwebengine_dictionaries"_L1; - candidatePaths << frameworkDictionariesPath; + candidatePaths.append(std::move(frameworkDictionariesPath)); #endif QString libraryDictionariesPath = QLibraryInfo::path(QLibraryInfo::DataPath) % QDir::separator() % "qtwebengine_dictionaries"_L1; - candidatePaths << libraryDictionariesPath; + candidatePaths.append(std::move(libraryDictionariesPath)); + } else { + // Only search in QTWEBENGINE_DICTIONARIES_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { @@ -283,7 +287,7 @@ QString dictionariesPath(bool showWarnings) for (const QString &candidate : std::as_const(candidatePaths)) warningMessage += " "_L1 + candidate + u'\n'; warningMessage += "but could not find it.\n"_L1; - if (fromEnv.isEmpty()) { + if (includeOverrideMessage) { warningMessage += "You may override the default search path by using " "QTWEBENGINE_DICTIONARIES_PATH environment variable.\n"_L1; } @@ -305,11 +309,10 @@ QString resourcesPath() if (potentialResourcesPath.isEmpty()) { QStringList candidatePaths; const auto resourcesPakFilename = "qtwebengine_resources.pak"_L1; - const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINE_RESOURCES_PATH if set - candidatePaths << fromEnv; - } else { + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH"); + fromEnv.isEmpty()) { + includeOverrideMessage = true; #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) candidatePaths << getResourcesPath(frameworkBundle()); #endif @@ -318,6 +321,9 @@ QString resourcesPath() candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath); candidatePaths << QCoreApplication::applicationDirPath(); candidatePaths << fallbackDir(); + } else { + // Only search in QTWEBENGINE_RESOURCES_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { @@ -335,7 +341,7 @@ QString resourcesPath() for (const QString &candidate : std::as_const(candidatePaths)) errorMessage += " "_L1 + candidate + u'\n'; errorMessage += "but could not find any.\n"_L1; - if (fromEnv.isEmpty()) { + if (includeOverrideMessage) { errorMessage += "You may override the default search paths by using " "QTWEBENGINE_RESOURCES_PATH environment variable.\n"_L1; } From 73784f64689cd527bee71708027d08202eaa4d70 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 28 Feb 2025 08:11:51 +0000 Subject: [PATCH 287/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I9b56213b7d5235c9c1e3319776a0d33a696096e4 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 6b4c0c5a26f..393eda358ed 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 72d314d1e51709a71d856fa0bf1eb0d146013f8e + ref: 38a2283787edfe6f3d2f873599792c695a02afb0 required: true ../qtpositioning: - ref: d439b858a902e16f198a973ac605bdc13c171ad7 + ref: b78a3269dd1fafbd6ce7b314f609b00b70b9d6e3 required: false ../qttools: - ref: 53798d1ceb1ff9fa4fc1b291b49f656929f8059d + ref: cab5a7992bd13c789882d6d25a62fa2fa272edbb required: false ../qtwebchannel: - ref: fcfe7c1a7d3f841111bb6e5409411e46d0f5b116 + ref: c5d6e02e2653551433035268daf0a0724900c408 required: false From 4a8cc427fb9c8bfa97efc78a437104deb67014d0 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 7 Feb 2025 12:31:15 +0000 Subject: [PATCH 288/341] Doc: Fix documentation issues PdfStyle.qml: (qdoc) warning: Unknown base 'QtObject' for QML type 'PdfStyle' Fixed by introducing a doc dependency to `qtqml`. qwebenginenewwindowrequest.cpp: (qdoc) warning: Invalid QML property type: QUrl (qdoc) warning: Invalid QML property type: QRect Replaced with QML types (url, rect) instead. qwebenginewebauthuxrequest.cpp: (qdoc) warning: Can't link to 'WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin' (qdoc) warning: Can't link to 'WebEngineWebAuthPinRequest::reason' Fixes: QTBUG-134248 Change-Id: I313dddba6a374e65c23d371437d0fb148374bd2c Reviewed-by: Andreas Eliasson (cherry picked from commit 5f976f185d3ead42e1dbb028deca60a2cfc0b9c6) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit e258edec23a24c6b308455c2706e945612787aff) Reviewed-by: Allan Sandfeld Jensen --- src/core/api/qwebenginenewwindowrequest.cpp | 4 ++-- src/core/api/qwebenginewebauthuxrequest.cpp | 7 ++++--- src/pdf/doc/qtpdf.qdocconf | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/api/qwebenginenewwindowrequest.cpp b/src/core/api/qwebenginenewwindowrequest.cpp index 1f0be9aa03c..500f3ac2bf2 100644 --- a/src/core/api/qwebenginenewwindowrequest.cpp +++ b/src/core/api/qwebenginenewwindowrequest.cpp @@ -98,7 +98,7 @@ QWebEngineNewWindowRequest::DestinationType QWebEngineNewWindowRequest::destinat \brief The URL that is requested for the new page. */ /*! - \qmlproperty QUrl WebEngineNewWindowRequest::requestedUrl + \qmlproperty url WebEngineNewWindowRequest::requestedUrl \brief The URL that is requested for the new page. \since QtWebEngine 1.5 */ @@ -112,7 +112,7 @@ QUrl QWebEngineNewWindowRequest::requestedUrl() const \brief The size that is requested for the new page. */ /*! - \qmlproperty QRect WebEngineNewWindowRequest::requestedGeometry + \qmlproperty rect WebEngineNewWindowRequest::requestedGeometry \brief The size that is requested for the new page. \since QtWebEngine 2.0 */ diff --git a/src/core/api/qwebenginewebauthuxrequest.cpp b/src/core/api/qwebenginewebauthuxrequest.cpp index 18ebbb70ea9..3c289fd5c3a 100644 --- a/src/core/api/qwebenginewebauthuxrequest.cpp +++ b/src/core/api/qwebenginewebauthuxrequest.cpp @@ -109,8 +109,9 @@ \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. \li The minimum PIN length that the authenticator will accept for the PIN. \endlist - Use this structure to update the WebAuth UX dialog when the WebAuth UX state is \l - WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin. + Use this structure to update the WebAuth UX dialog when the WebAuth UX + \l {WebEngineWebAuthUxRequest::}{state} is + \c {WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin}. */ /*! @@ -137,7 +138,7 @@ /*! \qmlproperty int QtWebEngine::webEngineWebAuthPinRequest::remainingAttempts \brief The number of attempts remaining before a hard lock. Should be ignored unless - \l{WebEngineWebAuthPinRequest::reason} is + \l{webEngineWebAuthPinRequest::reason} is \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. */ diff --git a/src/pdf/doc/qtpdf.qdocconf b/src/pdf/doc/qtpdf.qdocconf index d0340fe8317..d208188df8d 100644 --- a/src/pdf/doc/qtpdf.qdocconf +++ b/src/pdf/doc/qtpdf.qdocconf @@ -38,6 +38,7 @@ depends += qtcore \ qtdoc \ qmake \ qtdesigner \ + qtqml \ qtquick \ qtquickcontrols \ qtcmake \ From f33a4a521f7472c44808dab83af595ff0f76692b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucie=20G=C3=A9rard?= Date: Wed, 15 Jan 2025 15:01:39 +0100 Subject: [PATCH 289/341] Make module ready for source SBOM checking This includes: - turning VERIFY_SOURCE_SBOM ON - adding rules to the licenseRule.json files - correcting the licensing given via REUSE.toml files A lot of files are skipped during the license test, but all are present in the source SBOM. This is why corrections are needed before turning the source SBOM check on. Task-number: QTBUG-131434 Change-Id: Iabe0bee0ed0fc9de42ee69508eb0dd7d84601647 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 815ea62cc2f4a20b8c19e6d62146e07c0876ab19) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 56065dae710699f332ccb9f1e306b639a6b284aa) --- REUSE.toml | 12 +++++----- coin/module_config.yaml | 3 +++ licenseRule.json | 49 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/REUSE.toml b/REUSE.toml index 9474f351661..18dbbabe24b 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -11,7 +11,8 @@ path = ["src/core/doc/QtWebEngineDoc", "src/process/QtWebEngineProcess.exe.manifest", "src/webenginequick/ui/information.png", "src/webenginequick/ui/question.png", - "src/webenginewidgets/plugins/qwebengineview/images/qwebengineview.png"] + "src/webenginewidgets/plugins/qwebengineview/images/qwebengineview.png", + "src/pdf/plugins/imageformats/pdf/pdf.json"] precedence = "closest" comment = "module and plugin" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." @@ -70,8 +71,9 @@ SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GPL-3.0-only" [[annotations]] -path = ["**.pro", "**.qrc", "**CMakeLists.txt", ".cmake.conf", "**.yaml", "**.json", - "**.cfg", "**BLACKLIST", "**.plist", "**.plist.in", "**BUILD**.in"] +path = ["**.pro", "**.qrc", "**CMakeLists.txt", ".cmake.conf", "**.yaml", + "**.cfg", "**BLACKLIST", "**.plist", "**.plist.in", "**BUILD**.in", "coin.nodes", + "coin/qt-installer-package-config.json", ".gitmodules"] precedence = "closest" comment = "build system" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." @@ -85,14 +87,14 @@ SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" [[annotations]] -path = ["**/doc/images/**", "examples/**", "tests/manual/examples/**", "**/doc/snippets/**"] +path = ["examples/**", "tests/manual/examples/**", "**/doc/snippets/**"] comment = "this must be after the build system table because example and snippets take precedence over build system" precedence = "closest" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] -path = ["**.qdocconf", "config_help.txt", ".gitmodules"] +path = ["**/doc/images/**", "**.qdocconf", "config_help.txt"] comment = "documentation" precedence = "closest" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." diff --git a/coin/module_config.yaml b/coin/module_config.yaml index 9c6e1d003e5..cceb2502a34 100644 --- a/coin/module_config.yaml +++ b/coin/module_config.yaml @@ -13,6 +13,9 @@ machine_type: instructions: Build: + - type: EnvironmentVariable + variableName: VERIFY_SOURCE_SBOM + variableValue: "ON" - type: EnvironmentVariable variableName: CMAKE_BUILD_TIMEOUT variableValue: "36000" diff --git a/licenseRule.json b/licenseRule.json index 5f78a7dc8c1..695e3a422fe 100644 --- a/licenseRule.json +++ b/licenseRule.json @@ -10,7 +10,11 @@ "Files with other endings can also be build system files" ], "file_pattern_ending" : ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", - "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", ".clang-format"], + "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", + ".clang-format", ".plist", ".qrc", "BLACKLIST", ".gitignore", ".gitattributes", + ".tag", ".cmake.conf", ".yaml", "coin/qt-installer-package-config.json", + "BUILD.root.gn.in", "BUILD.toolchain.gn.in", "BUILD.msvc.toolchain.gn.in", + ".cfg", "coin.nodes", ".gitmodules"], "location" : { "" : { "comment" : "Default", @@ -44,7 +48,8 @@ }, { "comment" : "Files with the following endings are Documentation licensed.", - "file_pattern_ending" : [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", ".txt", "README", "qt_attribution.json"], + "file_pattern_ending" : [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", "README", "qt_attribution.json", + "REUSE.toml", "config_help.txt", "licenseRule.json"], "location" :{ "" : { "comment" : "", @@ -64,6 +69,11 @@ "file type" : "module and plugin", "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] }, + "dist/" : { + "comment" : "Default", + "file type" : "documentation", + "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + }, "src/" : { "comment" : "Default", "file type" : "module and plugin", @@ -79,6 +89,11 @@ "file type" : "examples and snippets", "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] }, + "(.*|examples).*doc/images/" : { + "comment" : "Default", + "file type" : "documentation", + "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + }, "src/host/config\\.tests/" : { "comment" : "Default", "file type" : "build system", @@ -98,6 +113,36 @@ "comment" : "Partially from Chromium", "file type" : "module and plugin", "spdx" : ["BSD-3-Clause"] + }, + "tests/auto/widgets/qwebengine(view|script|page|history)/tst_qwebengine.*.cpp" : { + "comment" : "exception", + "file type" : "test", + "spdx" : ["LGPL-2.0-or-later"] + }, + "tests/auto/widgets/accessibility/tst_accessibility.cpp" : { + "comment" : "exception", + "file type" : "test", + "spdx" : ["LGPL-2.0-or-later"] + }, + "tests/auto/core/qwebengine(settings|frame)/tst_qwebengine.*.cpp" : { + "comment" : "exception", + "file type" : "test", + "spdx" : ["LGPL-2.0-or-later"] + }, + "examples/webenginewidgets/contentmanipulation/jquery.min.js" : { + "comment" : "", + "file type" : "3rd party", + "spdx" : ["MIT"] + }, + "src/core/ozone/(ozone_extra.gni|BUILD.gn)" : { + "comment" : "Chrominum", + "file type" : "3rd party", + "spdx" : ["BSD-3-Clause"] + }, + "CHROMIUM_VERSION" : { + "comment" : "Chrominum", + "file type" : "3rd party", + "spdx" : ["CC0-1.0"] } } } From 9ab8432ee9c64668e7413a526309874410c5ee4e Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Tue, 4 Mar 2025 16:31:36 +0000 Subject: [PATCH 290/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I3134fdeddb32f55509c8248abe408c94a78a8fa1 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 393eda358ed..3245aafc1ed 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 38a2283787edfe6f3d2f873599792c695a02afb0 + ref: 7b4837d3e34a206ccbd3b921e65f1401b09066ee required: true ../qtpositioning: - ref: b78a3269dd1fafbd6ce7b314f609b00b70b9d6e3 + ref: 83cc61df4afb3b81da03c9ec6d3536b32d60b07d required: false ../qttools: - ref: cab5a7992bd13c789882d6d25a62fa2fa272edbb + ref: feda5851ddced220d26ce80624fca527dde0a0ea required: false ../qtwebchannel: - ref: c5d6e02e2653551433035268daf0a0724900c408 + ref: ca7d35059a0effe4fbdb57a1b5e604f3d815b12a required: false From 596d1125105842250396de35f683c5ef77e1fe96 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 17 Feb 2025 17:20:25 +0000 Subject: [PATCH 291/341] Doc: Add WebEngineDriver source directory to documentation build While there is no documentation sources to parse there, the Chromium code attribution script uses it as the output directory for the generated 3rd party licenses. Add the directory to make QDoc parse the generated output. Fixes: QTBUG-133495 Pick-to: 6.5 Change-Id: I06643163e1b7791664afcfead90a91b65d3039af Reviewed-by: Paul Wicking Reviewed-by: Moss Heim (cherry picked from commit d34d887f271df107ff0ec668cf85de149feeae6d) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 706e582b2016090b68fe6b4ebdc6904dd92ec628) --- src/core/doc/qtwebengine.qdocconf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf index 25f55f154cf..ee875780165 100644 --- a/src/core/doc/qtwebengine.qdocconf +++ b/src/core/doc/qtwebengine.qdocconf @@ -70,6 +70,7 @@ headerdirs += ../../core/api \ sourcedirs += ../../core/api \ ../../core/doc \ + ../../core/tools/webenginedriver \ ../../webenginequick/api \ ../../webenginequick/doc \ ../../webenginewidgets/api \ From f0090ef1bad65e682659c0de445ccc7b3a38d15e Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 4 Mar 2025 15:17:19 +0100 Subject: [PATCH 292/341] NativeSkiaOutputDevice: Fix leaking texture Release texture resources before unbinding the compositor. Otherwise we don't have compositor to release texture after navigating to a new page. Detected by Vulkan validation layer but supposedly affects all backends. Amends 6781151fc Compositor: do not call unbind() from the base destructor Change-Id: I4d9330de64a81c195091691e92164bd9eeb6d121 Reviewed-by: Michal Klocek (cherry picked from commit 53b6d433d70d6992652d7031d8a6f0600a22eacd) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 2d2f63211b80a77cddfbb608f601051d7beebbd5) --- src/core/compositor/native_skia_output_device.cpp | 2 ++ src/core/render_widget_host_view_qt_delegate_item.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp index 64688f9a018..aef0a8158f7 100644 --- a/src/core/compositor/native_skia_output_device.cpp +++ b/src/core/compositor/native_skia_output_device.cpp @@ -215,6 +215,8 @@ NativeSkiaOutputDevice::Buffer::Buffer(NativeSkiaOutputDevice *parent) NativeSkiaOutputDevice::Buffer::~Buffer() { + DCHECK(!textureCleanupCallback); + if (m_scopedSkiaWriteAccess) endWriteSkia(false); diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp index 94f786d1ca8..85d0c9111e8 100644 --- a/src/core/render_widget_host_view_qt_delegate_item.cpp +++ b/src/core/render_widget_host_view_qt_delegate_item.cpp @@ -37,8 +37,8 @@ RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWid RenderWidgetHostViewQtDelegateItem::~RenderWidgetHostViewQtDelegateItem() { - unbind(); // Compositor::Observer releaseTextureResources(); + unbind(); // Compositor::Observer if (m_widgetDelegate) { m_widgetDelegate->Unbind(); m_widgetDelegate->Destroy(); From f488766eb4f716158c7f993a8fe33e942d2da5cc Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Fri, 7 Mar 2025 15:08:05 +0100 Subject: [PATCH 293/341] Update Chromium Submodule src/3rdparty c8dcfa48..b9e733ff: * [Backport] Security bug 396481096 * [Backport] CVE-2024-11477 / Security bug 383772517 * [Backport] CVE-2025-1426: Heap buffer overflow in GPU * [Backport] CVE-2025-1006: Use after free in Network * [Backport] CVE-2025-0999: Heap buffer overflow in V8 * [Backport] CVE-2025-0996: Inappropriate implementation in Browser UI * [Backport] CVE-2025-0998: Out of bounds memory access in V8 * [Backport] Security bug 390465670 * [Backport] Security bug 379418979 * [Backport] Security bug 378917565 (2/2) * [Backport] Security bug 378917565 (1/2) * [Backport] Security bug 359992017 * [Backport] CVE-2025-0762: Use after free in DevTools * [fixup][ffmpeg] Fix building with system ffmpeg * Disable DCHECK in property_tree.cc, layer_tree_impl.cc * [fixup][msvc22] IWYU adding missing includes * [fixup][msvc22] Add missing include for Supplement * Fix invalid iterator access inside LockManager Fixes: QTBUG-133881 Fixes: QTBUG-133889 Fixes: QTBUG-133883 Fixes: QTBUG-134132 Change-Id: I4ddef14e27dc7f5517571f6fca9dc074a109fba3 Reviewed-by: Peter Varga Reviewed-by: Allan Sandfeld Jensen --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 4a17fe015bd..c386131a578 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 132.0.6834.111 +Patched with security patches up to Chromium version: 133.0.6943.141 diff --git a/src/3rdparty b/src/3rdparty index c8dcfa4891c..b9e733fff4c 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit c8dcfa4891c8dcf733b0c6ecc6ddcfe781d4567d +Subproject commit b9e733fff4cb73f6c417ec6c6d8fc78113ea1904 diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index f77b380db33..59c946f0f1d 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1296,7 +1296,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "132.0.6834.111"; // FIXME: Remember to update + return "133.0.6943.141"; // FIXME: Remember to update } QT_END_NAMESPACE From 2b231fe3fd283eccb4df0dac6685eb68e1f6e9b1 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 6 Mar 2025 13:11:27 +0100 Subject: [PATCH 294/341] Fix modifier flags for lock keys on Linux Amends 2dc642d3f Forward modifier flags for lock keys Fixes: QTBUG-134107 Change-Id: I3bb5bff0fb43f2db4c91411f3d4e78469aa41747 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit e4785c85d61ae3a4694ddd105a66ef5869b36038) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 885c263791af9cddb1056af9ed092225099046f3) --- src/core/web_event_factory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index fc15134eb27..52100048da0 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -1252,9 +1252,9 @@ static WebInputEvent::Modifiers lockKeyModifiers(const quint32 nativeModifiers) { unsigned result = 0; if (keyboardDriver() == KeyboardDriver::Xkb) { - if (nativeModifiers & 0x42) /* Caps_Lock */ + if (nativeModifiers & 0x2) /* XCB_MOD_MASK_LOCK */ result |= WebInputEvent::kCapsLockOn; - if (nativeModifiers & 0x4d) /* Num_Lock */ + if (nativeModifiers & 0x10) /* XCB_MOD_MASK_2 */ result |= WebInputEvent::kNumLockOn; } else if (keyboardDriver() == KeyboardDriver::Windows) { if (nativeModifiers & 0x100) /* CapsLock */ From 5425f083555c2b0761b4027bbceb41c513be0957 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 12 Mar 2025 15:16:20 +0100 Subject: [PATCH 295/341] Update Chromium Submodule src/3rdparty b9e733ff..a3fcb1e2: * [backport] CVE-2025-1915 * [backport] CVE-2025-1919 * [backport] CVE-2025-1921 * [backport] CVE-2025-1918 Pick-to: 6.8.3 Fixes: QTBUG-134644 Change-Id: I04cd7417930cd43653a914be05781d40ba5df626 Reviewed-by: Anu Aliyas --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index c386131a578..4ab0b3cdbcd 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 133.0.6943.141 +Patched with security patches up to Chromium version: 134.0.6998.35 diff --git a/src/3rdparty b/src/3rdparty index b9e733fff4c..a3fcb1e25e5 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit b9e733fff4cb73f6c417ec6c6d8fc78113ea1904 +Subproject commit a3fcb1e25e55e372d52c37722fad3074e8403d65 diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 59c946f0f1d..b7aafd3a050 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1296,7 +1296,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "133.0.6943.141"; // FIXME: Remember to update + return "134.0.6998.35"; // FIXME: Remember to update } QT_END_NAMESPACE From a953359ed855ad91b848f22e7d38b13d0f2eb61e Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 12 Mar 2025 15:23:54 +0100 Subject: [PATCH 296/341] Update Chromium Submodule src/3rdparty a3fcb1e2..55749ed0: * [backport] CVE-2025-24201 2/2 * [backport] CVE-2025-24201 1/2 * [backport] CVE-2025-2136 Pick-to: 6.8.3 Fixes: QTBUG-134642 Change-Id: I5b7657b0f88f08365bdfd51818f1aa1279b14626 Reviewed-by: Anu Aliyas --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 4ab0b3cdbcd..58db9e1086a 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 134.0.6998.35 +Patched with security patches up to Chromium version: 134.0.6998.89 diff --git a/src/3rdparty b/src/3rdparty index a3fcb1e25e5..55749ed0af5 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit a3fcb1e25e55e372d52c37722fad3074e8403d65 +Subproject commit 55749ed0af5869215b88007df0cba430746583ae diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index b7aafd3a050..5eea0c45622 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1296,7 +1296,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "134.0.6998.35"; // FIXME: Remember to update + return "134.0.6998.89"; // FIXME: Remember to update } QT_END_NAMESPACE From 8933c29eb1c6979beb2d26063d7861b7a999bd79 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 7 Feb 2025 13:24:22 +0100 Subject: [PATCH 297/341] Use printf-like syntax for qFatal, qWarning and qInfo where appropriate Also use qUtf16Printable() where appropriate. Merge conflict resolution for 6.8: - compositor.cpp: adapt to more compositor type - native_skia_output_device_opengl.cpp: no getGLErrorString() and no clearing GL error flags - wgl_helper.cpp: no WGLHelper and no ::GetLastError to replace - download_manager_delegate_qt.cpp: the qWarning is in another method - egl_helper.cpp: no EGLHelper, qWarnings are in gl_context_qt.cpp - glx_helper.cpp: no GLXHelper, qWarning is in native_skia_output_device_opengl.cpp - surface_factory_qt.cpp: no EGLHelper::getLastEGLErrorString(), adapt fix to eglGetError() Change-Id: I23e8a9b6b419f692dfd719f38c9a8a39086dffd2 Reviewed-by: Marc Mutz (cherry picked from commit 51d36fdd193d7acd597bed713e278fc26cd1f0e6) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit cbef11c876c3cc8a8859c8644e687235deb045dc) --- src/core/api/qwebenginescript.cpp | 2 +- src/core/api/qwebengineurlscheme.cpp | 14 +++++++++----- src/core/compositor/compositor.cpp | 4 ++-- .../native_skia_output_device_direct3d11.cpp | 4 ++-- .../native_skia_output_device_opengl.cpp | 6 +++--- .../native_skia_output_device_vulkan.cpp | 4 ++-- src/core/desktop_media_controller.cpp | 4 ++-- src/core/devtools_manager_delegate_qt.cpp | 8 ++++++-- src/core/download_manager_delegate_qt.cpp | 3 ++- src/core/file_picker_controller.cpp | 11 ++++++++--- src/core/media_capture_devices_dispatcher.cpp | 8 ++++++-- src/core/net/url_request_custom_job_proxy.cpp | 4 +++- src/core/ozone/gl_context_qt.cpp | 12 ++++++------ src/core/ozone/surface_factory_qt.cpp | 8 +++----- src/core/profile_io_data_qt.cpp | 2 +- src/core/profile_qt.cpp | 3 ++- src/core/web_contents_adapter.cpp | 2 +- src/core/web_engine_context.cpp | 13 ++++++------- src/core/web_engine_library_info.cpp | 16 ++++++++-------- 19 files changed, 73 insertions(+), 55 deletions(-) diff --git a/src/core/api/qwebenginescript.cpp b/src/core/api/qwebenginescript.cpp index 772dd7dfb2c..ab91576bd89 100644 --- a/src/core/api/qwebenginescript.cpp +++ b/src/core/api/qwebenginescript.cpp @@ -168,7 +168,7 @@ void QWebEngineScript::setSourceUrl(const QUrl &url) } if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "Can't open user script " << url; + qWarning("Can't open user script %ls", qUtf16Printable(url.toString())); return; } diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp index be56a304801..d2ca56f62d8 100644 --- a/src/core/api/qwebengineurlscheme.cpp +++ b/src/core/api/qwebengineurlscheme.cpp @@ -335,29 +335,33 @@ void QWebEngineUrlScheme::setFlags(Flags newValue) void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme) { if (scheme.d->name.empty()) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty"); return; } bool needsPort = scheme.d->has_port_component(); bool hasPort = scheme.d->default_port != url::PORT_UNSPECIFIED; if (needsPort && !hasPort) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "needs a default port"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s needs a default port", + scheme.d->name.data()); return; } if (url::CustomScheme::FindScheme(scheme.d->name)) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "already registered"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s already registered", + scheme.d->name.data()); return; } if (url::IsStandard(scheme.d->name.data(), url::Component(0, static_cast(scheme.d->name.size())))) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "is a standard scheme"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s is a standard scheme", + scheme.d->name.data()); return; } if (g_schemesLocked) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Too late to register scheme" << scheme.name(); + qWarning("QWebEngineUrlScheme::registerScheme: Too late to register scheme %s", + scheme.d->name.data()); return; } diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp index 1ea92250501..9a99ddfd952 100644 --- a/src/core/compositor/compositor.cpp +++ b/src/core/compositor/compositor.cpp @@ -179,8 +179,8 @@ Compositor::Compositor(Type type) : m_type(type) break; } } - qCDebug(lcWebEngineCompositor, "QPA Platform Plugin: %s", - qPrintable(QGuiApplication::platformName())); + qCDebug(lcWebEngineCompositor, "QPA Platform Plugin: %ls", + qUtf16Printable(QGuiApplication::platformName())); } Compositor::~Compositor() diff --git a/src/core/compositor/native_skia_output_device_direct3d11.cpp b/src/core/compositor/native_skia_output_device_direct3d11.cpp index e2f33506890..ff469382f84 100644 --- a/src/core/compositor/native_skia_output_device_direct3d11.cpp +++ b/src/core/compositor/native_skia_output_device_direct3d11.cpp @@ -81,9 +81,9 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_ ID3D11Texture2D *qtTexture = nullptr; hr = device1->OpenSharedResource1(sharedHandle, IID_PPV_ARGS(&qtTexture)); if (FAILED(hr)) { - qWarning("D3D: Failed to share D3D11 texture (%s). This will result in failed rendering. " + qWarning("D3D: Failed to share D3D11 texture (%ls). This will result in failed rendering. " "Report the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu", - qPrintable(QSystemError::windowsComString(hr))); + qUtf16Printable(QSystemError::windowsComString(hr))); ::CloseHandle(sharedHandle); return nullptr; } diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index 195d4dc72f3..deccd247b8d 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -97,9 +97,9 @@ x11::Pixmap XPixmapFromNativePixmap(const gfx::NativePixmap &nativePixmap) .Sync(); if (response.error) { - qWarning() << "Could not import the dma-buf as an XPixmap because " - "PixmapFromBuffer() failed; error: " - << response.error->ToString(); + qWarning("Could not import the dma-buf as an XPixmap because PixmapFromBuffer() " + "failed; error: %s", + response.error->ToString().c_str()); return x11::Pixmap::None; } diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index 1e3ba2d51c3..428dc06cf65 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -248,7 +248,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te result = df->vkCreateImage(qtVulkanDevice, &importedImageCreateInfo, nullptr /* pAllocator */, &importedImage); if (result != VK_SUCCESS) - qFatal() << "VULKAN: vkCreateImage failed result:" << result; + qFatal("VULKAN: vkCreateImage failed result: %d", static_cast(result)); #if defined(USE_OZONE) VkImportMemoryFdInfoKHR importMemoryHandleInfo = { @@ -309,7 +309,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te result = df->vkAllocateMemory(qtVulkanDevice, &memoryAllocateInfo, nullptr /* pAllocator */, &importedImageMemory); if (result != VK_SUCCESS) - qFatal() << "VULKAN: vkAllocateMemory failed result:" << result; + qFatal("VULKAN: vkAllocateMemory failed result: %d", static_cast(result)); df->vkBindImageMemory(qtVulkanDevice, importedImage, importedImageMemory, 0); diff --git a/src/core/desktop_media_controller.cpp b/src/core/desktop_media_controller.cpp index 09c1aea1914..2321d31047c 100644 --- a/src/core/desktop_media_controller.cpp +++ b/src/core/desktop_media_controller.cpp @@ -42,7 +42,7 @@ std::unique_ptr createMediaList(DesktopMediaType type) std::unique_ptr screenCapturer = webrtc::DesktopCapturer::CreateScreenCapturer(options); if (!screenCapturer) { - qWarning() << "Screen capturing is not available. Media list will be empty."; + qWarning("Screen capturing is not available. Media list will be empty."); return nullptr; } auto capturer = std::make_unique(std::move(screenCapturer)); @@ -52,7 +52,7 @@ std::unique_ptr createMediaList(DesktopMediaType type) std::unique_ptr windowCapturer = webrtc::DesktopCapturer::CreateWindowCapturer(options); if (!windowCapturer) { - qWarning() << "Window capturing is not available. Media list will be empty."; + qWarning("Window capturing is not available. Media list will be empty."); return nullptr; } auto capturer = std::make_unique(std::move(windowCapturer)); diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp index 838964d01be..b584ecb0de7 100644 --- a/src/core/devtools_manager_delegate_qt.cpp +++ b/src/core/devtools_manager_delegate_qt.cpp @@ -84,8 +84,12 @@ void DevToolsServerQt::parseAddressAndPort() m_port = portStr.toInt(&m_valid); m_valid = m_valid && (m_port > 0 && m_port < 65535); - if (!m_valid) - qWarning("Invalid port given for the inspector server \"%s\". Examples of valid input: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's network interface).", qPrintable(portStr)); + if (!m_valid) { + qWarning("Invalid port given for the inspector server \"%ls\". " + "Examples of valid input: \"12345\" or \"192.168.2.14:12345\" " + "(with the address of one of this host's network interface).", + qUtf16Printable(portStr)); + } } std::unique_ptr DevToolsServerQt::CreateSocketFactory() diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index afd616e5468..bbe487fc918 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -220,7 +220,8 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * QDir suggestedDir = QDir(suggestedFile.absolutePath()); if (!suggestedDir.isRoot() || !suggestedDir.exists()) { #endif - qWarning("Creating download path failed, download cancelled: %s", suggestedFile.absolutePath().toUtf8().data()); + qWarning("Creating download path failed, download cancelled: %ls", + qUtf16Printable(suggestedFile.absolutePath())); info.accepted = false; #if defined(Q_OS_WIN) } diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 8f6bd40702c..3aeb0f5da5f 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -96,7 +96,9 @@ void FilePickerController::accepted(const QStringList &files) absolutePath += scheme.at(5) + ":/"_L1; } else { #endif - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + qWarning("Ignoring invalid item in " + "FilePickerController::accepted(QStringList): %ls", + qUtf16Printable(urlString)); continue; #if defined(Q_OS_WIN) } @@ -115,7 +117,9 @@ void FilePickerController::accepted(const QStringList &files) absolutePath += u'/'; #endif } else { - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + qWarning("Ignoring invalid item in " + "FilePickerController::accepted(QStringList): %ls", + qUtf16Printable(urlString)); continue; } } @@ -132,7 +136,8 @@ void FilePickerController::accepted(const QStringList &files) continue; } } - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %ls", + qUtf16Printable(urlString)); } FilePickerController::filesSelectedInChooser(stringList); diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 73885b6f203..73cf2be6cac 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -361,8 +361,12 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: bool securityOriginsMatch = (requestSecurityOrigin.host() == securityOrigin.host() && requestSecurityOrigin.scheme() == securityOrigin.scheme() && requestSecurityOrigin.port() == securityOrigin.port()); - if (!securityOriginsMatch) - qWarning("Security origin mismatch for media access permission: %s requested and %s provided\n", qPrintable(requestSecurityOrigin.toString()), qPrintable(securityOrigin.toString())); + if (!securityOriginsMatch) { + qWarning("Security origin mismatch for media access permission: %ls requested " + "and %ls provided\n", + qUtf16Printable(requestSecurityOrigin.toString()), + qUtf16Printable(securityOrigin.toString())); + } WebContentsAdapterClient::MediaRequestFlags requestFlags = mediaRequestFlagsForRequest(request); WebContentsAdapterClient::MediaRequestFlags finalFlags = requestFlags & authorizationFlags; diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp index 54faddc6227..21d73730d4b 100644 --- a/src/core/net/url_request_custom_job_proxy.cpp +++ b/src/core/net/url_request_custom_job_proxy.cpp @@ -55,7 +55,9 @@ void URLRequestCustomJobProxy::reply(std::string contentType, QIODevice *device, m_client->m_charset = qcontentType.mid(cidx + 8).trimmed().toStdString(); qcontentType = qcontentType.first(sidx); } else { - qWarning() << "QWebEngineUrlRequestJob::reply(): Unrecognized content-type format with ';'" << qcontentType; + qWarning("QWebEngineUrlRequestJob::reply(): Unrecognized content-type format with ';' " + "%s", + qcontentType.constData()); } } m_client->m_mimeType = qcontentType.trimmed().toStdString(); diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index f59c3fa14d0..ab6717b5e19 100644 --- a/src/core/ozone/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -342,21 +342,21 @@ void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *str EGLImage eglImage = m_functions->eglCreateImage(eglDisplay, eglContext, EGL_GL_TEXTURE_2D, (EGLClientBuffer)textureId, NULL); if (eglImage == EGL_NO_IMAGE) { - qWarning() << "EGL: Failed to create EGLImage:" - << ui::GetEGLErrorString(m_functions->eglGetError()); + qWarning("EGL: Failed to create EGLImage: %s", + ui::GetEGLErrorString(m_functions->eglGetError())); return; } int numPlanes = 0; if (!m_functions->eglExportDMABUFImageQueryMESA(eglDisplay, eglImage, nullptr, &numPlanes, modifiers)) - qWarning() << "EGL: Failed to retrieve the pixel format of the buffer:" - << ui::GetEGLErrorString(m_functions->eglGetError()); + qWarning("EGL: Failed to retrieve the pixel format of the buffer: %s", + ui::GetEGLErrorString(m_functions->eglGetError())); Q_ASSERT(numPlanes == 1); if (!m_functions->eglExportDMABUFImageMESA(eglDisplay, eglImage, fd, stride, offset)) - qWarning() << "EGL: Failed to retrieve the dma_buf file descriptor:" - << ui::GetEGLErrorString(m_functions->eglGetError()); + qWarning("EGL: Failed to retrieve the dma_buf file descriptor: %s", + ui::GetEGLErrorString(m_functions->eglGetError())); m_functions->eglDestroyImage(eglDisplay, eglImage); #endif // QT_CONFIG(egl) diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index 835d2fed210..e2aec542d67 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -69,7 +69,7 @@ ui::GLOzone *SurfaceFactoryQt::GetGLOzone(const gl::GLImplementationParts &imple return impl.second.get(); } - qFatal() << "GLOzone not found for" << gl::GetGLImplementationGLName(implementation); + qFatal("GLOzone not found for %s", gl::GetGLImplementationGLName(implementation)); return nullptr; } @@ -223,8 +223,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( eglFun->eglCreateImage(eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, attrs.data()); if (eglImage == EGL_NO_IMAGE_KHR) { - qFatal() << "Failed to import EGLImage:" - << ui::GetEGLErrorString(eglFun->eglGetError()); + qFatal("Failed to import EGLImage: %s", ui::GetEGLErrorString(eglFun->eglGetError())); } Q_ASSERT(numPlanes <= 3); @@ -232,8 +231,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( int strides[3]; int offsets[3]; if (!eglFun->eglExportDMABUFImageMESA(eglDisplay, eglImage, fds, strides, offsets)) { - qFatal() << "Failed to export EGLImage:" - << ui::GetEGLErrorString(eglFun->eglGetError()); + qFatal("Failed to export EGLImage: %s", ui::GetEGLErrorString(eglFun->eglGetError())); } bufferHandle.modifier = handle.modifier; diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp index 31a85a534c1..7bab41530dc 100644 --- a/src/core/profile_io_data_qt.cpp +++ b/src/core/profile_io_data_qt.cpp @@ -62,7 +62,7 @@ void ProfileIODataQt::shutdownOnUIThread() bool posted = content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, this); if (!posted) { - qWarning() << "Could not delete ProfileIODataQt on io thread !"; + qWarning("Could not delete ProfileIODataQt on io thread !"); delete this; } } diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index 5bb9599bc79..eaaa4f2536b 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -278,7 +278,8 @@ void ProfileQt::setupStoragePath() auto it = std::find(storagePaths.begin(), storagePaths.end(), thisStoragePath); if (it == storagePaths.end()) { if (storagePaths.size() >= (PATH_QT_END - PATH_QT_START)) { - qWarning() << "Number of profile paths exceeded " << PATH_QT_END - PATH_QT_START << ", storage may break"; + qWarning("Number of profile paths exceeded %ull, storage may break", + static_cast(PATH_QT_END - PATH_QT_START)); return; } diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index adbae106017..a34de4e501c 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1071,7 +1071,7 @@ void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldI if (!rfh) return exit(); if (!static_cast(rfh)->GetAssociatedLocalFrame()) { - qWarning() << "Local frame is gone, not running script"; + qWarning("Local frame is gone, not running script"); return exit(); } diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 5eea0c45622..bc84b68fee3 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -201,7 +201,7 @@ class GPUInfo if (it != vendorIdMap.end()) return it->second; - qWarning() << "Unknown Vendor ID:" << QStringLiteral("0x%1").arg(vendorId, 0, 16); + qWarning("Unknown Vendor ID: 0x%llx", vendorId); return Unknown; } @@ -913,7 +913,7 @@ WebEngineContext::WebEngineContext() #endif } else { parsedCommandLine->AppendSwitch(sandbox::policy::switches::kNoSandbox); - qInfo() << "Sandboxing disabled by user."; + qInfo("Sandboxing disabled by user."); } // Do not advertise a feature we have removed at compile time @@ -994,11 +994,10 @@ WebEngineContext::WebEngineContext() found++; } if (found != requiredDeviceExtensions.size()) { - qWarning().nospace() - << "Vulkan rendering may fail because " << deviceExtensionsVar - << " environment variable is already set but it doesn't contain" - << " some of the required Vulkan device extensions:\n" - << qPrintable(requiredDeviceExtensions.join('\n')); + qWarning("Vulkan rendering may fail because %s environment variable is already " + "set but it doesn't contain some of the required Vulkan device " + "extensions:\n%s", + deviceExtensionsVar, requiredDeviceExtensions.join('\n').constData()); } } else { qputenv(deviceExtensionsVar, requiredDeviceExtensions.join(';')); diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index f7ab89681eb..bb704926d33 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -152,8 +152,8 @@ QString subProcessPath() for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate)) { processPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine process path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine process path: %ls", + qUtf16Printable(candidate)); break; } } @@ -209,8 +209,8 @@ QString localesPath() for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate % QDir::separator() % translationPakFilename)) { potentialLocalesPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine locales path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine locales path: %ls", + qUtf16Printable(candidate)); break; } } @@ -276,8 +276,8 @@ QString dictionariesPath(bool showWarnings) for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate)) { potentialDictionariesPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine dictionaries path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine dictionaries path: %ls", + qUtf16Printable(candidate)); break; } } @@ -329,8 +329,8 @@ QString resourcesPath() for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate % QDir::separator() % resourcesPakFilename)) { potentialResourcesPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine resources path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine resources path: %ls", + qUtf16Printable(candidate)); break; } } From 317de2ae549b5efd150abe53dc7010e42d810ac4 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 5 Mar 2025 13:28:18 +0000 Subject: [PATCH 298/341] Doc: Instruct QDoc to ignore output file overwrite warnings We have two components (WebEngine Core, WebEngineDriver) that both have associated 3rd party attributions originating from Chromium. These attributions overlap each other, and cause multiple `Output file already exist` warnings when generating the documentation. Instruct QDoc to ignore these, in order to reduce noise during documentation build. Fixes: QTBUG-134416 Change-Id: I57842910fe4835ac5f536a757d3347fa7cee636a Reviewed-by: Paul Wicking (cherry picked from commit b0f0471d44fbe0e61e4901625f01a6626a3fe981) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 6435f29112c6c56ad6c6be5182c169b93296e2f4) --- src/core/doc/qtwebengine.qdocconf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf index ee875780165..d67c6c69fea 100644 --- a/src/core/doc/qtwebengine.qdocconf +++ b/src/core/doc/qtwebengine.qdocconf @@ -98,5 +98,9 @@ navigation.qmltypespage = "Qt WebEngine QML Types" # \QWE macro expands to 'Qt WebEngine' without auto-linking anywhere. macro.QWE = "Qt \\WebEngine" +# QTBUG-134416: Ignore overwrite warnings, attribution +# documentation generates many of these +spurious += "Output file already exists, overwriting .*" + # Enforce zero documentation warnings warninglimit = 2 From a3c48b2d3eb5e1fcc28141eb4221562107185251 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Wed, 19 Feb 2025 15:06:39 +0100 Subject: [PATCH 299/341] Docs: fix typo Change-Id: I0e973f599218a719aa8cff0ce65c4d35cefe4b3f Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit cf84eee54f218a01bc85d428501c7c7bba347b3e) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 7c7af8ecd0dc4ed144b915a59283046ccae55c99) --- .../webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc index a312da3ad1e..8523ed6896f 100644 --- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc +++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc @@ -180,7 +180,7 @@ We add a menu item to the context menu, so that users can right-click to have an inspector opened in a new window. We override QWebEngineView::contextMenuEvent and use - QWebEnginePage::createStandardContextMenu to create a default QMenu with a + QWebEngineView::createStandardContextMenu to create a default QMenu with a default list of QWebEnginePage::WebAction actions. The default name for QWebEnginePage::InspectElement action is From aebd217c579d4beb29b66de992c54f148372039c Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Tue, 23 Jul 2024 10:53:48 +0200 Subject: [PATCH 300/341] Fix webrtc manual test Fixed compilation error due to mismatched signatures Fixed crash when no selection was made Change-Id: If1e6a70a40c04e211f5f7c9be99ac45642a11d63 Reviewed-by: Anu Aliyas (cherry picked from commit 0e48cf6a96dbe78c33d6374d499126a7979ae5d8) Reviewed-by: Moss Heim --- tests/manual/widgets/webrtc/main.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/manual/widgets/webrtc/main.cpp b/tests/manual/widgets/webrtc/main.cpp index 7eecf0735a0..a6c2ff8d43c 100644 --- a/tests/manual/widgets/webrtc/main.cpp +++ b/tests/manual/widgets/webrtc/main.cpp @@ -28,7 +28,7 @@ class Page : public QWebEnginePage public: Page(QWebEngineProfile *profile, QObject *parent = nullptr); private slots: - void handlePermissionRequest(const QUrl &origin, Feature feature); + void handlePermissionRequest(QWebEnginePermission permission); void handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request); }; @@ -66,13 +66,21 @@ void Page::handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &reques windowsView->setModel(windowsModel); if (dialog.exec() == QDialog::Accepted) { - if (mediaPickerDialog.tabWidget->currentIndex() == 0) - request.selectWindow(windowsView->selectionModel()->selectedIndexes().first()); - else - request.selectScreen(screensView->selectionModel()->selectedIndexes().first()); - } else { - request.cancel(); + if (mediaPickerDialog.tabWidget->currentIndex() == 0) { + auto list = windowsView->selectionModel()->selectedIndexes(); + if (!list.empty()) { + request.selectWindow(list.first()); + return; + } + } else { + auto list = screensView->selectionModel()->selectedIndexes(); + if (!list.empty()) { + request.selectScreen(list.first()); + return; + } + } } + request.cancel(); } int main(int argc, char *argv[]) From 802c43c199a8cb75f43210d14f5777f3db332fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucie=20G=C3=A9rard?= Date: Tue, 11 Mar 2025 21:06:18 +0100 Subject: [PATCH 301/341] Update licensing of files with infrastructure type A QUIP 18[1] update sets git files, REUSE.toml and licenseRule.json as infrastructure type files. They are licensed with: LicenseRef-Qt-Commercial OR BSD-3-Clause [1]: https://contribute.qt-project.org/quips/18 Change-Id: I4ff3f1ce79565153d23a625172c2760dba8e4a8e Reviewed-by: Joerg Bornemann (cherry picked from commit 0546e3d722350c31d04f9a74446d02f79c928fbe) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 775f6976b5c6437d9189dd592945c23b535d0923) --- REUSE.toml | 12 +-- licenseRule.json | 242 +++++++++++++++++++++++++---------------------- 2 files changed, 133 insertions(+), 121 deletions(-) diff --git a/REUSE.toml b/REUSE.toml index 18dbbabe24b..faaa2093da1 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -73,18 +73,18 @@ SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GPL-3.0-only" [[annotations]] path = ["**.pro", "**.qrc", "**CMakeLists.txt", ".cmake.conf", "**.yaml", "**.cfg", "**BLACKLIST", "**.plist", "**.plist.in", "**BUILD**.in", "coin.nodes", - "coin/qt-installer-package-config.json", ".gitmodules"] + "coin/qt-installer-package-config.json", ".tag"] precedence = "closest" comment = "build system" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" [[annotations]] -path = [".tag", "**/.gitattributes", "**.gitignore"] +path = ["**/.gitattributes", "**.gitignore", ".gitmodules", "**.gitreview"] precedence = "closest" -comment = "version control system. Licensed as build system" +comment = "version control system. Infrastructure" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." -SPDX-License-Identifier = "BSD-3-Clause" +SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] path = ["examples/**", "tests/manual/examples/**", "**/doc/snippets/**"] @@ -102,10 +102,10 @@ SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-on [[annotations]] path = ["**.toml", "licenseRule.json"] -comment = "documentation" +comment = "infrastructure" precedence = "override" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." -SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" +SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] path = ["**/qt_attribution.json"] diff --git a/licenseRule.json b/licenseRule.json index 695e3a422fe..4ae4a4e8453 100644 --- a/licenseRule.json +++ b/licenseRule.json @@ -1,6 +1,6 @@ [ { - "comment" : ["file_pattern_ending: strings matched against the end of a file name.", + "comment": ["file_pattern_ending: strings matched against the end of a file name.", "location keys: regular expression matched against the beginning of", "the file path (relative to the git submodule root).", "spdx: list of SPDX-License-Expression's allowed in the matching files.", @@ -9,140 +9,152 @@ "unless they are examples", "Files with other endings can also be build system files" ], - "file_pattern_ending" : ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", + "file_pattern_ending": ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", - ".clang-format", ".plist", ".qrc", "BLACKLIST", ".gitignore", ".gitattributes", + ".clang-format", ".plist", ".qrc", "BLACKLIST", ".tag", ".cmake.conf", ".yaml", "coin/qt-installer-package-config.json", "BUILD.root.gn.in", "BUILD.toolchain.gn.in", "BUILD.msvc.toolchain.gn.in", - ".cfg", "coin.nodes", ".gitmodules"], - "location" : { - "" : { - "comment" : "Default", - "file type" : "build system", - "spdx" : ["BSD-3-Clause"] - }, - "(.*)(examples/|snippets/)" : { - "comment" : "Example takes precedence", - "file type" : "examples and snippets", - "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + "BUILD.clang-cl.toolchain.gn.in", ".cfg", "coin.nodes"], + "location": { + "": { + "comment": "Default", + "file type": "build system", + "spdx": ["BSD-3-Clause"] + }, + "(.*)(examples/|snippets/)": { + "comment": "Example takes precedence", + "file type": "examples and snippets", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] } } }, { - "comments" : ["Files with the following endings are Tool licensed,", + "comments": ["Files with the following endings are infrastructure licensed"], + "file_pattern_ending": [".gitattributes", ".gitignore", ".gitmodules", ".gitreview", + "clang-format", "licenseRule.json", "REUSE.toml"], + "location":{ + "": { + "comment": "Default", + "file type": "infrastructure", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + } + } + }, + { + "comments": ["Files with the following endings are Tool licensed,", "unless they are examples.", "Files with other endings can also be tool files."], - "file_pattern_ending" : [".sh", ".py", ".pl", ".bat", ".ps1"], - "location" :{ - "" : { - "comment" : "Default", - "file type" : "tools and utils", - "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] - }, - "(.*)(examples/|snippets/)" : { - "comment" : "Example takes precedence", - "file type" : "examples and snippets", - "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + "file_pattern_ending": [".sh", ".py", ".pl", ".bat", ".ps1"], + "location":{ + "": { + "comment": "Default", + "file type": "tools and utils", + "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] + }, + "(.*)(examples/|snippets/)": { + "comment": "Example takes precedence", + "file type": "examples and snippets", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] } } }, { - "comment" : "Files with the following endings are Documentation licensed.", - "file_pattern_ending" : [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", "README", "qt_attribution.json", - "REUSE.toml", "config_help.txt", "licenseRule.json"], - "location" :{ - "" : { - "comment" : "", - "file type" : "documentation", - "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + "comment": "Files with the following endings are Documentation licensed.", + "file_pattern_ending": [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", "README", "qt_attribution.json", + "config_help.txt"], + "location":{ + "": { + "comment": "", + "file type": "documentation", + "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] } } }, { - "comment" : ["All other files", + "comment": ["All other files", "The licensing is defined only by the file location in the Qt module repository.", "NO key for this case!", "This needs to be the last entry of the file."], - "location" : { - "" : { - "comment" : "Default", - "file type" : "module and plugin", - "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] - }, - "dist/" : { - "comment" : "Default", - "file type" : "documentation", - "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] - }, - "src/" : { - "comment" : "Default", - "file type" : "module and plugin", - "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] - }, - "tests/" : { - "comment" : "Default", - "file type" : "test", - "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"] - }, - "(.*)(examples/|snippets/)" : { - "comment" : "Default", - "file type" : "examples and snippets", - "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] - }, - "(.*|examples).*doc/images/" : { - "comment" : "Default", - "file type" : "documentation", - "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] - }, - "src/host/config\\.tests/" : { - "comment" : "Default", - "file type" : "build system", - "spdx" : ["BSD-3-Clause"] - }, - "src/core/clipboard_util_win.cpp" : { - "comment" : "Partially from Chromium", - "file type" : "module and plugin", - "spdx" : ["BSD-3-Clause"] - }, - "src/core/common/qt_messages.*" : { - "comment" : "Partially from Chromium", - "file type" : "module and plugin", - "spdx" : ["BSD-3-Clause"] - }, - "src/core/tools/qwebengine_convert_dict/main.cpp" : { - "comment" : "Partially from Chromium", - "file type" : "module and plugin", - "spdx" : ["BSD-3-Clause"] - }, - "tests/auto/widgets/qwebengine(view|script|page|history)/tst_qwebengine.*.cpp" : { - "comment" : "exception", - "file type" : "test", - "spdx" : ["LGPL-2.0-or-later"] - }, - "tests/auto/widgets/accessibility/tst_accessibility.cpp" : { - "comment" : "exception", - "file type" : "test", - "spdx" : ["LGPL-2.0-or-later"] - }, - "tests/auto/core/qwebengine(settings|frame)/tst_qwebengine.*.cpp" : { - "comment" : "exception", - "file type" : "test", - "spdx" : ["LGPL-2.0-or-later"] - }, - "examples/webenginewidgets/contentmanipulation/jquery.min.js" : { - "comment" : "", - "file type" : "3rd party", - "spdx" : ["MIT"] - }, - "src/core/ozone/(ozone_extra.gni|BUILD.gn)" : { - "comment" : "Chrominum", - "file type" : "3rd party", - "spdx" : ["BSD-3-Clause"] - }, - "CHROMIUM_VERSION" : { - "comment" : "Chrominum", - "file type" : "3rd party", - "spdx" : ["CC0-1.0"] + "location": { + "": { + "comment": "Default", + "file type": "module and plugin", + "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "dist/": { + "comment": "Default", + "file type": "documentation", + "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + }, + "src/": { + "comment": "Default", + "file type": "module and plugin", + "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "tests/": { + "comment": "Default", + "file type": "test", + "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only"] + }, + "(.*)(examples/|snippets/)": { + "comment": "Default", + "file type": "examples and snippets", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + }, + "(.*|examples).*doc/images/": { + "comment": "Default", + "file type": "documentation", + "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + }, + "src/host/config\\.tests/": { + "comment": "Default", + "file type": "build system", + "spdx": ["BSD-3-Clause"] + }, + "src/core/clipboard_util_win.cpp": { + "comment": "Partially from Chromium", + "file type": "module and plugin", + "spdx": ["BSD-3-Clause"] + }, + "src/core/common/qt_messages.*": { + "comment": "Partially from Chromium", + "file type": "module and plugin", + "spdx": ["BSD-3-Clause"] + }, + "src/core/tools/qwebengine_convert_dict/main.cpp": { + "comment": "Partially from Chromium", + "file type": "module and plugin", + "spdx": ["BSD-3-Clause"] + }, + "tests/auto/widgets/qwebengine(view|script|page|history)/tst_qwebengine.*.cpp": { + "comment": "exception", + "file type": "test", + "spdx": ["LGPL-2.0-or-later"] + }, + "tests/auto/widgets/accessibility/tst_accessibility.cpp": { + "comment": "exception", + "file type": "test", + "spdx": ["LGPL-2.0-or-later"] + }, + "tests/auto/core/qwebengine(settings|frame)/tst_qwebengine.*.cpp": { + "comment": "exception", + "file type": "test", + "spdx": ["LGPL-2.0-or-later"] + }, + "examples/webenginewidgets/contentmanipulation/jquery.min.js": { + "comment": "", + "file type": "3rd party", + "spdx": ["MIT"] + }, + "src/core/ozone/(ozone_extra.gni|BUILD.gn)": { + "comment": "Chrominum", + "file type": "3rd party", + "spdx": ["BSD-3-Clause"] + }, + "CHROMIUM_VERSION": { + "comment": "Chrominum", + "file type": "3rd party", + "spdx": ["CC0-1.0"] } } } From 6c2e507e6139c662d00a48cd1aca53452cf8b3ec Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Thu, 20 Mar 2025 10:26:58 +0100 Subject: [PATCH 302/341] Add missing TOOLKIT_QT define When compiling "api" part or "covert_dict" targets we never set TOOLKIT_QT, meaning BUILDFLAG(IS_QTWEBENGINE) is not set for headers included from "api" sources. This can lead do unexpected side effects. Change-Id: I149da31725df94a4911562213a73f84aeb110ea8 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit f88512537efd173eb8aaebe8522e173e40b5363d) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 575a8c4a58bb2b9b0ae9e36cf8877f14ef7b6d5f) --- src/core/api/CMakeLists.txt | 1 + src/core/tools/qwebengine_convert_dict/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt index 9ca610d3299..3d2a153a39e 100644 --- a/src/core/api/CMakeLists.txt +++ b/src/core/api/CMakeLists.txt @@ -45,6 +45,7 @@ qt_internal_add_module(WebEngineCore qwebenginewebauthuxrequest.cpp qwebenginewebauthuxrequest.h qwebenginewebauthuxrequest_p.h DEFINES BUILDING_CHROMIUM + TOOLKIT_QT INCLUDE_DIRECTORIES ../ ../../3rdparty/chromium diff --git a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt index fcc11bdcb8c..4d36ca004fb 100644 --- a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt +++ b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt @@ -7,6 +7,7 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING) TARGET_DESCRIPTION "QtWebEngine Dictionary Conversion Tool" INSTALL_DIR ${INSTALL_LIBEXECDIR} TOOLS_TARGET WebEngineCore + DEFINES TOOLKIT_QT SOURCES main.cpp INCLUDE_DIRECTORIES ../../../3rdparty/chromium/third_party/abseil-cpp From d69ed3f38b51817d60460bf869826cd3b05b5603 Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Mon, 17 Feb 2025 09:21:53 +0100 Subject: [PATCH 303/341] Add .gitreview file `git-review` is a command line tool for interacting with Gerrit. Some IDEs offer support for this tool, either natively or through plugins. The tool relies on a configuration file, .gitreview. Adding this configuration file to our repositories simplifies initial setup for contributors that use the tool directly or through their IDE of choice. The configuration file adds a remote called 'gerrit'. This is the default for the tool, and also the name set for codereview.qt-project.org by Qt's `init-repository` script. Thus, the configuration should work seamlessly alongside other repository helpers. Task-number: QTBUG-132604 Change-Id: Ib122816f9e73a19406b7227ec401f7cf0574b52e Reviewed-by: Samuel Gaist (cherry picked from commit 1d3793644519ca93a50cbc3173d11be39a4840f7) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 6e1cea1afd4ff72ca12538b7d5eafb59cd2b09c8) --- .gitreview | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitreview diff --git a/.gitreview b/.gitreview new file mode 100644 index 00000000000..a17ec896fca --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=codereview.qt-project.org +project=qt/qtwebengine +defaultbranch=dev From b54d2fa59023c6c6908c151b7b9ee2ea9e3b1699 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Mon, 24 Mar 2025 13:07:10 +0100 Subject: [PATCH 304/341] CMake: fix example target name conflict This conflicts with a target named server in qtbase benchmarks. Give the targets more unique names. Change-Id: I52d71e37c976ada5bf48813ecaf200923b07aef6 Reviewed-by: Anu Aliyas (cherry picked from commit 211dc916fd0a1f57171c634e0849c84cd1fb8a97) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 9682155a1360ad9af779c9d3a06b106667dc3ce3) --- .../clientcertificate/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/webenginewidgets/clientcertificate/CMakeLists.txt b/examples/webenginewidgets/clientcertificate/CMakeLists.txt index 97c9393ffce..ef1f9a6d415 100644 --- a/examples/webenginewidgets/clientcertificate/CMakeLists.txt +++ b/examples/webenginewidgets/clientcertificate/CMakeLists.txt @@ -14,20 +14,20 @@ set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/clientcertificat find_package(Qt6 REQUIRED COMPONENTS Core Gui WebEngineWidgets) -qt_add_executable(server +qt_add_executable(example_cert_server server.cpp ) -qt_add_executable(client +qt_add_executable(example_cert_client client.cpp ) -set_target_properties(client PROPERTIES +set_target_properties(example_cert_client PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE ) -qt_add_resources(client "client" +qt_add_resources(example_cert_client "client" PREFIX "/" FILES @@ -35,7 +35,7 @@ qt_add_resources(client "client" "resources/client.key" ) -qt_add_resources(server "server" +qt_add_resources(example_cert_server "server" PREFIX "/" FILES @@ -44,16 +44,16 @@ qt_add_resources(server "server" "resources/ca.pem" ) -target_link_libraries(client PUBLIC +target_link_libraries(example_cert_client PUBLIC Qt::WebEngineWidgets ) -target_link_libraries(server PUBLIC +target_link_libraries(example_cert_server PUBLIC Qt::Core Qt::Network ) -install(TARGETS server client +install(TARGETS example_cert_server example_cert_client RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" From e4251fb5b4f8fcae6ba4412b786bdb8b41da6d6c Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Sat, 22 Mar 2025 02:26:10 +0100 Subject: [PATCH 305/341] Fix RenderWidgetHostViewQtDelegateItem::viewGeometry We need to map the item not the scene Task-number: QTBUG-135040 Change-Id: I1fa2087f822d3fb7fcb431592c222c2e7ddb5e34 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit e2185036c9dab55b2984a5923163482dbb4b32e5) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 538326e6dd2ff571a10c5fd60273ee02bc5f0060) --- ...nder_widget_host_view_qt_delegate_item.cpp | 4 +- .../tst_qquickwebengineview.cpp | 69 +++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp index 85d0c9111e8..0c38f0f7a02 100644 --- a/src/core/render_widget_host_view_qt_delegate_item.cpp +++ b/src/core/render_widget_host_view_qt_delegate_item.cpp @@ -56,8 +56,8 @@ void RenderWidgetHostViewQtDelegateItem::initAsPopup(const QRect &screenRect) QRectF RenderWidgetHostViewQtDelegateItem::viewGeometry() const { // Transform the entire rect to find the correct top left corner. - const QPointF p1 = mapToGlobal(mapFromScene(QPointF(0, 0))); - const QPointF p2 = mapToGlobal(mapFromScene(QPointF(width(), height()))); + const QPointF p1 = mapToGlobal(mapFromItem(this, QPointF(0, 0))); + const QPointF p2 = mapToGlobal(mapFromItem(this, QPointF(width(), height()))); QRectF geometry = QRectF(p1, p2).normalized(); // But keep the size untransformed to behave like other QQuickItems. geometry.setSize(size()); diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 1fdccb7d4b3..1d85c495cbe 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -76,6 +76,7 @@ private Q_SLOTS: #if QT_CONFIG(accessibility) void focusChild_data(); void focusChild(); + void accessibilityRect(); #endif void htmlSelectPopup(); void savePage_data(); @@ -1254,6 +1255,74 @@ void tst_QQuickWebEngineView::focusChild() // -> -> QCOMPARE(traverseToWebDocumentAccessibleInterface(iface)->child(0)->child(0), iface->focusChild()); } + +void tst_QQuickWebEngineView::accessibilityRect() +{ + auto *engine = new QQmlEngine(this); + auto *component = new QQmlComponent(engine, this); + component->setData(QByteArrayLiteral("import QtQuick\n" + "import QtWebEngine\n" + "Window {\n" + " visible: true; width: 600; height: 400\n" + " Text { id: textId; text: \"text\"; width: 100; Accessible.focusable: true; Accessible.name: \"text\" }\n" + " WebEngineView { anchors.left: textId.right; anchors.top: textId.bottom; anchors.right: parent.right; anchors.bottom: parent.bottom }\n" + "}") + , QUrl()); + QObject *rootObject = component->create(); + QVERIFY(rootObject); + + QQuickWebEngineView *webView = rootObject->findChild(); + QVERIFY(webView); + + webView->loadHtml(""); + QVERIFY(waitForLoadSucceeded(webView)); + + QAccessibleInterface *rootObjectIface = QAccessible::queryAccessibleInterface(rootObject); + QVERIFY(rootObjectIface); + QCOMPARE(rootObjectIface->childCount(), 2); + + QAccessibleInterface *textIface = rootObjectIface->child(0); + QVERIFY(textIface); + QCOMPARE(textIface->role(), QAccessible::StaticText); + + QCOMPARE(textIface->rect().width(), 100); + QVERIFY(textIface->rect().height() > 0); + + // It takes a while for the webIface to get its width, unfortunately we can't have a + // QTRY_COMPARE since it seems in some platforms the iface gets recreated and we end up + // accessible the wrong pointer, so roll up our own try+compare + QAccessibleInterface *webIface = nullptr; + QElapsedTimer t; + t.start(); + bool isWebIfaceOfCorrectWidth = false; + while (!isWebIfaceOfCorrectWidth && t.elapsed() < 5000) { + QTest::qWait(100); + webIface = rootObjectIface->child(1)->child(0); + QVERIFY(webIface); + QCOMPARE(webIface->role(), QAccessible::WebDocument); + isWebIfaceOfCorrectWidth = webIface->rect().width() == 500; + } + + QVERIFY(isWebIfaceOfCorrectWidth); + QCOMPARE(webIface->rect().height(), 400 - textIface->rect().height()); + QCOMPARE(webIface->rect().x(), textIface->rect().x() + textIface->rect().width()); + QCOMPARE(webIface->rect().y(), textIface->rect().y() + textIface->rect().height()); + + // Set active focus on the input field. + webView->runJavaScript("document.getElementById('input1').focus();"); + QTRY_COMPARE(evaluateJavaScriptSync(webView, "document.activeElement.id").toString(), QStringLiteral("input1")); + + // Check that children of the web rect are inside it + QAccessibleInterface *inputIface = webIface->focusChild(); + QVERIFY(inputIface); + QTRY_COMPARE(inputIface->role(), QAccessible::EditableText); + QVERIFY(webIface->rect().contains(inputIface->rect())); + + delete rootObject; + delete component; + delete engine; +} + #endif // QT_CONFIG(accessibility) void tst_QQuickWebEngineView::htmlSelectPopup() From ace8bf7b92284a24c0d83fd3afac119fe20ae275 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Wed, 7 Aug 2024 16:14:07 +0200 Subject: [PATCH 306/341] Fix webrtc manual test compilation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QHttpServer no longer has a listen() convenience function, use a TcpServer instead. Change-Id: I53db234590d67eabd4e23b2a8397e931178f1155 Reviewed-by: Michael BrĂ¼ning (cherry picked from commit a782eb6fa6c5a80b10c4af64963f903214d19ed5) Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Moss Heim --- tests/manual/widgets/webrtc/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/manual/widgets/webrtc/main.cpp b/tests/manual/widgets/webrtc/main.cpp index a6c2ff8d43c..e788f3a2936 100644 --- a/tests/manual/widgets/webrtc/main.cpp +++ b/tests/manual/widgets/webrtc/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -87,8 +88,6 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - QHttpServer server; - QFile file(":index.html"); if (!file.open(QIODeviceBase::ReadOnly)) { @@ -102,11 +101,12 @@ int main(int argc, char *argv[]) return 0; } - server.route("/index.html", [data]() { - return data; - }); + QHttpServer httpServer; + httpServer.route("/index.html", [data]() { return data; }); - server.listen(QHostAddress::Any, 3000); + auto tcpServer = new QTcpServer(&httpServer); + tcpServer->listen(QHostAddress::Any, 3000); + httpServer.bind(tcpServer); QWebEngineView view; Page *page = new Page(QWebEngineProfile::defaultProfile(), &view); From aee2b8e8c49bf91b860d3204245ad6b78e3100dc Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Fri, 8 Mar 2024 14:52:54 +0100 Subject: [PATCH 307/341] [Backport] Make download API asynchronous Modify the already existing downloadRequest() API. Now the requests not necessarily have to be answered in a directly connected signal handler and the API users can postpone their user's decision. The only exceptions are automatically accepted save page requests. There is no better place to call their callback than directly after the signal emission. Adapt auto tests to the new lifecycle of download items. Modify the quicknanobrowser example to use a simple async method to wait for the user's decision. Keep simplebrowser to use its old synchronous method to illustrate that it's still possible. Correct documentation at some places. [ChangeLog] QWebEngineProfile::downloadRequested() is not limited to synchronous usage anymore. QWebEngineDownloadRequest can be accepted or rejected later without blocking the browsing session. Fixes: QTBUG-118584 Change-Id: I9828352a835cbaf48f0d1311179ab1d972a95668 Reviewed-by: Allan Sandfeld Jensen --- .../quicknanobrowser/BrowserWindow.qml | 26 ++- .../quicknanobrowser/DownloadView.qml | 1 + src/core/api/qwebenginedownloadrequest.cpp | 51 +++-- src/core/api/qwebenginedownloadrequest_p.h | 5 + src/core/api/qwebengineprofile.cpp | 24 +- src/core/download_manager_delegate_qt.cpp | 213 +++++++++--------- src/core/download_manager_delegate_qt.h | 9 + src/core/profile_adapter.cpp | 9 + src/core/profile_adapter.h | 3 + src/core/profile_adapter_client.h | 14 +- .../api/qquickwebengineprofile.cpp | 21 +- .../tst_qwebenginedownloadrequest.cpp | 87 ++++++- 12 files changed, 298 insertions(+), 165 deletions(-) diff --git a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml index 1c31ea94409..1b2816583c4 100644 --- a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml +++ b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml @@ -5,6 +5,7 @@ import QtCore import QtQml import QtQuick import QtQuick.Controls.Fusion +import QtQuick.Dialogs import QtQuick.Layouts import QtQuick.Window import QtWebEngine @@ -824,10 +825,29 @@ ApplicationWindow { visible: false } + MessageDialog { + id: downloadAcceptDialog + property var downloadRequest: downloadView.pendingDownloadRequest + title: "Download requested" + text: downloadRequest ? downloadRequest.suggestedFileName : "" + buttons: Dialog.No | Dialog.Yes + onAccepted: { + downloadView.visible = true; + downloadView.append(downloadRequest); + downloadRequest.accept(); + } + onRejected: { + downloadRequest.cancel(); + } + onButtonClicked: { + visible = false; + } + visible: false + } + function onDownloadRequested(download) { - downloadView.visible = true; - downloadView.append(download); - download.accept(); + downloadView.pendingDownloadRequest = download; + downloadAcceptDialog.visible = true; } FindBar { diff --git a/examples/webenginequick/quicknanobrowser/DownloadView.qml b/examples/webenginequick/quicknanobrowser/DownloadView.qml index 421b4f55cc9..b116ab86734 100644 --- a/examples/webenginequick/quicknanobrowser/DownloadView.qml +++ b/examples/webenginequick/quicknanobrowser/DownloadView.qml @@ -9,6 +9,7 @@ import QtQuick.Layouts Rectangle { id: downloadView color: "lightgray" + property var pendingDownloadRequest: null ListModel { id: downloadModel diff --git a/src/core/api/qwebenginedownloadrequest.cpp b/src/core/api/qwebenginedownloadrequest.cpp index 70f4b094197..7471d8205a1 100644 --- a/src/core/api/qwebenginedownloadrequest.cpp +++ b/src/core/api/qwebenginedownloadrequest.cpp @@ -9,6 +9,7 @@ #include "profile_adapter.h" #include "web_contents_adapter_client.h" +#include #include QT_BEGIN_NAMESPACE @@ -81,11 +82,9 @@ static inline QWebEngineDownloadRequest::DownloadInterruptReason toDownloadInter requests, which it does by emitting the \l{QWebEngineProfile::downloadRequested}{downloadRequested} signal together with a newly created QWebEngineDownloadRequest. The application can then - examine this item and decide whether to accept it or not. A signal handler - must explicitly call accept() on the item for \QWE to actually start - downloading and writing data to disk. If no signal handler calls accept(), - then the download request will be automatically rejected and nothing will be - written to disk. + examine this item and decide whether to accept it or not. When a decision is + made, the application must explicitly call accept() or cancel() on the item + for \QWE to actually start downloading or rejecting the request. \note Some properties, such as setting the path and file name where the file will be saved (see \l downloadDirectory() and \l downloadFileName()), can @@ -93,18 +92,10 @@ static inline QWebEngineDownloadRequest::DownloadInterruptReason toDownloadInter \section2 Object Life Cycle - All items are guaranteed to be valid during the emission of the - \l{QWebEngineProfile::downloadRequested}{downloadRequested} signal. If - accept() is \e not called by any signal handler, then the item will be - deleted \e immediately after signal emission. This means that the - application \b{must not} keep references to rejected download items. It also - means the application should not use a queued connection to this signal. - - If accept() \e is called by a signal handler, then the QWebEngineProfile - will take ownership of the item. However, it is safe for the application to - delete the item at any time, except during the handling of the - \l{QWebEngineProfile::downloadRequested}{downloadRequested} signal. The - QWebEngineProfile being a long-lived object, it is in fact recommended that + In each and every case, the QWebEngineProfile takes the ownership of the item. + However, it is safe for the application to delete the item at any time, except + during the handling of the \l{QWebEngineProfile::downloadRequested}{downloadRequested} + signal. The QWebEngineProfile being a long-lived object, it is in fact recommended that the application delete any items it is no longer interested in. \note Deleting an item will also automatically cancel a download since 5.12.2, @@ -119,6 +110,12 @@ static inline QWebEngineDownloadRequest::DownloadInterruptReason toDownloadInter into a special file format (\l savePageFormat). To check if a download is for a file or a web page, use \l isSavePageDownload. + Web page save requests are accepted automatically and started from + \l DownloadInProgress state by convenience reasons. The first directly connected + \l{QWebEngineProfile::downloadRequested}{downloadRequested} signal handler + can prevent this by calling cancel(), otherwise the save operation will start + writing data to the disk. + \sa QWebEngineProfile, QWebEngineProfile::downloadRequested, QWebEnginePage::download, QWebEnginePage::save */ @@ -137,7 +134,9 @@ void QWebEngineDownloadRequestPrivate::update(const ProfileAdapterClient::Downlo { Q_Q(QWebEngineDownloadRequest); - Q_ASSERT(downloadState != QWebEngineDownloadRequest::DownloadRequested); + // Don't change download state until users accept/cancel the request + if (!answered && downloadState == QWebEngineDownloadRequest::DownloadRequested) + return; if (toDownloadInterruptReason(info.downloadInterruptReason) != interruptReason) { interruptReason = toDownloadInterruptReason(info.downloadInterruptReason); @@ -178,6 +177,20 @@ void QWebEngineDownloadRequestPrivate::setFinished() Q_EMIT q_ptr->isFinishedChanged(); } +void QWebEngineDownloadRequestPrivate::answer() +{ + if (answered) + return; + + if (profileAdapter) { + QString path = QDir(downloadDirectory).filePath(downloadFileName); + bool accepted = downloadState != QWebEngineDownloadRequest::DownloadCancelled + && downloadState != QWebEngineDownloadRequest::DownloadRequested; + profileAdapter->acceptDownload(downloadId, accepted, useDownloadTargetCallback, path, savePageFormat); + answered = true; + } +} + /*! Accepts the current download request, which will start the download. @@ -197,6 +210,7 @@ void QWebEngineDownloadRequest::accept() d->downloadState = QWebEngineDownloadRequest::DownloadInProgress; Q_EMIT stateChanged(d->downloadState); + d->answer(); } /*! @@ -239,6 +253,7 @@ void QWebEngineDownloadRequest::cancel() Q_EMIT stateChanged(d->downloadState); d->setFinished(); } + d->answer(); } /*! diff --git a/src/core/api/qwebenginedownloadrequest_p.h b/src/core/api/qwebenginedownloadrequest_p.h index eef6c9bb52f..e829f94b1b3 100644 --- a/src/core/api/qwebenginedownloadrequest_p.h +++ b/src/core/api/qwebenginedownloadrequest_p.h @@ -36,6 +36,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineDownloadRequestPrivate void update(const QtWebEngineCore::ProfileAdapterClient::DownloadItemInfo &info); void setFinished(); + void answer(); bool downloadFinished = false; quint32 downloadId = -1; @@ -56,10 +57,14 @@ class Q_WEBENGINECORE_EXPORT QWebEngineDownloadRequestPrivate bool isCustomFileName = false; qint64 totalBytes = -1; qint64 receivedBytes = 0; + // The user initiated the download by saving the page bool isSavePageDownload = false; + // Which type of callback should be called when the request is answered + bool useDownloadTargetCallback = true; QWebEngineDownloadRequest *q_ptr; QPointer profileAdapter; QtWebEngineCore::WebContentsAdapterClient *adapterClient = nullptr; + bool answered = false; Q_DECLARE_PUBLIC(QWebEngineDownloadRequest) }; diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index b0824af3503..1c5807a9386 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -17,7 +17,7 @@ #include "visited_links_manager_qt.h" #include "web_engine_settings.h" -#include +#include #include QT_BEGIN_NAMESPACE @@ -220,6 +220,12 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) { Q_Q(QWebEngineProfile); + if (!q->receivers(SIGNAL(downloadRequested(QWebEngineDownloadRequest *)))) { + m_profileAdapter->acceptDownload(info.id, info.accepted, info.useDownloadTargetCallback, info.path, + info.savePageFormat); + return; + } + Q_ASSERT(!m_ongoingDownloads.contains(info.id)); QWebEngineDownloadRequestPrivate *itemPrivate = new QWebEngineDownloadRequestPrivate(m_profileAdapter); @@ -235,6 +241,7 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) itemPrivate->mimeType = info.mimeType; itemPrivate->savePageFormat = static_cast(info.savePageFormat); itemPrivate->isSavePageDownload = info.isSavePageDownload; + itemPrivate->useDownloadTargetCallback = info.useDownloadTargetCallback; if (info.page && info.page->clientType() == QtWebEngineCore::WebContentsAdapterClient::WidgetsClient) itemPrivate->adapterClient = info.page; else @@ -247,18 +254,9 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) Q_EMIT q->downloadRequested(download); - QWebEngineDownloadRequest::DownloadState state = download->state(); - - info.path = QDir(download->downloadDirectory()).filePath(download->downloadFileName()); - info.savePageFormat = static_cast( - download->savePageFormat()); - info.accepted = state != QWebEngineDownloadRequest::DownloadCancelled; - - if (state == QWebEngineDownloadRequest::DownloadRequested) { - // Delete unaccepted downloads. - info.accepted = false; - delete download; - } + // Callbacks of automatically accepted save operations have to be called here + if (info.isSavePageDownload && info.accepted) + itemPrivate->answer(); } void QWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index bbe487fc918..4f0fce199a9 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -74,6 +74,8 @@ void DownloadManagerDelegateQt::cancelDownload(download::DownloadTargetCallback bool DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) { + m_pendingDownloads.erase(downloadId); + m_pendingSaves.erase(downloadId); if (download::DownloadItem *download = findDownloadById(downloadId)) { download->Cancel(/* user_cancel */ true); return true; @@ -97,6 +99,8 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId) { if (download::DownloadItem *download = findDownloadById(downloadId)) download->Remove(); + m_pendingDownloads.erase(downloadId); + m_pendingSaves.erase(downloadId); } bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *item, @@ -187,68 +191,66 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * item->AddObserver(this); QList clients = m_profileAdapter->clients(); if (!clients.isEmpty()) { - ProfileAdapterClient::DownloadItemInfo info = { - item->GetId(), - toQt(item->GetURL()), - item->GetState(), - item->GetTotalBytes(), - item->GetReceivedBytes(), - std::move(mimeTypeString), - std::move(suggestedFilePath), - ProfileAdapterClient::UnknownSavePageFormat, - acceptedByDefault, - false /* paused */, - false /* done */, - isSavePageDownload, - item->GetLastReason(), - adapterClient, - std::move(suggestedFilename), - item->GetStartTime().ToTimeT() - }; + ProfileAdapterClient::DownloadItemInfo info = {}; + info.id = item->GetId(); + info.url = toQt(item->GetURL()); + info.state = item->GetState(); + info.totalBytes = item->GetTotalBytes(); + info.receivedBytes = item->GetReceivedBytes(); + info.mimeType = std::move(mimeTypeString); + info.path = std::move(suggestedFilePath); + info.savePageFormat = ProfileAdapterClient::UnknownSavePageFormat; + info.accepted = acceptedByDefault; + info.paused = false; + info.done = false; + info.isSavePageDownload = isSavePageDownload; + info.useDownloadTargetCallback = true; + info.downloadInterruptReason = item->GetLastReason(); + info.page = adapterClient; + info.suggestedFileName = std::move(suggestedFilename); + info.startTime = item->GetStartTime().ToTimeT(); + + m_pendingDownloads.emplace(m_currentId, std::move(*callback)); + clients[0]->downloadRequested(info); + } else + cancelDownload(std::move(*callback)); - for (ProfileAdapterClient *client : std::as_const(clients)) { - client->downloadRequested(info); - if (info.accepted) - break; - } + return true; +} - QFileInfo suggestedFile(info.path); - - if (info.accepted && !suggestedFile.absoluteDir().mkpath(suggestedFile.absolutePath())) { -#if defined(Q_OS_WIN) - // TODO: Remove this when https://bugreports.qt.io/browse/QTBUG-85997 is fixed. - QDir suggestedDir = QDir(suggestedFile.absolutePath()); - if (!suggestedDir.isRoot() || !suggestedDir.exists()) { -#endif - qWarning("Creating download path failed, download cancelled: %ls", - qUtf16Printable(suggestedFile.absolutePath())); - info.accepted = false; -#if defined(Q_OS_WIN) - } -#endif - } +void DownloadManagerDelegateQt::downloadTargetDetermined(quint32 downloadId, bool accepted, + const QString &path) +{ + if (!m_pendingDownloads.contains(downloadId)) + return; + auto callback = std::move(m_pendingDownloads.find(downloadId)->second); + m_pendingDownloads.erase(downloadId); - if (!info.accepted) { - cancelDownload(std::move(*callback)); - return true; - } + download::DownloadItem *item = findDownloadById(downloadId); + if (!accepted || !item) { + cancelDownload(std::move(callback)); + return; + } - base::FilePath filePathForCallback(toFilePathString(suggestedFile.absoluteFilePath())); - download::DownloadTargetInfo target_info; - target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE; - target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; - target_info.insecure_download_status = download::DownloadItem::VALIDATED; - target_info.mime_type = item->GetMimeType(); - target_info.intermediate_path = - filePathForCallback.AddExtension(toFilePathString("download")); - target_info.display_name = base::FilePath(); - target_info.target_path = filePathForCallback; - target_info.interrupt_reason = download::DOWNLOAD_INTERRUPT_REASON_NONE; - std::move(*callback).Run(std::move(target_info)); - } else - cancelDownload(std::move(*callback)); + QFileInfo suggestedFile(path); + if (!suggestedFile.absoluteDir().mkpath(suggestedFile.absolutePath())) { + qWarning() << "Creating download path failed, download cancelled:" << suggestedFile.absolutePath(); + cancelDownload(std::move(callback)); + return; + } + base::FilePath targetPath(toFilePathString(suggestedFile.absoluteFilePath())); - return true; + download::DownloadTargetInfo target_info; + target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE; + target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; + target_info.insecure_download_status = download::DownloadItem::VALIDATED; + target_info.mime_type = item->GetMimeType(); + target_info.intermediate_path = + targetPath.AddExtension(toFilePathString("download")); + target_info.display_name = base::FilePath(); + target_info.target_path = targetPath; + target_info.interrupt_reason = download::DOWNLOAD_INTERRUPT_REASON_NONE; + std::move(callback).Run(std::move(target_info)); } void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_context, @@ -303,38 +305,46 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content if (web_contents) adapterClient = static_cast(web_contents->GetDelegate())->adapterClient(); + ProfileAdapterClient::DownloadItemInfo info = {}; // Chromium doesn't increase download ID when saving page. - ProfileAdapterClient::DownloadItemInfo info = { - ++m_currentId, - toQt(web_contents->GetURL()), - download::DownloadItem::IN_PROGRESS, - -1, /* totalBytes */ - 0, /* receivedBytes */ - u"application/x-mimearchive"_s, - suggestedFilePath, - suggestedSaveFormat, - acceptedByDefault, - false, /* paused */ - false, /* done */ - true, /* isSavePageDownload */ - ProfileAdapterClient::NoReason, - adapterClient, - QFileInfo(suggestedFilePath).fileName(), - QDateTime::currentMSecsSinceEpoch() - }; - - for (ProfileAdapterClient *client : std::as_const(clients)) { - client->downloadRequested(info); - if (info.accepted) - break; + info.id = ++m_currentId; + info.url = toQt(web_contents->GetURL()); + info.state = download::DownloadItem::IN_PROGRESS; + info.totalBytes = -1; + info.receivedBytes = 0; + info.mimeType = u"application/x-mimearchive"_s; + info.path = suggestedFilePath; + info.savePageFormat = suggestedSaveFormat; + info.accepted = acceptedByDefault; + info.paused = false; + info.done = false; + info.isSavePageDownload = true; + info.useDownloadTargetCallback = false; + info.downloadInterruptReason = ProfileAdapterClient::NoReason; + info.page = adapterClient; + info.suggestedFileName = QFileInfo(suggestedFilePath).fileName(); + info.startTime = QDateTime::currentMSecsSinceEpoch(); + + m_pendingSaves.emplace(m_currentId, std::move(callback)); + clients[0]->downloadRequested(info); +} + +void DownloadManagerDelegateQt::savePathDetermined(quint32 downloadId, bool accepted, + const QString &path, int format) +{ + if (!accepted) { + m_pendingSaves.erase(downloadId); + return; } - if (!info.accepted) + if (!m_pendingSaves.contains(downloadId)) return; + auto callback = std::move(m_pendingSaves.find(downloadId)->second); + m_pendingSaves.erase(downloadId); content::SavePackagePathPickedParams params; - params.file_path = toFilePath(info.path); - params.save_type = static_cast(info.savePageFormat); + params.file_path = toFilePath(path); + params.save_type = static_cast(format); std::move(callback).Run(std::move(params), base::BindOnce(&DownloadManagerDelegateQt::savePackageDownloadCreated, m_weakPtrFactory.GetWeakPtr())); @@ -355,24 +365,25 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(download::DownloadItem *downlo if (webContents) adapterClient = static_cast(webContents->GetDelegate())->adapterClient(); - ProfileAdapterClient::DownloadItemInfo info = { - download->GetId(), - toQt(download->GetURL()), - download->GetState(), - download->GetTotalBytes(), - download->GetReceivedBytes(), - toQt(download->GetMimeType()), - QString(), - ProfileAdapterClient::UnknownSavePageFormat, - true /* accepted */, - download->IsPaused(), - download->IsDone(), - 0 /* downloadType (unused) */, - download->GetLastReason(), - adapterClient, - toQt(download->GetSuggestedFilename()), - download->GetStartTime().ToTimeT() - }; + ProfileAdapterClient::DownloadItemInfo info = {}; + // Chromium doesn't increase download ID when saving page. + info.id = download->GetId(); + info.url = toQt(download->GetURL()); + info.state = download->GetState(); + info.totalBytes = download->GetTotalBytes(); + info.receivedBytes = download->GetReceivedBytes(); + info.mimeType = toQt(download->GetMimeType()); + info.path = QString(); + info.savePageFormat = ProfileAdapterClient::UnknownSavePageFormat; + info.accepted = true; + info.paused = download->IsPaused(); + info.done = download->IsDone(); + info.isSavePageDownload = false; // unused + info.useDownloadTargetCallback = false; // unused + info.downloadInterruptReason = download->GetLastReason(); + info.page = adapterClient; + info.suggestedFileName = toQt(download->GetSuggestedFilename()); + info.startTime = download->GetStartTime().ToTimeT(); for (ProfileAdapterClient *client : std::as_const(clients)) { client->downloadUpdated(info); diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index e7dfad29dcf..3b7ccc1c4a1 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -7,7 +7,11 @@ #include "content/public/browser/download_manager_delegate.h" #include +#include #include +#include + +#include "profile_adapter_client.h" namespace base { class FilePath; @@ -51,6 +55,9 @@ class DownloadManagerDelegateQt void resumeDownload(quint32 downloadId); void removeDownload(quint32 downloadId); + void downloadTargetDetermined(quint32 downloadId, bool accepted, const QString &path); + void savePathDetermined(quint32 downloadId, bool accepted, const QString &path, int format); + // Inherited from content::DownloadItem::Observer void OnDownloadUpdated(download::DownloadItem *download) override; void OnDownloadDestroyed(download::DownloadItem *download) override; @@ -62,6 +69,8 @@ class DownloadManagerDelegateQt ProfileAdapter *m_profileAdapter; uint32_t m_currentId; + std::map m_pendingDownloads; + std::map m_pendingSaves; base::WeakPtrFactory m_weakPtrFactory; }; diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 9f8fc958680..fa84f53e76f 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -231,6 +231,15 @@ void ProfileAdapter::removeDownload(quint32 downloadId) downloadManagerDelegate()->removeDownload(downloadId); } +void ProfileAdapter::acceptDownload(quint32 downloadId, bool accepted, bool useDownloadTargetCallback, + const QString &path, int savePageFormat) +{ + if (useDownloadTargetCallback) + downloadManagerDelegate()->downloadTargetDetermined(downloadId, accepted, path); + else + downloadManagerDelegate()->savePathDetermined(downloadId, accepted, path, savePageFormat); +} + ProfileAdapter *ProfileAdapter::createDefaultProfileAdapter() { return WebEngineContext::current()->createDefaultProfileAdapter(); diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 06628632193..4301cd8a2e7 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -77,6 +77,9 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject void pauseDownload(quint32 downloadId); void resumeDownload(quint32 downloadId); void removeDownload(quint32 downloadId); + void acceptDownload(quint32 downloadId, bool accepted, + bool useDownloadTargetCallback, const QString &path, + int savePageFormat); ProfileQt *profile(); bool ensureDataPathExists(); diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h index 06ac0de8b37..aaeefb5440a 100644 --- a/src/core/profile_adapter_client.h +++ b/src/core/profile_adapter_client.h @@ -82,19 +82,19 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapterClient }; struct DownloadItemInfo { - const quint32 id; - const QUrl url; - const int state; - const qint64 totalBytes; - const qint64 receivedBytes; - const QString mimeType; - + quint32 id; + QUrl url; + int state; + qint64 totalBytes; + qint64 receivedBytes; + QString mimeType; QString path; int savePageFormat; bool accepted; bool paused; bool done; bool isSavePageDownload; + bool useDownloadTargetCallback; int downloadInterruptReason; WebContentsAdapterClient *page; QString suggestedFileName; diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index eb6a3199595..e5308b43f6a 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -246,6 +246,12 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) { Q_Q(QQuickWebEngineProfile); + if (!q->receivers(SIGNAL(downloadRequested(QQuickWebEngineDownloadRequest *)))) { + m_profileAdapter->acceptDownload(info.id, info.accepted, info.useDownloadTargetCallback, info.path, + info.savePageFormat); + return; + } + Q_ASSERT(!m_ongoingDownloads.contains(info.id)); QWebEngineDownloadRequestPrivate *itemPrivate = new QWebEngineDownloadRequestPrivate(m_profileAdapter); @@ -262,6 +268,7 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) itemPrivate->savePageFormat = static_cast( info.savePageFormat); itemPrivate->isSavePageDownload = info.isSavePageDownload; + itemPrivate->useDownloadTargetCallback = info.useDownloadTargetCallback; if (info.page && info.page->clientType() == QtWebEngineCore::WebContentsAdapterClient::QmlClient) itemPrivate->adapterClient = info.page; else @@ -275,17 +282,9 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) QQmlEngine::setObjectOwnership(download, QQmlEngine::JavaScriptOwnership); Q_EMIT q->downloadRequested(download); - QWebEngineDownloadRequest::DownloadState state = download->state(); - info.path = QDir(download->downloadDirectory()).filePath(download->downloadFileName()); - info.savePageFormat = itemPrivate->savePageFormat; - info.accepted = state != QWebEngineDownloadRequest::DownloadCancelled - && state != QWebEngineDownloadRequest::DownloadRequested; - - if (state == QWebEngineDownloadRequest::DownloadRequested) { - // Delete unaccepted downloads. - info.accepted = false; - delete download; - } + // Callbacks of automatically accepted save operations have to be called here + if (info.isSavePageDownload && info.accepted) + itemPrivate->answer(); } void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) diff --git a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp index 30c480f951f..c9f048976f3 100644 --- a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp +++ b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp @@ -76,10 +76,12 @@ private Q_SLOTS: void downloadPage_data(); void downloadPage(); void downloadViaSetUrl(); - void downloadFileNot1(); - void downloadFileNot2(); + void downloadAnswerLater_data(); + void downloadAnswerLater(); + void downloadFileCancel(); void downloadDeleted(); void downloadDeletedByProfile(); + void downloadRequestedWithoutHandler(); void downloadUniqueFilename_data(); void downloadUniqueFilename(); void downloadUniqueFilenameWithTimestamp(); @@ -717,6 +719,7 @@ void tst_QWebEngineDownloadRequest::downloadViaSetUrl() QList downloadUrls; ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadRequest *item) { downloadUrls.append(item->url()); + item->cancel(); }); // Set up the test scenario by trying to load some unrelated HTML. @@ -746,29 +749,88 @@ void tst_QWebEngineDownloadRequest::downloadViaSetUrl() } } -void tst_QWebEngineDownloadRequest::downloadFileNot1() +void tst_QWebEngineDownloadRequest::downloadRequestedWithoutHandler() +{ + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); + rr->setResponseBody(QByteArrayLiteral("Hello")); + rr->sendResponse(); + }); + + QTemporaryDir tmpDir; + QVERIFY(tmpDir.isValid()); + QString downloadPath = tmpDir.filePath("test.html"); + + QWebEngineProfile profile; + QWebEnginePage page(&profile); + + // Load some HTML + QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished); + page.load(m_server->url()); + QTRY_COMPARE(loadSpy.size(), 1); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + + // Save and verify + page.save(downloadPath, QWebEngineDownloadRequest::SingleHtmlSaveFormat); + QFile file(downloadPath); + QTRY_VERIFY(file.exists()); +} + +void tst_QWebEngineDownloadRequest::downloadAnswerLater_data() { - // Trigger file download via download() but don't accept(). + QTest::addColumn("answer"); + QTest::addColumn("accept"); + + QTest::newRow("accept") << true << true; + QTest::newRow("cancel") << true << false; + QTest::newRow("ignore") << false << true; +} + +void tst_QWebEngineDownloadRequest::downloadAnswerLater() +{ + QFETCH(bool, answer); + QFETCH(bool, accept); ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { - rr->sendResponse(404); + rr->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment")); + rr->setResponseBody(QByteArrayLiteral("a")); + rr->sendResponse(); }); - QPointer downloadItem; + QTemporaryDir tmpDir; + QVERIFY(tmpDir.isValid()); + m_profile->setDownloadPath(tmpDir.path()); + + QPointer downloadRequest; int downloadCount = 0; - ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadRequest *item) { - QVERIFY(item); - QCOMPARE(item->state(), QWebEngineDownloadRequest::DownloadRequested); - downloadItem = item; + ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadRequest *request) { + QVERIFY(request); + QCOMPARE(request->state(), QWebEngineDownloadRequest::DownloadRequested); + downloadRequest = request; downloadCount++; }); m_page->download(m_server->url(https://github.com/QByteArrayLiteral(%22/file"))); QTRY_COMPARE(downloadCount, 1); - QVERIFY(!downloadItem); + QVERIFY(downloadRequest); + + if (answer) { + if (accept) { + downloadRequest->accept(); + QCOMPARE(downloadRequest->state(), QWebEngineDownloadRequest::DownloadInProgress); + QTRY_COMPARE(m_finishedDownloads.size(), 1); + QCOMPARE(downloadRequest->state(), QWebEngineDownloadRequest::DownloadCompleted); + } else { + downloadRequest->cancel(); + QCOMPARE(downloadRequest->state(), QWebEngineDownloadRequest::DownloadCancelled); + } + } + + QVERIFY(downloadRequest); + delete downloadRequest; } -void tst_QWebEngineDownloadRequest::downloadFileNot2() +void tst_QWebEngineDownloadRequest::downloadFileCancel() { // Trigger file download via download() but call cancel() instead of accept(). @@ -1306,6 +1368,7 @@ void tst_QWebEngineDownloadRequest::downloadDataUrls() QCOMPARE(item->state(), QWebEngineDownloadRequest::DownloadRequested); QCOMPARE(item->downloadFileName(), expectedFileName); downloadRequestCount++; + item->cancel(); }); QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); From 7c8f507840ba9615bd880f0da6ae356bbd5333b4 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Thu, 26 Sep 2024 15:03:42 +0200 Subject: [PATCH 308/341] tests: disable print/pdf tests when feature is off Change-Id: I20203b0e4b40e8829d77d1b6ae700157319ac6bb Reviewed-by: Michal Klocek (cherry picked from commit 70ca58326b4727c7080ab141ef276d2c88274432) Reviewed-by: Tim Jenssen --- tests/auto/core/qwebengineframe/CMakeLists.txt | 1 + tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/tests/auto/core/qwebengineframe/CMakeLists.txt b/tests/auto/core/qwebengineframe/CMakeLists.txt index 7d73e5a4aac..0f4d24289ed 100644 --- a/tests/auto/core/qwebengineframe/CMakeLists.txt +++ b/tests/auto/core/qwebengineframe/CMakeLists.txt @@ -8,6 +8,7 @@ qt_internal_add_test(tst_qwebengineframe tst_qwebengineframe.cpp LIBRARIES Qt::WebEngineCore + Qt::WebEngineCorePrivate Qt::WebEngineWidgets Test::Util ) diff --git a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp index 8bbefd5f58a..0e036ac7449 100644 --- a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp +++ b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp @@ -22,6 +22,7 @@ #include #include +#include class tst_QWebEngineFrame : public QObject { @@ -39,10 +40,12 @@ private Q_SLOTS: void size(); void isMainFrame(); void runJavaScript(); +#if QT_CONFIG(webengine_printing_and_pdf) void printRequestedByFrame(); void printToPdfFile(); void printToPdfFileFailures(); void printToPdfFunction(); +#endif private: }; @@ -207,6 +210,7 @@ void tst_QWebEngineFrame::runJavaScript() QCOMPARE(result, QString("test-subframe0")); } +#if QT_CONFIG(webengine_printing_and_pdf) void tst_QWebEngineFrame::printRequestedByFrame() { QWebEnginePage page; @@ -340,6 +344,7 @@ void tst_QWebEngineFrame::printToPdfFunction() QVERIFY(invalidSpy.wasCalled()); QCOMPARE(invalidPdfData.size(), 0); } +#endif QTEST_MAIN(tst_QWebEngineFrame) From 132a0273c57d2e341adbf13a464ad4828cc909f7 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 24 Mar 2025 16:07:51 +0100 Subject: [PATCH 309/341] multipage example: correct the qrc file to support build with qmake Change-Id: Ib3ff4394009364c673ef45e4244b65ed38e41379 Reviewed-by: Shawn Rutledge (cherry picked from commit ef03fa46d3bcdb4bc188fcd0038610e0a036d340) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 52b3d114ddcdb4f10cd83562ad46a9ed7a6f8ac9) --- examples/pdf/multipage/viewer.qrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc index e786ae4ce6c..b8ec1c8c68e 100644 --- a/examples/pdf/multipage/viewer.qrc +++ b/examples/pdf/multipage/viewer.qrc @@ -1,5 +1,5 @@ - + viewer.qml resources/document-open.svg resources/edit-clear.svg From 9618fe173ee3b5a9fe538dd24f03efa17f1c15e5 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Fri, 7 Feb 2025 14:34:36 +0100 Subject: [PATCH 310/341] Fix QWebEngineDownloadRequest::pause() Calling pause() (or any method which causes state update) in a directly connected signal handler of a download request causes an assertion fail in DownloadItemImpl::UpdateObservers() because it is protected from nested updates. Use QTimer::singleShot() to detach download requests and updates from the direct code path. Add auto test to check if pausing and resuming a download work. Change-Id: Ia8c977a626fd0d39ca51df42984381a75cca2101 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 1ffe3392eae1e70f76d621c8a4ee1b20feb004f2) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 2727607f8ff974b7c69453eed0d6356f8f4cd535) --- src/core/api/qwebenginedownloadrequest.cpp | 18 +++---- src/core/api/qwebengineprofile.cpp | 2 +- src/core/api/qwebengineprofile_p.h | 2 +- src/core/download_manager_delegate_qt.cpp | 12 +++-- src/core/profile_adapter_client.h | 2 +- .../api/qquickwebengineprofile.cpp | 2 +- .../api/qquickwebengineprofile_p.h | 2 +- .../tst_qwebenginedownloadrequest.cpp | 50 +++++++++++++++++++ 8 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/core/api/qwebenginedownloadrequest.cpp b/src/core/api/qwebenginedownloadrequest.cpp index 7471d8205a1..f67454134bd 100644 --- a/src/core/api/qwebenginedownloadrequest.cpp +++ b/src/core/api/qwebenginedownloadrequest.cpp @@ -146,17 +146,13 @@ void QWebEngineDownloadRequestPrivate::update(const ProfileAdapterClient::Downlo downloadState = toDownloadState(info.state); Q_EMIT q->stateChanged(downloadState); } - - if (info.receivedBytes != receivedBytes || info.totalBytes != totalBytes) { - - if (info.receivedBytes != receivedBytes) { - receivedBytes = info.receivedBytes; - Q_EMIT q->receivedBytesChanged(); - } - if (info.totalBytes != totalBytes) { - totalBytes = info.totalBytes; - Q_EMIT q->totalBytesChanged(); - } + if (info.receivedBytes != receivedBytes) { + receivedBytes = info.receivedBytes; + Q_EMIT q->receivedBytesChanged(); + } + if (info.totalBytes != totalBytes) { + totalBytes = info.totalBytes; + Q_EMIT q->totalBytesChanged(); } if (info.done) diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index 1c5807a9386..45b5a349d26 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -216,7 +216,7 @@ void QWebEngineProfilePrivate::cleanDownloads() m_ongoingDownloads.clear(); } -void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) +void QWebEngineProfilePrivate::downloadRequested(const DownloadItemInfo &info) { Q_Q(QWebEngineProfile); diff --git a/src/core/api/qwebengineprofile_p.h b/src/core/api/qwebengineprofile_p.h index 0ccc2703756..d4b3513cd5d 100644 --- a/src/core/api/qwebengineprofile_p.h +++ b/src/core/api/qwebengineprofile_p.h @@ -51,7 +51,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineProfilePrivate : public QtWebEngineCore:: void cleanDownloads(); - void downloadRequested(DownloadItemInfo &info) override; + void downloadRequested(const DownloadItemInfo &info) override; void downloadUpdated(const DownloadItemInfo &info) override; void showNotification(QSharedPointer &) override; diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 4f0fce199a9..0d4983fb6b8 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "profile_adapter_client.h" #include "profile_adapter.h" @@ -211,7 +212,8 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * info.startTime = item->GetStartTime().ToTimeT(); m_pendingDownloads.emplace(m_currentId, std::move(*callback)); - clients[0]->downloadRequested(info); + QTimer::singleShot(0, m_profileAdapter, + [client = clients[0], info]() { client->downloadRequested(info); }); } else cancelDownload(std::move(*callback)); @@ -326,7 +328,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content info.startTime = QDateTime::currentMSecsSinceEpoch(); m_pendingSaves.emplace(m_currentId, std::move(callback)); - clients[0]->downloadRequested(info); + QTimer::singleShot(0, m_profileAdapter, + [client = clients[0], info]() { client->downloadRequested(info); }); } void DownloadManagerDelegateQt::savePathDetermined(quint32 downloadId, bool accepted, @@ -385,9 +388,8 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(download::DownloadItem *downlo info.suggestedFileName = toQt(download->GetSuggestedFilename()); info.startTime = download->GetStartTime().ToTimeT(); - for (ProfileAdapterClient *client : std::as_const(clients)) { - client->downloadUpdated(info); - } + QTimer::singleShot(0, m_profileAdapter, + [client = clients[0], info]() { client->downloadUpdated(info); }); } } diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h index aaeefb5440a..cb83e82799b 100644 --- a/src/core/profile_adapter_client.h +++ b/src/core/profile_adapter_client.h @@ -103,7 +103,7 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapterClient virtual ~ProfileAdapterClient() { } - virtual void downloadRequested(DownloadItemInfo &info) = 0; + virtual void downloadRequested(const DownloadItemInfo &info) = 0; virtual void downloadUpdated(const DownloadItemInfo &info) = 0; virtual void showNotification(QSharedPointer &) { } diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index e5308b43f6a..47f8a1e95a4 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -242,7 +242,7 @@ void QQuickWebEngineProfilePrivate::cleanDownloads() m_ongoingDownloads.clear(); } -void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) +void QQuickWebEngineProfilePrivate::downloadRequested(const DownloadItemInfo &info) { Q_Q(QQuickWebEngineProfile); diff --git a/src/webenginequick/api/qquickwebengineprofile_p.h b/src/webenginequick/api/qquickwebengineprofile_p.h index 477936f98c4..fde24763665 100644 --- a/src/webenginequick/api/qquickwebengineprofile_p.h +++ b/src/webenginequick/api/qquickwebengineprofile_p.h @@ -50,7 +50,7 @@ class QQuickWebEngineProfilePrivate : public QtWebEngineCore::ProfileAdapterClie void cleanDownloads(); - void downloadRequested(DownloadItemInfo &info) override; + void downloadRequested(const DownloadItemInfo &info) override; void downloadUpdated(const DownloadItemInfo &info) override; void showNotification(QSharedPointer &controller) override; diff --git a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp index c9f048976f3..b01d7b8c933 100644 --- a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp +++ b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp @@ -92,6 +92,7 @@ private Q_SLOTS: void downloadToDirectoryWithFileName(); void downloadDataUrls_data(); void downloadDataUrls(); + void pauseDownload(); private: void saveLink(QPoint linkPos); @@ -1383,5 +1384,54 @@ void tst_QWebEngineDownloadRequest::downloadDataUrls() QTRY_COMPARE(downloadRequestCount, 1); } +void tst_QWebEngineDownloadRequest::pauseDownload() +{ + const int fileSize = 1024 * 1024 * 512; + + // Set up HTTP server + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + if (rr->requestMethod() == "GET" && rr->requestPath() == "/") { + rr->setResponseHeader(QByteArrayLiteral("content-type"), + QByteArrayLiteral("application/octet-stream")); + static const QByteArray bigfile(fileSize, '0'); + rr->setResponseBody(bigfile); + rr->sendResponse(); + } + }); + + // Set up profile and download handler + QTemporaryDir tmpDir; + QVERIFY(tmpDir.isValid()); + m_profile->setDownloadPath(tmpDir.path()); + + bool firstBytesReceived = true; + int pausedCount = 0; + ScopedConnection sc2 = connect( + m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadRequest *item) { + QCOMPARE(item->state(), QWebEngineDownloadRequest::DownloadRequested); + connect(item, &QWebEngineDownloadRequest::receivedBytesChanged, [item, &firstBytesReceived] { + if (firstBytesReceived) { + firstBytesReceived = false; + item->pause(); + } + }); + connect(item, &QWebEngineDownloadRequest::isPausedChanged, [item, &pausedCount]() { + if (item->isPaused()) { + pausedCount++; + item->resume(); + } + }); + item->accept(); + }); + + QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + m_view->load(m_server->url()); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(pausedCount, 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(m_finishedDownloads.size(), 1, 10000); + QTRY_COMPARE(m_finishedDownloads.values()[0]->isPaused(), false); + QTRY_COMPARE(m_finishedDownloads.values()[0]->receivedBytes(), fileSize); +} + QTEST_MAIN(tst_QWebEngineDownloadRequest) #include "tst_qwebenginedownloadrequest.moc" From 3e19092ef719a5a25c350af0bf801eb00cb1bf1c Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 31 Mar 2025 15:39:26 +0000 Subject: [PATCH 311/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Ie2b2b1474d11adc75846b3ccd624af45c5082b5e Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 3245aafc1ed..680ebaf7a63 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 7b4837d3e34a206ccbd3b921e65f1401b09066ee + ref: 5a5b4e295b433c7cf4b9f391eb1bc1b9623d83b0 required: true ../qtpositioning: - ref: 83cc61df4afb3b81da03c9ec6d3536b32d60b07d + ref: 2f486d06d23195263922f702cfdf4354eb5c5365 required: false ../qttools: - ref: feda5851ddced220d26ce80624fca527dde0a0ea + ref: f8b263a8309e0d1db742cec9df7eb39aae382ecb required: false ../qtwebchannel: - ref: ca7d35059a0effe4fbdb57a1b5e604f3d815b12a + ref: 6d8d2689731e9337c7362355bc166e7ec7ee8361 required: false From 331461fb2c0a946318f043143512555ff383b463 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 28 Mar 2025 13:22:32 +0100 Subject: [PATCH 312/341] Fix flaky tst_qwebengineview::inputContextQueryInput TestInputContext relies on focus object. Wait for the focus object to be set before trying to record input. Fixes: QTBUG-128440 Change-Id: Idc4a985d0f7305d13a4cb18f69da542c5e0469bd Reviewed-by: Michal Klocek (cherry picked from commit eb9bde4be0ecfeaee58415d52d63f64b4fbfe5fa) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 55fbfea91ade85235ef1f3cc77c819e4dc219930) --- tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 0d9b078c064..a6383c63023 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -2069,6 +2069,7 @@ void tst_QWebEngineView::inputContextQueryInput() ""); QTRY_COMPARE(loadFinishedSpy.size(), 1); QVERIFY(QTest::qWaitForWindowExposed(&view)); + QTRY_VERIFY(qApp->focusObject()); QCOMPARE(testContext.infos.size(), 0); // Set focus on an input field. From 74930dda2ce4fff4bcd5914dde3d6f36412bccc2 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Wed, 2 Apr 2025 10:10:50 +0000 Subject: [PATCH 313/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Iaa056e2de57cc3a9e5fb0155e7f52814c906065d Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 680ebaf7a63..b615ef44ead 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 5a5b4e295b433c7cf4b9f391eb1bc1b9623d83b0 + ref: 3103d51986b8b982267a768b7f29c249e942c81a required: true ../qtpositioning: - ref: 2f486d06d23195263922f702cfdf4354eb5c5365 + ref: e062e3457e70fadee0e37ee4989b6f2fa693343f required: false ../qttools: - ref: f8b263a8309e0d1db742cec9df7eb39aae382ecb + ref: 45cb129d38b8025c7832320fa8ec3b54a286a07b required: false ../qtwebchannel: - ref: 6d8d2689731e9337c7362355bc166e7ec7ee8361 + ref: e6969f5c5585463f75066cd8ac20203767bb7d48 required: false From df165e564b60822f2d66080e68e983455f9dc6cc Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 3 Apr 2025 09:24:23 +0000 Subject: [PATCH 314/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I3df296af90647b686e8be494f185b938424586e4 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index b615ef44ead..2c0ecb48769 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 3103d51986b8b982267a768b7f29c249e942c81a + ref: 253bed4ab8cd6f68d677c1dc8b459bb14cd37833 required: true ../qtpositioning: - ref: e062e3457e70fadee0e37ee4989b6f2fa693343f + ref: 2b92855c184f342d99edddb91e53e887bf2b049e required: false ../qttools: - ref: 45cb129d38b8025c7832320fa8ec3b54a286a07b + ref: e2637b0c459f801d06df79fb68329cf0a76f0d10 required: false ../qtwebchannel: - ref: e6969f5c5585463f75066cd8ac20203767bb7d48 + ref: 57f6b62b83163335733e664de00877d370a09929 required: false From df01b4bcdfa1a5f15bfcbb60353f461e8ee4e492 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Thu, 6 Feb 2025 16:24:03 +0100 Subject: [PATCH 315/341] Cleanup permissionbrowser example Remove an unused member, dynamically populate the policy combo box so its items and data stay synced, fix a documentation typo, and simplify a few expressions. Change-Id: I37997fbbeca51ed4c71c83a86d989917ce92b3df Reviewed-by: Anu Aliyas (cherry picked from commit a0da756ef2a3281ef32a063e9a5397aa29268ae6) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 927d80e518e1350f124696433c6b86461234a10b) --- .../doc/src/permissionbrowser.qdoc | 2 +- .../permissionbrowser/mainwindow.cpp | 47 +++++++------------ .../permissionbrowser/mainwindow.h | 6 +-- .../permissionbrowser/mainwindow.ui | 15 ------ 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc index 995d0046afe..8a394e5c8e4 100644 --- a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc +++ b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc @@ -193,7 +193,7 @@ \list \li \l QWebEngineProfile::StoreOnDisk is the default, and it ensures that any permissions that have been granted in the current application run will be - loaded back up at next startup. A permission onlycneeds to be granted once, and + loaded back up at next startup. A permission only needs to be granted once, and subsequent uses of the API that triggered the request will automatically be granted, until the application calls QWebEnginePermission::reset(). \li \l QWebEngineProfile::StoreInMemory Has the same behavior as above, diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp index 8fd811e8383..1cc9b74efd6 100644 --- a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp @@ -9,30 +9,23 @@ #include PermissionDialog::PermissionDialog(const QWebEngineProfile *profile, QWidget *parent) - : QDialog(parent) - , m_profile(profile) - , m_permission(nullptr) + : QDialog(parent), m_profile(profile) { setupUi(this); auto metaEnum = QMetaEnum::fromType(); - Q_ASSERT(metaEnum.value((quint8)QWebEnginePermission::PermissionType::Unsupported) == 0); - for (int i = 1; i < metaEnum.keyCount(); ++i) { - QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i)); + for (int i = 0; i < metaEnum.keyCount(); ++i) { + auto permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i)); if (QWebEnginePermission::isPersistent(permissionType)) - m_permissionTypeComboBox->addItem(metaEnum.valueToKey((quint8)permissionType), QVariant::fromValue(permissionType)); + m_permissionTypeComboBox->addItem(metaEnum.key(i), QVariant::fromValue(permissionType)); } } -PermissionDialog::~PermissionDialog() +QWebEnginePermission PermissionDialog::permission() const { - delete m_permission; -} - -QWebEnginePermission PermissionDialog::permission() -{ - return m_profile->queryPermission(QUrl(m_originLineEdit->text()), - QWebEnginePermission::PermissionType(m_permissionTypeComboBox->itemData(m_permissionTypeComboBox->currentIndex()).toInt())); + return m_profile->queryPermission( + QUrl(m_originLineEdit->text()), + m_permissionTypeComboBox->currentData().value()); } PermissionWidget::PermissionWidget(const QWebEnginePermission &permission, QWidget *parent) @@ -92,6 +85,13 @@ MainWindow::MainWindow(const QUrl &url) , m_pendingWidget(nullptr) { setupUi(this); + + auto metaEnum = QMetaEnum::fromType(); + for (int i = 0; i < metaEnum.keyCount(); ++i) { + auto policy = QWebEngineProfile::PersistentPermissionsPolicy(metaEnum.value(i)); + m_policyComboBox->addItem(metaEnum.key(i), QVariant::fromValue(policy)); + } + m_urlLineEdit->setText(url.toString()); m_layout->addItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding)); @@ -204,21 +204,10 @@ void MainWindow::handleForwardClicked() m_webview->triggerPageAction(QWebEnginePage::Forward); } -void MainWindow::handlePolicyComboBoxIndexChanged(int index) +void MainWindow::handlePolicyComboBoxIndexChanged(int) { - QWebEngineProfile::PersistentPermissionsPolicy policy; - switch (index) { - case 0: - policy = QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime; - break; - case 1: - policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory; - break; - case 2: - policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk; - break; - } - + auto policy = + m_policyComboBox->currentData().value(); if (policy == m_profile->persistentPermissionsPolicy()) return; diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.h b/examples/webenginewidgets/permissionbrowser/mainwindow.h index 8f7a0945035..ce239be8250 100644 --- a/examples/webenginewidgets/permissionbrowser/mainwindow.h +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.h @@ -20,12 +20,10 @@ class PermissionDialog : public QDialog, public Ui_PermissionDialog Q_OBJECT public: PermissionDialog(const QWebEngineProfile *profile, QWidget *parent = nullptr); - ~PermissionDialog(); - QWebEnginePermission permission(); + QWebEnginePermission permission() const; private: const QWebEngineProfile *m_profile; - QWebEnginePermission *m_permission; }; class PermissionWidget : public QWidget, public Ui_PermissionWidget @@ -60,7 +58,7 @@ private slots: void handleRefreshClicked(); void handleBackClicked(); void handleForwardClicked(); - void handlePolicyComboBoxIndexChanged(int index); + void handlePolicyComboBoxIndexChanged(int); private: bool containsPermission(const QWebEnginePermission &permission); diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.ui b/examples/webenginewidgets/permissionbrowser/mainwindow.ui index 4496b8c0782..2cef35130ab 100644 --- a/examples/webenginewidgets/permissionbrowser/mainwindow.ui +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.ui @@ -215,21 +215,6 @@ QComboBox::AdjustToContents - - - Persist on disk - - - - - Persist in memory - - - - - Do not persist - - From 15d1563cd11a76c7401ffcad2bae90eb56e5fbe2 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 3 Apr 2025 14:47:02 +0200 Subject: [PATCH 316/341] CMake: Avoid CMP0174 warning due to empty NINJA_DATA_STAMP Starting with CMake 3.31, the following warning is shown if the data stamp option is passed an empty string: CMake Warning (dev) at cmake/Functions.cmake:332 (cmake_parse_arguments): The NINJA_DATA_STAMP keyword was followed by an empty string or no value at all. Policy CMP0174 is not set, so cmake_parse_arguments() will unset the arg_NINJA_DATA_STAMP variable rather than setting it to an empty string. Call Stack (most recent call first): src/core/CMakeLists.txt:615 (add_gn_build_artifacts_to_target) Only pass the option if it has a value. Change-Id: I19a38b2eb05ab902e4c176f36b2410f62c403d32 Reviewed-by: Michal Klocek (cherry picked from commit 0c589dc6f46b27478066f18326a08077e7b3a35b) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 669950582129dcefa22425f99a6d4e1f4d4e58ee) --- cmake/Functions.cmake | 6 +++++- src/core/CMakeLists.txt | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 8d5a977771d..02276e46b91 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -1208,12 +1208,16 @@ function(add_gn_build_artifacts_to_target) foreach(arch ${archs}) set(target ${arg_NINJA_TARGET}_${config}_${arch}) set(stamps ${arg_NINJA_STAMP} ${arg_NINJA_DATA_STAMP}) + set(data_stamp_option "") + if(arg_NINJA_DATA_STAMP) + set(data_stamp_option NINJA_DATA_STAMP ${arg_NINJA_DATA_STAMP}) + endif() add_ninja_target( TARGET ${target} NINJA_TARGET ${arg_NINJA_TARGET} CMAKE_TARGET ${arg_CMAKE_TARGET} NINJA_STAMP ${arg_NINJA_STAMP} - NINJA_DATA_STAMP ${arg_NINJA_DATA_STAMP} + ${data_stamp_option} CONFIG ${config} ARCH ${arch} BUILDDIR ${arg_BUILDDIR} diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8059d1dcf90..487d0a004e2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -589,8 +589,9 @@ target_include_directories(WebEngineCore PRIVATE ) set(stamps QtWebEngineCore.stamp) +set(dataStampOption "") if(QT_FEATURE_webengine_v8_context_snapshot) - set(dataStamp obj/tools/v8_context_snapshot/v8_context_snapshot.stamp) + set(dataStampOption NINJA_DATA_STAMP obj/tools/v8_context_snapshot/v8_context_snapshot.stamp) endif() add_gn_build_artifacts_to_target( @@ -601,7 +602,7 @@ add_gn_build_artifacts_to_target( BUILDDIR ${buildDir} COMPLETE_STATIC FALSE NINJA_STAMP QtWebEngineCore.stamp - NINJA_DATA_STAMP ${dataStamp} + ${dataStampOption} ) add_dependencies(WebEngineCore run_core_NinjaDone) if(COIN_BUG_699) From 3c1488eb0c114742b12c00e50f2b3cd44050b0fa Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Tue, 4 Feb 2025 13:53:33 +0100 Subject: [PATCH 317/341] CMake: silence warning configuring examples When configuring qtwebengine as its own module, Svg is not searched as an optional component, leading to the warning in examples/pdf/CMakeLists.txt always being printed even when QtSvg is available. Add Svg as an optional package in find_package and move the checks into the individual examples so the warning will also appear when the individual example is built. Change-Id: I387dfd70ae1abc1a70f28dbfe74ac45b75bdf387 Reviewed-by: Michal Klocek (cherry picked from commit 50db3f69ec74926ffc360c865a8c0e1740e2ca64) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 9575d9c2acb57abde7139ca0e67c83f71a98749e) --- examples/pdf/CMakeLists.txt | 3 --- examples/pdf/multipage/CMakeLists.txt | 5 ++++- examples/pdf/singlepage/CMakeLists.txt | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/pdf/CMakeLists.txt b/examples/pdf/CMakeLists.txt index bdc1d0f0524..7255752b814 100644 --- a/examples/pdf/CMakeLists.txt +++ b/examples/pdf/CMakeLists.txt @@ -3,6 +3,3 @@ qt_internal_add_example(singlepage) qt_internal_add_example(multipage) -if(NOT TARGET Qt::Svg) - message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.") -endif() diff --git a/examples/pdf/multipage/CMakeLists.txt b/examples/pdf/multipage/CMakeLists.txt index 8f8111c826d..fb4e449fd7a 100644 --- a/examples/pdf/multipage/CMakeLists.txt +++ b/examples/pdf/multipage/CMakeLists.txt @@ -12,7 +12,10 @@ endif() set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/multipage") -find_package(Qt6 REQUIRED COMPONENTS Gui Qml) +find_package(Qt6 REQUIRED COMPONENTS Gui Qml OPTIONAL_COMPONENTS Svg) +if(NOT TARGET Qt::Svg) + message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.") +endif() qt_add_executable(multipage main.cpp diff --git a/examples/pdf/singlepage/CMakeLists.txt b/examples/pdf/singlepage/CMakeLists.txt index fac95f54a98..647a30f8d4d 100644 --- a/examples/pdf/singlepage/CMakeLists.txt +++ b/examples/pdf/singlepage/CMakeLists.txt @@ -12,7 +12,10 @@ endif() set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/singlepage") -find_package(Qt6 REQUIRED COMPONENTS Gui Qml) +find_package(Qt6 REQUIRED COMPONENTS Gui Qml OPTIONAL_COMPONENTS Svg) +if(NOT TARGET Qt::Svg) + message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.") +endif() qt_add_executable(pdfviewerquick main.cpp From 2a3d355db0516e428594632ec94c46cd10d08332 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Mon, 7 Apr 2025 20:09:12 +0000 Subject: [PATCH 318/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I087e179a2e914b55262c02e2556a648272364aa9 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 2c0ecb48769..349f94d6da0 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 253bed4ab8cd6f68d677c1dc8b459bb14cd37833 + ref: 32452675dc7661de32013969f9d2eb613da70096 required: true ../qtpositioning: - ref: 2b92855c184f342d99edddb91e53e887bf2b049e + ref: 73e77ed97a9384eb73140b83a364d3866358e364 required: false ../qttools: - ref: e2637b0c459f801d06df79fb68329cf0a76f0d10 + ref: 31ec5e9c0f3388756d06aa8ffd1c59c5f097dbaa required: false ../qtwebchannel: - ref: 57f6b62b83163335733e664de00877d370a09929 + ref: 5d51387a00af8cb76ca7e879583f398faef1f602 required: false From 23d1c956c243d3bab5fd8e2d8e12526fe9166907 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Fri, 4 Apr 2025 17:22:20 +0200 Subject: [PATCH 319/341] CMake: Fix QtWebEngine deployment when DESTDIR is set If DESTDIR is set, the install destination for all files should be $ENV{DESTDIR}/${CMAKE_INSTALL_PREFIX} by default. And that is the actual default value for QT_DEPLOY_PREFIX. The problem is that file(INSTALL) always prepends $ENV{DESTDIR} to the install destination, which when used with QT_DEPLOY_PREFIX results in DESTDIR being prepended twice to a path. Change the code to use CMAKE_INSTALL_PREFIX for file(INSTALL) commands and QT_DEPLOY_PREFIX for other commands. This was discovered while trying to create an installer for a deployed WebEngine application using CPack, which always sets a DESTDIR. Amends 73d58b489e8f4f900042f0ab6c1104e6431752e1 Fixes: QTBUG-135620 Task-number: QTBUG-109553 Task-number: QTBUG-119077 Change-Id: I5860c58454d6a204b36b2185b76b6f974e88f652 Reviewed-by: Joerg Bornemann Reviewed-by: Alexey Edelev (cherry picked from commit 19fac197602effd0f46b511753098b5191d2e964) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 2889a6136cca7f7dfb8250c64c105b878129c8c6) --- .../api/Qt6WebEngineCoreDeploySupport.cmake | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake index e67eb212b3d..a74616bc3b7 100644 --- a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake +++ b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake @@ -74,24 +74,31 @@ function(_qt_internal_deploy_webenginecore_binary) endif() endforeach() - set(install_destination "${QT_DEPLOY_PREFIX}/") + # CMAKE_INSTALL_PREFIX does not contain $ENV{DESTDIR}, whereas QT_DEPLOY_PREFIX does. + # The install_ variant should be used in file(INSTALL) to avoid double DESTDIR in paths. + # Other code should reference the destdir_ variant instead. + set(install_destination "${CMAKE_INSTALL_PREFIX}/") + set(destdir_destination "${QT_DEPLOY_PREFIX}/") + if(__QT_DEPLOY_SYSTEM_NAME STREQUAL "Windows") string(APPEND install_destination "${QT_DEPLOY_BIN_DIR}") + string(APPEND destdir_destination "${QT_DEPLOY_BIN_DIR}") else() string(APPEND install_destination "${QT_DEPLOY_LIBEXEC_DIR}") + string(APPEND destdir_destination "${QT_DEPLOY_LIBEXEC_DIR}") endif() file(INSTALL "${process_path}" DESTINATION "${install_destination}") get_filename_component(process_file_name "${process_path}" NAME) if(CMAKE_VERSION GREATER_EQUAL "3.19") - file(CHMOD "${install_destination}/${process_file_name}" + file(CHMOD "${destdir_destination}/${process_file_name}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ ) else() execute_process( - COMMAND chmod 0755 "${install_destination}/${process_file_name}" + COMMAND chmod 0755 "${destdir_destination}/${process_file_name}" ) endif() endfunction() @@ -117,8 +124,9 @@ function(_qt_internal_deploy_webenginecore_data) list(APPEND data_files "${snapshot_file}") endif() + # See comment above why we use CMAKE_INSTALL_PREFIX instead of QT_DEPLOY_PREFIX. get_filename_component(install_destination "${QT_DEPLOY_WEBENGINECORE_RESOURCES_DIR}" ABSOLUTE - BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_DATA_DIR}" + BASE_DIR "${CMAKE_INSTALL_PREFIX}/${QT_DEPLOY_DATA_DIR}" ) foreach(data_file IN LISTS data_files) file(INSTALL "${resources_dir}/${data_file}" DESTINATION "${install_destination}") @@ -163,8 +171,9 @@ function(_qt_internal_deploy_webenginecore_translations) get_filename_component(locales_dir "qtwebengine_locales" ABSOLUTE BASE_DIR "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_TRANSLATIONS}" ) + # See comment above why we use CMAKE_INSTALL_PREFIX instead of QT_DEPLOY_PREFIX. get_filename_component(install_destination "qtwebengine_locales" ABSOLUTE - BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}" + BASE_DIR "${CMAKE_INSTALL_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}" ) file(GLOB locale_files "${locales_dir}/*.pak") foreach(locale_file IN LISTS locale_files) From baf86f78b9de95b4a5727bccb9c6eca19e0cf008 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 6 Mar 2025 09:56:13 +0100 Subject: [PATCH 320/341] Add "default" and "gl" ANGLE implementation support to Ozone The EGL_EXT_image_dma_buf_import display extension is not available for non EGL display thus importing NativePixmap with EGL is not possible. Make possible to import NativePixmap as X11 pixmap. This makes --webEngineArgs --use-gl=angle --webEngineArgs --use-gl=angle --use-angle=default --webEngineArgs --use-gl=angle --use-angle=gl configurations work on Linux. Merge conflict resolution for 6.8: - Adapt to guards around header includes - NativePixmapEGLBinding::IsBufferFormatSupported() and NativePixmapEGLX11Binding::IsBufferFormatSupported() are not available in 122-based Chromium Task-number: QTBUG-129769 Task-number: QTBUG-133570 Change-Id: Ic6a40de373c5fd27c62abc3effb2f3ddee9210a8 Reviewed-by: Moss Heim Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 75b0d12f6a7f506d8d06a96ab4aa77d89358becd) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit a56ea1e9cf1004d475932dc954c9cc494fbf32b1) --- src/core/configure/BUILD.root.gn.in | 3 ++ src/core/ozone/gl_ozone_angle_qt.cpp | 53 +++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in index 42b06d4f7b7..c5cef0c7606 100644 --- a/src/core/configure/BUILD.root.gn.in +++ b/src/core/configure/BUILD.root.gn.in @@ -391,11 +391,14 @@ source_set("qtwebengine_sources") { deps += [ "//ui/base/x:gl", "//ui/gfx/linux:gpu_memory_buffer_support_x11", + "//ui/gfx/x", ] sources += [ "//ui/ozone/platform/x11/gl_egl_utility_x11.cc", "//ui/ozone/platform/x11/gl_egl_utility_x11.h", + "//ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc", + "//ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h", ] } } diff --git a/src/core/ozone/gl_ozone_angle_qt.cpp b/src/core/ozone/gl_ozone_angle_qt.cpp index 66692ed09a6..13258e4247f 100644 --- a/src/core/ozone/gl_ozone_angle_qt.cpp +++ b/src/core/ozone/gl_ozone_angle_qt.cpp @@ -1,6 +1,10 @@ -// Copyright (C) 2024 The Qt Company Ltd. +// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Copyright 2016 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #if defined(USE_OZONE) #include "gl_context_qt.h" #include "gl_ozone_angle_qt.h" @@ -15,6 +19,8 @@ #if BUILDFLAG(IS_OZONE_X11) #include "ui/gl/gl_glx_api_implementation.h" + +#include "ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h" #endif extern "C" { @@ -23,6 +29,34 @@ extern __eglMustCastToProperFunctionPointerType EGL_GetProcAddress(const char *p } namespace ui { +namespace { +// Based on //ui/ozone/platform/x11/x11_surface_factory.cc +enum class NativePixmapSupportType { + // Importing native pixmaps not supported. + kNone, + + // Native pixmaps are imported directly into EGL using the + // EGL_EXT_image_dma_buf_import extension. + kDMABuf, + + // Native pixmaps are first imported as X11 pixmaps using DRI3 and then into + // EGL. + kX11Pixmap, +}; + +NativePixmapSupportType GetNativePixmapSupportType() +{ + if (gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_EXT_image_dma_buf_import) + return NativePixmapSupportType::kDMABuf; + +#if BUILDFLAG(IS_OZONE_X11) + if (NativePixmapEGLX11Binding::CanImportNativeGLXPixmap()) + return NativePixmapSupportType::kX11Pixmap; +#endif + + return NativePixmapSupportType::kNone; +} +} // namespace bool GLOzoneANGLEQt::LoadGLES2Bindings(const gl::GLImplementationParts & /*implementation*/) { @@ -101,7 +135,7 @@ gl::EGLDisplayPlatform GLOzoneANGLEQt::GetNativeDisplay() bool GLOzoneANGLEQt::CanImportNativePixmap() { - return gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_EXT_image_dma_buf_import; + return GetNativePixmapSupportType() != NativePixmapSupportType::kNone; } std::unique_ptr @@ -110,8 +144,19 @@ GLOzoneANGLEQt::ImportNativePixmap(scoped_refptr pixmap, gfx::Size plane_size, const gfx::ColorSpace &color_space, GLenum target, GLuint texture_id) { - return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, color_space, - target, texture_id); + switch (GetNativePixmapSupportType()) { + case NativePixmapSupportType::kDMABuf: + return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, color_space, + target, texture_id); +#if BUILDFLAG(IS_OZONE_X11) + case NativePixmapSupportType::kX11Pixmap: + return NativePixmapEGLX11Binding::Create(pixmap, plane_format, plane_size, target, + texture_id); +#endif + default: + NOTREACHED(); + return nullptr; + } } } // namespace ui From ad147705c6e248fc423096ebcea94c2c9866b252 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Mon, 24 Mar 2025 10:53:12 +0100 Subject: [PATCH 321/341] NativeSkiaOutputDeviceOpenGL: Fix leaking X11 Pixmap Merge conflict resolution for 6.8: - No GLXHelper in 6.8, call xcb_free_pixmap() through Chromium's xcb protos Fixes: QTBUG-135047 Change-Id: I42b6387407551079241350661adadedf7d71a303 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit dbf459268d4bbc20e0a7e83e7889e0f6da79cf84) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 08f793a6ef5da886e1282a3fb9a2829bd14413b2) --- .../compositor/native_skia_output_device_opengl.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index deccd247b8d..d418bfe5c97 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -106,6 +106,12 @@ x11::Pixmap XPixmapFromNativePixmap(const gfx::NativePixmap &nativePixmap) return pixmapId; } +void FreeXPixmap(x11::Pixmap pixmap) +{ + auto *connection = x11::Connection::Get(); + connection->FreePixmap({ pixmap }); +} + GLXFBConfig GetFBConfig(Display *display) { // clang-format off @@ -269,9 +275,11 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te glXBindTexImageEXT(display, glxPixmap, GLX_FRONT_LEFT_EXT, nullptr); glFun->glBindTexture(GL_TEXTURE_2D, 0); - m_frontBuffer->textureCleanupCallback = [glFun, glTexture, display, glxPixmap]() { + m_frontBuffer->textureCleanupCallback = [glFun, glTexture, display, glxPixmap, + pixmapId]() { glFun->glDeleteTextures(1, &glTexture); glXDestroyGLXPixmap(display, glxPixmap); + FreeXPixmap(pixmapId); }; } #endif // BUILDFLAG(IS_OZONE_X11) From 2af24f9058442ea123eaea303316297b2f6c2f3f Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 7 Apr 2025 15:21:46 +0200 Subject: [PATCH 322/341] CMake: Adjust rpath of WebEngineProcess binary during deployment If the deployed lib dir is different from the Qt configured one (e.g. lib64 vs lib), __QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH will be set to true. In that case we need to adjust the rpath of the WebEngineProcess binary to point to the new lib dir. Amends 73d58b489e8f4f900042f0ab6c1104e6431752e1 Fixes: QTBUG-135620 Task-number: QTBUG-109553 Task-number: QTBUG-119077 Change-Id: Ic8b730386f4ab7d77da7e1ffb44d8482bd150209 Reviewed-by: Joerg Bornemann (cherry picked from commit a46b19e16f629d013c9b55d200b3fa645489bd5a) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 77b4452f8369ce4646a7cafff3d01f33ac7b5154) --- src/core/api/Qt6WebEngineCoreDeploySupport.cmake | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake index a74616bc3b7..b6f8b146380 100644 --- a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake +++ b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake @@ -101,6 +101,19 @@ function(_qt_internal_deploy_webenginecore_binary) COMMAND chmod 0755 "${destdir_destination}/${process_file_name}" ) endif() + + # Checking for __QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH is a bit strange because this is not a + # plugin, but it gives a single common way to detect when the rpath adjustment must be done, + # because the lib dir is different than the original Qt configured one. + if(__QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH) + _qt_internal_get_rpath_origin(rpath_origin) + file(RELATIVE_PATH rel_lib_dir "${destdir_destination}" + "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_LIB_DIR}") + _qt_internal_set_rpath( + FILE "${destdir_destination}/${process_file_name}" + NEW_RPATH "${rpath_origin}/${rel_lib_dir}" + ) + endif() endfunction() function(_qt_internal_deploy_webenginecore_data) From 61bfe4b78dd863e13b7664812f2ad0f1fd343386 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 3 Apr 2025 14:44:05 +0200 Subject: [PATCH 323/341] CMake: Stop passing DEPENDS to addCopyCommand addCopyCommand uses add_custom_target(POST_BUILD) which does not accept the DEPENDS argument. This was causing the following warning with CMake 3.31: CMake Warning (dev) at cmake/Functions.cmake:469 (add_custom_command): The following keywords are not supported when using add_custom_command(TARGET): DEPENDS. Policy CMP0175 is not set: add_custom_command() rejects invalid arguments. Run "cmake --help-policy CMP0175" for policy details. Use the cmake_policy command to set the policy and suppress this warning. Call Stack (most recent call first): src/core/api/CMakeLists.txt:241 (addCopyCommand) Stop passing the DEPENDS option. Change-Id: If58c3fa12f484b1ddf3136c79756f917bb8cfec3 Reviewed-by: Alexey Edelev (cherry picked from commit 324a4f6bec6a4612e4534d41e9a27ab6db480eca) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit c4b39cac33b5b567f908cf16ff5430a0a16e2d07) --- cmake/Functions.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 02276e46b91..5788efea56a 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -1352,7 +1352,6 @@ function(addCopyCommand target src dst) COMMAND ${CMAKE_COMMAND} -E make_directory ${dst} COMMAND ${CMAKE_COMMAND} -E copy ${src} ${dst} TARGET ${target} - DEPENDS ${src} USES_TERMINAL ) endfunction() From 97947de3e897515bfafb24246a52afc4f6c3c8ad Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 28 Mar 2025 09:38:15 +0100 Subject: [PATCH 324/341] Fix detection of VMware graphics driver Amends 83e85bebc Add more vendors to GPU detection Fixes: QTBUG-126722 Change-Id: Ie14c66d593e6ac8e1b55c377b73895397ef373ca Reviewed-by: Moss Heim Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 0738a7eca23acf1a14bdc37855245391f4b145cf) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit e6c6ea2f68b79e6cb4aec38a2485d985e42ae1b9) --- src/core/web_engine_context.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index bc84b68fee3..5d99dc70f43 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -151,7 +151,7 @@ class GPUInfo Qualcomm, Samsung, Broadcom, - VMWare, + VMware, VirtIO, // Khronos-registered vendors @@ -186,7 +186,7 @@ class GPUInfo {0x5143, Qualcomm}, {0x144D, Samsung}, {0x14E4, Broadcom}, - {0x15AD, VMWare}, + {0x15AD, VMware}, {0x1AF4, VirtIO}, {0x10001, Vivante}, {0x10002, VeriSilicon}, @@ -214,6 +214,8 @@ class GPUInfo return Intel; if (deviceName.contains("Nvidia"_L1, Qt::CaseInsensitive)) return Nvidia; + if (deviceName.contains("VMware"_L1, Qt::CaseInsensitive)) + return VMware; #if defined(USE_OZONE) if (deviceName.contains("Mesa llvmpipe"_L1)) @@ -244,7 +246,7 @@ class GPUInfo {Qualcomm, "Qualcomm"}, {Samsung, "Samsung"}, {Broadcom, "Broadcom"}, - {VMWare, "VMWare"}, + {VMware, "VMware"}, {VirtIO, "VirtIO"}, {Vivante, "Vivante"}, {VeriSilicon, "VeriSilicon"}, From bbf9599da65065a8418a6335eb7a2bfb09bbafa9 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 25 Mar 2025 14:53:38 +0100 Subject: [PATCH 325/341] NativeSkiaOutputDeviceVulkan: Use minimal set of usage flags for VkImage VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT usage flag is not necessary because the native VkImage imported into QSG seems to be only accessed via sampling. VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT also seems to conflict with the VK_IMAGE_LAYOUT_UNDEFINED initial layout with Nvidia driver. VK_IMAGE_LAYOUT_UNDEFINED is a requirement for importing external texture from Chromium. Keep VK_IMAGE_USAGE_SAMPLE_BIT usage flag because it is a requirement for sampling. Remove the corressponding VK_IMAGE_LAYOUT_PRINITIALIZED initial layout workaround for Nvidia. It is not necessary without the VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT flag and fixes validation layer warning. Also remove VK_IMAGE_USAGE_TRANSFER_DST_BIT and VK_IMAGE_TRANSFER_SRC_BIT usage flags because those are not used and seem to be leftover from an earlier implementation. Task-number: QTBUG-123607 Change-Id: If9dba4b6ff9d584e3d103ec8d05b7fe0cdaec339 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit f88fa0c83c7f0c063475539b327065f8615fe9d7) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit b829ca7c36d3d525b3f794d8c3ebf3417bdcb43a) --- .../native_skia_output_device_vulkan.cpp | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index 428dc06cf65..d65a609b94f 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -112,16 +112,6 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te QVulkanFunctions *f = win->vulkanInstance()->functions(); QVulkanDeviceFunctions *df = win->vulkanInstance()->deviceFunctions(qtVulkanDevice); - VkImageLayout imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkPhysicalDeviceProperties deviceProperties; - f->vkGetPhysicalDeviceProperties(qtPhysicalDevice, &deviceProperties); - if (deviceProperties.vendorID == 0x10DE) { - // FIXME: This is a workaround for Nvidia driver. - // The imported image is empty if the initialLayout is not - // VK_IMAGE_LAYOUT_PREINITIALIZED. - imageLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - } - VkExternalMemoryImageCreateInfoKHR externalMemoryImageCreateInfo = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR, .pNext = nullptr, @@ -210,10 +200,6 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te Q_ASSERT(sharedHandle != INVALID_HANDLE_VALUE); #endif - constexpr VkImageUsageFlags kUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT - | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - VkImageCreateInfo importedImageCreateInfo = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = &externalMemoryImageCreateInfo, @@ -229,11 +215,13 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = kUsage, + // The image is fed into a combined image sampler + .usage = VK_IMAGE_USAGE_SAMPLED_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, - .initialLayout = imageLayout, + // VkExternalMemoryImageCreateInfo only allows UNDEFINED + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, }; #if defined(USE_OZONE) @@ -314,8 +302,8 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te df->vkBindImageMemory(qtVulkanDevice, importedImage, importedImageMemory, 0); QQuickWindow::CreateTextureOptions texOpts(textureOptions); - QSGTexture *texture = QNativeInterface::QSGVulkanTexture::fromNative(importedImage, imageLayout, - win, size(), texOpts); + QSGTexture *texture = QNativeInterface::QSGVulkanTexture::fromNative( + importedImage, importedImageCreateInfo.initialLayout, win, size(), texOpts); m_frontBuffer->textureCleanupCallback = [=]() { df->vkDestroyImage(qtVulkanDevice, importedImage, nullptr); From 778386987677cf17fd77323fe74464ed55b78d24 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 9 Apr 2025 15:32:51 +0200 Subject: [PATCH 326/341] Turn webEngineCertificateError into a well-behaved value type Allow a nullptr as the controller and add an "Ok" value to the enum to signify "no error". This is in line with the "OK" value in Chromium's net_errors.h. Furthermore, add a public default ctor to allow QMetaType to create it. Task-number: QTBUG-108649 Fixes: QTBUG-135032 Change-Id: Id06db78f273805ba117eefaa0ada3eac2f538962 Reviewed-by: Michal Klocek (cherry picked from commit ba79e85eb5e7e28ff494c95d405164d8b25583d7) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 3a8022c68c8598b4c5ab39b782113c11fbc2bd73) --- src/core/api/qwebenginecertificateerror.cpp | 34 ++++++++++++++------ src/core/api/qwebenginecertificateerror.h | 3 ++ tests/auto/quick/publicapi/tst_publicapi.cpp | 1 + 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/core/api/qwebenginecertificateerror.cpp b/src/core/api/qwebenginecertificateerror.cpp index 85c5d512752..60ec3c95b19 100644 --- a/src/core/api/qwebenginecertificateerror.cpp +++ b/src/core/api/qwebenginecertificateerror.cpp @@ -42,6 +42,7 @@ QWebEngineCertificateError::~QWebEngineCertificateError() = default; QSslError::SslError values are not used directly, because the Qt error categories cannot be mapped to the Chromium error categories. + \value Ok There was no actual certificate error. \value SslPinnedKeyNotInCertificateChain The certificate did not match the built-in public keys pinned for the host name. \value CertificateCommonNameInvalid The certificate's common name did not match the host name. @@ -74,7 +75,9 @@ QWebEngineCertificateError::~QWebEngineCertificateError() = default; */ bool QWebEngineCertificateError::isOverridable() const { - return d->overridable(); + if (Q_LIKELY(d)) + return d->overridable(); + return false; } /*! @@ -84,7 +87,9 @@ bool QWebEngineCertificateError::isOverridable() const */ QUrl QWebEngineCertificateError::url() const { - return d->url(); + if (Q_LIKELY(d)) + return d->url(); + return QUrl(); } /*! @@ -97,7 +102,9 @@ QUrl QWebEngineCertificateError::url() const */ bool QWebEngineCertificateError::isMainFrame() const { - return d->isMainFrame(); + if (Q_LIKELY(d)) + return d->isMainFrame(); + return false; } /*! @@ -107,7 +114,9 @@ bool QWebEngineCertificateError::isMainFrame() const */ QWebEngineCertificateError::Type QWebEngineCertificateError::type() const { - return d->error(); + if (Q_LIKELY(d)) + return d->error(); + return Ok; } /*! @@ -117,7 +126,9 @@ QWebEngineCertificateError::Type QWebEngineCertificateError::type() const */ QString QWebEngineCertificateError::description() const { - return d->errorString(); + if (Q_LIKELY(d)) + return d->errorString(); + return QString(); } /*! @@ -135,7 +146,8 @@ QString QWebEngineCertificateError::description() const */ void QWebEngineCertificateError::defer() { - d->defer(); + if (Q_LIKELY(d)) + d->defer(); } /*! @@ -145,7 +157,8 @@ void QWebEngineCertificateError::defer() */ void QWebEngineCertificateError::acceptCertificate() { - d->ignoreCertificateError(); + if (Q_LIKELY(d)) + d->ignoreCertificateError(); } /*! @@ -155,7 +168,8 @@ void QWebEngineCertificateError::acceptCertificate() */ void QWebEngineCertificateError::rejectCertificate() { - d->rejectCertificate(); + if (Q_LIKELY(d)) + d->rejectCertificate(); } /*! @@ -167,7 +181,9 @@ void QWebEngineCertificateError::rejectCertificate() */ QList QWebEngineCertificateError::certificateChain() const { - return d->certificateChain(); + if (Q_LIKELY(d)) + return d->certificateChain(); + return QList(); } QT_END_NAMESPACE diff --git a/src/core/api/qwebenginecertificateerror.h b/src/core/api/qwebenginecertificateerror.h index 3eef3dcca58..73a3ac09099 100644 --- a/src/core/api/qwebenginecertificateerror.h +++ b/src/core/api/qwebenginecertificateerror.h @@ -27,12 +27,15 @@ class Q_WEBENGINECORE_EXPORT QWebEngineCertificateError Q_PROPERTY(bool isMainFrame READ isMainFrame CONSTANT FINAL REVISION(6, 8)) public: + QWebEngineCertificateError() = default; QWebEngineCertificateError(const QWebEngineCertificateError &other); QWebEngineCertificateError &operator=(const QWebEngineCertificateError &other); ~QWebEngineCertificateError(); // Keep this identical to NET_ERROR in net_error_list.h, or add mapping layer. enum Type { + Ok = 0, // No actual error. See net_errors.h for that one + SslPinnedKeyNotInCertificateChain = -150, CertificateCommonNameInvalid = -200, CertificateDateInvalid = -201, diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 499acbfc51e..10b07f36050 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -138,6 +138,7 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineCertificateError.CertificateSymantecLegacy --> Type" << "QWebEngineCertificateError.SslObsoleteVersion --> Type" << "QWebEngineCertificateError.SslPinnedKeyNotInCertificateChain --> Type" + << "QWebEngineCertificateError.Ok --> Type" << "QWebEngineCertificateError.defer() --> void" << "QWebEngineCertificateError.description --> QString" << "QWebEngineCertificateError.type --> QWebEngineCertificateError::Type" From a1059f50897c111950e59f111b9fe766ba876bc2 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Apr 2025 10:18:56 +0200 Subject: [PATCH 327/341] Turn webEngineFileSystemAccessRequest into well-behaved value type Allow a nullptr as the controller and add a public default ctor to allow QMetaType to create it. Task-number: QTBUG-108649 Task-number: QTBUG-135032 Change-Id: I70dc626bb7cce1fdb96c4c3b4dabce2fdfc17537 Reviewed-by: Michal Klocek (cherry picked from commit fc3e9ec77ffad4708b9dbc15a79cc651ab09832e) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 892c0c215ddf7b59f0d7ead4b1f238e8bb9d14b0) --- .../api/qwebenginefilesystemaccessrequest.cpp | 22 ++++++++++++++----- .../api/qwebenginefilesystemaccessrequest.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/core/api/qwebenginefilesystemaccessrequest.cpp b/src/core/api/qwebenginefilesystemaccessrequest.cpp index 3f901b671cf..0834468f659 100644 --- a/src/core/api/qwebenginefilesystemaccessrequest.cpp +++ b/src/core/api/qwebenginefilesystemaccessrequest.cpp @@ -72,7 +72,8 @@ QWebEngineFileSystemAccessRequest::QWebEngineFileSystemAccessRequest( */ void QWebEngineFileSystemAccessRequest::reject() { - d_ptr->reject(); + if (Q_LIKELY(d_ptr)) + d_ptr->reject(); } /*! @@ -80,7 +81,8 @@ void QWebEngineFileSystemAccessRequest::reject() */ void QWebEngineFileSystemAccessRequest::accept() { - d_ptr->accept(); + if (Q_LIKELY(d_ptr)) + d_ptr->accept(); } /*! @@ -90,7 +92,9 @@ void QWebEngineFileSystemAccessRequest::accept() QUrl QWebEngineFileSystemAccessRequest::origin() const { - return d_ptr->origin(); + if (Q_LIKELY(d_ptr)) + return d_ptr->origin(); + return QUrl(); } /*! @@ -100,7 +104,9 @@ QUrl QWebEngineFileSystemAccessRequest::origin() const QUrl QWebEngineFileSystemAccessRequest::filePath() const { - return d_ptr->filePath(); + if (Q_LIKELY(d_ptr)) + return d_ptr->filePath(); + return QUrl(); } /*! @@ -109,7 +115,9 @@ QUrl QWebEngineFileSystemAccessRequest::filePath() const */ HandleType QWebEngineFileSystemAccessRequest::handleType() const { - return d_ptr->handleType(); + if (Q_LIKELY(d_ptr)) + return d_ptr->handleType(); + return File; } /*! @@ -118,7 +126,9 @@ HandleType QWebEngineFileSystemAccessRequest::handleType() const */ AccessFlags QWebEngineFileSystemAccessRequest::accessFlags() const { - return d_ptr->accessFlags(); + if (Q_LIKELY(d_ptr)) + return d_ptr->accessFlags(); + return {}; } QT_END_NAMESPACE diff --git a/src/core/api/qwebenginefilesystemaccessrequest.h b/src/core/api/qwebenginefilesystemaccessrequest.h index 37b1e186111..7707c607c8c 100644 --- a/src/core/api/qwebenginefilesystemaccessrequest.h +++ b/src/core/api/qwebenginefilesystemaccessrequest.h @@ -24,6 +24,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFileSystemAccessRequest Q_PROPERTY(AccessFlags accessFlags READ accessFlags CONSTANT FINAL) public: + QWebEngineFileSystemAccessRequest() = default; QWebEngineFileSystemAccessRequest(const QWebEngineFileSystemAccessRequest &other); QWebEngineFileSystemAccessRequest &operator=(const QWebEngineFileSystemAccessRequest &other); QWebEngineFileSystemAccessRequest(QWebEngineFileSystemAccessRequest &&other) noexcept = default; From bf7ca506a3999950748d615fba445147d0bd8a47 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Apr 2025 10:27:37 +0200 Subject: [PATCH 328/341] Turn fullScreenRequest into a well-behaved value type Add a default constructor so that QMetaType can create it. Task-number: QTBUG-108649 Task-number: QTBUG-135032 Change-Id: If82aa9e318f17ba5727b3bd6ad3684afb8b36c7f Reviewed-by: Michal Klocek (cherry picked from commit c3cc6f868351401b07f162b06f1196df2e7f3794) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit f0ee80397bb6b2a10bf734740dd154983c85d135) --- src/core/api/qwebenginefullscreenrequest.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/api/qwebenginefullscreenrequest.h b/src/core/api/qwebenginefullscreenrequest.h index 8e25286b64f..b07d158fd35 100644 --- a/src/core/api/qwebenginefullscreenrequest.h +++ b/src/core/api/qwebenginefullscreenrequest.h @@ -23,6 +23,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFullScreenRequest Q_PROPERTY(QUrl origin READ origin CONSTANT) public: + QWebEngineFullScreenRequest() : QWebEngineFullScreenRequest(QUrl(), false, [](bool){}) {} QWebEngineFullScreenRequest(const QWebEngineFullScreenRequest &other); QWebEngineFullScreenRequest &operator=(const QWebEngineFullScreenRequest &other); QWebEngineFullScreenRequest(QWebEngineFullScreenRequest &&other); From 43e863088ba415cc197a74fadbbe0b20750fe1f9 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Apr 2025 10:35:00 +0200 Subject: [PATCH 329/341] Turn webEngineLoadingInfo into a well-behaved value type Add a default constructor so that QMetaType can create it. Task-number: QTBUG-108649 Task-number: QTBUG-135032 Change-Id: I9390392f24f29cc16e0f36367a6a77e60a76b068 Reviewed-by: Kaloyan Chehlarski Reviewed-by: Michal Klocek (cherry picked from commit 82cd5895d72cb5a0d555d5dcefa2719a1986169b) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 998a2a0a3d1ccd4d9b099d6533c893e936d2c52f) --- src/core/api/qwebengineloadinginfo.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/api/qwebengineloadinginfo.h b/src/core/api/qwebengineloadinginfo.h index 48d14601ab6..5c206d9a709 100644 --- a/src/core/api/qwebengineloadinginfo.h +++ b/src/core/api/qwebengineloadinginfo.h @@ -50,6 +50,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo }; Q_ENUM(ErrorDomain) + QWebEngineLoadingInfo() : QWebEngineLoadingInfo(QUrl(), LoadStartedStatus) {} QWebEngineLoadingInfo(const QWebEngineLoadingInfo &other); QWebEngineLoadingInfo &operator=(const QWebEngineLoadingInfo &other); QWebEngineLoadingInfo(QWebEngineLoadingInfo &&other); From fe932330413d1965954a58d66001c28ce614432c Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Fri, 11 Apr 2025 16:32:03 +0000 Subject: [PATCH 330/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: Iba6ad0b73fbdb80103e5b60e31b0c78245282b40 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 349f94d6da0..54ac8c407a5 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 32452675dc7661de32013969f9d2eb613da70096 + ref: b206c4e687f2c942cd429258b93be6aae245bb34 required: true ../qtpositioning: - ref: 73e77ed97a9384eb73140b83a364d3866358e364 + ref: 82ba4ba2bf4dfcb582a91d75ba65eb01999c6276 required: false ../qttools: - ref: 31ec5e9c0f3388756d06aa8ffd1c59c5f097dbaa + ref: 7176f0d188d648293859e232854fd1858ae71694 required: false ../qtwebchannel: - ref: 5d51387a00af8cb76ca7e879583f398faef1f602 + ref: f10f75ab8fa9fb6fdcb4a3d5182e9462c0ea258a required: false From 5e100030a9b6e2bf42d3cd6f133190a0387afdc2 Mon Sep 17 00:00:00 2001 From: Christophe Marin Date: Thu, 26 Dec 2024 13:11:51 +0100 Subject: [PATCH 331/341] Build system: remove libxml2 compilation test Chromium doesn't need LIBXML_ICU_ENABLED to be defined to build. Change-Id: I5788bfca058a7b65f1b2e80e9ad740b04b3dc7c6 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit d036335a9367e3631c92e247155334d15a14b1fe) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit a7c14eebd17ea974fb42de10720043fee1a385ed) --- configure.cmake | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/configure.cmake b/configure.cmake index 7df4c2b797a..c0276751f10 100644 --- a/configure.cmake +++ b/configure.cmake @@ -129,21 +129,6 @@ int main() { }" ) -qt_config_compile_test(libxml2 - LABEL "compatible libxml2 and libxslt" - LIBRARIES - PkgConfig::LIBXML2 - CODE -" -#include \"libxml/xmlversion.h\" -#if !defined(LIBXML_ICU_ENABLED) -#error libxml icu not enabled -#endif -int main() { - return 0; -}" -) - qt_config_compile_test(jpeg LABEL "compatible libjpeg" LIBRARIES @@ -373,7 +358,7 @@ qt_feature("webengine-system-libevent" PRIVATE ) qt_feature("webengine-system-libxml" PRIVATE LABEL "libxml2 and libxslt" - CONDITION UNIX AND TEST_libxml2 + CONDITION UNIX AND LIBXML2_FOUND ) qt_feature("webengine-system-lcms2" PRIVATE LABEL "lcms2" From f1d1f6b4f6f24ae60e46f604ed11f489f761fbdf Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 15 Apr 2025 14:14:03 +0200 Subject: [PATCH 332/341] Update Chromium Submodule src/3rdparty 55749ed0..5fff3583: * [fixup] Reinstate jumbo-builds * [Backport] CVE-2025-3071: Inappropriate implementation in Navigations (2/2) * [Backport] CVE-2025-3071: Inappropriate implementation in Navigations (1/2) * [Backport] Security bug 396460489 (2/2) * [Backport] Security bug 396460489 (1/2) * [Backport] CVE-2025-24855 Fix use-after-free of XPath context node * [Backport] CVE-2024-55549: Fix UAF related to excluded namespaces * [Backport] Security bug 397187119 * [Backport] Security bug 399002829 * [backport] Security bug 389707046 4/4 * [backport] Security bug 389707046 3/4 * [backport] Security bug 389707046 2/4 * [backport] Security bug 389707046 1/4 * Dependency for Security bug 389707046 * [Backport] CVE-2025-2783: Incorrect handle provided in unspecified circumstances in Mojo on Windows * Allow MAP_DROPPABLE memory mappings in Linux sandbox * Support clang-14 on macos-13 build * [fixup] Adapt favicon and history component for WebEngine Fixes: QTBUG-135998 Task-number: QTBUG-134644 Fixes: QTBUG-135837 Fixes: QTBUG-135424 Fixes: QTBUG-135902 Change-Id: If377e2f720ce6ca1df644c8f42d1c247d2929969 Reviewed-by: Allan Sandfeld Jensen --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 58db9e1086a..bce67801379 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 134.0.6998.89 +Patched with security patches up to Chromium version: 135.0.7049.85 diff --git a/src/3rdparty b/src/3rdparty index 55749ed0af5..5fff35835d9 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 55749ed0af5869215b88007df0cba430746583ae +Subproject commit 5fff35835d9b8a62348173a76466f18001113bca diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 5d99dc70f43..ce7332f0d10 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1297,7 +1297,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "134.0.6998.89"; // FIXME: Remember to update + return "135.0.7049.85"; // FIXME: Remember to update } QT_END_NAMESPACE From c36197b11e99d91f4f7dc56fb44f1457e3aea3bf Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Thu, 17 Apr 2025 10:37:35 +0000 Subject: [PATCH 333/341] Update dependencies on '6.8' in qt/qtwebengine Change-Id: I8f2e80c38fe40d66c132f17d16f0efa11f392117 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 54ac8c407a5..31d95285f1f 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: b206c4e687f2c942cd429258b93be6aae245bb34 + ref: f9e719687fe5160894203a5030bbb2e33ab0cf6f required: true ../qtpositioning: - ref: 82ba4ba2bf4dfcb582a91d75ba65eb01999c6276 + ref: 8277b8175e31ae6c81a79d8677a42c5e84db6261 required: false ../qttools: - ref: 7176f0d188d648293859e232854fd1858ae71694 + ref: 77db9c950477d9aa89d583b025f01c9e13e3ae44 required: false ../qtwebchannel: - ref: f10f75ab8fa9fb6fdcb4a3d5182e9462c0ea258a + ref: 36e6623be61e4d12376dcc1ed4c9ae059fa64bc3 required: false From 0f674a889aa4f6b2cbbb489521e9c74354aa7ab8 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 22 Apr 2025 14:32:52 +0200 Subject: [PATCH 334/341] Update Chromium MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule src/3rdparty 5fff3583..4a348a11: * [backport] CVE-2025-3619 * [fixup] Fix QtWebEngine build on Windows Fixes: QTBUG-136040 Change-Id: I4c48e90781443af774aee26ef24af2050976211d Reviewed-by: Michael BrĂ¼ning --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index bce67801379..bc95fd83e00 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 135.0.7049.85 +Patched with security patches up to Chromium version: 135.0.7049.95 diff --git a/src/3rdparty b/src/3rdparty index 5fff35835d9..4a348a11cae 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 5fff35835d9b8a62348173a76466f18001113bca +Subproject commit 4a348a11cae30c8d99591e093db895ad514a0a88 diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index ce7332f0d10..0802e7f182f 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1297,7 +1297,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "135.0.7049.85"; // FIXME: Remember to update + return "135.0.7049.95"; // FIXME: Remember to update } QT_END_NAMESPACE From 2df37bb1e76d68773ad2cdb3cd8ba3359dc4c018 Mon Sep 17 00:00:00 2001 From: Moss Heim Date: Tue, 8 Apr 2025 12:28:48 +0200 Subject: [PATCH 335/341] CMake: fix Svg dependency handling for pdf examples Since the find_package() calls in the example CMakeLists only create targets when the example is being built standalone, we still get warnings when configuring the full module. Without Svg support the example will look a bit broken, but this way it is still possible to build without qtsvg and deploy for a system which has svg rendering runtime. Amends 50db3f69e CMake: silence warning configuring examples Change-Id: Ifc17f00e1ba7d29638296c823f2af005996a44c5 Reviewed-by: Michal Klocek (cherry picked from commit 0ddb417eb702f388ee1ddd94fa62a693587d467d) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 1135b356ef377e3bcadc21090cc43d0448e49efa) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c647140e604..ee7fbca49ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ find_package(Qt6 ${PROJECT_VERSION} CONFIG QUIET OPTIONAL_COMPONENTS WebChannel WebChannelQuick Positioning QuickControls2 Test QuickWidgets QuickTest WebSockets Designer JpegPrivate PngPrivate HarfbuzzPrivate FreetypePrivate ZlibPrivate - HttpServer + HttpServer Svg ) if(MATRIX_BUILD AND NOT MATRIX_SUBBUILD AND NOT QT_SUPERBUILD) From 6cf0a23c785e1c72c308c42987b978a60fee30a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Wed, 23 Apr 2025 20:19:42 +0200 Subject: [PATCH 336/341] Update Chromium Submodule src/3rdparty 4a348a11..b110b061: * [Backport] Security bug 409243443 Pick-to: 6.5 Fixes: QTBUG-136168 Change-Id: Ibc719dde36ff29707e4c63967eee5fd47ff82b38 Reviewed-by: Allan Sandfeld Jensen --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index bc95fd83e00..80e969763e7 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 135.0.7049.95 +Patched with security patches up to Chromium version: 135.0.7049.115 diff --git a/src/3rdparty b/src/3rdparty index 4a348a11cae..b110b0619ad 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 4a348a11cae30c8d99591e093db895ad514a0a88 +Subproject commit b110b0619ad8c53a32362c384f2012a7333f0dfd diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 0802e7f182f..a2da0a71e37 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1297,7 +1297,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "135.0.7049.95"; // FIXME: Remember to update + return "135.0.7049.115"; // FIXME: Remember to update } QT_END_NAMESPACE From b6f421c3621e1306f6ee86d2c3cd67018307629a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Fri, 2 May 2025 17:29:39 +0200 Subject: [PATCH 337/341] Update Chromium Submodule src/3rdparty b110b061..35b2fd5a: * [Backport] CVE-2025-4051: Insufficient data validation in DevTools * [Backport] CVE-2025-4052: Inappropriate implementation in DevTools * [Backport] Security bug 403364367 * Avoid crash due to long dictionary commands * [fixup] Qt GN Integration * [fixup][android] Support android build for qtpdf Task-number: QTBUG-136542 Change-Id: I37cf620ea6d8037f6bf3d04483b9e3aa1e967196 Reviewed-by: Anu Aliyas --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 80e969763e7..fc3c8fc70fa 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 135.0.7049.115 +Patched with security patches up to Chromium version: 136.0.7103.59 diff --git a/src/3rdparty b/src/3rdparty index b110b0619ad..35b2fd5a667 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit b110b0619ad8c53a32362c384f2012a7333f0dfd +Subproject commit 35b2fd5a66733b0d57b94bdb1df2baad4d888f5e diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index a2da0a71e37..404ec74a60a 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1297,7 +1297,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "135.0.7049.115"; // FIXME: Remember to update + return "136.0.7103.59"; // FIXME: Remember to update } QT_END_NAMESPACE From 51343a5e9902b10465f77f44bbc935045ad12535 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 8 Apr 2025 17:52:08 +0200 Subject: [PATCH 338/341] Do pass -isysroot optionally for gn build With cmake 4.0 changes, we can no longer expect CMAKE_OSX_SYSROOT to be set: https://cmake.org/cmake/help/latest/release/4.0.html#other-changes Therefore make the setting optional for gn, as it should not be required on "modern macOS". Task-number: QTBUG-135621 Change-Id: I48ed72d6e920fec4c395eb04c8a18619e045c1b4 Reviewed-by: Moss Heim (cherry picked from commit 4bf8f28aeeba3f416bc411c396f2be92f5a1c4b9) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 7c01d710dbfc7441077d9c0fecb6acc674715307) --- src/gn/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gn/CMakeLists.txt b/src/gn/CMakeLists.txt index 9782f17abc8..fdf0b11a1ac 100644 --- a/src/gn/CMakeLists.txt +++ b/src/gn/CMakeLists.txt @@ -70,8 +70,8 @@ add_custom_command( --platform ${platform} --ar ${CMAKE_AR} --qt-version "${QT_REPO_MODULE_VERSION}.qtwebengine.qt.io" - $<$:--isysroot> - $<$:${CMAKE_OSX_SYSROOT}> + $<$,$>:--isysroot> + $<$,$>:${CMAKE_OSX_SYSROOT}> $<$,$>:--osx-architectures> $<$,$>:${OSX_ARCH}> COMMAND Ninja::ninja -C ${GN_BINARY_DIR}/$ ${GN_EXECUTABLE} From 13e34061f279c57caeb83f5812779649221e8a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Mon, 12 May 2025 10:34:20 +0200 Subject: [PATCH 339/341] Update Chromium Submodule src/3rdparty 35b2fd5a..681cfd93: * [Backport] CVE-2025-3277 Fixes: QTBUG-136644 Change-Id: Iaf211d3f0fa7741c9fe3b479d7f86a3b5a39fae0 Reviewed-by: Michal Klocek --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index fc3c8fc70fa..6babc4b88e0 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 136.0.7103.59 +Patched with security patches up to Chromium version: 136.0.7103.92 diff --git a/src/3rdparty b/src/3rdparty index 35b2fd5a667..681cfd93f2a 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 35b2fd5a66733b0d57b94bdb1df2baad4d888f5e +Subproject commit 681cfd93f2a4b5b3e3644e95f40b6a58e05aaabe diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 404ec74a60a..9ab2790da80 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1297,7 +1297,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "136.0.7103.59"; // FIXME: Remember to update + return "136.0.7103.92"; // FIXME: Remember to update } QT_END_NAMESPACE From 8f01d41808eb2097eea187cbb92ae6d5d1beddf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Mon, 19 May 2025 16:41:25 +0200 Subject: [PATCH 340/341] Update Chromium Submodule src/3rdparty 681cfd93..5f5c3ab2: * [Backport] Fixup for bugs 414858409 and 413080347 * [Backport] Security bug 413080347 * [Backport] Security bug 414858409 (2/2) * [Backport] Security bug 414858409 (1/2) * [Backport] CVE-2025-4609: Incorrect handle provided in unspecified circumstances in Mojo * [Backport] CVE-2025-4664: Insufficient policy enforcement in Loader Fixes: QTBUG-136994 Change-Id: Ifebb3a864aec7128556484554eeed1ca60e753a0 Reviewed-by: Michal Klocek --- CHROMIUM_VERSION | 2 +- src/3rdparty | 2 +- src/core/web_engine_context.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 6babc4b88e0..eb2bd1e90dc 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 136.0.7103.92 +Patched with security patches up to Chromium version: 136.0.7103.114 diff --git a/src/3rdparty b/src/3rdparty index 681cfd93f2a..5f5c3ab297f 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 681cfd93f2a4b5b3e3644e95f40b6a58e05aaabe +Subproject commit 5f5c3ab297fe330253f0630b1e9b6f2112c5cb41 diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 9ab2790da80..8dc83fcc99e 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1297,7 +1297,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "136.0.7103.92"; // FIXME: Remember to update + return "136.0.7103.114"; // FIXME: Remember to update } QT_END_NAMESPACE From 8a65a43b07ef210aa069c7db3c1d3fa1d168f19c Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 3 Apr 2025 14:25:11 +0200 Subject: [PATCH 341/341] NativeSkiaOutputDeviceVulkan: Fix Vulkan rendering with AMD GPU on Linux gbm_bo_get_modifier() may return invalid DRM format modifier for AMD driver. In this case, create VkImage without DRM format modifier and fallback tiling to VK_IMAGE_TILING_OPTIMAL instead of VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Fixes: QTBUG-123607 Change-Id: Iacf4fc514ab42fa9ab712f5d9fde2d20000f599d Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 0af1b2b24955d77815642e005a3e528b2c0151d0) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit a4b729fe555f92a0708bc5131f0396b9648ed932) --- .../native_skia_output_device_vulkan.cpp | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index d65a609b94f..8cb01cd22c1 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -136,17 +136,23 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te .pPlaneLayouts = &planeLayout, }; + bool usingDrmModifier = false; if (nativePixmap) { qCDebug(lcWebEngineCompositor, "VULKAN: Importing NativePixmap into VkImage."); gfx::NativePixmapHandle nativePixmapHandle = nativePixmap->ExportHandle(); - if (nativePixmapHandle.planes.size() != 1) - qFatal("VULKAN: Multiple planes are not supported."); + qCDebug(lcWebEngineCompositor, " DRM Format Modifier: 0x%lx", nativePixmapHandle.modifier); - planeLayout.offset = nativePixmapHandle.planes[0].offset; - planeLayout.rowPitch = nativePixmapHandle.planes[0].stride; - modifierInfo.drmFormatModifier = nativePixmapHandle.modifier; + if (nativePixmapHandle.modifier != gfx::NativePixmapHandle::kNoModifier) { + usingDrmModifier = true; + if (nativePixmapHandle.planes.size() != 1) + qFatal("VULKAN: Multiple planes are not supported."); - externalMemoryImageCreateInfo.pNext = &modifierInfo; + planeLayout.offset = nativePixmapHandle.planes[0].offset; + planeLayout.rowPitch = nativePixmapHandle.planes[0].stride; + modifierInfo.drmFormatModifier = nativePixmapHandle.modifier; + + externalMemoryImageCreateInfo.pNext = &modifierInfo; + } externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; scopedFd = std::move(nativePixmapHandle.planes[0].fd); @@ -225,9 +231,9 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te }; #if defined(USE_OZONE) - if (nativePixmap) + if (usingDrmModifier) importedImageCreateInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - else + else if (vkImageInfo.fAlloc.fMemory != VK_NULL_HANDLE) importedImageCreateInfo.tiling = vkImageInfo.fImageTiling; #endif