diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2022-05-03 12:25:50 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2022-11-01 18:56:15 +0100 |
commit | 33cf9d32da0ba78ec90df063a3dda91ea793634d (patch) | |
tree | 4a87de10dcdceb5ced327aba84e2632fb1b1fc47 /tests/manual | |
parent | 62a4fe434d4d9cb27a6285778fdab7e2ce43b61b (diff) |
Long live QPermissions!
Many features of today's devices and operating systems can have
significant privacy, security, and performance implications if
misused. It's therefore increasingly common for platforms to
require explicit consent from the user before accessing these
features.
The Qt permission APIs allow the application to check or request
permission for such features in a cross platform manner.
The check is always synchronous, and can be used in both
library and application code, from any thread.
The request is asynchronous, and should be initiated from
application code on the main thread. The result of the request
can be delivered to lambdas, standalone functions, or
regular member functions such as slots, with an optional
context parameter to manage the lifetime of the request.
Individual permissions are distinct types, not enum values,
and can be added and extended at a later point.
Task-number: QTBUG-90498
Done-with: Timur Pocheptsov <timur.pocheptsov@qt.io>
Done-with: Volker Hilsheimer <volker.hilsheimer@qt.io>
Done-with: Mårten Nordheim <marten.nordheim@qt.io>
Change-Id: I821380bbe56bbc0178cb43e6cabbc99fdbd1235e
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'tests/manual')
-rw-r--r-- | tests/manual/permissions/.gitignore | 1 | ||||
-rw-r--r-- | tests/manual/permissions/CMakeLists.txt | 7 | ||||
-rw-r--r-- | tests/manual/permissions/tst_qpermissions.cpp | 111 |
3 files changed, 119 insertions, 0 deletions
diff --git a/tests/manual/permissions/.gitignore b/tests/manual/permissions/.gitignore new file mode 100644 index 0000000000..bd59d3407e --- /dev/null +++ b/tests/manual/permissions/.gitignore @@ -0,0 +1 @@ +tst_qpermissions diff --git a/tests/manual/permissions/CMakeLists.txt b/tests/manual/permissions/CMakeLists.txt new file mode 100644 index 0000000000..847d9a7411 --- /dev/null +++ b/tests/manual/permissions/CMakeLists.txt @@ -0,0 +1,7 @@ + +qt_internal_add_test(tst_qpermissions + SOURCES + tst_qpermissions.cpp + LIBRARIES + Qt::CorePrivate +) diff --git a/tests/manual/permissions/tst_qpermissions.cpp b/tests/manual/permissions/tst_qpermissions.cpp new file mode 100644 index 0000000000..a97afe8487 --- /dev/null +++ b/tests/manual/permissions/tst_qpermissions.cpp @@ -0,0 +1,111 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include <QTest> + +#include <QtCore/qpermissions.h> +#include <QtCore/qthread.h> +#include <QtCore/qmutex.h> +#include <QtCore/qwaitcondition.h> +#include <QtCore/qtimer.h> + +class tst_QPermissions : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase_data(); + + void checkPermission(); + void checkPermissionInNonMainThread(); + + void requestPermission(); + void requestPermissionInNonMainThread(); +}; + +void tst_QPermissions::initTestCase_data() +{ + QTest::addColumn<QPermission>("permission"); + + QTest::newRow("Camera") << QPermission(QCameraPermission{}); + QTest::newRow("Microphone") << QPermission(QMicrophonePermission{}); + QTest::newRow("Bluetooth") << QPermission(QBluetoothPermission{}); + QTest::newRow("Contacts") << QPermission(QContactsPermission{}); + QTest::newRow("Calendar") << QPermission(QCalendarPermission{}); + QTest::newRow("Location") << QPermission(QLocationPermission{}); +} + +void tst_QPermissions::checkPermission() +{ + QFETCH_GLOBAL(QPermission, permission); + qApp->checkPermission(permission); +} + +class Thread : public QThread +{ +public: + QMutex mutex; + QWaitCondition cond; + std::function<void()> function; + + void run() override + { + QMutexLocker locker(&mutex); + function(); + cond.wakeOne(); + } +}; + +void tst_QPermissions::checkPermissionInNonMainThread() +{ + QFETCH_GLOBAL(QPermission, permission); + + Thread thread; + thread.function = [=]{ + qApp->checkPermission(permission); + }; + + QVERIFY(!thread.isFinished()); + QMutexLocker locker(&thread.mutex); + thread.start(); + QVERIFY(!thread.isFinished()); + thread.cond.wait(locker.mutex()); + QVERIFY(thread.wait(1000)); + QVERIFY(thread.isFinished()); +} + +void tst_QPermissions::requestPermission() +{ + QFETCH_GLOBAL(QPermission, permission); + QTimer::singleShot(0, [=] { + qApp->requestPermission(permission, [=](auto result) { + qDebug() << result; + Q_ASSERT(QThread::currentThread() == thread()); + qApp->exit(); + }); + }); + qApp->exec(); +} + +void tst_QPermissions::requestPermissionInNonMainThread() +{ + QFETCH_GLOBAL(QPermission, permission); + + QTest::ignoreMessage(QtWarningMsg, "Permissions can only be requested from the GUI (main) thread"); + + Thread thread; + thread.function = [&]{ + qApp->requestPermission(permission, [&]() {}); + }; + + QVERIFY(!thread.isFinished()); + QMutexLocker locker(&thread.mutex); + thread.start(); + QVERIFY(!thread.isFinished()); + thread.cond.wait(locker.mutex()); + QVERIFY(thread.wait(1000)); + QVERIFY(thread.isFinished()); +} + +QTEST_MAIN(tst_QPermissions) +#include "tst_qpermissions.moc" |