QBluetoothPermission: introduce fine-grained permissions
This commit introduces fine-grained Bluetooth permissions control to the QBluetoothPermission class. For now the fine-tuning of the permissions is only supported on Android. On Apple enabling any of the permissions is equivalent to requesting full Bluetooth control. Task-number: QTBUG-109964 Change-Id: Ie7ac6577cf6a21419b73b33f8cf7e87bc3f8cf43 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
346dcc696b
commit
0198a74b72
@ -387,9 +387,60 @@ QT_PERMISSION_IMPL_COMMON(QMicrophonePermission)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
QT_PERMISSION_IMPL_COMMON(QBluetoothPermission)
|
QT_PERMISSION_IMPL_COMMON(QBluetoothPermission)
|
||||||
: u{} // stateless, atm
|
: u{ShortData{CommunicationMode::Default, {}}}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum QBluetoothPermission::CommunicationMode
|
||||||
|
\since 6.6
|
||||||
|
|
||||||
|
This enum is used to control the allowed Bluetooth communication modes.
|
||||||
|
|
||||||
|
\value Access Allow this device to access other Bluetooth devices. This
|
||||||
|
includes scanning for nearby devices and connecting to them.
|
||||||
|
\value Advertise Allow other Bluetooth devices to discover this device.
|
||||||
|
\value Default This configuration is used by default.
|
||||||
|
|
||||||
|
\note The fine-grained permissions are currently supported only on
|
||||||
|
Android 12 and newer. On older Android versions, as well as on Apple
|
||||||
|
operating systems, any mode results in full Bluetooth access.
|
||||||
|
|
||||||
|
\note For now the \c Access mode on Android also requests the
|
||||||
|
\l {QLocationPermission::Precise}{precise location} permission.
|
||||||
|
This permission coupling may change in the future.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.6
|
||||||
|
|
||||||
|
Sets the allowed Bluetooth communication modes to \a modes.
|
||||||
|
|
||||||
|
\note A default-constructed instance of \l {QBluetoothPermission::}
|
||||||
|
{CommunicationModes} has no sense, so an attempt to set such a mode will
|
||||||
|
raise a \c {qWarning()} and fall back to using the
|
||||||
|
\l {QBluetoothPermission::}{Default} mode.
|
||||||
|
*/
|
||||||
|
void QBluetoothPermission::setCommunicationModes(CommunicationModes modes)
|
||||||
|
{
|
||||||
|
if (modes == CommunicationModes{}) {
|
||||||
|
qCWarning(lcPermissions, "QBluetoothPermission: trying to set an invalid empty mode. "
|
||||||
|
"Falling back to CommunicationMode::Default.");
|
||||||
|
u.data.mode = Default;
|
||||||
|
} else {
|
||||||
|
u.data.mode = static_cast<CommunicationMode>(modes.toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.6
|
||||||
|
|
||||||
|
Returns the allowed Bluetooth communication modes.
|
||||||
|
*/
|
||||||
|
QBluetoothPermission::CommunicationModes QBluetoothPermission::communicationModes() const
|
||||||
|
{
|
||||||
|
return u.data.mode;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QLocationPermission
|
\class QLocationPermission
|
||||||
\brief Access the user's location.
|
\brief Access the user's location.
|
||||||
|
@ -173,6 +173,32 @@ private:
|
|||||||
};
|
};
|
||||||
Q_DECLARE_SHARED(QContactsPermission)
|
Q_DECLARE_SHARED(QContactsPermission)
|
||||||
|
|
||||||
|
class QBluetoothPermissionPrivate;
|
||||||
|
class QBluetoothPermission
|
||||||
|
{
|
||||||
|
Q_GADGET_EXPORT(Q_CORE_EXPORT)
|
||||||
|
public:
|
||||||
|
enum CommunicationMode : quint8 {
|
||||||
|
Access = 0x01,
|
||||||
|
Advertise = 0x02,
|
||||||
|
Default = Access | Advertise,
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(CommunicationModes, CommunicationMode)
|
||||||
|
Q_FLAG(CommunicationModes)
|
||||||
|
|
||||||
|
Q_CORE_EXPORT void setCommunicationModes(CommunicationModes modes);
|
||||||
|
Q_CORE_EXPORT CommunicationModes communicationModes() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ShortData {
|
||||||
|
CommunicationMode mode;
|
||||||
|
char reserved[sizeof(void*) - sizeof(mode)];
|
||||||
|
};
|
||||||
|
QT_PERMISSION(QBluetoothPermission)
|
||||||
|
};
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothPermission::CommunicationModes)
|
||||||
|
Q_DECLARE_SHARED(QBluetoothPermission)
|
||||||
|
|
||||||
#define Q_DECLARE_MINIMAL_PERMISSION(ClassName) \
|
#define Q_DECLARE_MINIMAL_PERMISSION(ClassName) \
|
||||||
class ClassName##Private; \
|
class ClassName##Private; \
|
||||||
class ClassName \
|
class ClassName \
|
||||||
@ -184,7 +210,6 @@ Q_DECLARE_SHARED(QContactsPermission)
|
|||||||
|
|
||||||
Q_DECLARE_MINIMAL_PERMISSION(QCameraPermission)
|
Q_DECLARE_MINIMAL_PERMISSION(QCameraPermission)
|
||||||
Q_DECLARE_MINIMAL_PERMISSION(QMicrophonePermission)
|
Q_DECLARE_MINIMAL_PERMISSION(QMicrophonePermission)
|
||||||
Q_DECLARE_MINIMAL_PERMISSION(QBluetoothPermission)
|
|
||||||
|
|
||||||
#undef QT_PERMISSION
|
#undef QT_PERMISSION
|
||||||
#undef Q_DECLARE_MINIMAL_PERMISSION
|
#undef Q_DECLARE_MINIMAL_PERMISSION
|
||||||
|
@ -49,7 +49,7 @@ static QStringList nativeLocationPermission(const QLocationPermission &permissio
|
|||||||
return nativeLocationPermissionList;
|
return nativeLocationPermissionList;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList nativeBluetoothPermission()
|
static QStringList nativeBluetoothPermission(const QBluetoothPermission &permission)
|
||||||
{
|
{
|
||||||
// See https://developer.android.com/guide/topics/connectivity/bluetooth/permissions
|
// See https://developer.android.com/guide/topics/connectivity/bluetooth/permissions
|
||||||
// for the details.
|
// for the details.
|
||||||
@ -64,10 +64,17 @@ static QStringList nativeBluetoothPermission()
|
|||||||
// strictly necessary for API Level >= 31. See QTBUG-112164.
|
// strictly necessary for API Level >= 31. See QTBUG-112164.
|
||||||
static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s;
|
static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s;
|
||||||
|
|
||||||
if (QtAndroidPrivate::androidSdkVersion() < 31)
|
if (QtAndroidPrivate::androidSdkVersion() < 31) {
|
||||||
return {bluetoothGeneral, fineLocation};
|
return {bluetoothGeneral, fineLocation};
|
||||||
else
|
} else {
|
||||||
return {bluetoothScan, bluetoothAdvertise, bluetoothConnect, fineLocation};
|
const auto modes = permission.communicationModes();
|
||||||
|
QStringList permissionList;
|
||||||
|
if (modes & QBluetoothPermission::Advertise)
|
||||||
|
permissionList << bluetoothAdvertise;
|
||||||
|
if (modes & QBluetoothPermission::Access)
|
||||||
|
permissionList << bluetoothScan << bluetoothConnect << fineLocation;
|
||||||
|
return permissionList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList nativeStringsFromPermission(const QPermission &permission)
|
static QStringList nativeStringsFromPermission(const QPermission &permission)
|
||||||
@ -80,7 +87,7 @@ static QStringList nativeStringsFromPermission(const QPermission &permission)
|
|||||||
} else if (id == qMetaTypeId<QMicrophonePermission>()) {
|
} else if (id == qMetaTypeId<QMicrophonePermission>()) {
|
||||||
return { u"android.permission.RECORD_AUDIO"_s };
|
return { u"android.permission.RECORD_AUDIO"_s };
|
||||||
} else if (id == qMetaTypeId<QBluetoothPermission>()) {
|
} else if (id == qMetaTypeId<QBluetoothPermission>()) {
|
||||||
return nativeBluetoothPermission();
|
return nativeBluetoothPermission(*permission.value<QBluetoothPermission>());
|
||||||
} else if (id == qMetaTypeId<QContactsPermission>()) {
|
} else if (id == qMetaTypeId<QContactsPermission>()) {
|
||||||
const auto readContactsString = u"android.permission.READ_CONTACTS"_s;
|
const auto readContactsString = u"android.permission.READ_CONTACTS"_s;
|
||||||
switch (permission.value<QContactsPermission>()->accessMode()) {
|
switch (permission.value<QContactsPermission>()->accessMode()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user