diff options
Diffstat (limited to 'tests')
30 files changed, 1056 insertions, 190 deletions
diff --git a/tests/auto/core/CMakeLists.txt b/tests/auto/core/CMakeLists.txt index 5908756b4..eb8e9266f 100644 --- a/tests/auto/core/CMakeLists.txt +++ b/tests/auto/core/CMakeLists.txt @@ -2,6 +2,7 @@ # SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qwebenginecookiestore) +add_subdirectory(qwebengineframe) add_subdirectory(qwebengineloadinginfo) add_subdirectory(qwebenginesettings) if(QT_FEATURE_ssl) diff --git a/tests/auto/core/certificateerror/tst_certificateerror.cpp b/tests/auto/core/certificateerror/tst_certificateerror.cpp index 67e2d8ae4..61201e250 100644 --- a/tests/auto/core/certificateerror/tst_certificateerror.cpp +++ b/tests/auto/core/certificateerror/tst_certificateerror.cpp @@ -19,6 +19,7 @@ private Q_SLOTS: void handleError_data(); void handleError(); void fatalError(); + void resourceError(); }; struct PageWithCertificateErrorHandler : QWebEnginePage @@ -130,5 +131,20 @@ void tst_CertificateError::fatalError() } } +void tst_CertificateError::resourceError() +{ + PageWithCertificateErrorHandler page(false, false); + page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + + page.setHtml("<img src=\"https://expired.badssl.com\">"); + if (!page.loadSpy.wait(10000)) { + QVERIFY2(!page.error, "There shouldn't be any certificate error if not loaded due to missing internet access!"); + QSKIP("Couldn't load page from network, skipping test."); + } + + QTRY_VERIFY(page.error); + QCOMPARE(page.error->isMainFrame(), false); +} + QTEST_MAIN(tst_CertificateError) #include <tst_certificateerror.moc> diff --git a/tests/auto/core/qwebengineframe/CMakeLists.txt b/tests/auto/core/qwebengineframe/CMakeLists.txt new file mode 100644 index 000000000..7d73e5a4a --- /dev/null +++ b/tests/auto/core/qwebengineframe/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +include(../../util/util.cmake) + +qt_internal_add_test(tst_qwebengineframe + SOURCES + tst_qwebengineframe.cpp + LIBRARIES + Qt::WebEngineCore + Qt::WebEngineWidgets + Test::Util +) + +qt_internal_add_resource(tst_qwebengineframe "tst_qwebengineframe" + PREFIX + "/" + FILES + "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/frameset.html b/tests/auto/core/qwebengineframe/resources/frameset.html new file mode 100644 index 000000000..53f5e6638 --- /dev/null +++ b/tests/auto/core/qwebengineframe/resources/frameset.html @@ -0,0 +1,20 @@ +<!doctype html> +<html> + <head><title>Test-title</title></head> + <script> + window.name = 'test-main-frame' + onload = (e) => { + const frames = window.frames; + for (let i = 0; i < frames.length; i++) { + frames[i].name = 'test-subframe' + i; + } + }; + </script> + <frameset cols="50%, 50%"> + <frameset cols="50%, 50%"> + <frame style="border: red dashed 1em;"/> + <frame style="border: green dashed 1em;"/> + </frameset> + <frame style="border: blue solid 1em;"/> + </frameset> +</html> diff --git a/tests/auto/core/qwebengineframe/resources/iframes.html b/tests/auto/core/qwebengineframe/resources/iframes.html new file mode 100644 index 000000000..648acb166 --- /dev/null +++ b/tests/auto/core/qwebengineframe/resources/iframes.html @@ -0,0 +1,17 @@ +<!doctype html> +<html> + <head><title>Test-title</title></head> + <script> + window.name = 'test-main-frame' + onload = (e) => { + const frames = window.frames; + for (let i = 0; i < frames.length; i++) { + frames[i].name = 'test-subframe' + i; + } + }; + </script> + <body> + <iframe name="iframe0-300x200" width="300" height="200"></iframe> + <iframe name="iframe1-350x250" width="350" height="250"></iframe> + </body> +</html> diff --git a/tests/auto/core/qwebengineframe/resources/nesting-iframe.html b/tests/auto/core/qwebengineframe/resources/nesting-iframe.html new file mode 100644 index 000000000..cd784e3dd --- /dev/null +++ b/tests/auto/core/qwebengineframe/resources/nesting-iframe.html @@ -0,0 +1,7 @@ +<!doctype html> +<html> + <head><title>Test-title</title></head> + <body> + <iframe name="iframe2-parent" src="iframes.html"></iframe> + </body> +</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 000000000..2e5a53af5 --- /dev/null +++ b/tests/auto/core/qwebengineframe/resources/printing-inner-document.html @@ -0,0 +1,7 @@ +<!doctype html> +<html> + <head><title>Printing Inner Document</title></head> + <body> + <h1>Inner Header</h1> + </body> +</html> 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 000000000..c5947371e --- /dev/null +++ b/tests/auto/core/qwebengineframe/resources/printing-outer-document.html @@ -0,0 +1,8 @@ +<!doctype html> +<html> + <head><title>Printing Outer Document</title></head> + <body> + <h1>Outer Header</h1> + <iframe name="inner" src="printing-inner-document.html"></iframe> + </body> +</html> diff --git a/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp new file mode 100644 index 000000000..8bbefd5f5 --- /dev/null +++ b/tests/auto/core/qwebengineframe/tst_qwebengineframe.cpp @@ -0,0 +1,346 @@ +/* + Copyright (C) 2024 The Qt Company Ltd. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <util.h> + +#include <QtTest/QtTest> + +#include <QtWebEngineCore/qwebengineframe.h> + +class tst_QWebEngineFrame : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void mainFrame(); + void findFrameByName(); + void isValid(); + void name(); + void htmlName(); + void children(); + void childrenOfInvalidFrame(); + void url(); + void size(); + void isMainFrame(); + void runJavaScript(); + void printRequestedByFrame(); + void printToPdfFile(); + void printToPdfFileFailures(); + void printToPdfFunction(); + +private: +}; + +void tst_QWebEngineFrame::mainFrame() +{ + 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.isValid()); +} + +void tst_QWebEngineFrame::findFrameByName() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/iframes.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto maybeFrame = page.findFrameByName("test-subframe0"); + QVERIFY(maybeFrame.has_value()); + QCOMPARE(maybeFrame->name(), "test-subframe0"); + QVERIFY(!page.findFrameByName("foobar").has_value()); +} + +void tst_QWebEngineFrame::isValid() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/iframes.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto firstPageSubframe = page.findFrameByName("test-subframe0"); + QVERIFY(firstPageSubframe && firstPageSubframe->isValid()); + + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 2); + QVERIFY(!firstPageSubframe->isValid()); +} + +void tst_QWebEngineFrame::name() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 1); + QCOMPARE(page.mainFrame().name(), "test-main-frame"); + auto children = page.mainFrame().children(); + QCOMPARE(children.at(0).name(), "test-subframe0"); + QCOMPARE(children.at(1).name(), "test-subframe1"); + QCOMPARE(children.at(2).name(), "test-subframe2"); + + page.load(QUrl("qrc:/resources/iframes.html")); + QTRY_COMPARE(loadSpy.size(), 2); + QVERIFY(!children.at(0).isValid()); + QCOMPARE(children.at(0).name(), QString()); +} + +void tst_QWebEngineFrame::htmlName() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/iframes.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto children = page.mainFrame().children(); + QCOMPARE(children.at(0).name(), "test-subframe0"); + QCOMPARE(children.at(0).htmlName(), "iframe0-300x200"); + QCOMPARE(children.at(1).name(), "test-subframe1"); + QCOMPARE(children.at(1).htmlName(), "iframe1-350x250"); + + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 2); + QVERIFY(!children.at(0).isValid()); + QCOMPARE(children.at(0).htmlName(), QString()); +} + +void tst_QWebEngineFrame::children() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto frame = page.mainFrame(); + auto children = frame.children(); + QCOMPARE(children.size(), 3); + for (auto child : children) { + QVERIFY(child.isValid()); + } +} + +void tst_QWebEngineFrame::childrenOfInvalidFrame() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/nesting-iframe.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto nestedFrame = page.mainFrame().children().at(0); + QCOMPARE(nestedFrame.children().size(), 2); + + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 2); + QVERIFY(!nestedFrame.isValid()); + QVERIFY(nestedFrame.children().empty()); +} + +void tst_QWebEngineFrame::url() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/nesting-iframe.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto children = page.mainFrame().children(); + QCOMPARE(children.at(0).url(), QUrl("qrc:/resources/iframes.html")); + + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 2); + QVERIFY(!children.at(0).isValid()); + QCOMPARE(children.at(0).url(), QUrl()); +} + +void tst_QWebEngineFrame::size() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/iframes.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto frame1 = *page.findFrameByName("test-subframe0"); + auto size1 = frame1.size(); + auto size2 = page.findFrameByName("test-subframe1")->size(); + QCOMPARE(size1, QSizeF(300, 200)); + QCOMPARE(size2, QSizeF(350, 250)); + + page.load(QUrl("qrc:/resources/frameset.html")); + QTRY_COMPARE(loadSpy.size(), 2); + QVERIFY(!frame1.isValid()); + 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; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + page.load(QUrl("qrc:/resources/iframes.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto children = page.mainFrame().children(); + CallbackSpy<QVariant> spy; + children[0].runJavaScript("window.name", spy.ref()); + auto result = spy.waitForResult(); + QCOMPARE(result, QString("test-subframe0")); +} + +void tst_QWebEngineFrame::printRequestedByFrame() +{ + QWebEnginePage page; + QSignalSpy loadSpy{ &page, SIGNAL(loadFinished(bool)) }; + QSignalSpy printRequestedSpy{ &page, SIGNAL(printRequestedByFrame(QWebEngineFrame)) }; + + page.load(QUrl("qrc:/resources/nesting-iframe.html")); + QTRY_COMPARE(loadSpy.size(), 1); + auto oFrame2 = page.findFrameByName("test-main-frame"); + QVERIFY(oFrame2.has_value()); + CallbackSpy<QVariant> spy; + oFrame2->runJavaScript("window.print()", spy.ref()); + spy.waitForResult(); + QCOMPARE(printRequestedSpy.size(), 1); + auto *framePtr = get_if<QWebEngineFrame>(&printRequestedSpy[0][0]); + 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<QVariant> 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<QVariant> 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<QVariant> 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<QVariant> 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<QByteArray> outerSpy; + outerFrame.printToPdf(outerSpy.ref()); + auto outerPdfData = outerSpy.waitForResult(); + QCOMPARE_GT(outerPdfData.size(), 0); + + CallbackSpy<QByteArray> 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<QByteArray> 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/core/qwebengineglobalsettings/CMakeLists.txt b/tests/auto/core/qwebengineglobalsettings/CMakeLists.txt index fa81ba8df..dd2f28857 100644 --- a/tests/auto/core/qwebengineglobalsettings/CMakeLists.txt +++ b/tests/auto/core/qwebengineglobalsettings/CMakeLists.txt @@ -8,6 +8,7 @@ qt_internal_add_test(tst_qwebengineglobalsettings SOURCES tst_qwebengineglobalsettings.cpp LIBRARIES + Qt::Network Qt::WebEngineCore Test::HttpServer Qt::WebEngineWidgets diff --git a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp index 0af85a711..5b6b64778 100644 --- a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp +++ b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp @@ -3,6 +3,8 @@ #include <QtTest> #include <widgetutil.h> +#include <QNetworkAccessManager> +#include <QNetworkRequest> #include <QWebEngineProfile> #include <QWebEnginePage> #include <QWebEngineGlobalSettings> @@ -68,6 +70,15 @@ void tst_QWebEngineGlobalSettings::dnsOverHttps_data() void tst_QWebEngineGlobalSettings::dnsOverHttps() { + const QUrl url = QStringLiteral("https://google.com/"); + // Verify network access with NAM because the result of loadFinished signal + // is used to verify that the DNS resolution was successful. + QNetworkAccessManager nam; + QSignalSpy namSpy(&nam, &QNetworkAccessManager::finished); + QScopedPointer<QNetworkReply> reply(nam.get(QNetworkRequest(url))); + if (!namSpy.wait(20000) || reply->error() != QNetworkReply::NoError) + QSKIP("Couldn't load page from network, skipping test."); + QFETCH(QWebEngineGlobalSettings::SecureDnsMode, dnsMode); QFETCH(QString, uriTemplate); QFETCH(bool, isMockDnsServerCalledExpected); @@ -105,10 +116,8 @@ void tst_QWebEngineGlobalSettings::dnsOverHttps() connect(&page, &QWebEnginePage::loadFinished, this, [&isLoadSuccessful](bool ok) { isLoadSuccessful = ok; }); - page.load(QUrl("https://google.com/")); - if (!loadSpy.wait(20000)) { - QSKIP("Couldn't load page from network, skipping test."); - } + page.load(url); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000); QTRY_COMPARE(isMockDnsServerCalled, isMockDnsServerCalledExpected); QCOMPARE(isLoadSuccessful, isDnsResolutionSuccessExpected); diff --git a/tests/auto/core/qwebengineurlrequestjob/CMakeLists.txt b/tests/auto/core/qwebengineurlrequestjob/CMakeLists.txt index 02b668313..59520e4ed 100644 --- a/tests/auto/core/qwebengineurlrequestjob/CMakeLists.txt +++ b/tests/auto/core/qwebengineurlrequestjob/CMakeLists.txt @@ -1,11 +1,14 @@ # Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause +include(../../util/util.cmake) + qt_internal_add_test(tst_qwebengineurlrequestjob SOURCES tst_qwebengineurlrequestjob.cpp LIBRARIES Qt::WebEngineCore + Test::Util ) # Resources: diff --git a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp index d48da2c44..d92aad5c4 100644 --- a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp +++ b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp @@ -2,12 +2,15 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include <QtTest/QtTest> +#include <util.h> +#include <QtWebEngineCore/qwebengineloadinginfo.h> #include <QtWebEngineCore/qwebengineurlschemehandler.h> #include <QtWebEngineCore/qwebengineurlscheme.h> #include <QtWebEngineCore/qwebengineurlrequestjob.h> #include <QtWebEngineCore/qwebengineprofile.h> #include <QtWebEngineCore/qwebenginepage.h> + class CustomPage : public QWebEnginePage { Q_OBJECT @@ -125,6 +128,32 @@ public: const static inline QByteArray schemeName = QByteArrayLiteral("requestbodyhandler"); }; +class SuccessHandler : public QWebEngineUrlSchemeHandler +{ +public: + SuccessHandler() { } + + void requestStarted(QWebEngineUrlRequestJob *requestJob) override + { + if (silentSuccess) + requestJob->reply("", nullptr); + else { + QBuffer *buffer = new QBuffer(requestJob); + buffer->setData(requestJob->requestUrl().toString().toUtf8()); + requestJob->reply("text/plain;charset=utf-8", buffer); + } + } + + static void registerUrlScheme() + { + QWebEngineUrlScheme successScheme(schemeName); + QWebEngineUrlScheme::registerScheme(successScheme); + } + + bool silentSuccess = false; + const static inline QByteArray schemeName = QByteArrayLiteral("success"); +}; + class tst_QWebEngineUrlRequestJob : public QObject { Q_OBJECT @@ -137,6 +166,7 @@ private Q_SLOTS: { AdditionalResponseHeadersHandler::registerUrlScheme(); RequestBodyHandler::registerUrlScheme(); + SuccessHandler::registerUrlScheme(); } void withAdditionalResponseHeaders_data() @@ -181,6 +211,30 @@ private Q_SLOTS: QVERIFY(spy.wait()); QCOMPARE(page.comparedMessageCount(), 1); } + + void notifySuccess() + { + QWebEngineProfile profile; + QWebEnginePage page(&profile); + QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); + + SuccessHandler handler; + page.profile()->installUrlSchemeHandler(SuccessHandler::schemeName, &handler); + + page.load(QUrl("success://one")); + QTRY_COMPARE(loadFinishedSpy.size(), 1); + QTRY_COMPARE(loadFinishedSpy.at(0).first().toBool(), true); + QCOMPARE(toPlainTextSync(&page), "success://one"); + + handler.silentSuccess = true; + + page.load(QUrl("success://two")); + // Page load was successful + QTRY_COMPARE(loadFinishedSpy.size(), 2); + QTRY_COMPARE(loadFinishedSpy.at(1).first().toBool(), true); + // The content of the page did not change + QCOMPARE(toPlainTextSync(&page), "success://one"); + } }; QTEST_MAIN(tst_QWebEngineUrlRequestJob) diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index b98e2a942..e6605dc41 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -25,6 +25,8 @@ #include <QtWebEngineCore/QWebEngineScript> #include <QtWebEngineCore/QWebEngineLoadingInfo> #include <QtWebEngineCore/QWebEngineWebAuthUxRequest> +#include <QtWebEngineCore/QWebEngineFrame> +#include <QtWebEngineCore/QWebEnginePermission> #include <private/qquickwebengineview_p.h> #include <private/qquickwebengineaction_p.h> #include <private/qquickwebengineclientcertificateselection_p.h> @@ -71,15 +73,18 @@ static const QList<const QMetaObject *> typesToCheck = QList<const QMetaObject * << &QWebEngineNavigationRequest::staticMetaObject << &QWebEngineNewWindowRequest::staticMetaObject << &QWebEngineNotification::staticMetaObject + << &QWebEnginePermission::staticMetaObject << &QWebEngineQuotaRequest::staticMetaObject << &QWebEngineRegisterProtocolHandlerRequest::staticMetaObject << &QQuickWebEngineTouchSelectionMenuRequest::staticMetaObject << &QWebEngineWebAuthUxRequest::staticMetaObject << &QWebEngineWebAuthPinRequest::staticMetaObject + << &QWebEngineFrame::staticMetaObject ; static QList<QMetaEnum> knownEnumNames = QList<QMetaEnum>() << QWebEngineDownloadRequest::staticMetaObject.enumerator(QWebEngineDownloadRequest::staticMetaObject.indexOfEnumerator("SavePageFormat")) + << QWebEnginePermission::staticMetaObject.enumerator(QWebEnginePermission::staticMetaObject.indexOfEnumerator("Feature")) ; static const QStringList hardcodedTypes = QStringList() @@ -93,7 +98,9 @@ static const QStringList hardcodedTypes = QStringList() << "Qt::LayoutDirection" << "QQuickWebEngineScriptCollection*" << "QQmlComponent*" - << "QMultiMap<QByteArray,QByteArray>"; + << "QMultiMap<QByteArray,QByteArray>" + << "QList<QWebEnginePermission>" + ; static const QStringList expectedAPI = QStringList() << "QQuickWebEngineAction.text --> QString" @@ -132,6 +139,7 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineCertificateError.defer() --> void" << "QWebEngineCertificateError.description --> QString" << "QWebEngineCertificateError.type --> QWebEngineCertificateError::Type" + << "QWebEngineCertificateError.isMainFrame --> bool" << "QWebEngineCertificateError.acceptCertificate() --> void" << "QWebEngineCertificateError.overridable --> bool" << "QWebEngineCertificateError.rejectCertificate() --> void" @@ -350,6 +358,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" @@ -357,6 +388,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.cachePath --> QString" << "QQuickWebEngineProfile.cachePathChanged() --> void" << "QQuickWebEngineProfile.clearHttpCache() --> void" @@ -365,6 +399,12 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadRequest*) --> void" << "QQuickWebEngineProfile.downloadPath --> QString" << "QQuickWebEngineProfile.downloadPathChanged() --> void" + << "QQuickWebEngineProfile.getPermission(QUrl,QWebEnginePermission::Feature) --> QWebEnginePermission" + << "QQuickWebEngineProfile.listPermissions() --> QList<QWebEnginePermission>" + << "QQuickWebEngineProfile.listPermissions(QUrl) --> QList<QWebEnginePermission>" + << "QQuickWebEngineProfile.listPermissions(QWebEnginePermission::Feature) --> QList<QWebEnginePermission>" + << "QQuickWebEngineProfile.persistentPermissionsPolicy --> QQuickWebEngineProfile::PersistentPermissionsPolicy" + << "QQuickWebEngineProfile.persistentPermissionsPolicyChanged() --> void" << "QQuickWebEngineProfile.presentNotification(QWebEngineNotification*) --> void" << "QQuickWebEngineProfile.httpAcceptLanguage --> QString" << "QQuickWebEngineProfile.httpAcceptLanguageChanged() --> void" @@ -529,10 +569,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" @@ -544,8 +594,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" @@ -600,7 +648,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" @@ -645,12 +692,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" @@ -715,6 +757,7 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.featurePermissionRequested(QUrl,QQuickWebEngineView::Feature) --> void" << "QQuickWebEngineView.fileDialogRequested(QQuickWebEngineFileDialogRequest*) --> void" << "QQuickWebEngineView.fileSystemAccessRequested(QWebEngineFileSystemAccessRequest) --> void" + << "QQuickWebEngineView.findFrameByName(QString) --> QWebEngineFrame" << "QQuickWebEngineView.findText(QString) --> void" << "QQuickWebEngineView.findText(QString,FindFlags) --> void" << "QQuickWebEngineView.findText(QString,FindFlags,QJSValue) --> void" @@ -725,7 +768,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" @@ -744,6 +789,7 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.loadProgressChanged() --> void" << "QQuickWebEngineView.loading --> bool" << "QQuickWebEngineView.loadingChanged(QWebEngineLoadingInfo) --> void" + << "QQuickWebEngineView.mainFrame --> QWebEngineFrame" << "QQuickWebEngineView.navigationRequested(QWebEngineNavigationRequest*) --> void" << "QQuickWebEngineView.newWindowRequested(QQuickWebEngineNewWindowRequest*) --> void" << "QQuickWebEngineView.AcceptRequest --> NavigationRequestAction" @@ -759,8 +805,10 @@ 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" << "QQuickWebEngineView.printToPdf(QJSValue) --> void" << "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId) --> void" << "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId,PrintedPageOrientation) --> void" @@ -880,6 +928,18 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineSettings.DisallowImageAnimation --> ImageAnimationPolicy" << "QQuickWebEngineSettings.imageAnimationPolicy --> QQuickWebEngineSettings::ImageAnimationPolicy" << "QQuickWebEngineSettings.imageAnimationPolicyChanged() --> void" + << "QWebEngineFrame.htmlName --> QString" + << "QWebEngineFrame.isMainFrame --> bool" + << "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" + << "QWebEngineFrame.runJavaScript(QString,uint,QJSValue) --> void" + << "QWebEngineFrame.size --> QSizeF" + << "QWebEngineFrame.url --> QUrl" ; static bool isCheckedEnum(QMetaType t) @@ -998,4 +1058,3 @@ void tst_publicapi::publicAPI() QTEST_MAIN(tst_publicapi) #include "tst_publicapi.moc" - diff --git a/tests/auto/quick/qmltests/data/tst_datalist.qml b/tests/auto/quick/qmltests/data/tst_datalist.qml index f739639b2..1e5a7ad6b 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/quick/qmltests/data/tst_geopermission.qml b/tests/auto/quick/qmltests/data/tst_geopermission.qml index b99e50acc..e425a82c7 100644 --- a/tests/auto/quick/qmltests/data/tst_geopermission.qml +++ b/tests/auto/quick/qmltests/data/tst_geopermission.qml @@ -13,20 +13,22 @@ TestWebEngineView { property bool deniedGeolocation: false property bool geoPermissionRequested: false + 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() } } } @@ -55,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() === "") } @@ -71,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 3b33b7abe..9a876778b 100644 --- a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml +++ b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml @@ -11,6 +11,7 @@ TestWebEngineView { height: 400 settings.screenCaptureEnabled: true + profile.persistentPermissionsPolicy: WebEngineProfile.NoPersistentPermissions TestCase { name: "GetUserMedia" @@ -21,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", @@ -42,7 +43,7 @@ TestWebEngineView { } } }, - feature: WebEngineView.DesktopVideoCapture, + feature: WebEnginePermission.DesktopVideoCapture, }, { tag: "desktop audio+video", @@ -58,7 +59,7 @@ TestWebEngineView { } } }, - feature: WebEngineView.DesktopAudioVideoCapture, + feature: WebEnginePermission.DesktopAudioVideoCapture, } ] } @@ -115,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 5d55e1201..5defbff4b 100644 --- a/tests/auto/quick/qmltests/data/tst_notification.qml +++ b/tests/auto/quick/qmltests/data/tst_notification.qml @@ -13,21 +13,26 @@ TestWebEngineView { property bool permissionRequested: false property bool grantPermission: false - property url securityOrigin: '' + property var permissionObject + + profile.persistentPermissionsPolicy: WebEngineProfile.NoPersistentPermissions signal consoleMessage(string message) 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() } } @@ -91,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/util/quickutil.h b/tests/auto/util/quickutil.h index 687cb94dc..eab38ed32 100644 --- a/tests/auto/util/quickutil.h +++ b/tests/auto/util/quickutil.h @@ -1,8 +1,8 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#ifndef UTIL_H -#define UTIL_H +#ifndef QUICKUTIL_H +#define QUICKUTIL_H #include <QEventLoop> #include <QQmlEngine> @@ -162,5 +162,5 @@ int main(int argc, char *argv[]) \ QTEST_SET_MAIN_SOURCE_PATH \ return QTest::qExec(&tc, argc, argv); \ } -#endif /* UTIL_H */ +#endif /* QUICKUTIL_H */ diff --git a/tests/auto/util/util.h b/tests/auto/util/util.h index 5533eed80..a3609fc0c 100644 --- a/tests/auto/util/util.h +++ b/tests/auto/util/util.h @@ -1,6 +1,9 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#ifndef UTIL_H +#define UTIL_H + // Functions and macros that really need to be in QTestLib #if 0 @@ -145,11 +148,28 @@ static inline QUrl baseUrlSync(QWebEnginePage *page) return spy.waitForResult().toUrl(); } -static inline bool loadSync(QWebEnginePage *page, const QUrl &url, bool ok = true) +static inline bool loadSync(QWebEnginePage *page, const QUrl &url, bool ok = true, + int timeout = 20000) { QSignalSpy spy(page, &QWebEnginePage::loadFinished); page->load(url); - return (!spy.empty() || spy.wait(20000)) && (spy.front().value(0).toBool() == ok); + return (!spy.empty() || spy.wait(timeout)) && (spy.front().value(0).toBool() == ok); +} + +static inline bool setHtmlSync(QWebEnginePage *page, const QString &html, + const QUrl &baseUrl = QUrl()) +{ + QSignalSpy spy(page, &QWebEnginePage::loadFinished); + page->setHtml(html, baseUrl); + return (!spy.empty() || spy.wait(20000)) && spy.front().value(0).toBool(); +} + +static inline bool webActionLoadSync(QWebEnginePage *page, QWebEnginePage::WebAction action, + bool ok = true, int timeout = 20000) +{ + QSignalSpy spy(page, &QWebEnginePage::loadFinished); + page->triggerAction(action); + return (!spy.empty() || spy.wait(timeout)) && (spy.front().value(0).toBool() == ok); } static inline QRect elementGeometry(QWebEnginePage *page, const QString &id) @@ -176,3 +196,5 @@ static inline QPoint elementCenter(QWebEnginePage *page, const QString &id) } #define W_QSKIP(a, b) QSKIP(a) + +#endif /* UTIL_H */ diff --git a/tests/auto/util/widgetutil.h b/tests/auto/util/widgetutil.h index 67d09ee4f..e6f955468 100644 --- a/tests/auto/util/widgetutil.h +++ b/tests/auto/util/widgetutil.h @@ -1,6 +1,9 @@ // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#ifndef WIDGETUTIL_H +#define WIDGETUTIL_H + // Functions and macros that really need to be in QTestLib #include "util.h" @@ -26,3 +29,5 @@ int main(int argc, char *argv[]) \ QTEST_SET_MAIN_SOURCE_PATH \ return QTest::qExec(&tc, argc, argv); \ } + +#endif /* WIDGETUTIL_H */ diff --git a/tests/auto/widgets/accessibility/tst_accessibility.cpp b/tests/auto/widgets/accessibility/tst_accessibility.cpp index 1579b61e2..0a65e7a95 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("<html><body>" \ "Hello world" \ "<input type='text' value='some text'></input>" \ "</body></html>"); 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/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST index 52def48d1..01d1ffe3d 100644 --- a/tests/auto/widgets/qwebenginepage/BLACKLIST +++ b/tests/auto/widgets/qwebenginepage/BLACKLIST @@ -13,3 +13,7 @@ macos [backgroundColor] macos + +[dynamicFrame] +ubuntu-22.04 + diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index f1d64776b..976a650ec 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -72,6 +72,7 @@ #include <qwebengineurlscheme.h> #include <qwebengineurlschemehandler.h> #include <qwebengineview.h> +#include <qwebenginepermission.h> #include <qimagewriter.h> #include <QColorSpace> #include <QQuickRenderControl> @@ -175,8 +176,7 @@ private Q_SLOTS: void requestQuota_data(); void requestQuota(); - - // Tests from tst_QWebEngineFrame + // Tests from pre-6.8 tst_QWebEngineFrame void symmetricUrl(); void progressSignal(); void urlChange(); @@ -451,12 +451,12 @@ public: 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: @@ -485,10 +485,11 @@ void tst_QWebEnginePage::geolocationRequestJS() QWebEngineView view; JSTestPage *newPage = new JSTestPage(&view); view.setPage(newPage); + 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("<html><body>test</body></html>"), QUrl("qrc://secure/origin")); @@ -1655,11 +1656,13 @@ public: 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; }); + profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); // We need to load content from a resource in order for the securityOrigin to be valid. load(QUrl("qrc:///resources/content.html")); } @@ -1693,18 +1696,20 @@ public: 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 @@ -1718,50 +1723,47 @@ public: } 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<QWebEnginePermission> m_permission; }; void tst_QWebEnginePage::getUserMediaRequest_data() { QTest::addColumn<QString>("call"); - QTest::addColumn<QWebEnginePage::Feature>("feature"); + QTest::addColumn<QWebEnginePermission::Feature>("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); @@ -1831,7 +1833,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<GetUserMediaTestPage> pages(10); // Desktop capture needs to be on a desktop @@ -1864,7 +1866,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 @@ -3793,20 +3795,32 @@ 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; + default: + break; + } + spyRequest.ref()(permission.origin()); }); load(QStringLiteral("qrc:///shared/notification.html")); @@ -3826,40 +3840,50 @@ public: void tst_QWebEnginePage::notificationPermission_data() { QTest::addColumn<bool>("setOnInit"); - QTest::addColumn<QWebEnginePage::PermissionPolicy>("policy"); + QTest::addColumn<QWebEnginePermission::State>("policy"); QTest::addColumn<QString>("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; + otr.setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); QWebEnginePage page(&otr, nullptr); 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(QUrl::RemoveFilename)) { - qWarning() << "Unexpected case. Can't proceed." << setOnInit << permissionRequested << o; + if (permissionRequested || permission.origin() != baseUrl.url(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); + 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("<html><body>Test</body></html>"), baseUrl); @@ -3868,7 +3892,10 @@ void tst_QWebEnginePage::notificationPermission() QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), setOnInit ? permission : QLatin1String("default")); if (!setOnInit) { - page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, policy); + if (policy == QWebEnginePermission::Granted) + permissionObject.grant(); + else + permissionObject.deny(); QTRY_COMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), permission); } @@ -3882,7 +3909,7 @@ void tst_QWebEnginePage::notificationPermission() void tst_QWebEnginePage::sendNotification() { - NotificationPage page(QWebEnginePage::PermissionGrantedByUser); + NotificationPage page(QWebEnginePermission::Granted); QVERIFY(page.spyLoad.waitForResult()); page.resetPermission(); @@ -3948,6 +3975,7 @@ void tst_QWebEnginePage::clipboardReadWritePermissionInitialState() QFETCH(QString, permission); QWebEngineProfile otr; + otr.setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); QWebEngineView view(&otr); QWebEnginePage &page = *view.page(); view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); @@ -3969,45 +3997,46 @@ void tst_QWebEnginePage::clipboardReadWritePermissionInitialState() void tst_QWebEnginePage::clipboardReadWritePermission_data() { QTest::addColumn<bool>("canAccessClipboard"); - QTest::addColumn<QWebEnginePage::PermissionPolicy>("initialPolicy"); + QTest::addColumn<QWebEnginePermission::State>("initialPolicy"); QTest::addColumn<QString>("initialPermission"); - QTest::addColumn<QWebEnginePage::PermissionPolicy>("requestPolicy"); + QTest::addColumn<QWebEnginePermission::State>("requestPolicy"); QTest::addColumn<QString>("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; + otr.setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); QWebEngineView view(&otr); QWebEnginePage &page = *view.page(); view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); @@ -4021,20 +4050,45 @@ 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(QUrl::RemoveFilename)) { - qWarning() << "Unexpected case. Can't proceed." << o; + if (permission.origin() != baseUrl.url(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); + 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("<html><body>Test</body></html>"), baseUrl); @@ -4094,30 +4148,35 @@ void tst_QWebEnginePage::contentsSize() void tst_QWebEnginePage::localFontAccessPermission_data() { - QTest::addColumn<QWebEnginePage::PermissionPolicy>("policy"); + QTest::addColumn<QWebEnginePermission::State>("policy"); QTest::addColumn<bool>("ignore"); QTest::addColumn<bool>("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); QWebEngineView view; QWebEnginePage page(&view); + 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); @@ -4141,9 +4200,6 @@ void tst_QWebEnginePage::localFontAccessPermission() { QTRY_VERIFY_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool() == true, 1000); QVERIFY((evaluateJavaScriptSync(&page, QStringLiteral("fonts.length")).toInt() == 0) == shouldBeEmpty); } - - // Reset permission, since otherwise it will be stored between runs - page.setFeaturePermission(QUrl("qrc:///resources/fontaccess.html"), QWebEnginePage::LocalFontsAccess, QWebEnginePage::PermissionUnknown); } void tst_QWebEnginePage::setLifecycleState() @@ -5721,6 +5777,7 @@ void tst_QWebEnginePage::chooseDesktopMedia() QWebEnginePage page; QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); + page.profile()->setPersistentPermissionsPolicy(QWebEngineProfile::NoPersistentPermissions); bool desktopMediaRequested = false; bool permissionRequested = false; @@ -5730,12 +5787,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 095d4c8f2..6245a6c7a 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -56,6 +56,11 @@ private Q_SLOTS: void changePersistentCookiesPolicy(); void initiator(); void badDeleteOrder(); + void permissionPersistence_data(); + void permissionPersistence(); + void getPermission_data(); + void getPermission(); + void listPermissions(); void qtbug_71895(); // this should be the last test }; @@ -188,6 +193,7 @@ void tst_QWebEngineProfile::clearDataFromCache() QVERIFY(server.start()); AutoDir cacheDir("./tst_QWebEngineProfile_clearDataFromCache"); + QVERIFY(!cacheDir.exists("Cache")); QWebEngineProfile profile(QStringLiteral("clearDataFromCache")); QSignalSpy cacheSpy(&profile, &QWebEngineProfile::clearHttpCacheCompleted); @@ -201,9 +207,14 @@ void tst_QWebEngineProfile::clearDataFromCache() QVERIFY(cacheDir.exists("Cache")); qint64 sizeBeforeClear = totalSize(cacheDir); + QCOMPARE_GT(sizeBeforeClear, 0); profile.clearHttpCache(); QTRY_COMPARE(cacheSpy.size(), 1); - QVERIFY(sizeBeforeClear > totalSize(cacheDir)); +#if defined(Q_OS_WIN) + QTRY_COMPARE_GT(sizeBeforeClear, totalSize(cacheDir)); +#else + QCOMPARE_GT(sizeBeforeClear, totalSize(cacheDir)); +#endif (void)server.stop(); } @@ -1009,6 +1020,187 @@ void tst_QWebEngineProfile::badDeleteOrder() delete view; } +void tst_QWebEngineProfile::permissionPersistence_data() +{ + QTest::addColumn<QWebEngineProfile::PersistentPermissionsPolicy>("policy"); + QTest::addColumn<bool>("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; +} + +void tst_QWebEngineProfile::permissionPersistence() +{ + QFETCH(QWebEngineProfile::PersistentPermissionsPolicy, policy); + QFETCH(bool, granted); + + TestServer server; + QVERIFY(server.start()); + + std::unique_ptr<QWebEngineProfile> profile(new QWebEngineProfile("tst_persistence")); + profile->setPersistentPermissionsPolicy(policy); + + std::unique_ptr<QWebEnginePage> page(new QWebEnginePage(profile.get())); + std::unique_ptr<QSignalSpy> loadSpy(new QSignalSpy(page.get(), &QWebEnginePage::loadFinished)); + QDir storageDir = QDir(profile->persistentStoragePath()); + + // Delete permissions file if it somehow survived on disk + storageDir.remove("permissions.json"); + + page->load(server.url("/hedgehog.html")); + QTRY_COMPARE(loadSpy->size(), 1); + + QVariant variant = granted ? "granted" : "denied"; + QVariant defaultVariant = "default"; + + QWebEnginePermission permissionObject = profile->getPermission(server.url("/hedgehog.html"), QWebEnginePermission::Notifications); + if (granted) + permissionObject.grant(); + else + permissionObject.deny(); + QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), variant); + + page.reset(); + profile.reset(); + loadSpy.reset(); + + bool expectSame = false; + if (policy == QWebEngineProfile::PersistentPermissionsOnDisk) { + expectSame = true; + + // File is written asynchronously, wait for it to be created + QTRY_COMPARE(storageDir.exists("permissions.json"), true); + } + + profile.reset(new QWebEngineProfile("tst_persistence")); + profile->setPersistentPermissionsPolicy(policy); + + page.reset(new QWebEnginePage(profile.get())); + loadSpy.reset(new QSignalSpy(page.get(), &QWebEnginePage::loadFinished)); + page->load(server.url("/hedgehog.html")); + QTRY_COMPARE(loadSpy->size(), 1); + QTRY_COMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), + expectSame ? variant : defaultVariant); + + // Re-acquire the permission, since deleting the Profile makes it invalid + permissionObject = profile->getPermission(server.url("/hedgehog.html"), QWebEnginePermission::Notifications); + permissionObject.reset(); + QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), defaultVariant); + + page.reset(); + profile.reset(); + loadSpy.reset(); + + if (policy == QWebEngineProfile::PersistentPermissionsOnDisk) { + // Wait for file to be written to before deleting + QTest::qWait(1000); + storageDir.remove("permissions.json"); + } + + QVERIFY(server.stop()); +} + +void tst_QWebEngineProfile::getPermission_data() +{ + QTest::addColumn<QWebEnginePermission::Feature>("feature"); + QTest::addColumn<QUrl>("url"); + QTest::addColumn<bool>("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<QWebEnginePermission> permissionsListAll = profile.listPermissions(); + QList<QWebEnginePermission> permissionsListUrl = profile.listPermissions(commonUrl); + QList<QWebEnginePermission> 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<QWebEnginePermission> 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; diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index f4ed06e14..03acd69fe 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); diff --git a/tests/manual/quick/geopermission/tst_geopermission.qml b/tests/manual/quick/geopermission/tst_geopermission.qml index 36317c176..ace48d464 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/quick/pdf/withdoc.qml b/tests/manual/quick/pdf/withdoc.qml index d4bf12e29..0a2a86630 100644 --- a/tests/manual/quick/pdf/withdoc.qml +++ b/tests/manual/quick/pdf/withdoc.qml @@ -19,6 +19,11 @@ Window { onPasswordRequired: function() { passwordDialog.open() } } + Component.onCompleted: { + if (Application.arguments.length > 2) + doc.source = Application.arguments[Application.arguments.length - 1] + } + FileDialog { id: fileDialog title: "Open a PDF file" @@ -85,6 +90,7 @@ Window { PdfPageImage { id: image document: doc + retainWhileLoading: true property real zoomFactor: Math.sqrt(2) diff --git a/tests/manual/widgets/geolocation/main.cpp b/tests/manual/widgets/geolocation/main.cpp index f33cf5798..1f4cefe54 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 328e4ae36..b5718159c 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) |