summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--REUSE.toml2
-rw-r--r--src/webenginequick/api/qquickwebengineprofile.h2
-rw-r--r--tests/auto/quick/qmltests/data/tst_getUserMedia.qml13
-rw-r--r--tests/auto/util/util.h7
-rw-r--r--tests/auto/widgets/CMakeLists.txt1
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp417
-rw-r--r--tests/auto/widgets/qwebenginepermission/CMakeLists.txt28
-rw-r--r--tests/auto/widgets/qwebenginepermission/resources/iframe.html5
-rw-r--r--tests/auto/widgets/qwebenginepermission/resources/index.html14
-rw-r--r--tests/auto/widgets/qwebenginepermission/resources/qt144.pngbin0 -> 8315 bytes
-rw-r--r--tests/auto/widgets/qwebenginepermission/tst_qwebenginepermission.cpp727
-rw-r--r--tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp191
12 files changed, 814 insertions, 593 deletions
diff --git a/REUSE.toml b/REUSE.toml
index 19f9b97b3..075c0b340 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -24,6 +24,7 @@ path = ["tests/auto/widgets/qwebenginepage/resources/*",
"tests/auto/widgets/qwebengineview/resources/*",
"tests/auto/widgets/qwebengineprofile/resources/*",
"tests/auto/widgets/qwebengineprofilebuilder/resources/*",
+ "tests/auto/widgets/qwebenginepermission/resources/*",
"tests/auto/widgets/qwebenginehistory/resources/*",
"tests/auto/core/certificateerror/resources/*",
"tests/auto/core/origins/resources/subdir/*",
@@ -121,4 +122,3 @@ precedence = "override"
comment = "License file."
SPDX-FileCopyrightText = "None"
SPDX-License-Identifier = "CC0-1.0"
-
diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h
index 899d431a1..0995538be 100644
--- a/src/webenginequick/api/qquickwebengineprofile.h
+++ b/src/webenginequick/api/qquickwebengineprofile.h
@@ -44,7 +44,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject {
Q_PROPERTY(bool isPushServiceEnabled READ isPushServiceEnabled WRITE setPushServiceEnabled NOTIFY pushServiceEnabledChanged FINAL REVISION(6,5))
Q_PROPERTY(QWebEngineClientHints *clientHints READ clientHints FINAL REVISION(6,8))
#if QT_CONFIG(webengine_extensions)
- Q_PROPERTY(QWebEngineExtensionManager *extensionManager READ extensionManager REVISION(6, 10))
+ Q_PROPERTY(QWebEngineExtensionManager *extensionManager READ extensionManager CONSTANT REVISION(6, 10))
#endif
QML_NAMED_ELEMENT(WebEngineProfile)
QML_ADDED_IN_VERSION(1, 1)
diff --git a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml
index ebb49f9df..a56584230 100644
--- a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml
+++ b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml
@@ -75,6 +75,9 @@ TestWebEngineView {
rejectPendingRequest()
tryVerify(jsPromiseRejected)
+ resetRequestState()
+ wait(1000)
+
// 2. Accepting request on QML side should either fulfill or reject the
// Promise on JS side. Due to the potential lack of physical media devices
// deeper in the content layer we cannot guarantee that the promise will
@@ -85,11 +88,16 @@ TestWebEngineView {
acceptPendingRequest()
tryVerify(jsPromiseSettled)
+ resetRequestState()
+ wait(1000)
+
// 3. Media feature permissions are not remembered.
jsGetUserMedia(row.constraints);
verifyPermissionType(row.feature)
acceptPendingRequest()
tryVerify(jsPromiseSettled)
+
+ resetRequestState()
}
}
@@ -158,10 +166,12 @@ TestWebEngineView {
function acceptPendingRequest() {
if (permissionObject)
permissionObject.grant()
- resetRequestState()
}
function resetRequestState() {
+ if (permissionObject)
+ permissionObject.reset()
+
permissionObject = undefined
isDesktopMediaRequestHandled = false
gotEmptyDesktopMediaRequest = false
@@ -170,7 +180,6 @@ TestWebEngineView {
function rejectPendingRequest() {
if (permissionObject)
permissionObject.deny()
- resetRequestState()
}
////
diff --git a/tests/auto/util/util.h b/tests/auto/util/util.h
index 65e7fb8b5..6dc420194 100644
--- a/tests/auto/util/util.h
+++ b/tests/auto/util/util.h
@@ -134,6 +134,13 @@ static inline QVariant evaluateJavaScriptSync(QWebEnginePage *page, const QStrin
return spy.waitForResult();
}
+static inline QVariant evaluateJavaScriptSync(QWebEngineFrame *frame, const QString &script)
+{
+ CallbackSpy<QVariant> spy;
+ frame->runJavaScript(script, spy.ref());
+ return spy.waitForResult();
+}
+
static inline QVariant evaluateJavaScriptSyncInWorld(QWebEnginePage *page, const QString &script, int worldId)
{
CallbackSpy<QVariant> spy;
diff --git a/tests/auto/widgets/CMakeLists.txt b/tests/auto/widgets/CMakeLists.txt
index e31ff2170..2195dd5e6 100644
--- a/tests/auto/widgets/CMakeLists.txt
+++ b/tests/auto/widgets/CMakeLists.txt
@@ -3,6 +3,7 @@
add_subdirectory(defaultsurfaceformat)
add_subdirectory(qwebenginepage)
+add_subdirectory(qwebenginepermission)
add_subdirectory(qwebengineprofile)
add_subdirectory(qwebengineprofilebuilder)
add_subdirectory(qwebengineview)
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 6df52dc61..10851580e 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -128,10 +128,6 @@ private Q_SLOTS:
void acceptNavigationRequestWithFormData();
void acceptNavigationRequestNavigationType();
void acceptNavigationRequestRelativeToNothing();
-#ifndef Q_OS_MACOS
- void geolocationRequestJS_data();
- void geolocationRequestJS();
-#endif
void loadFinished();
void actionStates();
void pasteImage();
@@ -240,16 +236,8 @@ private Q_SLOTS:
void triggerActionWithoutMenu();
void dynamicFrame();
- void notificationPermission_data();
- void notificationPermission();
void sendNotification();
- void clipboardReadWritePermissionInitialState_data();
- void clipboardReadWritePermissionInitialState();
- void clipboardReadWritePermission_data();
- void clipboardReadWritePermission();
void contentsSize();
- void localFontAccessPermission_data();
- void localFontAccessPermission();
void setLifecycleState();
void setVisible();
@@ -448,79 +436,6 @@ void tst_QWebEnginePage::acceptNavigationRequest()
QCOMPARE(toPlainTextSync(&page), QString("/foo?"));
}
-class JSTestPage : public QWebEnginePage
-{
-Q_OBJECT
-public:
- JSTestPage(QObject* parent = 0)
- : QWebEnginePage(parent) {}
-
- virtual bool shouldInterruptJavaScript()
- {
- return true;
- }
-public Q_SLOTS:
- void requestPermission(QWebEnginePermission permission)
- {
- if (m_allowGeolocation)
- permission.grant();
- else
- permission.deny();
- }
-
-public:
- void setGeolocationPermission(bool allow)
- {
- m_allowGeolocation = allow;
- }
-
-private:
- bool m_allowGeolocation;
-};
-
-#ifndef Q_OS_MACOS
-void tst_QWebEnginePage::geolocationRequestJS_data()
-{
- QTest::addColumn<bool>("allowed");
- QTest::addColumn<int>("errorCode");
- QTest::newRow("allowed") << true << 0;
- QTest::newRow("not allowed") << false << 1;
-}
-
-void tst_QWebEnginePage::geolocationRequestJS()
-{
- QFETCH(bool, allowed);
- QFETCH(int, errorCode);
- QWebEngineView view;
- JSTestPage *newPage = new JSTestPage(&view);
- view.setPage(newPage);
- newPage->profile()->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
- newPage->setGeolocationPermission(allowed);
-
- 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"));
- QTRY_COMPARE_WITH_TIMEOUT(spyLoadFinished.size(), 1, 20000);
-
- // Geolocation is only enabled for visible WebContents.
- view.show();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
-
- if (evaluateJavaScriptSync(newPage, QLatin1String("!navigator.geolocation")).toBool())
- QSKIP("Geolocation is not supported.");
-
- evaluateJavaScriptSync(newPage, "var errorCode = 0; var done = false; function error(err) { errorCode = err.code; done = true; } function success(pos) { done = true; } navigator.geolocation.getCurrentPosition(success, error)");
-
- QTRY_VERIFY(evaluateJavaScriptSync(newPage, "done").toBool());
- int result = evaluateJavaScriptSync(newPage, "errorCode").toInt();
- if (result == 2)
- QEXPECT_FAIL("", "No location service available.", Continue);
- QCOMPARE(result, errorCode);
-}
-#endif
-
void tst_QWebEnginePage::loadFinished()
{
QWebEnginePage page;
@@ -1784,14 +1699,21 @@ public:
{
if (m_permission)
m_permission->deny();
- resetRequestState();
}
void acceptPendingRequest()
{
if (m_permission)
m_permission->grant();
- resetRequestState();
+ }
+
+ void resetRequestState()
+ {
+ m_gotDesktopMediaRequest = false;
+ m_gotEmptyDesktopMediaRequest = false;
+ if (m_permission)
+ m_permission->reset();
+ m_permission.reset();
}
bool gotExpectedRequests(bool isDesktopPermission,
@@ -1828,13 +1750,6 @@ private Q_SLOTS:
}
private:
- void resetRequestState()
- {
- m_gotDesktopMediaRequest = false;
- m_gotEmptyDesktopMediaRequest = false;
- m_permission.reset();
- }
-
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel, const QString &message, int,
const QString &) override
{
@@ -1888,7 +1803,7 @@ void tst_QWebEnginePage::getUserMediaRequest()
QVERIFY(QTest::qWaitForWindowExposed(&view));
}
- QTRY_VERIFY_WITH_TIMEOUT(page.loadSucceeded(), 60000);
+ QTRY_VERIFY_WITH_TIMEOUT(page.loadSucceeded(), 10000);
page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
// 1. Rejecting request on C++ side should reject promise on JS side.
@@ -1897,6 +1812,9 @@ void tst_QWebEnginePage::getUserMediaRequest()
page.rejectPendingRequest();
QTRY_VERIFY(page.jsPromiseRejected());
+ page.resetRequestState();
+ QTest::qWait(1000);
+
// 2. Accepting request on C++ side should either fulfill or reject the
// Promise on JS side. Due to the potential lack of physical media devices
// deeper in the content layer we cannot guarantee that the promise will
@@ -1905,19 +1823,22 @@ void tst_QWebEnginePage::getUserMediaRequest()
page.jsGetMedia(call);
QTRY_VERIFY(page.gotExpectedRequests(isDesktopPermission, permissionType));
page.acceptPendingRequest();
- QTRY_VERIFY(page.jsPromiseSettled());
+ QTRY_VERIFY_WITH_TIMEOUT(page.jsPromiseSettled(), 10000);
+
+ page.resetRequestState();
+ QTest::qWait(1000);
// 3. Media permissions are not remembered.
page.jsGetMedia(call);
QTRY_VERIFY(page.gotExpectedRequests(isDesktopPermission, permissionType));
page.acceptPendingRequest();
- QTRY_VERIFY(page.jsPromiseSettled());
+ QTRY_VERIFY_WITH_TIMEOUT(page.jsPromiseSettled(), 10000);
}
void tst_QWebEnginePage::getUserMediaRequestDesktopAudio()
{
GetUserMediaTestPage page;
- QTRY_VERIFY_WITH_TIMEOUT(page.loadSucceeded(), 20000);
+ QTRY_VERIFY_WITH_TIMEOUT(page.loadSucceeded(), 10000);
page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
// Audio-only desktop capture is not supported. JS Promise should be
@@ -3848,76 +3769,6 @@ public:
}
};
-void tst_QWebEnginePage::notificationPermission_data()
-{
- QTest::addColumn<bool>("setOnInit");
- QTest::addColumn<QWebEnginePermission::State>("policy");
- QTest::addColumn<QString>("permission");
- 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()
-{
- QFETCH(bool, setOnInit);
- QFETCH(QWebEnginePermission::State, policy);
- QFETCH(QString, permission);
-
- QWebEngineProfile otr;
- 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.permissionType() != QWebEnginePermission::PermissionType::Notifications)
- return;
- if (permissionRequested || permission.origin() != baseUrl.url(QUrl::RemoveFilename)) {
- qWarning() << "Unexpected case. Can't proceed." << setOnInit << permissionRequested << permission.origin();
- errorState = true;
- return;
- }
- permissionRequested = true;
-
- if (policy == QWebEnginePermission::State::Granted)
- permission.grant();
- else
- permission.deny();
- });
-
- QWebEnginePermission permissionObject = otr.queryPermission(baseUrl, QWebEnginePermission::PermissionType::Notifications);
- if (setOnInit) {
- if (policy == QWebEnginePermission::State::Granted)
- permissionObject.grant();
- else
- permissionObject.deny();
- }
-
- QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
- page.setHtml(QString("<html><body>Test</body></html>"), baseUrl);
- QTRY_COMPARE(spy.size(), 1);
-
- QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), setOnInit ? permission : QLatin1String("default"));
-
- if (!setOnInit) {
- if (policy == QWebEnginePermission::State::Granted)
- permissionObject.grant();
- else
- permissionObject.deny();
- QTRY_COMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), permission);
- }
-
- auto js = QStringLiteral("var permission; Notification.requestPermission().then(p => { permission = p })");
- evaluateJavaScriptSync(&page, js);
- QTRY_COMPARE(evaluateJavaScriptSync(&page, "permission").toString(), permission);
- // permission is not 'remembered' from api standpoint, hence is not suppressed on explicit call from JS
- QVERIFY(permissionRequested);
- QVERIFY(!errorState);
-}
-
void tst_QWebEnginePage::sendNotification()
{
NotificationPage page(QWebEnginePermission::State::Granted);
@@ -3958,180 +3809,6 @@ void tst_QWebEnginePage::sendNotification()
QTRY_VERIFY2(page.messages.contains("onclose"), page.messages.join("\n").toLatin1().constData());
}
-static QString clipboardPermissionQuery(QString variableName, QString permissionName)
-{
- return QString("var %1; navigator.permissions.query({ name:'%2' }).then((p) => { %1 = p.state; "
- "});")
- .arg(variableName)
- .arg(permissionName);
-}
-
-
-void tst_QWebEnginePage::clipboardReadWritePermissionInitialState_data()
-{
- QTest::addColumn<bool>("canAccessClipboard");
- QTest::addColumn<bool>("canPaste");
- QTest::addColumn<QString>("readPermission");
- QTest::addColumn<QString>("writePermission");
- QTest::newRow("access and paste should grant both") << true << true << "granted" << "granted";
- QTest::newRow("paste only should prompt for both") << false << true << "prompt" << "prompt";
- QTest::newRow("access only should grant for write only")
- << true << false << "prompt" << "granted";
- QTest::newRow("no access or paste should prompt for both")
- << false << false << "prompt" << "prompt";
-}
-
-void tst_QWebEnginePage::clipboardReadWritePermissionInitialState()
-{
- QFETCH(bool, canAccessClipboard);
- QFETCH(bool, canPaste);
- QFETCH(QString, readPermission);
- QFETCH(QString, writePermission);
-
- QWebEngineProfile otr;
- otr.setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
- QWebEngineView view(&otr);
- QWebEnginePage &page = *view.page();
- view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
- page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard,
- canAccessClipboard);
- page.settings()->setAttribute(QWebEngineSettings::JavascriptCanPaste, canPaste);
-
- QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
- QUrl baseUrl("https://www.example.com/somepage.html");
- page.setHtml(QString("<html><body>Test</body></html>"), baseUrl);
- QTRY_COMPARE(spy.size(), 1);
-
- evaluateJavaScriptSync(&page, clipboardPermissionQuery("readPermission", "clipboard-read"));
- QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("readPermission")), readPermission);
- evaluateJavaScriptSync(&page, clipboardPermissionQuery("writePermission", "clipboard-write"));
- QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("writePermission")), writePermission);
-}
-
-void tst_QWebEnginePage::clipboardReadWritePermission_data()
-{
- QTest::addColumn<bool>("canAccessClipboard");
- QTest::addColumn<QWebEnginePermission::State>("initialPolicy");
- QTest::addColumn<QString>("initialPermission");
- QTest::addColumn<QWebEnginePermission::State>("requestPolicy");
- QTest::addColumn<QString>("finalPermission");
-
- QTest::newRow("noAccessGrantGrant")
- << false << QWebEnginePermission::State::Granted << "granted"
- << QWebEnginePermission::State::Granted << "granted";
- QTest::newRow("noAccessGrantDeny")
- << false << QWebEnginePermission::State::Granted << "granted"
- << QWebEnginePermission::State::Denied << "denied";
- QTest::newRow("noAccessDenyGrant")
- << 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::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()
-{
- QFETCH(bool, canAccessClipboard);
- QFETCH(QWebEnginePermission::State, initialPolicy);
- QFETCH(QString, initialPermission);
- QFETCH(QWebEnginePermission::State, requestPolicy);
- QFETCH(QString, finalPermission);
-
- QWebEngineProfile otr;
- otr.setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
- QWebEngineView view(&otr);
- QWebEnginePage &page = *view.page();
- view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
- page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard,
- canAccessClipboard);
- page.settings()->setAttribute(QWebEngineSettings::JavascriptCanPaste, true);
-
- QUrl baseUrl("https://www.example.com/somepage.html");
-
- int permissionRequestCount = 0;
- bool errorState = false;
-
- // if JavascriptCanAccessClipboard is true, this never fires
- connect(&page, &QWebEnginePage::permissionRequested, &page,
- [&](QWebEnginePermission permission) {
- if (permission.permissionType() != QWebEnginePermission::PermissionType::ClipboardReadWrite)
- return;
- if (permission.origin() != baseUrl.url(QUrl::RemoveFilename)) {
- qWarning() << "Unexpected case. Can't proceed." << permission.origin();
- errorState = true;
- return;
- }
- permissionRequestCount++;
- switch (requestPolicy) {
- case QWebEnginePermission::State::Granted:
- permission.grant();
- break;
- case QWebEnginePermission::State::Denied:
- permission.deny();
- break;
- case QWebEnginePermission::State::Ask:
- permission.reset();
- break;
- default:
- break;
- }
- });
-
- QWebEnginePermission permissionObject = otr.queryPermission(baseUrl, QWebEnginePermission::PermissionType::ClipboardReadWrite);
- switch (initialPolicy) {
- case QWebEnginePermission::State::Granted:
- permissionObject.grant();
- break;
- case QWebEnginePermission::State::Denied:
- permissionObject.deny();
- break;
- case QWebEnginePermission::State::Ask:
- permissionObject.reset();
- break;
- case QWebEnginePermission::State::Invalid:
- break;
- }
-
- QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
- page.setHtml(QString("<html><body>Test</body></html>"), baseUrl);
- QTRY_COMPARE(spy.size(), 1);
-
- evaluateJavaScriptSync(&page, clipboardPermissionQuery("readPermission", "clipboard-read"));
- QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("readPermission")), initialPermission);
- evaluateJavaScriptSync(&page, clipboardPermissionQuery("writePermission", "clipboard-write"));
- QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("writePermission")), initialPermission);
-
- auto triggerRequest = [&page](QString variableName, QString apiCall)
- {
- auto js = QString("var %1; navigator.clipboard.%2.then((v) => { %1 = 'granted' }, (v) => { %1 = "
- "'denied' });")
- .arg(variableName)
- .arg(apiCall);
- evaluateJavaScriptSync(&page, js);
- };
-
- // permission is not 'remembered' from api standpoint, hence is not suppressed on explicit call
- // from JS
- triggerRequest("readState", "readText()");
- QTRY_COMPARE(evaluateJavaScriptSync(&page, "readState"), finalPermission);
- triggerRequest("writeState", "writeText('foo')");
- QTRY_COMPARE(evaluateJavaScriptSync(&page, "writeState"), finalPermission);
- QCOMPARE(permissionRequestCount, canAccessClipboard ? 0 : 2);
- QVERIFY(!errorState);
-}
-
void tst_QWebEnginePage::contentsSize()
{
m_view->resize(800, 600);
@@ -4160,62 +3837,6 @@ void tst_QWebEnginePage::contentsSize()
QCOMPARE(m_page->contentsSize().height(), 1216);
}
-void tst_QWebEnginePage::localFontAccessPermission_data()
-{
- QTest::addColumn<QWebEnginePermission::State>("policy");
- QTest::addColumn<bool>("ignore");
- QTest::addColumn<bool>("shouldBeEmpty");
-
- 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() {
- QFETCH(QWebEnginePermission::State, policy);
- QFETCH(bool, ignore);
- QFETCH(bool, shouldBeEmpty);
-
- QWebEngineView view;
- QWebEnginePage page(&view);
- page.profile()->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
- view.setPage(&page);
-
- connect(&page, &QWebEnginePage::permissionRequested, &page, [&] (QWebEnginePermission permission) {
- if (permission.permissionType() != QWebEnginePermission::PermissionType::LocalFontsAccess)
- return;
-
- if (!ignore) {
- if (policy == QWebEnginePermission::State::Granted)
- permission.grant();
- else
- permission.deny();
- }
- });
-
- QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
- page.load(QUrl("qrc:///resources/fontaccess.html"));
- QTRY_COMPARE(spy.size(), 1);
-
- // Font access is only enabled for visible WebContents.
- view.show();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
-
- if (evaluateJavaScriptSync(&page, QStringLiteral("!window.queryLocalFonts")).toBool())
- QSKIP("Local fonts access is not supported.");
-
- // Access to the API requires recent user interaction
- QTest::keyPress(view.focusProxy(), Qt::Key_Space);
- QTRY_COMPARE(evaluateJavaScriptSync(&page, QStringLiteral("activated")).toBool(), true);
-
- if (ignore) {
- QTRY_COMPARE_NE_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool(), true, 1000);
- } else {
- QTRY_VERIFY_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool() == true, 1000);
- QVERIFY((evaluateJavaScriptSync(&page, QStringLiteral("fonts.length")).toInt() == 0) == shouldBeEmpty);
- }
-}
-
void tst_QWebEnginePage::setLifecycleState()
{
qRegisterMetaType<QWebEnginePage::LifecycleState>("LifecycleState");
diff --git a/tests/auto/widgets/qwebenginepermission/CMakeLists.txt b/tests/auto/widgets/qwebenginepermission/CMakeLists.txt
new file mode 100644
index 000000000..d6092c8c5
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepermission/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+include(../../util/util.cmake)
+
+qt_internal_add_test(tst_qwebenginepermission
+ SOURCES
+ tst_qwebenginepermission.cpp
+ LIBRARIES
+ Qt::WebEngineCore
+ Qt::WebEngineWidgets
+ Qt::WebEngineCorePrivate
+ Qt::CorePrivate
+ Test::Util
+)
+
+set(tst_qwebenginepermission_resource_files
+ "resources/index.html"
+ "resources/iframe.html"
+ "resources/qt144.png"
+)
+
+qt_internal_add_resource(tst_qwebenginepermission "tst_qwebenginepermission"
+ PREFIX
+ "/"
+ FILES
+ ${tst_qwebenginepermission_resource_files}
+)
diff --git a/tests/auto/widgets/qwebenginepermission/resources/iframe.html b/tests/auto/widgets/qwebenginepermission/resources/iframe.html
new file mode 100644
index 000000000..483800cd6
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepermission/resources/iframe.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ <iframe name="frame" allow="camera; microphone; display-capture; geolocation; local-fonts; clipboard-read; clipboard-write;" src="qrc:///resources/index.html" width="400" height="400"></iframe>
+</body>
+</html>
diff --git a/tests/auto/widgets/qwebenginepermission/resources/index.html b/tests/auto/widgets/qwebenginepermission/resources/index.html
new file mode 100644
index 000000000..6150a2bd9
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepermission/resources/index.html
@@ -0,0 +1,14 @@
+<html>
+<body onclick='onClick()'>
+<script>
+var triggerFunc = undefined;
+var testFunc = undefined;
+var done = false;
+var skipReason = undefined;
+var data = undefined;
+function onClick() {
+ triggerFunc();
+}
+</script>
+</body>
+</html>
diff --git a/tests/auto/widgets/qwebenginepermission/resources/qt144.png b/tests/auto/widgets/qwebenginepermission/resources/qt144.png
new file mode 100644
index 000000000..050b1e066
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepermission/resources/qt144.png
Binary files differ
diff --git a/tests/auto/widgets/qwebenginepermission/tst_qwebenginepermission.cpp b/tests/auto/widgets/qwebenginepermission/tst_qwebenginepermission.cpp
new file mode 100644
index 000000000..bfc70557e
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepermission/tst_qwebenginepermission.cpp
@@ -0,0 +1,727 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <util.h>
+
+#include <QtTest/QtTest>
+#include <QDir>
+#include <QStringLiteral>
+#include <QWebEngineDesktopMediaRequest>
+#include <QWebEngineFrame>
+#include <QWebEnginePage>
+#include <QWebEnginePermission>
+#include <QWebEngineProfile>
+#include <QWebEngineSettings>
+#include <QWebEngineView>
+
+using namespace Qt::StringLiterals;
+
+class tst_QWebEnginePermission : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWebEnginePermission();
+ ~tst_QWebEnginePermission();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void triggerFromJavascript_data();
+ void triggerFromJavascript();
+ void preGrant_data();
+ void preGrant();
+ void iframe_data();
+ void iframe();
+
+ void permissionPersistence_data();
+ void permissionPersistence();
+
+ void queryPermission_data();
+ void queryPermission();
+ void listPermissions();
+
+ void clipboardReadWritePermissionInitialState_data();
+ void clipboardReadWritePermissionInitialState();
+ void clipboardReadWritePermission_data();
+ void clipboardReadWritePermission();
+
+private:
+ std::unique_ptr<QWebEngineProfile> m_profile;
+ QString m_profileName;
+};
+
+tst_QWebEnginePermission::tst_QWebEnginePermission()
+ : m_profileName("tst_QWebEnginePermission")
+{
+}
+
+tst_QWebEnginePermission::~tst_QWebEnginePermission()
+{
+}
+
+void tst_QWebEnginePermission::initTestCase()
+{
+}
+
+void tst_QWebEnginePermission::cleanupTestCase()
+{
+}
+
+void tst_QWebEnginePermission::init()
+{
+ m_profile.reset(new QWebEngineProfile("tst_QWebEnginePermission"));
+}
+
+void tst_QWebEnginePermission::cleanup()
+{
+ if (m_profile && m_profile->persistentPermissionsPolicy()
+ == QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk) {
+ QDir dir(m_profile->persistentStoragePath());
+ dir.remove("permissions.json");
+
+ // Set a persistent permission to force the creation of a permission.json
+ // in test cases where it wouldn't be created otherwise
+ m_profile->queryPermission(QUrl("https://google.com"),
+ QWebEnginePermission::PermissionType::Notifications).grant();
+
+ // This will trigger the writing of permissions to disk
+ m_profile.reset();
+
+ // Wait for the new permissions.json to be written to disk before deleting
+ QTRY_VERIFY_WITH_TIMEOUT(dir.exists("permissions.json"), 5000);
+ dir.remove("permissions.json");
+ } else {
+ m_profile.reset();
+ }
+}
+
+static QString MediaAudioCapture_trigger =
+ "navigator.mediaDevices.getUserMedia({ video: false, audio: true }).then(s => { data = s; done = true; })"
+ ".catch(err => { skipReason = err.message; done = true; });"_L1;
+static QString MediaAudioCapture_check =
+ "return data != undefined;"_L1;
+
+static QString MediaVideoCapture_trigger =
+ "navigator.mediaDevices.getUserMedia({ video: true, audio: false }).then(s => { data = s; done = true; })"
+ ".catch(err => { skipReason = err.message; done = true; });"_L1;
+static QString MediaVideoCapture_check =
+ "return data != undefined;"_L1;
+
+static QString MediaAudioVideoCapture_trigger =
+ "navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(s => { data = s; done = true; })"
+ ".catch(err => { skipReason = err.message; done = true; });"_L1;
+static QString MediaAudioVideoCapture_check =
+ "return data != undefined;"_L1;
+
+static QString DesktopVideoCapture_trigger =
+ "navigator.mediaDevices.getDisplayMedia({ video: true, audio: false }).then(s => { data = s; done = true; })"
+ ".catch(err => { skipReason = err.message; done = true; });"_L1;
+static QString DesktopVideoCapture_check =
+ "return data != undefined;"_L1;
+
+static QString DesktopAudioVideoCapture_trigger =
+ "navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }).then(s => { data = s; done = true; })"
+ ".catch(err => { skipReason = err.message; done = true; });"_L1;
+static QString DesktopAudioVideoCapture_check =
+ "return data != undefined;"_L1;
+
+static QString MouseLock_trigger =
+ "document.documentElement.requestPointerLock().then(() => { data = document.pointerLockElement(); done = true; }).catch(() => { done = true; });"_L1;
+static QString MouseLock_check =
+ "var ret = (data != undefined); document.exitPointerLock(); return ret;"_L1;
+
+static QString Notifications_trigger =
+ "Notification.requestPermission().then(p => { data = p; done = true; }).catch(() => { done = true; });"_L1;
+static QString Notifications_check =
+ "return data != undefined && Notification.permission === 'granted';"_L1;
+
+static QString Geolocation_trigger =
+ "success = function(p) { data = p; done = true; };"
+ "failure = function(err) { if (err.code === 2) skipReason = 'Positioning is unavailable'; done = true; };"
+ "navigator.geolocation.getCurrentPosition(success, failure);"_L1;
+static QString Geolocation_check =
+ "return data != undefined;"_L1;
+
+static QString ClipboardReadWrite_trigger =
+ "navigator.clipboard.readText().then(c => { data = c; done = true; }).catch(() => { done = true; });"_L1;
+static QString ClipboardReadWrite_check =
+ "return data != undefined;"_L1;
+
+static QString LocalFontsAccess_trigger =
+ "if (!window.queryLocalFonts) { skipReason = 'Local fonts access is not supported on this system'; done = true; }"
+ "else { window.queryLocalFonts().then(f => { data = f; done = true; }); };"_L1;
+static QString LocalFontsAccess_check =
+ "return data.length != 0;"_L1;
+
+static void commonTestData()
+{
+ QTest::addColumn<QWebEnginePermission::PermissionType>("permissionType");
+ QTest::addColumn<QString>("triggerFunction");
+ QTest::addColumn<QString>("testFunction");
+ QTest::addColumn<QWebEngineProfile::PersistentPermissionsPolicy>("policy");
+
+#define QWebEnginePermissionTestCase(pt) \
+ QTest::newRow(#pt "_AskEveryTime") \
+ << QWebEnginePermission::PermissionType::pt \
+ << pt ## _trigger << pt ## _check \
+ << QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime; \
+ QTest::newRow(#pt "_StoreInMemory") \
+ << QWebEnginePermission::PermissionType::pt \
+ << pt ## _trigger << pt ## _check \
+ << QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory; \
+ QTest::newRow(#pt "_StoreOnDisk") \
+ << QWebEnginePermission::PermissionType::pt \
+ << pt ## _trigger << pt ## _check \
+ << QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk;
+
+ QWebEnginePermissionTestCase(MediaAudioCapture);
+
+ // Video capture tests don't work with offscreen
+ if (QGuiApplication::platformName() != QLatin1String("offscreen")) {
+ QWebEnginePermissionTestCase(MediaVideoCapture);
+ QWebEnginePermissionTestCase(MediaAudioVideoCapture);
+ QWebEnginePermissionTestCase(DesktopVideoCapture);
+ QWebEnginePermissionTestCase(DesktopAudioVideoCapture);
+ }
+ // QWebEnginePermissionTestCase(MouseLock); // currently untestable
+ QWebEnginePermissionTestCase(Notifications);
+#ifndef Q_OS_MACOS
+ QWebEnginePermissionTestCase(Geolocation);
+#endif
+ QWebEnginePermissionTestCase(ClipboardReadWrite);
+ QWebEnginePermissionTestCase(LocalFontsAccess);
+
+#undef QWebEnginePermissionTestCase
+}
+
+void tst_QWebEnginePermission::triggerFromJavascript_data()
+{
+ commonTestData();
+}
+
+void tst_QWebEnginePermission::triggerFromJavascript()
+{
+ QFETCH(QWebEnginePermission::PermissionType, permissionType);
+ QFETCH(QString, triggerFunction);
+ QFETCH(QString, testFunction);
+ QFETCH(QWebEngineProfile::PersistentPermissionsPolicy, policy);
+
+ QWebEngineView view;
+ QWebEnginePage page(m_profile.get(), &view);
+ m_profile->setPersistentPermissionsPolicy(policy);
+ view.setPage(&page);
+
+ page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, true);
+ connect(&page, &QWebEnginePage::desktopMediaRequested, &page, [&](const QWebEngineDesktopMediaRequest &request) {
+ request.selectScreen(request.screensModel()->index(0));
+ });
+
+ bool grant = true;
+ QWebEnginePermission permission;
+ connect(&page, &QWebEnginePage::permissionRequested, &page, [&](QWebEnginePermission p) {
+ QCOMPARE(p.permissionType(), permissionType);
+ grant ? p.grant() : p.deny();
+ permission = p;
+ });
+
+ QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
+ page.load(QUrl("qrc:///resources/index.html"));
+ QTRY_COMPARE(spy.size(), 1);
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ evaluateJavaScriptSync(&page, "triggerFunc = function() {"_L1 + triggerFunction + "}"_L1);
+ evaluateJavaScriptSync(&page, "testFunc = function() {"_L1 + testFunction + "done = true;" + "}"_L1);
+
+ // Access to some pf the APIs requires recent user interaction
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, QPoint{100, 100});
+
+ QTRY_VERIFY_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool(), 5000);
+ if (evaluateJavaScriptSync(&page, QStringLiteral("skipReason")).toBool()) {
+ // Catch expected failures and skip test
+ QSKIP(("Skipping test. Reason: " + evaluateJavaScriptSync(&page, QStringLiteral("skipReason")).toString()).toStdString().c_str());
+ }
+ qWarning() << evaluateJavaScriptSync(&page, QStringLiteral("data"));
+
+ QVERIFY(evaluateJavaScriptSync(&page, QStringLiteral("testFunc()")).toBool());
+ QCOMPARE(permission.state(), QWebEnginePermission::State::Granted);
+
+ // Now reset the permission, and try denying it
+ permission.reset();
+ QCOMPARE(permission.state(), QWebEnginePermission::State::Ask);
+ evaluateJavaScriptSync(&page, "done = false; data = undefined"_L1);
+ grant = false;
+
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, QPoint{100, 100});
+
+ QTRY_VERIFY_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool(), 5000);
+ QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("testFunc()")).toBool(), false);
+ QCOMPARE(permission.state(), QWebEnginePermission::State::Denied);
+}
+
+void tst_QWebEnginePermission::preGrant_data()
+{
+ commonTestData();
+}
+
+void tst_QWebEnginePermission::preGrant()
+{
+ QFETCH(QWebEnginePermission::PermissionType, permissionType);
+ QFETCH(QString, triggerFunction);
+ QFETCH(QString, testFunction);
+ QFETCH(QWebEngineProfile::PersistentPermissionsPolicy, policy);
+
+ QWebEngineView view;
+ QWebEnginePage page(m_profile.get(), &view);
+ m_profile->setPersistentPermissionsPolicy(policy);
+ view.setPage(&page);
+
+ QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished);
+ page.load(QUrl("qrc:///resources/index.html"));
+ QTRY_COMPARE(loadSpy.size(), 1);
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, true);
+ connect(&page, &QWebEnginePage::desktopMediaRequested, &page, [&](const QWebEngineDesktopMediaRequest &request) {
+ request.selectScreen(request.screensModel()->index(0));
+ });
+
+ QWebEnginePermission permission = m_profile->queryPermission(page.url(), permissionType);
+ QVERIFY(permission.state() == QWebEnginePermission::State::Ask);
+ permission.grant();
+
+ evaluateJavaScriptSync(&page, "triggerFunc = function() {"_L1 + triggerFunction + "}"_L1);
+ evaluateJavaScriptSync(&page, "testFunc = function() {"_L1 + testFunction + "done = true;" + "}"_L1);
+
+ QSignalSpy spy(&page, &QWebEnginePage::permissionRequested);
+
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, QPoint{100, 100});
+ QTRY_VERIFY_WITH_TIMEOUT(evaluateJavaScriptSync(&page, QStringLiteral("done")).toBool(), 5000);
+ if (evaluateJavaScriptSync(&page, QStringLiteral("skipReason")).toBool()) {
+ // No media devices, or no geolocation plugin
+ QSKIP(("Skipping test. Reason: " + evaluateJavaScriptSync(&page, QStringLiteral("skipReason")).toString()).toStdString().c_str());
+ }
+ QVERIFY(evaluateJavaScriptSync(&page, QStringLiteral("testFunc()")).toBool());
+
+ // The permissionRequested signal must NOT fire
+ QCOMPARE(spy.size(), 0);
+}
+
+void tst_QWebEnginePermission::iframe_data()
+{
+ commonTestData();
+}
+
+void tst_QWebEnginePermission::iframe()
+{
+ QFETCH(QWebEnginePermission::PermissionType, permissionType);
+ QFETCH(QString, triggerFunction);
+ QFETCH(QString, testFunction);
+ QFETCH(QWebEngineProfile::PersistentPermissionsPolicy, policy);
+
+ QWebEngineView view;
+ QWebEnginePage page(m_profile.get(), &view);
+ m_profile->setPersistentPermissionsPolicy(policy);
+ view.setPage(&page);
+
+ page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, true);
+ connect(&page, &QWebEnginePage::desktopMediaRequested, &page, [&](const QWebEngineDesktopMediaRequest &request) {
+ request.selectScreen(request.screensModel()->index(0));
+ });
+
+ bool grant = true;
+ QWebEnginePermission permission;
+ connect(&page, &QWebEnginePage::permissionRequested, &page, [&](QWebEnginePermission p) {
+ grant ? p.grant() : p.deny();
+ permission = p;
+ });
+
+ QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished);
+ page.load(QUrl("qrc:///resources/iframe.html"));
+ QTRY_COMPARE(loadSpy.size(), 1);
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ auto maybeFrame = page.findFrameByName("frame");
+ QVERIFY(maybeFrame);
+ QWebEngineFrame &frame = maybeFrame.value();
+
+ evaluateJavaScriptSync(&frame, "triggerFunc = function() {"_L1 + triggerFunction + "}"_L1);
+ evaluateJavaScriptSync(&frame, "testFunc = function() {"_L1 + testFunction + "done = true;" + "}"_L1);
+
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, QPoint{100, 100});
+
+ QTRY_VERIFY_WITH_TIMEOUT(evaluateJavaScriptSync(&frame, QStringLiteral("done")).toBool(), 10000);
+ if (evaluateJavaScriptSync(&frame, QStringLiteral("skipReason")).toBool()) {
+ // Catch expected failures and skip test
+ QSKIP(("Skipping test. Reason: " + evaluateJavaScriptSync(&frame, QStringLiteral("skipReason")).toString()).toStdString().c_str());
+ }
+
+ QVERIFY(evaluateJavaScriptSync(&frame, QStringLiteral("testFunc()")).toBool());
+ QCOMPARE(permission.state(), QWebEnginePermission::State::Granted);
+
+ // Now reset the permission, and try denying it
+ permission.reset();
+ QCOMPARE(permission.state(), QWebEnginePermission::State::Ask);
+ evaluateJavaScriptSync(&frame, "done = false; data = undefined"_L1);
+ grant = false;
+
+ // Only test non-persistent permissions past this point
+ if (QWebEnginePermission::isPersistent(permissionType)
+ && policy != QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime)
+ return;
+
+ // Perform a cross-origin navigation and then go back to check if the permission has been cleared
+ // We don't need a valid URL to trigger the cross-origin logic.
+ evaluateJavaScriptSync(&page, "document.getElementsByName('frame')[0].src = 'http://bad-url.bad-url'"_L1);
+ QTRY_VERIFY_WITH_TIMEOUT(frame.url() != QUrl("qrc:///resources/index.html"_L1), 10000);
+ evaluateJavaScriptSync(&page, "document.getElementsByName('frame')[0].src = 'qrc:///resources/index.html'"_L1);
+ QTRY_VERIFY_WITH_TIMEOUT(frame.url() == QUrl("qrc:///resources/index.html"_L1), 10000);
+
+ QCOMPARE(permission.state(), QWebEnginePermission::State::Ask);
+}
+
+void tst_QWebEnginePermission::permissionPersistence_data()
+{
+ QTest::addColumn<QWebEngineProfile::PersistentPermissionsPolicy>("policy");
+ QTest::addColumn<bool>("granted");
+
+ QTest::newRow("noPersistenceDeny") << QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime << false;
+ QTest::newRow("noPersistenceGrant") << QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime << true;
+ QTest::newRow("memoryPersistenceDeny") << QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory << false;
+ QTest::newRow("memoryPersistenceGrant") << QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory << true;
+ QTest::newRow("diskPersistenceDeny") << QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk << false;
+ QTest::newRow("diskPersistenceGrant") << QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk << true;
+}
+
+void tst_QWebEnginePermission::permissionPersistence()
+{
+ QFETCH(QWebEngineProfile::PersistentPermissionsPolicy, policy);
+ QFETCH(bool, granted);
+
+ m_profile->setPersistentPermissionsPolicy(policy);
+
+ std::unique_ptr<QWebEnginePage> page(new QWebEnginePage(m_profile.get()));
+ std::unique_ptr<QSignalSpy> loadSpy(new QSignalSpy(page.get(), &QWebEnginePage::loadFinished));
+ QDir storageDir = QDir(m_profile->persistentStoragePath());
+
+ page->load(QUrl("qrc:///resources/index.html"_L1));
+ QTRY_COMPARE(loadSpy->size(), 1);
+
+ QVariant variant = granted ? "granted" : "denied";
+ QVariant defaultVariant = "default";
+
+ QWebEnginePermission permissionObject = m_profile->queryPermission(
+ QUrl("qrc:///resources/index.html"_L1), QWebEnginePermission::PermissionType::Notifications);
+ if (granted)
+ permissionObject.grant();
+ else
+ permissionObject.deny();
+ QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), variant);
+
+ page.reset();
+ m_profile.reset();
+ loadSpy.reset();
+
+ bool expectSame = false;
+ if (policy == QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk) {
+ expectSame = true;
+
+ // File is written asynchronously, wait for it to be created
+ QTRY_COMPARE(storageDir.exists("permissions.json"), true);
+ }
+
+ m_profile.reset(new QWebEngineProfile(m_profileName));
+ m_profile->setPersistentPermissionsPolicy(policy);
+
+ page.reset(new QWebEnginePage(m_profile.get()));
+ loadSpy.reset(new QSignalSpy(page.get(), &QWebEnginePage::loadFinished));
+ page->load(QUrl("qrc:///resources/index.html"_L1));
+ 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 = m_profile->queryPermission(QUrl("qrc:///resources/index.html"_L1), QWebEnginePermission::PermissionType::Notifications);
+ permissionObject.reset();
+ QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), defaultVariant);
+}
+
+void tst_QWebEnginePermission::queryPermission_data()
+{
+ QTest::addColumn<QWebEnginePermission::PermissionType>("permissionType");
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<bool>("expectedValid");
+
+ QTest::newRow("badUrl")
+ << QWebEnginePermission::PermissionType::Notifications << QUrl("//:bad-url"_L1) << false;
+ QTest::newRow("badFeature")
+ << QWebEnginePermission::PermissionType::Unsupported << QUrl("qrc:/resources/index.html"_L1) << false;
+ QTest::newRow("transientFeature")
+ << QWebEnginePermission::PermissionType::MouseLock << QUrl("qrc:/resources/index.html"_L1) << true;
+ QTest::newRow("good")
+ << QWebEnginePermission::PermissionType::Notifications << QUrl("qrc:/resources/index.html"_L1) << true;
+}
+
+void tst_QWebEnginePermission::queryPermission()
+{
+ QFETCH(QWebEnginePermission::PermissionType, permissionType);
+ QFETCH(QUrl, url);
+ QFETCH(bool, expectedValid);
+
+ // In-memory is the default for otr profiles
+ m_profile.reset(new QWebEngineProfile());
+ QVERIFY(m_profile->persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory);
+
+ QWebEnginePermission permission = m_profile->queryPermission(url, permissionType);
+ bool valid = permission.isValid();
+ QCOMPARE(valid, expectedValid);
+ if (!valid)
+ QCOMPARE(permission.state(), QWebEnginePermission::State::Invalid);
+
+ // Verify that we can grant a valid permission, and we can't grant an invalid one...
+ permission.grant();
+ QCOMPARE(permission.state(), valid ? QWebEnginePermission::State::Granted : QWebEnginePermission::State::Invalid);
+
+ // ...and that doing so twice doesn't mess up the state...
+ permission.grant();
+ QCOMPARE(permission.state(), valid ? QWebEnginePermission::State::Granted : QWebEnginePermission::State::Invalid);
+
+ // ...and that the same thing applies to denying them...
+ permission.deny();
+ QCOMPARE(permission.state(), valid ? QWebEnginePermission::State::Denied : QWebEnginePermission::State::Invalid);
+ permission.deny();
+ QCOMPARE(permission.state(), valid ? QWebEnginePermission::State::Denied : QWebEnginePermission::State::Invalid);
+
+ // ...and that resetting works
+ permission.reset();
+ QCOMPARE(permission.state(), valid ? QWebEnginePermission::State::Ask : QWebEnginePermission::State::Invalid);
+ permission.reset();
+ QCOMPARE(permission.state(), valid ? QWebEnginePermission::State::Ask : QWebEnginePermission::State::Invalid);
+}
+
+void tst_QWebEnginePermission::listPermissions()
+{
+ // In-memory is the default for otr profiles
+ m_profile.reset(new QWebEngineProfile());
+ QVERIFY(m_profile->persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory);
+
+ QUrl commonUrl = QUrl(QStringLiteral("https://www.bing.com/maps"));
+ QWebEnginePermission::PermissionType commonType = QWebEnginePermission::PermissionType::Notifications;
+
+ // First, set several permissions at once
+ m_profile->queryPermission(commonUrl, QWebEnginePermission::PermissionType::Geolocation).deny();
+ m_profile->queryPermission(commonUrl, QWebEnginePermission::PermissionType::Unsupported).grant(); // Invalid
+ m_profile->queryPermission(commonUrl, commonType).grant();
+ m_profile->queryPermission(QUrl(QStringLiteral("https://www.google.com/translate")), commonType).grant();
+
+ QList<QWebEnginePermission> permissionsListAll = m_profile->listAllPermissions();
+ QList<QWebEnginePermission> permissionsListUrl = m_profile->listPermissionsForOrigin(commonUrl);
+ QList<QWebEnginePermission> permissionsListFeature = m_profile->listPermissionsForPermissionType(commonType);
+
+ // 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::PermissionType permissionType, QWebEnginePermission::State state)
+ {
+ bool found = false;
+ for (auto &permission : list) {
+ if (permission.origin().adjusted(QUrl::RemovePath) == url.adjusted(QUrl::RemovePath)
+ && permission.permissionType() == permissionType && permission.state() == state) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+ };
+
+ // Check full list
+ QVERIFY(permissionsListAll.size() == 3);
+ QVERIFY(findInList(permissionsListAll, commonUrl, QWebEnginePermission::PermissionType::Geolocation, QWebEnginePermission::State::Denied));
+ QVERIFY(findInList(permissionsListAll, commonUrl, commonType, QWebEnginePermission::State::Granted));
+ QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("https://www.google.com")), commonType, QWebEnginePermission::State::Granted));
+
+ // Check list filtered by URL
+ QVERIFY(permissionsListUrl.size() == 2);
+ 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, commonType, QWebEnginePermission::State::Granted));
+ QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("https://www.google.com")), commonType, QWebEnginePermission::State::Granted));
+}
+
+static QString clipboardPermissionQuery(QString variableName, QString permissionName)
+{
+ return QString("var %1; navigator.permissions.query({ name:'%2' }).then((p) => { %1 = p.state; "
+ "});")
+ .arg(variableName)
+ .arg(permissionName);
+}
+
+void tst_QWebEnginePermission::clipboardReadWritePermissionInitialState_data()
+{
+ QTest::addColumn<bool>("canAccessClipboard");
+ QTest::addColumn<bool>("canPaste");
+ QTest::addColumn<QString>("readPermission");
+ QTest::addColumn<QString>("writePermission");
+ QTest::newRow("access and paste should grant both") << true << true << "granted" << "granted";
+ QTest::newRow("paste only should prompt for both") << false << true << "prompt" << "prompt";
+ QTest::newRow("access only should grant for write only")
+ << true << false << "prompt" << "granted";
+ QTest::newRow("no access or paste should prompt for both")
+ << false << false << "prompt" << "prompt";
+}
+
+void tst_QWebEnginePermission::clipboardReadWritePermissionInitialState()
+{
+ QFETCH(bool, canAccessClipboard);
+ QFETCH(bool, canPaste);
+ QFETCH(QString, readPermission);
+ QFETCH(QString, writePermission);
+
+ m_profile->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
+ QWebEngineView view(m_profile.get());
+ QWebEnginePage &page = *view.page();
+ view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard,
+ canAccessClipboard);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanPaste, canPaste);
+
+ QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
+ QUrl baseUrl("https://www.example.com/somepage.html");
+ page.setHtml(QString("<html><body>Test</body></html>"), baseUrl);
+ QTRY_COMPARE(spy.size(), 1);
+
+ evaluateJavaScriptSync(&page, clipboardPermissionQuery("readPermission", "clipboard-read"));
+ QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("readPermission")), readPermission);
+ evaluateJavaScriptSync(&page, clipboardPermissionQuery("writePermission", "clipboard-write"));
+ QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("writePermission")), writePermission);
+}
+
+void tst_QWebEnginePermission::clipboardReadWritePermission_data()
+{
+ QTest::addColumn<bool>("canAccessClipboard");
+ QTest::addColumn<QWebEnginePermission::State>("initialPolicy");
+ QTest::addColumn<QString>("initialPermission");
+ QTest::addColumn<QString>("finalPermission");
+
+ QTest::newRow("noAccessGrant")
+ << false << QWebEnginePermission::State::Granted << "granted" << "granted";
+ QTest::newRow("noAccessDeny")
+ << false << QWebEnginePermission::State::Denied << "denied" << "denied";
+ QTest::newRow("noAccessAsk")
+ << false << QWebEnginePermission::State::Ask << "prompt" << "granted";
+
+ // All policies are ignored and overridden by setting JsCanAccessClipboard and JsCanPaste to
+ // true
+ QTest::newRow("accessGrant")
+ << true << QWebEnginePermission::State::Granted << "granted" << "granted";
+ QTest::newRow("accessDeny")
+ << true << QWebEnginePermission::State::Denied << "granted" << "granted";
+ QTest::newRow("accessAsk")
+ << true << QWebEnginePermission::State::Ask << "granted" << "granted";
+}
+
+void tst_QWebEnginePermission::clipboardReadWritePermission()
+{
+ QFETCH(bool, canAccessClipboard);
+ QFETCH(QWebEnginePermission::State, initialPolicy);
+ QFETCH(QString, initialPermission);
+ QFETCH(QString, finalPermission);
+
+ m_profile->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
+ QWebEngineView view(m_profile.get());
+ QWebEnginePage &page = *view.page();
+ view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard,
+ canAccessClipboard);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanPaste, true);
+
+ QUrl baseUrl("https://www.example.com/somepage.html");
+
+ int permissionRequestCount = 0;
+ bool errorState = false;
+
+ // This should only fire in the noAccessAsk case. The other NoAccess cases will remember the initial permission,
+ // and the Access cases will auto-grant because JavascriptCanPaste and JavascriptCanAccessClipboard are set.
+ connect(&page, &QWebEnginePage::permissionRequested, &page,
+ [&](QWebEnginePermission permission) {
+ if (permission.permissionType() != QWebEnginePermission::PermissionType::ClipboardReadWrite)
+ return;
+ if (permission.origin() != baseUrl.url(QUrl::RemoveFilename)) {
+ qWarning() << "Unexpected case. Can't proceed." << permission.origin();
+ errorState = true;
+ return;
+ }
+ permissionRequestCount++;
+ // Deliberately set to the opposite state; we want to force a fail when this triggers
+ if (initialPolicy == QWebEnginePermission::State::Granted)
+ permission.deny();
+ else
+ permission.grant();
+ });
+
+ QWebEnginePermission permissionObject = m_profile->queryPermission(baseUrl, QWebEnginePermission::PermissionType::ClipboardReadWrite);
+ switch (initialPolicy) {
+ case QWebEnginePermission::State::Granted:
+ permissionObject.grant();
+ break;
+ case QWebEnginePermission::State::Denied:
+ permissionObject.deny();
+ break;
+ case QWebEnginePermission::State::Ask:
+ permissionObject.reset();
+ break;
+ case QWebEnginePermission::State::Invalid:
+ break;
+ }
+
+ QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
+ page.setHtml(QString("<html><body>Test</body></html>"), baseUrl);
+ QTRY_COMPARE(spy.size(), 1);
+
+ evaluateJavaScriptSync(&page, clipboardPermissionQuery("readPermission", "clipboard-read"));
+ QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("readPermission")), initialPermission);
+ evaluateJavaScriptSync(&page, clipboardPermissionQuery("writePermission", "clipboard-write"));
+ QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("writePermission")), initialPermission);
+
+ auto triggerRequest = [&page](QString variableName, QString apiCall)
+ {
+ auto js = QString("var %1; navigator.clipboard.%2.then((v) => { %1 = 'granted' }, (v) => { %1 = "
+ "'denied' });")
+ .arg(variableName)
+ .arg(apiCall);
+ evaluateJavaScriptSync(&page, js);
+ };
+
+ // Permission is remembered, and shouldn't trigger a new request when called from JS
+ triggerRequest("readState", "readText()");
+ QTRY_COMPARE(evaluateJavaScriptSync(&page, "readState"), finalPermission);
+ triggerRequest("writeState", "writeText('foo')");
+ QTRY_COMPARE(evaluateJavaScriptSync(&page, "writeState"), finalPermission);
+
+ if (initialPermission != finalPermission) {
+ QCOMPARE(permissionRequestCount, 1);
+ } else {
+ QCOMPARE(permissionRequestCount, 0);
+ }
+
+ QVERIFY(!errorState);
+}
+
+QTEST_MAIN(tst_QWebEnginePermission)
+#include "tst_qwebenginepermission.moc"
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index eefb41863..ff3eeae65 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -58,11 +58,6 @@ private Q_SLOTS:
void changePersistentCookiesPolicy();
void initiator();
void badDeleteOrder();
- void permissionPersistence_data();
- void permissionPersistence();
- void queryPermission_data();
- void queryPermission();
- void listPermissions();
void qtbug_71895(); // this should be the last test
};
@@ -1034,192 +1029,6 @@ void tst_QWebEngineProfile::badDeleteOrder()
delete view;
}
-void tst_QWebEngineProfile::permissionPersistence_data()
-{
- QTest::addColumn<QWebEngineProfile::PersistentPermissionsPolicy>("policy");
- QTest::addColumn<bool>("granted");
-
- 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()
-{
- 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->queryPermission(server.url("/hedgehog.html"), QWebEnginePermission::PermissionType::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::PersistentPermissionsPolicy::StoreOnDisk) {
- 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->queryPermission(server.url("/hedgehog.html"), QWebEnginePermission::PermissionType::Notifications);
- permissionObject.reset();
- QCOMPARE(evaluateJavaScriptSync(page.get(), "Notification.permission"), defaultVariant);
-
- page.reset();
- profile.reset();
- loadSpy.reset();
-
- if (policy == QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk) {
- // Wait for file to be written to before deleting
- QTest::qWait(1000);
- storageDir.remove("permissions.json");
- }
-
- QTRY_VERIFY(server.stop());
-}
-
-void tst_QWebEngineProfile::queryPermission_data()
-{
- QTest::addColumn<QWebEnginePermission::PermissionType>("permissionType");
- QTest::addColumn<QUrl>("url");
- QTest::addColumn<bool>("expectedValid");
-
- QTest::newRow("badUrl")
- << QWebEnginePermission::PermissionType::Notifications << QUrl(QStringLiteral("//:bad-url")) << false;
- QTest::newRow("badFeature")
- << QWebEnginePermission::PermissionType::Unsupported << QUrl(QStringLiteral("qrc:/resources/permission.html")) << false;
- QTest::newRow("transientFeature")
- << QWebEnginePermission::PermissionType::MouseLock << QUrl(QStringLiteral("qrc:/resources/permission.html")) << true;
- QTest::newRow("good")
- << QWebEnginePermission::PermissionType::Notifications << QUrl(QStringLiteral("qrc:/resources/permission.html")) << true;
-}
-
-void tst_QWebEngineProfile::queryPermission()
-{
- QFETCH(QWebEnginePermission::PermissionType, permissionType);
- QFETCH(QUrl, url);
- QFETCH(bool, expectedValid);
-
- QWebEngineProfile profile;
- // In-memory is the default for otr profiles
- QVERIFY(profile.persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory);
-
- QWebEnginePermission permission = profile.queryPermission(url, permissionType);
- bool valid = permission.isValid();
- QVERIFY(valid == expectedValid);
- if (!valid)
- 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::State::Granted : QWebEnginePermission::State::Invalid));
-
- // ...and that doing so twice doesn't mess up the state...
- permission.grant();
- 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::State::Denied : QWebEnginePermission::State::Invalid));
- permission.deny();
- QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Denied : QWebEnginePermission::State::Invalid));
-
- // ...and that resetting works
- permission.reset();
- QVERIFY(permission.state() == (valid ? QWebEnginePermission::State::Ask : QWebEnginePermission::State::Invalid));
- permission.reset();
- 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::PersistentPermissionsPolicy::StoreInMemory);
-
- QUrl commonUrl = QUrl(QStringLiteral("http://www.bing.com/maps"));
- QWebEnginePermission::PermissionType commonType = QWebEnginePermission::PermissionType::Notifications;
-
- // First, set several permissions at once
- 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<QWebEnginePermission> permissionsListAll = profile.listAllPermissions();
- QList<QWebEnginePermission> permissionsListUrl = profile.listPermissionsForOrigin(commonUrl);
- QList<QWebEnginePermission> 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<QWebEnginePermission> list, const QUrl &url,
- QWebEnginePermission::PermissionType permissionType, QWebEnginePermission::State state)
- {
- bool found = false;
- for (auto &permission : list) {
- if (permission.origin().adjusted(QUrl::RemovePath) == url.adjusted(QUrl::RemovePath)
- && permission.permissionType() == permissionType && permission.state() == state) {
- found = true;
- break;
- }
- }
- return found;
- };
-
- // Check full list
- QVERIFY(permissionsListAll.size() == 3);
- 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::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, commonType, QWebEnginePermission::State::Granted));
- QVERIFY(findInList(permissionsListAll, QUrl(QStringLiteral("http://www.google.com")), commonType, QWebEnginePermission::State::Granted));
-}
-
void tst_QWebEngineProfile::qtbug_71895()
{
QWebEngineView view;